@oyasmi/pipiclaw 0.5.2 → 0.5.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +308 -209
- package/dist/agent/channel-runner.d.ts +3 -2
- package/dist/agent/channel-runner.js +22 -14
- package/dist/{command-extension.d.ts → agent/command-extension.d.ts} +0 -1
- package/dist/{command-extension.js → agent/command-extension.js} +1 -2
- package/dist/{commands.d.ts → agent/commands.d.ts} +0 -1
- package/dist/{commands.js → agent/commands.js} +0 -1
- package/dist/agent/index.d.ts +0 -1
- package/dist/agent/index.js +0 -1
- package/dist/agent/progress-formatter.d.ts +0 -1
- package/dist/agent/progress-formatter.js +0 -1
- package/dist/{prompt-builder.d.ts → agent/prompt-builder.d.ts} +1 -2
- package/dist/{prompt-builder.js → agent/prompt-builder.js} +0 -1
- package/dist/agent/run-queue.d.ts +0 -1
- package/dist/agent/run-queue.js +0 -1
- package/dist/agent/runner-factory.d.ts +0 -1
- package/dist/agent/runner-factory.js +0 -1
- package/dist/agent/session-events.d.ts +0 -1
- package/dist/agent/session-events.js +0 -1
- package/dist/agent/session-resource-gate.d.ts +10 -0
- package/dist/agent/session-resource-gate.js +44 -0
- package/dist/agent/type-guards.d.ts +0 -1
- package/dist/agent/type-guards.js +1 -2
- package/dist/agent/types.d.ts +1 -2
- package/dist/agent/types.js +0 -1
- package/dist/{config-loader.d.ts → agent/workspace-resources.d.ts} +3 -10
- package/dist/{config-loader.js → agent/workspace-resources.js} +3 -19
- package/dist/index.d.ts +9 -9
- package/dist/index.js +9 -9
- package/dist/log.d.ts +0 -1
- package/dist/log.js +0 -1
- package/dist/main.d.ts +0 -1
- package/dist/main.js +0 -1
- package/dist/memory/bootstrap.d.ts +0 -1
- package/dist/memory/bootstrap.js +0 -1
- package/dist/memory/candidates.d.ts +0 -1
- package/dist/memory/candidates.js +0 -1
- package/dist/memory/chinese-words.d.ts +0 -1
- package/dist/memory/chinese-words.js +64 -1
- package/dist/memory/consolidation.d.ts +0 -1
- package/dist/memory/consolidation.js +2 -3
- package/dist/memory/files.d.ts +0 -1
- package/dist/memory/files.js +0 -1
- package/dist/memory/lifecycle.d.ts +1 -2
- package/dist/memory/lifecycle.js +0 -1
- package/dist/memory/recall.d.ts +1 -1
- package/dist/memory/recall.js +77 -11
- package/dist/memory/session.d.ts +0 -1
- package/dist/memory/session.js +2 -3
- package/dist/{sidecar-worker.d.ts → memory/sidecar-worker.d.ts} +0 -1
- package/dist/{sidecar-worker.js → memory/sidecar-worker.js} +1 -2
- package/dist/models/api-keys.d.ts +7 -0
- package/dist/models/api-keys.js +16 -0
- package/dist/{model-utils.d.ts → models/utils.d.ts} +1 -2
- package/dist/{model-utils.js → models/utils.js} +0 -1
- package/dist/paths.d.ts +0 -1
- package/dist/paths.js +0 -1
- package/dist/runtime/bootstrap.d.ts +0 -1
- package/dist/runtime/bootstrap.js +2 -3
- package/dist/runtime/delivery.d.ts +0 -1
- package/dist/runtime/delivery.js +0 -1
- package/dist/runtime/dingtalk.d.ts +0 -1
- package/dist/runtime/dingtalk.js +1 -2
- package/dist/runtime/events.d.ts +0 -1
- package/dist/runtime/events.js +0 -1
- package/dist/runtime/store.d.ts +0 -1
- package/dist/runtime/store.js +0 -1
- package/dist/sandbox.d.ts +0 -1
- package/dist/sandbox.js +1 -2
- package/dist/{context.d.ts → settings.d.ts} +1 -2
- package/dist/{context.js → settings.js} +1 -2
- package/dist/{llm-json.d.ts → shared/llm-json.d.ts} +0 -1
- package/dist/{llm-json.js → shared/llm-json.js} +0 -1
- package/dist/shared/markdown-sections.d.ts +0 -1
- package/dist/shared/markdown-sections.js +0 -1
- package/dist/{shell-escape.d.ts → shared/shell-escape.d.ts} +0 -1
- package/dist/{shell-escape.js → shared/shell-escape.js} +0 -1
- package/dist/shared/text-utils.d.ts +0 -1
- package/dist/shared/text-utils.js +0 -1
- package/dist/shared/type-guards.d.ts +0 -1
- package/dist/shared/type-guards.js +0 -1
- package/dist/shared/types.d.ts +0 -1
- package/dist/shared/types.js +0 -1
- package/dist/subagents/discovery.d.ts +0 -1
- package/dist/subagents/discovery.js +1 -2
- package/dist/subagents/tool.d.ts +1 -2
- package/dist/subagents/tool.js +1 -2
- package/dist/tools/attach.d.ts +0 -1
- package/dist/tools/attach.js +0 -1
- package/dist/tools/bash.d.ts +0 -1
- package/dist/tools/bash.js +0 -1
- package/dist/tools/edit.d.ts +0 -1
- package/dist/tools/edit.js +1 -2
- package/dist/tools/index.d.ts +1 -2
- package/dist/tools/index.js +0 -1
- package/dist/tools/read.d.ts +0 -1
- package/dist/tools/read.js +1 -2
- package/dist/tools/truncate.d.ts +0 -1
- package/dist/tools/truncate.js +0 -1
- package/dist/tools/write-content.d.ts +0 -1
- package/dist/tools/write-content.js +1 -2
- package/dist/tools/write.d.ts +0 -1
- package/dist/tools/write.js +0 -1
- package/package.json +9 -3
- package/CHANGELOG.md +0 -47
- package/dist/agent/channel-runner.d.ts.map +0 -1
- package/dist/agent/channel-runner.js.map +0 -1
- package/dist/agent/index.d.ts.map +0 -1
- package/dist/agent/index.js.map +0 -1
- package/dist/agent/progress-formatter.d.ts.map +0 -1
- package/dist/agent/progress-formatter.js.map +0 -1
- package/dist/agent/run-queue.d.ts.map +0 -1
- package/dist/agent/run-queue.js.map +0 -1
- package/dist/agent/runner-factory.d.ts.map +0 -1
- package/dist/agent/runner-factory.js.map +0 -1
- package/dist/agent/session-events.d.ts.map +0 -1
- package/dist/agent/session-events.js.map +0 -1
- package/dist/agent/type-guards.d.ts.map +0 -1
- package/dist/agent/type-guards.js.map +0 -1
- package/dist/agent/types.d.ts.map +0 -1
- package/dist/agent/types.js.map +0 -1
- package/dist/agent.d.ts +0 -3
- package/dist/agent.d.ts.map +0 -1
- package/dist/agent.js +0 -2
- package/dist/agent.js.map +0 -1
- package/dist/command-extension.d.ts.map +0 -1
- package/dist/command-extension.js.map +0 -1
- package/dist/commands.d.ts.map +0 -1
- package/dist/commands.js.map +0 -1
- package/dist/config-loader.d.ts.map +0 -1
- package/dist/config-loader.js.map +0 -1
- package/dist/context.d.ts.map +0 -1
- package/dist/context.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/llm-json.d.ts.map +0 -1
- package/dist/llm-json.js.map +0 -1
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js.map +0 -1
- package/dist/main.d.ts.map +0 -1
- package/dist/main.js.map +0 -1
- package/dist/memory/bootstrap.d.ts.map +0 -1
- package/dist/memory/bootstrap.js.map +0 -1
- package/dist/memory/candidates.d.ts.map +0 -1
- package/dist/memory/candidates.js.map +0 -1
- package/dist/memory/chinese-words.d.ts.map +0 -1
- package/dist/memory/chinese-words.js.map +0 -1
- package/dist/memory/consolidation.d.ts.map +0 -1
- package/dist/memory/consolidation.js.map +0 -1
- package/dist/memory/files.d.ts.map +0 -1
- package/dist/memory/files.js.map +0 -1
- package/dist/memory/lifecycle.d.ts.map +0 -1
- package/dist/memory/lifecycle.js.map +0 -1
- package/dist/memory/recall.d.ts.map +0 -1
- package/dist/memory/recall.js.map +0 -1
- package/dist/memory/session.d.ts.map +0 -1
- package/dist/memory/session.js.map +0 -1
- package/dist/model-utils.d.ts.map +0 -1
- package/dist/model-utils.js.map +0 -1
- package/dist/paths.d.ts.map +0 -1
- package/dist/paths.js.map +0 -1
- package/dist/prompt-builder.d.ts.map +0 -1
- package/dist/prompt-builder.js.map +0 -1
- package/dist/runtime/bootstrap.d.ts.map +0 -1
- package/dist/runtime/bootstrap.js.map +0 -1
- package/dist/runtime/delivery.d.ts.map +0 -1
- package/dist/runtime/delivery.js.map +0 -1
- package/dist/runtime/dingtalk.d.ts.map +0 -1
- package/dist/runtime/dingtalk.js.map +0 -1
- package/dist/runtime/events.d.ts.map +0 -1
- package/dist/runtime/events.js.map +0 -1
- package/dist/runtime/store.d.ts.map +0 -1
- package/dist/runtime/store.js.map +0 -1
- package/dist/sandbox.d.ts.map +0 -1
- package/dist/sandbox.js.map +0 -1
- package/dist/shared/markdown-sections.d.ts.map +0 -1
- package/dist/shared/markdown-sections.js.map +0 -1
- package/dist/shared/text-utils.d.ts.map +0 -1
- package/dist/shared/text-utils.js.map +0 -1
- package/dist/shared/type-guards.d.ts.map +0 -1
- package/dist/shared/type-guards.js.map +0 -1
- package/dist/shared/types.d.ts.map +0 -1
- package/dist/shared/types.js.map +0 -1
- package/dist/shell-escape.d.ts.map +0 -1
- package/dist/shell-escape.js.map +0 -1
- package/dist/sidecar-worker.d.ts.map +0 -1
- package/dist/sidecar-worker.js.map +0 -1
- package/dist/subagents/discovery.d.ts.map +0 -1
- package/dist/subagents/discovery.js.map +0 -1
- package/dist/subagents/tool.d.ts.map +0 -1
- package/dist/subagents/tool.js.map +0 -1
- package/dist/tools/attach.d.ts.map +0 -1
- package/dist/tools/attach.js.map +0 -1
- package/dist/tools/bash.d.ts.map +0 -1
- package/dist/tools/bash.js.map +0 -1
- package/dist/tools/edit.d.ts.map +0 -1
- package/dist/tools/edit.js.map +0 -1
- package/dist/tools/index.d.ts.map +0 -1
- package/dist/tools/index.js.map +0 -1
- package/dist/tools/read.d.ts.map +0 -1
- package/dist/tools/read.js.map +0 -1
- package/dist/tools/truncate.d.ts.map +0 -1
- package/dist/tools/truncate.js.map +0 -1
- package/dist/tools/write-content.d.ts.map +0 -1
- package/dist/tools/write-content.js.map +0 -1
- package/dist/tools/write.d.ts.map +0 -1
- package/dist/tools/write.js.map +0 -1
- package/docs/memory-audit.md +0 -330
- package/docs/memory-optimization-round2.md +0 -319
- package/docs/specs/001-implement-memory/memory-rfc.md +0 -297
- package/docs/specs/002-subagent/pi-subagent-analyse.txt +0 -190
- package/docs/specs/002-subagent/pi-subagent-design.txt +0 -266
- package/docs/specs/002-subagent/pi-subagent-phase1-plan.txt +0 -529
- package/docs/specs/003-improve-memory/design.md +0 -537
- package/docs/specs/003-improve-memory/interfaces-and-tests.md +0 -473
- package/docs/specs/003-improve-memory/spec.md +0 -357
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/subagents/tool.ts"],"names":[],"mappings":"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","sourcesContent":["import { Agent, type AgentEvent, type AgentMessage, type AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Api, AssistantMessage, Model } from \"@mariozechner/pi-ai\";\nimport { convertToLlm } from \"@mariozechner/pi-coding-agent\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { PipiclawMemoryRecallSettings } from \"../context.js\";\nimport { createMemoryCandidateCache } from \"../memory/candidates.js\";\nimport { readChannelSession } from \"../memory/files.js\";\nimport { recallRelevantMemory } from \"../memory/recall.js\";\nimport { formatModelReference } from \"../model-utils.js\";\nimport type { Executor } from \"../sandbox.js\";\nimport { splitH1Sections } from \"../shared/markdown-sections.js\";\nimport { clipText, extractAssistantText, extractLabelFromArgs, HAN_REGEX } from \"../shared/text-utils.js\";\nimport type { UsageTotals } from \"../shared/types.js\";\nimport { createBashTool } from \"../tools/bash.js\";\nimport { createEditTool } from \"../tools/edit.js\";\nimport { createReadTool } from \"../tools/read.js\";\nimport { createWriteTool } from \"../tools/write.js\";\nimport {\n\tformatSubAgentList,\n\ttype ResolvedSubAgentConfig,\n\tresolveSubAgentConfig,\n\ttype SubAgentConfig,\n\ttype SubAgentDiscoveryResult,\n\tvalidateSubAgentTask,\n} from \"./discovery.js\";\n\nconst subagentSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of what this sub-agent task does (shown to user)\" }),\n\tagent: Type.Optional(Type.String({ description: \"Name of a predefined sub-agent from workspaceDir/sub-agents/\" })),\n\tname: Type.Optional(Type.String({ description: \"Optional display name for an inline sub-agent\" })),\n\ttask: Type.String({ description: \"Complete task description for the sub-agent\" }),\n\tsystemPrompt: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: \"Optional inline system prompt for a temporary sub-agent. Use when no predefined agent fits.\",\n\t\t}),\n\t),\n\ttools: Type.Optional(Type.Array(Type.String(), { description: \"Optional tool whitelist for the sub-agent\" })),\n\tmodel: Type.Optional(\n\t\tType.String({ description: \"Optional exact model reference. Defaults to the parent's current model.\" }),\n\t),\n\tmaxTurns: Type.Optional(Type.Number({ description: \"Optional maximum assistant turns for this sub-agent\" })),\n\tmaxToolCalls: Type.Optional(Type.Number({ description: \"Optional maximum tool calls for this sub-agent\" })),\n\tmaxWallTimeSec: Type.Optional(\n\t\tType.Number({ description: \"Optional wall time budget in seconds for this sub-agent\" }),\n\t),\n\tbashTimeoutSec: Type.Optional(\n\t\tType.Number({ description: \"Optional default timeout in seconds for bash commands inside this sub-agent\" }),\n\t),\n\tcontextMode: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: 'Optional context mode. Use \"contextual\" to inject selected session and memory context.',\n\t\t}),\n\t),\n\tmemory: Type.Optional(\n\t\tType.String({\n\t\t\tdescription: 'Optional memory mode for contextual sub-agents: \"none\", \"session\", or \"relevant\".',\n\t\t}),\n\t),\n\tpaths: Type.Optional(\n\t\tType.Array(Type.String(), {\n\t\t\tdescription: \"Optional preferred file or directory paths for the sub-agent to focus on.\",\n\t\t}),\n\t),\n});\n\nexport interface SubAgentToolDetails {\n\tkind: \"subagent\";\n\tagent: string;\n\tsource: \"predefined\" | \"inline\";\n\tmodel: string;\n\ttools: string[];\n\tturns: number;\n\ttoolCalls: number;\n\tdurationMs: number;\n\tfailed: boolean;\n\tfailureReason?: string;\n\tusage: UsageTotals;\n}\n\nexport interface SubAgentToolOptions {\n\texecutor: Executor;\n\tgetCurrentModel: () => Model<Api>;\n\tgetAvailableModels: () => Model<Api>[];\n\tresolveApiKey: (model: Model<Api>) => Promise<string>;\n\tworkspaceDir: string;\n\tchannelDir: string;\n\tgetSubAgentDiscovery?: () => SubAgentDiscoveryResult;\n\tgetMemoryRecallSettings?: () => PipiclawMemoryRecallSettings;\n\truntimeContext: {\n\t\tworkspacePath: string;\n\t\tchannelId: string;\n\t\tsandbox: string;\n\t};\n\tcreateWorker?: (config: {\n\t\tsubAgent: ResolvedSubAgentConfig;\n\t\tapiKey: string;\n\t\ttools: AgentTool<any>[];\n\t}) => SubAgentWorker;\n}\n\ninterface SubAgentWorker {\n\tstate: { messages: AgentMessage[] };\n\tsubscribe(listener: (event: AgentEvent) => void): () => void;\n\tabort(): void;\n\tprompt(input: string): Promise<void>;\n\twaitForIdle(): Promise<void>;\n}\n\nconst DEFAULT_SUBAGENT_MEMORY_RECALL_SETTINGS: PipiclawMemoryRecallSettings = {\n\tenabled: true,\n\tmaxCandidates: 12,\n\tmaxInjected: 5,\n\tmaxChars: 5000,\n\trerankWithModel: true,\n};\nconst SESSION_SECTION_ORDER = [\"Current State\", \"User Intent\", \"Active Files\", \"Errors & Corrections\", \"Next Steps\"];\nconst MAX_SESSION_SECTION_CHARS = 280;\nconst MAX_SESSION_CONTEXT_CHARS = 1800;\nconst MAX_RECALL_CONTEXT_CHARS = 2200;\n\nfunction createEmptyUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\ttotal: 0,\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 },\n\t};\n}\n\nfunction isAssistantMessage(message: AgentMessage): message is AssistantMessage {\n\treturn typeof message === \"object\" && message !== null && \"role\" in message && message.role === \"assistant\";\n}\n\nfunction getLastAssistantMessage(messages: AgentMessage[]): AssistantMessage | null {\n\tfor (let i = messages.length - 1; i >= 0; i--) {\n\t\tconst message = messages[i];\n\t\tif (isAssistantMessage(message)) {\n\t\t\treturn message;\n\t\t}\n\t}\n\treturn null;\n}\n\nfunction formatStatus(agentName: string, text: string): string {\n\treturn `Subagent ${agentName}: ${text}`;\n}\n\nfunction buildFailureText(config: SubAgentConfig, reason: string, lastAssistantText: string): string {\n\tconst trimmedLastText = lastAssistantText.trim();\n\tif (!trimmedLastText) {\n\t\treturn `Sub-agent ${config.name} failed: ${reason}`;\n\t}\n\treturn `Sub-agent ${config.name} failed: ${reason}\\n\\nLast output:\\n${trimmedLastText}`;\n}\n\nfunction buildStoppedText(config: SubAgentConfig, reason: string, finalText: string): string {\n\tconst trimmedFinalText = finalText.trim();\n\tif (!trimmedFinalText) {\n\t\treturn `Sub-agent ${config.name} stopped: ${reason}`;\n\t}\n\treturn `[Sub-agent ${config.name} stopped: ${reason}]\\n\\n${trimmedFinalText}`;\n}\n\nfunction createToolSet(executor: Executor, bashTimeoutSec: number): AgentTool<any>[] {\n\treturn [\n\t\tcreateReadTool(executor),\n\t\tcreateBashTool(executor, { defaultTimeoutSeconds: bashTimeoutSec }),\n\t\tcreateEditTool(executor),\n\t\tcreateWriteTool(executor),\n\t];\n}\n\nfunction buildSubAgentTask(\n\ttask: string,\n\tconfig: ResolvedSubAgentConfig,\n\truntimeContext: SubAgentToolOptions[\"runtimeContext\"],\n\tcontextBlocks: string[],\n): string {\n\tconst taskText = task.trim();\n\tconst lines = [\n\t\t`Runtime context:`,\n\t\t`- Workspace root: ${runtimeContext.workspacePath}`,\n\t\t`- Channel id: ${runtimeContext.channelId}`,\n\t\t`- Channel directory: ${runtimeContext.workspacePath}/${runtimeContext.channelId}`,\n\t\t`- Sandbox: ${runtimeContext.sandbox}`,\n\t\t`- Filesystem isolation: none (files written here are visible to the parent agent)`,\n\t\t`- Your configured role: ${config.name}`,\n\t];\n\n\tfor (const block of contextBlocks) {\n\t\tif (!block.trim()) {\n\t\t\tcontinue;\n\t\t}\n\t\tlines.push(\"\", block.trim());\n\t}\n\n\tlines.push(\"\", `Task:`, taskText);\n\treturn lines.join(\"\\n\");\n}\n\nfunction buildSessionContextBlock(sessionMarkdown: string): string {\n\tconst sections = splitH1Sections(sessionMarkdown);\n\tif (sections.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst selectedSections = SESSION_SECTION_ORDER.flatMap((heading) =>\n\t\tsections.filter((section) => section.heading.toLowerCase() === heading.toLowerCase()),\n\t);\n\n\tif (selectedSections.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst lines = [\"Relevant session state:\"];\n\tlet usedChars = lines[0].length;\n\tfor (const section of selectedSections) {\n\t\tconst clipped = clipText(section.content, MAX_SESSION_SECTION_CHARS, { headRatio: 1, omitHint: \"...\" });\n\t\tconst block = `- ${section.heading}: ${clipped}`;\n\t\tif (usedChars + block.length > MAX_SESSION_CONTEXT_CHARS) {\n\t\t\tbreak;\n\t\t}\n\t\tlines.push(block);\n\t\tusedChars += block.length + 1;\n\t}\n\treturn lines.length > 1 ? lines.join(\"\\n\") : \"\";\n}\n\nfunction stripRuntimeContextWrapper(renderedText: string): string {\n\treturn renderedText\n\t\t.replace(/^<runtime_context>\\s*/i, \"\")\n\t\t.replace(/\\s*<\\/runtime_context>$/i, \"\")\n\t\t.trim();\n}\n\nasync function buildContextualBlocks(\n\ttask: string,\n\tconfig: ResolvedSubAgentConfig,\n\toptions: SubAgentToolOptions,\n\tcurrentModel: Model<Api>,\n\tcandidateCache = createMemoryCandidateCache(),\n): Promise<string[]> {\n\tif (config.contextMode !== \"contextual\") {\n\t\treturn [];\n\t}\n\n\tconst blocks: string[] = [];\n\tif (config.paths.length > 0) {\n\t\tblocks.push(`Preferred focus paths:\\n${config.paths.map((path) => `- ${path}`).join(\"\\n\")}`);\n\t}\n\n\tif (config.memory === \"none\") {\n\t\treturn blocks;\n\t}\n\n\tconst sessionMarkdown = await readChannelSession(options.channelDir);\n\tconst sessionBlock = buildSessionContextBlock(sessionMarkdown);\n\tif (sessionBlock) {\n\t\tblocks.push(sessionBlock);\n\t}\n\n\tif (config.memory !== \"relevant\") {\n\t\treturn blocks;\n\t}\n\n\tconst recallSettings = {\n\t\t...DEFAULT_SUBAGENT_MEMORY_RECALL_SETTINGS,\n\t\t...options.getMemoryRecallSettings?.(),\n\t};\n\tif (!recallSettings.enabled) {\n\t\treturn blocks;\n\t}\n\n\tconst recallQuery = [task.trim(), config.description.trim(), ...config.paths].filter(Boolean).join(\"\\n\");\n\tconst recalled = await recallRelevantMemory({\n\t\tquery: recallQuery,\n\t\tworkspaceDir: options.workspaceDir,\n\t\tchannelDir: options.channelDir,\n\t\tmaxCandidates: recallSettings.maxCandidates,\n\t\tmaxInjected: recallSettings.maxInjected,\n\t\tmaxChars: Math.min(recallSettings.maxChars, MAX_RECALL_CONTEXT_CHARS),\n\t\trerankWithModel: recallSettings.rerankWithModel,\n\t\tautoRerank: HAN_REGEX.test(recallQuery),\n\t\tmodel: currentModel,\n\t\tresolveApiKey: options.resolveApiKey,\n\t\tallowedSources: [\"workspace-memory\", \"channel-memory\", \"channel-history\"],\n\t\tcandidateCache,\n\t});\n\tconst recalledText = stripRuntimeContextWrapper(recalled.renderedText);\n\tif (recalledText) {\n\t\tblocks.push(recalledText);\n\t}\n\n\treturn blocks;\n}\n\nfunction filterToolsByName(allTools: AgentTool<any>[], names: string[]): AgentTool<any>[] {\n\tconst allowed = new Set(names);\n\treturn allTools.filter((tool) => allowed.has(tool.name));\n}\n\nfunction createDetails(\n\tconfig: ResolvedSubAgentConfig,\n\tusage: UsageTotals,\n\tturns: number,\n\ttoolCalls: number,\n\tdurationMs: number,\n\tfailed: boolean,\n\tfailureReason?: string,\n): SubAgentToolDetails {\n\treturn {\n\t\tkind: \"subagent\",\n\t\tagent: config.name,\n\t\tsource: config.source,\n\t\tmodel: formatModelReference(config.model),\n\t\ttools: [...config.tools],\n\t\tturns,\n\t\ttoolCalls,\n\t\tdurationMs,\n\t\tfailed,\n\t\tfailureReason,\n\t\tusage: {\n\t\t\t...usage,\n\t\t\tcost: { ...usage.cost },\n\t\t},\n\t};\n}\n\nfunction linkAbortSignals(parentSignal: AbortSignal | undefined, childController: AbortController): () => void {\n\tif (!parentSignal) {\n\t\treturn () => {};\n\t}\n\n\tconst abortChild = () => childController.abort(parentSignal.reason);\n\tif (parentSignal.aborted) {\n\t\tabortChild();\n\t\treturn () => {};\n\t}\n\n\tparentSignal.addEventListener(\"abort\", abortChild, { once: true });\n\treturn () => parentSignal.removeEventListener(\"abort\", abortChild);\n}\n\nexport function createSubAgentTool(\n\toptions: SubAgentToolOptions,\n): AgentTool<typeof subagentSchema, SubAgentToolDetails> {\n\treturn {\n\t\tname: \"subagent\",\n\t\tlabel: \"subagent\",\n\t\tdescription:\n\t\t\t\"Delegate a task to a sub-agent with an isolated context. You may use a predefined sub-agent from workspaceDir/sub-agents/ or define a temporary inline sub-agent by providing systemPrompt/tools/model parameters. Sub-agents never receive the subagent tool, so they cannot create nested agents.\",\n\t\tparameters: subagentSchema,\n\t\texecute: async (_toolCallId, params, signal, onUpdate) => {\n\t\t\tconst availableModels = options.getAvailableModels();\n\t\t\tconst discovery = options.getSubAgentDiscovery?.() ?? {\n\t\t\t\tdirectory: `${options.workspaceDir}/sub-agents`,\n\t\t\t\tagents: [],\n\t\t\t\twarnings: [],\n\t\t\t};\n\t\t\tconst currentModel = options.getCurrentModel();\n\t\t\tconst taskLengthError = validateSubAgentTask(params.task);\n\t\t\tif (taskLengthError) {\n\t\t\t\tthrow new Error(taskLengthError);\n\t\t\t}\n\t\t\tconst invocation = resolveSubAgentConfig(availableModels, currentModel, discovery.agents, params);\n\t\t\tif (!invocation.config) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${invocation.error}\\n\\nAvailable predefined sub-agents:\\n${formatSubAgentList(discovery.agents)}`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tconst config = invocation.config;\n\t\t\tconst apiKey = await options.resolveApiKey(config.model);\n\t\t\tconst startedAt = Date.now();\n\t\t\tconst usage = createEmptyUsageTotals();\n\t\t\tlet assistantTurns = 0;\n\t\t\tlet toolCalls = 0;\n\t\t\tlet failureReason: string | undefined;\n\t\t\tlet lastUpdateText = \"\";\n\n\t\t\tconst emitUpdate = (text: string) => {\n\t\t\t\tconst nextText = text.trim();\n\t\t\t\tif (!nextText || nextText === lastUpdateText) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\tlastUpdateText = nextText;\n\t\t\t\tonUpdate?.({\n\t\t\t\t\tcontent: [{ type: \"text\", text: nextText }],\n\t\t\t\t\tdetails: createDetails(\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tusage,\n\t\t\t\t\t\tassistantTurns,\n\t\t\t\t\t\ttoolCalls,\n\t\t\t\t\t\tDate.now() - startedAt,\n\t\t\t\t\t\tBoolean(failureReason),\n\t\t\t\t\t\tfailureReason,\n\t\t\t\t\t),\n\t\t\t\t});\n\t\t\t};\n\n\t\t\tconst worker =\n\t\t\t\toptions.createWorker?.({\n\t\t\t\t\tsubAgent: config,\n\t\t\t\t\tapiKey,\n\t\t\t\t\ttools: filterToolsByName(createToolSet(options.executor, config.bashTimeoutSec), config.tools),\n\t\t\t\t}) ??\n\t\t\t\tnew Agent({\n\t\t\t\t\tinitialState: {\n\t\t\t\t\t\tsystemPrompt: config.systemPrompt,\n\t\t\t\t\t\tmodel: config.model,\n\t\t\t\t\t\tthinkingLevel: \"off\",\n\t\t\t\t\t\ttools: filterToolsByName(createToolSet(options.executor, config.bashTimeoutSec), config.tools),\n\t\t\t\t\t},\n\t\t\t\t\tconvertToLlm,\n\t\t\t\t\tgetApiKey: async () => apiKey,\n\t\t\t\t});\n\n\t\t\tconst childController = new AbortController();\n\t\t\tconst unlinkAbortSignals = linkAbortSignals(signal, childController);\n\t\t\tconst wallClockTimer = setTimeout(() => {\n\t\t\t\tfailureReason = `Wall time budget exceeded (${config.maxWallTimeSec}s)`;\n\t\t\t\tworker.abort();\n\t\t\t}, config.maxWallTimeSec * 1000);\n\n\t\t\tconst unsubscribe = worker.subscribe((event: AgentEvent) => {\n\t\t\t\tif (event.type === \"message_end\" && isAssistantMessage(event.message)) {\n\t\t\t\t\tassistantTurns++;\n\t\t\t\t\tconst messageUsage = event.message.usage;\n\t\t\t\t\tusage.input += messageUsage.input;\n\t\t\t\t\tusage.output += messageUsage.output;\n\t\t\t\t\tusage.cacheRead += messageUsage.cacheRead;\n\t\t\t\t\tusage.cacheWrite += messageUsage.cacheWrite;\n\t\t\t\t\tusage.total += messageUsage.totalTokens;\n\t\t\t\t\tusage.cost.input += messageUsage.cost.input;\n\t\t\t\t\tusage.cost.output += messageUsage.cost.output;\n\t\t\t\t\tusage.cost.cacheRead += messageUsage.cost.cacheRead;\n\t\t\t\t\tusage.cost.cacheWrite += messageUsage.cost.cacheWrite;\n\t\t\t\t\tusage.cost.total += messageUsage.cost.total;\n\t\t\t\t}\n\n\t\t\t\tif (event.type === \"tool_execution_start\") {\n\t\t\t\t\ttoolCalls++;\n\t\t\t\t\tconst label = extractLabelFromArgs(event.args) || event.toolName;\n\t\t\t\t\temitUpdate(formatStatus(config.name, label));\n\t\t\t\t\tif (toolCalls > config.maxToolCalls) {\n\t\t\t\t\t\tfailureReason = `Tool call budget exceeded (${config.maxToolCalls})`;\n\t\t\t\t\t\temitUpdate(formatStatus(config.name, \"tool budget reached\"));\n\t\t\t\t\t\tworker.abort();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\tevent.type === \"turn_end\" &&\n\t\t\t\t\tisAssistantMessage(event.message) &&\n\t\t\t\t\tevent.toolResults.length > 0 &&\n\t\t\t\t\tassistantTurns >= config.maxTurns\n\t\t\t\t) {\n\t\t\t\t\tfailureReason = `Turn budget exceeded (${config.maxTurns})`;\n\t\t\t\t\temitUpdate(formatStatus(config.name, \"turn budget reached\"));\n\t\t\t\t\tworker.abort();\n\t\t\t\t}\n\t\t\t});\n\n\t\t\temitUpdate(formatStatus(config.name, \"started\"));\n\n\t\t\ttry {\n\t\t\t\tif (childController.signal.aborted) {\n\t\t\t\t\tthrow new Error(\"Sub-agent aborted\");\n\t\t\t\t}\n\n\t\t\t\tconst abortWorker = () => worker.abort();\n\t\t\t\tchildController.signal.addEventListener(\"abort\", abortWorker, { once: true });\n\t\t\t\ttry {\n\t\t\t\t\tconst contextualBlocks = await buildContextualBlocks(params.task, config, options, currentModel);\n\t\t\t\t\tawait worker.prompt(buildSubAgentTask(params.task, config, options.runtimeContext, contextualBlocks));\n\t\t\t\t\tawait worker.waitForIdle();\n\t\t\t\t} finally {\n\t\t\t\t\tchildController.signal.removeEventListener(\"abort\", abortWorker);\n\t\t\t\t}\n\t\t\t} finally {\n\t\t\t\tunsubscribe();\n\t\t\t\tunlinkAbortSignals();\n\t\t\t\tclearTimeout(wallClockTimer);\n\t\t\t}\n\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Sub-agent aborted\");\n\t\t\t}\n\n\t\t\tconst lastAssistantMessage = getLastAssistantMessage(worker.state.messages);\n\t\t\tconst durationMs = Date.now() - startedAt;\n\t\t\tif (!lastAssistantMessage) {\n\t\t\t\tfailureReason = failureReason || \"Sub-agent returned no assistant message\";\n\t\t\t\temitUpdate(formatStatus(config.name, \"failed\"));\n\t\t\t\tthrow new Error(`Sub-agent ${config.name} failed: ${failureReason}`);\n\t\t\t}\n\n\t\t\tconst finalText = extractAssistantText(lastAssistantMessage);\n\t\t\tconst effectiveFailureReason =\n\t\t\t\tfailureReason ||\n\t\t\t\t(lastAssistantMessage.stopReason === \"error\" || lastAssistantMessage.stopReason === \"aborted\"\n\t\t\t\t\t? lastAssistantMessage.errorMessage || `Sub-agent stopped with ${lastAssistantMessage.stopReason}`\n\t\t\t\t\t: undefined);\n\n\t\t\tif (effectiveFailureReason) {\n\t\t\t\tif (!finalText.trim()) {\n\t\t\t\t\temitUpdate(formatStatus(config.name, \"failed\"));\n\t\t\t\t\tthrow new Error(buildFailureText(config, effectiveFailureReason, finalText));\n\t\t\t\t}\n\t\t\t\temitUpdate(formatStatus(config.name, \"stopped\"));\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: buildStoppedText(config, effectiveFailureReason, finalText) }],\n\t\t\t\t\tdetails: createDetails(\n\t\t\t\t\t\tconfig,\n\t\t\t\t\t\tusage,\n\t\t\t\t\t\tassistantTurns,\n\t\t\t\t\t\ttoolCalls,\n\t\t\t\t\t\tdurationMs,\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\teffectiveFailureReason,\n\t\t\t\t\t),\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: finalText || `(Sub-agent ${config.name} completed with no text output)` }],\n\t\t\t\tdetails: createDetails(config, usage, assistantTurns, toolCalls, durationMs, false),\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attach.d.ts","sourceRoot":"","sources":["../../src/tools/attach.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAI7D,QAAA,MAAM,YAAY;;;;EAIhB,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAEjF;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,CAAC,EAAE,cAAc,GAAG,SAAS,CAAC,OAAO,YAAY,CAAC,CAiC1F"}
|
package/dist/tools/attach.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"attach.js","sourceRoot":"","sources":["../../src/tools/attach.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,MAAM,CAAC;AAExD,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC;IAChC,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;IAC/F,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,4BAA4B,EAAE,CAAC;IAChE,KAAK,EAAE,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,2CAA2C,EAAE,CAAC,CAAC;CAC/F,CAAC,CAAC;AAIH;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,QAAyB;IACzD,OAAO;QACN,IAAI,EAAE,QAAQ;QACd,KAAK,EAAE,QAAQ;QACf,WAAW,EACV,2IAA2I;QAC5I,UAAU,EAAE,YAAY;QACxB,OAAO,EAAE,KAAK,EACb,WAAmB,EACnB,EAAE,IAAI,EAAE,KAAK,EAAmD,EAChE,MAAoB,EACnB,EAAE;YACH,IAAI,CAAC,QAAQ,EAAE,CAAC;gBACf,MAAM,IAAI,KAAK,CACd,gHAAgH,CAChH,CAAC;YACH,CAAC;YAED,IAAI,MAAM,EAAE,OAAO,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC,CAAC;YACtC,CAAC;YAED,MAAM,YAAY,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACvC,MAAM,QAAQ,GAAG,KAAK,IAAI,QAAQ,CAAC,YAAY,CAAC,CAAC;YAEjD,MAAM,QAAQ,CAAC,YAAY,EAAE,QAAQ,CAAC,CAAC;YAEvC,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAe,EAAE,IAAI,EAAE,kBAAkB,QAAQ,EAAE,EAAE,CAAC;gBACxE,OAAO,EAAE,SAAS;aAClB,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport { basename, resolve as resolvePath } from \"path\";\n\nconst attachSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of what you're sharing (shown to user)\" }),\n\tpath: Type.String({ description: \"Path to the file to attach\" }),\n\ttitle: Type.Optional(Type.String({ description: \"Title for the file (defaults to filename)\" })),\n});\n\nexport type UploadFunction = (filePath: string, title?: string) => Promise<void>;\n\n/**\n * Create the attach tool. If no uploadFn is provided, the tool will throw\n * an informative error guiding the LLM to use alternative approaches.\n */\nexport function createAttachTool(uploadFn?: UploadFunction): AgentTool<typeof attachSchema> {\n\treturn {\n\t\tname: \"attach\",\n\t\tlabel: \"attach\",\n\t\tdescription:\n\t\t\t\"Attach a file to your response. Use this to share files, images, or documents with the user. Only files from /workspace/ can be attached.\",\n\t\tparameters: attachSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, title }: { label: string; path: string; title?: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tif (!uploadFn) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t\"File upload is not supported in DingTalk mode. Output file content as text instead, or use bash to host files.\",\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (signal?.aborted) {\n\t\t\t\tthrow new Error(\"Operation aborted\");\n\t\t\t}\n\n\t\t\tconst absolutePath = resolvePath(path);\n\t\t\tconst fileName = title || basename(absolutePath);\n\n\t\t\tawait uploadFn(absolutePath, fileName);\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\" as const, text: `Attached file: ${fileName}` }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
package/dist/tools/bash.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash.d.ts","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAW9C,QAAA,MAAM,UAAU;;;;EAId,CAAC;AAOH,MAAM,WAAW,eAAe;IAC/B,qBAAqB,CAAC,EAAE,MAAM,CAAC;CAC/B;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,GAAE,eAAoB,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAqE9G"}
|
package/dist/tools/bash.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"bash.js","sourceRoot":"","sources":["../../src/tools/bash.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomBytes } from \"node:crypto\";\nimport { createWriteStream } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { Executor } from \"../sandbox.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateTail } from \"./truncate.js\";\n\n/**\n * Generate a unique temp file path for bash output\n */\nfunction getTempFilePath(): string {\n\tconst id = randomBytes(8).toString(\"hex\");\n\treturn join(tmpdir(), `pipiclaw-bash-${id}.log`);\n}\n\nconst bashSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of what this command does (shown to user)\" }),\n\tcommand: Type.String({ description: \"Bash command to execute\" }),\n\ttimeout: Type.Optional(Type.Number({ description: \"Timeout in seconds (optional, no default timeout)\" })),\n});\n\ninterface BashToolDetails {\n\ttruncation?: TruncationResult;\n\tfullOutputPath?: string;\n}\n\nexport interface BashToolOptions {\n\tdefaultTimeoutSeconds?: number;\n}\n\nexport function createBashTool(executor: Executor, options: BashToolOptions = {}): AgentTool<typeof bashSchema> {\n\treturn {\n\t\tname: \"bash\",\n\t\tlabel: \"bash\",\n\t\tdescription: `Execute a bash command in the current working directory. Returns stdout and stderr. Output is truncated to last ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). If truncated, full output is saved to a temp file. Optionally provide a timeout in seconds.`,\n\t\tparameters: bashSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ command, timeout }: { label: string; command: string; timeout?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\t// Track output for potential temp file writing\n\t\t\tlet tempFilePath: string | undefined;\n\t\t\tlet tempFileStream: ReturnType<typeof createWriteStream> | undefined;\n\n\t\t\tconst effectiveTimeout = timeout ?? options.defaultTimeoutSeconds;\n\t\t\tconst result = await executor.exec(command, { timeout: effectiveTimeout, signal });\n\t\t\tlet output = \"\";\n\t\t\tif (result.stdout) output += result.stdout;\n\t\t\tif (result.stderr) {\n\t\t\t\tif (output) output += \"\\n\";\n\t\t\t\toutput += result.stderr;\n\t\t\t}\n\n\t\t\tconst totalBytes = Buffer.byteLength(output, \"utf-8\");\n\n\t\t\t// Write to temp file if output exceeds limit\n\t\t\tif (totalBytes > DEFAULT_MAX_BYTES) {\n\t\t\t\ttempFilePath = getTempFilePath();\n\t\t\t\ttempFileStream = createWriteStream(tempFilePath);\n\t\t\t\ttempFileStream.write(output);\n\t\t\t\ttempFileStream.end();\n\t\t\t}\n\n\t\t\t// Apply tail truncation\n\t\t\tconst truncation = truncateTail(output);\n\t\t\tlet outputText = truncation.content || \"(no output)\";\n\n\t\t\t// Build details with truncation info\n\t\t\tlet details: BashToolDetails | undefined;\n\n\t\t\tif (truncation.truncated) {\n\t\t\t\tdetails = {\n\t\t\t\t\ttruncation,\n\t\t\t\t\tfullOutputPath: tempFilePath,\n\t\t\t\t};\n\n\t\t\t\t// Build actionable notice\n\t\t\t\tconst startLine = truncation.totalLines - truncation.outputLines + 1;\n\t\t\t\tconst endLine = truncation.totalLines;\n\n\t\t\t\tif (truncation.lastLinePartial) {\n\t\t\t\t\t// Edge case: last line alone > 50KB\n\t\t\t\t\tconst lastLineSize = formatSize(Buffer.byteLength(output.split(\"\\n\").pop() || \"\", \"utf-8\"));\n\t\t\t\t\toutputText += `\\n\\n[Showing last ${formatSize(truncation.outputBytes)} of line ${endLine} (line is ${lastLineSize}). Full output: ${tempFilePath}]`;\n\t\t\t\t} else if (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines}. Full output: ${tempFilePath}]`;\n\t\t\t\t} else {\n\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLine}-${endLine} of ${truncation.totalLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Full output: ${tempFilePath}]`;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (result.code !== 0) {\n\t\t\t\tthrow new Error(`${outputText}\\n\\nCommand exited with code ${result.code}`.trim());\n\t\t\t}\n\n\t\t\treturn { content: [{ type: \"text\", text: outputText }], details };\n\t\t},\n\t};\n}\n"]}
|
package/dist/tools/edit.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAG7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuF9C,QAAA,MAAM,UAAU;;;;;EAKd,CAAC;AAEH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CA4D/E"}
|
package/dist/tools/edit.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"edit.js","sourceRoot":"","sources":["../../src/tools/edit.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AACzC,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;GAEG;AACH,SAAS,kBAAkB,CAAC,UAAkB,EAAE,UAAkB,EAAE,YAAY,GAAG,CAAC;IACnF,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,UAAU,EAAE,UAAU,CAAC,CAAC;IACrD,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,QAAQ,GAAG,UAAU,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC9D,MAAM,YAAY,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,MAAM,CAAC;IAE/C,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,aAAa,GAAG,KAAK,CAAC;IAE1B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,GAAG,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;YAChC,GAAG,CAAC,GAAG,EAAE,CAAC;QACX,CAAC;QAED,IAAI,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YAChC,KAAK,MAAM,IAAI,IAAI,GAAG,EAAE,CAAC;gBACxB,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;oBAChB,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;oBAC/D,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;oBACnC,UAAU,EAAE,CAAC;gBACd,CAAC;qBAAM,CAAC;oBACP,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;oBAC/D,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;oBACnC,UAAU,EAAE,CAAC;gBACd,CAAC;YACF,CAAC;YACD,aAAa,GAAG,IAAI,CAAC;QACtB,CAAC;aAAM,CAAC;YACP,MAAM,gBAAgB,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;YAE9F,IAAI,aAAa,IAAI,gBAAgB,EAAE,CAAC;gBACvC,IAAI,WAAW,GAAG,GAAG,CAAC;gBACtB,IAAI,SAAS,GAAG,CAAC,CAAC;gBAClB,IAAI,OAAO,GAAG,CAAC,CAAC;gBAEhB,IAAI,CAAC,aAAa,EAAE,CAAC;oBACpB,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,CAAC,MAAM,GAAG,YAAY,CAAC,CAAC;oBACnD,WAAW,GAAG,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;gBACpC,CAAC;gBAED,IAAI,CAAC,gBAAgB,IAAI,WAAW,CAAC,MAAM,GAAG,YAAY,EAAE,CAAC;oBAC5D,OAAO,GAAG,WAAW,CAAC,MAAM,GAAG,YAAY,CAAC;oBAC5C,WAAW,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,YAAY,CAAC,CAAC;gBAClD,CAAC;gBAED,IAAI,SAAS,GAAG,CAAC,EAAE,CAAC;oBACnB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBACvD,CAAC;gBAED,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;oBAChC,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,CAAC;oBAC/D,MAAM,CAAC,IAAI,CAAC,IAAI,OAAO,IAAI,IAAI,EAAE,CAAC,CAAC;oBACnC,UAAU,EAAE,CAAC;oBACb,UAAU,EAAE,CAAC;gBACd,CAAC;gBAED,IAAI,OAAO,GAAG,CAAC,EAAE,CAAC;oBACjB,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC;gBACvD,CAAC;gBAED,UAAU,IAAI,SAAS,GAAG,OAAO,CAAC;gBAClC,UAAU,IAAI,SAAS,GAAG,OAAO,CAAC;YACnC,CAAC;iBAAM,CAAC;gBACP,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC;gBACzB,UAAU,IAAI,GAAG,CAAC,MAAM,CAAC;YAC1B,CAAC;YAED,aAAa,GAAG,KAAK,CAAC;QACvB,CAAC;IACF,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC;IAC9B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,6DAA6D,EAAE,CAAC;IAClG,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,iDAAiD,EAAE,CAAC;IACrF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,qDAAqD,EAAE,CAAC;IAC5F,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,uCAAuC,EAAE,CAAC;CAC9E,CAAC,CAAC;AAEH,MAAM,UAAU,cAAc,CAAC,QAAkB;IAChD,OAAO;QACN,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,MAAM;QACb,WAAW,EACV,mIAAmI;QACpI,UAAU,EAAE,UAAU;QACtB,OAAO,EAAE,KAAK,EACb,WAAmB,EACnB,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAqE,EAC7F,MAAoB,EACnB,EAAE;YACH,gBAAgB;YAChB,MAAM,UAAU,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,OAAO,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;YAC/E,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,UAAU,CAAC,MAAM,IAAI,mBAAmB,IAAI,EAAE,CAAC,CAAC;YACjE,CAAC;YAED,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,CAAC;YAElC,2BAA2B;YAC3B,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC;gBAChC,MAAM,IAAI,KAAK,CACd,oCAAoC,IAAI,0EAA0E,CAClH,CAAC;YACH,CAAC;YAED,oBAAoB;YACpB,MAAM,WAAW,GAAG,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;YAEtD,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;gBACrB,MAAM,IAAI,KAAK,CACd,SAAS,WAAW,+BAA+B,IAAI,2EAA2E,CAClI,CAAC;YACH,CAAC;YAED,sBAAsB;YACtB,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;YACvC,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,OAAO,GAAG,OAAO,CAAC,SAAS,CAAC,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;YAErG,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;gBAC5B,MAAM,IAAI,KAAK,CACd,sBAAsB,IAAI,0IAA0I,CACpK,CAAC;YACH,CAAC;YAED,sBAAsB;YACtB,MAAM,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;YAEvD,OAAO;gBACN,OAAO,EAAE;oBACR;wBACC,IAAI,EAAE,MAAM;wBACZ,IAAI,EAAE,iCAAiC,IAAI,aAAa,OAAO,CAAC,MAAM,kBAAkB,OAAO,CAAC,MAAM,cAAc;qBACpH;iBACD;gBACD,OAAO,EAAE,EAAE,IAAI,EAAE,kBAAkB,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE;aAC1D,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport * as Diff from \"diff\";\nimport type { Executor } from \"../sandbox.js\";\nimport { shellEscape } from \"../shell-escape.js\";\nimport { writeContent } from \"./write-content.js\";\n\n/**\n * Generate a unified diff string with line numbers and context\n */\nfunction generateDiffString(oldContent: string, newContent: string, contextLines = 4): string {\n\tconst parts = Diff.diffLines(oldContent, newContent);\n\tconst output: string[] = [];\n\n\tconst oldLines = oldContent.split(\"\\n\");\n\tconst newLines = newContent.split(\"\\n\");\n\tconst maxLineNum = Math.max(oldLines.length, newLines.length);\n\tconst lineNumWidth = String(maxLineNum).length;\n\n\tlet oldLineNum = 1;\n\tlet newLineNum = 1;\n\tlet lastWasChange = false;\n\n\tfor (let i = 0; i < parts.length; i++) {\n\t\tconst part = parts[i];\n\t\tconst raw = part.value.split(\"\\n\");\n\t\tif (raw[raw.length - 1] === \"\") {\n\t\t\traw.pop();\n\t\t}\n\n\t\tif (part.added || part.removed) {\n\t\t\tfor (const line of raw) {\n\t\t\t\tif (part.added) {\n\t\t\t\t\tconst lineNum = String(newLineNum).padStart(lineNumWidth, \" \");\n\t\t\t\t\toutput.push(`+${lineNum} ${line}`);\n\t\t\t\t\tnewLineNum++;\n\t\t\t\t} else {\n\t\t\t\t\tconst lineNum = String(oldLineNum).padStart(lineNumWidth, \" \");\n\t\t\t\t\toutput.push(`-${lineNum} ${line}`);\n\t\t\t\t\toldLineNum++;\n\t\t\t\t}\n\t\t\t}\n\t\t\tlastWasChange = true;\n\t\t} else {\n\t\t\tconst nextPartIsChange = i < parts.length - 1 && (parts[i + 1].added || parts[i + 1].removed);\n\n\t\t\tif (lastWasChange || nextPartIsChange) {\n\t\t\t\tlet linesToShow = raw;\n\t\t\t\tlet skipStart = 0;\n\t\t\t\tlet skipEnd = 0;\n\n\t\t\t\tif (!lastWasChange) {\n\t\t\t\t\tskipStart = Math.max(0, raw.length - contextLines);\n\t\t\t\t\tlinesToShow = raw.slice(skipStart);\n\t\t\t\t}\n\n\t\t\t\tif (!nextPartIsChange && linesToShow.length > contextLines) {\n\t\t\t\t\tskipEnd = linesToShow.length - contextLines;\n\t\t\t\t\tlinesToShow = linesToShow.slice(0, contextLines);\n\t\t\t\t}\n\n\t\t\t\tif (skipStart > 0) {\n\t\t\t\t\toutput.push(` ${\"\".padStart(lineNumWidth, \" \")} ...`);\n\t\t\t\t}\n\n\t\t\t\tfor (const line of linesToShow) {\n\t\t\t\t\tconst lineNum = String(oldLineNum).padStart(lineNumWidth, \" \");\n\t\t\t\t\toutput.push(` ${lineNum} ${line}`);\n\t\t\t\t\toldLineNum++;\n\t\t\t\t\tnewLineNum++;\n\t\t\t\t}\n\n\t\t\t\tif (skipEnd > 0) {\n\t\t\t\t\toutput.push(` ${\"\".padStart(lineNumWidth, \" \")} ...`);\n\t\t\t\t}\n\n\t\t\t\toldLineNum += skipStart + skipEnd;\n\t\t\t\tnewLineNum += skipStart + skipEnd;\n\t\t\t} else {\n\t\t\t\toldLineNum += raw.length;\n\t\t\t\tnewLineNum += raw.length;\n\t\t\t}\n\n\t\t\tlastWasChange = false;\n\t\t}\n\t}\n\n\treturn output.join(\"\\n\");\n}\n\nconst editSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of the edit you're making (shown to user)\" }),\n\tpath: Type.String({ description: \"Path to the file to edit (relative or absolute)\" }),\n\toldText: Type.String({ description: \"Exact text to find and replace (must match exactly)\" }),\n\tnewText: Type.String({ description: \"New text to replace the old text with\" }),\n});\n\nexport function createEditTool(executor: Executor): AgentTool<typeof editSchema> {\n\treturn {\n\t\tname: \"edit\",\n\t\tlabel: \"edit\",\n\t\tdescription:\n\t\t\t\"Edit a file by replacing exact text. The oldText must match exactly (including whitespace). Use this for precise, surgical edits.\",\n\t\tparameters: editSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, oldText, newText }: { label: string; path: string; oldText: string; newText: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\t// Read the file\n\t\t\tconst readResult = await executor.exec(`cat ${shellEscape(path)}`, { signal });\n\t\t\tif (readResult.code !== 0) {\n\t\t\t\tthrow new Error(readResult.stderr || `File not found: ${path}`);\n\t\t\t}\n\n\t\t\tconst content = readResult.stdout;\n\n\t\t\t// Check if old text exists\n\t\t\tif (!content.includes(oldText)) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Could not find the exact text in ${path}. The old text must match exactly including all whitespace and newlines.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Count occurrences\n\t\t\tconst occurrences = content.split(oldText).length - 1;\n\n\t\t\tif (occurrences > 1) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`Found ${occurrences} occurrences of the text in ${path}. The text must be unique. Please provide more context to make it unique.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Perform replacement\n\t\t\tconst index = content.indexOf(oldText);\n\t\t\tconst newContent = content.substring(0, index) + newText + content.substring(index + oldText.length);\n\n\t\t\tif (content === newContent) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`No changes made to ${path}. The replacement produced identical content. This might indicate an issue with special characters or the text not existing as expected.`,\n\t\t\t\t);\n\t\t\t}\n\n\t\t\t// Write the file back\n\t\t\tawait writeContent(executor, path, newContent, signal);\n\n\t\t\treturn {\n\t\t\t\tcontent: [\n\t\t\t\t\t{\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\ttext: `Successfully replaced text in ${path}. Changed ${oldText.length} characters to ${newText.length} characters.`,\n\t\t\t\t\t},\n\t\t\t\t],\n\t\t\t\tdetails: { diff: generateDiffString(content, newContent) },\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAC7D,OAAO,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,qBAAqB,CAAC;AACtD,OAAO,KAAK,EAAE,4BAA4B,EAAE,MAAM,eAAe,CAAC;AAClE,OAAO,KAAK,EAAE,QAAQ,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC7D,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,2BAA2B,CAAC;AAOzE,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,EAAE,QAAQ,CAAC;IACnB,eAAe,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,CAAC;IAClC,kBAAkB,EAAE,MAAM,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;IACvC,aAAa,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,GAAG,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IACtD,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,aAAa,CAAC;IAC7B,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;IACpD,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;CAC5D;AAED,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAE5E;AAED,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,0BAA0B,GAAG,SAAS,CAAC,GAAG,CAAC,EAAE,CAoBzF"}
|
package/dist/tools/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/tools/index.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAgB7C,MAAM,UAAU,uBAAuB,CAAC,QAAkB;IACzD,OAAO,CAAC,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC;AAClH,CAAC;AAED,MAAM,UAAU,mBAAmB,CAAC,OAAmC;IACtE,MAAM,SAAS,GAAG,uBAAuB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IAC5D,OAAO;QACN,GAAG,SAAS;QACZ,kBAAkB,CAAC;YAClB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,eAAe,EAAE,OAAO,CAAC,eAAe;YACxC,kBAAkB,EAAE,OAAO,CAAC,kBAAkB;YAC9C,aAAa,EAAE,OAAO,CAAC,aAAa;YACpC,YAAY,EAAE,OAAO,CAAC,YAAY;YAClC,UAAU,EAAE,OAAO,CAAC,UAAU;YAC9B,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;YAClD,uBAAuB,EAAE,OAAO,CAAC,uBAAuB;YACxD,cAAc,EAAE;gBACf,aAAa,EAAE,OAAO,CAAC,aAAa;gBACpC,SAAS,EAAE,OAAO,CAAC,SAAS;gBAC5B,OAAO,EAAE,OAAO,CAAC,aAAa,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,OAAO,CAAC,aAAa,CAAC,SAAS,EAAE;aACrG;SACD,CAAC;KACF,CAAC;AACH,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { Api, Model } from \"@mariozechner/pi-ai\";\nimport type { PipiclawMemoryRecallSettings } from \"../context.js\";\nimport type { Executor, SandboxConfig } from \"../sandbox.js\";\nimport type { SubAgentDiscoveryResult } from \"../subagents/discovery.js\";\nimport { createSubAgentTool } from \"../subagents/tool.js\";\nimport { createBashTool } from \"./bash.js\";\nimport { createEditTool } from \"./edit.js\";\nimport { createReadTool } from \"./read.js\";\nimport { createWriteTool } from \"./write.js\";\n\nexport interface CreatePipiclawToolsOptions {\n\texecutor: Executor;\n\tgetCurrentModel: () => Model<Api>;\n\tgetAvailableModels: () => Model<Api>[];\n\tresolveApiKey: (model: Model<Api>) => Promise<string>;\n\tworkspaceDir: string;\n\tchannelDir: string;\n\tworkspacePath: string;\n\tchannelId: string;\n\tsandboxConfig: SandboxConfig;\n\tgetSubAgentDiscovery: () => SubAgentDiscoveryResult;\n\tgetMemoryRecallSettings: () => PipiclawMemoryRecallSettings;\n}\n\nexport function createPipiclawBaseTools(executor: Executor): AgentTool<any>[] {\n\treturn [createReadTool(executor), createBashTool(executor), createEditTool(executor), createWriteTool(executor)];\n}\n\nexport function createPipiclawTools(options: CreatePipiclawToolsOptions): AgentTool<any>[] {\n\tconst baseTools = createPipiclawBaseTools(options.executor);\n\treturn [\n\t\t...baseTools,\n\t\tcreateSubAgentTool({\n\t\t\texecutor: options.executor,\n\t\t\tgetCurrentModel: options.getCurrentModel,\n\t\t\tgetAvailableModels: options.getAvailableModels,\n\t\t\tresolveApiKey: options.resolveApiKey,\n\t\t\tworkspaceDir: options.workspaceDir,\n\t\t\tchannelDir: options.channelDir,\n\t\t\tgetSubAgentDiscovery: options.getSubAgentDiscovery,\n\t\t\tgetMemoryRecallSettings: options.getMemoryRecallSettings,\n\t\t\truntimeContext: {\n\t\t\t\tworkspacePath: options.workspacePath,\n\t\t\t\tchannelId: options.channelId,\n\t\t\t\tsandbox: options.sandboxConfig.type === \"host\" ? \"host\" : `docker:${options.sandboxConfig.container}`,\n\t\t\t},\n\t\t}),\n\t];\n}\n"]}
|
package/dist/tools/read.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read.d.ts","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAI7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAuB9C,QAAA,MAAM,UAAU;;;;;EAKd,CAAC;AAMH,wBAAgB,cAAc,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,UAAU,CAAC,CAqH/E"}
|
package/dist/tools/read.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"read.js","sourceRoot":"","sources":["../../src/tools/read.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport type { ImageContent, TextContent } from \"@mariozechner/pi-ai\";\nimport { Type } from \"@sinclair/typebox\";\nimport { extname } from \"path\";\nimport type { Executor } from \"../sandbox.js\";\nimport { shellEscape } from \"../shell-escape.js\";\nimport { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationResult, truncateHead } from \"./truncate.js\";\n\n/**\n * Map of file extensions to MIME types for common image formats\n */\nconst IMAGE_MIME_TYPES: Record<string, string> = {\n\t\".jpg\": \"image/jpeg\",\n\t\".jpeg\": \"image/jpeg\",\n\t\".png\": \"image/png\",\n\t\".gif\": \"image/gif\",\n\t\".webp\": \"image/webp\",\n};\n\n/**\n * Check if a file is an image based on its extension\n */\nfunction isImageFile(filePath: string): string | null {\n\tconst ext = extname(filePath).toLowerCase();\n\treturn IMAGE_MIME_TYPES[ext] || null;\n}\n\nconst readSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of what you're reading and why (shown to user)\" }),\n\tpath: Type.String({ description: \"Path to the file to read (relative or absolute)\" }),\n\toffset: Type.Optional(Type.Number({ description: \"Line number to start reading from (1-indexed)\" })),\n\tlimit: Type.Optional(Type.Number({ description: \"Maximum number of lines to read\" })),\n});\n\ninterface ReadToolDetails {\n\ttruncation?: TruncationResult;\n}\n\nexport function createReadTool(executor: Executor): AgentTool<typeof readSchema> {\n\treturn {\n\t\tname: \"read\",\n\t\tlabel: \"read\",\n\t\tdescription: `Read the contents of a file. Supports text files and images (jpg, png, gif, webp). Images are sent as attachments. For text files, output is truncated to ${DEFAULT_MAX_LINES} lines or ${DEFAULT_MAX_BYTES / 1024}KB (whichever is hit first). Use offset/limit for large files.`,\n\t\tparameters: readSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, offset, limit }: { label: string; path: string; offset?: number; limit?: number },\n\t\t\tsignal?: AbortSignal,\n\t\t): Promise<{ content: (TextContent | ImageContent)[]; details: ReadToolDetails | undefined }> => {\n\t\t\tconst mimeType = isImageFile(path);\n\n\t\t\tif (mimeType) {\n\t\t\t\t// Read as image (binary) - use base64\n\t\t\t\tconst result = await executor.exec(`base64 < ${shellEscape(path)}`, { signal });\n\t\t\t\tif (result.code !== 0) {\n\t\t\t\t\tthrow new Error(result.stderr || `Failed to read file: ${path}`);\n\t\t\t\t}\n\t\t\t\tconst base64 = result.stdout.replace(/\\s/g, \"\"); // Remove whitespace from base64\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [\n\t\t\t\t\t\t{ type: \"text\", text: `Read image file [${mimeType}]` },\n\t\t\t\t\t\t{ type: \"image\", data: base64, mimeType },\n\t\t\t\t\t],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Get total line count first\n\t\t\tconst countResult = await executor.exec(`wc -l < ${shellEscape(path)}`, { signal });\n\t\t\tif (countResult.code !== 0) {\n\t\t\t\tthrow new Error(countResult.stderr || `Failed to read file: ${path}`);\n\t\t\t}\n\t\t\tconst totalFileLines = Number.parseInt(countResult.stdout.trim(), 10) + 1; // wc -l counts newlines, not lines\n\n\t\t\t// Apply offset if specified (1-indexed)\n\t\t\tconst startLine = offset ? Math.max(1, offset) : 1;\n\t\t\tconst startLineDisplay = startLine;\n\n\t\t\t// Check if offset is out of bounds\n\t\t\tif (startLine > totalFileLines) {\n\t\t\t\tthrow new Error(`Offset ${offset} is beyond end of file (${totalFileLines} lines total)`);\n\t\t\t}\n\n\t\t\t// Read content with offset\n\t\t\tlet cmd: string;\n\t\t\tif (startLine === 1) {\n\t\t\t\tcmd = `cat ${shellEscape(path)}`;\n\t\t\t} else {\n\t\t\t\tcmd = `tail -n +${startLine} ${shellEscape(path)}`;\n\t\t\t}\n\n\t\t\tconst result = await executor.exec(cmd, { signal });\n\t\t\tif (result.code !== 0) {\n\t\t\t\tthrow new Error(result.stderr || `Failed to read file: ${path}`);\n\t\t\t}\n\n\t\t\tlet selectedContent = result.stdout;\n\t\t\tlet userLimitedLines: number | undefined;\n\n\t\t\t// Apply user limit if specified\n\t\t\tif (limit !== undefined) {\n\t\t\t\tconst lines = selectedContent.split(\"\\n\");\n\t\t\t\tconst endLine = Math.min(limit, lines.length);\n\t\t\t\tselectedContent = lines.slice(0, endLine).join(\"\\n\");\n\t\t\t\tuserLimitedLines = endLine;\n\t\t\t}\n\n\t\t\t// Apply truncation (respects both line and byte limits)\n\t\t\tconst truncation = truncateHead(selectedContent);\n\n\t\t\tlet outputText: string;\n\t\t\tlet details: ReadToolDetails | undefined;\n\n\t\t\tif (truncation.firstLineExceedsLimit) {\n\t\t\t\t// First line at offset exceeds 50KB - tell model to use bash\n\t\t\t\tconst firstLineSize = formatSize(Buffer.byteLength(selectedContent.split(\"\\n\")[0], \"utf-8\"));\n\t\t\t\toutputText = `[Line ${startLineDisplay} is ${firstLineSize}, exceeds ${formatSize(DEFAULT_MAX_BYTES)} limit. Use bash: sed -n '${startLineDisplay}p' ${path} | head -c ${DEFAULT_MAX_BYTES}]`;\n\t\t\t\tdetails = { truncation };\n\t\t\t} else if (truncation.truncated) {\n\t\t\t\t// Truncation occurred - build actionable notice\n\t\t\t\tconst endLineDisplay = startLineDisplay + truncation.outputLines - 1;\n\t\t\t\tconst nextOffset = endLineDisplay + 1;\n\n\t\t\t\toutputText = truncation.content;\n\n\t\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines}. Use offset=${nextOffset} to continue]`;\n\t\t\t\t} else {\n\t\t\t\t\toutputText += `\\n\\n[Showing lines ${startLineDisplay}-${endLineDisplay} of ${totalFileLines} (${formatSize(DEFAULT_MAX_BYTES)} limit). Use offset=${nextOffset} to continue]`;\n\t\t\t\t}\n\t\t\t\tdetails = { truncation };\n\t\t\t} else if (userLimitedLines !== undefined) {\n\t\t\t\t// User specified limit, check if there's more content\n\t\t\t\tconst linesFromStart = startLine - 1 + userLimitedLines;\n\t\t\t\tif (linesFromStart < totalFileLines) {\n\t\t\t\t\tconst remaining = totalFileLines - linesFromStart;\n\t\t\t\t\tconst nextOffset = startLine + userLimitedLines;\n\n\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t\toutputText += `\\n\\n[${remaining} more lines in file. Use offset=${nextOffset} to continue]`;\n\t\t\t\t} else {\n\t\t\t\t\toutputText = truncation.content;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t// No truncation, no user limit exceeded\n\t\t\t\toutputText = truncation.content;\n\t\t\t}\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: outputText }],\n\t\t\t\tdetails,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"truncate.d.ts","sourceRoot":"","sources":["../../src/tools/truncate.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,eAAO,MAAM,iBAAiB,OAAO,CAAC;AACtC,eAAO,MAAM,iBAAiB,QAAY,CAAC;AAE3C,MAAM,WAAW,gBAAgB;IAChC,4BAA4B;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,kCAAkC;IAClC,SAAS,EAAE,OAAO,CAAC;IACnB,sEAAsE;IACtE,WAAW,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAAC;IACtC,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,oDAAoD;IACpD,UAAU,EAAE,MAAM,CAAC;IACnB,uDAAuD;IACvD,WAAW,EAAE,MAAM,CAAC;IACpB,8CAA8C;IAC9C,WAAW,EAAE,MAAM,CAAC;IACpB,yFAAyF;IACzF,eAAe,EAAE,OAAO,CAAC;IACzB,2EAA2E;IAC3E,qBAAqB,EAAE,OAAO,CAAC;CAC/B;AAED,MAAM,WAAW,iBAAiB;IACjC,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAQhD;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CA4E/F;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,iBAAsB,GAAG,gBAAgB,CAqE/F"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"truncate.js","sourceRoot":"","sources":["../../src/tools/truncate.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Shared truncation utilities for tool outputs.\n *\n * Truncation is based on two independent limits - whichever is hit first wins:\n * - Line limit (default: 2000 lines)\n * - Byte limit (default: 50KB)\n *\n * Never returns partial lines (except bash tail truncation edge case).\n */\n\nexport const DEFAULT_MAX_LINES = 2000;\nexport const DEFAULT_MAX_BYTES = 50 * 1024; // 50KB\n\nexport interface TruncationResult {\n\t/** The truncated content */\n\tcontent: string;\n\t/** Whether truncation occurred */\n\ttruncated: boolean;\n\t/** Which limit was hit: \"lines\", \"bytes\", or null if not truncated */\n\ttruncatedBy: \"lines\" | \"bytes\" | null;\n\t/** Total number of lines in the original content */\n\ttotalLines: number;\n\t/** Total number of bytes in the original content */\n\ttotalBytes: number;\n\t/** Number of complete lines in the truncated output */\n\toutputLines: number;\n\t/** Number of bytes in the truncated output */\n\toutputBytes: number;\n\t/** Whether the last line was partially truncated (only for tail truncation edge case) */\n\tlastLinePartial: boolean;\n\t/** Whether the first line exceeded the byte limit (for head truncation) */\n\tfirstLineExceedsLimit: boolean;\n}\n\nexport interface TruncationOptions {\n\t/** Maximum number of lines (default: 2000) */\n\tmaxLines?: number;\n\t/** Maximum number of bytes (default: 50KB) */\n\tmaxBytes?: number;\n}\n\n/**\n * Format bytes as human-readable size.\n */\nexport function formatSize(bytes: number): string {\n\tif (bytes < 1024) {\n\t\treturn `${bytes}B`;\n\t} else if (bytes < 1024 * 1024) {\n\t\treturn `${(bytes / 1024).toFixed(1)}KB`;\n\t} else {\n\t\treturn `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n\t}\n}\n\n/**\n * Truncate content from the head (keep first N lines/bytes).\n * Suitable for file reads where you want to see the beginning.\n *\n * Never returns partial lines. If first line exceeds byte limit,\n * returns empty content with firstLineExceedsLimit=true.\n */\nexport function truncateHead(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = content.split(\"\\n\");\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t};\n\t}\n\n\t// Check if first line alone exceeds byte limit\n\tconst firstLineBytes = Buffer.byteLength(lines[0], \"utf-8\");\n\tif (firstLineBytes > maxBytes) {\n\t\treturn {\n\t\t\tcontent: \"\",\n\t\t\ttruncated: true,\n\t\t\ttruncatedBy: \"bytes\",\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: 0,\n\t\t\toutputBytes: 0,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: true,\n\t\t};\n\t}\n\n\t// Collect complete lines that fit\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\n\tfor (let i = 0; i < lines.length && i < maxLines; i++) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (i > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.push(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial: false,\n\t\tfirstLineExceedsLimit: false,\n\t};\n}\n\n/**\n * Truncate content from the tail (keep last N lines/bytes).\n * Suitable for bash output where you want to see the end (errors, final results).\n *\n * May return partial first line if the last line of original content exceeds byte limit.\n */\nexport function truncateTail(content: string, options: TruncationOptions = {}): TruncationResult {\n\tconst maxLines = options.maxLines ?? DEFAULT_MAX_LINES;\n\tconst maxBytes = options.maxBytes ?? DEFAULT_MAX_BYTES;\n\n\tconst totalBytes = Buffer.byteLength(content, \"utf-8\");\n\tconst lines = content.split(\"\\n\");\n\tconst totalLines = lines.length;\n\n\t// Check if no truncation needed\n\tif (totalLines <= maxLines && totalBytes <= maxBytes) {\n\t\treturn {\n\t\t\tcontent,\n\t\t\ttruncated: false,\n\t\t\ttruncatedBy: null,\n\t\t\ttotalLines,\n\t\t\ttotalBytes,\n\t\t\toutputLines: totalLines,\n\t\t\toutputBytes: totalBytes,\n\t\t\tlastLinePartial: false,\n\t\t\tfirstLineExceedsLimit: false,\n\t\t};\n\t}\n\n\t// Work backwards from the end\n\tconst outputLinesArr: string[] = [];\n\tlet outputBytesCount = 0;\n\tlet truncatedBy: \"lines\" | \"bytes\" = \"lines\";\n\tlet lastLinePartial = false;\n\n\tfor (let i = lines.length - 1; i >= 0 && outputLinesArr.length < maxLines; i--) {\n\t\tconst line = lines[i];\n\t\tconst lineBytes = Buffer.byteLength(line, \"utf-8\") + (outputLinesArr.length > 0 ? 1 : 0); // +1 for newline\n\n\t\tif (outputBytesCount + lineBytes > maxBytes) {\n\t\t\ttruncatedBy = \"bytes\";\n\t\t\t// Edge case: if we haven't added ANY lines yet and this line exceeds maxBytes,\n\t\t\t// take the end of the line (partial)\n\t\t\tif (outputLinesArr.length === 0) {\n\t\t\t\tconst truncatedLine = truncateStringToBytesFromEnd(line, maxBytes);\n\t\t\t\toutputLinesArr.unshift(truncatedLine);\n\t\t\t\toutputBytesCount = Buffer.byteLength(truncatedLine, \"utf-8\");\n\t\t\t\tlastLinePartial = true;\n\t\t\t}\n\t\t\tbreak;\n\t\t}\n\n\t\toutputLinesArr.unshift(line);\n\t\toutputBytesCount += lineBytes;\n\t}\n\n\t// If we exited due to line limit\n\tif (outputLinesArr.length >= maxLines && outputBytesCount <= maxBytes) {\n\t\ttruncatedBy = \"lines\";\n\t}\n\n\tconst outputContent = outputLinesArr.join(\"\\n\");\n\tconst finalOutputBytes = Buffer.byteLength(outputContent, \"utf-8\");\n\n\treturn {\n\t\tcontent: outputContent,\n\t\ttruncated: true,\n\t\ttruncatedBy,\n\t\ttotalLines,\n\t\ttotalBytes,\n\t\toutputLines: outputLinesArr.length,\n\t\toutputBytes: finalOutputBytes,\n\t\tlastLinePartial,\n\t\tfirstLineExceedsLimit: false,\n\t};\n}\n\n/**\n * Truncate a string to fit within a byte limit (from the end).\n * Handles multi-byte UTF-8 characters correctly.\n */\nfunction truncateStringToBytesFromEnd(str: string, maxBytes: number): string {\n\tconst buf = Buffer.from(str, \"utf-8\");\n\tif (buf.length <= maxBytes) {\n\t\treturn str;\n\t}\n\n\t// Start from the end, skip maxBytes back\n\tlet start = buf.length - maxBytes;\n\n\t// Find a valid UTF-8 boundary (start of a character)\n\twhile (start < buf.length && (buf[start] & 0xc0) === 0x80) {\n\t\tstart++;\n\t}\n\n\treturn buf.slice(start).toString(\"utf-8\");\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write-content.d.ts","sourceRoot":"","sources":["../../src/tools/write-content.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAc,QAAQ,EAAE,MAAM,eAAe,CAAC;AAmB1D,wBAAsB,YAAY,CACjC,QAAQ,EAAE,QAAQ,EAClB,IAAI,EAAE,MAAM,EACZ,OAAO,EAAE,MAAM,EACf,MAAM,EAAE,WAAW,GAAG,SAAS,EAC/B,OAAO,CAAC,EAAE;IAAE,eAAe,CAAC,EAAE,OAAO,CAAA;CAAE,GACrC,OAAO,CAAC,IAAI,CAAC,CAiBf"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write-content.js","sourceRoot":"","sources":["../../src/tools/write-content.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAEjD,MAAM,sBAAsB,GAAG,EAAE,GAAG,IAAI,CAAC;AAEzC,SAAS,MAAM,CAAC,IAAY;IAC3B,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC5E,CAAC;AAED,SAAS,YAAY,CAAC,OAAe;IACpC,OAAO,MAAM,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,sBAAsB,CAAC;AACtE,CAAC;AAED,SAAS,aAAa,CAAC,MAAkB,EAAE,IAAY;IACtD,IAAI,MAAM,CAAC,IAAI,KAAK,CAAC,EAAE,CAAC;QACvB,MAAM,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,IAAI,yBAAyB,IAAI,EAAE,CAAC,CAAC;IACnE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CACjC,QAAkB,EAClB,IAAY,EACZ,OAAe,EACf,MAA+B,EAC/B,OAAuC;IAEvC,MAAM,eAAe,GAAG,OAAO,EAAE,eAAe,IAAI,KAAK,CAAC;IAC1D,MAAM,SAAS,GAAG,eAAe,CAAC,CAAC,CAAC,YAAY,WAAW,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;IAErF,IAAI,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC;QAC3B,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,eAAe,WAAW,CAAC,OAAO,CAAC,MAAM,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE;YAC5G,MAAM;SACN,CAAC,CAAC;QACH,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC5B,OAAO;IACR,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,GAAG,SAAS,SAAS,WAAW,CAAC,IAAI,CAAC,EAAE,EAAE;QAC5E,MAAM;QACN,KAAK,EAAE,OAAO;KACd,CAAC,CAAC;IACH,aAAa,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;AAC7B,CAAC","sourcesContent":["import type { ExecResult, Executor } from \"../sandbox.js\";\nimport { shellEscape } from \"../shell-escape.js\";\n\nconst INLINE_WRITE_MAX_BYTES = 64 * 1024;\n\nfunction getDir(path: string): string {\n\treturn path.includes(\"/\") ? path.substring(0, path.lastIndexOf(\"/\")) : \".\";\n}\n\nfunction isInlineSafe(content: string): boolean {\n\treturn Buffer.byteLength(content, \"utf-8\") <= INLINE_WRITE_MAX_BYTES;\n}\n\nfunction ensureSuccess(result: ExecResult, path: string): void {\n\tif (result.code !== 0) {\n\t\tthrow new Error(result.stderr || `Failed to write file: ${path}`);\n\t}\n}\n\nexport async function writeContent(\n\texecutor: Executor,\n\tpath: string,\n\tcontent: string,\n\tsignal: AbortSignal | undefined,\n\toptions?: { createParentDir?: boolean },\n): Promise<void> {\n\tconst createParentDir = options?.createParentDir ?? false;\n\tconst dirPrefix = createParentDir ? `mkdir -p ${shellEscape(getDir(path))} && ` : \"\";\n\n\tif (isInlineSafe(content)) {\n\t\tconst result = await executor.exec(`${dirPrefix}printf '%s' ${shellEscape(content)} > ${shellEscape(path)}`, {\n\t\t\tsignal,\n\t\t});\n\t\tensureSuccess(result, path);\n\t\treturn;\n\t}\n\n\tconst result = await executor.exec(`${dirPrefix}cat > ${shellEscape(path)}`, {\n\t\tsignal,\n\t\tstdin: content,\n\t});\n\tensureSuccess(result, path);\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AAE7D,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAG9C,QAAA,MAAM,WAAW;;;;EAIf,CAAC;AAEH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,QAAQ,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAoBjF"}
|
package/dist/tools/write.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"write.js","sourceRoot":"","sources":["../../src/tools/write.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,IAAI,EAAE,MAAM,mBAAmB,CAAC;AAEzC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD,MAAM,WAAW,GAAG,IAAI,CAAC,MAAM,CAAC;IAC/B,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,0DAA0D,EAAE,CAAC;IAC/F,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,kDAAkD,EAAE,CAAC;IACtF,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,8BAA8B,EAAE,CAAC;CACrE,CAAC,CAAC;AAEH,MAAM,UAAU,eAAe,CAAC,QAAkB;IACjD,OAAO;QACN,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,WAAW,EACV,iIAAiI;QAClI,UAAU,EAAE,WAAW;QACvB,OAAO,EAAE,KAAK,EACb,WAAmB,EACnB,EAAE,IAAI,EAAE,OAAO,EAAoD,EACnE,MAAoB,EACnB,EAAE;YACH,MAAM,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,eAAe,EAAE,IAAI,EAAE,CAAC,CAAC;YAE/E,OAAO;gBACN,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,sBAAsB,OAAO,CAAC,MAAM,aAAa,IAAI,EAAE,EAAE,CAAC;gBAC1F,OAAO,EAAE,SAAS;aAClB,CAAC;QACH,CAAC;KACD,CAAC;AACH,CAAC","sourcesContent":["import type { AgentTool } from \"@mariozechner/pi-agent-core\";\nimport { Type } from \"@sinclair/typebox\";\nimport type { Executor } from \"../sandbox.js\";\nimport { writeContent } from \"./write-content.js\";\n\nconst writeSchema = Type.Object({\n\tlabel: Type.String({ description: \"Brief description of what you're writing (shown to user)\" }),\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport function createWriteTool(executor: Executor): AgentTool<typeof writeSchema> {\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tparameters: writeSchema,\n\t\texecute: async (\n\t\t\t_toolCallId: string,\n\t\t\t{ path, content }: { label: string; path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t) => {\n\t\t\tawait writeContent(executor, path, content, signal, { createParentDir: true });\n\n\t\t\treturn {\n\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote ${content.length} bytes to ${path}` }],\n\t\t\t\tdetails: undefined,\n\t\t\t};\n\t\t},\n\t};\n}\n"]}
|
package/docs/memory-audit.md
DELETED
|
@@ -1,330 +0,0 @@
|
|
|
1
|
-
# Pipiclaw Memory 子系统深度审计报告
|
|
2
|
-
|
|
3
|
-
> **Date**: 2026-04-02
|
|
4
|
-
> **Scope**: `src/memory/` 全部文件 + 相关调用方
|
|
5
|
-
> **Version**: v0.5.1 post-refactoring (commit c4dc08b)
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
## Executive Summary
|
|
10
|
-
|
|
11
|
-
Pipiclaw 的三层记忆系统(SESSION / MEMORY / HISTORY)在实际使用中存在两个根本性问题:**"写不进去"** 和 **"读不出来"**。Consolidation 仅在 compaction/new-session 时触发,导致 MEMORY.md 和 HISTORY.md 几乎不更新;召回评分被 base priority 主导,token overlap 对最终排序影响极小,导致召回本质上是按来源类型排序而非按相关性排序。中文场景下问题尤为突出。
|
|
12
|
-
|
|
13
|
-
---
|
|
14
|
-
|
|
15
|
-
## 一、现状观察
|
|
16
|
-
|
|
17
|
-
| 文件 | 更新频率 | 用户感知 |
|
|
18
|
-
|------|---------|---------|
|
|
19
|
-
| SESSION.md | 频繁、及时 | 正常 |
|
|
20
|
-
| MEMORY.md | 偶尔 | 不足 |
|
|
21
|
-
| HISTORY.md | 极少 | 几乎无 |
|
|
22
|
-
|
|
23
|
-
---
|
|
24
|
-
|
|
25
|
-
## 二、核心问题诊断
|
|
26
|
-
|
|
27
|
-
### 问题 1:Consolidation 触发时机过窄
|
|
28
|
-
|
|
29
|
-
**根因链**:
|
|
30
|
-
|
|
31
|
-
```
|
|
32
|
-
MEMORY.md/HISTORY.md 更新 ← runInlineConsolidation()
|
|
33
|
-
← 仅在 session_before_compact 和 session_before_switch(reason="new") 时触发
|
|
34
|
-
← compaction 由 SDK 在上下文窗口满时触发
|
|
35
|
-
← new-session 仅在频道首次激活时触发
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
对于钉钉场景,用户通常是短问答(1-3 轮),上下文窗口永远不会满,compaction 永远不触发。这意味着:
|
|
39
|
-
|
|
40
|
-
- **HISTORY.md**:几乎永远不会收到新的 history block
|
|
41
|
-
- **MEMORY.md**:几乎永远不会收到新的 memory entries
|
|
42
|
-
- 只有 SESSION.md 因为有独立的 `enqueueSessionMemoryUpdate()` 路径而能正常更新
|
|
43
|
-
|
|
44
|
-
**关键代码** (`src/memory/lifecycle.ts`):
|
|
45
|
-
```typescript
|
|
46
|
-
// consolidation 仅在这两个事件中触发
|
|
47
|
-
case "session_before_compact":
|
|
48
|
-
case "session_before_switch": // 且 reason === "new"
|
|
49
|
-
await runInlineConsolidation(options);
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
### 问题 2:召回评分被 base priority 主导
|
|
53
|
-
|
|
54
|
-
**评分构成** (`src/memory/recall.ts:scoreCandidate`):
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
base priority: 40 ~ 120(占绝对主导)
|
|
58
|
-
title overlap: 每匹配一个 token +10(标题通常很短,0~30)
|
|
59
|
-
content overlap: 每匹配一个 token +3(0~15)
|
|
60
|
-
path overlap: 每匹配一个 token +6(0~12)
|
|
61
|
-
recency boost: 0 ~ 8
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
**实际效果**:一个完全不相关但来源是 session 的候选(score=100+)总是排在一个高度相关但来源是 history 的候选(score=40+几个 overlap)前面。**召回本质上是按来源类型排序,不是按相关性排序**。
|
|
65
|
-
|
|
66
|
-
**候选优先级梯度** (`src/memory/candidates.ts`):
|
|
67
|
-
|
|
68
|
-
```
|
|
69
|
-
channel-session "current state" = 120
|
|
70
|
-
channel-session "next steps" = 115
|
|
71
|
-
channel-session "errors" = 110
|
|
72
|
-
channel-session "constraints" = 108
|
|
73
|
-
channel-session "user intent" = 105
|
|
74
|
-
channel-session (other) = 100
|
|
75
|
-
channel-memory (constraints) = 88
|
|
76
|
-
channel-memory (decisions) = 86
|
|
77
|
-
channel-memory (open loops) = 84
|
|
78
|
-
channel-memory (default) = 80
|
|
79
|
-
workspace-memory = 60
|
|
80
|
-
channel-history = 40
|
|
81
|
-
```
|
|
82
|
-
|
|
83
|
-
session 到 history 的 priority 差距达 60-80 分,token overlap 几乎不可能弥补。
|
|
84
|
-
|
|
85
|
-
### 问题 3:中文分词质量低
|
|
86
|
-
|
|
87
|
-
当前实现用字符级 n-gram(bigram + trigram),没有词级分词:
|
|
88
|
-
|
|
89
|
-
```
|
|
90
|
-
"如何优化记忆系统"
|
|
91
|
-
→ bigrams: ["如何", "何优", "优化", "化记", "记忆", "忆系", "系统"]
|
|
92
|
-
→ trigrams: ["如何优", "何优化", "优化记", "化记忆", "记忆系", "忆系统"]
|
|
93
|
-
```
|
|
94
|
-
|
|
95
|
-
问题:
|
|
96
|
-
- 产生大量无意义的跨词 n-gram(如"何优"、"化记"),增加噪音匹配
|
|
97
|
-
- 短查询(2-3 字)只产生 1-2 个 token,overlap 信号极弱
|
|
98
|
-
- 无法处理同义词/近义词(如"bug"和"缺陷")
|
|
99
|
-
|
|
100
|
-
### 问题 4:Background maintenance 阈值过于保守
|
|
101
|
-
|
|
102
|
-
| 维护操作 | 当前阈值 | 实际达到难度 |
|
|
103
|
-
|---------|---------|------------|
|
|
104
|
-
| Memory cleanup | ≥8,000 字符 OR ≥6 个 update 块 | 需要 6 次 consolidation,而 consolidation 本身就很少触发 |
|
|
105
|
-
| History folding | ≥16,000 字符 OR ≥8 个 block,且总 block>4 | 几乎不可能达到 |
|
|
106
|
-
|
|
107
|
-
### 问题 5:Inline consolidation 的 LLM 可靠性
|
|
108
|
-
|
|
109
|
-
当前用一次 LLM 调用同时产生 `memoryEntries` 和 `historyBlock`。问题:
|
|
110
|
-
- LLM 在短对话时倾向于返回空的 `historyBlock`
|
|
111
|
-
- `hasMeaningfulMessages()` 要求 ≥2 条有意义消息,否则整个 consolidation 被跳过
|
|
112
|
-
- Rerank 超时仅 5 秒,内容截断到 300 字符,信息损失大
|
|
113
|
-
|
|
114
|
-
---
|
|
115
|
-
|
|
116
|
-
## 三、优化方案
|
|
117
|
-
|
|
118
|
-
### 方案 A:新增空闲超时 consolidation 触发(P0)
|
|
119
|
-
|
|
120
|
-
**核心思路**:不再仅依赖 compaction/new-session,在对话"自然结束"时也触发 consolidation。
|
|
121
|
-
|
|
122
|
-
**实现方式**:在 `MemoryLifecycle` 中新增基于空闲超时的触发:
|
|
123
|
-
|
|
124
|
-
```typescript
|
|
125
|
-
// lifecycle.ts 新增
|
|
126
|
-
const IDLE_CONSOLIDATION_TIMEOUT_MS = 60_000; // 对话空闲60秒后触发
|
|
127
|
-
|
|
128
|
-
private idleTimer: ReturnType<typeof setTimeout> | null = null;
|
|
129
|
-
private turnsSinceLastConsolidation = 0;
|
|
130
|
-
|
|
131
|
-
// 在 noteCompletedAssistantTurn() 中调用
|
|
132
|
-
private scheduleIdleConsolidation(): void {
|
|
133
|
-
this.clearIdleTimer();
|
|
134
|
-
this.idleTimer = setTimeout(() => {
|
|
135
|
-
void this.runIdleConsolidation();
|
|
136
|
-
}, IDLE_CONSOLIDATION_TIMEOUT_MS);
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
private clearIdleTimer(): void {
|
|
140
|
-
if (this.idleTimer) {
|
|
141
|
-
clearTimeout(this.idleTimer);
|
|
142
|
-
this.idleTimer = null;
|
|
143
|
-
}
|
|
144
|
-
}
|
|
145
|
-
|
|
146
|
-
private async runIdleConsolidation(): Promise<void> {
|
|
147
|
-
if (this.turnsSinceLastConsolidation < 2) return;
|
|
148
|
-
await runInlineConsolidation(this.buildConsolidationOptions());
|
|
149
|
-
await runBackgroundMaintenance(this.buildConsolidationOptions());
|
|
150
|
-
this.turnsSinceLastConsolidation = 0;
|
|
151
|
-
}
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
**为什么有效**:钉钉场景下用户问完问题就离开,60 秒内没有新消息说明对话结束,此时触发 consolidation 可以可靠地将本轮对话的关键信息写入 MEMORY.md 和 HISTORY.md。
|
|
155
|
-
|
|
156
|
-
**预期效果**:HISTORY.md 和 MEMORY.md 从几乎不更新变为每轮对话结束后都更新。
|
|
157
|
-
|
|
158
|
-
---
|
|
159
|
-
|
|
160
|
-
### 方案 B:重新平衡召回评分(P0)
|
|
161
|
-
|
|
162
|
-
**核心思路**:归一化 token overlap 分数,使其与 base priority 在同一量级。
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
function scoreCandidate(queryTokens: string[], candidate: MemoryCandidate): number {
|
|
166
|
-
// 1. base priority 压缩到 0-20 范围(原始 40-120 → 归一化)
|
|
167
|
-
const normalizedPriority = (candidate.priority / 120) * 20;
|
|
168
|
-
|
|
169
|
-
// 2. token overlap 归一化到 0-50 范围
|
|
170
|
-
const titleOverlap = computeNormalizedOverlap(queryTokens, candidate.title);
|
|
171
|
-
const contentOverlap = computeNormalizedOverlap(queryTokens, candidate.content);
|
|
172
|
-
const pathOverlap = computeNormalizedOverlap(queryTokens, candidate.path);
|
|
173
|
-
const relevanceScore = titleOverlap * 25 + contentOverlap * 15 + pathOverlap * 10;
|
|
174
|
-
|
|
175
|
-
// 3. recency boost 保持 0-8
|
|
176
|
-
const recencyBoost = computeRecencyBoost(candidate.timestamp);
|
|
177
|
-
|
|
178
|
-
return normalizedPriority + relevanceScore + recencyBoost;
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
function computeNormalizedOverlap(queryTokens: string[], text: string): number {
|
|
182
|
-
if (queryTokens.length === 0) return 0;
|
|
183
|
-
const haystack = new Set(tokenize(text));
|
|
184
|
-
let matches = 0;
|
|
185
|
-
for (const token of queryTokens) {
|
|
186
|
-
if (haystack.has(token)) matches++;
|
|
187
|
-
}
|
|
188
|
-
return matches / queryTokens.length; // 归一化到 0-1
|
|
189
|
-
}
|
|
190
|
-
```
|
|
191
|
-
|
|
192
|
-
**效果**:一个 history 候选如果与查询高度匹配(relevanceScore ≈ 40),可以超过一个不相关的 session 候选(normalizedPriority ≈ 17,relevanceScore ≈ 0)。
|
|
193
|
-
|
|
194
|
-
---
|
|
195
|
-
|
|
196
|
-
### 方案 C:改进中文分词(P1)
|
|
197
|
-
|
|
198
|
-
#### C1:轻量级词表分词(推荐)
|
|
199
|
-
|
|
200
|
-
引入常见中文词表做正向最大匹配,作为 n-gram 的补充:
|
|
201
|
-
|
|
202
|
-
```typescript
|
|
203
|
-
// 内置一个高频词表(约 2000-3000 个技术 + 通用词)
|
|
204
|
-
import { COMMON_WORDS } from "./chinese-words.js";
|
|
205
|
-
|
|
206
|
-
function tokenizeHanPart(part: string): string[] {
|
|
207
|
-
const tokens: string[] = [];
|
|
208
|
-
// 正向最大匹配分词
|
|
209
|
-
const words = forwardMaxMatch(part, COMMON_WORDS);
|
|
210
|
-
tokens.push(...words.filter(w => w.length >= 2));
|
|
211
|
-
// 保留 bigram 作为兜底(但移除 trigram 以减少噪音)
|
|
212
|
-
const chars = Array.from(part);
|
|
213
|
-
for (let i = 0; i <= chars.length - 2; i++) {
|
|
214
|
-
tokens.push(chars.slice(i, i + 2).join(""));
|
|
215
|
-
}
|
|
216
|
-
return tokens;
|
|
217
|
-
}
|
|
218
|
-
```
|
|
219
|
-
|
|
220
|
-
#### C2:提升 Rerank 质量
|
|
221
|
-
|
|
222
|
-
```typescript
|
|
223
|
-
// recall.ts 修改
|
|
224
|
-
const RERANK_CONTENT_CLIP = 800; // 从 300 提升到 800
|
|
225
|
-
const MEMORY_RECALL_RERANK_TIMEOUT_MS = 8_000; // 从 5s 提升到 8s
|
|
226
|
-
```
|
|
227
|
-
|
|
228
|
-
建议 **C1 + C2 组合使用**。
|
|
229
|
-
|
|
230
|
-
---
|
|
231
|
-
|
|
232
|
-
### 方案 D:降低 maintenance 阈值(P1)
|
|
233
|
-
|
|
234
|
-
```typescript
|
|
235
|
-
// consolidation.ts
|
|
236
|
-
// 当前 → 建议
|
|
237
|
-
const MEMORY_CLEANUP_LENGTH_THRESHOLD = 8_000; // → 4_000
|
|
238
|
-
const MEMORY_UPDATE_BLOCK_THRESHOLD = 6; // → 3
|
|
239
|
-
const HISTORY_LENGTH_THRESHOLD = 16_000; // → 6_000
|
|
240
|
-
const HISTORY_BLOCK_THRESHOLD = 8; // → 4
|
|
241
|
-
const HISTORY_RECENT_BLOCKS_TO_KEEP = 4; // → 2
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
**理由**:方案 A 实施后 consolidation 频率显著提升,MEMORY.md 和 HISTORY.md 增长加快,需要更积极的清理/折叠。
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
### 方案 E:Recall 默认配置调优(P1)
|
|
249
|
-
|
|
250
|
-
```typescript
|
|
251
|
-
// channel-runner.ts 中的 recall 调用参数
|
|
252
|
-
// 当前 → 建议
|
|
253
|
-
maxCandidates: 8, // → 12(给 reranker 更多候选)
|
|
254
|
-
maxInjected: 3, // → 5(注入更多上下文)
|
|
255
|
-
maxChars: 3500, // → 5000(允许更长的回忆文本)
|
|
256
|
-
rerankWithModel: false, // → true(默认开启 LLM rerank)
|
|
257
|
-
```
|
|
258
|
-
|
|
259
|
-
**注意**:开启默认 rerank 会增加约 1 次 sidecar LLM 调用/轮,但对提升召回质量非常值得。
|
|
260
|
-
|
|
261
|
-
---
|
|
262
|
-
|
|
263
|
-
### 方案 F:独立 MEMORY 和 HISTORY 的更新路径(P2)
|
|
264
|
-
|
|
265
|
-
将 memoryEntries 提取做成确定性规则 + LLM 混合:
|
|
266
|
-
|
|
267
|
-
```typescript
|
|
268
|
-
// 确定性提取:从 assistant 回复中提取结构化信息
|
|
269
|
-
function extractDeterministicMemoryEntries(messages: Message[]): string[] {
|
|
270
|
-
const entries: string[] = [];
|
|
271
|
-
// 提取用户明确要求记住的内容("记住..."、"以后...")
|
|
272
|
-
// 提取关键决策点("决定用..."、"选择...")
|
|
273
|
-
// 提取纠正/偏好表达("不要..."、"应该...")
|
|
274
|
-
return entries;
|
|
275
|
-
}
|
|
276
|
-
```
|
|
277
|
-
|
|
278
|
-
对 historyBlock 的 prompt 强化:
|
|
279
|
-
|
|
280
|
-
```typescript
|
|
281
|
-
const INLINE_CONSOLIDATION_SYSTEM_PROMPT = `...
|
|
282
|
-
- historyBlock MUST NOT be empty. Even for short conversations,
|
|
283
|
-
summarize what was discussed in 1-2 sentences.
|
|
284
|
-
...`;
|
|
285
|
-
```
|
|
286
|
-
|
|
287
|
-
---
|
|
288
|
-
|
|
289
|
-
## 四、优先级总览
|
|
290
|
-
|
|
291
|
-
| 优先级 | 方案 | 预期效果 | 实施复杂度 |
|
|
292
|
-
|-------|------|---------|-----------|
|
|
293
|
-
| **P0** | A: 空闲触发 consolidation | HISTORY/MEMORY 从几乎不更新 → 每轮对话都更新 | 中 |
|
|
294
|
-
| **P0** | B: 评分重新平衡 | 召回从按来源排序 → 按相关性排序 | 低 |
|
|
295
|
-
| **P1** | C: 中文分词改进 | 中文召回准确率显著提升 | 中 |
|
|
296
|
-
| **P1** | D: 降低 maintenance 阈值 | MEMORY/HISTORY 及时整理 | 低 |
|
|
297
|
-
| **P1** | E: Recall 默认配置调优 | 更多相关上下文被注入 | 低 |
|
|
298
|
-
| **P2** | F: 独立更新路径 | HISTORY 可靠产出 | 高 |
|
|
299
|
-
|
|
300
|
-
---
|
|
301
|
-
|
|
302
|
-
## 五、实施建议
|
|
303
|
-
|
|
304
|
-
### 第一阶段(立即)
|
|
305
|
-
1. 实施方案 A(空闲触发)+ 方案 B(评分平衡)— 解决"写不进去"和"读不出来"两个根本问题
|
|
306
|
-
2. 实施方案 D(降低阈值)— 配合方案 A 的效果
|
|
307
|
-
|
|
308
|
-
### 第二阶段(跟进)
|
|
309
|
-
3. 实施方案 C(中文分词)+ 方案 E(配置调优)— 进一步提升召回质量
|
|
310
|
-
4. 为所有方案补充测试用例
|
|
311
|
-
|
|
312
|
-
### 第三阶段(可选)
|
|
313
|
-
5. 实施方案 F(独立路径)— 提升 consolidation 可靠性
|
|
314
|
-
6. 添加 sidecar LLM 调用的 token 追踪(可观测性)
|
|
315
|
-
|
|
316
|
-
---
|
|
317
|
-
|
|
318
|
-
## 附录:关键文件参照
|
|
319
|
-
|
|
320
|
-
| 文件 | 行数 | 涉及方案 |
|
|
321
|
-
|------|------|---------|
|
|
322
|
-
| `src/memory/lifecycle.ts` | 294 | A |
|
|
323
|
-
| `src/memory/recall.ts` | 280 | B, C, E |
|
|
324
|
-
| `src/memory/consolidation.ts` | 328 | A, D, F |
|
|
325
|
-
| `src/memory/candidates.ts` | 170 | B |
|
|
326
|
-
| `src/memory/session.ts` | 290 | — |
|
|
327
|
-
| `src/memory/files.ts` | 193 | — |
|
|
328
|
-
| `src/agent/channel-runner.ts` | 495 | E |
|
|
329
|
-
| `src/sidecar-worker.ts` | 138 | — |
|
|
330
|
-
|