import type { AnyAgentTool, AgentToolResult } from "@letta-ai/letta-agent-sdk"; import { parseJsonObject, type JsonObject } from "../core/json.js"; import type { AgentContextPacket } from "../agents/context.js"; import { publicKnowledgeProposedDiffOutputSchema, type PublicKnowledgeProposedDiffOutput, type SanitizedOutputIssue, } from "../agents/output-contracts.js"; import { validatePublicKnowledgeProposedDiffAgainstContext } from "./context.js"; export const PUBLIC_KNOWLEDGE_PROPOSAL_TOOL_NAME = "submit_public_knowledge_diff"; export const PUBLIC_KNOWLEDGE_PROPOSAL_TOOL_PROFILE = "public-knowledge-diff" as const; export type PublicKnowledgeProposalToolFailure = | "duplicate-call" | "invalid-context" | "invalid-schema"; export interface PublicKnowledgeProposalToolSnapshot { calls: number; accepted?: PublicKnowledgeProposedDiffOutput | undefined; failure?: PublicKnowledgeProposalToolFailure | undefined; validationIssues: SanitizedOutputIssue[]; } export class PublicKnowledgeProposalToolCapture { private calls = 0; private accepted: PublicKnowledgeProposedDiffOutput | undefined; private failure: PublicKnowledgeProposalToolFailure | undefined; private validationIssues: SanitizedOutputIssue[] = []; readonly tool: AnyAgentTool = { name: PUBLIC_KNOWLEDGE_PROPOSAL_TOOL_NAME, label: "Submit Public Knowledge diff", description: "Submit exactly one complete inert private Public Knowledge diff proposal for the current ThoughtStream document. Pass the complete proposal object as JSON text in raw. This records a proposal only; it does not edit, stage, publish, deploy, or write any external system.", parameters: publicKnowledgeProposalToolParameters, execute: async (_toolCallId, args) => this.execute(args), }; constructor(private readonly context: AgentContextPacket) {} snapshot(): PublicKnowledgeProposalToolSnapshot { return { calls: this.calls, ...(this.accepted ? { accepted: this.accepted } : {}), ...(this.failure ? { failure: this.failure } : {}), validationIssues: [...this.validationIssues], }; } recover(args: unknown): void { this.capture(args); } private async execute(args: unknown): Promise> { const accepted = this.capture(args); return accepted ? { content: [{ type: "text", text: "{\"accepted\":true,\"proposalState\":\"agent-proposed\",\"publicationEligible\":false}", }], details: { accepted: true, publicationEligible: false }, } : { content: [{ type: "text", text: `{"accepted":false,"code":"${this.failure ?? "invalid-proposal"}"}` }], isError: true, details: { accepted: false, publicationEligible: false }, }; } private capture(args: unknown): boolean { this.calls += 1; if (this.calls !== 1) { this.accepted = undefined; this.failure = "duplicate-call"; this.validationIssues = []; return false; } const envelope = args && typeof args === "object" && !Array.isArray(args) ? args as Record : undefined; let candidate: unknown; try { if (!envelope || Object.keys(envelope).length !== 1 || typeof envelope.raw !== "string" || envelope.raw.length > 64_000) { throw new Error("Proposal tool input must contain one bounded raw JSON string"); } candidate = parseJsonObject(envelope.raw); } catch { this.failure = "invalid-schema"; this.validationIssues = [{ code: "invalid_type", path: ["raw"] }]; return false; } const parsed = publicKnowledgeProposedDiffOutputSchema.safeParse(candidate); if (!parsed.success) { this.failure = "invalid-schema"; this.validationIssues = parsed.error.issues.map((issue) => ({ code: issue.code, path: issue.path.map((part) => typeof part === "symbol" ? String(part) : part), })); return false; } try { validatePublicKnowledgeProposedDiffAgainstContext(parsed.data, this.context); } catch { this.failure = "invalid-context"; this.validationIssues = []; return false; } this.accepted = parsed.data; this.failure = undefined; this.validationIssues = []; return true; } } export const publicKnowledgeProposalToolParameters: JsonObject = { type: "object", additionalProperties: false, required: ["raw"], properties: { raw: { type: "string", minLength: 2, maxLength: 64_000, description: "One JSON-encoded object satisfying stream.thought.output.public-knowledge-proposed-diff@1.", }, }, };