@mikode13/harness 4.0.1 → 5.0.0
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 +278 -16
- package/dist/agent/domain/agent.d.ts +12 -0
- package/dist/agent/domain/agent.js.map +1 -1
- package/dist/agent/domain/approval.d.ts +9 -0
- package/dist/agent/domain/approval.js.map +1 -1
- package/dist/agent/domain/runContext.d.ts +31 -0
- package/dist/agent/domain/runContext.js +47 -0
- package/dist/agent/domain/runContext.js.map +1 -0
- package/dist/diff/domain/unifiedDiff.d.ts +19 -0
- package/dist/diff/domain/unifiedDiff.js +166 -0
- package/dist/diff/domain/unifiedDiff.js.map +1 -0
- package/dist/engines/domain/model/historyFollower.d.ts +41 -0
- package/dist/engines/domain/model/historyFollower.js +158 -0
- package/dist/engines/domain/model/historyFollower.js.map +1 -0
- package/dist/engines/domain/model/llmAgent.d.ts +42 -4
- package/dist/engines/domain/model/llmAgent.js +223 -23
- package/dist/engines/domain/model/llmAgent.js.map +1 -1
- package/dist/factory/infrastructure/agentFactory.d.ts +14 -0
- package/dist/factory/infrastructure/agentFactory.js +20 -2
- package/dist/factory/infrastructure/agentFactory.js.map +1 -1
- package/dist/factory/infrastructure/agentLLMFactory.d.ts +119 -14
- package/dist/factory/infrastructure/agentLLMFactory.js +284 -57
- package/dist/factory/infrastructure/agentLLMFactory.js.map +1 -1
- package/dist/index.d.ts +11 -3
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/domain/conversation.d.ts +44 -4
- package/dist/llm/domain/conversation.js +56 -7
- package/dist/llm/domain/conversation.js.map +1 -1
- package/dist/llm/domain/llm.d.ts +3 -1
- package/dist/llm/domain/llm.js.map +1 -1
- package/dist/llm/domain/tool.d.ts +13 -0
- package/dist/llm/domain/tool.js +12 -1
- package/dist/llm/domain/tool.js.map +1 -1
- package/dist/llm/infrastructure/claudeLLMClient.d.ts +3 -2
- package/dist/llm/infrastructure/claudeLLMClient.js +38 -10
- package/dist/llm/infrastructure/claudeLLMClient.js.map +1 -1
- package/dist/llm/infrastructure/openAILLMClient.d.ts +2 -1
- package/dist/llm/infrastructure/openAILLMClient.js +66 -16
- package/dist/llm/infrastructure/openAILLMClient.js.map +1 -1
- package/dist/orchestration/domain/model/orchestratorAgent.d.ts +11 -2
- package/dist/orchestration/domain/model/orchestratorAgent.js +43 -4
- package/dist/orchestration/domain/model/orchestratorAgent.js.map +1 -1
- package/dist/recovery/domain/fileChanges.d.ts +31 -0
- package/dist/recovery/domain/fileChanges.js +48 -0
- package/dist/recovery/domain/fileChanges.js.map +1 -0
- package/dist/recovery/domain/history.d.ts +114 -0
- package/dist/recovery/domain/history.js +62 -0
- package/dist/recovery/domain/history.js.map +1 -0
- package/dist/recovery/domain/recoveryStore.d.ts +233 -0
- package/dist/recovery/domain/recoveryStore.js +32 -0
- package/dist/recovery/domain/recoveryStore.js.map +1 -0
- package/dist/recovery/domain/retention.d.ts +33 -0
- package/dist/recovery/domain/retention.js +90 -0
- package/dist/recovery/domain/retention.js.map +1 -0
- package/dist/recovery/domain/runChanges.d.ts +37 -0
- package/dist/recovery/domain/runChanges.js +109 -0
- package/dist/recovery/domain/runChanges.js.map +1 -0
- package/dist/recovery/domain/runTree.d.ts +32 -0
- package/dist/recovery/domain/runTree.js +90 -0
- package/dist/recovery/domain/runTree.js.map +1 -0
- package/dist/recovery/infrastructure/createHistory.d.ts +11 -0
- package/dist/recovery/infrastructure/createHistory.js +17 -0
- package/dist/recovery/infrastructure/createHistory.js.map +1 -0
- package/dist/recovery/infrastructure/fileRecoveryStore.d.ts +133 -0
- package/dist/recovery/infrastructure/fileRecoveryStore.js +1043 -0
- package/dist/recovery/infrastructure/fileRecoveryStore.js.map +1 -0
- package/dist/recovery/infrastructure/workspaceFiles.d.ts +30 -0
- package/dist/recovery/infrastructure/workspaceFiles.js +125 -0
- package/dist/recovery/infrastructure/workspaceFiles.js.map +1 -0
- package/dist/tools/domain/accessPolicy.d.ts +30 -0
- package/dist/tools/domain/accessPolicy.js +11 -0
- package/dist/tools/domain/accessPolicy.js.map +1 -0
- package/dist/tools/domain/commands.d.ts +93 -0
- package/dist/tools/domain/commands.js +191 -0
- package/dist/tools/domain/commands.js.map +1 -0
- package/dist/tools/domain/editResponse.d.ts +14 -0
- package/dist/tools/domain/editResponse.js +79 -0
- package/dist/tools/domain/editResponse.js.map +1 -0
- package/dist/tools/domain/fileEdits.d.ts +64 -0
- package/dist/tools/domain/fileEdits.js +21 -0
- package/dist/tools/domain/fileEdits.js.map +1 -0
- package/dist/tools/domain/lineLength.d.ts +7 -0
- package/dist/tools/domain/lineLength.js +26 -0
- package/dist/tools/domain/lineLength.js.map +1 -0
- package/dist/tools/domain/preparedCall.d.ts +31 -0
- package/dist/tools/domain/preparedCall.js +14 -0
- package/dist/tools/domain/preparedCall.js.map +1 -0
- package/dist/tools/domain/readRegistry.d.ts +46 -0
- package/dist/tools/domain/readRegistry.js +62 -0
- package/dist/tools/domain/readRegistry.js.map +1 -0
- package/dist/tools/domain/textLines.d.ts +26 -0
- package/dist/tools/domain/textLines.js +44 -0
- package/dist/tools/domain/textLines.js.map +1 -0
- package/dist/tools/domain/v4aPatch.d.ts +17 -0
- package/dist/tools/domain/v4aPatch.js +236 -0
- package/dist/tools/domain/v4aPatch.js.map +1 -0
- package/dist/tools/infrastructure/boundedWorkspace.d.ts +11 -2
- package/dist/tools/infrastructure/boundedWorkspace.js +9 -1
- package/dist/tools/infrastructure/boundedWorkspace.js.map +1 -1
- package/dist/tools/infrastructure/commandCheckpoint.d.ts +55 -0
- package/dist/tools/infrastructure/commandCheckpoint.js +178 -0
- package/dist/tools/infrastructure/commandCheckpoint.js.map +1 -0
- package/dist/tools/infrastructure/commandProcess.d.ts +47 -0
- package/dist/tools/infrastructure/commandProcess.js +217 -0
- package/dist/tools/infrastructure/commandProcess.js.map +1 -0
- package/dist/tools/infrastructure/commandTool.d.ts +36 -0
- package/dist/tools/infrastructure/commandTool.js +254 -0
- package/dist/tools/infrastructure/commandTool.js.map +1 -0
- package/dist/tools/infrastructure/createWorkspace.d.ts +10 -0
- package/dist/tools/infrastructure/createWorkspace.js +11 -3
- package/dist/tools/infrastructure/createWorkspace.js.map +1 -1
- package/dist/tools/infrastructure/defineTool.d.ts +14 -0
- package/dist/tools/infrastructure/defineTool.js +28 -5
- package/dist/tools/infrastructure/defineTool.js.map +1 -1
- package/dist/tools/infrastructure/editFormats.d.ts +22 -0
- package/dist/tools/infrastructure/editFormats.js +211 -0
- package/dist/tools/infrastructure/editFormats.js.map +1 -0
- package/dist/tools/infrastructure/fileEditor.d.ts +64 -0
- package/dist/tools/infrastructure/fileEditor.js +306 -0
- package/dist/tools/infrastructure/fileEditor.js.map +1 -0
- package/dist/tools/infrastructure/fileTools.d.ts +81 -0
- package/dist/tools/infrastructure/fileTools.js +152 -0
- package/dist/tools/infrastructure/fileTools.js.map +1 -0
- package/dist/tools/infrastructure/gitIgnoreRules.d.ts +15 -0
- package/dist/tools/infrastructure/gitIgnoreRules.js +74 -0
- package/dist/tools/infrastructure/gitIgnoreRules.js.map +1 -0
- package/dist/tools/infrastructure/gitWorkspace.d.ts +1 -1
- package/dist/tools/infrastructure/gitWorkspace.js +1 -1
- package/dist/tools/infrastructure/gitWorkspace.js.map +1 -1
- package/dist/tools/infrastructure/ignoreFileChanges.d.ts +14 -0
- package/dist/tools/infrastructure/ignoreFileChanges.js +62 -0
- package/dist/tools/infrastructure/ignoreFileChanges.js.map +1 -0
- package/dist/tools/infrastructure/policyWorkspace.d.ts +52 -0
- package/dist/tools/infrastructure/policyWorkspace.js +32 -0
- package/dist/tools/infrastructure/policyWorkspace.js.map +1 -0
- package/dist/tools/infrastructure/ripgrepWorkspace.d.ts +2 -1
- package/dist/tools/infrastructure/ripgrepWorkspace.js +1 -1
- package/dist/tools/infrastructure/ripgrepWorkspace.js.map +1 -1
- package/dist/tools/infrastructure/rootsAccessPolicy.d.ts +100 -0
- package/dist/tools/infrastructure/rootsAccessPolicy.js +301 -0
- package/dist/tools/infrastructure/rootsAccessPolicy.js.map +1 -0
- package/dist/tools/infrastructure/runProcess.d.ts +4 -1
- package/dist/tools/infrastructure/runProcess.js +4 -2
- package/dist/tools/infrastructure/runProcess.js.map +1 -1
- package/dist/tools/infrastructure/secretPaths.d.ts +8 -0
- package/dist/tools/infrastructure/secretPaths.js +76 -0
- package/dist/tools/infrastructure/secretPaths.js.map +1 -0
- package/dist/tools/infrastructure/showChangesTool.d.ts +12 -0
- package/dist/tools/infrastructure/showChangesTool.js +43 -0
- package/dist/tools/infrastructure/showChangesTool.js.map +1 -0
- package/dist/tools/infrastructure/trackedEdits.d.ts +33 -0
- package/dist/tools/infrastructure/trackedEdits.js +70 -0
- package/dist/tools/infrastructure/trackedEdits.js.map +1 -0
- package/dist/tools/infrastructure/trackedReadFile.d.ts +21 -0
- package/dist/tools/infrastructure/trackedReadFile.js +78 -0
- package/dist/tools/infrastructure/trackedReadFile.js.map +1 -0
- package/dist/tools/infrastructure/workspaceTools.d.ts +28 -0
- package/dist/tools/infrastructure/workspaceTools.js +53 -40
- package/dist/tools/infrastructure/workspaceTools.js.map +1 -1
- package/dist/tools/infrastructure/workspaceWrites.d.ts +23 -0
- package/dist/tools/infrastructure/workspaceWrites.js +42 -0
- package/dist/tools/infrastructure/workspaceWrites.js.map +1 -0
- package/dist/tools/infrastructure/writeSession.d.ts +35 -0
- package/dist/tools/infrastructure/writeSession.js +81 -0
- package/dist/tools/infrastructure/writeSession.js.map +1 -0
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agentLLMFactory.js","sourceRoot":"","sources":["../../../src/factory/infrastructure/agentLLMFactory.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Agent } from '#src/agent/domain/agent';\nimport { InvalidAgentConfigError } from '#src/shared/domain/errors';\nimport { LLMAgent } from '#src/engines/domain/model/llmAgent';\nimport type { LLMClient } from '#src/llm/domain/llm';\nimport { ClaudeLLMClient } from '#src/llm/infrastructure/claudeLLMClient';\nimport { OpenAILLMClient } from '#src/llm/infrastructure/openAILLMClient';\nimport { InstructedAgent } from '#src/orchestration/domain/model/instructedAgent';\nimport {\n\texecutorInstructions,\n\tOrchestratorAgent,\n\tplannerInstructions,\n\treviewerInstructions,\n} from '#src/orchestration/domain/model/orchestratorAgent';\nimport { ReviewerDecisionValidator } from '#src/orchestration/infrastructure/model/reviewerDecisionValidator';\nimport { RetryingAgent } from '#src/retry/domain/model/retryingAgent';\nimport type { ILogger } from '#src/shared/domain/logger';\nimport { Logger } from '#src/shared/infrastructure/logger';\nimport type { Tool } from '#src/tools/domain/tool';\nimport { createWorkspace } from '#src/tools/infrastructure/createWorkspace';\nimport { createWorkspaceTools } from '#src/tools/infrastructure/workspaceTools';\nimport { createAgent, orchestratorRolesFor, type Role } from './agentFactory.ts';\nimport {\n\tagentProviders,\n\ttype AgentModel,\n\ttype AgentProvider,\n\ttype CreateOrchestratorOptions,\n\ttype ReasoningEffort,\n} from './types.ts';\n\nexport interface CreateLLMAgentOptions {\n\t/**\n\t * Defaults to `'sonnet'` on Anthropic and `'gpt-5.6-luna'` on OpenAI. The provider's client\n\t * rejects a model it does not support.\n\t */\n\tmodel?: AgentModel;\n\t/** Defaults to `'high'`. The provider's client rejects an effort it does not support. */\n\treasoningEffort?: ReasoningEffort;\n\t/** Sent as the model's instructions on every call. */\n\tsystemPrompt: string;\n\t/** The tools the model may call. Defaults to none. */\n\ttools?: Tool[];\n\t/**\n\t * Runs every tool call without asking, `destructive` ones included, for CI where no one can\n\t * answer. Without it, a `destructive` call goes to the run's `approve`, or is denied.\n\t */\n\tautoApprove?: boolean;\n\t/** Defaults to warnings on stderr. */\n\tlogger?: ILogger;\n}\n\nconst defaultLLMAgentModels = {\n\tanthropic: 'sonnet',\n\topenai: 'gpt-5.6-luna',\n} as const satisfies Record<AgentProvider, AgentModel>;\n\n/**\n * Builds an agent whose conversation MiKode owns, on a provider's model API, already wrapped in\n * the harness's retry policy. It needs the provider's API key and bills per token, where\n * `createAgent` uses the Agent SDK's login. Each tool judges the risk of each call; a\n * `destructive` one runs only when the run's `approve` allows it, or with `autoApprove`.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a model or reasoning effort its\n * client does not support, or two tools that share a name.\n * @throws {UnrecoverableError} when the client cannot be set up, for example because\n * `OPENAI_API_KEY` is missing. The Anthropic SDK resolves credentials lazily, so a missing\n * `ANTHROPIC_API_KEY` fails the first run instead, with an `UnrecoverableError`.\n */\nexport function createLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools,\n\t\tautoApprove,\n\t\tlogger = new Logger(),\n\t}: CreateLLMAgentOptions,\n): Agent {\n\tlet llmClient: LLMClient;\n\n\tswitch (provider) {\n\t\tcase 'anthropic':\n\t\t\tllmClient = new ClaudeLLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.anthropic,\n\t\t\t\treasoningEffort,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\t\tbreak;\n\t\tcase 'openai':\n\t\t\tllmClient = new OpenAILLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.openai,\n\t\t\t\treasoningEffort,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\t\tbreak;\n\t\tdefault: {\n\t\t\t// Reachable from untyped input.\n\t\t\tconst unknownProvider: never = provider;\n\t\t\tthrow new InvalidAgentConfigError(\n\t\t\t\t`\"${String(unknownProvider)}\" is not an agent provider; expected one of: ${agentProviders.join(', ')}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// LLMAgent records nothing from a failed call, so the original prompt is the whole story.\n\treturn new RetryingAgent({\n\t\tinner: new LLMAgent({ llmClient, tools, autoApprove }),\n\t\tlogger,\n\t\tnoteFailures: false,\n\t});\n}\n\n// Sent on every call after the role's instructions, so it stays short: it only says how to find\n// one's way around the repository without reading all of it.\nconst repositoryGuidance =\n\t'Paths are relative to the repository root. Start with AGENTS.md and the architecture document it links to learn where things live, then read only the files your task needs.';\n\n/**\n * Builds the planner → executor → reviewer workflow with the planner and reviewer on the model\n * APIs, from `createLLMAgent`, each holding its role's instructions, or `systemPrompts`, as its\n * system prompt, with the read-only repository tools for the current working directory. The\n * executor stays on its Agent SDK, from `createAgent`, until an agent of ours can change files;\n * `autoApprove` reaches only it. Asynchronous because finding the program that reads the\n * repository is.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider.\n * @throws {UnrecoverableError} when a role cannot be set up, for example because\n * `OPENAI_API_KEY` or the Codex CLI binary is missing, or when no program can read the\n * repository.\n */\nexport async function createLLMOrchestrator({\n\tprovider,\n\tautoApprove,\n\tsystemPrompts = {},\n\tlogger = new Logger(),\n}: CreateOrchestratorOptions = {}): Promise<Agent> {\n\tconst roles = orchestratorRolesFor(provider);\n\tconst tools = createWorkspaceTools(await createWorkspace({ root: process.cwd(), logger }));\n\tconst llmAgentFor = ({ provider, model, reasoningEffort }: Role, systemPrompt: string) =>\n\t\tcreateLLMAgent(provider, { model, reasoningEffort, systemPrompt, tools, logger });\n\t// A caller's own prompt replaces the whole of ours, guidance included.\n\tconst withGuidance = (instructions: string) => `${instructions}\\n\\n${repositoryGuidance}`;\n\n\treturn new OrchestratorAgent({\n\t\tplannerAgent: llmAgentFor(\n\t\t\troles.planner,\n\t\t\tsystemPrompts.planner ?? withGuidance(plannerInstructions),\n\t\t),\n\t\texecutorAgent: new InstructedAgent({\n\t\t\tinner: createAgent(roles.executor.provider, {\n\t\t\t\tmodel: roles.executor.model,\n\t\t\t\treasoningEffort: roles.executor.reasoningEffort,\n\t\t\t\tautoApprove,\n\t\t\t\tlogger,\n\t\t\t}),\n\t\t\tinstructions: systemPrompts.executor ?? executorInstructions,\n\t\t}),\n\t\treviewerAgent: llmAgentFor(\n\t\t\troles.reviewer,\n\t\t\tsystemPrompts.reviewer ?? withGuidance(reviewerInstructions),\n\t\t),\n\t\treviewerDecisionValidator: new ReviewerDecisionValidator(),\n\t\tlogger,\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"agentLLMFactory.js","sourceRoot":"","sources":["../../../src/factory/infrastructure/agentLLMFactory.ts"],"names":[],"mappings":"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","sourcesContent":["import { resolve } from 'node:path';\nimport type { Agent } from '#src/agent/domain/agent';\nimport type { HistoryReader } from '#src/engines/domain/model/historyFollower';\nimport { LLMAgent } from '#src/engines/domain/model/llmAgent';\nimport type { LLMClient } from '#src/llm/domain/llm';\nimport {\n\tClaudeLLMClient,\n\tclaudeLLMModels,\n\tclaudeLLMReasoningEfforts,\n} from '#src/llm/infrastructure/claudeLLMClient';\nimport {\n\tOpenAILLMClient,\n\topenAIModels,\n\topenAIReasoningEfforts,\n} from '#src/llm/infrastructure/openAILLMClient';\nimport {\n\texecutorInstructions,\n\texecutorInstructionsWithoutCommands,\n\tOrchestratorAgent,\n\tplannerInstructions,\n\treviewerInstructions,\n\treviewerInstructionsWithoutCommands,\n} from '#src/orchestration/domain/model/orchestratorAgent';\nimport { ReviewerDecisionValidator } from '#src/orchestration/infrastructure/model/reviewerDecisionValidator';\nimport type { RecoveryStore } from '#src/recovery/domain/recoveryStore';\nimport { RetryingAgent } from '#src/retry/domain/model/retryingAgent';\nimport { InvalidAgentConfigError } from '#src/shared/domain/errors';\nimport { isOneOf } from '#src/shared/domain/isOneOf';\nimport type { ILogger } from '#src/shared/domain/logger';\nimport { Logger } from '#src/shared/infrastructure/logger';\nimport type { WorkspaceRoot } from '#src/tools/domain/accessPolicy';\nimport {\n\ttype CommandRole,\n\ttype Commands,\n\tcommandsFor,\n\tvalidateCommands,\n} from '#src/tools/domain/commands';\nimport type { AgentTool } from '#src/tools/domain/preparedCall';\nimport type { Tool } from '#src/tools/domain/tool';\nimport {\n\tcommandToolFor,\n\ttype FileTool,\n\tfileToolsFor,\n\ttype OpenedWorkspace,\n\topenStore,\n\topenWorkspace,\n\tstateDirectoryOf,\n\ttype WorkspaceOptions,\n} from '#src/tools/infrastructure/fileTools';\nimport { createShowChangesTool } from '#src/tools/infrastructure/showChangesTool';\nimport { createTrackedReadFile } from '#src/tools/infrastructure/trackedReadFile';\nimport { createWorkspaceTools } from '#src/tools/infrastructure/workspaceTools';\nimport { isAgentProvider, orchestratorRolesFor, type Role } from './agentFactory.ts';\nimport {\n\tagentProviders,\n\ttype AgentModel,\n\ttype AgentProvider,\n\ttype CreateOrchestratorOptions,\n\ttype ReasoningEffort,\n} from './types.ts';\n\n/** The models each provider's model API accepts. */\nexport const llmModels = {\n\tanthropic: claudeLLMModels,\n\topenai: openAIModels,\n} as const satisfies Readonly<Record<AgentProvider, readonly AgentModel[]>>;\n\n/** The reasoning efforts each provider's model API accepts. */\nexport const llmReasoningEfforts = {\n\tanthropic: claudeLLMReasoningEfforts,\n\topenai: openAIReasoningEfforts,\n} as const satisfies Readonly<Record<AgentProvider, readonly ReasoningEffort[]>>;\n\n/** Narrows a model to one accepted by the selected provider's model API. */\nexport function isLLMModelOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmModels)[Provider][number] {\n\treturn isOneOf(llmModels[provider], value);\n}\n\n/** Narrows a reasoning effort to one accepted by the selected provider's model API. */\nexport function isLLMReasoningEffortOf<Provider extends AgentProvider>(\n\tprovider: Provider,\n\tvalue: string,\n): value is (typeof llmReasoningEfforts)[Provider][number] {\n\treturn isOneOf(llmReasoningEfforts[provider], value);\n}\n\nexport interface CreateLLMAgentOptions {\n\t/**\n\t * Defaults to `'sonnet'` on Anthropic and `'gpt-5.6-luna'` on OpenAI. The provider's client\n\t * rejects a model it does not support.\n\t */\n\tmodel?: AgentModel;\n\t/** Defaults to `'high'`. The provider's client rejects an effort it does not support. */\n\treasoningEffort?: ReasoningEffort;\n\t/** Sent as the model's instructions on every call. */\n\tsystemPrompt: string;\n\t/** The tools the model may call: the consumer's own, and those of `createFileTools`. Defaults to none. */\n\ttools?: (Tool | FileTool)[];\n\t/**\n\t * The folders the agent works on, the same as given to `createFileTools`. With it, the agent\n\t * follows the workspace's history: after the user undoes runs, its next run starts from the\n\t * conversation as it was, and is told what was undone. The system prompt is followed by the\n\t * roots and how to name a file in them.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * With `workspace`, a summary of what was undone, from the provider's cheap model, in place\n\t * of the undone prompts. That is Claude Haiku without thinking, or `gpt-5.6-luna` at high\n\t * effort, and the call is billed with the run's tokens. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n\t/**\n\t * How many calls to the model one run may make before it fails. Defaults to 65, with no upper\n\t * bound. A run that asks for exactly the same tool calls 5 times in a row fails before that.\n\t */\n\tmaxSteps?: number;\n\t/**\n\t * Runs every tool call without asking, `destructive` ones included, for CI where no one can\n\t * answer. Without it, a `destructive` call goes to the run's `approve`, or is denied.\n\t */\n\tautoApprove?: boolean;\n\t/** Defaults to warnings on stderr. */\n\tlogger?: ILogger;\n}\n\n/** A limit per role of `createLLMOrchestrator`; a role left out keeps its default. */\nexport type RoleSteps = Partial<Record<OrchestratorRole, number>>;\n\n// The same three roles a command can be given to.\ntype OrchestratorRole = CommandRole;\n\n// The executor reads, edits and checks, so it needs more calls than the roles that only read.\nconst defaultRoleSteps: Record<OrchestratorRole, number> = {\n\tplanner: 65,\n\texecutor: 80,\n\treviewer: 65,\n};\n\n/**\n * Each role's step limit, from one number for all of them or a number per role.\n *\n * @throws {InvalidAgentConfigError} for a value that is neither, and for a role that does not\n * exist, which is a typo that would otherwise leave that role on its default without a word.\n */\nfunction stepsPerRole(maxSteps: unknown): Record<OrchestratorRole, number> {\n\tif (maxSteps === undefined) return defaultRoleSteps;\n\tif (typeof maxSteps === 'number') {\n\t\treturn { planner: maxSteps, executor: maxSteps, reviewer: maxSteps };\n\t}\n\t// Untyped input, such as the CLI's configuration file, can hold `null` or a list here.\n\tif (typeof maxSteps !== 'object' || maxSteps === null || Array.isArray(maxSteps)) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t'maxSteps must be a number or an object of steps per role, such as { \"executor\": 120 }',\n\t\t);\n\t}\n\tconst unknown = Object.keys(maxSteps).filter(role => !(role in defaultRoleSteps));\n\tif (unknown.length > 0) {\n\t\tthrow new InvalidAgentConfigError(\n\t\t\t`maxSteps names roles that do not exist: ${unknown.join(', ')}; expected planner, executor or reviewer`,\n\t\t);\n\t}\n\t// A role given as `undefined`, which untyped input can do, keeps its default.\n\tconst given = Object.entries(maxSteps as Record<string, unknown>).filter(\n\t\t([, steps]) => steps !== undefined,\n\t);\n\treturn { ...defaultRoleSteps, ...Object.fromEntries(given) };\n}\n\nexport interface CreateLLMOrchestratorOptions extends CreateOrchestratorOptions {\n\t/**\n\t * The folders the agents work on. The executor changes files only in a `write` root, every\n\t * change recorded in the workspace's history. Defaults to the current working directory,\n\t * read only.\n\t */\n\tworkspace?: WorkspaceOptions;\n\t/**\n\t * How many calls to the model one run of each role may make: one number for every role, or a\n\t * number per role. Defaults to 80 for the executor and 65 for the planner and the reviewer,\n\t * with no upper bound. A run that asks for exactly the same tool calls 5 times in a row fails\n\t * before its limit.\n\t */\n\tmaxSteps?: number | RoleSteps;\n\t/**\n\t * Commands the roles may run, such as the project's tests, through `runCommand`. Each goes to\n\t * the roles its `roles` names, the executor by default. See `createFileTools`. Each needs a\n\t * `write` root to run in.\n\t */\n\tcommands?: Commands;\n\t/**\n\t * A summary of what the user undid, from the planner's provider's cheap model, for every\n\t * role. See `CreateLLMAgentOptions.summarizeUndone`. Defaults to `true`.\n\t */\n\tsummarizeUndone?: boolean;\n}\n\nconst defaultLLMAgentModels = {\n\tanthropic: 'sonnet',\n\topenai: 'gpt-5.6-luna',\n} as const satisfies Record<AgentProvider, AgentModel>;\n\nfunction unknownProvider(provider: never): InvalidAgentConfigError {\n\treturn new InvalidAgentConfigError(\n\t\t`\"${String(provider)}\" is not an agent provider; expected one of: ${agentProviders.join(', ')}`,\n\t);\n}\n\nfunction llmClientFor(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\tlogger,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tsystemPrompt: string;\n\t\tlogger: ILogger;\n\t},\n): LLMClient {\n\tswitch (provider) {\n\t\tcase 'anthropic':\n\t\t\treturn new ClaudeLLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.anthropic,\n\t\t\t\treasoningEffort,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tcase 'openai':\n\t\t\treturn new OpenAILLMClient({\n\t\t\t\tmodel: model ?? defaultLLMAgentModels.openai,\n\t\t\t\treasoningEffort,\n\t\t\t\tsystemPrompt,\n\t\t\t\tlogger,\n\t\t\t});\n\t\tdefault:\n\t\t\t// Reachable from untyped input.\n\t\t\tthrow unknownProvider(provider);\n\t}\n}\n\n/** The provider's cheap model, for the summary of what was undone. */\nfunction summarizerFor(provider: AgentProvider, logger: ILogger): LLMClient {\n\treturn provider === 'anthropic'\n\t\t? new ClaudeLLMClient({ model: 'haiku', systemPrompt: '', logger })\n\t\t: new OpenAILLMClient({\n\t\t\t\tmodel: 'gpt-5.6-luna',\n\t\t\t\treasoningEffort: 'high',\n\t\t\t\tsystemPrompt: '',\n\t\t\t\tlogger,\n\t\t\t});\n}\n\n/**\n * The workspace's history, opened on first use, so a factory that builds an agent stays\n * synchronous. Every agent and every file tool of one workspace reads the same files on disk.\n */\nfunction historyOf(workspace: WorkspaceOptions): HistoryReader {\n\t// Checked now: an agent with no root to follow is a setup error, not a first-run one.\n\tif (workspace.roots.length === 0) {\n\t\tthrow new InvalidAgentConfigError('A workspace needs at least one root');\n\t}\n\tlet store: Promise<RecoveryStore> | undefined;\n\tconst open = () => {\n\t\tstore ??= stateDirectoryOf(workspace)\n\t\t\t.then(directory => openStore(workspace, directory))\n\t\t\t.catch((error: unknown) => {\n\t\t\t\t// Not kept: the next run tries again, as one whose disk was full for a moment.\n\t\t\t\tstore = undefined;\n\t\t\t\tthrow error;\n\t\t\t});\n\t\treturn store;\n\t};\n\treturn {\n\t\tlistRuns: async () => (await open()).listRuns(),\n\t\tlistRevisions: async () => (await open()).listRevisions(),\n\t\treadRun: async runId => (await open()).readRun(runId),\n\t};\n}\n\n/**\n * What the model is told about the workspace after its instructions: the roots, which it may\n * change, and how to name a file. A host path in an error sends the model looking for it, so\n * the real root is given here once.\n */\nfunction workspaceGuidance(roots: WorkspaceRoot[]): string {\n\tconst [first, ...others] = roots.map(root => ({ ...root, path: resolve(root.path) }));\n\tif (!first) return '';\n\tconst described = [first, ...others].map(\n\t\t({ path, access }) => `- ${path}${access === 'write' ? '' : ' (read only)'}`,\n\t);\n\treturn [\n\t\t'The workspace:',\n\t\t...described,\n\t\t`Name a file by its path relative to ${first.path}, such as src/index.ts, and a file in another folder of the workspace by its full path. Read a file before you change it.`,\n\t].join('\\n');\n}\n\nfunction withGuidance(systemPrompt: string, guidance: string): string {\n\treturn guidance === '' ? systemPrompt : `${systemPrompt}\\n\\n${guidance}`;\n}\n\n/** An `LLMAgent` on `provider`, wrapped in the harness's retry policy. */\nfunction buildLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools,\n\t\thistory,\n\t\tsummarizer,\n\t\tmaxSteps,\n\t\tautoApprove,\n\t\tlogger,\n\t}: {\n\t\tmodel?: AgentModel;\n\t\treasoningEffort?: ReasoningEffort;\n\t\tsystemPrompt: string;\n\t\ttools: AgentTool[];\n\t\thistory?: HistoryReader;\n\t\tsummarizer?: LLMClient;\n\t\tmaxSteps?: number;\n\t\tautoApprove?: boolean;\n\t\tlogger: ILogger;\n\t},\n): Agent {\n\tconst llmClient = llmClientFor(provider, { model, reasoningEffort, systemPrompt, logger });\n\t// LLMAgent records nothing from a failed call, so the original prompt is the whole story.\n\treturn new RetryingAgent({\n\t\tinner: new LLMAgent({\n\t\t\tllmClient,\n\t\t\ttools,\n\t\t\tautoApprove,\n\t\t\tlogger,\n\t\t\t...(history ? { history } : {}),\n\t\t\t...(summarizer ? { summarizer } : {}),\n\t\t\t...(maxSteps === undefined ? {} : { maxSteps }),\n\t\t}),\n\t\tlogger,\n\t\tnoteFailures: false,\n\t});\n}\n\n/**\n * Builds an agent whose conversation MiKode owns, on a provider's model API, already wrapped in\n * the harness's retry policy. It needs the provider's API key and bills per token, where\n * `createAgent` uses the Agent SDK's login. Each tool judges the risk of each call; a\n * `destructive` one runs only when the run's `approve` allows it, or with `autoApprove`.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a model or reasoning effort its\n * client does not support, or two tools that share a name.\n * @throws {UnrecoverableError} when the client cannot be set up, for example because\n * `OPENAI_API_KEY` is missing. The Anthropic SDK resolves credentials lazily, so a missing\n * `ANTHROPIC_API_KEY` fails the first run instead, with an `UnrecoverableError`.\n */\nexport function createLLMAgent(\n\tprovider: AgentProvider,\n\t{\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt,\n\t\ttools = [],\n\t\tworkspace,\n\t\tsummarizeUndone = true,\n\t\tmaxSteps,\n\t\tautoApprove,\n\t\tlogger = new Logger(),\n\t}: CreateLLMAgentOptions,\n): Agent {\n\treturn buildLLMAgent(provider, {\n\t\tmodel,\n\t\treasoningEffort,\n\t\tsystemPrompt: workspace\n\t\t\t? withGuidance(systemPrompt, workspaceGuidance(workspace.roots))\n\t\t\t: systemPrompt,\n\t\t// A file tool is a harness tool under its public name.\n\t\ttools: tools as AgentTool[],\n\t\t...(workspace ? { history: historyOf(workspace) } : {}),\n\t\t...(workspace && summarizeUndone ? { summarizer: summarizerFor(provider, logger) } : {}),\n\t\tmaxSteps,\n\t\tautoApprove,\n\t\tlogger,\n\t});\n}\n\n/**\n * The file tools for an agent from `createLLMAgent` on `provider`, over `workspace`, in the\n * provider's own format:\n *\n * - OpenAI: `listFiles`, `searchText`, `readFile` and its native `apply_patch`;\n * - Anthropic: `listFiles`, `searchText`, its native text editor, whose `view` reads, and\n * `delete_file`.\n *\n * Every one goes through the workspace's access policy: a path outside the roots, a secret,\n * a file `.gitignore` excludes or the harness protects is refused. A change is made only in a\n * `write` root, only from a version the agent read, and is recorded in the workspace's history,\n * so it can be undone. Without a `write` root the tools only read. Give the agent the same\n * `workspace`, so it follows what the history undoes.\n *\n * With `commands`, they include `runCommand`, which runs one of them by name, with only the\n * parameters it declares and never through a shell. Each run asks the approver, showing the\n * program exactly as it will run, and gets a small environment without the provider keys. The\n * files of the `write` roots are captured before it and compared after, so what it changed is\n * in the history too. It is trusted execution, not a sandbox: a command can reach whatever\n * this user can. Not supported on Windows yet.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, a workspace with no root, or an\n * invalid command, including one whose `cwd` is not in a `write` root, or any on Windows.\n * @throws {UnrecoverableError} when no program can read the first root.\n */\nexport async function createFileTools(\n\tprovider: AgentProvider,\n\tworkspace: WorkspaceOptions,\n\t{ logger = new Logger(), commands }: { logger?: ILogger; commands?: Commands } = {},\n): Promise<FileTool[]> {\n\t// Reachable from untyped input.\n\tif (!isAgentProvider(provider)) throw unknownProvider(provider);\n\tif (commands !== undefined) validateCommands(commands);\n\tconst opened = await openWorkspace(workspace, logger);\n\treturn (await executorTools(provider, opened, commands)) as unknown as FileTool[];\n}\n\n/** The executor's file tools, and `runCommand` when there are commands. */\nasync function executorTools(\n\tprovider: AgentProvider,\n\tworkspace: OpenedWorkspace,\n\tcommands: Commands | undefined,\n): Promise<AgentTool[]> {\n\tconst tools = fileToolsFor(provider, workspace);\n\t// Every command may belong to other roles, leaving none for this one.\n\tif (commands === undefined || Object.keys(commands).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, commands)];\n}\n\n/**\n * What the planner and the reviewer read with: no edits, the current task's changes, and the\n * commands given to their role.\n */\nasync function readingTools(\n\tworkspace: OpenedWorkspace,\n\trole: CommandRole,\n\tcommands: Commands | undefined,\n): Promise<AgentTool[]> {\n\tconst { read, policy, store } = workspace;\n\tconst finding = createWorkspaceTools(read).filter(tool => tool.name !== 'readFile');\n\tconst tools = [\n\t\t...finding,\n\t\tcreateTrackedReadFile(policy),\n\t\tcreateShowChangesTool({ store, policy }),\n\t];\n\tconst own = commands && commandsFor(commands, role);\n\tif (!own || Object.keys(own).length === 0) return tools;\n\treturn [...tools, await commandToolFor(workspace, own)];\n}\n\n// Sent after the workspace's roots, so it stays short: it only says how to find one's way\n// around the repository without reading all of it.\nconst repositoryGuidance =\n\t'Start with AGENTS.md and the architecture document it links to learn where things live, then read only the files your task needs. When you know you need several files, or several searches, ask for all of them in one answer rather than one at a time: each answer is a step, and steps are limited.';\n\n/**\n * Builds the planner → executor → reviewer workflow with every role on the model APIs, each\n * holding its role's instructions, or `systemPrompts`, as its system prompt, followed by the\n * workspace's roots.\n *\n * - The planner and the reviewer read: `listFiles`, `searchText`, `readFile`, and\n * `showChanges`, the current task's changes as far as each may read them.\n * - The executor gets its provider's file tools (see `createFileTools`), and changes files only\n * in a `write` root; `autoApprove` reaches only it.\n * - Each role has its own step limit: `maxSteps`, 80 for the executor and 65 for the others by\n * default.\n * - Each role gets `runCommand` with the `commands` whose `roles` name it, the executor by\n * default. A command asks the approver in any role, and its files are captured around it.\n * - The executor is told to finish only once the tests and checks pass, and the reviewer that\n * they passed, when the executor has a command; without one, both are told the tests were\n * not run, and the reviewer judges from the code whether they would pass.\n *\n * One run of the orchestrator is one run of the workspace's history, every round and retry\n * included, and its `AgentResponse` names it. Every role follows what the user undoes.\n * Asynchronous because opening the workspace is.\n *\n * @throws {InvalidAgentConfigError} for an unknown provider, or a workspace with no root.\n * @throws {UnrecoverableError} when a role cannot be set up, for example because\n * `OPENAI_API_KEY` is missing, or when no program can read the repository.\n */\nexport async function createLLMOrchestrator({\n\tprovider,\n\tautoApprove,\n\tsystemPrompts = {},\n\tworkspace = { roots: [{ path: process.cwd(), access: 'read' }] },\n\tmaxSteps,\n\tcommands,\n\tsummarizeUndone = true,\n\tlogger = new Logger(),\n}: CreateLLMOrchestratorOptions = {}): Promise<Agent> {\n\tconst roles = orchestratorRolesFor(provider);\n\tconst steps = stepsPerRole(maxSteps);\n\tconst opened = await openWorkspace(workspace, logger);\n\tconst guidance = workspaceGuidance(workspace.roots);\n\tconst summarizer = summarizeUndone ? summarizerFor(roles.planner.provider, logger) : undefined;\n\tconst shared = { history: opened.store, ...(summarizer ? { summarizer } : {}), logger };\n\t// A caller's own prompt replaces our instructions and guidance, not the workspace: the model\n\t// needs the roots to name a file, as `createLLMAgent` gives them.\n\tconst prompt = (own: string | undefined, instructions: string) =>\n\t\town === undefined\n\t\t\t? withGuidance(instructions, `${guidance}\\n${repositoryGuidance}`)\n\t\t\t: withGuidance(own, guidance);\n\t// Every command, checked once, before any role takes its share.\n\tif (commands !== undefined) validateCommands(commands);\n\tconst reader = async (\n\t\t{ provider, model, reasoningEffort }: Role,\n\t\trole: CommandRole,\n\t\tsystemPrompt: string,\n\t) =>\n\t\tbuildLLMAgent(provider, {\n\t\t\tmodel,\n\t\t\treasoningEffort,\n\t\t\tsystemPrompt,\n\t\t\ttools: await readingTools(opened, role, commands),\n\t\t\tmaxSteps: steps[role],\n\t\t\t...shared,\n\t\t});\n\tconst { executor } = roles;\n\tconst executorToolset = await executorTools(\n\t\texecutor.provider,\n\t\topened,\n\t\tcommands && commandsFor(commands, 'executor'),\n\t);\n\t// The executor and the reviewer are told whether the tests were run, which only an executor\n\t// with a command can do.\n\tconst executorRuns = executorToolset.some(tool => tool.name === 'runCommand');\n\n\treturn new OrchestratorAgent({\n\t\tplannerAgent: await reader(\n\t\t\troles.planner,\n\t\t\t'planner',\n\t\t\tprompt(systemPrompts.planner, plannerInstructions),\n\t\t),\n\t\texecutorAgent: buildLLMAgent(executor.provider, {\n\t\t\tmodel: executor.model,\n\t\t\treasoningEffort: executor.reasoningEffort,\n\t\t\tsystemPrompt: prompt(\n\t\t\t\tsystemPrompts.executor,\n\t\t\t\texecutorRuns ? executorInstructions : executorInstructionsWithoutCommands,\n\t\t\t),\n\t\t\ttools: executorToolset,\n\t\t\tmaxSteps: steps.executor,\n\t\t\tautoApprove,\n\t\t\t...shared,\n\t\t}),\n\t\treviewerAgent: await reader(\n\t\t\troles.reviewer,\n\t\t\t'reviewer',\n\t\t\tprompt(\n\t\t\t\tsystemPrompts.reviewer,\n\t\t\t\texecutorRuns ? reviewerInstructions : reviewerInstructionsWithoutCommands,\n\t\t\t),\n\t\t),\n\t\treviewerDecisionValidator: new ReviewerDecisionValidator(),\n\t\tlogger,\n\t});\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,23 @@
|
|
|
1
1
|
export type { ILogger } from './shared/domain/logger.ts';
|
|
2
|
-
export { createAgent, createOrchestrator, isAgentProvider, type CreateAgentOptions, } from './factory/infrastructure/agentFactory.ts';
|
|
3
|
-
export { createLLMAgent, createLLMOrchestrator, type CreateLLMAgentOptions, } from './factory/infrastructure/agentLLMFactory.ts';
|
|
2
|
+
export { createAgent, createOrchestrator, agentModels, agentReasoningEfforts, isAgentProvider, isModelOf, isReasoningEffortOf, type CreateAgentOptions, } from './factory/infrastructure/agentFactory.ts';
|
|
3
|
+
export { createFileTools, createLLMAgent, createLLMOrchestrator, isLLMModelOf, isLLMReasoningEffortOf, llmModels, llmReasoningEfforts, type CreateLLMAgentOptions, type CreateLLMOrchestratorOptions, type RoleSteps, } from './factory/infrastructure/agentLLMFactory.ts';
|
|
4
|
+
export type { FileTool, WorkspaceOptions } from './tools/infrastructure/fileTools.ts';
|
|
5
|
+
export type { WorkspaceRoot } from './tools/domain/accessPolicy.ts';
|
|
6
|
+
export type { CommandArgument, CommandDefinition, CommandParameter, CommandRole, Commands, } from './tools/domain/commands.ts';
|
|
7
|
+
export type { SecretRules } from './tools/infrastructure/rootsAccessPolicy.ts';
|
|
4
8
|
export { agentProviders, type AgentModel, type AgentProvider, type CreateOrchestratorOptions, type ReasoningEffort, } from './factory/infrastructure/types.ts';
|
|
5
9
|
export { type Agent, type AgentResponse, type Callback, type ProgressEvent, type RunOptions, } from './agent/domain/agent.ts';
|
|
6
10
|
export { InvalidAgentConfigError, RecoverableError, UnrecoverableError, } from './shared/domain/errors.ts';
|
|
7
11
|
export { isAbortError } from './shared/domain/isAbortError.ts';
|
|
8
12
|
export type { Tokens } from './shared/domain/tokens.ts';
|
|
9
|
-
export { rememberApprovals, type ApprovalDecision, type ApprovalRequest, type Approver, type RememberableDecision, type ToolRisk, } from './agent/domain/approval.ts';
|
|
13
|
+
export { rememberApprovals, type ApprovalDecision, type ApprovalRequest, type Approver, type CommandLine, type RememberableDecision, type ToolRisk, } from './agent/domain/approval.ts';
|
|
10
14
|
export type { JSONSchema, ToolDefinition } from './llm/domain/tool.ts';
|
|
11
15
|
export type { Tool } from './tools/domain/tool.ts';
|
|
12
16
|
export type { TextMatch, Workspace } from './tools/domain/workspace.ts';
|
|
13
17
|
export { defineTool } from './tools/infrastructure/defineTool.ts';
|
|
14
18
|
export { createWorkspace } from './tools/infrastructure/createWorkspace.ts';
|
|
15
19
|
export { createWorkspaceTools } from './tools/infrastructure/workspaceTools.ts';
|
|
20
|
+
export { createHistory } from './recovery/infrastructure/createHistory.ts';
|
|
21
|
+
export type { History, HistoryRun, Move } from './recovery/domain/history.ts';
|
|
22
|
+
export { historyStart, NothingToMoveError, WorkspaceBusyError, WorkspaceMovedError, type MoveOptions, type RunStatus, } from './recovery/domain/recoveryStore.ts';
|
|
23
|
+
export { HistoryExpiredError, UnknownRunError } from './recovery/domain/runTree.ts';
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export { createAgent, createOrchestrator, isAgentProvider, } from "./factory/infrastructure/agentFactory.js";
|
|
2
|
-
export { createLLMAgent, createLLMOrchestrator, } from "./factory/infrastructure/agentLLMFactory.js";
|
|
1
|
+
export { createAgent, createOrchestrator, agentModels, agentReasoningEfforts, isAgentProvider, isModelOf, isReasoningEffortOf, } from "./factory/infrastructure/agentFactory.js";
|
|
2
|
+
export { createFileTools, createLLMAgent, createLLMOrchestrator, isLLMModelOf, isLLMReasoningEffortOf, llmModels, llmReasoningEfforts, } from "./factory/infrastructure/agentLLMFactory.js";
|
|
3
3
|
export { agentProviders, } from "./factory/infrastructure/types.js";
|
|
4
4
|
export {} from "./agent/domain/agent.js";
|
|
5
5
|
export { InvalidAgentConfigError, RecoverableError, UnrecoverableError, } from "./shared/domain/errors.js";
|
|
@@ -8,4 +8,7 @@ export { rememberApprovals, } from "./agent/domain/approval.js";
|
|
|
8
8
|
export { defineTool } from "./tools/infrastructure/defineTool.js";
|
|
9
9
|
export { createWorkspace } from "./tools/infrastructure/createWorkspace.js";
|
|
10
10
|
export { createWorkspaceTools } from "./tools/infrastructure/workspaceTools.js";
|
|
11
|
+
export { createHistory } from "./recovery/infrastructure/createHistory.js";
|
|
12
|
+
export { historyStart, NothingToMoveError, WorkspaceBusyError, WorkspaceMovedError, } from "./recovery/domain/recoveryStore.js";
|
|
13
|
+
export { HistoryExpiredError, UnknownRunError } from "./recovery/domain/runTree.js";
|
|
11
14
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,WAAW,EACX,kBAAkB,EAClB,eAAe,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EACN,WAAW,EACX,kBAAkB,EAClB,WAAW,EACX,qBAAqB,EACrB,eAAe,EACf,SAAS,EACT,mBAAmB,GAEnB,MAAM,0CAA0C,CAAC;AAClD,OAAO,EACN,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,sBAAsB,EACtB,SAAS,EACT,mBAAmB,GAInB,MAAM,6CAA6C,CAAC;AAWrD,OAAO,EACN,cAAc,GAKd,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAMN,MAAM,yBAAyB,CAAC;AACjC,OAAO,EACN,uBAAuB,EACvB,gBAAgB,EAChB,kBAAkB,GAClB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,YAAY,EAAE,MAAM,iCAAiC,CAAC;AAE/D,OAAO,EACN,iBAAiB,GAOjB,MAAM,4BAA4B,CAAC;AAIpC,OAAO,EAAE,UAAU,EAAE,MAAM,sCAAsC,CAAC;AAClE,OAAO,EAAE,eAAe,EAAE,MAAM,2CAA2C,CAAC;AAC5E,OAAO,EAAE,oBAAoB,EAAE,MAAM,0CAA0C,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,4CAA4C,CAAC;AAE3E,OAAO,EACN,YAAY,EACZ,kBAAkB,EAClB,kBAAkB,EAClB,mBAAmB,GAGnB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["export type { ILogger } from './shared/domain/logger.ts';\nexport {\n\tcreateAgent,\n\tcreateOrchestrator,\n\tagentModels,\n\tagentReasoningEfforts,\n\tisAgentProvider,\n\tisModelOf,\n\tisReasoningEffortOf,\n\ttype CreateAgentOptions,\n} from './factory/infrastructure/agentFactory.ts';\nexport {\n\tcreateFileTools,\n\tcreateLLMAgent,\n\tcreateLLMOrchestrator,\n\tisLLMModelOf,\n\tisLLMReasoningEffortOf,\n\tllmModels,\n\tllmReasoningEfforts,\n\ttype CreateLLMAgentOptions,\n\ttype CreateLLMOrchestratorOptions,\n\ttype RoleSteps,\n} from './factory/infrastructure/agentLLMFactory.ts';\nexport type { FileTool, WorkspaceOptions } from './tools/infrastructure/fileTools.ts';\nexport type { WorkspaceRoot } from './tools/domain/accessPolicy.ts';\nexport type {\n\tCommandArgument,\n\tCommandDefinition,\n\tCommandParameter,\n\tCommandRole,\n\tCommands,\n} from './tools/domain/commands.ts';\nexport type { SecretRules } from './tools/infrastructure/rootsAccessPolicy.ts';\nexport {\n\tagentProviders,\n\ttype AgentModel,\n\ttype AgentProvider,\n\ttype CreateOrchestratorOptions,\n\ttype ReasoningEffort,\n} from './factory/infrastructure/types.ts';\nexport {\n\ttype Agent,\n\ttype AgentResponse,\n\ttype Callback,\n\ttype ProgressEvent,\n\ttype RunOptions,\n} from './agent/domain/agent.ts';\nexport {\n\tInvalidAgentConfigError,\n\tRecoverableError,\n\tUnrecoverableError,\n} from './shared/domain/errors.ts';\nexport { isAbortError } from './shared/domain/isAbortError.ts';\nexport type { Tokens } from './shared/domain/tokens.ts';\nexport {\n\trememberApprovals,\n\ttype ApprovalDecision,\n\ttype ApprovalRequest,\n\ttype Approver,\n\ttype CommandLine,\n\ttype RememberableDecision,\n\ttype ToolRisk,\n} from './agent/domain/approval.ts';\nexport type { JSONSchema, ToolDefinition } from './llm/domain/tool.ts';\nexport type { Tool } from './tools/domain/tool.ts';\nexport type { TextMatch, Workspace } from './tools/domain/workspace.ts';\nexport { defineTool } from './tools/infrastructure/defineTool.ts';\nexport { createWorkspace } from './tools/infrastructure/createWorkspace.ts';\nexport { createWorkspaceTools } from './tools/infrastructure/workspaceTools.ts';\nexport { createHistory } from './recovery/infrastructure/createHistory.ts';\nexport type { History, HistoryRun, Move } from './recovery/domain/history.ts';\nexport {\n\thistoryStart,\n\tNothingToMoveError,\n\tWorkspaceBusyError,\n\tWorkspaceMovedError,\n\ttype MoveOptions,\n\ttype RunStatus,\n} from './recovery/domain/recoveryStore.ts';\nexport { HistoryExpiredError, UnknownRunError } from './recovery/domain/runTree.ts';\n"]}
|
|
@@ -1,21 +1,61 @@
|
|
|
1
1
|
import type { Message } from './message.ts';
|
|
2
|
+
/**
|
|
3
|
+
* Which run of a workspace's history a turn belongs to. It is filled once that run writes, and
|
|
4
|
+
* the same object is shared by every turn the run records, so a turn recorded before the run
|
|
5
|
+
* first wrote still learns its run. A run that never writes leaves it empty.
|
|
6
|
+
*/
|
|
7
|
+
export interface TurnRun {
|
|
8
|
+
runId?: string;
|
|
9
|
+
}
|
|
10
|
+
/** What is known about one recorded turn, without its messages. */
|
|
11
|
+
export interface TurnInfo {
|
|
12
|
+
index: number;
|
|
13
|
+
/** The turn it followed, or `undefined` for one that followed only the initial messages. */
|
|
14
|
+
parent: number | undefined;
|
|
15
|
+
/** The history run it belongs to, as known now. */
|
|
16
|
+
runId: string | undefined;
|
|
17
|
+
}
|
|
2
18
|
/**
|
|
3
19
|
* What one agent remembers across its runs. The LLM never sees this object, only the
|
|
4
20
|
* context built from it, so how the context is derived (compaction, later) can change
|
|
5
21
|
* without touching either side.
|
|
22
|
+
*
|
|
23
|
+
* Its turns form a tree. Each follows the turn that ended the context it was given, and the
|
|
24
|
+
* context is the path to the current turn, so going back in the workspace's history can point
|
|
25
|
+
* the conversation back at an earlier turn and keep the later ones for a redo.
|
|
6
26
|
*/
|
|
7
27
|
export declare class Conversation {
|
|
8
|
-
private readonly
|
|
28
|
+
private readonly initial;
|
|
29
|
+
private readonly turns;
|
|
30
|
+
private current;
|
|
9
31
|
constructor(messages?: Message[]);
|
|
10
32
|
/**
|
|
11
33
|
* Records a whole run at once, once it succeeded: the prompt, every step the model took and
|
|
12
34
|
* every tool result. A failed run records nothing, so a retry cannot repeat its prompt, and
|
|
13
|
-
* no tool call is ever kept without its result.
|
|
35
|
+
* no tool call is ever kept without its result. The turn follows the current one and becomes
|
|
36
|
+
* the current one.
|
|
14
37
|
*/
|
|
15
38
|
addRun(messages: Message[]): void;
|
|
16
39
|
/**
|
|
17
|
-
*
|
|
18
|
-
*
|
|
40
|
+
* Records a run like `addRun`, after `turn` (`undefined` for none but the initial messages).
|
|
41
|
+
* `run` is kept as it is, not copied, so it can still learn its run id.
|
|
42
|
+
*/
|
|
43
|
+
addRunAfter(turn: number | undefined, messages: Message[], run: TurnRun): void;
|
|
44
|
+
/**
|
|
45
|
+
* The initial messages, then every turn on the path to the current one. A deep copy, like
|
|
46
|
+
* everything the conversation takes in: a client that rewrites the messages it was sent
|
|
47
|
+
* cannot change what the next turn sends.
|
|
19
48
|
*/
|
|
20
49
|
getContext(): Message[];
|
|
50
|
+
/** The context with the path to `turn` in place of the current one's. */
|
|
51
|
+
contextAfter(turn: number | undefined): Message[];
|
|
52
|
+
/** The turn the next one follows by default: the last one recorded. */
|
|
53
|
+
get currentTurn(): number | undefined;
|
|
54
|
+
/** Every turn recorded, oldest first. */
|
|
55
|
+
describeTurns(): TurnInfo[];
|
|
56
|
+
/** The indexes from the first turn down to `turn`. */
|
|
57
|
+
path(turn: number | undefined): number[];
|
|
58
|
+
/** A copy of the messages one turn recorded. */
|
|
59
|
+
messagesOf(turn: number): Message[];
|
|
60
|
+
private turnAt;
|
|
21
61
|
}
|
|
@@ -2,26 +2,75 @@
|
|
|
2
2
|
* What one agent remembers across its runs. The LLM never sees this object, only the
|
|
3
3
|
* context built from it, so how the context is derived (compaction, later) can change
|
|
4
4
|
* without touching either side.
|
|
5
|
+
*
|
|
6
|
+
* Its turns form a tree. Each follows the turn that ended the context it was given, and the
|
|
7
|
+
* context is the path to the current turn, so going back in the workspace's history can point
|
|
8
|
+
* the conversation back at an earlier turn and keep the later ones for a redo.
|
|
5
9
|
*/
|
|
6
10
|
export class Conversation {
|
|
7
|
-
|
|
11
|
+
initial;
|
|
12
|
+
turns = [];
|
|
13
|
+
current;
|
|
8
14
|
constructor(messages = []) {
|
|
9
|
-
this.
|
|
15
|
+
this.initial = structuredClone(messages);
|
|
10
16
|
}
|
|
11
17
|
/**
|
|
12
18
|
* Records a whole run at once, once it succeeded: the prompt, every step the model took and
|
|
13
19
|
* every tool result. A failed run records nothing, so a retry cannot repeat its prompt, and
|
|
14
|
-
* no tool call is ever kept without its result.
|
|
20
|
+
* no tool call is ever kept without its result. The turn follows the current one and becomes
|
|
21
|
+
* the current one.
|
|
15
22
|
*/
|
|
16
23
|
addRun(messages) {
|
|
17
|
-
this.
|
|
24
|
+
this.addRunAfter(this.current, messages, {});
|
|
18
25
|
}
|
|
19
26
|
/**
|
|
20
|
-
*
|
|
21
|
-
*
|
|
27
|
+
* Records a run like `addRun`, after `turn` (`undefined` for none but the initial messages).
|
|
28
|
+
* `run` is kept as it is, not copied, so it can still learn its run id.
|
|
29
|
+
*/
|
|
30
|
+
addRunAfter(turn, messages, run) {
|
|
31
|
+
this.turns.push({ messages: structuredClone(messages), parent: turn, run });
|
|
32
|
+
this.current = this.turns.length - 1;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The initial messages, then every turn on the path to the current one. A deep copy, like
|
|
36
|
+
* everything the conversation takes in: a client that rewrites the messages it was sent
|
|
37
|
+
* cannot change what the next turn sends.
|
|
22
38
|
*/
|
|
23
39
|
getContext() {
|
|
24
|
-
return
|
|
40
|
+
return this.contextAfter(this.current);
|
|
41
|
+
}
|
|
42
|
+
/** The context with the path to `turn` in place of the current one's. */
|
|
43
|
+
contextAfter(turn) {
|
|
44
|
+
return structuredClone([
|
|
45
|
+
...this.initial,
|
|
46
|
+
...this.path(turn).flatMap(index => this.turnAt(index).messages),
|
|
47
|
+
]);
|
|
48
|
+
}
|
|
49
|
+
/** The turn the next one follows by default: the last one recorded. */
|
|
50
|
+
get currentTurn() {
|
|
51
|
+
return this.current;
|
|
52
|
+
}
|
|
53
|
+
/** Every turn recorded, oldest first. */
|
|
54
|
+
describeTurns() {
|
|
55
|
+
return this.turns.map(({ parent, run }, index) => ({ index, parent, runId: run.runId }));
|
|
56
|
+
}
|
|
57
|
+
/** The indexes from the first turn down to `turn`. */
|
|
58
|
+
path(turn) {
|
|
59
|
+
const indexes = [];
|
|
60
|
+
for (let index = turn; index !== undefined; index = this.turnAt(index).parent) {
|
|
61
|
+
indexes.unshift(index);
|
|
62
|
+
}
|
|
63
|
+
return indexes;
|
|
64
|
+
}
|
|
65
|
+
/** A copy of the messages one turn recorded. */
|
|
66
|
+
messagesOf(turn) {
|
|
67
|
+
return structuredClone(this.turnAt(turn).messages);
|
|
68
|
+
}
|
|
69
|
+
turnAt(index) {
|
|
70
|
+
const turn = this.turns[index];
|
|
71
|
+
if (!turn)
|
|
72
|
+
throw new RangeError(`The conversation has no turn ${String(index)}`);
|
|
73
|
+
return turn;
|
|
25
74
|
}
|
|
26
75
|
}
|
|
27
76
|
//# sourceMappingURL=conversation.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../../src/llm/domain/conversation.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"conversation.js","sourceRoot":"","sources":["../../../src/llm/domain/conversation.ts"],"names":[],"mappings":"AA0BA;;;;;;;;GAQG;AACH,MAAM,OAAO,YAAY;IACP,OAAO,CAAY;IACnB,KAAK,GAAW,EAAE,CAAC;IAC5B,OAAO,CAAqB;IAEpC,YAAY,WAAsB,EAAE;QACnC,IAAI,CAAC,OAAO,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,QAAmB;QACzB,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC9C,CAAC;IAED;;;OAGG;IACH,WAAW,CAAC,IAAwB,EAAE,QAAmB,EAAE,GAAY;QACtE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,eAAe,CAAC,QAAQ,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,CAAC;QAC5E,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;IACtC,CAAC;IAED;;;;OAIG;IACH,UAAU;QACT,OAAO,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACxC,CAAC;IAED,yEAAyE;IACzE,YAAY,CAAC,IAAwB;QACpC,OAAO,eAAe,CAAC;YACtB,GAAG,IAAI,CAAC,OAAO;YACf,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC;SAChE,CAAC,CAAC;IACJ,CAAC;IAED,uEAAuE;IACvE,IAAI,WAAW;QACd,OAAO,IAAI,CAAC,OAAO,CAAC;IACrB,CAAC;IAED,yCAAyC;IACzC,aAAa;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;IAC1F,CAAC;IAED,sDAAsD;IACtD,IAAI,CAAC,IAAwB;QAC5B,MAAM,OAAO,GAAa,EAAE,CAAC;QAC7B,KAAK,IAAI,KAAK,GAAG,IAAI,EAAE,KAAK,KAAK,SAAS,EAAE,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE,CAAC;YAC/E,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACxB,CAAC;QACD,OAAO,OAAO,CAAC;IAChB,CAAC;IAED,gDAAgD;IAChD,UAAU,CAAC,IAAY;QACtB,OAAO,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,CAAC;IACpD,CAAC;IAEO,MAAM,CAAC,KAAa;QAC3B,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QAC/B,IAAI,CAAC,IAAI;YAAE,MAAM,IAAI,UAAU,CAAC,gCAAgC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QACjF,OAAO,IAAI,CAAC;IACb,CAAC;CACD","sourcesContent":["import type { Message } from './message.ts';\n\n/**\n * Which run of a workspace's history a turn belongs to. It is filled once that run writes, and\n * the same object is shared by every turn the run records, so a turn recorded before the run\n * first wrote still learns its run. A run that never writes leaves it empty.\n */\nexport interface TurnRun {\n\trunId?: string;\n}\n\n/** What is known about one recorded turn, without its messages. */\nexport interface TurnInfo {\n\tindex: number;\n\t/** The turn it followed, or `undefined` for one that followed only the initial messages. */\n\tparent: number | undefined;\n\t/** The history run it belongs to, as known now. */\n\trunId: string | undefined;\n}\n\ninterface Turn {\n\tmessages: Message[];\n\tparent: number | undefined;\n\trun: TurnRun;\n}\n\n/**\n * What one agent remembers across its runs. The LLM never sees this object, only the\n * context built from it, so how the context is derived (compaction, later) can change\n * without touching either side.\n *\n * Its turns form a tree. Each follows the turn that ended the context it was given, and the\n * context is the path to the current turn, so going back in the workspace's history can point\n * the conversation back at an earlier turn and keep the later ones for a redo.\n */\nexport class Conversation {\n\tprivate readonly initial: Message[];\n\tprivate readonly turns: Turn[] = [];\n\tprivate current: number | undefined;\n\n\tconstructor(messages: Message[] = []) {\n\t\tthis.initial = structuredClone(messages);\n\t}\n\n\t/**\n\t * Records a whole run at once, once it succeeded: the prompt, every step the model took and\n\t * every tool result. A failed run records nothing, so a retry cannot repeat its prompt, and\n\t * no tool call is ever kept without its result. The turn follows the current one and becomes\n\t * the current one.\n\t */\n\taddRun(messages: Message[]): void {\n\t\tthis.addRunAfter(this.current, messages, {});\n\t}\n\n\t/**\n\t * Records a run like `addRun`, after `turn` (`undefined` for none but the initial messages).\n\t * `run` is kept as it is, not copied, so it can still learn its run id.\n\t */\n\taddRunAfter(turn: number | undefined, messages: Message[], run: TurnRun): void {\n\t\tthis.turns.push({ messages: structuredClone(messages), parent: turn, run });\n\t\tthis.current = this.turns.length - 1;\n\t}\n\n\t/**\n\t * The initial messages, then every turn on the path to the current one. A deep copy, like\n\t * everything the conversation takes in: a client that rewrites the messages it was sent\n\t * cannot change what the next turn sends.\n\t */\n\tgetContext(): Message[] {\n\t\treturn this.contextAfter(this.current);\n\t}\n\n\t/** The context with the path to `turn` in place of the current one's. */\n\tcontextAfter(turn: number | undefined): Message[] {\n\t\treturn structuredClone([\n\t\t\t...this.initial,\n\t\t\t...this.path(turn).flatMap(index => this.turnAt(index).messages),\n\t\t]);\n\t}\n\n\t/** The turn the next one follows by default: the last one recorded. */\n\tget currentTurn(): number | undefined {\n\t\treturn this.current;\n\t}\n\n\t/** Every turn recorded, oldest first. */\n\tdescribeTurns(): TurnInfo[] {\n\t\treturn this.turns.map(({ parent, run }, index) => ({ index, parent, runId: run.runId }));\n\t}\n\n\t/** The indexes from the first turn down to `turn`. */\n\tpath(turn: number | undefined): number[] {\n\t\tconst indexes: number[] = [];\n\t\tfor (let index = turn; index !== undefined; index = this.turnAt(index).parent) {\n\t\t\tindexes.unshift(index);\n\t\t}\n\t\treturn indexes;\n\t}\n\n\t/** A copy of the messages one turn recorded. */\n\tmessagesOf(turn: number): Message[] {\n\t\treturn structuredClone(this.turnAt(turn).messages);\n\t}\n\n\tprivate turnAt(index: number): Turn {\n\t\tconst turn = this.turns[index];\n\t\tif (!turn) throw new RangeError(`The conversation has no turn ${String(index)}`);\n\t\treturn turn;\n\t}\n}\n"]}
|
package/dist/llm/domain/llm.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { Tokens } from '#src/shared/domain/tokens';
|
|
2
2
|
import type { Message } from './message.ts';
|
|
3
|
-
import type { ToolDefinition } from './tool.ts';
|
|
3
|
+
import type { NativeTool, ToolDefinition } from './tool.ts';
|
|
4
4
|
export type StopReason = 'completed' | 'truncated' | 'refused';
|
|
5
5
|
export interface LLMResponse {
|
|
6
6
|
message: Message & {
|
|
@@ -15,6 +15,8 @@ export interface LLMResponse {
|
|
|
15
15
|
stopReason: StopReason;
|
|
16
16
|
}
|
|
17
17
|
export interface LLMClient {
|
|
18
|
+
/** Whether this client can declare a native tool. Missing means it declares none. */
|
|
19
|
+
supportsNative?(tool: NativeTool): boolean;
|
|
18
20
|
send({ context, tools }: {
|
|
19
21
|
context: Message[];
|
|
20
22
|
tools: ToolDefinition[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/llm/domain/llm.ts"],"names":[],"mappings":"","sourcesContent":["import type { Tokens } from '#src/shared/domain/tokens';\nimport type { Message } from './message.ts';\nimport type { ToolDefinition } from './tool.ts';\n\nexport type StopReason = 'completed' | 'truncated' | 'refused';\n\nexport interface LLMResponse {\n\tmessage: Message & { role: 'assistant' };\n\t/**\n\t * Missing when the provider did not report it. The call was made and may have been billed,\n\t * so the agent keeps the answer and only its tokens become unknown; a failure raised from\n\t * such a response is marked `usageUnreported`.\n\t */\n\tusage: Tokens | undefined;\n\tstopReason: StopReason;\n}\n\nexport interface LLMClient {\n\tsend(\n\t\t{ context, tools }: { context: Message[]; tools: ToolDefinition[] },\n\t\tsignal: AbortSignal,\n\t): Promise<LLMResponse>;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"llm.js","sourceRoot":"","sources":["../../../src/llm/domain/llm.ts"],"names":[],"mappings":"","sourcesContent":["import type { Tokens } from '#src/shared/domain/tokens';\nimport type { Message } from './message.ts';\nimport type { NativeTool, ToolDefinition } from './tool.ts';\n\nexport type StopReason = 'completed' | 'truncated' | 'refused';\n\nexport interface LLMResponse {\n\tmessage: Message & { role: 'assistant' };\n\t/**\n\t * Missing when the provider did not report it. The call was made and may have been billed,\n\t * so the agent keeps the answer and only its tokens become unknown; a failure raised from\n\t * such a response is marked `usageUnreported`.\n\t */\n\tusage: Tokens | undefined;\n\tstopReason: StopReason;\n}\n\nexport interface LLMClient {\n\t/** Whether this client can declare a native tool. Missing means it declares none. */\n\tsupportsNative?(tool: NativeTool): boolean;\n\tsend(\n\t\t{ context, tools }: { context: Message[]; tools: ToolDefinition[] },\n\t\tsignal: AbortSignal,\n\t): Promise<LLMResponse>;\n}\n"]}
|
|
@@ -8,3 +8,16 @@ export interface ToolDefinition {
|
|
|
8
8
|
description: string;
|
|
9
9
|
inputSchema: JSONSchema;
|
|
10
10
|
}
|
|
11
|
+
/**
|
|
12
|
+
* A tool whose shape the provider defines, and its models were trained on: OpenAI's
|
|
13
|
+
* `apply_patch`, which sends V4A diffs, or Claude's text editor. The client declares it the
|
|
14
|
+
* provider's way, and the agent still runs it like any other tool.
|
|
15
|
+
*/
|
|
16
|
+
export type NativeTool = 'applyPatch' | 'textEditor';
|
|
17
|
+
/**
|
|
18
|
+
* The same definition, declared as a native tool. Internal: the mark travels under a symbol, so
|
|
19
|
+
* `ToolDefinition` stays as consumers know it and no consumer tool can claim to be native.
|
|
20
|
+
*/
|
|
21
|
+
export declare function asNative<Definition extends ToolDefinition>(definition: Definition, tool: NativeTool): Definition;
|
|
22
|
+
/** Which native tool a definition declares, if any. */
|
|
23
|
+
export declare function nativeOf(definition: ToolDefinition): NativeTool | undefined;
|
package/dist/llm/domain/tool.js
CHANGED
|
@@ -1,2 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
const nativeKey = Symbol('mikode-harness.nativeTool');
|
|
2
|
+
/**
|
|
3
|
+
* The same definition, declared as a native tool. Internal: the mark travels under a symbol, so
|
|
4
|
+
* `ToolDefinition` stays as consumers know it and no consumer tool can claim to be native.
|
|
5
|
+
*/
|
|
6
|
+
export function asNative(definition, tool) {
|
|
7
|
+
return Object.assign(definition, { [nativeKey]: tool });
|
|
8
|
+
}
|
|
9
|
+
/** Which native tool a definition declares, if any. */
|
|
10
|
+
export function nativeOf(definition) {
|
|
11
|
+
return definition[nativeKey];
|
|
12
|
+
}
|
|
2
13
|
//# sourceMappingURL=tool.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/llm/domain/tool.ts"],"names":[],"mappings":"","sourcesContent":["export interface JSONSchema {\n\ttype: 'object';\n\t[keyword: string]: unknown;\n}\n\n/** What a client describes to the model. Running the tool is not the model's concern. */\nexport interface ToolDefinition {\n\tname: string;\n\tdescription: string;\n\tinputSchema: JSONSchema;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"tool.js","sourceRoot":"","sources":["../../../src/llm/domain/tool.ts"],"names":[],"mappings":"AAmBA,MAAM,SAAS,GAAG,MAAM,CAAC,2BAA2B,CAAC,CAAC;AAEtD;;;GAGG;AACH,MAAM,UAAU,QAAQ,CACvB,UAAsB,EACtB,IAAgB;IAEhB,OAAO,MAAM,CAAC,MAAM,CAAC,UAAU,EAAE,EAAE,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC;AACzD,CAAC;AAED,uDAAuD;AACvD,MAAM,UAAU,QAAQ,CAAC,UAA0B;IAClD,OAAQ,UAA2C,CAAC,SAAS,CAAC,CAAC;AAChE,CAAC","sourcesContent":["export interface JSONSchema {\n\ttype: 'object';\n\t[keyword: string]: unknown;\n}\n\n/** What a client describes to the model. Running the tool is not the model's concern. */\nexport interface ToolDefinition {\n\tname: string;\n\tdescription: string;\n\tinputSchema: JSONSchema;\n}\n\n/**\n * A tool whose shape the provider defines, and its models were trained on: OpenAI's\n * `apply_patch`, which sends V4A diffs, or Claude's text editor. The client declares it the\n * provider's way, and the agent still runs it like any other tool.\n */\nexport type NativeTool = 'applyPatch' | 'textEditor';\n\nconst nativeKey = Symbol('mikode-harness.nativeTool');\n\n/**\n * The same definition, declared as a native tool. Internal: the mark travels under a symbol, so\n * `ToolDefinition` stays as consumers know it and no consumer tool can claim to be native.\n */\nexport function asNative<Definition extends ToolDefinition>(\n\tdefinition: Definition,\n\ttool: NativeTool,\n): Definition {\n\treturn Object.assign(definition, { [nativeKey]: tool });\n}\n\n/** Which native tool a definition declares, if any. */\nexport function nativeOf(definition: ToolDefinition): NativeTool | undefined {\n\treturn (definition as { [nativeKey]?: NativeTool })[nativeKey];\n}\n"]}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import type { ILogger } from '#src/shared/domain/logger';
|
|
2
2
|
import type { LLMClient, LLMResponse } from '../domain/llm.ts';
|
|
3
3
|
import type { Message } from '../domain/message.ts';
|
|
4
|
-
import type
|
|
5
|
-
export declare const claudeLLMModels: readonly ["opus", "fable", "sonnet"];
|
|
4
|
+
import { type NativeTool, type ToolDefinition } from '../domain/tool.ts';
|
|
5
|
+
export declare const claudeLLMModels: readonly ["opus", "fable", "sonnet", "haiku"];
|
|
6
6
|
export type ClaudeLLMModel = (typeof claudeLLMModels)[number];
|
|
7
7
|
export declare const claudeLLMReasoningEfforts: readonly ["low", "medium", "high", "xhigh", "max"];
|
|
8
8
|
export type ClaudeLLMReasoningEffort = (typeof claudeLLMReasoningEfforts)[number];
|
|
@@ -22,6 +22,7 @@ export declare class ClaudeLLMClient implements LLMClient {
|
|
|
22
22
|
systemPrompt: string;
|
|
23
23
|
logger: ILogger;
|
|
24
24
|
});
|
|
25
|
+
supportsNative(tool: NativeTool): boolean;
|
|
25
26
|
send({ context, tools }: {
|
|
26
27
|
context: Message[];
|
|
27
28
|
tools: ToolDefinition[];
|
|
@@ -3,14 +3,17 @@ import { InvalidAgentConfigError, UnrecoverableError, withSpentTokens, } from '#
|
|
|
3
3
|
import { classifyHostFailure, classifyLocalFailure, classifyProviderFailure, describeFailure, treatErrors, } from '#src/shared/domain/providerFailure';
|
|
4
4
|
import { isOneOf } from '#src/shared/domain/isOneOf';
|
|
5
5
|
import { MaxContextError } from "../domain/errors.js";
|
|
6
|
+
import { nativeOf } from "../domain/tool.js";
|
|
6
7
|
// The Messages API takes full model IDs. Callers name a model by the Agent SDK's alias, so both
|
|
7
8
|
// paths share one vocabulary; this table pins the ID each alias means here, and moves by hand
|
|
8
|
-
// when Anthropic releases a newer model. Haiku
|
|
9
|
-
|
|
9
|
+
// when Anthropic releases a newer model. Haiku runs without thinking: it has no adaptive thinking
|
|
10
|
+
// and takes no reasoning effort, and it is here for short, simple calls such as a summary.
|
|
11
|
+
export const claudeLLMModels = ['opus', 'fable', 'sonnet', 'haiku'];
|
|
10
12
|
const claudeLLMModelIds = {
|
|
11
13
|
opus: 'claude-opus-5-5',
|
|
12
14
|
fable: 'claude-fable-5-1',
|
|
13
15
|
sonnet: 'claude-sonnet-5',
|
|
16
|
+
haiku: 'claude-haiku-4-5',
|
|
14
17
|
};
|
|
15
18
|
export const claudeLLMReasoningEfforts = [
|
|
16
19
|
'low',
|
|
@@ -77,11 +80,25 @@ function toClaudeInput(message) {
|
|
|
77
80
|
}
|
|
78
81
|
return [{ role: message.role === 'tool' ? 'user' : message.role, content }];
|
|
79
82
|
}
|
|
83
|
+
// Anthropic fixes the text editor's name: its calls arrive under it.
|
|
84
|
+
const textEditorName = 'str_replace_based_edit_tool';
|
|
80
85
|
/**
|
|
81
86
|
* Strict: the API constrains the model to the schema, so its input always parses and matches.
|
|
82
|
-
* A schema outside what strict mode supports fails the request with a 400.
|
|
87
|
+
* A schema outside what strict mode supports fails the request with a 400. The native text
|
|
88
|
+
* editor has Anthropic's own schema, and its calls and results are ordinary tool blocks.
|
|
83
89
|
*/
|
|
84
|
-
function toClaudeTool(
|
|
90
|
+
function toClaudeTool(definition) {
|
|
91
|
+
const native = nativeOf(definition);
|
|
92
|
+
if (native === 'textEditor') {
|
|
93
|
+
if (definition.name !== textEditorName) {
|
|
94
|
+
throw new InvalidAgentConfigError(`Claude's text editor must be named "${textEditorName}", not "${definition.name}"`);
|
|
95
|
+
}
|
|
96
|
+
return { type: 'text_editor_20250728', name: textEditorName };
|
|
97
|
+
}
|
|
98
|
+
if (native !== undefined) {
|
|
99
|
+
throw new InvalidAgentConfigError(`Claude has no native tool "${native}"`);
|
|
100
|
+
}
|
|
101
|
+
const { name, description, inputSchema } = definition;
|
|
85
102
|
return { name, description, input_schema: inputSchema, strict: true };
|
|
86
103
|
}
|
|
87
104
|
function describeBlock(block, logger) {
|
|
@@ -212,17 +229,22 @@ function classifyClaudeFailure(error) {
|
|
|
212
229
|
export class ClaudeLLMClient {
|
|
213
230
|
client;
|
|
214
231
|
model;
|
|
232
|
+
// Missing for Haiku, which runs without thinking.
|
|
215
233
|
reasoningEffort;
|
|
216
234
|
systemPrompt;
|
|
217
235
|
logger;
|
|
218
236
|
// `model` and `reasoningEffort` are untyped on purpose: this adapter is the one that knows
|
|
219
237
|
// what Claude supports.
|
|
220
|
-
constructor({ model, reasoningEffort
|
|
238
|
+
constructor({ model, reasoningEffort, systemPrompt, logger, }) {
|
|
221
239
|
if (!isOneOf(claudeLLMModels, model)) {
|
|
222
240
|
throw new InvalidAgentConfigError(`"${model}" is not a Claude API model; expected one of: ${claudeLLMModels.join(', ')}`);
|
|
223
241
|
}
|
|
224
|
-
if (
|
|
225
|
-
throw new InvalidAgentConfigError(
|
|
242
|
+
if (model === 'haiku' && reasoningEffort !== undefined) {
|
|
243
|
+
throw new InvalidAgentConfigError('Claude Haiku takes no reasoning effort: it runs without thinking');
|
|
244
|
+
}
|
|
245
|
+
const effort = model === 'haiku' ? undefined : (reasoningEffort ?? 'high');
|
|
246
|
+
if (effort !== undefined && !isOneOf(claudeLLMReasoningEfforts, effort)) {
|
|
247
|
+
throw new InvalidAgentConfigError(`"${effort}" is not a Claude API reasoning effort; expected one of: ${claudeLLMReasoningEfforts.join(', ')}`);
|
|
226
248
|
}
|
|
227
249
|
try {
|
|
228
250
|
// The SDK's default retries stay on, as OpenAI's do. See "The provider SDKs keep their
|
|
@@ -237,10 +259,13 @@ export class ClaudeLLMClient {
|
|
|
237
259
|
});
|
|
238
260
|
}
|
|
239
261
|
this.model = claudeLLMModelIds[model];
|
|
240
|
-
this.reasoningEffort =
|
|
262
|
+
this.reasoningEffort = effort;
|
|
241
263
|
this.systemPrompt = systemPrompt;
|
|
242
264
|
this.logger = logger;
|
|
243
265
|
}
|
|
266
|
+
supportsNative(tool) {
|
|
267
|
+
return tool === 'textEditor';
|
|
268
|
+
}
|
|
244
269
|
async send({ context, tools }, signal) {
|
|
245
270
|
let response;
|
|
246
271
|
try {
|
|
@@ -251,8 +276,11 @@ export class ClaudeLLMClient {
|
|
|
251
276
|
messages: context.flatMap(toClaudeInput),
|
|
252
277
|
// Left out when empty, so a request without tools stays as it always was.
|
|
253
278
|
...(tools.length > 0 && { tools: tools.map(toClaudeTool) }),
|
|
254
|
-
|
|
255
|
-
|
|
279
|
+
// Haiku has no adaptive thinking, and an effort is refused with a 400.
|
|
280
|
+
...(this.reasoningEffort !== undefined && {
|
|
281
|
+
thinking: { type: 'adaptive', display: 'summarized' },
|
|
282
|
+
output_config: { effort: this.reasoningEffort },
|
|
283
|
+
}),
|
|
256
284
|
// Anthropic caches only on request. This marks the last block, so the next call
|
|
257
285
|
// reads everything before it from the cache instead of paying for it again.
|
|
258
286
|
cache_control: { type: 'ephemeral' },
|