akm-cli 0.9.0-beta.9 → 0.9.0-rc.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 +592 -0
- package/README.md +12 -4
- package/dist/akm +38 -0
- package/dist/akm-migrate-storage +38 -0
- package/dist/assets/help/help-improve.md +9 -6
- package/dist/assets/hints/cli-hints-full.md +6 -5
- package/dist/assets/profiles/default.json +9 -4
- package/dist/assets/profiles/frequent.json +1 -1
- package/dist/assets/profiles/memory-focus.json +1 -1
- package/dist/assets/profiles/proactive-maintenance.json +25 -0
- package/dist/assets/profiles/quick.json +1 -1
- package/dist/assets/profiles/recombine-only.json +21 -0
- package/dist/assets/profiles/reflect-distill.json +30 -0
- package/dist/assets/profiles/synthesize.json +15 -0
- package/dist/assets/profiles/thorough.json +1 -1
- package/dist/assets/prompts/consolidate-system.md +23 -0
- package/dist/assets/prompts/contradiction-judge.md +33 -0
- package/dist/assets/prompts/distill-knowledge-system.md +22 -0
- package/dist/assets/prompts/distill-lesson-system.md +36 -0
- package/dist/assets/prompts/extract-session.md +11 -3
- package/dist/assets/prompts/graph-extract-system.md +1 -0
- package/dist/assets/prompts/graph-extract-user-prompt.md +1 -1
- package/dist/assets/prompts/memory-infer-system.md +1 -0
- package/dist/assets/prompts/memory-infer-user.md +5 -0
- package/dist/assets/prompts/metadata-enhance-system.md +1 -0
- package/dist/assets/prompts/procedural-system.md +44 -0
- package/dist/assets/prompts/recombine-system.md +40 -0
- package/dist/assets/prompts/staleness-detect-system.md +6 -0
- package/dist/assets/prompts/validate-summary-judge.md +1 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/agent.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/command.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/fact.md +39 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/knowledge.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/lesson.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/memory.md +38 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/script.md +43 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/skill.md +40 -0
- package/dist/assets/stash-skeleton/facts/conventions/assets/workflow.md +43 -0
- package/dist/assets/templates/html/health.html +281 -111
- package/dist/assets/wiki/ingest-workflow-template.md +45 -16
- package/dist/assets/wiki/schema-template.md +4 -4
- package/dist/cli/clack.js +56 -0
- package/dist/cli/config-migrate.js +7 -1
- package/dist/cli/confirm.js +1 -1
- package/dist/cli/parse-args.js +46 -1
- package/dist/cli/shared.js +28 -0
- package/dist/cli.js +25 -21
- package/dist/commands/agent/agent-dispatch.js +3 -2
- package/dist/commands/agent/agent-support.js +0 -7
- package/dist/commands/agent/contribute-cli.js +26 -7
- package/dist/commands/config-cli.js +26 -13
- package/dist/commands/env/child-env.js +47 -0
- package/dist/commands/env/env-cli.js +220 -227
- package/dist/commands/env/env.js +14 -67
- package/dist/commands/env/secret-cli.js +140 -138
- package/dist/commands/feedback-cli.js +156 -155
- package/dist/commands/graph/graph-cli.js +5 -13
- package/dist/commands/graph/graph.js +3 -3
- package/dist/commands/health/advisories.js +151 -0
- package/dist/commands/health/checks.js +103 -16
- package/dist/commands/health/html-report.js +447 -81
- package/dist/commands/health/improve-metrics.js +771 -0
- package/dist/commands/health/llm-usage.js +65 -0
- package/dist/commands/health/md-report.js +103 -0
- package/dist/commands/health/metrics.js +278 -0
- package/dist/commands/health/stash-exposure.js +46 -0
- package/dist/commands/health/surfaces.js +216 -0
- package/dist/commands/health/task-runs.js +135 -0
- package/dist/commands/health/types.js +26 -0
- package/dist/commands/health/windows.js +195 -0
- package/dist/commands/health.js +91 -1091
- package/dist/commands/improve/anti-collapse.js +170 -0
- package/dist/commands/improve/calibration.js +161 -0
- package/dist/commands/improve/collapse-detector.js +421 -0
- package/dist/commands/improve/consolidate/chunking.js +141 -0
- package/dist/commands/improve/consolidate/eligibility.js +64 -0
- package/dist/commands/improve/consolidate/merge.js +145 -0
- package/dist/commands/improve/consolidate/sanitize.js +231 -0
- package/dist/commands/{lint.js → improve/consolidate/types.js} +1 -1
- package/dist/commands/improve/consolidate.js +1295 -1277
- package/dist/commands/improve/dedup.js +482 -0
- package/dist/commands/improve/distill/content-repair.js +202 -0
- package/dist/commands/improve/distill/promote-memory.js +229 -0
- package/dist/commands/improve/distill/quality-gate.js +236 -0
- package/dist/commands/improve/distill-guards.js +127 -0
- package/dist/commands/improve/distill-promotion-policy.js +826 -167
- package/dist/commands/improve/distill.js +228 -605
- package/dist/commands/improve/eligibility.js +434 -0
- package/dist/commands/improve/encoding-salience.js +205 -0
- package/dist/commands/improve/extract-cli.js +179 -59
- package/dist/commands/improve/extract-prompt.js +54 -3
- package/dist/commands/improve/extract-watch.js +140 -0
- package/dist/commands/improve/extract.js +409 -43
- package/dist/commands/improve/feedback-valence.js +54 -0
- package/dist/commands/improve/hot-probation.js +45 -0
- package/dist/commands/improve/improve-auto-accept.js +157 -10
- package/dist/commands/improve/improve-cli.js +115 -73
- package/dist/commands/improve/improve-profiles.js +28 -8
- package/dist/commands/improve/improve-result-file.js +15 -25
- package/dist/commands/improve/improve-session.js +58 -0
- package/dist/commands/improve/improve.js +485 -2764
- package/dist/commands/improve/locks.js +154 -0
- package/dist/commands/improve/loop-stages.js +1100 -0
- package/dist/commands/improve/memory/memory-belief.js +14 -15
- package/dist/commands/improve/memory/memory-contradiction-detect.js +83 -60
- package/dist/commands/improve/memory/memory-improve.js +27 -27
- package/dist/commands/improve/outcome-loop.js +270 -0
- package/dist/commands/improve/preparation.js +2002 -0
- package/dist/commands/improve/proactive-maintenance.js +37 -35
- package/dist/commands/improve/procedural.js +398 -0
- package/dist/commands/improve/recombine.js +818 -0
- package/dist/commands/improve/reflect-noise.js +0 -0
- package/dist/commands/improve/reflect.js +206 -45
- package/dist/commands/improve/salience.js +455 -0
- package/dist/commands/improve/schema-similarity-gate.js +168 -0
- package/dist/commands/improve/shared.js +51 -0
- package/dist/commands/improve/triage.js +93 -0
- package/dist/commands/lint/agent-linter.js +19 -24
- package/dist/commands/lint/base-linter.js +173 -60
- package/dist/commands/lint/command-linter.js +19 -24
- package/dist/commands/lint/env-key-rules.js +38 -1
- package/dist/commands/lint/fact-linter.js +39 -0
- package/dist/commands/lint/index.js +31 -13
- package/dist/commands/lint/memory-linter.js +1 -1
- package/dist/commands/lint/registry.js +7 -2
- package/dist/commands/lint/task-linter.js +3 -3
- package/dist/commands/lint/workflow-linter.js +26 -1
- package/dist/commands/observability-cli.js +4 -4
- package/dist/commands/proposal/drain-policies.js +13 -4
- package/dist/commands/proposal/drain.js +45 -51
- package/dist/commands/proposal/legacy-import.js +115 -0
- package/dist/commands/proposal/proposal-cli.js +24 -34
- package/dist/commands/proposal/proposal.js +2 -1
- package/dist/commands/proposal/propose.js +8 -3
- package/dist/commands/proposal/repository.js +829 -0
- package/dist/commands/proposal/validators/proposal-quality-validators.js +9 -8
- package/dist/commands/proposal/validators/proposals.js +93 -895
- package/dist/commands/read/curate.js +410 -111
- package/dist/commands/read/knowledge.js +10 -3
- package/dist/commands/read/remember-cli.js +133 -138
- package/dist/commands/read/search-cli.js +15 -8
- package/dist/commands/read/search.js +22 -11
- package/dist/commands/read/show.js +106 -14
- package/dist/commands/registry-cli.js +76 -87
- package/dist/commands/remember.js +11 -12
- package/dist/commands/sources/add-cli.js +91 -95
- package/dist/commands/sources/history.js +1 -1
- package/dist/commands/sources/init.js +66 -18
- package/dist/commands/sources/installed-stashes.js +11 -3
- package/dist/commands/sources/schema-repair.js +44 -46
- package/dist/commands/sources/self-update.js +2 -2
- package/dist/commands/sources/source-add.js +7 -3
- package/dist/commands/sources/sources-cli.js +3 -3
- package/dist/commands/sources/stash-cli.js +19 -39
- package/dist/commands/sources/stash-skeleton.js +57 -8
- package/dist/commands/tasks/default-tasks.js +15 -2
- package/dist/commands/tasks/tasks-cli.js +20 -29
- package/dist/commands/tasks/tasks.js +39 -11
- package/dist/commands/wiki-cli.js +23 -38
- package/dist/commands/workflow-cli.js +15 -1
- package/dist/core/asset/asset-registry.js +3 -1
- package/dist/core/asset/asset-spec.js +21 -4
- package/dist/core/asset/frontmatter.js +188 -167
- package/dist/core/asset/markdown.js +8 -0
- package/dist/core/authoring-rules.js +92 -0
- package/dist/core/common.js +4 -23
- package/dist/core/concurrent.js +10 -1
- package/dist/core/config/config-io.js +10 -1
- package/dist/core/config/config-migration.js +18 -40
- package/dist/core/config/config-schema.js +382 -62
- package/dist/core/config/config-types.js +3 -3
- package/dist/core/config/config.js +67 -22
- package/dist/core/deep-merge.js +38 -0
- package/dist/core/errors.js +1 -0
- package/dist/core/eval/rank-metrics.js +113 -0
- package/dist/core/events.js +4 -7
- package/dist/core/improve-types.js +47 -8
- package/dist/core/logs-db.js +14 -75
- package/dist/core/parse.js +36 -16
- package/dist/core/paths.js +18 -18
- package/dist/core/standards/resolve-standards-context.js +87 -0
- package/dist/core/standards/resolve-stash-standards.js +99 -0
- package/dist/core/standards/resolve-type-conventions.js +66 -0
- package/dist/core/state/migrations.js +770 -0
- package/dist/core/state-db.js +132 -1126
- package/dist/core/structured.js +69 -0
- package/dist/core/time.js +53 -0
- package/dist/core/warn.js +21 -0
- package/dist/core/write-source.js +37 -0
- package/dist/indexer/db/db.js +259 -769
- package/dist/indexer/db/entry-mapper.js +41 -0
- package/dist/indexer/db/graph-db.js +129 -86
- package/dist/indexer/db/llm-cache.js +2 -2
- package/dist/indexer/db/schema.js +516 -0
- package/dist/indexer/ensure-index.js +36 -92
- package/dist/indexer/feedback/utility-policy.js +75 -0
- package/dist/indexer/graph/graph-boost.js +51 -41
- package/dist/indexer/graph/graph-extraction.js +207 -4
- package/dist/indexer/index-writer-lock.js +18 -11
- package/dist/indexer/index-written-assets.js +105 -0
- package/dist/indexer/indexer.js +182 -204
- package/dist/indexer/passes/dir-staleness.js +114 -0
- package/dist/indexer/passes/memory-inference.js +13 -5
- package/dist/indexer/passes/metadata.js +20 -0
- package/dist/indexer/read-preflight.js +23 -0
- package/dist/indexer/search/db-search.js +89 -13
- package/dist/indexer/search/fts-query.js +51 -0
- package/dist/indexer/search/ranking-contributors.js +95 -9
- package/dist/indexer/search/ranking.js +79 -3
- package/dist/indexer/search/search-fields.js +6 -0
- package/dist/indexer/search/search-source.js +32 -21
- package/dist/indexer/search/semantic-status.js +4 -0
- package/dist/indexer/walk/matchers.js +9 -0
- package/dist/indexer/walk/walker.js +21 -13
- package/dist/integrations/agent/builders.js +39 -13
- package/dist/integrations/agent/config.js +20 -59
- package/dist/integrations/agent/detect.js +9 -0
- package/dist/integrations/agent/index.js +3 -19
- package/dist/integrations/agent/model-aliases.js +7 -2
- package/dist/integrations/agent/profiles.js +7 -1
- package/dist/integrations/agent/prompts.js +75 -9
- package/dist/integrations/agent/runner-dispatch.js +59 -0
- package/dist/integrations/agent/runner.js +13 -9
- package/dist/integrations/agent/spawn.js +69 -67
- package/dist/integrations/harnesses/claude/agent-builder.js +1 -1
- package/dist/integrations/harnesses/claude/index.js +2 -0
- package/dist/integrations/harnesses/claude/session-log.js +10 -0
- package/dist/integrations/harnesses/index.js +2 -3
- package/dist/integrations/harnesses/opencode/agent-builder.js +1 -1
- package/dist/integrations/harnesses/opencode/index.js +2 -0
- package/dist/integrations/harnesses/opencode/session-log.js +173 -3
- package/dist/integrations/harnesses/opencode-sdk/index.js +2 -2
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +98 -17
- package/dist/integrations/harnesses/types.js +1 -0
- package/dist/integrations/session-logs/index.js +16 -0
- package/dist/llm/call-ai.js +2 -2
- package/dist/llm/client.js +34 -11
- package/dist/llm/embedder.js +67 -4
- package/dist/llm/embedders/cache.js +3 -1
- package/dist/llm/embedders/deterministic.js +66 -0
- package/dist/llm/embedders/local.js +73 -3
- package/dist/llm/feature-gate.js +16 -15
- package/dist/llm/graph-extract.js +67 -44
- package/dist/llm/memory-infer-impl.js +138 -0
- package/dist/llm/memory-infer.js +1 -127
- package/dist/llm/metadata-enhance.js +44 -31
- package/dist/llm/structured-call.js +49 -0
- package/dist/migrate-storage-node.mjs +8 -0
- package/dist/output/context.js +5 -5
- package/dist/output/renderers.js +85 -14
- package/dist/output/shapes/curate.js +14 -2
- package/dist/output/shapes/helpers.js +0 -3
- package/dist/output/shapes/passthrough.js +2 -1
- package/dist/output/text/helpers.js +29 -1
- package/dist/output/text/workflow.js +1 -0
- package/dist/registry/providers/skills-sh.js +21 -147
- package/dist/registry/providers/static-index.js +15 -157
- package/dist/registry/resolve.js +27 -9
- package/dist/runtime.js +25 -1
- package/dist/scripts/migrate-storage.js +2661 -2369
- package/dist/scripts/migrations/import-fs-improve-runs-to-db.js +883 -596
- package/dist/setup/detect.js +9 -0
- package/dist/setup/legacy-config.js +106 -0
- package/dist/setup/prompt.js +57 -0
- package/dist/setup/providers.js +14 -0
- package/dist/setup/registry-stash-loader.js +12 -0
- package/dist/setup/semantic-assets.js +124 -0
- package/dist/setup/setup.js +52 -1614
- package/dist/setup/steps/connection.js +734 -0
- package/dist/setup/steps/output.js +31 -0
- package/dist/setup/steps/platforms.js +124 -0
- package/dist/setup/steps/semantic.js +27 -0
- package/dist/setup/steps/sources.js +222 -0
- package/dist/setup/steps/stashdir.js +42 -0
- package/dist/setup/steps/tasks.js +152 -0
- package/dist/sources/include.js +6 -2
- package/dist/sources/providers/filesystem.js +0 -1
- package/dist/sources/providers/git-install.js +210 -0
- package/dist/sources/providers/git-provider.js +234 -0
- package/dist/sources/providers/git-stash.js +248 -0
- package/dist/sources/providers/git.js +10 -661
- package/dist/sources/providers/npm.js +2 -6
- package/dist/sources/providers/provider-utils.js +13 -7
- package/dist/sources/providers/sync-from-ref.js +9 -1
- package/dist/sources/providers/website.js +9 -5
- package/dist/sources/website-ingest.js +187 -29
- package/dist/sources/wiki-fetchers/registry.js +53 -0
- package/dist/sources/wiki-fetchers/youtube.js +239 -0
- package/dist/storage/database.js +45 -10
- package/dist/storage/managed-db.js +82 -0
- package/dist/storage/repositories/canaries-repository.js +107 -0
- package/dist/storage/repositories/consolidation-repository.js +38 -0
- package/dist/storage/repositories/embeddings-repository.js +72 -0
- package/dist/storage/repositories/events-repository.js +187 -0
- package/dist/storage/repositories/extract-sessions-repository.js +96 -0
- package/dist/storage/repositories/improve-runs-repository.js +146 -0
- package/dist/storage/repositories/index-db.js +14 -8
- package/dist/storage/repositories/proposals-repository.js +220 -0
- package/dist/storage/repositories/recombine-repository.js +213 -0
- package/dist/storage/repositories/registry-cache.js +93 -0
- package/dist/storage/repositories/registry-index-cache-repository.js +46 -0
- package/dist/storage/repositories/task-history-repository.js +93 -0
- package/dist/storage/sqlite-pragmas.js +146 -0
- package/dist/tasks/backends/cron.js +1 -1
- package/dist/tasks/backends/index.js +9 -0
- package/dist/tasks/backends/launchd.js +1 -1
- package/dist/tasks/backends/schtasks.js +1 -1
- package/dist/tasks/{resolveAkmBin.js → resolve-akm-bin.js} +2 -2
- package/dist/tasks/runner.js +15 -13
- package/dist/text-import-hook.mjs +0 -0
- package/dist/wiki/wiki.js +52 -11
- package/dist/workflows/cli.js +1 -0
- package/dist/workflows/db.js +3 -4
- package/dist/workflows/runtime/runs.js +43 -118
- package/dist/workflows/runtime/workflow-asset-loader.js +125 -0
- package/dist/workflows/validate-summary.js +2 -7
- package/docs/README.md +69 -18
- package/docs/data-and-telemetry.md +5 -4
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +39 -0
- package/package.json +10 -10
- package/dist/assets/tasks/core/update-stashes.yml +0 -4
- package/dist/commands/db-cli.js +0 -23
- package/dist/indexer/db/db-backup.js +0 -376
- package/dist/indexer/passes/staleness-detect.js +0 -488
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
* during validation. We carry it through if the agent supplies it.
|
|
27
27
|
*/
|
|
28
28
|
import { TYPE_DIRS } from "../../core/asset/asset-spec.js";
|
|
29
|
+
import { authoringRulesForType, DESCRIPTION_MAX_CHARS, DESCRIPTION_MIN_CHARS, requiresDescription, } from "../../core/authoring-rules.js";
|
|
29
30
|
import { parseEmbeddedJsonResponse, stripCodeFences, stripThinkBlocks } from "../../core/parse.js";
|
|
30
31
|
/**
|
|
31
32
|
* Per-asset-type frontmatter / authoring hints surfaced in the prompt so
|
|
@@ -41,8 +42,9 @@ const TYPE_HINTS = {
|
|
|
41
42
|
memory: "memory assets are short factual notes the user wants persisted across sessions. Frontmatter usually includes `description`.",
|
|
42
43
|
workflow: "workflow assets are markdown describing a multi-step process. Include `# <Title>` and ordered `## Step N` sections.",
|
|
43
44
|
script: "script assets are executable text files. Include a shebang and minimal usage comment.",
|
|
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
|
|
45
|
+
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>`; prefer `--clean` in agent contexts so the child starts from a minimal inherited environment. AKM itself does not print values, but the child command can print its environment, so do not run `env`, `printenv`, shell tracing, or similar diagnostics when secrets are in scope. 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
46
|
wiki: "wiki assets are markdown reference pages with `# Title` and structured headings.",
|
|
47
|
+
fact: "fact assets are durable stash-level facts (personal/team/project details, coding conventions, stash-meta). Frontmatter SHOULD include `description` and a `category` (personal|team|project|convention|meta); set `pinned: true` only for the small always-injected core. Keep each fact short, high-signal, and self-contained — it is durable context, not an episodic note.",
|
|
46
48
|
};
|
|
47
49
|
function hintForType(type) {
|
|
48
50
|
return TYPE_HINTS[type] ?? `assets of type "${type}" — produce sensible markdown with optional frontmatter.`;
|
|
@@ -109,6 +111,30 @@ export function extractDraftConfidence(stdout) {
|
|
|
109
111
|
return undefined;
|
|
110
112
|
return value;
|
|
111
113
|
}
|
|
114
|
+
/**
|
|
115
|
+
* Whether the source asset content has a non-empty `description:` key in its
|
|
116
|
+
* YAML frontmatter. Used by {@link buildReflectPrompt} (#636) to decide whether
|
|
117
|
+
* to inject the synthesize-a-description instruction. Uses an inline regex to
|
|
118
|
+
* avoid pulling the full YAML parser into the prompt module (mirrors the
|
|
119
|
+
* existing inline frontmatter handling here).
|
|
120
|
+
*/
|
|
121
|
+
function sourceHasNonEmptyDescription(assetContent) {
|
|
122
|
+
if (!assetContent)
|
|
123
|
+
return false;
|
|
124
|
+
const fmMatch = assetContent.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
125
|
+
if (!fmMatch)
|
|
126
|
+
return false;
|
|
127
|
+
const fmBlock = fmMatch[1] ?? "";
|
|
128
|
+
// Match a top-level `description:` line and capture its inline value.
|
|
129
|
+
const descMatch = fmBlock.match(/^description\s*:\s*(.*)$/m);
|
|
130
|
+
if (!descMatch)
|
|
131
|
+
return false;
|
|
132
|
+
const value = (descMatch[1] ?? "")
|
|
133
|
+
.trim()
|
|
134
|
+
.replace(/^['"]|['"]$/g, "")
|
|
135
|
+
.trim();
|
|
136
|
+
return value.length > 0;
|
|
137
|
+
}
|
|
112
138
|
/**
|
|
113
139
|
* Build the prompt for `akm reflect [ref]`. Asks the agent to review an
|
|
114
140
|
* existing asset (plus any negative feedback / lint findings) and propose
|
|
@@ -155,6 +181,34 @@ export function buildReflectPrompt(input) {
|
|
|
155
181
|
// ref is set but no feedback — explicitly constrain scope to schema compliance
|
|
156
182
|
sections.push("No usage feedback recorded. Limit your proposal to schema and structural improvements only: missing required frontmatter fields, unclear `when_to_use`, ambiguous description, or broken formatting. Do not speculate about runtime weaknesses you have not observed.");
|
|
157
183
|
}
|
|
184
|
+
if (input.standardsContext?.trim()) {
|
|
185
|
+
sections.push("Standards to follow (the rulebook for this target):");
|
|
186
|
+
sections.push(input.standardsContext.trim());
|
|
187
|
+
}
|
|
188
|
+
{
|
|
189
|
+
const resolvedType = input.type ?? (input.ref?.includes(":") ? input.ref.split(":")[0] : "");
|
|
190
|
+
const authoringRules = resolvedType ? authoringRulesForType(resolvedType) : "";
|
|
191
|
+
if (authoringRules) {
|
|
192
|
+
sections.push(authoringRules);
|
|
193
|
+
}
|
|
194
|
+
// #636 — synthesize-a-description instruction. Many source assets (notably
|
|
195
|
+
// scraped docs: `source`/`title`/`scraped`) carry frontmatter but NO
|
|
196
|
+
// `description`. Reflect echoes the source frontmatter, so the proposal
|
|
197
|
+
// inherits the missing description and the promote-time validator
|
|
198
|
+
// (isValidDescription, 20–400 chars) rejects it. The fix is at GENERATION
|
|
199
|
+
// time: when the source lacks a non-empty `description` and the type
|
|
200
|
+
// requires one, tell the model — unmissably — that it MUST author a valid
|
|
201
|
+
// `description`. (The validator/promote path is NOT changed: it must never
|
|
202
|
+
// fabricate content to pass itself.)
|
|
203
|
+
if (resolvedType && requiresDescription(resolvedType) && !sourceHasNonEmptyDescription(input.assetContent)) {
|
|
204
|
+
sections.push([
|
|
205
|
+
"REQUIRED — synthesize a `description` (the source asset has none):",
|
|
206
|
+
`- The source frontmatter does NOT include a non-empty \`description\`, but a ${resolvedType} asset REQUIRES one or the proposal will be rejected at promote time.`,
|
|
207
|
+
`- You MUST author a valid \`description\` in the proposal frontmatter: ${DESCRIPTION_MIN_CHARS}–${DESCRIPTION_MAX_CHARS} characters of plain-prose sentence summarizing what this asset is about.`,
|
|
208
|
+
'- Synthesize it from the asset\'s `title:` frontmatter, its first `# Heading`, or the opening body sentence. Do NOT copy a bare heading fragment (e.g. "Overview", "Named Page", "Key Insight") and do NOT emit a truncated phrase that ends on `:`/`;`/`,` or a hanging connector word.',
|
|
209
|
+
].join("\n"));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
158
212
|
if (input.assetContent?.trim()) {
|
|
159
213
|
// Cap at 12 000 chars to stay well under OS ARG_MAX when the prompt is
|
|
160
214
|
// passed as a CLI argument to opencode/claude. Large assets (wiki snapshots,
|
|
@@ -288,6 +342,16 @@ export function buildProposePrompt(input) {
|
|
|
288
342
|
for (const line of input.schemaHints)
|
|
289
343
|
sections.push(`- ${line}`);
|
|
290
344
|
}
|
|
345
|
+
if (input.standardsContext?.trim()) {
|
|
346
|
+
sections.push("Standards to follow (the rulebook for this target):");
|
|
347
|
+
sections.push(input.standardsContext.trim());
|
|
348
|
+
}
|
|
349
|
+
{
|
|
350
|
+
const authoringRules = authoringRulesForType(input.type);
|
|
351
|
+
if (authoringRules) {
|
|
352
|
+
sections.push(authoringRules);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
291
355
|
sections.push("Produce a single proposal that, if accepted, would land as the asset described above.");
|
|
292
356
|
sections.push(input.draftFilePath ? fileWriteContract(input.draftFilePath) : RESPONSE_CONTRACT_JSON);
|
|
293
357
|
return sections.join("\n\n");
|
|
@@ -304,6 +368,16 @@ export function buildSchemaRepairPrompt(input) {
|
|
|
304
368
|
`while preserving all existing content.`);
|
|
305
369
|
sections.push(`Target ref: ${input.ref}`);
|
|
306
370
|
sections.push(`Schema requirements for ${input.type} assets: ${hintForType(input.type)}`);
|
|
371
|
+
if (input.standardsContext?.trim()) {
|
|
372
|
+
sections.push("Standards to follow (the rulebook for this target):");
|
|
373
|
+
sections.push(input.standardsContext.trim());
|
|
374
|
+
}
|
|
375
|
+
{
|
|
376
|
+
const authoringRules = authoringRulesForType(input.type);
|
|
377
|
+
if (authoringRules) {
|
|
378
|
+
sections.push(authoringRules);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
307
381
|
const CONTENT_CAP = 3000;
|
|
308
382
|
const body = input.assetContent.trimEnd();
|
|
309
383
|
const truncated = body.length > CONTENT_CAP;
|
|
@@ -370,11 +444,3 @@ export function parseAgentProposalPayload(stdout) {
|
|
|
370
444
|
}
|
|
371
445
|
return out;
|
|
372
446
|
}
|
|
373
|
-
/**
|
|
374
|
-
* Strip `\`\`\`json … \`\`\`` fences and `<think>…</think>` reasoning blocks
|
|
375
|
-
* from agent output. Thin wrapper around `core/parse` helpers, kept exported
|
|
376
|
-
* for backward compatibility (re-exported from `integrations/agent/index.ts`).
|
|
377
|
-
*/
|
|
378
|
-
export function stripJsonFences(text) {
|
|
379
|
-
return stripCodeFences(stripThinkBlocks(text));
|
|
380
|
-
}
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
* X3 — the ONE dispatch seam for the {@link RunnerSpec} tagged union.
|
|
6
|
+
*
|
|
7
|
+
* The improve slice dispatches a `RunnerSpec` (`llm | agent | sdk`) in several
|
|
8
|
+
* places (`reflect.ts`, `proposal/drain.ts`, …). Before this module each site
|
|
9
|
+
* re-rolled the identical 3-arm switch and re-declared its own per-kind test
|
|
10
|
+
* seams (`chat`, `runAgentFn`, `runSdkFn`). `executeRunner` collapses that into
|
|
11
|
+
* one switch + one {@link RunnerSeams} object.
|
|
12
|
+
*
|
|
13
|
+
* Scoping (behavior-preserving):
|
|
14
|
+
* - The `agent` and `sdk` arms are byte-identical across call sites: invoke
|
|
15
|
+
* the profile runner (`runAgent` / `runOpencodeSdk`) with the per-call
|
|
16
|
+
* `RunAgentOptions` the caller passes. Those default runners live here so
|
|
17
|
+
* callers stop importing `runAgent` / `runOpencodeSdk` for dispatch. The
|
|
18
|
+
* `opts` (incl. any `timeoutMs`) is constructed by the caller and passed
|
|
19
|
+
* through unchanged, so each site keeps its exact option set.
|
|
20
|
+
* - The `llm` arm is irreducibly caller-specific (reflect wraps
|
|
21
|
+
* `runReflectViaLlm`, which returns reflect's iteration shape; drain wraps a
|
|
22
|
+
* plain `chatCompletion`). It is therefore a REQUIRED seam — there is no
|
|
23
|
+
* default `llm` handler — so neither caller's bespoke behavior is changed.
|
|
24
|
+
* - The `assertNever` exhaustiveness arm is kept so a 4th `RunnerSpec` kind is
|
|
25
|
+
* a compile error here instead of a silent runtime fall-through.
|
|
26
|
+
*
|
|
27
|
+
* The return type is {@link AgentRunResult} so a later `callStructured` layer
|
|
28
|
+
* (X2) can wrap `executeRunner` without changing this contract.
|
|
29
|
+
*/
|
|
30
|
+
import { assertNever } from "../../core/assert.js";
|
|
31
|
+
import { runOpencodeSdk } from "../harnesses/opencode-sdk/index.js";
|
|
32
|
+
import { runAgent } from "./spawn.js";
|
|
33
|
+
/**
|
|
34
|
+
* Dispatch a {@link RunnerSpec} to its runner and return the raw
|
|
35
|
+
* {@link AgentRunResult}. `opts` is the {@link RunAgentOptions} for the profile
|
|
36
|
+
* (`agent` / `sdk`) arms; it is passed through unchanged so each caller keeps
|
|
37
|
+
* its exact option set (incl. any `timeoutMs` the caller chose to apply).
|
|
38
|
+
*/
|
|
39
|
+
export async function executeRunner(spec, prompt, opts, seams = {}) {
|
|
40
|
+
switch (spec.kind) {
|
|
41
|
+
case "llm": {
|
|
42
|
+
if (!seams.llm) {
|
|
43
|
+
throw new Error("executeRunner: an `llm` runner requires a `seams.llm` handler (no default LLM dispatch).");
|
|
44
|
+
}
|
|
45
|
+
return seams.llm(spec, prompt);
|
|
46
|
+
}
|
|
47
|
+
case "agent": {
|
|
48
|
+
const run = seams.runAgent ?? runAgent;
|
|
49
|
+
return run(spec.profile, prompt, opts);
|
|
50
|
+
}
|
|
51
|
+
case "sdk": {
|
|
52
|
+
const run = seams.runSdk ?? runOpencodeSdk;
|
|
53
|
+
return run(spec.profile, prompt, opts);
|
|
54
|
+
}
|
|
55
|
+
default:
|
|
56
|
+
// Exhaustiveness arm: a 4th RunnerSpec kind becomes a compile error here.
|
|
57
|
+
return assertNever(spec);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -157,6 +157,19 @@ function resolveProcessRunnerWithLlmFallback(block, config, opts) {
|
|
|
157
157
|
}
|
|
158
158
|
return null;
|
|
159
159
|
}
|
|
160
|
+
/**
|
|
161
|
+
* Build the tool-less HTTP runner from `defaults.llm`, or `null` when unset.
|
|
162
|
+
* The unattended-improve reflect pin (meta-review 07 Chain-G / P1.3) uses this
|
|
163
|
+
* as the mandatory downgrade target when config would otherwise hand reflect a
|
|
164
|
+
* tool-capable (agent/SDK) runner in a scheduled run. Throws ConfigError when
|
|
165
|
+
* `defaults.llm` names a profile that does not exist.
|
|
166
|
+
*/
|
|
167
|
+
export function resolveDefaultLlmRunner(config, timeoutMs) {
|
|
168
|
+
const name = config.defaults?.llm;
|
|
169
|
+
if (!name)
|
|
170
|
+
return null;
|
|
171
|
+
return buildLlmRunnerSpec(name, timeoutMs, config);
|
|
172
|
+
}
|
|
160
173
|
export function resolveValidationRunner(config) {
|
|
161
174
|
const validation = config.profiles?.improve?.default?.processes?.validation;
|
|
162
175
|
const block = validation && validation.enabled !== false ? validation : undefined;
|
|
@@ -213,15 +226,6 @@ export function resolveImproveProcessRunnerFromProfile(processConfig, config) {
|
|
|
213
226
|
}
|
|
214
227
|
return null;
|
|
215
228
|
}
|
|
216
|
-
/**
|
|
217
|
-
* Convenience accessor for callers that previously read
|
|
218
|
-
* `getProcessOptions("index", "staleness_detection", config).thresholdDays`.
|
|
219
|
-
* After the 0.8.0 migration, those values live on first-class config keys —
|
|
220
|
-
* see `config.index?.stalenessDetection?.thresholdDays` etc.
|
|
221
|
-
*/
|
|
222
|
-
export function getStalenessDetectionThresholdDays(config) {
|
|
223
|
-
return config.index?.stalenessDetection?.thresholdDays;
|
|
224
|
-
}
|
|
225
229
|
// Re-export `isProcessEnabled` from feature-gate.ts so callers that previously
|
|
226
230
|
// imported it from runner.ts continue to work.
|
|
227
231
|
export { isProcessEnabled } from "../../llm/feature-gate.js";
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
import fs from "node:fs";
|
|
18
18
|
import os from "node:os";
|
|
19
19
|
import path from "node:path";
|
|
20
|
+
import { parseEmbeddedJsonResponse } from "../../core/parse.js";
|
|
20
21
|
import { spawn as runtimeSpawn } from "../../runtime.js";
|
|
21
22
|
import { getCommandBuilder } from "./builders.js";
|
|
22
23
|
import { DEFAULT_AGENT_TIMEOUT_MS } from "./config.js";
|
|
@@ -203,6 +204,19 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
203
204
|
const finalArgv = [...builtArgv, ...(options.dispatch ? (options.args ?? []) : [])];
|
|
204
205
|
const env = { ...buildChildEnv(profile, options), ...(builtEnv ?? {}) };
|
|
205
206
|
const start = Date.now();
|
|
207
|
+
// Cooperative cancel: refuse to spawn at all when the caller's signal is
|
|
208
|
+
// already aborted (e.g. the run's budget was exhausted before this unit).
|
|
209
|
+
if (options.signal?.aborted) {
|
|
210
|
+
return {
|
|
211
|
+
ok: false,
|
|
212
|
+
exitCode: null,
|
|
213
|
+
stdout: "",
|
|
214
|
+
stderr: "",
|
|
215
|
+
durationMs: 0,
|
|
216
|
+
reason: "aborted",
|
|
217
|
+
error: `agent CLI "${profile.name}" not started: caller signal already aborted`,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
206
220
|
let proc;
|
|
207
221
|
try {
|
|
208
222
|
const spawnFn = resolveSpawnFn(options);
|
|
@@ -211,7 +225,9 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
211
225
|
stdout: stdioMode === "captured" ? "pipe" : "inherit",
|
|
212
226
|
stderr: stdioMode === "captured" ? "pipe" : "inherit",
|
|
213
227
|
env,
|
|
214
|
-
|
|
228
|
+
// options.cwd wins; dispatch.cwd is the request-level fallback (it was
|
|
229
|
+
// declared on AgentDispatchRequest but consumed by nothing — P0.5 fix).
|
|
230
|
+
...((options.cwd ?? options.dispatch?.cwd) ? { cwd: options.cwd ?? options.dispatch?.cwd } : {}),
|
|
215
231
|
// Spawn in its own process group so killGroup(-pid, signal) reaches all
|
|
216
232
|
// descendants (e.g. the .opencode binary that opencode's node wrapper forks).
|
|
217
233
|
// Only applied in captured mode — interactive mode inherits the parent
|
|
@@ -258,6 +274,31 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
258
274
|
}, 5000);
|
|
259
275
|
}, timeoutMs);
|
|
260
276
|
}
|
|
277
|
+
// Cooperative cancel: same SIGTERM→SIGKILL discipline as the timeout, but
|
|
278
|
+
// flagged separately so the result carries `reason: "aborted"`.
|
|
279
|
+
let aborted = false;
|
|
280
|
+
const abortSignal = options.signal;
|
|
281
|
+
const onAbort = () => {
|
|
282
|
+
if (!proc || proc.exitCode !== null)
|
|
283
|
+
return;
|
|
284
|
+
aborted = true;
|
|
285
|
+
killGroup(proc, "SIGTERM");
|
|
286
|
+
const sigkillTimer = setTimeoutImpl(() => {
|
|
287
|
+
if (!proc || proc.exitCode !== null)
|
|
288
|
+
return;
|
|
289
|
+
killGroup(proc, "SIGKILL");
|
|
290
|
+
}, 5000);
|
|
291
|
+
if (typeof sigkillTimer !== "number")
|
|
292
|
+
sigkillTimer.unref?.();
|
|
293
|
+
};
|
|
294
|
+
if (abortSignal) {
|
|
295
|
+
// A signal that aborted between the pre-spawn check and here is handled
|
|
296
|
+
// by calling the listener directly.
|
|
297
|
+
if (abortSignal.aborted)
|
|
298
|
+
onAbort();
|
|
299
|
+
else
|
|
300
|
+
abortSignal.addEventListener("abort", onAbort, { once: true });
|
|
301
|
+
}
|
|
261
302
|
// Stream-drain timeout: the overall wall-clock budget plus a 2 s grace
|
|
262
303
|
// period. When a process is killed via SIGTERM/SIGKILL (from our timeout
|
|
263
304
|
// handler or from outside) some runtimes keep the pipe write-end open in
|
|
@@ -304,6 +345,7 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
304
345
|
catch (err) {
|
|
305
346
|
if (timer !== undefined)
|
|
306
347
|
clearTimeoutImpl(timer);
|
|
348
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
307
349
|
// BUG-H2: drain stream readers before the early return so they don't
|
|
308
350
|
// surface as unhandled rejections after the function resolves.
|
|
309
351
|
// The streams already carry a built-in drain timeout so this allSettled
|
|
@@ -321,8 +363,20 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
321
363
|
};
|
|
322
364
|
}
|
|
323
365
|
clearTimeoutImpl(timer);
|
|
366
|
+
abortSignal?.removeEventListener("abort", onAbort);
|
|
324
367
|
const [stdout, stderr] = await Promise.all([stdoutPromise, stderrPromise]);
|
|
325
368
|
const durationMs = Date.now() - start;
|
|
369
|
+
if (aborted) {
|
|
370
|
+
return {
|
|
371
|
+
ok: false,
|
|
372
|
+
exitCode,
|
|
373
|
+
stdout,
|
|
374
|
+
stderr,
|
|
375
|
+
durationMs,
|
|
376
|
+
reason: "aborted",
|
|
377
|
+
error: `agent CLI "${profile.name}" aborted by caller signal`,
|
|
378
|
+
};
|
|
379
|
+
}
|
|
326
380
|
if (timedOut) {
|
|
327
381
|
return {
|
|
328
382
|
ok: false,
|
|
@@ -346,72 +400,20 @@ export async function runAgent(profile, prompt, options = {}) {
|
|
|
346
400
|
};
|
|
347
401
|
}
|
|
348
402
|
if (parseOutput === "json" && stdioMode === "captured") {
|
|
349
|
-
// Strip <think> blocks and code fences, then
|
|
350
|
-
//
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
// Fallback: extract the first balanced {…} from prose output.
|
|
364
|
-
let found;
|
|
365
|
-
for (let s = 0; s < cleaned.length; s++) {
|
|
366
|
-
if (cleaned[s] !== "{")
|
|
367
|
-
continue;
|
|
368
|
-
let depth = 0, inStr = false, esc = false;
|
|
369
|
-
for (let i = s; i < cleaned.length; i++) {
|
|
370
|
-
const c = cleaned[i];
|
|
371
|
-
if (inStr) {
|
|
372
|
-
if (esc) {
|
|
373
|
-
esc = false;
|
|
374
|
-
}
|
|
375
|
-
else if (c === "\\") {
|
|
376
|
-
esc = true;
|
|
377
|
-
}
|
|
378
|
-
else if (c === '"') {
|
|
379
|
-
inStr = false;
|
|
380
|
-
}
|
|
381
|
-
continue;
|
|
382
|
-
}
|
|
383
|
-
if (c === '"') {
|
|
384
|
-
inStr = true;
|
|
385
|
-
continue;
|
|
386
|
-
}
|
|
387
|
-
if (c === "{")
|
|
388
|
-
depth++;
|
|
389
|
-
if (c === "}") {
|
|
390
|
-
depth--;
|
|
391
|
-
if (depth === 0) {
|
|
392
|
-
try {
|
|
393
|
-
found = JSON.parse(cleaned.slice(s, i + 1));
|
|
394
|
-
}
|
|
395
|
-
catch { }
|
|
396
|
-
break;
|
|
397
|
-
}
|
|
398
|
-
}
|
|
399
|
-
}
|
|
400
|
-
if (found !== undefined)
|
|
401
|
-
break;
|
|
402
|
-
}
|
|
403
|
-
if (found === undefined) {
|
|
404
|
-
return {
|
|
405
|
-
ok: false,
|
|
406
|
-
exitCode,
|
|
407
|
-
stdout,
|
|
408
|
-
stderr,
|
|
409
|
-
durationMs,
|
|
410
|
-
reason: "parse_error",
|
|
411
|
-
error: "no JSON object found in agent output",
|
|
412
|
-
};
|
|
413
|
-
}
|
|
414
|
-
parsed = found;
|
|
403
|
+
// Strip <think> blocks and code fences, then parse with embedded-JSON
|
|
404
|
+
// fallback for local LLMs that emit prose around the payload. Handles
|
|
405
|
+
// both top-level `{…}` and `[…]` structures.
|
|
406
|
+
const parsed = parseEmbeddedJsonResponse(stdout);
|
|
407
|
+
if (parsed === undefined) {
|
|
408
|
+
return {
|
|
409
|
+
ok: false,
|
|
410
|
+
exitCode,
|
|
411
|
+
stdout,
|
|
412
|
+
stderr,
|
|
413
|
+
durationMs,
|
|
414
|
+
reason: "parse_error",
|
|
415
|
+
error: "no JSON structure found in agent output",
|
|
416
|
+
};
|
|
415
417
|
}
|
|
416
418
|
return { ok: true, exitCode, stdout, stderr, durationMs, parsed };
|
|
417
419
|
}
|
|
@@ -33,7 +33,7 @@ export const claudeBuilder = {
|
|
|
33
33
|
args.push("--system-prompt", req.systemPrompt);
|
|
34
34
|
}
|
|
35
35
|
if (req.model) {
|
|
36
|
-
const resolved = resolveModel(req.model, "claude", profile.modelAliases);
|
|
36
|
+
const resolved = resolveModel(req.model, "claude", profile.modelAliases, profile.globalModelAliases);
|
|
37
37
|
args.push("--model", resolved);
|
|
38
38
|
}
|
|
39
39
|
if (req.tools) {
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
* that say `'claude-code'` keep working unchanged.
|
|
26
26
|
*/
|
|
27
27
|
import { BaseHarness } from "../types.js";
|
|
28
|
+
import { claudeBuilder } from "./agent-builder.js";
|
|
28
29
|
export { claudeBuilder } from "./agent-builder.js";
|
|
29
30
|
export { claudeCodeImporter } from "./config-import.js";
|
|
30
31
|
export { ClaudeCodeProvider } from "./session-log.js";
|
|
@@ -53,6 +54,7 @@ export class ClaudeHarness extends BaseHarness {
|
|
|
53
54
|
// Home-relative config dir scanned by `akm setup` (#567). Claude Code has a
|
|
54
55
|
// session-log provider, so offering it as a stash source is functional.
|
|
55
56
|
setupDetectionDir = ".claude";
|
|
57
|
+
agentBuilder = claudeBuilder;
|
|
56
58
|
capabilities = caps({
|
|
57
59
|
sessionLogs: true,
|
|
58
60
|
agentDispatch: true,
|
|
@@ -107,6 +107,16 @@ export class ClaudeCodeProvider {
|
|
|
107
107
|
isAvailable() {
|
|
108
108
|
return fs.existsSync(claudeProjectsDir());
|
|
109
109
|
}
|
|
110
|
+
/**
|
|
111
|
+
* Directory holding Claude Code's per-project session JSONL files
|
|
112
|
+
* (`~/.claude/projects`, honoring `AKM_CLAUDE_PROJECTS_DIR`). Returns `[]`
|
|
113
|
+
* when the directory does not exist on this machine. See {@link
|
|
114
|
+
* SessionLogHarness.watchRoots}.
|
|
115
|
+
*/
|
|
116
|
+
watchRoots() {
|
|
117
|
+
const dir = claudeProjectsDir();
|
|
118
|
+
return fs.existsSync(dir) ? [dir] : [];
|
|
119
|
+
}
|
|
110
120
|
*readEvents(input) {
|
|
111
121
|
try {
|
|
112
122
|
for (const jsonlPath of this.#walkJsonl(claudeProjectsDir())) {
|
|
@@ -60,9 +60,8 @@ const HARNESS_BY_ANY_ID = (() => {
|
|
|
60
60
|
})();
|
|
61
61
|
/**
|
|
62
62
|
* Canonical, ordered list of valid harness / platform ids. The Zod
|
|
63
|
-
* `AgentPlatformSchema` enum, the `
|
|
64
|
-
*
|
|
65
|
-
* union all derive from this so they cannot drift.
|
|
63
|
+
* `AgentPlatformSchema` enum, the `AgentProfileConfig` platform union, and
|
|
64
|
+
* setup's `DetectedHarness` union all derive from this so they cannot drift.
|
|
66
65
|
*/
|
|
67
66
|
export const VALID_HARNESS_IDS = Object.freeze(HARNESS_REGISTRY.map((h) => h.id));
|
|
68
67
|
/** Harnesses that expose readable native session logs. */
|
|
@@ -33,7 +33,7 @@ export const opencodeBuilder = {
|
|
|
33
33
|
args.push("--system-prompt", req.systemPrompt);
|
|
34
34
|
}
|
|
35
35
|
if (req.model) {
|
|
36
|
-
const resolved = resolveModel(req.model, "opencode", profile.modelAliases);
|
|
36
|
+
const resolved = resolveModel(req.model, "opencode", profile.modelAliases, profile.globalModelAliases);
|
|
37
37
|
args.push("--model", resolved);
|
|
38
38
|
}
|
|
39
39
|
args.push("--");
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* Claude Code's 'claude' vs 'claude-code'), so no alias bridge is needed.
|
|
19
19
|
*/
|
|
20
20
|
import { BaseHarness } from "../types.js";
|
|
21
|
+
import { opencodeBuilder } from "./agent-builder.js";
|
|
21
22
|
export { opencodeBuilder } from "./agent-builder.js";
|
|
22
23
|
export { openCodeImporter } from "./config-import.js";
|
|
23
24
|
export { OpenCodeProvider } from "./session-log.js";
|
|
@@ -48,6 +49,7 @@ export class OpencodeHarness extends BaseHarness {
|
|
|
48
49
|
// `v1ProfilePlatform()` resolves most-specific-id-first, so "opencode-sdk-*"
|
|
49
50
|
// is claimed by OpencodeSdkHarness before this prefix can over-match it.
|
|
50
51
|
v1ProfilePrefixes = ["opencode"];
|
|
52
|
+
agentBuilder = opencodeBuilder;
|
|
51
53
|
capabilities = caps({
|
|
52
54
|
sessionLogs: true,
|
|
53
55
|
agentDispatch: true,
|