@elie-laloum/outpost 4.1.0 → 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/CHANGELOG.md +38 -0
- package/README.md +13 -7
- package/SECURITY.md +2 -0
- package/dist/{cli/init-authentication.constants.js → adapters/agents/authentication.constants.js} +1 -1
- package/dist/adapters/agents/authentication.constants.js.map +1 -0
- package/dist/adapters/agents/authentication.d.ts +2 -0
- package/dist/adapters/agents/authentication.js +52 -0
- package/dist/adapters/agents/authentication.js.map +1 -0
- package/dist/adapters/agents/claude-adapter.d.ts +2 -2
- package/dist/adapters/agents/claude-adapter.js +30 -2
- package/dist/adapters/agents/claude-adapter.js.map +1 -1
- package/dist/adapters/agents/claude-request.d.ts +2 -2
- package/dist/adapters/agents/claude-request.js +3 -3
- package/dist/adapters/agents/claude-request.js.map +1 -1
- package/dist/adapters/agents/codex-adapter.d.ts +2 -2
- package/dist/adapters/agents/codex-adapter.js +17 -1
- package/dist/adapters/agents/codex-adapter.js.map +1 -1
- package/dist/adapters/agents/codex-provider.d.ts +2 -2
- package/dist/adapters/agents/codex-provider.js +1 -1
- package/dist/adapters/agents/codex-provider.js.map +1 -1
- package/dist/adapters/agents/codex-request.d.ts +2 -2
- package/dist/adapters/agents/codex-request.js +3 -3
- package/dist/adapters/agents/codex-request.js.map +1 -1
- package/dist/adapters/agents/gemini-adapter.d.ts +2 -2
- package/dist/adapters/agents/gemini-adapter.js +20 -1
- package/dist/adapters/agents/gemini-adapter.js.map +1 -1
- package/dist/adapters/agents/gemini-request.d.ts +2 -1
- package/dist/adapters/agents/gemini-request.js +1 -1
- package/dist/adapters/agents/gemini-request.js.map +1 -1
- package/dist/adapters/agents/gemini.types.d.ts +2 -1
- package/dist/adapters/agents/gemini.types.js.map +1 -1
- package/dist/adapters/agents/model-support.constants.d.ts +6 -0
- package/dist/adapters/agents/model-support.constants.js +18 -0
- package/dist/adapters/agents/model-support.constants.js.map +1 -0
- package/dist/adapters/agents/model-support.d.ts +4 -0
- package/dist/adapters/agents/model-support.js +11 -0
- package/dist/adapters/agents/model-support.js.map +1 -0
- package/dist/adapters/agents/settings.types.d.ts +11 -3
- package/dist/adapters/agents/settings.types.js.map +1 -1
- package/dist/adapters/models/anthropic-model-provider.constants.d.ts +3 -0
- package/dist/adapters/models/anthropic-model-provider.constants.js +17 -0
- package/dist/adapters/models/anthropic-model-provider.constants.js.map +1 -0
- package/dist/adapters/models/anthropic-model-provider.d.ts +3 -0
- package/dist/adapters/models/anthropic-model-provider.js +31 -0
- package/dist/adapters/models/anthropic-model-provider.js.map +1 -0
- package/dist/adapters/models/anthropic-model-provider.types.d.ts +7 -0
- package/dist/adapters/models/anthropic-model-provider.types.js +2 -0
- package/dist/adapters/models/anthropic-model-provider.types.js.map +1 -0
- package/dist/adapters/models/anthropic-request.d.ts +4 -0
- package/dist/adapters/models/anthropic-request.js +81 -0
- package/dist/adapters/models/anthropic-request.js.map +1 -0
- package/dist/adapters/models/anthropic-response.d.ts +3 -0
- package/dist/adapters/models/anthropic-response.js +55 -0
- package/dist/adapters/models/anthropic-response.js.map +1 -0
- package/dist/adapters/models/anthropic-stream.d.ts +2 -0
- package/dist/adapters/models/anthropic-stream.js +96 -0
- package/dist/adapters/models/anthropic-stream.js.map +1 -0
- package/dist/adapters/models/http-provider.d.ts +3 -0
- package/dist/adapters/models/http-provider.js +113 -0
- package/dist/adapters/models/http-provider.js.map +1 -0
- package/dist/adapters/models/model-http.d.ts +1 -0
- package/dist/adapters/models/model-http.js +30 -0
- package/dist/adapters/models/model-http.js.map +1 -0
- package/dist/adapters/models/model-protocol.types.d.ts +41 -0
- package/dist/adapters/models/model-protocol.types.js +2 -0
- package/dist/adapters/models/model-protocol.types.js.map +1 -0
- package/dist/adapters/models/model-request.d.ts +2 -0
- package/dist/adapters/models/model-request.js +18 -0
- package/dist/adapters/models/model-request.js.map +1 -0
- package/dist/adapters/models/model-response.d.ts +7 -0
- package/dist/adapters/models/model-response.js +41 -0
- package/dist/adapters/models/model-response.js.map +1 -0
- package/dist/adapters/models/model.constants.d.ts +4 -0
- package/dist/adapters/models/model.constants.js +15 -0
- package/dist/adapters/models/model.constants.js.map +1 -0
- package/dist/adapters/models/openai-chat-stream.d.ts +2 -0
- package/dist/adapters/models/openai-chat-stream.js +66 -0
- package/dist/adapters/models/openai-chat-stream.js.map +1 -0
- package/dist/adapters/models/openai-chat.d.ts +4 -0
- package/dist/adapters/models/openai-chat.js +108 -0
- package/dist/adapters/models/openai-chat.js.map +1 -0
- package/dist/adapters/models/openai-model-provider.d.ts +3 -0
- package/dist/adapters/models/openai-model-provider.js +13 -0
- package/dist/adapters/models/openai-model-provider.js.map +1 -0
- package/dist/adapters/models/openai-model-provider.types.d.ts +4 -0
- package/dist/adapters/models/openai-model-provider.types.js +2 -0
- package/dist/adapters/models/openai-model-provider.types.js.map +1 -0
- package/dist/adapters/models/openai-protocols.d.ts +2 -0
- package/dist/adapters/models/openai-protocols.js +22 -0
- package/dist/adapters/models/openai-protocols.js.map +1 -0
- package/dist/adapters/models/openai-responses-stream.d.ts +2 -0
- package/dist/adapters/models/openai-responses-stream.js +35 -0
- package/dist/adapters/models/openai-responses-stream.js.map +1 -0
- package/dist/adapters/models/openai-responses.d.ts +4 -0
- package/dist/adapters/models/openai-responses.js +107 -0
- package/dist/adapters/models/openai-responses.js.map +1 -0
- package/dist/adapters/models/openai-usage.d.ts +3 -0
- package/dist/adapters/models/openai-usage.js +20 -0
- package/dist/adapters/models/openai-usage.js.map +1 -0
- package/dist/adapters/models/stop-reasons.constants.d.ts +4 -0
- package/dist/adapters/models/stop-reasons.constants.js +19 -0
- package/dist/adapters/models/stop-reasons.constants.js.map +1 -0
- package/dist/adapters/models/stream-events.d.ts +3 -0
- package/dist/adapters/models/stream-events.js +22 -0
- package/dist/adapters/models/stream-events.js.map +1 -0
- package/dist/adapters/tools/edit-tools.d.ts +2 -0
- package/dist/adapters/tools/edit-tools.js +84 -0
- package/dist/adapters/tools/edit-tools.js.map +1 -0
- package/dist/adapters/tools/file-tools.d.ts +2 -0
- package/dist/adapters/tools/file-tools.js +97 -0
- package/dist/adapters/tools/file-tools.js.map +1 -0
- package/dist/adapters/tools/git-tools.d.ts +2 -0
- package/dist/adapters/tools/git-tools.js +54 -0
- package/dist/adapters/tools/git-tools.js.map +1 -0
- package/dist/adapters/tools/sandbox-files.d.ts +10 -0
- package/dist/adapters/tools/sandbox-files.js +60 -0
- package/dist/adapters/tools/sandbox-files.js.map +1 -0
- package/dist/adapters/tools/search-tools.d.ts +2 -0
- package/dist/adapters/tools/search-tools.js +65 -0
- package/dist/adapters/tools/search-tools.js.map +1 -0
- package/dist/adapters/tools/shell-tools.d.ts +3 -0
- package/dist/adapters/tools/shell-tools.js +38 -0
- package/dist/adapters/tools/shell-tools.js.map +1 -0
- package/dist/adapters/tools/tools.constants.d.ts +11 -0
- package/dist/adapters/tools/tools.constants.js +17 -0
- package/dist/adapters/tools/tools.constants.js.map +1 -0
- package/dist/adapters/tools/tools.types.d.ts +41 -0
- package/dist/adapters/tools/tools.types.js +2 -0
- package/dist/adapters/tools/tools.types.js.map +1 -0
- package/dist/application/activity-watchdog.js +15 -2
- package/dist/application/activity-watchdog.js.map +1 -1
- package/dist/application/agent-bootstrap.d.ts +2 -2
- package/dist/application/agent-bootstrap.js +2 -0
- package/dist/application/agent-bootstrap.js.map +1 -1
- package/dist/application/agent-storage.d.ts +3 -2
- package/dist/application/agent-storage.js +9 -2
- package/dist/application/agent-storage.js.map +1 -1
- package/dist/application/agent-turn.d.ts +3 -3
- package/dist/application/agent-turn.js +7 -1
- package/dist/application/agent-turn.js.map +1 -1
- package/dist/application/attach.js +1 -0
- package/dist/application/attach.js.map +1 -1
- package/dist/application/custom-turn.d.ts +5 -0
- package/dist/application/custom-turn.js +190 -0
- package/dist/application/custom-turn.js.map +1 -0
- package/dist/application/dispatch-observation.d.ts +3 -0
- package/dist/application/dispatch-observation.js +51 -0
- package/dist/application/dispatch-observation.js.map +1 -0
- package/dist/application/dispatch-observation.types.d.ts +5 -0
- package/dist/application/dispatch-observation.types.js +2 -0
- package/dist/application/dispatch-observation.types.js.map +1 -0
- package/dist/application/dispatch-validation.d.ts +2 -2
- package/dist/application/dispatch-validation.js.map +1 -1
- package/dist/application/dispatch.js +8 -3
- package/dist/application/dispatch.js.map +1 -1
- package/dist/application/doctor-image.js +3 -3
- package/dist/application/doctor-image.js.map +1 -1
- package/dist/application/doctor-protocol.js +9 -4
- package/dist/application/doctor-protocol.js.map +1 -1
- package/dist/application/doctor-sandbox.js +4 -4
- package/dist/application/doctor-sandbox.js.map +1 -1
- package/dist/application/doctor-sandbox.types.d.ts +2 -2
- package/dist/application/doctor-sandbox.types.js.map +1 -1
- package/dist/application/doctor.constants.d.ts +1 -1
- package/dist/application/doctor.constants.js +1 -1
- package/dist/application/doctor.constants.js.map +1 -1
- package/dist/application/doctor.js +10 -9
- package/dist/application/doctor.js.map +1 -1
- package/dist/application/doctor.types.d.ts +3 -3
- package/dist/application/doctor.types.js.map +1 -1
- package/dist/application/execution.d.ts +2 -2
- package/dist/application/execution.js +1 -1
- package/dist/application/execution.js.map +1 -1
- package/dist/application/execution.types.d.ts +11 -2
- package/dist/application/execution.types.js.map +1 -1
- package/dist/application/harness-context.d.ts +2 -0
- package/dist/application/harness-context.js +54 -0
- package/dist/application/harness-context.js.map +1 -0
- package/dist/application/harness-history.d.ts +3 -0
- package/dist/application/harness-history.js +17 -0
- package/dist/application/harness-history.js.map +1 -0
- package/dist/application/harness-hooks.d.ts +9 -0
- package/dist/application/harness-hooks.js +90 -0
- package/dist/application/harness-hooks.js.map +1 -0
- package/dist/application/harness-loop.d.ts +2 -0
- package/dist/application/harness-loop.js +132 -0
- package/dist/application/harness-loop.js.map +1 -0
- package/dist/application/harness.types.d.ts +55 -0
- package/dist/application/harness.types.js +2 -0
- package/dist/application/harness.types.js.map +1 -0
- package/dist/application/lifecycle.constants.d.ts +1 -1
- package/dist/application/lifecycle.constants.js +1 -1
- package/dist/application/lifecycle.constants.js.map +1 -1
- package/dist/application/outpost.types.d.ts +11 -6
- package/dist/application/outpost.types.js.map +1 -1
- package/dist/application/recovery-archive.d.ts +4 -0
- package/dist/application/recovery-archive.js +29 -0
- package/dist/application/recovery-archive.js.map +1 -0
- package/dist/application/recovery-archive.types.d.ts +10 -0
- package/dist/application/recovery-archive.types.js +2 -0
- package/dist/application/recovery-archive.types.js.map +1 -0
- package/dist/application/recovery-inspection.js +3 -0
- package/dist/application/recovery-inspection.js.map +1 -1
- package/dist/application/recovery-inspection.types.d.ts +2 -0
- package/dist/application/recovery-inspection.types.js.map +1 -1
- package/dist/application/recovery-retention.d.ts +2 -1
- package/dist/application/recovery-retention.js +9 -1
- package/dist/application/recovery-retention.js.map +1 -1
- package/dist/application/recovery-retention.types.d.ts +6 -0
- package/dist/application/recovery-retention.types.js.map +1 -1
- package/dist/application/remote-backup.js +8 -0
- package/dist/application/remote-backup.js.map +1 -1
- package/dist/application/remote-download.js +1 -1
- package/dist/application/remote-download.js.map +1 -1
- package/dist/application/remote-workspace.types.d.ts +2 -0
- package/dist/application/remote-workspace.types.js.map +1 -1
- package/dist/application/sandbox-agents.js +13 -4
- package/dist/application/sandbox-agents.js.map +1 -1
- package/dist/application/sandbox-attach.js +5 -2
- package/dist/application/sandbox-attach.js.map +1 -1
- package/dist/application/sandbox-dispatch.js +12 -3
- package/dist/application/sandbox-dispatch.js.map +1 -1
- package/dist/application/sandbox-provision.js +19 -10
- package/dist/application/sandbox-provision.js.map +1 -1
- package/dist/application/sandbox-session.types.d.ts +8 -8
- package/dist/application/sandbox-session.types.js.map +1 -1
- package/dist/application/sandbox.js +6 -3
- package/dist/application/sandbox.js.map +1 -1
- package/dist/application/speculation.js +1 -1
- package/dist/application/speculation.js.map +1 -1
- package/dist/application/speculation.types.d.ts +3 -3
- package/dist/application/speculation.types.js.map +1 -1
- package/dist/application/storage-reservation.js +3 -0
- package/dist/application/storage-reservation.js.map +1 -1
- package/dist/application/tasks.types.d.ts +2 -2
- package/dist/application/tasks.types.js.map +1 -1
- package/dist/application/tool-execution.d.ts +3 -0
- package/dist/application/tool-execution.js +211 -0
- package/dist/application/tool-execution.js.map +1 -0
- package/dist/application/transport-inspection.constants.d.ts +2 -0
- package/dist/application/transport-inspection.constants.js +10 -0
- package/dist/application/transport-inspection.constants.js.map +1 -0
- package/dist/application/transport-inspection.d.ts +2 -0
- package/dist/application/transport-inspection.js +103 -0
- package/dist/application/transport-inspection.js.map +1 -0
- package/dist/application/transport-retention.d.ts +4 -0
- package/dist/application/transport-retention.js +153 -0
- package/dist/application/transport-retention.js.map +1 -0
- package/dist/cli/commands.js +4 -2
- package/dist/cli/commands.js.map +1 -1
- package/dist/cli/doctor-command.js +6 -6
- package/dist/cli/doctor-command.js.map +1 -1
- package/dist/cli/init-authentication.js +6 -7
- package/dist/cli/init-authentication.js.map +1 -1
- package/dist/cli/init-command.js +3 -3
- package/dist/cli/init-command.js.map +1 -1
- package/dist/cli/main.constants.d.ts +4 -4
- package/dist/cli/main.constants.js +4 -4
- package/dist/cli/main.constants.js.map +1 -1
- package/dist/cli/recovery-command.js +1 -1
- package/dist/cli/recovery-command.js.map +1 -1
- package/dist/cli/scaffold-files.js +5 -4
- package/dist/cli/scaffold-files.js.map +1 -1
- package/dist/cli/scaffold-validation.js +13 -10
- package/dist/cli/scaffold-validation.js.map +1 -1
- package/dist/cli/scaffold.js +8 -4
- package/dist/cli/scaffold.js.map +1 -1
- package/dist/cli/scaffold.types.d.ts +1 -1
- package/dist/cli/scaffold.types.js.map +1 -1
- package/dist/cli/starters.js +8 -8
- package/dist/cli/starters.js.map +1 -1
- package/dist/domain/agent-model.d.ts +3 -0
- package/dist/domain/agent-model.js +22 -0
- package/dist/domain/agent-model.js.map +1 -0
- package/dist/domain/agent.d.ts +4 -0
- package/dist/domain/agent.js +32 -0
- package/dist/domain/agent.js.map +1 -0
- package/dist/domain/agent.types.d.ts +69 -2
- package/dist/domain/agent.types.js.map +1 -1
- package/dist/domain/context.constants.d.ts +7 -0
- package/dist/domain/context.constants.js +8 -0
- package/dist/domain/context.constants.js.map +1 -0
- package/dist/domain/context.d.ts +4 -0
- package/dist/domain/context.js +81 -0
- package/dist/domain/context.js.map +1 -0
- package/dist/domain/context.types.d.ts +26 -0
- package/dist/domain/context.types.js +2 -0
- package/dist/domain/context.types.js.map +1 -0
- package/dist/domain/conversation.types.d.ts +2 -0
- package/dist/domain/conversation.types.js.map +1 -1
- package/dist/domain/dispatch-telemetry.types.d.ts +12 -0
- package/dist/domain/dispatch-telemetry.types.js +2 -0
- package/dist/domain/dispatch-telemetry.types.js.map +1 -0
- package/dist/domain/errors.types.d.ts +1 -1
- package/dist/domain/errors.types.js.map +1 -1
- package/dist/domain/glob.d.ts +2 -0
- package/dist/domain/glob.js +25 -0
- package/dist/domain/glob.js.map +1 -0
- package/dist/domain/glob.types.d.ts +1 -0
- package/dist/domain/glob.types.js +2 -0
- package/dist/domain/glob.types.js.map +1 -0
- package/dist/domain/harness.constants.d.ts +11 -0
- package/dist/domain/harness.constants.js +24 -0
- package/dist/domain/harness.constants.js.map +1 -0
- package/dist/domain/harness.d.ts +2 -0
- package/dist/domain/harness.js +89 -0
- package/dist/domain/harness.js.map +1 -0
- package/dist/domain/harness.types.d.ts +60 -0
- package/dist/domain/harness.types.js +2 -0
- package/dist/domain/harness.types.js.map +1 -0
- package/dist/domain/hook.constants.d.ts +3 -0
- package/dist/domain/hook.constants.js +10 -0
- package/dist/domain/hook.constants.js.map +1 -0
- package/dist/domain/hook.d.ts +3 -0
- package/dist/domain/hook.js +25 -0
- package/dist/domain/hook.js.map +1 -0
- package/dist/domain/hook.types.d.ts +66 -0
- package/dist/domain/hook.types.js +2 -0
- package/dist/domain/hook.types.js.map +1 -0
- package/dist/domain/instructions.d.ts +3 -0
- package/dist/domain/instructions.js +25 -0
- package/dist/domain/instructions.js.map +1 -0
- package/dist/domain/model-messages.d.ts +5 -0
- package/dist/domain/model-messages.js +81 -0
- package/dist/domain/model-messages.js.map +1 -0
- package/dist/domain/model-messages.types.d.ts +6 -0
- package/dist/domain/model-messages.types.js +2 -0
- package/dist/domain/model-messages.types.js.map +1 -0
- package/dist/domain/model.constants.d.ts +4 -0
- package/dist/domain/model.constants.js +16 -0
- package/dist/domain/model.constants.js.map +1 -0
- package/dist/domain/model.types.d.ts +72 -0
- package/dist/domain/model.types.js +2 -0
- package/dist/domain/model.types.js.map +1 -0
- package/dist/domain/permissions.d.ts +3 -0
- package/dist/domain/permissions.js +92 -0
- package/dist/domain/permissions.js.map +1 -0
- package/dist/domain/permissions.types.d.ts +34 -0
- package/dist/domain/permissions.types.js +2 -0
- package/dist/domain/permissions.types.js.map +1 -0
- package/dist/domain/response.js +3 -2
- package/dist/domain/response.js.map +1 -1
- package/dist/domain/response.types.d.ts +12 -0
- package/dist/domain/response.types.js.map +1 -1
- package/dist/domain/skill.constants.d.ts +2 -0
- package/dist/domain/skill.constants.js +8 -0
- package/dist/domain/skill.constants.js.map +1 -0
- package/dist/domain/skill.d.ts +8 -0
- package/dist/domain/skill.js +79 -0
- package/dist/domain/skill.js.map +1 -0
- package/dist/domain/skill.types.d.ts +18 -0
- package/dist/domain/skill.types.js +2 -0
- package/dist/domain/skill.types.js.map +1 -0
- package/dist/domain/standard-schema.d.ts +6 -0
- package/dist/domain/standard-schema.js +45 -0
- package/dist/domain/standard-schema.js.map +1 -0
- package/dist/domain/tool-schema.d.ts +3 -0
- package/dist/domain/tool-schema.js +109 -0
- package/dist/domain/tool-schema.js.map +1 -0
- package/dist/domain/tool.constants.d.ts +4 -0
- package/dist/domain/tool.constants.js +36 -0
- package/dist/domain/tool.constants.js.map +1 -0
- package/dist/domain/tool.d.ts +4 -0
- package/dist/domain/tool.js +66 -0
- package/dist/domain/tool.js.map +1 -0
- package/dist/domain/tool.types.d.ts +62 -0
- package/dist/domain/tool.types.js +2 -0
- package/dist/domain/tool.types.js.map +1 -0
- package/dist/domain/transcript.d.ts +4 -0
- package/dist/domain/transcript.js +48 -0
- package/dist/domain/transcript.js.map +1 -0
- package/dist/domain/transcript.types.d.ts +15 -0
- package/dist/domain/transcript.types.js +2 -0
- package/dist/domain/transcript.types.js.map +1 -0
- package/dist/domain/transport.constants.d.ts +2 -0
- package/dist/domain/transport.constants.js +3 -0
- package/dist/domain/transport.constants.js.map +1 -0
- package/dist/domain/transport.d.ts +6 -0
- package/dist/domain/transport.js +21 -0
- package/dist/domain/transport.js.map +1 -0
- package/dist/domain/transport.types.d.ts +31 -0
- package/dist/domain/transport.types.js +2 -0
- package/dist/domain/transport.types.js.map +1 -0
- package/dist/domain/workflow/workflow-state.js +13 -6
- package/dist/domain/workflow/workflow-state.js.map +1 -1
- package/dist/domain/workflow.d.ts +1 -1
- package/dist/domain/workflow.js.map +1 -1
- package/dist/domain/workflow.types.d.ts +4 -0
- package/dist/domain/workflow.types.js.map +1 -1
- package/dist/index.d.ts +48 -5
- package/dist/index.js +26 -3
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/artifact-store.js +10 -0
- package/dist/infrastructure/artifact-store.js.map +1 -1
- package/dist/infrastructure/artifact-store.types.d.ts +3 -1
- package/dist/infrastructure/artifact-store.types.js.map +1 -1
- package/dist/infrastructure/conversations/capture.js +1 -1
- package/dist/infrastructure/conversations/capture.js.map +1 -1
- package/dist/infrastructure/conversations/harness-store.d.ts +3 -0
- package/dist/infrastructure/conversations/harness-store.js +27 -0
- package/dist/infrastructure/conversations/harness-store.js.map +1 -0
- package/dist/infrastructure/conversations/harness-transcript.d.ts +2 -0
- package/dist/infrastructure/conversations/harness-transcript.js +50 -0
- package/dist/infrastructure/conversations/harness-transcript.js.map +1 -0
- package/dist/infrastructure/conversations/harness-transcript.types.d.ts +18 -0
- package/dist/infrastructure/conversations/harness-transcript.types.js +2 -0
- package/dist/infrastructure/conversations/harness-transcript.types.js.map +1 -0
- package/dist/infrastructure/conversations.d.ts +6 -1
- package/dist/infrastructure/conversations.js +5 -0
- package/dist/infrastructure/conversations.js.map +1 -1
- package/dist/infrastructure/conversations.types.d.ts +1 -0
- package/dist/infrastructure/conversations.types.js.map +1 -1
- package/dist/infrastructure/custom-reporter.d.ts +2 -0
- package/dist/infrastructure/custom-reporter.js +33 -0
- package/dist/infrastructure/custom-reporter.js.map +1 -0
- package/dist/infrastructure/custom-reporter.types.d.ts +13 -0
- package/dist/infrastructure/custom-reporter.types.js +2 -0
- package/dist/infrastructure/custom-reporter.types.js.map +1 -0
- package/dist/infrastructure/git/git.constants.d.ts +1 -1
- package/dist/infrastructure/git/git.constants.js +1 -0
- package/dist/infrastructure/git/git.constants.js.map +1 -1
- package/dist/infrastructure/inspection-file.js +3 -3
- package/dist/infrastructure/inspection-file.js.map +1 -1
- package/dist/infrastructure/inspection-hash.js +4 -3
- package/dist/infrastructure/inspection-hash.js.map +1 -1
- package/dist/infrastructure/inspection-path.d.ts +1 -0
- package/dist/infrastructure/inspection-path.js +18 -0
- package/dist/infrastructure/inspection-path.js.map +1 -0
- package/dist/infrastructure/journal.constants.d.ts +1 -0
- package/dist/infrastructure/journal.constants.js +2 -0
- package/dist/infrastructure/journal.constants.js.map +1 -0
- package/dist/infrastructure/journal.js +10 -1
- package/dist/infrastructure/journal.js.map +1 -1
- package/dist/infrastructure/journal.types.d.ts +3 -0
- package/dist/infrastructure/journal.types.js.map +1 -1
- package/dist/infrastructure/local-transport.d.ts +3 -0
- package/dist/infrastructure/local-transport.js +146 -0
- package/dist/infrastructure/local-transport.js.map +1 -0
- package/dist/infrastructure/local-transport.types.d.ts +3 -0
- package/dist/infrastructure/local-transport.types.js +2 -0
- package/dist/infrastructure/local-transport.types.js.map +1 -0
- package/dist/infrastructure/opentelemetry-dispatch.d.ts +6 -0
- package/dist/infrastructure/opentelemetry-dispatch.js +70 -0
- package/dist/infrastructure/opentelemetry-dispatch.js.map +1 -0
- package/dist/infrastructure/opentelemetry.constants.d.ts +3 -0
- package/dist/infrastructure/opentelemetry.constants.js +3 -0
- package/dist/infrastructure/opentelemetry.constants.js.map +1 -1
- package/dist/infrastructure/opentelemetry.js +4 -0
- package/dist/infrastructure/opentelemetry.js.map +1 -1
- package/dist/infrastructure/opentelemetry.types.d.ts +3 -3
- package/dist/infrastructure/opentelemetry.types.js.map +1 -1
- package/dist/infrastructure/reporter.js +27 -2
- package/dist/infrastructure/reporter.js.map +1 -1
- package/dist/infrastructure/resource-activity-inspection.d.ts +2 -1
- package/dist/infrastructure/resource-activity-inspection.js +5 -4
- package/dist/infrastructure/resource-activity-inspection.js.map +1 -1
- package/dist/infrastructure/resource-activity.js +44 -16
- package/dist/infrastructure/resource-activity.js.map +1 -1
- package/dist/infrastructure/resource-activity.types.d.ts +4 -2
- package/dist/infrastructure/resource-activity.types.js.map +1 -1
- package/dist/infrastructure/s3-transport.d.ts +4 -0
- package/dist/infrastructure/s3-transport.js +144 -0
- package/dist/infrastructure/s3-transport.js.map +1 -0
- package/dist/infrastructure/s3-transport.types.d.ts +6 -0
- package/dist/infrastructure/s3-transport.types.js +2 -0
- package/dist/infrastructure/s3-transport.types.js.map +1 -0
- package/dist/infrastructure/settings.d.ts +1 -1
- package/dist/infrastructure/settings.js +3 -3
- package/dist/infrastructure/settings.js.map +1 -1
- package/dist/infrastructure/sse.d.ts +2 -0
- package/dist/infrastructure/sse.js +64 -0
- package/dist/infrastructure/sse.js.map +1 -0
- package/dist/infrastructure/sse.types.d.ts +4 -0
- package/dist/infrastructure/sse.types.js +2 -0
- package/dist/infrastructure/sse.types.js.map +1 -0
- package/dist/infrastructure/storage-inventory.types.d.ts +2 -1
- package/dist/infrastructure/storage-inventory.types.js.map +1 -1
- package/dist/infrastructure/storage-reservations.types.d.ts +2 -0
- package/dist/infrastructure/storage-reservations.types.js.map +1 -1
- package/dist/infrastructure/task-queue-bullmq-resources.d.ts +13 -0
- package/dist/infrastructure/task-queue-bullmq-resources.js +118 -0
- package/dist/infrastructure/task-queue-bullmq-resources.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq-state.d.ts +5 -0
- package/dist/infrastructure/task-queue-bullmq-state.js +26 -0
- package/dist/infrastructure/task-queue-bullmq-state.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq.constants.d.ts +7 -0
- package/dist/infrastructure/task-queue-bullmq.constants.js +79 -0
- package/dist/infrastructure/task-queue-bullmq.constants.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq.d.ts +3 -0
- package/dist/infrastructure/task-queue-bullmq.js +124 -0
- package/dist/infrastructure/task-queue-bullmq.js.map +1 -0
- package/dist/infrastructure/task-queue-bullmq.types.d.ts +17 -0
- package/dist/infrastructure/task-queue-bullmq.types.js +2 -0
- package/dist/infrastructure/task-queue-bullmq.types.js.map +1 -0
- package/dist/infrastructure/transport-archive.constants.d.ts +6 -0
- package/dist/infrastructure/transport-archive.constants.js +7 -0
- package/dist/infrastructure/transport-archive.constants.js.map +1 -0
- package/dist/infrastructure/transport-archive.d.ts +5 -0
- package/dist/infrastructure/transport-archive.js +157 -0
- package/dist/infrastructure/transport-archive.js.map +1 -0
- package/dist/infrastructure/transport-archive.types.d.ts +17 -0
- package/dist/infrastructure/transport-archive.types.js +2 -0
- package/dist/infrastructure/transport-archive.types.js.map +1 -0
- package/dist/infrastructure/transport-artifact-store.d.ts +3 -0
- package/dist/infrastructure/transport-artifact-store.js +31 -0
- package/dist/infrastructure/transport-artifact-store.js.map +1 -0
- package/dist/infrastructure/transport-artifact-store.types.d.ts +4 -0
- package/dist/infrastructure/transport-artifact-store.types.js +2 -0
- package/dist/infrastructure/transport-artifact-store.types.js.map +1 -0
- package/dist/infrastructure/transport-checkpoint.d.ts +5 -0
- package/dist/infrastructure/transport-checkpoint.js +105 -0
- package/dist/infrastructure/transport-checkpoint.js.map +1 -0
- package/dist/infrastructure/transport-checkpoint.types.d.ts +9 -0
- package/dist/infrastructure/transport-checkpoint.types.js +2 -0
- package/dist/infrastructure/transport-checkpoint.types.js.map +1 -0
- package/dist/infrastructure/transport-conversations.d.ts +4 -0
- package/dist/infrastructure/transport-conversations.js +76 -0
- package/dist/infrastructure/transport-conversations.js.map +1 -0
- package/dist/infrastructure/transport-conversations.types.d.ts +4 -0
- package/dist/infrastructure/transport-conversations.types.js +2 -0
- package/dist/infrastructure/transport-conversations.types.js.map +1 -0
- package/dist/infrastructure/transport-envelope.d.ts +7 -0
- package/dist/infrastructure/transport-envelope.js +47 -0
- package/dist/infrastructure/transport-envelope.js.map +1 -0
- package/dist/infrastructure/transport-journal.d.ts +6 -0
- package/dist/infrastructure/transport-journal.js +94 -0
- package/dist/infrastructure/transport-journal.js.map +1 -0
- package/dist/infrastructure/transport-journal.types.d.ts +10 -0
- package/dist/infrastructure/transport-journal.types.js +2 -0
- package/dist/infrastructure/transport-journal.types.js.map +1 -0
- package/dist/infrastructure/transport-json.d.ts +6 -0
- package/dist/infrastructure/transport-json.js +46 -0
- package/dist/infrastructure/transport-json.js.map +1 -0
- package/dist/infrastructure/transport-reservations.d.ts +5 -0
- package/dist/infrastructure/transport-reservations.js +89 -0
- package/dist/infrastructure/transport-reservations.js.map +1 -0
- package/dist/infrastructure/transport-reservations.types.d.ts +4 -0
- package/dist/infrastructure/transport-reservations.types.js +2 -0
- package/dist/infrastructure/transport-reservations.types.js.map +1 -0
- package/dist/infrastructure/transport.constants.d.ts +8 -0
- package/dist/infrastructure/transport.constants.js +9 -0
- package/dist/infrastructure/transport.constants.js.map +1 -0
- package/dist/infrastructure/workflow-checkpoint.js +7 -0
- package/dist/infrastructure/workflow-checkpoint.js.map +1 -1
- package/dist/infrastructure/workflow-checkpoint.types.d.ts +3 -1
- package/dist/infrastructure/workflow-checkpoint.types.js.map +1 -1
- package/dist/providers/agents.d.ts +3 -3
- package/dist/providers/agents.js +3 -3
- package/dist/providers/agents.js.map +1 -1
- package/dist/providers/daytona.d.ts +1 -1
- package/dist/providers/daytona.js +1 -1
- package/dist/providers/daytona.js.map +1 -1
- package/dist/providers/docker.d.ts +1 -1
- package/dist/providers/docker.js +1 -1
- package/dist/providers/docker.js.map +1 -1
- package/dist/providers/factories.d.ts +2 -2
- package/dist/providers/factories.js +3 -3
- package/dist/providers/factories.js.map +1 -1
- package/dist/providers/firecracker.d.ts +1 -1
- package/dist/providers/firecracker.js +1 -1
- package/dist/providers/firecracker.js.map +1 -1
- package/dist/providers/local.d.ts +1 -1
- package/dist/providers/local.js +1 -1
- package/dist/providers/local.js.map +1 -1
- package/dist/providers/podman.d.ts +1 -1
- package/dist/providers/podman.js +1 -1
- package/dist/providers/podman.js.map +1 -1
- package/dist/providers/vercel.d.ts +1 -1
- package/dist/providers/vercel.js +1 -1
- package/dist/providers/vercel.js.map +1 -1
- package/package.json +26 -5
- package/dist/cli/init-authentication.constants.js.map +0 -1
- /package/dist/{cli/init-authentication.constants.d.ts → adapters/agents/authentication.constants.d.ts} +0 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { replayable, requestMessages } from "../../domain/model-messages.js";
|
|
2
|
+
import { modelResult, object, requireResponse, stopReason, toolInput, } from "./model-response.js";
|
|
3
|
+
import { openaiUsage, toolArguments } from "./openai-usage.js";
|
|
4
|
+
import { RESPONSES_INCOMPLETE_REASONS } from "./stop-reasons.constants.js";
|
|
5
|
+
export function responsesBody(request, context) {
|
|
6
|
+
const items = requestMessages(request).flatMap((message) => responseItems(message, context));
|
|
7
|
+
return {
|
|
8
|
+
model: context.model,
|
|
9
|
+
input: request.messages === undefined ? request.prompt : items,
|
|
10
|
+
...(request.system === undefined ? {} : { instructions: request.system }),
|
|
11
|
+
...(request.tools?.length
|
|
12
|
+
? {
|
|
13
|
+
tools: request.tools.map((tool) => ({
|
|
14
|
+
type: "function",
|
|
15
|
+
name: tool.name,
|
|
16
|
+
description: tool.description,
|
|
17
|
+
parameters: tool.inputSchema,
|
|
18
|
+
})),
|
|
19
|
+
}
|
|
20
|
+
: {}),
|
|
21
|
+
stream: false,
|
|
22
|
+
store: false,
|
|
23
|
+
...(request.maxOutputTokens === undefined
|
|
24
|
+
? {}
|
|
25
|
+
: { max_output_tokens: request.maxOutputTokens }),
|
|
26
|
+
...(request.reasoning === undefined
|
|
27
|
+
? {}
|
|
28
|
+
: { reasoning: { effort: request.reasoning } }),
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export function readModelResponse(value, context = { identity: "openai", model: "" }) {
|
|
32
|
+
const data = object(value);
|
|
33
|
+
requireResponse(data.error == null && Array.isArray(data.output));
|
|
34
|
+
const incomplete = data.status === "incomplete";
|
|
35
|
+
requireResponse(incomplete || data.status === "completed");
|
|
36
|
+
let refused = false;
|
|
37
|
+
const content = data.output.flatMap((value) => {
|
|
38
|
+
const item = object(value);
|
|
39
|
+
if (item.type === "reasoning")
|
|
40
|
+
return [
|
|
41
|
+
{
|
|
42
|
+
type: "reasoning",
|
|
43
|
+
provider: context.identity,
|
|
44
|
+
model: context.model,
|
|
45
|
+
data: item,
|
|
46
|
+
},
|
|
47
|
+
];
|
|
48
|
+
if (item.type === "function_call")
|
|
49
|
+
return [functionCall(item)];
|
|
50
|
+
requireResponse(item.type === "message" && item.role === "assistant");
|
|
51
|
+
requireResponse(item.status === "completed" || incomplete);
|
|
52
|
+
requireResponse(Array.isArray(item.content));
|
|
53
|
+
return item.content.flatMap((value) => {
|
|
54
|
+
const part = object(value);
|
|
55
|
+
if (part.type === "refusal") {
|
|
56
|
+
requireResponse(typeof part.refusal === "string");
|
|
57
|
+
refused = true;
|
|
58
|
+
return [];
|
|
59
|
+
}
|
|
60
|
+
requireResponse(part.type === "output_text" && typeof part.text === "string");
|
|
61
|
+
return [{ type: "text", text: part.text }];
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
const reason = refused ? "refusal" : completion(data, incomplete);
|
|
65
|
+
return modelResult(content, reason, openaiUsage(data.usage, "input_tokens", "output_tokens", "input_tokens_details"));
|
|
66
|
+
}
|
|
67
|
+
function completion(data, incomplete) {
|
|
68
|
+
if (!incomplete)
|
|
69
|
+
return "end";
|
|
70
|
+
return stopReason(RESPONSES_INCOMPLETE_REASONS, object(data.incomplete_details).reason);
|
|
71
|
+
}
|
|
72
|
+
function functionCall(item) {
|
|
73
|
+
requireResponse(typeof item.call_id === "string" &&
|
|
74
|
+
typeof item.name === "string" &&
|
|
75
|
+
typeof item.arguments === "string");
|
|
76
|
+
return {
|
|
77
|
+
type: "tool-call",
|
|
78
|
+
id: item.call_id,
|
|
79
|
+
name: item.name,
|
|
80
|
+
input: toolInput(item.arguments),
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function responseItems(message, context) {
|
|
84
|
+
return message.content
|
|
85
|
+
.filter((block) => replayable(block, context.identity, context.model))
|
|
86
|
+
.toSorted((left, right) => order(message, left) - order(message, right))
|
|
87
|
+
.map((block) => itemEncoders[block.type](block, message.role));
|
|
88
|
+
}
|
|
89
|
+
function order(message, block) {
|
|
90
|
+
return message.role === "user" && block.type !== "tool-result" ? 1 : 0;
|
|
91
|
+
}
|
|
92
|
+
const itemEncoders = {
|
|
93
|
+
text: (block, role) => ({ role, content: block.text }),
|
|
94
|
+
"tool-call": (block) => ({
|
|
95
|
+
type: "function_call",
|
|
96
|
+
call_id: block.id,
|
|
97
|
+
name: block.name,
|
|
98
|
+
arguments: toolArguments(block.input),
|
|
99
|
+
}),
|
|
100
|
+
"tool-result": (block) => ({
|
|
101
|
+
type: "function_call_output",
|
|
102
|
+
call_id: block.callId,
|
|
103
|
+
output: block.content,
|
|
104
|
+
}),
|
|
105
|
+
reasoning: (block) => block.data,
|
|
106
|
+
};
|
|
107
|
+
//# sourceMappingURL=openai-responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-responses.js","sourceRoot":"","sources":["../../../src/adapters/models/openai-responses.ts"],"names":[],"mappings":"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","sourcesContent":["import { replayable, requestMessages } from \"../../domain/model-messages.ts\";\nimport type {\n ModelContentBlock,\n ModelMessage,\n ModelRequest,\n ModelResult,\n ModelStopReason,\n} from \"../../domain/model.types.ts\";\nimport type { BlockEncoders, ProtocolContext } from \"./model-protocol.types.ts\";\nimport {\n modelResult,\n object,\n requireResponse,\n stopReason,\n toolInput,\n} from \"./model-response.ts\";\nimport { openaiUsage, toolArguments } from \"./openai-usage.ts\";\nimport { RESPONSES_INCOMPLETE_REASONS } from \"./stop-reasons.constants.ts\";\n\nexport function responsesBody(\n request: ModelRequest,\n context: ProtocolContext,\n): Record<string, unknown> {\n const items = requestMessages(request).flatMap((message) =>\n responseItems(message, context),\n );\n return {\n model: context.model,\n input: request.messages === undefined ? request.prompt : items,\n ...(request.system === undefined ? {} : { instructions: request.system }),\n ...(request.tools?.length\n ? {\n tools: request.tools.map((tool) => ({\n type: \"function\",\n name: tool.name,\n description: tool.description,\n parameters: tool.inputSchema,\n })),\n }\n : {}),\n stream: false,\n store: false,\n ...(request.maxOutputTokens === undefined\n ? {}\n : { max_output_tokens: request.maxOutputTokens }),\n ...(request.reasoning === undefined\n ? {}\n : { reasoning: { effort: request.reasoning } }),\n };\n}\n\nexport function readModelResponse(\n value: unknown,\n context: ProtocolContext = { identity: \"openai\", model: \"\" },\n): ModelResult {\n const data = object(value);\n requireResponse(data.error == null && Array.isArray(data.output));\n const incomplete = data.status === \"incomplete\";\n requireResponse(incomplete || data.status === \"completed\");\n let refused = false;\n const content = data.output.flatMap((value): ModelContentBlock[] => {\n const item = object(value);\n if (item.type === \"reasoning\")\n return [\n {\n type: \"reasoning\",\n provider: context.identity,\n model: context.model,\n data: item,\n },\n ];\n if (item.type === \"function_call\") return [functionCall(item)];\n requireResponse(item.type === \"message\" && item.role === \"assistant\");\n requireResponse(item.status === \"completed\" || incomplete);\n requireResponse(Array.isArray(item.content));\n return item.content.flatMap((value): ModelContentBlock[] => {\n const part = object(value);\n if (part.type === \"refusal\") {\n requireResponse(typeof part.refusal === \"string\");\n refused = true;\n return [];\n }\n requireResponse(\n part.type === \"output_text\" && typeof part.text === \"string\",\n );\n return [{ type: \"text\", text: part.text }];\n });\n });\n const reason = refused ? \"refusal\" : completion(data, incomplete);\n return modelResult(\n content,\n reason,\n openaiUsage(\n data.usage,\n \"input_tokens\",\n \"output_tokens\",\n \"input_tokens_details\",\n ),\n );\n}\n\nfunction completion(\n data: Record<string, unknown>,\n incomplete: boolean,\n): ModelStopReason {\n if (!incomplete) return \"end\";\n return stopReason(\n RESPONSES_INCOMPLETE_REASONS,\n object(data.incomplete_details).reason,\n );\n}\n\nfunction functionCall(item: Record<string, unknown>): ModelContentBlock {\n requireResponse(\n typeof item.call_id === \"string\" &&\n typeof item.name === \"string\" &&\n typeof item.arguments === \"string\",\n );\n return {\n type: \"tool-call\",\n id: item.call_id,\n name: item.name,\n input: toolInput(item.arguments),\n };\n}\n\nfunction responseItems(message: ModelMessage, context: ProtocolContext) {\n return message.content\n .filter((block) => replayable(block, context.identity, context.model))\n .toSorted((left, right) => order(message, left) - order(message, right))\n .map((block) => itemEncoders[block.type](block as never, message.role));\n}\n\nfunction order(message: ModelMessage, block: ModelContentBlock): number {\n return message.role === \"user\" && block.type !== \"tool-result\" ? 1 : 0;\n}\n\nconst itemEncoders: BlockEncoders<[role: ModelMessage[\"role\"]]> = {\n text: (block, role) => ({ role, content: block.text }),\n \"tool-call\": (block) => ({\n type: \"function_call\",\n call_id: block.id,\n name: block.name,\n arguments: toolArguments(block.input),\n }),\n \"tool-result\": (block) => ({\n type: \"function_call_output\",\n call_id: block.callId,\n output: block.content,\n }),\n reasoning: (block) => block.data,\n};\n"]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { object, requireResponse, tokens } from "./model-response.js";
|
|
2
|
+
export function openaiUsage(value, input, output, details) {
|
|
3
|
+
if (value === undefined || value === null)
|
|
4
|
+
return undefined;
|
|
5
|
+
const data = object(value);
|
|
6
|
+
const cached = data[details] == null
|
|
7
|
+
? 0
|
|
8
|
+
: tokens(object(data[details]).cached_tokens ?? 0);
|
|
9
|
+
const result = {
|
|
10
|
+
input: tokens(data[input]),
|
|
11
|
+
output: tokens(data[output]),
|
|
12
|
+
cached,
|
|
13
|
+
};
|
|
14
|
+
requireResponse(cached <= result.input);
|
|
15
|
+
return result;
|
|
16
|
+
}
|
|
17
|
+
export function toolArguments(input) {
|
|
18
|
+
return typeof input === "string" ? input : JSON.stringify(input);
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=openai-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"openai-usage.js","sourceRoot":"","sources":["../../../src/adapters/models/openai-usage.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAEtE,MAAM,UAAU,WAAW,CACzB,KAAc,EACd,KAAa,EACb,MAAc,EACd,OAAe;IAEf,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IAC5D,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC3B,MAAM,MAAM,GACV,IAAI,CAAC,OAAO,CAAC,IAAI,IAAI;QACnB,CAAC,CAAC,CAAC;QACH,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,aAAa,IAAI,CAAC,CAAC,CAAC;IACvD,MAAM,MAAM,GAAG;QACb,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC1B,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC5B,MAAM;KACP,CAAC;IACF,eAAe,CAAC,MAAM,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC;IACxC,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC","sourcesContent":["import type { Usage } from \"../../domain/agent.types.ts\";\nimport { object, requireResponse, tokens } from \"./model-response.ts\";\n\nexport function openaiUsage(\n value: unknown,\n input: string,\n output: string,\n details: string,\n): Usage | undefined {\n if (value === undefined || value === null) return undefined;\n const data = object(value);\n const cached =\n data[details] == null\n ? 0\n : tokens(object(data[details]).cached_tokens ?? 0);\n const result = {\n input: tokens(data[input]),\n output: tokens(data[output]),\n cached,\n };\n requireResponse(cached <= result.input);\n return result;\n}\n\nexport function toolArguments(input: unknown): string {\n return typeof input === \"string\" ? input : JSON.stringify(input);\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ModelStopReason } from "../../domain/model.types.ts";
|
|
2
|
+
export declare const ANTHROPIC_STOP_REASONS: Readonly<Record<string, ModelStopReason>>;
|
|
3
|
+
export declare const CHAT_FINISH_REASONS: Readonly<Record<string, ModelStopReason>>;
|
|
4
|
+
export declare const RESPONSES_INCOMPLETE_REASONS: Readonly<Record<string, ModelStopReason>>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export const ANTHROPIC_STOP_REASONS = {
|
|
2
|
+
end_turn: "end",
|
|
3
|
+
stop_sequence: "end",
|
|
4
|
+
tool_use: "tool-calls",
|
|
5
|
+
max_tokens: "max-tokens",
|
|
6
|
+
model_context_window_exceeded: "max-tokens",
|
|
7
|
+
refusal: "refusal",
|
|
8
|
+
};
|
|
9
|
+
export const CHAT_FINISH_REASONS = {
|
|
10
|
+
stop: "end",
|
|
11
|
+
tool_calls: "tool-calls",
|
|
12
|
+
length: "max-tokens",
|
|
13
|
+
content_filter: "refusal",
|
|
14
|
+
};
|
|
15
|
+
export const RESPONSES_INCOMPLETE_REASONS = {
|
|
16
|
+
max_output_tokens: "max-tokens",
|
|
17
|
+
content_filter: "refusal",
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=stop-reasons.constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stop-reasons.constants.js","sourceRoot":"","sources":["../../../src/adapters/models/stop-reasons.constants.ts"],"names":[],"mappings":"AAEA,MAAM,CAAC,MAAM,sBAAsB,GACjC;IACE,QAAQ,EAAE,KAAK;IACf,aAAa,EAAE,KAAK;IACpB,QAAQ,EAAE,YAAY;IACtB,UAAU,EAAE,YAAY;IACxB,6BAA6B,EAAE,YAAY;IAC3C,OAAO,EAAE,SAAS;CACnB,CAAC;AAEJ,MAAM,CAAC,MAAM,mBAAmB,GAA8C;IAC5E,IAAI,EAAE,KAAK;IACX,UAAU,EAAE,YAAY;IACxB,MAAM,EAAE,YAAY;IACpB,cAAc,EAAE,SAAS;CAC1B,CAAC;AAEF,MAAM,CAAC,MAAM,4BAA4B,GAErC;IACF,iBAAiB,EAAE,YAAY;IAC/B,cAAc,EAAE,SAAS;CAC1B,CAAC","sourcesContent":["import type { ModelStopReason } from \"../../domain/model.types.ts\";\n\nexport const ANTHROPIC_STOP_REASONS: Readonly<Record<string, ModelStopReason>> =\n {\n end_turn: \"end\",\n stop_sequence: \"end\",\n tool_use: \"tool-calls\",\n max_tokens: \"max-tokens\",\n model_context_window_exceeded: \"max-tokens\",\n refusal: \"refusal\",\n };\n\nexport const CHAT_FINISH_REASONS: Readonly<Record<string, ModelStopReason>> = {\n stop: \"end\",\n tool_calls: \"tool-calls\",\n length: \"max-tokens\",\n content_filter: \"refusal\",\n};\n\nexport const RESPONSES_INCOMPLETE_REASONS: Readonly<\n Record<string, ModelStopReason>\n> = {\n max_output_tokens: \"max-tokens\",\n content_filter: \"refusal\",\n};\n"]}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { OutpostError } from "../../domain/errors.js";
|
|
2
|
+
import { object } from "./model-response.js";
|
|
3
|
+
export function eventData(event) {
|
|
4
|
+
let value;
|
|
5
|
+
try {
|
|
6
|
+
value = JSON.parse(event.data);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
throw new OutpostError("response", "Model stream event is not valid JSON");
|
|
10
|
+
}
|
|
11
|
+
return object(value);
|
|
12
|
+
}
|
|
13
|
+
export function streamFailure(data) {
|
|
14
|
+
const error = data.error;
|
|
15
|
+
const type = error && typeof error === "object" && "type" in error
|
|
16
|
+
? String(error.type)
|
|
17
|
+
: undefined;
|
|
18
|
+
throw new OutpostError("provider", "Model stream reported an error", {
|
|
19
|
+
...(type ? { type } : {}),
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=stream-events.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream-events.js","sourceRoot":"","sources":["../../../src/adapters/models/stream-events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAE7C,MAAM,UAAU,SAAS,CAAC,KAAsB;IAC9C,IAAI,KAAc,CAAC;IACnB,IAAI,CAAC;QACH,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IACjC,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,sCAAsC,CAAC,CAAC;IAC7E,CAAC;IACD,OAAO,MAAM,CAAC,KAAK,CAAC,CAAC;AACvB,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,IAA6B;IACzD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC;IACzB,MAAM,IAAI,GACR,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK;QACnD,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC;QACpB,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,IAAI,YAAY,CAAC,UAAU,EAAE,gCAAgC,EAAE;QACnE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1B,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { OutpostError } from \"../../domain/errors.ts\";\nimport type { ServerSentEvent } from \"../../infrastructure/sse.types.ts\";\nimport { object } from \"./model-response.ts\";\n\nexport function eventData(event: ServerSentEvent): Record<string, unknown> {\n let value: unknown;\n try {\n value = JSON.parse(event.data);\n } catch {\n throw new OutpostError(\"response\", \"Model stream event is not valid JSON\");\n }\n return object(value);\n}\n\nexport function streamFailure(data: Record<string, unknown>): never {\n const error = data.error;\n const type =\n error && typeof error === \"object\" && \"type\" in error\n ? String(error.type)\n : undefined;\n throw new OutpostError(\"provider\", \"Model stream reported an error\", {\n ...(type ? { type } : {}),\n });\n}\n"]}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { writeFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
|
|
4
|
+
import { digest, downloadFile, repositoryPath, sandboxPath, withStaging, } from "./sandbox-files.js";
|
|
5
|
+
export function harnessEditTools() {
|
|
6
|
+
return defineHarnessToolset({
|
|
7
|
+
name: "edit",
|
|
8
|
+
tools: [writeFileTool(), editFileTool()],
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function writeFileTool() {
|
|
12
|
+
return defineHarnessTool({
|
|
13
|
+
name: "write_file",
|
|
14
|
+
description: "Create or replace a UTF-8 file relative to the repository root with the given content. Prefer edit_file to change part of an existing file.",
|
|
15
|
+
input: {
|
|
16
|
+
type: "object",
|
|
17
|
+
properties: {
|
|
18
|
+
path: { type: "string", minLength: 1 },
|
|
19
|
+
content: { type: "string" },
|
|
20
|
+
},
|
|
21
|
+
required: ["path", "content"],
|
|
22
|
+
additionalProperties: false,
|
|
23
|
+
},
|
|
24
|
+
resources: (input) => ({ paths: [input.path] }),
|
|
25
|
+
execute: (input, context) => withStaging(async (directory) => {
|
|
26
|
+
repositoryPath(input.path);
|
|
27
|
+
const staged = join(directory, "file");
|
|
28
|
+
await writeFile(staged, input.content);
|
|
29
|
+
await upload(context, staged, input.path);
|
|
30
|
+
return `Wrote ${Buffer.byteLength(input.content)} bytes to ${input.path}`;
|
|
31
|
+
}),
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
function editFileTool() {
|
|
35
|
+
return defineHarnessTool({
|
|
36
|
+
name: "edit_file",
|
|
37
|
+
description: "Replace an exact text in a UTF-8 file. old_text must appear exactly once unless replace_all is true; include surrounding lines to make it unique.",
|
|
38
|
+
input: {
|
|
39
|
+
type: "object",
|
|
40
|
+
properties: {
|
|
41
|
+
path: { type: "string", minLength: 1 },
|
|
42
|
+
old_text: { type: "string", minLength: 1 },
|
|
43
|
+
new_text: { type: "string" },
|
|
44
|
+
replace_all: { type: "boolean" },
|
|
45
|
+
},
|
|
46
|
+
required: ["path", "old_text", "new_text"],
|
|
47
|
+
additionalProperties: false,
|
|
48
|
+
},
|
|
49
|
+
resources: (input) => ({ paths: [input.path] }),
|
|
50
|
+
execute: (input, context) => withStaging(async (directory) => {
|
|
51
|
+
const original = await downloadFile(context, input.path, join(directory, "file"));
|
|
52
|
+
const text = original.bytes.toString("utf8");
|
|
53
|
+
const occurrences = text.split(input.old_text).length - 1;
|
|
54
|
+
if (occurrences === 0)
|
|
55
|
+
return {
|
|
56
|
+
content: `old_text was not found in ${input.path}`,
|
|
57
|
+
isError: true,
|
|
58
|
+
};
|
|
59
|
+
if (occurrences > 1 && !input.replace_all)
|
|
60
|
+
return {
|
|
61
|
+
content: `old_text appears ${occurrences} times in ${input.path}; add surrounding lines or set replace_all`,
|
|
62
|
+
isError: true,
|
|
63
|
+
};
|
|
64
|
+
const updated = input.replace_all
|
|
65
|
+
? text.split(input.old_text).join(input.new_text)
|
|
66
|
+
: text.replace(input.old_text, () => input.new_text);
|
|
67
|
+
const current = await downloadFile(context, input.path, join(directory, "current"));
|
|
68
|
+
if (digest(current.bytes) !== digest(original.bytes))
|
|
69
|
+
return {
|
|
70
|
+
content: `${input.path} changed during the edit; read it again and retry`,
|
|
71
|
+
isError: true,
|
|
72
|
+
};
|
|
73
|
+
await writeFile(original.staged, updated);
|
|
74
|
+
await upload(context, original.staged, input.path);
|
|
75
|
+
return `Replaced ${input.replace_all ? occurrences : 1} occurrence(s) in ${input.path}`;
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
function upload(context, staged, path) {
|
|
80
|
+
return context.sandbox.upload(staged, sandboxPath(context, path), {
|
|
81
|
+
signal: context.signal,
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=edit-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"edit-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/edit-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type {\n HarnessToolContext,\n HarnessToolset,\n} from \"../../domain/tool.types.ts\";\nimport {\n digest,\n downloadFile,\n repositoryPath,\n sandboxPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport type { EditFileInput, WriteFileInput } from \"./tools.types.ts\";\n\nexport function harnessEditTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"edit\",\n tools: [writeFileTool(), editFileTool()],\n });\n}\n\nfunction writeFileTool() {\n return defineHarnessTool({\n name: \"write_file\",\n description:\n \"Create or replace a UTF-8 file relative to the repository root with the given content. Prefer edit_file to change part of an existing file.\",\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n content: { type: \"string\" },\n },\n required: [\"path\", \"content\"],\n additionalProperties: false,\n },\n resources: (input: WriteFileInput) => ({ paths: [input.path] }),\n execute: (input: WriteFileInput, context) =>\n withStaging(async (directory) => {\n repositoryPath(input.path);\n const staged = join(directory, \"file\");\n await writeFile(staged, input.content);\n await upload(context, staged, input.path);\n return `Wrote ${Buffer.byteLength(input.content)} bytes to ${input.path}`;\n }),\n });\n}\n\nfunction editFileTool() {\n return defineHarnessTool({\n name: \"edit_file\",\n description:\n \"Replace an exact text in a UTF-8 file. old_text must appear exactly once unless replace_all is true; include surrounding lines to make it unique.\",\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n old_text: { type: \"string\", minLength: 1 },\n new_text: { type: \"string\" },\n replace_all: { type: \"boolean\" },\n },\n required: [\"path\", \"old_text\", \"new_text\"],\n additionalProperties: false,\n },\n resources: (input: EditFileInput) => ({ paths: [input.path] }),\n execute: (input: EditFileInput, context) =>\n withStaging(async (directory) => {\n const original = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const text = original.bytes.toString(\"utf8\");\n const occurrences = text.split(input.old_text).length - 1;\n if (occurrences === 0)\n return {\n content: `old_text was not found in ${input.path}`,\n isError: true,\n };\n if (occurrences > 1 && !input.replace_all)\n return {\n content: `old_text appears ${occurrences} times in ${input.path}; add surrounding lines or set replace_all`,\n isError: true,\n };\n const updated = input.replace_all\n ? text.split(input.old_text).join(input.new_text)\n : text.replace(input.old_text, () => input.new_text);\n const current = await downloadFile(\n context,\n input.path,\n join(directory, \"current\"),\n );\n if (digest(current.bytes) !== digest(original.bytes))\n return {\n content: `${input.path} changed during the edit; read it again and retry`,\n isError: true,\n };\n await writeFile(original.staged, updated);\n await upload(context, original.staged, input.path);\n return `Replaced ${input.replace_all ? occurrences : 1} occurrence(s) in ${input.path}`;\n }),\n });\n}\n\nfunction upload(context: HarnessToolContext, staged: string, path: string) {\n return context.sandbox.upload(staged, sandboxPath(context, path), {\n signal: context.signal,\n });\n}\n"]}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import { glob } from "../../domain/glob.js";
|
|
3
|
+
import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
|
|
4
|
+
import { anywhere, downloadFile, repositoryPath, withStaging, } from "./sandbox-files.js";
|
|
5
|
+
import { TOOL_LIMITS } from "./tools.constants.js";
|
|
6
|
+
export function harnessFileTools() {
|
|
7
|
+
return defineHarnessToolset({
|
|
8
|
+
name: "files",
|
|
9
|
+
tools: [readFileTool(), listFilesTool()],
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
function readFileTool() {
|
|
13
|
+
return defineHarnessTool({
|
|
14
|
+
name: "read_file",
|
|
15
|
+
description: "Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.",
|
|
16
|
+
readOnly: true,
|
|
17
|
+
input: {
|
|
18
|
+
type: "object",
|
|
19
|
+
properties: {
|
|
20
|
+
path: { type: "string", minLength: 1 },
|
|
21
|
+
offset: { type: "integer", minimum: 1 },
|
|
22
|
+
limit: { type: "integer", minimum: 1, maximum: TOOL_LIMITS.readLines },
|
|
23
|
+
},
|
|
24
|
+
required: ["path"],
|
|
25
|
+
additionalProperties: false,
|
|
26
|
+
},
|
|
27
|
+
resources: (input) => ({ paths: [input.path] }),
|
|
28
|
+
execute: (input, context) => withStaging(async (directory) => {
|
|
29
|
+
const file = await downloadFile(context, input.path, join(directory, "file"));
|
|
30
|
+
const lines = file.bytes.toString("utf8").split(/\r?\n/);
|
|
31
|
+
if (lines.at(-1) === "")
|
|
32
|
+
lines.pop();
|
|
33
|
+
const start = (input.offset ?? 1) - 1;
|
|
34
|
+
const selected = lines.slice(start, start + (input.limit ?? TOOL_LIMITS.readLines));
|
|
35
|
+
const width = String(start + selected.length).length;
|
|
36
|
+
const body = selected
|
|
37
|
+
.map((line, index) => `${String(start + index + 1).padStart(width)}\t${line}`)
|
|
38
|
+
.join("\n");
|
|
39
|
+
const end = start + selected.length;
|
|
40
|
+
const note = end < lines.length || start > 0
|
|
41
|
+
? `\n[lines ${start + 1}-${end} of ${lines.length}]`
|
|
42
|
+
: "";
|
|
43
|
+
return lines.length ? `${body}${note}` : "(empty file)";
|
|
44
|
+
}),
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function listFilesTool() {
|
|
48
|
+
return defineHarnessTool({
|
|
49
|
+
name: "list_files",
|
|
50
|
+
description: "List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.",
|
|
51
|
+
readOnly: true,
|
|
52
|
+
input: {
|
|
53
|
+
type: "object",
|
|
54
|
+
properties: {
|
|
55
|
+
path: { type: "string" },
|
|
56
|
+
pattern: { type: "string", minLength: 1 },
|
|
57
|
+
},
|
|
58
|
+
additionalProperties: false,
|
|
59
|
+
},
|
|
60
|
+
resources: (input) => ({ paths: [input.path ?? "."] }),
|
|
61
|
+
async execute(input, context) {
|
|
62
|
+
const scope = repositoryPath(input.path ?? ".") || ".";
|
|
63
|
+
const result = await context.sandbox.invoke({
|
|
64
|
+
executable: "git",
|
|
65
|
+
arguments: [
|
|
66
|
+
"ls-files",
|
|
67
|
+
"-z",
|
|
68
|
+
"--cached",
|
|
69
|
+
"--others",
|
|
70
|
+
"--exclude-standard",
|
|
71
|
+
"--",
|
|
72
|
+
scope,
|
|
73
|
+
],
|
|
74
|
+
retain: TOOL_LIMITS.commandCharacters * 10,
|
|
75
|
+
signal: context.signal,
|
|
76
|
+
});
|
|
77
|
+
if (result.status !== 0)
|
|
78
|
+
return {
|
|
79
|
+
content: result.stderr || "git ls-files failed",
|
|
80
|
+
isError: true,
|
|
81
|
+
};
|
|
82
|
+
const matcher = input.pattern
|
|
83
|
+
? glob(anywhere(input.pattern), "path")
|
|
84
|
+
: undefined;
|
|
85
|
+
const files = [...new Set(result.stdout.split("\0").filter(Boolean))]
|
|
86
|
+
.filter((file) => !matcher || matcher.test(file))
|
|
87
|
+
.sort();
|
|
88
|
+
const shown = files.slice(0, TOOL_LIMITS.listEntries);
|
|
89
|
+
if (!shown.length)
|
|
90
|
+
return "No files found.";
|
|
91
|
+
return shown.length < files.length
|
|
92
|
+
? `${shown.join("\n")}\n[${files.length - shown.length} more files; narrow the path or pattern]`
|
|
93
|
+
: shown.join("\n");
|
|
94
|
+
},
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=file-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/file-tools.ts"],"names":[],"mappings":"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","sourcesContent":["import { join } from \"node:path\";\nimport { glob } from \"../../domain/glob.ts\";\nimport { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport {\n anywhere,\n downloadFile,\n repositoryPath,\n withStaging,\n} from \"./sandbox-files.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { ListFilesInput, ReadFileInput } from \"./tools.types.ts\";\n\nexport function harnessFileTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"files\",\n tools: [readFileTool(), listFilesTool()],\n });\n}\n\nfunction readFileTool() {\n return defineHarnessTool({\n name: \"read_file\",\n description:\n \"Read a UTF-8 text file relative to the repository root. Lines are numbered; use offset and limit for long files.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\", minLength: 1 },\n offset: { type: \"integer\", minimum: 1 },\n limit: { type: \"integer\", minimum: 1, maximum: TOOL_LIMITS.readLines },\n },\n required: [\"path\"],\n additionalProperties: false,\n },\n resources: (input: ReadFileInput) => ({ paths: [input.path] }),\n execute: (input: ReadFileInput, context) =>\n withStaging(async (directory) => {\n const file = await downloadFile(\n context,\n input.path,\n join(directory, \"file\"),\n );\n const lines = file.bytes.toString(\"utf8\").split(/\\r?\\n/);\n if (lines.at(-1) === \"\") lines.pop();\n const start = (input.offset ?? 1) - 1;\n const selected = lines.slice(\n start,\n start + (input.limit ?? TOOL_LIMITS.readLines),\n );\n const width = String(start + selected.length).length;\n const body = selected\n .map(\n (line, index) =>\n `${String(start + index + 1).padStart(width)}\\t${line}`,\n )\n .join(\"\\n\");\n const end = start + selected.length;\n const note =\n end < lines.length || start > 0\n ? `\\n[lines ${start + 1}-${end} of ${lines.length}]`\n : \"\";\n return lines.length ? `${body}${note}` : \"(empty file)\";\n }),\n });\n}\n\nfunction listFilesTool() {\n return defineHarnessTool({\n name: \"list_files\",\n description:\n \"List files in the repository that are tracked or not ignored by Git, optionally under a directory and filtered by a glob such as src/**/*.ts; a glob without a slash matches file names at any depth.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n path: { type: \"string\" },\n pattern: { type: \"string\", minLength: 1 },\n },\n additionalProperties: false,\n },\n resources: (input: ListFilesInput) => ({ paths: [input.path ?? \".\"] }),\n async execute(input: ListFilesInput, context) {\n const scope = repositoryPath(input.path ?? \".\") || \".\";\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"ls-files\",\n \"-z\",\n \"--cached\",\n \"--others\",\n \"--exclude-standard\",\n \"--\",\n scope,\n ],\n retain: TOOL_LIMITS.commandCharacters * 10,\n signal: context.signal,\n });\n if (result.status !== 0)\n return {\n content: result.stderr || \"git ls-files failed\",\n isError: true,\n };\n const matcher = input.pattern\n ? glob(anywhere(input.pattern), \"path\")\n : undefined;\n const files = [...new Set(result.stdout.split(\"\\0\").filter(Boolean))]\n .filter((file) => !matcher || matcher.test(file))\n .sort();\n const shown = files.slice(0, TOOL_LIMITS.listEntries);\n if (!shown.length) return \"No files found.\";\n return shown.length < files.length\n ? `${shown.join(\"\\n\")}\\n[${files.length - shown.length} more files; narrow the path or pattern]`\n : shown.join(\"\\n\");\n },\n });\n}\n"]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { defineHarnessTool, defineHarnessToolset } from "../../domain/tool.js";
|
|
2
|
+
import { commandOutput } from "./sandbox-files.js";
|
|
3
|
+
import { GIT_BLOCKED_OPTIONS, GIT_READ_COMMANDS, TOOL_LIMITS, } from "./tools.constants.js";
|
|
4
|
+
export function harnessGitTools() {
|
|
5
|
+
return defineHarnessToolset({
|
|
6
|
+
name: "git",
|
|
7
|
+
tools: [
|
|
8
|
+
defineHarnessTool({
|
|
9
|
+
name: "git",
|
|
10
|
+
description: "Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.",
|
|
11
|
+
readOnly: true,
|
|
12
|
+
input: {
|
|
13
|
+
type: "object",
|
|
14
|
+
properties: {
|
|
15
|
+
command: { enum: [...GIT_READ_COMMANDS] },
|
|
16
|
+
arguments: { type: "array", items: { type: "string" } },
|
|
17
|
+
},
|
|
18
|
+
required: ["command"],
|
|
19
|
+
additionalProperties: false,
|
|
20
|
+
},
|
|
21
|
+
resources: (input) => ({
|
|
22
|
+
command: ["git", input.command, ...(input.arguments ?? [])].join(" "),
|
|
23
|
+
}),
|
|
24
|
+
async execute(input, context) {
|
|
25
|
+
const blocked = (input.arguments ?? []).find((argument) => GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)));
|
|
26
|
+
if (blocked)
|
|
27
|
+
return {
|
|
28
|
+
content: `Unsupported Git option: ${blocked}`,
|
|
29
|
+
isError: true,
|
|
30
|
+
};
|
|
31
|
+
const result = await context.sandbox.invoke({
|
|
32
|
+
executable: "git",
|
|
33
|
+
arguments: [
|
|
34
|
+
"--no-pager",
|
|
35
|
+
input.command,
|
|
36
|
+
...(input.command === "status"
|
|
37
|
+
? []
|
|
38
|
+
: ["--no-ext-diff", "--no-textconv"]),
|
|
39
|
+
...(input.arguments ?? []),
|
|
40
|
+
],
|
|
41
|
+
stdin: "",
|
|
42
|
+
retain: TOOL_LIMITS.commandCharacters,
|
|
43
|
+
signal: context.signal,
|
|
44
|
+
});
|
|
45
|
+
return {
|
|
46
|
+
content: commandOutput(result),
|
|
47
|
+
isError: result.status !== 0,
|
|
48
|
+
};
|
|
49
|
+
},
|
|
50
|
+
}),
|
|
51
|
+
],
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=git-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-tools.js","sourceRoot":"","sources":["../../../src/adapters/tools/git-tools.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAE/E,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EACL,mBAAmB,EACnB,iBAAiB,EACjB,WAAW,GACZ,MAAM,sBAAsB,CAAC;AAG9B,MAAM,UAAU,eAAe;IAC7B,OAAO,oBAAoB,CAAC;QAC1B,IAAI,EAAE,KAAK;QACX,KAAK,EAAE;YACL,iBAAiB,CAAC;gBAChB,IAAI,EAAE,KAAK;gBACX,WAAW,EACT,sIAAsI;gBACxI,QAAQ,EAAE,IAAI;gBACd,KAAK,EAAE;oBACL,IAAI,EAAE,QAAQ;oBACd,UAAU,EAAE;wBACV,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC,GAAG,iBAAiB,CAAC,EAAE;wBACzC,SAAS,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,EAAE;qBACxD;oBACD,QAAQ,EAAE,CAAC,SAAS,CAAC;oBACrB,oBAAoB,EAAE,KAAK;iBAC5B;gBACD,SAAS,EAAE,CAAC,KAAe,EAAE,EAAE,CAAC,CAAC;oBAC/B,OAAO,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;iBACtE,CAAC;gBACF,KAAK,CAAC,OAAO,CAAC,KAAe,EAAE,OAAO;oBACpC,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CACxD,mBAAmB,CAAC,IAAI,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,QAAQ,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC,CAClE,CAAC;oBACF,IAAI,OAAO;wBACT,OAAO;4BACL,OAAO,EAAE,2BAA2B,OAAO,EAAE;4BAC7C,OAAO,EAAE,IAAI;yBACd,CAAC;oBACJ,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC;wBAC1C,UAAU,EAAE,KAAK;wBACjB,SAAS,EAAE;4BACT,YAAY;4BACZ,KAAK,CAAC,OAAO;4BACb,GAAG,CAAC,KAAK,CAAC,OAAO,KAAK,QAAQ;gCAC5B,CAAC,CAAC,EAAE;gCACJ,CAAC,CAAC,CAAC,eAAe,EAAE,eAAe,CAAC,CAAC;4BACvC,GAAG,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;yBAC3B;wBACD,KAAK,EAAE,EAAE;wBACT,MAAM,EAAE,WAAW,CAAC,iBAAiB;wBACrC,MAAM,EAAE,OAAO,CAAC,MAAM;qBACvB,CAAC,CAAC;oBACH,OAAO;wBACL,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;wBAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,KAAK,CAAC;qBAC7B,CAAC;gBACJ,CAAC;aACF,CAAC;SACH;KACF,CAAC,CAAC;AACL,CAAC","sourcesContent":["import { defineHarnessTool, defineHarnessToolset } from \"../../domain/tool.ts\";\nimport type { HarnessToolset } from \"../../domain/tool.types.ts\";\nimport { commandOutput } from \"./sandbox-files.ts\";\nimport {\n GIT_BLOCKED_OPTIONS,\n GIT_READ_COMMANDS,\n TOOL_LIMITS,\n} from \"./tools.constants.ts\";\nimport type { GitInput } from \"./tools.types.ts\";\n\nexport function harnessGitTools(): HarnessToolset {\n return defineHarnessToolset({\n name: \"git\",\n tools: [\n defineHarnessTool({\n name: \"git\",\n description:\n \"Run a read-only Git command (status, diff, log or show) in the repository with extra arguments, for example log with -n 5 --oneline.\",\n readOnly: true,\n input: {\n type: \"object\",\n properties: {\n command: { enum: [...GIT_READ_COMMANDS] },\n arguments: { type: \"array\", items: { type: \"string\" } },\n },\n required: [\"command\"],\n additionalProperties: false,\n },\n resources: (input: GitInput) => ({\n command: [\"git\", input.command, ...(input.arguments ?? [])].join(\" \"),\n }),\n async execute(input: GitInput, context) {\n const blocked = (input.arguments ?? []).find((argument) =>\n GIT_BLOCKED_OPTIONS.some((option) => argument.startsWith(option)),\n );\n if (blocked)\n return {\n content: `Unsupported Git option: ${blocked}`,\n isError: true,\n };\n const result = await context.sandbox.invoke({\n executable: \"git\",\n arguments: [\n \"--no-pager\",\n input.command,\n ...(input.command === \"status\"\n ? []\n : [\"--no-ext-diff\", \"--no-textconv\"]),\n ...(input.arguments ?? []),\n ],\n stdin: \"\",\n retain: TOOL_LIMITS.commandCharacters,\n signal: context.signal,\n });\n return {\n content: commandOutput(result),\n isError: result.status !== 0,\n };\n },\n }),\n ],\n });\n}\n"]}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { CommandResult } from "../../domain/command.types.ts";
|
|
2
|
+
import type { HarnessToolContext } from "../../domain/tool.types.ts";
|
|
3
|
+
import type { SandboxFile } from "./tools.types.ts";
|
|
4
|
+
export declare function repositoryPath(path: string): string;
|
|
5
|
+
export declare function sandboxPath(context: HarnessToolContext, path: string): string;
|
|
6
|
+
export declare function withStaging<T>(operation: (directory: string) => Promise<T>): Promise<T>;
|
|
7
|
+
export declare function downloadFile(context: HarnessToolContext, path: string, staged: string): Promise<SandboxFile>;
|
|
8
|
+
export declare function digest(bytes: Buffer): string;
|
|
9
|
+
export declare function commandOutput(result: CommandResult): string;
|
|
10
|
+
export declare function anywhere(pattern: string): string;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { lstat, mkdtemp, readFile, rm } from "node:fs/promises";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import { join, posix } from "node:path";
|
|
5
|
+
import { normalizeResourcePath } from "../../domain/permissions.js";
|
|
6
|
+
import { TOOL_LIMITS } from "./tools.constants.js";
|
|
7
|
+
export function repositoryPath(path) {
|
|
8
|
+
const normalized = normalizeResourcePath(path);
|
|
9
|
+
if (normalized === undefined)
|
|
10
|
+
throw new Error(`Path must stay inside the repository: ${path}`);
|
|
11
|
+
return normalized;
|
|
12
|
+
}
|
|
13
|
+
export function sandboxPath(context, path) {
|
|
14
|
+
const normalized = repositoryPath(path);
|
|
15
|
+
return normalized
|
|
16
|
+
? posix.join(context.sandbox.root, normalized)
|
|
17
|
+
: context.sandbox.root;
|
|
18
|
+
}
|
|
19
|
+
export async function withStaging(operation) {
|
|
20
|
+
const directory = await mkdtemp(join(tmpdir(), "outpost-tool-"));
|
|
21
|
+
try {
|
|
22
|
+
return await operation(directory);
|
|
23
|
+
}
|
|
24
|
+
finally {
|
|
25
|
+
await rm(directory, { recursive: true, force: true });
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
export async function downloadFile(context, path, staged) {
|
|
29
|
+
await context.sandbox.download(sandboxPath(context, path), staged, {
|
|
30
|
+
signal: context.signal,
|
|
31
|
+
});
|
|
32
|
+
const info = await lstat(staged);
|
|
33
|
+
if (info.isSymbolicLink())
|
|
34
|
+
throw new Error(`${path} is a symbolic link; links are not followed`);
|
|
35
|
+
if (!info.isFile())
|
|
36
|
+
throw new Error(`${path} is not a regular file`);
|
|
37
|
+
if (info.size > TOOL_LIMITS.fileBytes)
|
|
38
|
+
throw new Error(`${path} has ${info.size} bytes; the limit is ${TOOL_LIMITS.fileBytes}`);
|
|
39
|
+
const bytes = await readFile(staged);
|
|
40
|
+
if (bytes.subarray(0, TOOL_LIMITS.binaryProbeBytes).includes(0))
|
|
41
|
+
throw new Error(`${path} looks binary and cannot be read as text`);
|
|
42
|
+
return { staged, bytes };
|
|
43
|
+
}
|
|
44
|
+
export function digest(bytes) {
|
|
45
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
46
|
+
}
|
|
47
|
+
export function commandOutput(result) {
|
|
48
|
+
const note = (text) => text.length >= TOOL_LIMITS.commandCharacters
|
|
49
|
+
? `[output truncated to the last ${TOOL_LIMITS.commandCharacters} characters]\n${text}`
|
|
50
|
+
: text;
|
|
51
|
+
return [
|
|
52
|
+
`exit status: ${result.status}`,
|
|
53
|
+
...(result.stdout ? ["--- stdout ---", note(result.stdout)] : []),
|
|
54
|
+
...(result.stderr ? ["--- stderr ---", note(result.stderr)] : []),
|
|
55
|
+
].join("\n");
|
|
56
|
+
}
|
|
57
|
+
export function anywhere(pattern) {
|
|
58
|
+
return pattern.includes("/") ? pattern : `**/${pattern}`;
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=sandbox-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sandbox-files.js","sourceRoot":"","sources":["../../../src/adapters/tools/sandbox-files.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from \"node:crypto\";\nimport { lstat, mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join, posix } from \"node:path\";\nimport { normalizeResourcePath } from \"../../domain/permissions.ts\";\nimport type { CommandResult } from \"../../domain/command.types.ts\";\nimport type { HarnessToolContext } from \"../../domain/tool.types.ts\";\nimport { TOOL_LIMITS } from \"./tools.constants.ts\";\nimport type { SandboxFile } from \"./tools.types.ts\";\n\nexport function repositoryPath(path: string): string {\n const normalized = normalizeResourcePath(path);\n if (normalized === undefined)\n throw new Error(`Path must stay inside the repository: ${path}`);\n return normalized;\n}\n\nexport function sandboxPath(context: HarnessToolContext, path: string): string {\n const normalized = repositoryPath(path);\n return normalized\n ? posix.join(context.sandbox.root, normalized)\n : context.sandbox.root;\n}\n\nexport async function withStaging<T>(\n operation: (directory: string) => Promise<T>,\n): Promise<T> {\n const directory = await mkdtemp(join(tmpdir(), \"outpost-tool-\"));\n try {\n return await operation(directory);\n } finally {\n await rm(directory, { recursive: true, force: true });\n }\n}\n\nexport async function downloadFile(\n context: HarnessToolContext,\n path: string,\n staged: string,\n): Promise<SandboxFile> {\n await context.sandbox.download(sandboxPath(context, path), staged, {\n signal: context.signal,\n });\n const info = await lstat(staged);\n if (info.isSymbolicLink())\n throw new Error(`${path} is a symbolic link; links are not followed`);\n if (!info.isFile()) throw new Error(`${path} is not a regular file`);\n if (info.size > TOOL_LIMITS.fileBytes)\n throw new Error(\n `${path} has ${info.size} bytes; the limit is ${TOOL_LIMITS.fileBytes}`,\n );\n const bytes = await readFile(staged);\n if (bytes.subarray(0, TOOL_LIMITS.binaryProbeBytes).includes(0))\n throw new Error(`${path} looks binary and cannot be read as text`);\n return { staged, bytes };\n}\n\nexport function digest(bytes: Buffer): string {\n return createHash(\"sha256\").update(bytes).digest(\"hex\");\n}\n\nexport function commandOutput(result: CommandResult): string {\n const note = (text: string) =>\n text.length >= TOOL_LIMITS.commandCharacters\n ? `[output truncated to the last ${TOOL_LIMITS.commandCharacters} characters]\\n${text}`\n : text;\n return [\n `exit status: ${result.status}`,\n ...(result.stdout ? [\"--- stdout ---\", note(result.stdout)] : []),\n ...(result.stderr ? [\"--- stderr ---\", note(result.stderr)] : []),\n ].join(\"\\n\");\n}\n\nexport function anywhere(pattern: string): string {\n return pattern.includes(\"/\") ? pattern : `**/${pattern}`;\n}\n"]}
|