akm-cli 0.8.3 → 0.9.0-beta.1
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 +209 -0
- package/dist/assets/help/help-proposals.md +1 -2
- package/dist/assets/hints/cli-hints-full.md +34 -19
- package/dist/assets/hints/cli-hints-short.md +1 -1
- package/dist/assets/profiles/catchup.json +13 -0
- package/dist/assets/profiles/consolidate.json +13 -0
- package/dist/assets/profiles/frequent.json +13 -0
- package/dist/assets/tasks/core/backup.yml +4 -0
- package/dist/assets/tasks/core/extract.yml +4 -0
- package/dist/assets/tasks/core/improve.yml +4 -0
- package/dist/assets/tasks/core/index-refresh.yml +4 -0
- package/dist/assets/tasks/core/sync.yml +4 -0
- package/dist/assets/tasks/core/update-stashes.yml +4 -0
- package/dist/assets/tasks/core/version-check.yml +4 -0
- package/dist/cli/config-migrate.js +6 -6
- package/dist/cli/config-validate.js +4 -4
- package/dist/cli/confirm.js +3 -3
- package/dist/cli/parse-args.js +1 -1
- package/dist/cli/shared.js +51 -14
- package/dist/cli-node.mjs +26 -0
- package/dist/cli.js +171 -3862
- package/dist/commands/{agent-dispatch.js → agent/agent-dispatch.js} +6 -6
- package/dist/commands/{agent-support.js → agent/agent-support.js} +2 -2
- package/dist/commands/agent/contribute-cli.js +200 -0
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +240 -3
- package/dist/commands/config-edit.js +344 -0
- package/dist/commands/db-cli.js +2 -2
- package/dist/commands/env/env-cli.js +529 -0
- package/dist/commands/env/env.js +410 -0
- package/dist/commands/env/secret-cli.js +259 -0
- package/dist/commands/{secret.js → env/secret.js} +6 -47
- package/dist/commands/events.js +4 -4
- package/dist/commands/feedback-cli.js +18 -34
- package/dist/commands/graph/graph-cli.js +132 -0
- package/dist/commands/{graph.js → graph/graph.js} +22 -16
- package/dist/commands/health/checks.js +279 -0
- package/dist/commands/health.js +94 -262
- package/dist/commands/{consolidate.js → improve/consolidate.js} +48 -36
- package/dist/commands/{distill-promotion-policy.js → improve/distill-promotion-policy.js} +3 -3
- package/dist/commands/{distill.js → improve/distill.js} +39 -18
- package/dist/commands/{eval-cases.js → improve/eval-cases.js} +1 -1
- package/dist/commands/{extract-cli.js → improve/extract-cli.js} +4 -4
- package/dist/commands/{extract-prompt.js → improve/extract-prompt.js} +2 -2
- package/dist/commands/{extract.js → improve/extract.js} +185 -26
- package/dist/commands/{improve-auto-accept.js → improve/improve-auto-accept.js} +4 -4
- package/dist/commands/{improve-cli.js → improve/improve-cli.js} +44 -22
- package/dist/commands/{improve-profiles.js → improve/improve-profiles.js} +13 -7
- package/dist/commands/{improve-result-file.js → improve/improve-result-file.js} +1 -1
- package/dist/commands/{improve.js → improve/improve.js} +517 -253
- package/dist/{core → commands/improve/memory}/memory-belief.js +2 -2
- package/dist/{core → commands/improve/memory}/memory-contradiction-detect.js +5 -5
- package/dist/{core → commands/improve/memory}/memory-improve.js +4 -4
- package/dist/commands/{reflect.js → improve/reflect.js} +33 -28
- package/dist/commands/improve/session-asset.js +248 -0
- package/dist/commands/lint/agent-linter.js +1 -1
- package/dist/commands/lint/base-linter.js +55 -37
- package/dist/commands/lint/command-linter.js +1 -1
- package/dist/commands/lint/default-linter.js +1 -1
- package/dist/commands/lint/env-key-rules.js +1 -1
- package/dist/commands/lint/index.js +19 -25
- package/dist/commands/lint/knowledge-linter.js +1 -1
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +8 -8
- package/dist/commands/lint/skill-linter.js +1 -1
- package/dist/commands/lint/task-linter.js +1 -1
- package/dist/commands/lint/workflow-linter.js +1 -1
- package/dist/commands/lint.js +1 -1
- package/dist/commands/observability-cli.js +244 -0
- package/dist/commands/proposal/drain-policies.js +3 -3
- package/dist/commands/proposal/drain.js +15 -10
- package/dist/commands/proposal/proposal-cli.js +478 -0
- package/dist/commands/{proposal.js → proposal/proposal.js} +5 -5
- package/dist/commands/{propose.js → proposal/propose.js} +11 -11
- package/dist/{core → commands/proposal/validators}/proposal-quality-validators.js +8 -3
- package/dist/{core → commands/proposal/validators}/proposal-validators.js +5 -5
- package/dist/{core → commands/proposal/validators}/proposals.js +13 -7
- package/dist/commands/{curate.js → read/curate.js} +7 -7
- package/dist/commands/{knowledge.js → read/knowledge.js} +22 -9
- package/dist/commands/{registry-search.js → read/registry-search.js} +5 -5
- package/dist/commands/{remember-cli.js → read/remember-cli.js} +15 -7
- package/dist/commands/read/search-cli.js +207 -0
- package/dist/commands/{search.js → read/search.js} +22 -27
- package/dist/commands/{show.js → read/show.js} +31 -45
- package/dist/commands/registry-cli.js +8 -8
- package/dist/commands/remember.js +8 -8
- package/dist/commands/sources/add-cli.js +293 -0
- package/dist/commands/{history.js → sources/history.js} +27 -25
- package/dist/commands/{info.js → sources/info.js} +6 -6
- package/dist/commands/{init.js → sources/init.js} +6 -6
- package/dist/commands/{installed-stashes.js → sources/installed-stashes.js} +12 -12
- package/dist/commands/{migration-help.js → sources/migration-help.js} +3 -2
- package/dist/commands/{schema-repair.js → sources/schema-repair.js} +8 -8
- package/dist/commands/{self-update.js → sources/self-update.js} +10 -9
- package/dist/commands/{source-add.js → sources/source-add.js} +10 -10
- package/dist/commands/{source-clone.js → sources/source-clone.js} +7 -7
- package/dist/commands/{source-manage.js → sources/source-manage.js} +4 -4
- package/dist/commands/sources/sources-cli.js +305 -0
- package/dist/commands/sources/stash-cli.js +219 -0
- package/dist/commands/{stash-skeleton.js → sources/stash-skeleton.js} +2 -1
- package/dist/commands/tasks/default-tasks.js +173 -0
- package/dist/commands/tasks/tasks-cli.js +210 -0
- package/dist/commands/{tasks.js → tasks/tasks.js} +14 -14
- package/dist/commands/wiki-cli.js +307 -0
- package/dist/commands/workflow-cli.js +329 -0
- package/dist/core/action-contributors.js +1 -1
- package/dist/core/assert.js +40 -0
- package/dist/core/asset/asset-create.js +54 -0
- package/dist/core/{asset-ref.js → asset/asset-ref.js} +21 -4
- package/dist/core/{asset-registry.js → asset/asset-registry.js} +3 -3
- package/dist/core/{asset-spec.js → asset/asset-spec.js} +17 -31
- package/dist/core/{markdown.js → asset/markdown.js} +1 -1
- package/dist/core/{stash-meta.js → asset/stash-meta.js} +1 -1
- package/dist/core/best-effort.js +64 -0
- package/dist/core/common.js +32 -18
- package/dist/core/{config-io.js → config/config-io.js} +29 -19
- package/dist/core/{config-migration.js → config/config-migration.js} +11 -9
- package/dist/core/{config-schema.js → config/config-schema.js} +45 -1
- package/dist/core/config/config-types.js +16 -0
- package/dist/core/{config-walker.js → config/config-walker.js} +2 -2
- package/dist/core/{config.js → config/config.js} +10 -8
- package/dist/core/env-secret-ref.js +90 -0
- package/dist/core/errors.js +13 -3
- package/dist/core/events.js +27 -4
- package/dist/core/file-lock.js +1 -1
- package/dist/core/improve-types.js +48 -0
- package/dist/core/lesson-lint.js +2 -2
- package/dist/core/paths.js +2 -2
- package/dist/core/ripgrep/install.js +2 -2
- package/dist/core/ripgrep/resolve.js +2 -2
- package/dist/core/state-db.js +88 -46
- package/dist/core/text-truncation.js +148 -0
- package/dist/core/time.js +1 -1
- package/dist/core/write-source.js +98 -85
- package/dist/indexer/{db-backup.js → db/db-backup.js} +9 -24
- package/dist/indexer/{db.js → db/db.js} +126 -116
- package/dist/indexer/{graph-db.js → db/graph-db.js} +9 -4
- package/dist/indexer/{llm-cache.js → db/llm-cache.js} +15 -12
- package/dist/indexer/ensure-index.js +4 -4
- package/dist/indexer/{graph-boost.js → graph/graph-boost.js} +1 -1
- package/dist/indexer/{graph-extraction.js → graph/graph-extraction.js} +55 -13
- package/dist/indexer/indexer.js +37 -30
- package/dist/indexer/init.js +54 -0
- package/dist/indexer/manifest.js +10 -10
- package/dist/indexer/{memory-inference.js → passes/memory-inference.js} +92 -23
- package/dist/indexer/{metadata-contributors.js → passes/metadata-contributors.js} +10 -8
- package/dist/indexer/{metadata.js → passes/metadata.js} +15 -19
- package/dist/indexer/{staleness-detect.js → passes/staleness-detect.js} +53 -12
- package/dist/indexer/{db-search.js → search/db-search.js} +28 -16
- package/dist/indexer/{ranking-contributors.js → search/ranking-contributors.js} +1 -1
- package/dist/indexer/{ranking.js → search/ranking.js} +2 -2
- package/dist/indexer/{search-hit-enrichers.js → search/search-hit-enrichers.js} +3 -3
- package/dist/indexer/{search-source.js → search/search-source.js} +8 -8
- package/dist/indexer/{semantic-status.js → search/semantic-status.js} +3 -3
- package/dist/indexer/usage/unmigrated-vaults-guard.js +94 -0
- package/dist/indexer/{usage-events.js → usage/usage-events.js} +32 -0
- package/dist/indexer/{file-context.js → walk/file-context.js} +10 -15
- package/dist/indexer/{matchers.js → walk/matchers.js} +13 -9
- package/dist/indexer/{path-resolver.js → walk/path-resolver.js} +6 -6
- package/dist/indexer/{project-context.js → walk/project-context.js} +1 -1
- package/dist/indexer/{walker.js → walk/walker.js} +4 -3
- package/dist/integrations/agent/builder-shared.js +39 -0
- package/dist/integrations/agent/builders.js +14 -81
- package/dist/integrations/agent/config.js +6 -4
- package/dist/integrations/agent/detect.js +1 -1
- package/dist/integrations/agent/index.js +23 -8
- package/dist/integrations/agent/prompts.js +2 -3
- package/dist/integrations/agent/runner.js +22 -3
- package/dist/integrations/agent/spawn.js +9 -10
- package/dist/integrations/harnesses/claude/agent-builder.js +48 -0
- package/dist/integrations/harnesses/claude/config-import.js +70 -0
- package/dist/integrations/harnesses/claude/index.js +64 -0
- package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js} +16 -1
- package/dist/integrations/harnesses/index.js +144 -0
- package/dist/integrations/harnesses/opencode/agent-builder.js +43 -0
- package/dist/integrations/harnesses/opencode/config-import.js +82 -0
- package/dist/integrations/harnesses/opencode/index.js +59 -0
- package/dist/integrations/{session-logs/providers/opencode.js → harnesses/opencode/session-log.js} +1 -1
- package/dist/integrations/harnesses/opencode-sdk/index.js +49 -0
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +234 -0
- package/dist/integrations/harnesses/types.js +43 -0
- package/dist/integrations/lockfile.js +7 -16
- package/dist/integrations/session-logs/index.js +82 -9
- package/dist/llm/call-ai.js +4 -4
- package/dist/llm/client.js +131 -6
- package/dist/llm/embedder.js +6 -6
- package/dist/llm/embedders/local.js +9 -22
- package/dist/llm/embedders/remote.js +2 -2
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/graph-extract.js +31 -12
- package/dist/llm/index-passes.js +1 -1
- package/dist/llm/memory-infer.js +12 -5
- package/dist/llm/metadata-enhance.js +2 -2
- package/dist/output/context.js +6 -44
- package/dist/output/renderers.js +88 -58
- package/dist/output/shapes/curate.js +7 -3
- package/dist/output/shapes/distill.js +7 -3
- package/dist/output/shapes/env-list.js +18 -16
- package/dist/output/shapes/events.js +5 -4
- package/dist/output/shapes/helpers.js +2 -4
- package/dist/output/shapes/history.js +7 -3
- package/dist/output/shapes/passthrough.js +8 -11
- package/dist/output/shapes/{proposal-accept.js → proposal/accept.js} +7 -3
- package/dist/output/shapes/{proposal-diff.js → proposal/diff.js} +7 -3
- package/dist/output/shapes/{proposal-list.js → proposal/list.js} +7 -3
- package/dist/output/shapes/{proposal-producer.js → proposal/producer.js} +5 -4
- package/dist/output/shapes/{proposal-reject.js → proposal/reject.js} +7 -3
- package/dist/output/shapes/{proposal-show.js → proposal/show.js} +7 -3
- package/dist/output/shapes/registry-search.js +7 -3
- package/dist/output/shapes/registry.js +12 -0
- package/dist/output/shapes/search.js +7 -3
- package/dist/output/shapes/secret-list.js +18 -16
- package/dist/output/shapes/show.js +7 -3
- package/dist/output/shapes.js +55 -30
- package/dist/output/text/add.js +2 -3
- package/dist/output/text/clone.js +2 -3
- package/dist/output/text/config.js +2 -3
- package/dist/output/text/curate.js +4 -3
- package/dist/output/text/distill.js +2 -3
- package/dist/output/text/enable-disable.js +5 -4
- package/dist/output/text/env.js +13 -0
- package/dist/output/text/events.js +5 -4
- package/dist/output/text/feedback.js +4 -3
- package/dist/output/text/helpers.js +54 -39
- package/dist/output/text/history.js +2 -3
- package/dist/output/text/import.js +2 -3
- package/dist/output/text/index.js +2 -3
- package/dist/output/text/info.js +2 -3
- package/dist/output/text/init.js +2 -3
- package/dist/output/text/list.js +2 -3
- package/dist/output/text/proposal/producer.js +9 -0
- package/dist/output/text/proposal/proposal.js +13 -0
- package/dist/output/text/registry-commands.js +8 -7
- package/dist/output/text/registry.js +12 -0
- package/dist/output/text/remember.js +4 -3
- package/dist/output/text/remove.js +2 -3
- package/dist/output/text/save.js +2 -3
- package/dist/output/text/search.js +4 -3
- package/dist/output/text/show.js +4 -3
- package/dist/output/text/update.js +2 -3
- package/dist/output/text/upgrade.js +2 -3
- package/dist/output/text/wiki.js +12 -11
- package/dist/output/text/workflow.js +12 -10
- package/dist/output/text.js +66 -32
- package/dist/registry/build-index.js +11 -10
- package/dist/registry/factory.js +1 -1
- package/dist/registry/origin-resolve.js +1 -1
- package/dist/registry/providers/index.js +2 -2
- package/dist/registry/providers/skills-sh.js +91 -72
- package/dist/registry/providers/static-index.js +75 -52
- package/dist/registry/resolve.js +3 -3
- package/dist/runtime.js +242 -0
- package/dist/scripts/migrate-storage.js +1594 -673
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +240 -166
- package/dist/setup/detect.js +311 -9
- package/dist/setup/harness-config-import.js +6 -120
- package/dist/setup/setup.js +454 -43
- package/dist/sources/include.js +1 -1
- package/dist/sources/provider-factory.js +2 -2
- package/dist/sources/providers/filesystem.js +3 -3
- package/dist/sources/providers/git.js +9 -9
- package/dist/sources/providers/index.js +4 -4
- package/dist/sources/providers/npm.js +6 -6
- package/dist/sources/providers/provider-utils.js +13 -20
- package/dist/sources/providers/sync-from-ref.js +5 -5
- package/dist/sources/providers/tar-utils.js +2 -2
- package/dist/sources/providers/website.js +2 -2
- package/dist/sources/resolve.js +5 -5
- package/dist/sources/website-ingest.js +5 -5
- package/dist/storage/database.js +102 -0
- package/dist/storage/engines/sqlite-migrations.js +42 -0
- package/dist/storage/locations.js +25 -0
- package/dist/storage/repositories/index-db.js +43 -0
- package/dist/storage/repositories/workflow-runs-repository.js +141 -0
- package/dist/tasks/backends/cron.js +4 -4
- package/dist/tasks/backends/exec-utils.js +32 -0
- package/dist/tasks/backends/index.js +3 -3
- package/dist/tasks/backends/launchd.js +7 -14
- package/dist/tasks/backends/schtasks.js +7 -16
- package/dist/tasks/embedded.js +71 -0
- package/dist/tasks/parser.js +2 -2
- package/dist/tasks/resolveAkmBin.js +1 -1
- package/dist/tasks/runner.js +28 -15
- package/dist/tasks/schedule.js +1 -1
- package/dist/tasks/validator.js +7 -7
- package/dist/text-import-hook.mjs +51 -0
- package/dist/version.js +2 -1
- package/dist/wiki/wiki.js +7 -7
- package/dist/workflows/{authoring.js → authoring/authoring.js} +6 -6
- package/dist/workflows/{scope-key.js → authoring/scope-key.js} +1 -1
- package/dist/workflows/cli.js +1 -1
- package/dist/workflows/db.js +50 -32
- package/dist/workflows/parser.js +4 -4
- package/dist/workflows/renderer.js +5 -5
- package/dist/workflows/runtime/agent-identity.js +56 -0
- package/dist/workflows/runtime/checkin.js +57 -0
- package/dist/workflows/{runs.js → runtime/runs.js} +197 -101
- package/dist/workflows/validate-summary.js +82 -0
- package/docs/README.md +1 -1
- package/docs/data-and-telemetry.md +6 -6
- package/package.json +16 -8
- package/dist/commands/add-cli.js +0 -279
- package/dist/commands/env.js +0 -213
- package/dist/integrations/agent/sdk-runner.js +0 -126
- package/dist/output/shapes/vault-list.js +0 -19
- package/dist/output/text/proposal-producer.js +0 -8
- package/dist/output/text/proposal.js +0 -12
- package/dist/output/text/vault.js +0 -16
- /package/dist/core/{asset-serialize.js → asset/asset-serialize.js} +0 -0
- /package/dist/core/{frontmatter.js → asset/frontmatter.js} +0 -0
- /package/dist/core/{config-sources.js → config/config-sources.js} +0 -0
- /package/dist/indexer/{graph-dedup.js → graph/graph-dedup.js} +0 -0
- /package/dist/{core/config-types.js → indexer/passes/pass-context.js} +0 -0
- /package/dist/indexer/{search-fields.js → search/search-fields.js} +0 -0
- /package/dist/indexer/{index-context.js → walk/index-context.js} +0 -0
- /package/dist/workflows/{document-cache.js → runtime/document-cache.js} +0 -0
|
@@ -1,11 +1,26 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
4
|
+
/**
|
|
5
|
+
* Internal entry point for the `agent` integration. CLI-only project — no
|
|
6
|
+
* public exports map. Other akm modules import from this barrel for the
|
|
7
|
+
* sake of grouping imports.
|
|
8
|
+
*
|
|
9
|
+
* Surface:
|
|
10
|
+
* • Types: AgentProfile, AgentConfig, AgentRunResult, AgentFailureReason.
|
|
11
|
+
* • Profiles: getBuiltinAgentProfile, listBuiltinAgentProfiles, BUILTIN_AGENT_PROFILE_NAMES.
|
|
12
|
+
* • Config: parseAgentConfig, resolveProfileFromConfig, requireAgentProfile, listResolvedAgentProfiles, listAgentProfileNames.
|
|
13
|
+
* • Spawn: runAgent. Builders: getCommandBuilder, AgentCommandBuilder, AgentDispatchRequest — platform-specific argv construction.
|
|
14
|
+
* • Detection: detectAgentCliProfiles, pickDefaultAgentProfile, defaultWhich.
|
|
15
|
+
*/
|
|
16
|
+
// The OpenCode SDK runner moved to its harness directory in #564
|
|
17
|
+
// (`harnesses/opencode-sdk/`). Re-exported here so existing `agent/index`
|
|
18
|
+
// import sites keep working.
|
|
19
|
+
export { runAgentSdk } from "../harnesses/opencode-sdk/index.js";
|
|
20
|
+
export { getCommandBuilder } from "./builders.js";
|
|
21
|
+
export { DEFAULT_AGENT_TIMEOUT_MS, listAgentProfileNames, listResolvedAgentProfiles, parseAgentConfig, requireAgentProfile, resolveAgentProfile, resolveDefaultProfileName, resolveProfileFromConfig, } from "./config.js";
|
|
22
|
+
export { defaultWhich, detectAgentCliProfiles, pickDefaultAgentProfile } from "./detect.js";
|
|
23
|
+
export { listBuiltinModelAliases, resolveModel } from "./model-aliases.js";
|
|
24
|
+
export { BUILTIN_AGENT_PROFILE_NAMES, getBuiltinAgentProfile, listBuiltinAgentProfiles, } from "./profiles.js";
|
|
25
|
+
export { buildProposePrompt, buildReflectPrompt, buildSchemaRepairPrompt, extractDraftConfidence, parseAgentProposalPayload, stripJsonFences, } from "./prompts.js";
|
|
26
|
+
export { runAgent } from "./spawn.js";
|
|
@@ -25,8 +25,8 @@
|
|
|
25
25
|
* `frontmatter` is optional — the proposal queue parses it from `content`
|
|
26
26
|
* during validation. We carry it through if the agent supplies it.
|
|
27
27
|
*/
|
|
28
|
-
import { TYPE_DIRS } from "../../core/asset-spec";
|
|
29
|
-
import { parseEmbeddedJsonResponse, stripCodeFences, stripThinkBlocks } from "../../core/parse";
|
|
28
|
+
import { TYPE_DIRS } from "../../core/asset/asset-spec.js";
|
|
29
|
+
import { parseEmbeddedJsonResponse, stripCodeFences, stripThinkBlocks } from "../../core/parse.js";
|
|
30
30
|
/**
|
|
31
31
|
* Per-asset-type frontmatter / authoring hints surfaced in the prompt so
|
|
32
32
|
* the agent can produce content that passes proposal validation. Kept tiny:
|
|
@@ -42,7 +42,6 @@ const TYPE_HINTS = {
|
|
|
42
42
|
workflow: "workflow assets are markdown describing a multi-step process. Include `# <Title>` and ordered `## Step N` sections.",
|
|
43
43
|
script: "script assets are executable text files. Include a shebang and minimal usage comment.",
|
|
44
44
|
env: "env assets are `.env` files holding a group of related CONFIGURATION for an app/service (KEY=VALUE pairs, `#` comments) — URLs, flags, and any credentials it needs. Values may or may not be sensitive; all are protected (key names discoverable, values stay on disk). Inject with `akm env run env:<name> -- <cmd>` (the safe path — values never reach stdout/your context); do NOT run `akm env export` and read its output, as that prints values. For a single sensitive value used on its own for authentication (token, key, cert) use a `secret` instead. Never echo values back to the user.",
|
|
45
|
-
vault: "vault assets are DEPRECATED (use env). They store environment variables (KEY=VALUE pairs); comments use `#`. Never echo secret values back to the user.",
|
|
46
45
|
wiki: "wiki assets are markdown reference pages with `# Title` and structured headings.",
|
|
47
46
|
};
|
|
48
47
|
function hintForType(type) {
|
|
@@ -1,8 +1,27 @@
|
|
|
1
1
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
2
|
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
3
|
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
-
import { ConfigError } from "../../core/errors";
|
|
5
|
-
import { warn } from "../../core/warn";
|
|
4
|
+
import { ConfigError } from "../../core/errors.js";
|
|
5
|
+
import { warn } from "../../core/warn.js";
|
|
6
|
+
// ── RunnerSpec capability predicates (H1) ───────────────────────────────────
|
|
7
|
+
// The `RunnerSpec` union is dispatched ad-hoc across the improve slice. These
|
|
8
|
+
// predicates co-locate the capability questions with the union definition so
|
|
9
|
+
// callers stop hand-inlining `kind !== "llm"` (which couples the call site to
|
|
10
|
+
// the exact shape of the union). They are typed as TypeScript type guards so
|
|
11
|
+
// narrowing flows through to the `connection` / `profile` accessors.
|
|
12
|
+
/** The in-tree LLM HTTP runner (`chatCompletion`); has no filesystem access. */
|
|
13
|
+
export function runnerIsLlm(runner) {
|
|
14
|
+
return runner.kind === "llm";
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Whether this runner can honour the file-write contract. Agent CLI + OpenCode
|
|
18
|
+
* SDK runners both have filesystem access; the direct LLM HTTP runner does NOT
|
|
19
|
+
* (see `src/llm/call-ai.ts`). Equivalent to `!runnerIsLlm(runner)` but names
|
|
20
|
+
* the capability the callers actually care about.
|
|
21
|
+
*/
|
|
22
|
+
export function runnerSupportsFileWrite(runner) {
|
|
23
|
+
return runner.kind !== "llm";
|
|
24
|
+
}
|
|
6
25
|
function resolveEffectiveMode(entry, profileName, config) {
|
|
7
26
|
if (entry.mode)
|
|
8
27
|
return entry.mode;
|
|
@@ -205,4 +224,4 @@ export function getStalenessDetectionThresholdDays(config) {
|
|
|
205
224
|
}
|
|
206
225
|
// Re-export `isProcessEnabled` from feature-gate.ts so callers that previously
|
|
207
226
|
// imported it from runner.ts continue to work.
|
|
208
|
-
export { isProcessEnabled } from "../../llm/feature-gate";
|
|
227
|
+
export { isProcessEnabled } from "../../llm/feature-gate.js";
|
|
@@ -17,8 +17,9 @@
|
|
|
17
17
|
import fs from "node:fs";
|
|
18
18
|
import os from "node:os";
|
|
19
19
|
import path from "node:path";
|
|
20
|
-
import {
|
|
21
|
-
import {
|
|
20
|
+
import { spawn as runtimeSpawn } from "../../runtime.js";
|
|
21
|
+
import { getCommandBuilder } from "./builders.js";
|
|
22
|
+
import { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
|
|
22
23
|
/**
|
|
23
24
|
* Kill the process group of `proc` with `signal`, falling back to
|
|
24
25
|
* `proc.kill(signal)` when `proc.pid` is unavailable (e.g. test fakes).
|
|
@@ -103,12 +104,10 @@ function pathCandidatesForCurrentPlatform(home) {
|
|
|
103
104
|
function resolveSpawnFn(options) {
|
|
104
105
|
if (options.spawn)
|
|
105
106
|
return options.spawn;
|
|
106
|
-
//
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}
|
|
111
|
-
return bun.spawn.bind(bun);
|
|
107
|
+
// Default to the runtime-boundary spawn, which delegates to the native
|
|
108
|
+
// subprocess API on each runtime. Tests inject `options.spawn` to avoid
|
|
109
|
+
// poking real binaries.
|
|
110
|
+
return runtimeSpawn;
|
|
112
111
|
}
|
|
113
112
|
/**
|
|
114
113
|
* Build the child env. Starts empty and copies through:
|
|
@@ -169,7 +168,7 @@ async function readStream(stream, opts) {
|
|
|
169
168
|
*
|
|
170
169
|
* Failure modes (see {@link AgentFailureReason}):
|
|
171
170
|
*
|
|
172
|
-
* • `spawn_failed` —
|
|
171
|
+
* • `spawn_failed` — the spawn call threw synchronously.
|
|
173
172
|
* • `timeout` — exceeded the resolved timeout.
|
|
174
173
|
* • `non_zero_exit` — child exited with a non-zero code.
|
|
175
174
|
* • `parse_error` — `parseOutput === "json"` and stdout was not JSON.
|
|
@@ -233,7 +232,7 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
233
232
|
};
|
|
234
233
|
}
|
|
235
234
|
// Hard timeout. We prefer SIGTERM, then SIGKILL if SIGTERM is ignored,
|
|
236
|
-
// but
|
|
235
|
+
// but the subprocess only exposes a single .kill() — one signal is enough
|
|
237
236
|
// for the structured-failure contract.
|
|
238
237
|
//
|
|
239
238
|
// BUG-M3: only flag `timedOut` when the child has not already exited. A
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Claude Code agent command builder (migrated from `agent/builders.ts`, #563).
|
|
6
|
+
*
|
|
7
|
+
* Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
|
|
8
|
+
* argv the `claude` CLI expects. This is the Claude-specific slice of the
|
|
9
|
+
* builder strategy; the shared infrastructure (`AgentCommandBuilder`,
|
|
10
|
+
* `getCommandBuilder`, the OpenCode/default builders, flag/tool helpers) stays
|
|
11
|
+
* in `agent/builders.ts`, which imports this builder back into
|
|
12
|
+
* `BUILTIN_BUILDERS`.
|
|
13
|
+
*
|
|
14
|
+
* Behaviour-preserving relocation: the produced argv is byte-identical to the
|
|
15
|
+
* pre-migration `claudeBuilder`. The builder's `platform` stays `'claude'` (the
|
|
16
|
+
* canonical harness id).
|
|
17
|
+
*/
|
|
18
|
+
import { assertNotFlag, normalizeTools } from "../../agent/builder-shared.js";
|
|
19
|
+
import { resolveModel } from "../../agent/model-aliases.js";
|
|
20
|
+
/**
|
|
21
|
+
* Claude Code builder.
|
|
22
|
+
* Command shape: claude [--system-prompt "..."] [--model <m>] [--allowedTools <t>] --print "<prompt>"
|
|
23
|
+
*
|
|
24
|
+
* --print switches Claude Code to non-interactive captured output mode.
|
|
25
|
+
*/
|
|
26
|
+
export const claudeBuilder = {
|
|
27
|
+
platform: "claude",
|
|
28
|
+
build(profile, req) {
|
|
29
|
+
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
30
|
+
assertNotFlag(req.model, "model");
|
|
31
|
+
const args = [...profile.args];
|
|
32
|
+
if (req.systemPrompt) {
|
|
33
|
+
args.push("--system-prompt", req.systemPrompt);
|
|
34
|
+
}
|
|
35
|
+
if (req.model) {
|
|
36
|
+
const resolved = resolveModel(req.model, "claude", profile.modelAliases);
|
|
37
|
+
args.push("--model", resolved);
|
|
38
|
+
}
|
|
39
|
+
if (req.tools) {
|
|
40
|
+
args.push("--allowedTools", normalizeTools(req.tools));
|
|
41
|
+
}
|
|
42
|
+
// --print = non-interactive, outputs to stdout — required for captured mode
|
|
43
|
+
args.push("--print");
|
|
44
|
+
args.push("--");
|
|
45
|
+
args.push(req.prompt);
|
|
46
|
+
return { argv: [profile.bin, ...args] };
|
|
47
|
+
},
|
|
48
|
+
};
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Claude Code LLM-config importer (migrated from `setup/harness-config-import.ts`,
|
|
6
|
+
* #563).
|
|
7
|
+
*
|
|
8
|
+
* Detects a Claude Code installation (filesystem only, no network) and reads
|
|
9
|
+
* its config to extract LLM connection details. API key VALUES are never
|
|
10
|
+
* stored — only the env var name that holds them. The pluggable registry
|
|
11
|
+
* (`HARNESS_CONFIG_IMPORTERS`) and the OpenCode importer stay in
|
|
12
|
+
* `setup/harness-config-import.ts`, which imports this importer back.
|
|
13
|
+
*
|
|
14
|
+
* Behaviour-preserving relocation.
|
|
15
|
+
*/
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
function homeDir() {
|
|
19
|
+
return process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Imports LLM config from a Claude Code installation.
|
|
23
|
+
*
|
|
24
|
+
* Claude Code stores settings in `~/.claude/settings.json` or `~/.claude.json`.
|
|
25
|
+
* The model field may appear at the root or under `env.ANTHROPIC_MODEL`.
|
|
26
|
+
* The API key is always `ANTHROPIC_API_KEY`.
|
|
27
|
+
*/
|
|
28
|
+
export const claudeCodeImporter = {
|
|
29
|
+
harnessName: "Claude Code",
|
|
30
|
+
detect() {
|
|
31
|
+
const home = homeDir();
|
|
32
|
+
// Claude Code is installed if the ~/.claude/ directory exists
|
|
33
|
+
return fs.existsSync(path.join(home, ".claude"));
|
|
34
|
+
},
|
|
35
|
+
importConfig() {
|
|
36
|
+
const home = homeDir();
|
|
37
|
+
// Try ~/.claude/settings.json, then ~/.claude.json
|
|
38
|
+
const candidates = [path.join(home, ".claude", "settings.json"), path.join(home, ".claude.json")];
|
|
39
|
+
for (const filePath of candidates) {
|
|
40
|
+
try {
|
|
41
|
+
if (!fs.existsSync(filePath))
|
|
42
|
+
continue;
|
|
43
|
+
const raw = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
44
|
+
// Claude Code settings: model may be at root or nested under env
|
|
45
|
+
const envBlock = raw.env;
|
|
46
|
+
const model = typeof raw.model === "string"
|
|
47
|
+
? raw.model
|
|
48
|
+
: typeof envBlock?.ANTHROPIC_MODEL === "string"
|
|
49
|
+
? String(envBlock.ANTHROPIC_MODEL)
|
|
50
|
+
: undefined;
|
|
51
|
+
return {
|
|
52
|
+
harnessName: "Claude Code",
|
|
53
|
+
provider: "anthropic",
|
|
54
|
+
model: model ?? "claude-sonnet-4-5",
|
|
55
|
+
apiKeyEnvVar: "ANTHROPIC_API_KEY",
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
// try next candidate
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
// ~/.claude exists but no readable settings — still return basic Anthropic config
|
|
63
|
+
return {
|
|
64
|
+
harnessName: "Claude Code",
|
|
65
|
+
provider: "anthropic",
|
|
66
|
+
model: "claude-sonnet-4-5",
|
|
67
|
+
apiKeyEnvVar: "ANTHROPIC_API_KEY",
|
|
68
|
+
};
|
|
69
|
+
},
|
|
70
|
+
};
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Claude Code harness (#563).
|
|
6
|
+
*
|
|
7
|
+
* This is the per-harness barrel that gathers the Claude Code integration
|
|
8
|
+
* surfaces that were previously scattered across the codebase:
|
|
9
|
+
* - session-log reader → ./session-log.ts (ClaudeCodeProvider)
|
|
10
|
+
* - agent command builder → ./agent-builder.ts (claudeBuilder)
|
|
11
|
+
* - config importer → ./config-import.ts (claudeCodeImporter)
|
|
12
|
+
*
|
|
13
|
+
* It also defines {@link ClaudeHarness}, the {@link AkmHarness} descriptor that
|
|
14
|
+
* `HARNESS_REGISTRY` registers.
|
|
15
|
+
*
|
|
16
|
+
* ## id normalization bridge ('claude' vs 'claude-code')
|
|
17
|
+
*
|
|
18
|
+
* The canonical, persisted id is `'claude'` (used by the agent runner, agent
|
|
19
|
+
* profiles, the Zod config schema and `--type` resolution after normalization).
|
|
20
|
+
* `'claude-code'` is the historical RUNTIME identity — the string stamped on
|
|
21
|
+
* session-log events/refs, the extracted-session dedup key, and the value
|
|
22
|
+
* `resolveAgentIdentity` reports. It is registered as an `alias` and exposed as
|
|
23
|
+
* `runtimeId` so BOTH directions round-trip via `normalizeHarnessId()` /
|
|
24
|
+
* `denormalizeRuntimeIdentity()`. Existing persisted configs and session logs
|
|
25
|
+
* that say `'claude-code'` keep working unchanged.
|
|
26
|
+
*/
|
|
27
|
+
import { BaseHarness } from "../types.js";
|
|
28
|
+
export { claudeBuilder } from "./agent-builder.js";
|
|
29
|
+
export { claudeCodeImporter } from "./config-import.js";
|
|
30
|
+
export { ClaudeCodeProvider } from "./session-log.js";
|
|
31
|
+
function caps(c) {
|
|
32
|
+
return {
|
|
33
|
+
sessionLogs: false,
|
|
34
|
+
agentDispatch: false,
|
|
35
|
+
detection: false,
|
|
36
|
+
configImport: false,
|
|
37
|
+
runtimeIdentity: false,
|
|
38
|
+
v1Migration: false,
|
|
39
|
+
...c,
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Claude Code.
|
|
44
|
+
*
|
|
45
|
+
* Canonical id is `'claude'`; `'claude-code'` is the runtime/session-log
|
|
46
|
+
* identity and is registered as an alias so both directions round-trip.
|
|
47
|
+
*/
|
|
48
|
+
export class ClaudeHarness extends BaseHarness {
|
|
49
|
+
id = "claude";
|
|
50
|
+
displayName = "Claude Code";
|
|
51
|
+
aliases = ["claude-code"];
|
|
52
|
+
runtimeId = "claude-code";
|
|
53
|
+
// Home-relative config dir scanned by `akm setup` (#567). Claude Code has a
|
|
54
|
+
// session-log provider, so offering it as a stash source is functional.
|
|
55
|
+
setupDetectionDir = ".claude";
|
|
56
|
+
capabilities = caps({
|
|
57
|
+
sessionLogs: true,
|
|
58
|
+
agentDispatch: true,
|
|
59
|
+
detection: true,
|
|
60
|
+
configImport: true,
|
|
61
|
+
runtimeIdentity: true,
|
|
62
|
+
v1Migration: true,
|
|
63
|
+
});
|
|
64
|
+
}
|
package/dist/integrations/{session-logs/providers/claude-code.js → harnesses/claude/session-log.js}
RENAMED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
import fs from "node:fs";
|
|
5
5
|
import os from "node:os";
|
|
6
6
|
import path from "node:path";
|
|
7
|
-
import { extractInlineRefMentions } from "
|
|
7
|
+
import { extractInlineRefMentions } from "../../session-logs/inline-refs.js";
|
|
8
8
|
const CLAUDE_PROJECTS_DIR = path.join(os.homedir(), ".claude", "projects");
|
|
9
9
|
/**
|
|
10
10
|
* Parse a single Claude Code JSONL event into a normalized {@link SessionEvent}.
|
|
@@ -75,7 +75,22 @@ function parseClaudeEvent(entry, sessionId, filePath, fallbackTsMs) {
|
|
|
75
75
|
filePath,
|
|
76
76
|
};
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Claude Code native session-log reader.
|
|
80
|
+
*
|
|
81
|
+
* id-normalization note (#563): the canonical harness id is `'claude'`, but
|
|
82
|
+
* the provider's `name` — which is STAMPED onto every {@link SessionEvent} /
|
|
83
|
+
* {@link SessionRef} (`harness: this.name`), used as the extracted-session
|
|
84
|
+
* dedup key, and embedded in `session:<harness>:<id>` proposal refs — stays
|
|
85
|
+
* `'claude-code'` (the harness runtimeId). Changing it would silently break
|
|
86
|
+
* round-tripping of already-persisted session-tracking rows and refs. Registry
|
|
87
|
+
* lookups normalize `'claude-code'` → `'claude'` via the #562 bridge
|
|
88
|
+
* (`getHarness`), and the `--type` flag accepts both, so the canonical id and
|
|
89
|
+
* the persisted runtime string coexist without drift.
|
|
90
|
+
*/
|
|
78
91
|
export class ClaudeCodeProvider {
|
|
92
|
+
// Runtime identity (NOT the canonical id) — see class doc. Equals
|
|
93
|
+
// HARNESS_BY_ID.get("claude").runtimeId.
|
|
79
94
|
name = "claude-code";
|
|
80
95
|
isAvailable() {
|
|
81
96
|
return fs.existsSync(CLAUDE_PROJECTS_DIR);
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* Single registration point for every akm agent harness (#562).
|
|
6
|
+
*
|
|
7
|
+
* `HARNESS_REGISTRY` is the ONE source of truth that replaces the three
|
|
8
|
+
* previously-disconnected registries (session-logs index, agent profiles,
|
|
9
|
+
* config/setup platform strings). All derived exports below are computed from
|
|
10
|
+
* it, so adding a harness is a single entry here instead of ~16 scattered edits.
|
|
11
|
+
*
|
|
12
|
+
* This module is a dependency-graph LEAF: it imports nothing from
|
|
13
|
+
* `core/config`. `core/config/config-types.ts` derives `VALID_HARNESS_IDS`
|
|
14
|
+
* from here, which keeps the import direction acyclic (config ← harnesses).
|
|
15
|
+
*
|
|
16
|
+
* Implementations (session-log readers, agent profiles) are migrated under each
|
|
17
|
+
* harness in #563/#564; this step only owns ids + capability membership and
|
|
18
|
+
* wires the existing call sites to consult it (behaviour-preserving).
|
|
19
|
+
*/
|
|
20
|
+
import { ClaudeHarness } from "./claude/index.js";
|
|
21
|
+
import { OpencodeHarness } from "./opencode/index.js";
|
|
22
|
+
import { OpencodeSdkHarness } from "./opencode-sdk/index.js";
|
|
23
|
+
// Each harness descriptor (ClaudeHarness, OpencodeHarness, OpencodeSdkHarness)
|
|
24
|
+
// lives in its own per-harness directory alongside that harness's session-log
|
|
25
|
+
// reader, agent builder, config importer, and/or SDK runner (#563/#564). They
|
|
26
|
+
// are imported above and registered in HARNESS_REGISTRY below.
|
|
27
|
+
/**
|
|
28
|
+
* The single registration point. Add a harness here (and nothing else) to make
|
|
29
|
+
* every derived registry pick it up.
|
|
30
|
+
*
|
|
31
|
+
* Typed `as const` (not `AkmHarness[]`) so each entry keeps its literal `id`,
|
|
32
|
+
* which lets `VALID_HARNESS_IDS` stay a literal tuple — `HarnessId`,
|
|
33
|
+
* `z.enum(...)`, and the `platform` union all need the literal types.
|
|
34
|
+
*/
|
|
35
|
+
// Order is significant: VALID_HARNESS_IDS derives from this array and feeds the
|
|
36
|
+
// committed JSON-schema enum order. Kept as [opencode, claude, opencode-sdk] to
|
|
37
|
+
// match the pre-unification VALID_HARNESS_IDS so the generated schema does not
|
|
38
|
+
// drift (behaviour-preserving, #562).
|
|
39
|
+
export const HARNESS_REGISTRY = Object.freeze([
|
|
40
|
+
new OpencodeHarness(),
|
|
41
|
+
new ClaudeHarness(),
|
|
42
|
+
new OpencodeSdkHarness(),
|
|
43
|
+
]);
|
|
44
|
+
/** Lookup by canonical id. */
|
|
45
|
+
export const HARNESS_BY_ID = new Map(HARNESS_REGISTRY.map((h) => [h.id, h]));
|
|
46
|
+
/**
|
|
47
|
+
* Lookup by canonical id OR any alias OR runtime id — the normalization bridge
|
|
48
|
+
* resolver. Both 'claude' and 'claude-code' map to the Claude harness.
|
|
49
|
+
*/
|
|
50
|
+
const HARNESS_BY_ANY_ID = (() => {
|
|
51
|
+
const m = new Map();
|
|
52
|
+
for (const h of HARNESS_REGISTRY) {
|
|
53
|
+
m.set(h.id, h);
|
|
54
|
+
if (h.runtimeId)
|
|
55
|
+
m.set(h.runtimeId, h);
|
|
56
|
+
for (const a of h.aliases)
|
|
57
|
+
m.set(a, h);
|
|
58
|
+
}
|
|
59
|
+
return m;
|
|
60
|
+
})();
|
|
61
|
+
/**
|
|
62
|
+
* Canonical, ordered list of valid harness / platform ids. The Zod
|
|
63
|
+
* `AgentPlatformSchema` enum, the `AgentProfileConfigV2` platform union,
|
|
64
|
+
* `parseAgentProfilesMapV2`'s membership check, and setup's `DetectedHarness`
|
|
65
|
+
* union all derive from this so they cannot drift.
|
|
66
|
+
*/
|
|
67
|
+
export const VALID_HARNESS_IDS = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
|
|
68
|
+
/** Harnesses that expose readable native session logs. */
|
|
69
|
+
export const SESSION_LOG_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.sessionLogs);
|
|
70
|
+
/** Harnesses that can be dispatched as an agent CLI / SDK. */
|
|
71
|
+
export const AGENT_DISPATCH_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.agentDispatch);
|
|
72
|
+
/** Harnesses that can import an existing harness config into akm. */
|
|
73
|
+
export const CONFIG_IMPORTER_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.configImport);
|
|
74
|
+
/** Harnesses that participate in `akm setup` detection. */
|
|
75
|
+
export const DETECTION_HARNESSES = HARNESS_REGISTRY.filter((h) => h.capabilities.detection);
|
|
76
|
+
/**
|
|
77
|
+
* Resolve any id form (canonical id, alias, or runtime id) to the harness
|
|
78
|
+
* descriptor, or `undefined` if unknown.
|
|
79
|
+
*/
|
|
80
|
+
export function getHarness(id) {
|
|
81
|
+
return HARNESS_BY_ANY_ID.get(id);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* id normalization bridge — alias → canonical.
|
|
85
|
+
*
|
|
86
|
+
* Maps any known alias/runtime id to its canonical persisted id (e.g.
|
|
87
|
+
* 'claude-code' → 'claude'). Unknown ids pass through unchanged so callers can
|
|
88
|
+
* still validate them. This is what keeps existing persisted configs that say
|
|
89
|
+
* 'claude-code' working against the canonical 'claude' registry.
|
|
90
|
+
*/
|
|
91
|
+
export function normalizeHarnessId(id) {
|
|
92
|
+
return HARNESS_BY_ANY_ID.get(id)?.id ?? id;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Resolve a legacy v1 agent-profile name to its v2 platform id (#566).
|
|
96
|
+
*
|
|
97
|
+
* v1 agent profiles never carried an explicit `platform`; it had to be inferred
|
|
98
|
+
* from the profile name. This is the SINGLE registry-backed resolver that
|
|
99
|
+
* replaces both the old standalone `guessAgentPlatform()` in config-migration
|
|
100
|
+
* and the `name.includes("claude") ? "claude" : "opencode"` heuristic in setup.
|
|
101
|
+
* Each harness owns its own `matchesV1ProfileName()`; an unknown name matches no
|
|
102
|
+
* harness and returns `undefined`, so the caller drops it instead of silently
|
|
103
|
+
* defaulting to `'opencode'`.
|
|
104
|
+
*
|
|
105
|
+
* Harnesses are consulted most-specific-id-first (longest id wins) so a
|
|
106
|
+
* decorated name like `"opencode-sdk-fast"` resolves to `'opencode-sdk'` rather
|
|
107
|
+
* than being over-matched by OpenCode's `"opencode"` prefix.
|
|
108
|
+
*/
|
|
109
|
+
const V1_RESOLUTION_ORDER = [...HARNESS_REGISTRY].sort((a, b) => b.id.length - a.id.length);
|
|
110
|
+
export function v1ProfilePlatform(name) {
|
|
111
|
+
for (const h of V1_RESOLUTION_ORDER) {
|
|
112
|
+
if (h.matchesV1ProfileName(name))
|
|
113
|
+
return h.id;
|
|
114
|
+
}
|
|
115
|
+
return undefined;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Default agent-profile name for a detected harness id (#566).
|
|
119
|
+
*
|
|
120
|
+
* Used by `akm setup`'s headless/recommended-config path so a newly added
|
|
121
|
+
* dispatch-capable harness gets a usable default profile name (its canonical
|
|
122
|
+
* id) instead of falling through a hardcoded if-chain with no default. Returns
|
|
123
|
+
* `undefined` for `"none"` or any id that is unknown / not agent-dispatch
|
|
124
|
+
* capable.
|
|
125
|
+
*/
|
|
126
|
+
export function defaultProfileName(detected) {
|
|
127
|
+
const h = HARNESS_BY_ANY_ID.get(detected);
|
|
128
|
+
if (!h?.capabilities.agentDispatch)
|
|
129
|
+
return undefined;
|
|
130
|
+
return h.id;
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* id normalization bridge — canonical → runtime identity.
|
|
134
|
+
*
|
|
135
|
+
* Maps a canonical id to the string a harness reports at runtime / in its
|
|
136
|
+
* session logs (e.g. 'claude' → 'claude-code'). Used by workflow run
|
|
137
|
+
* attribution and the session-logs provider name so the persisted runtime
|
|
138
|
+
* identity stays stable. Falls back to the canonical id when the harness has no
|
|
139
|
+
* distinct runtime identity.
|
|
140
|
+
*/
|
|
141
|
+
export function denormalizeRuntimeIdentity(id) {
|
|
142
|
+
const h = HARNESS_BY_ANY_ID.get(id);
|
|
143
|
+
return h?.runtimeId ?? h?.id ?? id;
|
|
144
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* OpenCode agent command builder (migrated from `agent/builders.ts`, #564).
|
|
6
|
+
*
|
|
7
|
+
* Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
|
|
8
|
+
* argv the `opencode` CLI expects. This is the OpenCode-specific slice of the
|
|
9
|
+
* builder strategy; the shared infrastructure (`AgentCommandBuilder`,
|
|
10
|
+
* `getCommandBuilder`, the default builder, flag/tool helpers) stays in
|
|
11
|
+
* `agent/builders.ts`, which imports this builder back into `BUILTIN_BUILDERS`.
|
|
12
|
+
*
|
|
13
|
+
* Behaviour-preserving relocation: the produced argv is byte-identical to the
|
|
14
|
+
* pre-migration `opencodeBuilder`. The builder's `platform` stays `'opencode'`
|
|
15
|
+
* (the canonical harness id).
|
|
16
|
+
*/
|
|
17
|
+
import { assertNotFlag } from "../../agent/builder-shared.js";
|
|
18
|
+
import { resolveModel } from "../../agent/model-aliases.js";
|
|
19
|
+
/**
|
|
20
|
+
* OpenCode builder.
|
|
21
|
+
* Command shape: opencode run [--system-prompt "..."] [--model <m>] "<prompt>"
|
|
22
|
+
*
|
|
23
|
+
* Tool policy is omitted — opencode manages tool access through its own agent
|
|
24
|
+
* config files, not via CLI flags.
|
|
25
|
+
*/
|
|
26
|
+
export const opencodeBuilder = {
|
|
27
|
+
platform: "opencode",
|
|
28
|
+
build(profile, req) {
|
|
29
|
+
assertNotFlag(req.systemPrompt, "systemPrompt");
|
|
30
|
+
assertNotFlag(req.model, "model");
|
|
31
|
+
const args = [...profile.args]; // starts with ["run"]
|
|
32
|
+
if (req.systemPrompt) {
|
|
33
|
+
args.push("--system-prompt", req.systemPrompt);
|
|
34
|
+
}
|
|
35
|
+
if (req.model) {
|
|
36
|
+
const resolved = resolveModel(req.model, "opencode", profile.modelAliases);
|
|
37
|
+
args.push("--model", resolved);
|
|
38
|
+
}
|
|
39
|
+
args.push("--");
|
|
40
|
+
args.push(req.prompt);
|
|
41
|
+
return { argv: [profile.bin, ...args] };
|
|
42
|
+
},
|
|
43
|
+
};
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
2
|
+
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
3
|
+
// file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
4
|
+
/**
|
|
5
|
+
* OpenCode LLM-config importer (migrated from `setup/harness-config-import.ts`,
|
|
6
|
+
* #564).
|
|
7
|
+
*
|
|
8
|
+
* Detects an OpenCode installation (filesystem only, no network) and reads its
|
|
9
|
+
* config to extract LLM connection details. API key VALUES are never stored —
|
|
10
|
+
* only the env var name that holds them. The pluggable registry
|
|
11
|
+
* (`HARNESS_CONFIG_IMPORTERS`) and the Claude importer stay in their respective
|
|
12
|
+
* modules; `setup/harness-config-import.ts` imports this importer back.
|
|
13
|
+
*
|
|
14
|
+
* Behaviour-preserving relocation.
|
|
15
|
+
*/
|
|
16
|
+
import fs from "node:fs";
|
|
17
|
+
import path from "node:path";
|
|
18
|
+
function homeDir() {
|
|
19
|
+
return process.env.HOME ?? process.env.USERPROFILE ?? "";
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Imports LLM config from an OpenCode installation.
|
|
23
|
+
*
|
|
24
|
+
* OpenCode stores config in `~/.config/opencode/config.json` or
|
|
25
|
+
* `~/.opencode/config.json`. Its schema has a `providers` array and a
|
|
26
|
+
* `model` field. API keys in providers appear as `$ENV_VAR_NAME` references.
|
|
27
|
+
*/
|
|
28
|
+
export const openCodeImporter = {
|
|
29
|
+
harnessName: "OpenCode",
|
|
30
|
+
detect() {
|
|
31
|
+
const home = homeDir();
|
|
32
|
+
return fs.existsSync(path.join(home, ".config", "opencode")) || fs.existsSync(path.join(home, ".opencode"));
|
|
33
|
+
},
|
|
34
|
+
importConfig() {
|
|
35
|
+
const home = homeDir();
|
|
36
|
+
const candidates = [
|
|
37
|
+
path.join(home, ".config", "opencode", "config.json"),
|
|
38
|
+
path.join(home, ".opencode", "config.json"),
|
|
39
|
+
path.join(process.cwd(), ".opencode", "config.json"),
|
|
40
|
+
];
|
|
41
|
+
for (const filePath of candidates) {
|
|
42
|
+
try {
|
|
43
|
+
if (!fs.existsSync(filePath))
|
|
44
|
+
continue;
|
|
45
|
+
const raw = JSON.parse(fs.readFileSync(filePath, "utf8"));
|
|
46
|
+
// OpenCode config shape: { model?: string, providers?: Array<{id, apiKey, baseUrl, ...}> }
|
|
47
|
+
const model = typeof raw.model === "string" ? raw.model : undefined;
|
|
48
|
+
// Extract provider info from the first entry in the providers array
|
|
49
|
+
let provider;
|
|
50
|
+
let baseUrl;
|
|
51
|
+
let apiKeyEnvVar;
|
|
52
|
+
const providers = Array.isArray(raw.providers) ? raw.providers : [];
|
|
53
|
+
if (providers.length > 0) {
|
|
54
|
+
const first = providers[0];
|
|
55
|
+
provider = typeof first?.id === "string" ? first.id : undefined;
|
|
56
|
+
baseUrl =
|
|
57
|
+
typeof first?.baseUrl === "string"
|
|
58
|
+
? first.baseUrl
|
|
59
|
+
: typeof first?.base_url === "string"
|
|
60
|
+
? first.base_url
|
|
61
|
+
: undefined;
|
|
62
|
+
// apiKey is an env var reference like "$OPENAI_API_KEY" — extract the var name
|
|
63
|
+
const apiKeyVal = typeof first?.apiKey === "string" ? first.apiKey : "";
|
|
64
|
+
if (apiKeyVal.startsWith("$")) {
|
|
65
|
+
apiKeyEnvVar = apiKeyVal.slice(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
harnessName: "OpenCode",
|
|
70
|
+
provider,
|
|
71
|
+
model,
|
|
72
|
+
baseUrl,
|
|
73
|
+
apiKeyEnvVar,
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
catch {
|
|
77
|
+
// try next candidate
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
},
|
|
82
|
+
};
|