akm-cli 0.10.261012-beta → 0.10.261014-beta
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 +710 -3
- package/README.md +15 -0
- package/SECURITY.md +11 -10
- package/STABILITY.md +47 -51
- package/dist/assets/hints/cli-hints-full.md +21 -19
- package/dist/assets/hints/cli-hints-short.md +3 -4
- package/dist/assets/opencode/akm-plugin.js +177 -0
- package/dist/assets/stash-skeleton/README.md +1 -1
- package/dist/assets/tasks/core/improve.yml +1 -1
- package/dist/assets/tasks/improve/akm-improve-consolidate.yml +1 -1
- package/dist/assets/ui/config.js +27 -10
- package/dist/assets/workflows/workflow-template.md +2 -2
- package/dist/cli/clack.js +3 -1
- package/dist/cli/selection.js +33 -0
- package/dist/cli/shared.js +14 -1
- package/dist/cli/unknown-flags.js +6 -37
- package/dist/cli.js +69 -48
- package/dist/commands/agent/agent-dispatch.js +17 -25
- package/dist/commands/agent/contribute-cli.js +9 -8
- package/dist/commands/command/command-cli.js +4 -8
- package/dist/commands/command/command-execution.js +25 -39
- package/dist/commands/command/execution-source-loader.js +10 -14
- package/dist/commands/completions.js +1 -1
- package/dist/commands/config-cli.js +14 -5
- package/dist/commands/env/child-env.js +12 -14
- package/dist/commands/env/env-binding.js +47 -58
- package/dist/commands/env/env-cli.js +22 -24
- package/dist/commands/env/env.js +10 -58
- package/dist/commands/env/secret-cli.js +11 -29
- package/dist/commands/env/secret.js +3 -10
- package/dist/commands/health/checks.js +10 -849
- package/dist/commands/health/connections-and-harnesses-check.js +109 -0
- package/dist/commands/health/egress.js +3 -3
- package/dist/commands/health/html-report.js +9 -10
- package/dist/commands/health/plugin-staleness.js +18 -11
- package/dist/commands/health/report-view-model.js +16 -12
- package/dist/commands/health/scheduler-binary.js +1 -1
- package/dist/commands/health/semantic-search-check.js +85 -0
- package/dist/commands/health/type-directory-check.js +0 -3
- package/dist/commands/health.js +30 -42
- package/dist/commands/improve/consolidate/pair-pass.js +10 -25
- package/dist/commands/improve/consolidate.js +10 -15
- package/dist/commands/improve/distill.js +5 -17
- package/dist/commands/improve/eligibility.js +1 -3
- package/dist/commands/improve/execution.js +37 -40
- package/dist/commands/improve/extract-cli.js +6 -11
- package/dist/commands/improve/extract-prompt.js +2 -2
- package/dist/commands/improve/extract.js +67 -97
- package/dist/commands/improve/improve-cli.js +22 -128
- package/dist/commands/improve/improve-report.js +1 -1
- package/dist/commands/improve/improve-strategies.js +25 -108
- package/dist/commands/improve/improve.js +10 -14
- package/dist/commands/improve/loop-stages.js +3 -0
- package/dist/commands/improve/memory/memory-improve.js +1 -1
- package/dist/commands/improve/preparation.js +8 -13
- package/dist/commands/improve/reflect.js +203 -332
- package/dist/commands/improve/retrieval-scope.js +1 -1
- package/dist/commands/improve/session-asset.js +3 -2
- package/dist/commands/improve/stage.js +87 -115
- package/dist/commands/lint/base-linter.js +3 -3
- package/dist/commands/lint/env-key-rules.js +7 -6
- package/dist/commands/lint/index.js +3 -3
- package/dist/commands/models-cli.js +103 -63
- package/dist/commands/proposal/drain.js +26 -39
- package/dist/commands/proposal/proposal-cli.js +14 -18
- package/dist/commands/proposal/propose-cli.js +4 -2
- package/dist/commands/proposal/propose.js +37 -64
- package/dist/commands/proposal/repository.js +17 -17
- package/dist/commands/proposal/validators/proposal-validators.js +3 -6
- package/dist/commands/read/curate.js +10 -6
- package/dist/commands/read/registry-search.js +2 -48
- package/dist/commands/read/search-cli.js +1 -8
- package/dist/commands/read/search.js +5 -6
- package/dist/commands/read/show.js +6 -29
- package/dist/commands/remember.js +25 -40
- package/dist/commands/sources/add-cli.js +8 -63
- package/dist/commands/sources/bundle-cli.js +8 -9
- package/dist/commands/sources/bundle-config-ops.js +2 -2
- package/dist/commands/sources/info.js +12 -1
- package/dist/commands/sources/init.js +1 -1
- package/dist/commands/sources/installed-stashes.js +119 -63
- package/dist/commands/sources/migration-help.js +1 -1
- package/dist/commands/sources/plugin-upgrade.js +8 -15
- package/dist/commands/sources/schema-repair.js +4 -10
- package/dist/commands/sources/source-add.js +2 -2
- package/dist/commands/sources/source-clone.js +31 -7
- package/dist/commands/sources/source-manage.js +4 -4
- package/dist/commands/targets.js +175 -0
- package/dist/commands/tasks/explain.js +104 -69
- package/dist/commands/tasks/tasks-cli.js +9 -11
- package/dist/commands/tasks/tasks.js +75 -97
- package/dist/commands/ui/api.js +11 -3
- package/dist/commands/ui/redact.js +5 -31
- package/dist/commands/ui/workspace-actions.js +1 -1
- package/dist/commands/workflow/plan.js +48 -9
- package/dist/commands/workflow-cli.js +40 -45
- package/dist/core/adapter/adapters/agent-skills-adapter.js +10 -11
- package/dist/core/adapter/adapters/akm-adapter.js +36 -41
- package/dist/core/adapter/adapters/akm-lint.js +10 -12
- package/dist/core/adapter/adapters/akm-metadata.js +2 -2
- package/dist/core/adapter/adapters/akm-task-adapter.js +8 -9
- package/dist/core/adapter/adapters/akm-workflow-adapter.js +5 -5
- package/dist/core/adapter/adapters/claude-adapter.js +1 -1
- package/dist/core/adapter/adapters/dotenv-adapter.js +7 -6
- package/dist/core/adapter/adapters/generic-files-adapter.js +5 -5
- package/dist/core/adapter/adapters/index.js +3 -4
- package/dist/core/adapter/adapters/llm-wiki-adapter.js +12 -14
- package/dist/core/adapter/adapters/okf-adapter.js +8 -10
- package/dist/core/adapter/adapters/opencode-adapter.js +1 -1
- package/dist/core/adapter/adapters/shared.js +3 -3
- package/dist/core/adapter/adapters/tool-dir-shared.js +7 -25
- package/dist/core/adapter/adapters/website-snapshot-adapter.js +3 -3
- package/dist/core/adapter/detect-adapter.js +1 -1
- package/dist/core/adapter/execution-source.js +13 -35
- package/dist/core/adapter/registry.js +1 -1
- package/dist/core/adapter/validate-context.js +2 -4
- package/dist/core/asset/asset-placement.js +1 -1
- package/dist/core/asset/asset-ref.js +3 -3
- package/dist/core/asset/resolve-ref.js +5 -0
- package/dist/core/bundle-rename.js +12 -4
- package/dist/core/closest-match.js +37 -0
- package/dist/core/common.js +37 -57
- package/dist/core/config/config-io.js +26 -18
- package/dist/core/config/config-schema.js +19 -106
- package/dist/core/config/config-sources.js +3 -3
- package/dist/core/config/config-types.js +4 -4
- package/dist/core/config/config-walker.js +50 -77
- package/dist/core/config/config.js +438 -109
- package/dist/core/config/convert-engine-references.js +114 -0
- package/dist/core/config/convert-engines-shared.js +40 -0
- package/dist/core/config/convert-engines.js +300 -0
- package/dist/core/config/convert-models-overlay.js +137 -0
- package/dist/core/config/credentials.js +304 -0
- package/dist/core/config/engine-semantics.js +3 -3
- package/dist/core/config/migrate-keys.js +222 -0
- package/dist/core/config/model-aliases.js +37 -0
- package/dist/core/config/models-file.js +34 -0
- package/dist/core/config/retired-engines.js +53 -0
- package/dist/core/config/schema/connections.js +41 -0
- package/dist/core/config/schema/embedding.js +2 -2
- package/dist/core/config/schema/harnesses.js +41 -0
- package/dist/core/config/schema/improve-processes.js +9 -28
- package/dist/core/config/schema/improve.js +36 -1
- package/dist/core/config/schema/index-config.js +18 -20
- package/dist/core/config/schema/primitives.js +42 -17
- package/dist/core/config/schema/search.js +6 -11
- package/dist/core/config/schema/sources-bundles.js +9 -9
- package/dist/core/config/schema/workflow.js +2 -6
- package/dist/core/config/unusable-entries.js +66 -0
- package/dist/core/content-safety.js +3 -6
- package/dist/core/endpoint-url.js +47 -0
- package/dist/core/env-secret-ref.js +84 -73
- package/dist/core/errors.js +10 -16
- package/dist/core/extra-params.js +3 -3
- package/dist/core/improve-result.js +8 -9
- package/dist/core/json-schema.js +1 -1
- package/dist/core/lesson-lint.js +1 -1
- package/dist/core/llm-inference.js +80 -0
- package/dist/core/parse.js +2 -2
- package/dist/core/paths.js +33 -10
- package/dist/core/recognition-util.js +8 -10
- package/dist/core/redaction.js +94 -55
- package/dist/core/ref-token.js +82 -0
- package/dist/core/secret-value.js +14 -0
- package/dist/core/state/migrations.js +17 -22
- package/dist/core/structured.js +2 -68
- package/dist/core/subprocess.js +63 -22
- package/dist/core/type-presentation.js +10 -14
- package/dist/core/write-source.js +20 -4
- package/dist/execution/input-contract.js +3 -6
- package/dist/execution/notices.js +49 -0
- package/dist/execution/resolved-request.js +24 -40
- package/dist/execution/source.js +21 -45
- package/dist/execution/target-ref.js +2 -2
- package/dist/indexer/bundle-identity-guard.js +6 -5
- package/dist/indexer/ensure-index.js +1 -1
- package/dist/indexer/index-writer-lock.js +1 -1
- package/dist/indexer/indexer.js +46 -42
- package/dist/indexer/installations.js +12 -22
- package/dist/indexer/lookup/adapter-concept-owner.js +40 -14
- package/dist/indexer/materialize-embeddings.js +20 -16
- package/dist/indexer/passes/memory-inference.js +21 -50
- package/dist/indexer/passes/metadata.js +5 -5
- package/dist/indexer/scan/doc-to-entry.js +1 -1
- package/dist/indexer/scan/drain-dir.js +9 -11
- package/dist/indexer/search/db-search.js +9 -7
- package/dist/indexer/search/search-source.js +42 -22
- package/dist/indexer/usage/usage-events.js +2 -3
- package/dist/indexer/walk/index-context.js +2 -1
- package/dist/indexer/walk/matchers.js +3 -11
- package/dist/indexer/walk/path-resolver.js +13 -68
- package/dist/indexer/walk/walker.js +32 -26
- package/dist/integrations/agent/akm-read-tools.js +81 -0
- package/dist/integrations/agent/config.js +1 -1
- package/dist/integrations/agent/detect.js +32 -36
- package/dist/integrations/agent/execution.js +130 -428
- package/dist/integrations/agent/index.js +1 -1
- package/dist/integrations/agent/profiles.js +24 -28
- package/dist/integrations/agent/prompts.js +17 -30
- package/dist/integrations/agent/request-lowering.js +67 -101
- package/dist/integrations/agent/resolution.js +332 -0
- package/dist/integrations/agent/runner-dispatch.js +156 -181
- package/dist/integrations/agent/runner.js +20 -70
- package/dist/integrations/agent/runtime-port.js +4 -0
- package/dist/integrations/agent/runtime.js +10 -0
- package/dist/integrations/agent/spawn.js +65 -190
- package/dist/integrations/harnesses/aider/index.js +19 -39
- package/dist/integrations/harnesses/amazonq/index.js +17 -32
- package/dist/integrations/harnesses/claude/index.js +59 -28
- package/dist/integrations/harnesses/claude/session-log.js +7 -5
- package/dist/integrations/harnesses/codex/index.js +19 -31
- package/dist/integrations/harnesses/copilot/index.js +17 -35
- package/dist/integrations/harnesses/gemini/index.js +18 -34
- package/dist/integrations/harnesses/harness.js +36 -0
- package/dist/integrations/harnesses/index.js +20 -51
- package/dist/integrations/harnesses/opencode/agent-builder.js +132 -100
- package/dist/integrations/harnesses/opencode/index.js +11 -33
- package/dist/integrations/harnesses/opencode/roots.js +50 -0
- package/dist/integrations/harnesses/opencode/runtime/binary.js +206 -0
- package/dist/integrations/harnesses/opencode/runtime/command.js +152 -0
- package/dist/integrations/harnesses/opencode/runtime/index.js +177 -0
- package/dist/integrations/harnesses/opencode/runtime/tar.js +107 -0
- package/dist/integrations/harnesses/opencode/session-log-v1.js +15 -7
- package/dist/integrations/harnesses/opencode/session-log-v2.js +72 -48
- package/dist/integrations/harnesses/opencode/session-log.js +58 -137
- package/dist/integrations/harnesses/opencode/version.js +34 -53
- package/dist/integrations/harnesses/openhands/index.js +13 -37
- package/dist/integrations/harnesses/pi/index.js +21 -32
- package/dist/integrations/lockfile.js +1 -1
- package/dist/integrations/session-logs/index.js +11 -31
- package/dist/llm/client.js +93 -111
- package/dist/llm/embedder.js +19 -34
- package/dist/llm/embedders/connection.js +31 -0
- package/dist/llm/embedders/local-model-files.js +56 -0
- package/dist/llm/embedders/local.js +146 -115
- package/dist/llm/embedders/remote.js +26 -23
- package/dist/llm/embedders/types.js +1 -1
- package/dist/llm/index-passes.js +33 -39
- package/dist/llm/memory-infer.js +67 -77
- package/dist/llm/model-list.js +35 -0
- package/dist/llm/rerank-client.js +8 -14
- package/dist/llm/structured-call.js +45 -99
- package/dist/llm/structured.js +60 -0
- package/dist/output/renderers.js +2 -8
- package/dist/output/shapes/helpers.js +18 -44
- package/dist/output/shapes/passthrough.js +1 -0
- package/dist/output/shapes.js +1 -7
- package/dist/output/text/command-format.js +41 -39
- package/dist/output/text/health-format.js +8 -2
- package/dist/output/text/helpers.js +1 -1
- package/dist/output/text/migrate.js +12 -0
- package/dist/output/text/models.js +3 -2
- package/dist/output/text/registry-commands.js +1 -2
- package/dist/output/text/show-directives.js +16 -28
- package/dist/output/text/show-format.js +0 -2
- package/dist/output/text/targets-table.js +70 -0
- package/dist/output/text/workflow-format.js +44 -15
- package/dist/output/text.js +1 -1
- package/dist/registry/providers/skills-sh.js +1 -28
- package/dist/registry/providers/static-index.js +1 -71
- package/dist/runtime.js +6 -2
- package/dist/scripts/akm-migrate-node.js +47095 -44905
- package/dist/scripts/akm-migrate.js +46946 -44755
- package/dist/setup/detect.js +28 -273
- package/dist/setup/endpoint.js +36 -0
- package/dist/setup/semantic-assets.js +13 -19
- package/dist/setup/setup-flags.js +77 -0
- package/dist/setup/setup-plan.js +144 -0
- package/dist/setup/setup.js +134 -358
- package/dist/setup/steps/connection-shared.js +49 -101
- package/dist/setup/steps/connection.js +121 -524
- package/dist/setup/steps/embeddings.js +151 -0
- package/dist/setup/steps/harnesses.js +118 -0
- package/dist/setup/steps/platforms.js +2 -81
- package/dist/setup/steps/tasks.js +1 -2
- package/dist/setup/steps.js +10 -0
- package/dist/setup/summary.js +67 -0
- package/dist/sources/freshness.js +16 -21
- package/dist/sources/providers/git-provider.js +2 -9
- package/dist/sources/providers/provider-utils.js +13 -5
- package/dist/sources/resolve.js +12 -16
- package/dist/sources/snapshot-fetchers/robots.js +11 -12
- package/dist/sources/snapshot-fetchers/secret-seam.js +2 -4
- package/dist/sources/snapshot-fetchers/website-ingest.js +8 -15
- package/dist/sources/snapshot-fetchers/x.js +1 -1
- package/dist/standalone/onnxruntime-library.js +52 -0
- package/dist/storage/repositories/improve-ledger-repository.js +1 -1
- package/dist/storage/repositories/improve-runs-repository.js +0 -13
- package/dist/storage/repositories/index-entries-repository.js +2 -2
- package/dist/storage/repositories/proposals-repository.js +2 -2
- package/dist/storage/repositories/task-history-repository.js +2 -2
- package/dist/storage/repositories/workflow-runs-repository.js +44 -129
- package/dist/storage/sqlite-read-snapshot.js +33 -29
- package/dist/tasks/embedded.js +1 -1
- package/dist/tasks/log-redaction.js +7 -119
- package/dist/tasks/prepare/prepare-support.js +8 -7
- package/dist/tasks/prepare/prepare.js +8 -9
- package/dist/tasks/prepare/script-capture.js +9 -25
- package/dist/tasks/run/attempt-lifecycle.js +17 -35
- package/dist/tasks/run/load-task.js +54 -27
- package/dist/tasks/run/run-command-task.js +15 -10
- package/dist/tasks/run/run-native-task.js +8 -21
- package/dist/tasks/run/run-task.js +5 -8
- package/dist/tasks/run/run-workflow-task.js +14 -21
- package/dist/tasks/run/task-history.js +9 -17
- package/dist/tasks/run/task-log.js +1 -5
- package/dist/tasks/scheduler-invocation.js +13 -18
- package/dist/tasks/scheduler-sync.js +0 -1
- package/dist/tasks/source/bounded-document.js +31 -117
- package/dist/tasks/source/parse-task-source.js +0 -1
- package/dist/tasks/source/project-v4.js +5 -3
- package/dist/tasks/source/task-input-diagnostics.js +3 -4
- package/dist/tasks/source/task-source-v4.js +48 -72
- package/dist/tasks/source-v3.js +2 -5
- package/dist/tasks/task-run-reserved-flags.js +1 -2
- package/dist/workflows/authoring/authoring.js +2 -7
- package/dist/workflows/compile.js +1 -15
- package/dist/workflows/concurrency-policy.js +4 -4
- package/dist/workflows/exec/child-workflow.js +1 -4
- package/dist/workflows/exec/dispatch-redaction.js +35 -86
- package/dist/workflows/exec/environment.js +13 -77
- package/dist/workflows/exec/exec-unit.js +14 -55
- package/dist/workflows/exec/frozen-judge.js +26 -28
- package/dist/workflows/exec/native-executor.js +126 -71
- package/dist/workflows/exec/run-workflow.js +38 -42
- package/dist/workflows/exec/step-work.js +13 -17
- package/dist/workflows/exec/unit-dispatch.js +7 -21
- package/dist/workflows/freeze/environment.js +14 -119
- package/dist/workflows/freeze/freeze.js +14 -33
- package/dist/workflows/freeze/step-values.js +6 -13
- package/dist/workflows/freeze/targets/child-workflow.js +3 -5
- package/dist/workflows/freeze/targets/command.js +9 -15
- package/dist/workflows/freeze/targets/shell.js +0 -3
- package/dist/workflows/freeze/task-bindings.js +0 -1
- package/dist/workflows/parser.js +50 -59
- package/dist/workflows/plan.js +8 -2
- package/dist/workflows/renderer.js +83 -9
- package/dist/workflows/resource-limits.js +2 -2
- package/dist/workflows/runtime/run-plan.js +38 -23
- package/dist/workflows/runtime/runs.js +55 -93
- package/dist/workflows/runtime/workflow-asset-loader.js +55 -86
- package/dist/workflows/source-files.js +7 -19
- package/docs/README.md +10 -16
- package/docs/architecture/README.md +2 -37
- package/docs/architecture/adapters.md +2 -2
- package/docs/architecture/akm-core-principles.md +256 -118
- package/docs/architecture/architecture.md +283 -99
- package/docs/architecture/improvement.md +8 -2
- package/docs/architecture/internals/classification.md +1 -3
- package/docs/architecture/internals/fresh-host-rebuild-runbook.md +7 -6
- package/docs/architecture/internals/health-advisories.md +35 -74
- package/docs/architecture/internals/improve-workflow.md +27 -26
- package/docs/architecture/internals/indexing.md +3 -3
- package/docs/architecture/internals/storage-locations.md +48 -15
- package/docs/architecture/persisted-data-compat.md +10 -6
- package/docs/architecture/specs/okf-support.md +9 -11
- package/docs/architecture/specs/ref.md +7 -9
- package/docs/architecture/testing/testing-workflow.md +172 -52
- package/docs/architecture/workflow-engine.md +51 -34
- package/docs/guides/README.md +0 -1
- package/docs/guides/author-bundles.md +15 -20
- package/docs/guides/author-workflows.md +93 -71
- package/docs/guides/bundles.md +20 -16
- package/docs/guides/discover-and-load.md +1 -1
- package/docs/guides/getting-started.md +49 -3
- package/docs/guides/improve-the-library.md +10 -4
- package/docs/guides/recipes/headless-install.md +11 -16
- package/docs/guides/run-workflows.md +29 -20
- package/docs/guides/scheduling.md +2 -2
- package/docs/guides/use-with-any-agent.md +20 -22
- package/docs/integration/bundling-akm.md +19 -9
- package/docs/maintainers/README.md +2 -6
- package/docs/maintainers/release-checklist.md +73 -126
- package/docs/migration/README.md +10 -3
- package/docs/migration/release-notes/0.10.0.md +81 -16
- package/docs/migration/release-notes/0.6.0.md +1 -1
- package/docs/migration/release-notes/0.7.0.md +1 -1
- package/docs/migration/release-notes/0.9.0.md +1 -1
- package/docs/migration/release-notes/README.md +1 -1
- package/docs/migration/v0.9-to-v0.10.md +300 -60
- package/docs/migration/v0.9.1-to-v0.9.2.md +6 -5
- package/docs/posts/config-v2-lessons-16.md +1 -1
- package/docs/posts/llm-mode-reflect-13.md +1 -1
- package/docs/posts/release-0.6.0.md +11 -11
- package/docs/posts/release-0.8.0.md +4 -4
- package/docs/posts/workflows-vaults-09.md +1 -1
- package/docs/reference/README.md +1 -1
- package/docs/reference/asset-types.md +2 -2
- package/docs/reference/cli.md +477 -388
- package/docs/reference/configuration.md +569 -550
- package/docs/reference/data-and-telemetry.md +9 -6
- package/docs/reference/env-and-secrets.md +72 -15
- package/docs/reference/refs.md +3 -20
- package/docs/reference/registry.md +12 -38
- package/docs/reference/supported-formats.md +1 -1
- package/docs/reference/tasks.md +22 -11
- package/docs/reference/ui-api.md +14 -9
- package/docs/reference/workflow-schema.md +199 -154
- package/docs/reference/workflows.md +4 -6
- package/package.json +9 -11
- package/schemas/akm-config.json +1696 -2922
- package/schemas/akm-task.json +4 -4
- package/schemas/akm-workflow.json +36 -9
- package/ROADMAP.md +0 -112
- package/dist/assets/models.json +0 -35
- package/dist/commands/health/engine-usage.js +0 -45
- package/dist/commands/sources/dangerous-env-audit.js +0 -134
- package/dist/core/activation-policy.js +0 -67
- package/dist/core/config/schema/engines.js +0 -160
- package/dist/core/config/schema/execution.js +0 -23
- package/dist/core/spawn-env.js +0 -268
- package/dist/execution/directory-identity.js +0 -78
- package/dist/integrations/agent/builder-shared.js +0 -33
- package/dist/integrations/agent/builders.js +0 -43
- package/dist/integrations/agent/engine-fallback.js +0 -59
- package/dist/integrations/agent/engine-resolution.js +0 -333
- package/dist/integrations/agent/model-map.js +0 -475
- package/dist/integrations/harnesses/aider/agent-builder.js +0 -107
- package/dist/integrations/harnesses/aider/result-extractor.js +0 -53
- package/dist/integrations/harnesses/amazonq/agent-builder.js +0 -138
- package/dist/integrations/harnesses/amazonq/result-extractor.js +0 -48
- package/dist/integrations/harnesses/claude/agent-builder.js +0 -106
- package/dist/integrations/harnesses/claude/config-import.js +0 -67
- package/dist/integrations/harnesses/claude/result-extractor.js +0 -67
- package/dist/integrations/harnesses/codex/agent-builder.js +0 -150
- package/dist/integrations/harnesses/codex/result-extractor.js +0 -110
- package/dist/integrations/harnesses/copilot/agent-builder.js +0 -117
- package/dist/integrations/harnesses/copilot/result-extractor.js +0 -178
- package/dist/integrations/harnesses/gemini/agent-builder.js +0 -114
- package/dist/integrations/harnesses/gemini/result-extractor.js +0 -149
- package/dist/integrations/harnesses/opencode/config-import.js +0 -149
- package/dist/integrations/harnesses/opencode/model-config.js +0 -33
- package/dist/integrations/harnesses/opencode/model-work-agent.js +0 -115
- package/dist/integrations/harnesses/opencode/session-log-types.js +0 -12
- package/dist/integrations/harnesses/opencode-sdk/index.js +0 -44
- package/dist/integrations/harnesses/opencode-sdk/sdk-runner.js +0 -1052
- package/dist/integrations/harnesses/opencode-sdk/v1-adapter.js +0 -199
- package/dist/integrations/harnesses/opencode-sdk/v2-adapter.js +0 -254
- package/dist/integrations/harnesses/opencode-sdk/wire.js +0 -66
- package/dist/integrations/harnesses/openhands/agent-builder.js +0 -120
- package/dist/integrations/harnesses/openhands/result-extractor.js +0 -135
- package/dist/integrations/harnesses/pi/agent-builder.js +0 -89
- package/dist/integrations/harnesses/pi/result-extractor.js +0 -168
- package/dist/integrations/harnesses/shared.js +0 -18
- package/dist/integrations/harnesses/types.js +0 -55
- package/dist/llm/feature-gate.js +0 -115
- package/dist/output/shapes/models-list.js +0 -16
- package/dist/output/shapes/registry-search.js +0 -10
- package/dist/setup/detected-engines.js +0 -136
- package/dist/setup/engine-config.js +0 -97
- package/dist/setup/harness-config-import.js +0 -47
- package/dist/setup/providers.js +0 -14
- package/dist/setup/steps/semantic.js +0 -39
- package/dist/workflows/authoring/scope-key.js +0 -79
- package/dist/workflows/exec/lowering-notices.js +0 -23
- package/dist/workflows/source-semantics.js +0 -110
- package/docs/architecture/0.10-process-rules.md +0 -832
- package/docs/architecture/akm-architecture-decision-history.md +0 -2055
- package/docs/architecture/comparisons/claude-code-vs-akm-workflows-full.md +0 -550
- package/docs/architecture/decisions/0001-no-interpolation-attached-structured-context.md +0 -72
- package/docs/architecture/decisions/0002-unit-reuse-and-input-hash-scope.md +0 -142
- package/docs/architecture/decisions/0003-child-env-allowlist-and-provenance.md +0 -189
- package/docs/architecture/decisions/0004-task-input-contract-and-flag-coercion.md +0 -97
- package/docs/architecture/decisions/0005-task-result-vocabulary-and-legacy-read-mapping.md +0 -108
- package/docs/architecture/decisions/0006-task-source-version-routing.md +0 -124
- package/docs/architecture/decisions/0007-workflow-composition-bounds.md +0 -83
- package/docs/architecture/decisions/0008-task-binding-normalization.md +0 -88
- package/docs/architecture/decisions/0009-child-run-publication-column-parity.md +0 -80
- package/docs/architecture/decisions/0010-driver-protocol-cut.md +0 -36
- package/docs/architecture/decisions/0011-engine-run-loop-invariants.md +0 -125
- package/docs/architecture/decisions/README.md +0 -62
- package/docs/architecture/internals/functional-contract-patterns.md +0 -340
- package/docs/architecture/internals/registry-network-boundary.md +0 -57
- package/docs/architecture/internals/search.md +0 -248
- package/docs/architecture/reviews/env-secret-access.md +0 -319
- package/docs/architecture/runtime-boundary-design.md +0 -153
- package/docs/architecture/specs/0.9.0-close-out-plan.md +0 -361
- package/docs/architecture/specs/0.9.0-decisions.md +0 -532
- package/docs/architecture/specs/0.9.0-docs-code-drift-register.md +0 -745
- package/docs/architecture/specs/0.9.0-open-items-register.md +0 -135
- package/docs/architecture/specs/0.9.0-public-api-issue-backlog.md +0 -740
- package/docs/architecture/specs/0.9.0-release-surface-review.md +0 -636
- package/docs/architecture/specs/agent-command-engine-model-design.md +0 -513
- package/docs/architecture/specs/akm-0.9.0-bundle-adapter-spec.md +0 -501
- package/docs/architecture/specs/akm-0.9.0-ref-grammar-decision.md +0 -291
- package/docs/architecture/specs/akm-format-neutral-bundle-workspace-spec.md +0 -2059
- package/docs/architecture/specs/di-seams-plan.md +0 -539
- package/docs/architecture/specs/driver-protocol-keep-or-cut.md +0 -275
- package/docs/architecture/specs/fact-asset-type.md +0 -142
- package/docs/architecture/specs/improve-collapse-churn-detector-design.md +0 -634
- package/docs/architecture/specs/reviews/task-workflow-unification/README.md +0 -72
- package/docs/architecture/specs/reviews/task-workflow-unification/findings-consolidated.md +0 -152
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-alternatives.md +0 -352
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-bunqueue.md +0 -300
- package/docs/architecture/specs/reviews/task-workflow-unification/library-eval-openworkflow.md +0 -402
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-1.md +0 -758
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-2.md +0 -645
- package/docs/architecture/specs/reviews/task-workflow-unification/opus-review-3.md +0 -602
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-adversarial.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-architecture.md +0 -27
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-coverage.md +0 -74
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r1-security.md +0 -15
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-adversarial.md +0 -132
- package/docs/architecture/specs/reviews/task-workflow-unification/panel-r2-verification.md +0 -147
- package/docs/architecture/specs/stash-conventions-code-spec.md +0 -275
- package/docs/architecture/specs/stash-organization-conventions.md +0 -377
- package/docs/architecture/specs/task-workflow-format-unification.md +0 -721
- package/docs/architecture/specs/workflow-engine-buy-vs-build.md +0 -231
- package/docs/architecture/specs/workflow-format-unification.md +0 -432
- package/docs/architecture/testing/manual-testing-checklist.md +0 -3411
- package/docs/architecture/testing/okf-v0.2-conformance-runbook.md +0 -924
- package/docs/architecture/testing/task-workflow-manual-tests.md +0 -1720
- package/docs/guides/claude-code-vs-akm-workflows.md +0 -29
- package/docs/guides/knowledge-management.md +0 -18
- package/docs/maintainers/curate-workmap.md +0 -335
- package/docs/migration/v0.5-to-v0.6.md +0 -759
- package/docs/migration/v0.7-to-v0.8.md +0 -1378
- package/docs/plans/0.9.2-agent-command-workflow-plan.md +0 -423
|
@@ -1,110 +0,0 @@
|
|
|
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
|
-
* OpenAI Codex CLI result extractor (P2, plan §"The adapter contract" step 3 /
|
|
6
|
-
* §"Structured-output normalization").
|
|
7
|
-
*
|
|
8
|
-
* Normalizes the raw {@link AgentRunResult} of a `codex exec --json` run into
|
|
9
|
-
* `{ text, sessionId? }` ({@link AgentResultExtraction}). Schema validation and
|
|
10
|
-
* the retry-until-valid loop stay in the engine, shared across harnesses —
|
|
11
|
-
* this module only strips transport framing.
|
|
12
|
-
*
|
|
13
|
-
* `--json` emits ONE JSON event per stdout line. Two documented event dialects
|
|
14
|
-
* exist across codex versions; the adapter contract localizes that churn here,
|
|
15
|
-
* so both are handled:
|
|
16
|
-
*
|
|
17
|
-
* Legacy protocol (envelope with an `msg` object):
|
|
18
|
-
* {"id":"0","msg":{"type":"session_configured","session_id":"<uuid>", ...}}
|
|
19
|
-
* {"id":"1","msg":{"type":"agent_message","message":"<text>"}}
|
|
20
|
-
* {"id":"1","msg":{"type":"task_complete","last_agent_message":"<text>"}}
|
|
21
|
-
*
|
|
22
|
-
* Newer experimental-JSON protocol (flat `type` field):
|
|
23
|
-
* {"type":"thread.started","thread_id":"<id>"}
|
|
24
|
-
* {"type":"item.completed","item":{"id":"item_1","type":"agent_message","text":"<text>"}}
|
|
25
|
-
* {"type":"turn.completed","usage":{...}}
|
|
26
|
-
*
|
|
27
|
-
* Extraction rules:
|
|
28
|
-
* - text: `task_complete.last_agent_message` wins when present (it is the
|
|
29
|
-
* harness's own "final answer" designation); otherwise the LAST
|
|
30
|
-
* agent-message event seen; otherwise the trimmed raw stdout (plain-text
|
|
31
|
-
* fallback for runs without `--json`, or unrecognized formats — the
|
|
32
|
-
* engine's `parseEmbeddedJsonResponse` tier still gets a fair input).
|
|
33
|
-
* - sessionId: `session_configured.session_id` / `thread.started.thread_id`,
|
|
34
|
-
* falling back to any sessionId the spawn layer already attached. Stored
|
|
35
|
-
* opportunistically on the unit row for `codex exec resume <id>`; akm
|
|
36
|
-
* never depends on it (plan §"Session, MCP, and identity").
|
|
37
|
-
*
|
|
38
|
-
* Non-event JSON lines (e.g. a bare JSON answer printed without framing) are
|
|
39
|
-
* ignored by the event scan and land in the raw-stdout fallback untouched.
|
|
40
|
-
*
|
|
41
|
-
* Registered: `codexResultExtractor` is `CodexHarness.resultExtractor`
|
|
42
|
-
* (`./index.ts`); the engine resolves it via `getHarness()` in
|
|
43
|
-
* `workflows/exec/native-executor.ts` to normalize agent-unit stdout before
|
|
44
|
-
* schema validation.
|
|
45
|
-
*/
|
|
46
|
-
import { asNonEmptyString, isRecord } from "../../../core/common.js";
|
|
47
|
-
/** Interpret one parsed JSONL event in either codex event dialect. */
|
|
48
|
-
function interpretEvent(event) {
|
|
49
|
-
// Legacy protocol: {"id":..., "msg":{"type": ...}}
|
|
50
|
-
const msg = event.msg;
|
|
51
|
-
if (isRecord(msg)) {
|
|
52
|
-
switch (msg.type) {
|
|
53
|
-
case "session_configured":
|
|
54
|
-
return { sessionId: asNonEmptyString(msg.session_id) };
|
|
55
|
-
case "agent_message":
|
|
56
|
-
return { agentMessage: asNonEmptyString(msg.message) };
|
|
57
|
-
case "task_complete":
|
|
58
|
-
return { finalMessage: asNonEmptyString(msg.last_agent_message) };
|
|
59
|
-
default:
|
|
60
|
-
return {};
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
// Newer protocol: flat {"type": "thread.started" | "item.completed" | ...}
|
|
64
|
-
switch (event.type) {
|
|
65
|
-
case "thread.started":
|
|
66
|
-
return { sessionId: asNonEmptyString(event.thread_id) };
|
|
67
|
-
case "item.completed": {
|
|
68
|
-
const item = event.item;
|
|
69
|
-
if (isRecord(item) && item.type === "agent_message") {
|
|
70
|
-
return { agentMessage: asNonEmptyString(item.text) };
|
|
71
|
-
}
|
|
72
|
-
return {};
|
|
73
|
-
}
|
|
74
|
-
default:
|
|
75
|
-
return {};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Codex result extractor: JSONL event stream (either dialect) → final agent
|
|
80
|
-
* message + opportunistic session id, with a plain-stdout fallback.
|
|
81
|
-
*/
|
|
82
|
-
export const codexResultExtractor = (result) => {
|
|
83
|
-
let sessionId = result.sessionId;
|
|
84
|
-
let lastAgentMessage;
|
|
85
|
-
let finalMessage;
|
|
86
|
-
for (const line of result.stdout.split("\n")) {
|
|
87
|
-
const trimmed = line.trim();
|
|
88
|
-
// Every codex event line is a JSON object; skip banner/noise lines cheaply.
|
|
89
|
-
if (!trimmed.startsWith("{"))
|
|
90
|
-
continue;
|
|
91
|
-
let parsed;
|
|
92
|
-
try {
|
|
93
|
-
parsed = JSON.parse(trimmed);
|
|
94
|
-
}
|
|
95
|
-
catch {
|
|
96
|
-
continue; // not a complete JSON line (e.g. wrapped text) — ignore
|
|
97
|
-
}
|
|
98
|
-
if (!isRecord(parsed))
|
|
99
|
-
continue;
|
|
100
|
-
const contribution = interpretEvent(parsed);
|
|
101
|
-
if (contribution.sessionId)
|
|
102
|
-
sessionId = contribution.sessionId;
|
|
103
|
-
if (contribution.agentMessage)
|
|
104
|
-
lastAgentMessage = contribution.agentMessage;
|
|
105
|
-
if (contribution.finalMessage)
|
|
106
|
-
finalMessage = contribution.finalMessage;
|
|
107
|
-
}
|
|
108
|
-
const text = finalMessage ?? lastAgentMessage ?? result.stdout.trim();
|
|
109
|
-
return sessionId === undefined ? { text } : { text, sessionId };
|
|
110
|
-
};
|
|
@@ -1,117 +0,0 @@
|
|
|
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
|
-
* GitHub Copilot CLI agent command builder (P2, plan §"The adapter contract"
|
|
6
|
-
* step 2 / §"Capability matrix").
|
|
7
|
-
*
|
|
8
|
-
* Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
|
|
9
|
-
* headless argv the `copilot` CLI expects. Per the capability matrix the
|
|
10
|
-
* headless invocation is:
|
|
11
|
-
*
|
|
12
|
-
* copilot -p "<prompt>" --allow-all-tools
|
|
13
|
-
*
|
|
14
|
-
* with `--output-format json` for structured output, `--model <m>` for model
|
|
15
|
-
* selection, and `--resume <id>` for resume (not built here because
|
|
16
|
-
* `AgentDispatchRequest` carries no session id).
|
|
17
|
-
*
|
|
18
|
-
* Platform-specific mapping decisions (all localized here, per the adapter
|
|
19
|
-
* contract):
|
|
20
|
-
*
|
|
21
|
-
* - **systemPrompt** — Copilot CLI has no system-prompt flag (it reads
|
|
22
|
-
* repo/user custom-instructions files instead), so the system prompt is
|
|
23
|
-
* folded into the `-p` payload ahead of the task prompt, separated by a
|
|
24
|
-
* blank line.
|
|
25
|
-
* - **schema** — the matrix places Copilot in the "via prompt+validate" tier
|
|
26
|
-
* (no native `--output-schema` equivalent, unlike Codex), so the JSON
|
|
27
|
-
* Schema reaches it as the instruction the shared request lowering appends
|
|
28
|
-
* to the prompt, and `--output-format json` is emitted so stdout is the
|
|
29
|
-
* documented JSON envelope the copilot result extractor normalizes. The
|
|
30
|
-
* engine's shared retry-until-valid loop performs the actual validation.
|
|
31
|
-
* - **tools** — a string/array tool policy maps to repeated
|
|
32
|
-
* `--allow-tool <t>` flags (Copilot's per-tool approval flag). With no
|
|
33
|
-
* policy at all, headless runs need autonomy, so `--allow-all-tools` is
|
|
34
|
-
* emitted per the matrix. A *structured* policy object is NOT expressible
|
|
35
|
-
* as Copilot flags; it is deliberately dropped without falling back to
|
|
36
|
-
* `--allow-all-tools` (never silently widen a restriction) — in
|
|
37
|
-
* programmatic mode Copilot then denies unapproved tool calls, which is the
|
|
38
|
-
* conservative failure mode.
|
|
39
|
-
*
|
|
40
|
-
* Registered: `copilotBuilder` is `CopilotHarness.agentBuilder`
|
|
41
|
-
* (`./index.ts`), one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
42
|
-
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
43
|
-
* that registry, so this builder is reachable under the `"copilot"` platform
|
|
44
|
-
* name without any further wiring.
|
|
45
|
-
*/
|
|
46
|
-
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
47
|
-
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
48
|
-
/** Canonical harness/platform id used for model-alias resolution. */
|
|
49
|
-
export const COPILOT_PLATFORM = "copilot";
|
|
50
|
-
/**
|
|
51
|
-
* Split a tool policy into individual tool names for `--allow-tool`.
|
|
52
|
-
* Strings are comma-separated lists; arrays are taken as-is. Structured
|
|
53
|
-
* policy objects return `undefined` (not expressible as Copilot flags — see
|
|
54
|
-
* module doc).
|
|
55
|
-
*/
|
|
56
|
-
function toolPolicyEntries(tools) {
|
|
57
|
-
if (typeof tools === "string") {
|
|
58
|
-
return tools
|
|
59
|
-
.split(",")
|
|
60
|
-
.map((t) => t.trim())
|
|
61
|
-
.filter(Boolean);
|
|
62
|
-
}
|
|
63
|
-
if (Array.isArray(tools)) {
|
|
64
|
-
return tools.map((t) => t.trim()).filter(Boolean);
|
|
65
|
-
}
|
|
66
|
-
return undefined;
|
|
67
|
-
}
|
|
68
|
-
/** Assemble the `-p` payload: optional system prompt, then the task prompt. */
|
|
69
|
-
function buildPromptPayload(req) {
|
|
70
|
-
const sections = [];
|
|
71
|
-
if (req.systemPrompt)
|
|
72
|
-
sections.push(req.systemPrompt);
|
|
73
|
-
sections.push(req.prompt);
|
|
74
|
-
return sections.join("\n\n");
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* GitHub Copilot CLI builder.
|
|
78
|
-
* Command shape:
|
|
79
|
-
* copilot [--model <m>] (--allow-all-tools | --allow-tool <t> ...)
|
|
80
|
-
* [--output-format json] -p "<systemPrompt?\n\nprompt>"
|
|
81
|
-
*/
|
|
82
|
-
export const copilotBuilder = {
|
|
83
|
-
platform: COPILOT_PLATFORM,
|
|
84
|
-
personaChannel: "prompt",
|
|
85
|
-
lower: createAgentRequestLowerer({
|
|
86
|
-
adapter: COPILOT_PLATFORM,
|
|
87
|
-
personaChannel: "prompt",
|
|
88
|
-
tools: "flat",
|
|
89
|
-
}),
|
|
90
|
-
build(profile, req) {
|
|
91
|
-
const args = [...profile.args];
|
|
92
|
-
if (req.model) {
|
|
93
|
-
const resolved = resolveDispatchModel(req, profile, COPILOT_PLATFORM);
|
|
94
|
-
args.push("--model", resolved);
|
|
95
|
-
}
|
|
96
|
-
if (req.tools) {
|
|
97
|
-
const entries = toolPolicyEntries(req.tools);
|
|
98
|
-
// Structured policy objects (entries === undefined) emit NO allow flags:
|
|
99
|
-
// dropping a restriction must never widen to --allow-all-tools.
|
|
100
|
-
for (const tool of entries ?? []) {
|
|
101
|
-
args.push("--allow-tool", tool);
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
else {
|
|
105
|
-
// Headless default per the capability matrix: units must run without
|
|
106
|
-
// interactive tool-approval prompts.
|
|
107
|
-
args.push("--allow-all-tools");
|
|
108
|
-
}
|
|
109
|
-
if (req.schema) {
|
|
110
|
-
// Structured unit: ask for the documented JSON envelope so the result
|
|
111
|
-
// extractor can pull the final message + session id deterministically.
|
|
112
|
-
args.push("--output-format", "json");
|
|
113
|
-
}
|
|
114
|
-
args.push("-p", buildPromptPayload(req));
|
|
115
|
-
return { argv: [profile.bin, ...args] };
|
|
116
|
-
},
|
|
117
|
-
};
|
|
@@ -1,178 +0,0 @@
|
|
|
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
|
-
* GitHub Copilot CLI result extractor (P2, plan §"The adapter contract"
|
|
6
|
-
* step 3 / §"Structured-output normalization", tier "native-json").
|
|
7
|
-
*
|
|
8
|
-
* Normalizes one raw {@link AgentRunResult} from a headless `copilot` run
|
|
9
|
-
* into `{ text, sessionId? }` — the {@link AgentResultExtraction} seam. The
|
|
10
|
-
* engine's shared schema-validation / retry-until-valid loop runs *after*
|
|
11
|
-
* this; the extractor only strips transport framing.
|
|
12
|
-
*
|
|
13
|
-
* Copilot's stdout takes one of three shapes depending on flags/version
|
|
14
|
-
* (`--output-format json` per the capability matrix), all handled here:
|
|
15
|
-
*
|
|
16
|
-
* 1. **Single JSON document** — a result envelope, e.g.
|
|
17
|
-
* `{"type":"result","session_id":"…","result":"<final answer>"}`.
|
|
18
|
-
* Pretty-printed multi-line JSON is included (whole-stdout parse is
|
|
19
|
-
* attempted first). Only objects carrying a transport marker (a `type`
|
|
20
|
-
* discriminator or a session-id field) are unwrapped; a bare JSON answer
|
|
21
|
-
* with no marker (a schema unit's `{"result":"ok"}`) is passed through
|
|
22
|
-
* raw so the engine's schema validator sees the whole object.
|
|
23
|
-
* 2. **JSONL event stream** — one JSON object per line
|
|
24
|
-
* (`session.start` / assistant `message` / `result` events); the LAST
|
|
25
|
-
* text-bearing event wins, the first session-id-bearing event supplies
|
|
26
|
-
* the session id. Non-JSON banner lines are skipped.
|
|
27
|
-
* 3. **Plain text** — no JSON anywhere; trimmed stdout passes through
|
|
28
|
-
* verbatim (the engine's embedded-JSON parsing still runs downstream for
|
|
29
|
-
* schema units).
|
|
30
|
-
*
|
|
31
|
-
* Key names are matched tolerantly (`result`/`response`/`text`/`output`/
|
|
32
|
-
* `content`/`message`, snake_case and camelCase session-id variants) so
|
|
33
|
-
* point-release renames in the CLI's envelope degrade to the plain-text
|
|
34
|
-
* fallback instead of hard-failing — version churn stays contained in this
|
|
35
|
-
* one file, per the adapter contract.
|
|
36
|
-
*
|
|
37
|
-
* Registered: `copilotResultExtractor` is `CopilotHarness.resultExtractor`
|
|
38
|
-
* (`./index.ts`); the engine resolves it via `getHarness()` in
|
|
39
|
-
* `workflows/exec/native-executor.ts` to normalize agent-unit stdout before
|
|
40
|
-
* schema validation.
|
|
41
|
-
*/
|
|
42
|
-
import { isRecord, tryParseJson } from "../../../core/common.js";
|
|
43
|
-
/** Keys that may carry the final answer, in precedence order. */
|
|
44
|
-
const TEXT_KEYS = ["result", "response", "text", "output", "content", "message"];
|
|
45
|
-
/** Keys that may carry the harness-native session id, in precedence order. */
|
|
46
|
-
const SESSION_KEYS = ["session_id", "sessionId", "conversation_id", "conversationId", "thread_id", "threadId"];
|
|
47
|
-
/**
|
|
48
|
-
* Coerce a candidate value into text. Handles the shapes Copilot's envelope
|
|
49
|
-
* nests answers in: bare strings, `{content|text}` wrappers (assistant
|
|
50
|
-
* message objects), and arrays of `{type:"text",text}` content blocks.
|
|
51
|
-
* Depth-bounded: JSON.parse output is acyclic, but nesting is capped anyway
|
|
52
|
-
* so a pathological envelope cannot recurse unboundedly.
|
|
53
|
-
*/
|
|
54
|
-
function textOf(value, depth = 0) {
|
|
55
|
-
if (depth > 4)
|
|
56
|
-
return undefined;
|
|
57
|
-
if (typeof value === "string")
|
|
58
|
-
return value;
|
|
59
|
-
if (Array.isArray(value)) {
|
|
60
|
-
const parts = [];
|
|
61
|
-
for (const block of value) {
|
|
62
|
-
const t = textOf(block, depth + 1);
|
|
63
|
-
if (t)
|
|
64
|
-
parts.push(t);
|
|
65
|
-
}
|
|
66
|
-
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
67
|
-
}
|
|
68
|
-
if (isRecord(value)) {
|
|
69
|
-
return textOf(value.content ?? value.text, depth + 1);
|
|
70
|
-
}
|
|
71
|
-
return undefined;
|
|
72
|
-
}
|
|
73
|
-
/** Extract the final-answer text from one parsed JSON value, if any. */
|
|
74
|
-
function extractText(value) {
|
|
75
|
-
if (typeof value === "string")
|
|
76
|
-
return value;
|
|
77
|
-
if (!isRecord(value))
|
|
78
|
-
return undefined;
|
|
79
|
-
for (const key of TEXT_KEYS) {
|
|
80
|
-
if (!(key in value))
|
|
81
|
-
continue;
|
|
82
|
-
const text = textOf(value[key]);
|
|
83
|
-
if (text !== undefined)
|
|
84
|
-
return text;
|
|
85
|
-
}
|
|
86
|
-
return undefined;
|
|
87
|
-
}
|
|
88
|
-
/** Extract a harness-native session id from one parsed JSON value, if any. */
|
|
89
|
-
function extractSessionId(value) {
|
|
90
|
-
if (!isRecord(value))
|
|
91
|
-
return undefined;
|
|
92
|
-
for (const key of SESSION_KEYS) {
|
|
93
|
-
const candidate = value[key];
|
|
94
|
-
if (typeof candidate === "string" && candidate.length > 0)
|
|
95
|
-
return candidate;
|
|
96
|
-
}
|
|
97
|
-
return undefined;
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* `type` discriminator values Copilot's `--output-format json` envelopes are
|
|
101
|
-
* documented to use (plus the `session.*` event family). Deliberately a
|
|
102
|
-
* CLOSED set: a schema unit's own answer may legitimately be a discriminated
|
|
103
|
-
* union with a `type` field (`{"type":"success","output":"data"}`), and
|
|
104
|
-
* treating ANY string `type` as a transport marker would unwrap — and
|
|
105
|
-
* corrupt — such answers. An unrecognized type degrades to raw pass-through,
|
|
106
|
-
* which the schema validator handles (whole object) and free-text tolerates.
|
|
107
|
-
*/
|
|
108
|
-
const ENVELOPE_TYPES = new Set(["result", "response", "message", "assistant", "error"]);
|
|
109
|
-
/**
|
|
110
|
-
* Does this parsed object look like one of Copilot's transport ENVELOPES (a
|
|
111
|
-
* `result`/event document) rather than a bare JSON answer the model produced?
|
|
112
|
-
*
|
|
113
|
-
* Copilot's `--output-format json` documents always carry a transport marker:
|
|
114
|
-
* a known `type` discriminator (`"result"`, `"session.start"`, `"message"`, …)
|
|
115
|
-
* and, in every documented result envelope, a session-id field. A bare
|
|
116
|
-
* structured answer a schema unit was asked for — e.g. `{"result":"ok"}` or
|
|
117
|
-
* `{"type":"success","output":"data"}` — carries neither a known discriminator
|
|
118
|
-
* nor (normally) a session-id key. Unwrapping such an answer would hand the
|
|
119
|
-
* schema validator only the field value (`"ok"`) and reject the run despite
|
|
120
|
-
* valid JSON (PR #714 review), so we only unwrap objects that are genuinely
|
|
121
|
-
* envelopes and pass everything else through raw.
|
|
122
|
-
*/
|
|
123
|
-
function isTransportEnvelope(value) {
|
|
124
|
-
const type = value.type;
|
|
125
|
-
if (typeof type === "string" && (ENVELOPE_TYPES.has(type) || type.startsWith("session.")))
|
|
126
|
-
return true;
|
|
127
|
-
return extractSessionId(value) !== undefined;
|
|
128
|
-
}
|
|
129
|
-
/**
|
|
130
|
-
* Normalize a raw copilot run result into `{ text, sessionId? }`.
|
|
131
|
-
* See the module doc for the three stdout shapes handled.
|
|
132
|
-
*/
|
|
133
|
-
export const copilotResultExtractor = (result) => {
|
|
134
|
-
// The raw result's own sessionId (SDK-style paths) is the fallback; an id
|
|
135
|
-
// found in the output stream wins because it is fresher.
|
|
136
|
-
const fallbackSessionId = result.sessionId;
|
|
137
|
-
const raw = result.stdout.trim();
|
|
138
|
-
// Shape 1 — whole stdout is one JSON document (spawn may have pre-parsed
|
|
139
|
-
// it when the profile requested parseOutput: "json").
|
|
140
|
-
const whole = result.parsed !== undefined ? result.parsed : raw.length > 0 ? tryParseJson(raw) : undefined;
|
|
141
|
-
if (whole !== undefined) {
|
|
142
|
-
const sessionId = extractSessionId(whole) ?? fallbackSessionId;
|
|
143
|
-
// A bare JSON OBJECT with no transport marker is a legitimate structured
|
|
144
|
-
// answer (a schema unit's `{"result":"ok"}`), NOT an envelope — pass its
|
|
145
|
-
// raw JSON through so the engine's schema validator receives the whole
|
|
146
|
-
// object instead of an unwrapped field value (PR #714 review). Only
|
|
147
|
-
// genuine Copilot envelopes are unwrapped; non-object JSON (a top-level
|
|
148
|
-
// string/array/primitive) keeps the prior extraction. Either way, an
|
|
149
|
-
// unknown envelope with no recognized text key falls back to raw stdout.
|
|
150
|
-
const text = isRecord(whole) && !isTransportEnvelope(whole) ? raw : (extractText(whole) ?? raw);
|
|
151
|
-
return { text, ...(sessionId ? { sessionId } : {}) };
|
|
152
|
-
}
|
|
153
|
-
// Shape 2 — JSONL event stream: last text-bearing event wins; first
|
|
154
|
-
// session-id-bearing event supplies the id. Non-JSON lines are banner
|
|
155
|
-
// noise and are skipped.
|
|
156
|
-
let lastText;
|
|
157
|
-
let streamSessionId;
|
|
158
|
-
let sawJsonLine = false;
|
|
159
|
-
for (const line of raw.split("\n")) {
|
|
160
|
-
const trimmed = line.trim();
|
|
161
|
-
if (trimmed.length === 0)
|
|
162
|
-
continue;
|
|
163
|
-
const event = tryParseJson(trimmed);
|
|
164
|
-
if (event === undefined)
|
|
165
|
-
continue;
|
|
166
|
-
sawJsonLine = true;
|
|
167
|
-
streamSessionId ??= extractSessionId(event);
|
|
168
|
-
const text = extractText(event);
|
|
169
|
-
if (text !== undefined)
|
|
170
|
-
lastText = text;
|
|
171
|
-
}
|
|
172
|
-
if (sawJsonLine) {
|
|
173
|
-
const sessionId = streamSessionId ?? fallbackSessionId;
|
|
174
|
-
return { text: lastText ?? raw, ...(sessionId ? { sessionId } : {}) };
|
|
175
|
-
}
|
|
176
|
-
// Shape 3 — plain text passthrough.
|
|
177
|
-
return { text: raw, ...(fallbackSessionId ? { sessionId: fallbackSessionId } : {}) };
|
|
178
|
-
};
|
|
@@ -1,114 +0,0 @@
|
|
|
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
|
-
* Gemini CLI agent command builder (P2, plan §"The adapter contract" step 2 /
|
|
6
|
-
* §"Capability matrix").
|
|
7
|
-
*
|
|
8
|
-
* Translates a platform-agnostic {@link AgentDispatchRequest} into the exact
|
|
9
|
-
* headless argv the `gemini` CLI expects. Per the capability matrix the
|
|
10
|
-
* headless invocation is:
|
|
11
|
-
*
|
|
12
|
-
* gemini -p "<prompt>"
|
|
13
|
-
*
|
|
14
|
-
* with `--output-format json` for structured output, `--model <m>` for model
|
|
15
|
-
* selection, and `--resume <id>` for resume; resume is not built here because
|
|
16
|
-
* `AgentDispatchRequest` carries no session id. The `GEMINI_CLI=1` identity
|
|
17
|
-
* env marker is likewise registry-side (`AkmHarness.identityEnv` /
|
|
18
|
-
* `agent-identity.ts`), not a builder concern.
|
|
19
|
-
*
|
|
20
|
-
* Platform-specific mapping decisions (all localized here, per the adapter
|
|
21
|
-
* contract):
|
|
22
|
-
*
|
|
23
|
-
* - **systemPrompt** — Gemini CLI has no system-prompt flag in headless mode
|
|
24
|
-
* (system text comes from `GEMINI.md` context files / `GEMINI_SYSTEM_MD`),
|
|
25
|
-
* so the system prompt is folded into the `-p` payload ahead of the task
|
|
26
|
-
* prompt, separated by a blank line.
|
|
27
|
-
* - **schema** — the matrix places Gemini in the "via prompt+validate" tier
|
|
28
|
-
* (no native `--output-schema` equivalent, unlike Codex — so no temp-file
|
|
29
|
-
* plumbing here), so the JSON Schema reaches it as the instruction the
|
|
30
|
-
* shared request lowering appends to the prompt, and
|
|
31
|
-
* `--output-format json` is emitted so stdout is the documented JSON
|
|
32
|
-
* envelope the gemini result extractor normalizes. The engine's shared
|
|
33
|
-
* retry-until-valid loop performs the actual validation.
|
|
34
|
-
* - **tools** — a string/array tool policy maps to repeated
|
|
35
|
-
* `--allowed-tools <t>` flags (Gemini's run-without-confirmation
|
|
36
|
-
* allowlist). A *structured* policy object is NOT expressible as Gemini
|
|
37
|
-
* flags; it is deliberately dropped without widening to an auto-approve
|
|
38
|
-
* flag (never silently widen a restriction). With no policy at all,
|
|
39
|
-
* NOTHING is emitted — the matrix's headless shape is the bare
|
|
40
|
-
* `gemini -p "<p>"`; autonomy flags (`--yolo`, `--approval-mode`) belong in
|
|
41
|
-
* `profile.args` where the operator opts in explicitly.
|
|
42
|
-
*
|
|
43
|
-
* Registered: `geminiBuilder` is `GeminiHarness.agentBuilder` (`./index.ts`),
|
|
44
|
-
* one of the ten harnesses `HARNESS_REGISTRY` constructs
|
|
45
|
-
* (`harnesses/index.ts`); `agent/builders.ts` derives `BUILTIN_BUILDERS` from
|
|
46
|
-
* that registry, so this builder is reachable under the `"gemini"` platform
|
|
47
|
-
* name without any further wiring.
|
|
48
|
-
*/
|
|
49
|
-
import { resolveDispatchModel } from "../../agent/builder-shared.js";
|
|
50
|
-
import { createAgentRequestLowerer } from "../../agent/request-lowering.js";
|
|
51
|
-
/** Canonical harness/platform id used for model-alias resolution. */
|
|
52
|
-
export const GEMINI_PLATFORM = "gemini";
|
|
53
|
-
/**
|
|
54
|
-
* Split a tool policy into individual tool names for `--allowed-tools`.
|
|
55
|
-
* Strings are comma-separated lists; arrays are taken as-is. Structured
|
|
56
|
-
* policy objects return `undefined` (not expressible as Gemini flags — see
|
|
57
|
-
* module doc).
|
|
58
|
-
*/
|
|
59
|
-
function toolPolicyEntries(tools) {
|
|
60
|
-
if (typeof tools === "string") {
|
|
61
|
-
return tools
|
|
62
|
-
.split(",")
|
|
63
|
-
.map((t) => t.trim())
|
|
64
|
-
.filter(Boolean);
|
|
65
|
-
}
|
|
66
|
-
if (Array.isArray(tools)) {
|
|
67
|
-
return tools.map((t) => t.trim()).filter(Boolean);
|
|
68
|
-
}
|
|
69
|
-
return undefined;
|
|
70
|
-
}
|
|
71
|
-
/** Assemble the `-p` payload: optional system prompt, then the task prompt. */
|
|
72
|
-
function buildPromptPayload(req) {
|
|
73
|
-
const sections = [];
|
|
74
|
-
if (req.systemPrompt)
|
|
75
|
-
sections.push(req.systemPrompt);
|
|
76
|
-
sections.push(req.prompt);
|
|
77
|
-
return sections.join("\n\n");
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Gemini CLI builder.
|
|
81
|
-
* Command shape:
|
|
82
|
-
* gemini [--model <m>] [--allowed-tools <t> ...]
|
|
83
|
-
* [--output-format json] -p "<systemPrompt?\n\nprompt>"
|
|
84
|
-
*/
|
|
85
|
-
export const geminiBuilder = {
|
|
86
|
-
platform: GEMINI_PLATFORM,
|
|
87
|
-
personaChannel: "prompt",
|
|
88
|
-
lower: createAgentRequestLowerer({
|
|
89
|
-
adapter: GEMINI_PLATFORM,
|
|
90
|
-
personaChannel: "prompt",
|
|
91
|
-
tools: "flat",
|
|
92
|
-
}),
|
|
93
|
-
build(profile, req) {
|
|
94
|
-
const args = [...profile.args];
|
|
95
|
-
if (req.model) {
|
|
96
|
-
const resolved = resolveDispatchModel(req, profile, GEMINI_PLATFORM);
|
|
97
|
-
args.push("--model", resolved);
|
|
98
|
-
}
|
|
99
|
-
if (req.tools) {
|
|
100
|
-
// Structured policy objects (entries === undefined) emit NO flags:
|
|
101
|
-
// dropping a restriction must never widen to auto-approval.
|
|
102
|
-
for (const tool of toolPolicyEntries(req.tools) ?? []) {
|
|
103
|
-
args.push("--allowed-tools", tool);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
if (req.schema) {
|
|
107
|
-
// Structured unit: ask for the documented JSON envelope so the result
|
|
108
|
-
// extractor can pull the final message + session id deterministically.
|
|
109
|
-
args.push("--output-format", "json");
|
|
110
|
-
}
|
|
111
|
-
args.push("-p", buildPromptPayload(req));
|
|
112
|
-
return { argv: [profile.bin, ...args] };
|
|
113
|
-
},
|
|
114
|
-
};
|
|
@@ -1,149 +0,0 @@
|
|
|
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
|
-
* Gemini CLI result extractor (P2, plan §"The adapter contract" step 3 /
|
|
6
|
-
* §"Structured-output normalization", tier "native-json").
|
|
7
|
-
*
|
|
8
|
-
* Normalizes one raw {@link AgentRunResult} from a headless `gemini` run into
|
|
9
|
-
* `{ text, sessionId? }` — the {@link AgentResultExtraction} seam. The
|
|
10
|
-
* engine's shared schema-validation / retry-until-valid loop runs *after*
|
|
11
|
-
* this; the extractor only strips transport framing.
|
|
12
|
-
*
|
|
13
|
-
* Gemini's stdout takes one of three shapes depending on flags/version
|
|
14
|
-
* (`--output-format json` per the capability matrix), all handled here:
|
|
15
|
-
*
|
|
16
|
-
* 1. **Single JSON document** — the documented `--output-format json`
|
|
17
|
-
* envelope, e.g. `{"response":"<final answer>","stats":{...}}` (an
|
|
18
|
-
* `error` variant carries `{error:{type,message,code}}` and no usable
|
|
19
|
-
* response — that degrades to the raw-stdout fallback so the engine's
|
|
20
|
-
* failure handling sees the whole envelope). Pretty-printed multi-line
|
|
21
|
-
* JSON is included (whole-stdout parse is attempted first).
|
|
22
|
-
* 2. **JSONL event stream** (`--output-format stream-json`) — one JSON
|
|
23
|
-
* object per line; the LAST text-bearing event wins, the first
|
|
24
|
-
* session-id-bearing event supplies the session id. Non-JSON banner
|
|
25
|
-
* lines ("Loaded cached credentials.", update notices) are skipped.
|
|
26
|
-
* 3. **Plain text** — no JSON anywhere; trimmed stdout passes through
|
|
27
|
-
* verbatim (the engine's embedded-JSON parsing still runs downstream for
|
|
28
|
-
* schema units).
|
|
29
|
-
*
|
|
30
|
-
* Key names are matched tolerantly (`response` first — Gemini's documented
|
|
31
|
-
* envelope key — then `result`/`text`/`output`/`content`/`message`;
|
|
32
|
-
* snake_case and camelCase session-id variants) so point-release renames in
|
|
33
|
-
* the CLI's envelope degrade to the plain-text fallback instead of
|
|
34
|
-
* hard-failing — version churn stays contained in this one file, per the
|
|
35
|
-
* adapter contract. The session id feeds `--resume <id>` opportunistically;
|
|
36
|
-
* `workflow_run_units` remains the durable source of truth.
|
|
37
|
-
*
|
|
38
|
-
* Registered: `geminiResultExtractor` is `GeminiHarness.resultExtractor`
|
|
39
|
-
* (`./index.ts`); the engine resolves it via `getHarness()` in
|
|
40
|
-
* `workflows/exec/native-executor.ts` to normalize agent-unit stdout before
|
|
41
|
-
* schema validation.
|
|
42
|
-
*/
|
|
43
|
-
import { isRecord, tryParseJson } from "../../../core/common.js";
|
|
44
|
-
/**
|
|
45
|
-
* Keys that may carry the final answer, in precedence order. `response` is
|
|
46
|
-
* Gemini's documented `--output-format json` envelope key.
|
|
47
|
-
*/
|
|
48
|
-
const TEXT_KEYS = ["response", "result", "text", "output", "content", "message"];
|
|
49
|
-
/** Keys that may carry the harness-native session id, in precedence order. */
|
|
50
|
-
const SESSION_KEYS = ["session_id", "sessionId", "conversation_id", "conversationId", "chat_id", "chatId"];
|
|
51
|
-
/**
|
|
52
|
-
* Coerce a candidate value into text. Handles the shapes Gemini nests
|
|
53
|
-
* answers in: bare strings, `{content|text}` wrappers (assistant message
|
|
54
|
-
* objects), and arrays of `{type:"text",text}` content blocks (Gemini API
|
|
55
|
-
* `parts`-style lists). Depth-bounded: JSON.parse output is acyclic, but
|
|
56
|
-
* nesting is capped anyway so a pathological envelope cannot recurse
|
|
57
|
-
* unboundedly.
|
|
58
|
-
*/
|
|
59
|
-
function textOf(value, depth = 0) {
|
|
60
|
-
if (depth > 4)
|
|
61
|
-
return undefined;
|
|
62
|
-
if (typeof value === "string")
|
|
63
|
-
return value;
|
|
64
|
-
if (Array.isArray(value)) {
|
|
65
|
-
const parts = [];
|
|
66
|
-
for (const block of value) {
|
|
67
|
-
const t = textOf(block, depth + 1);
|
|
68
|
-
if (t)
|
|
69
|
-
parts.push(t);
|
|
70
|
-
}
|
|
71
|
-
return parts.length > 0 ? parts.join("\n") : undefined;
|
|
72
|
-
}
|
|
73
|
-
if (isRecord(value)) {
|
|
74
|
-
return textOf(value.content ?? value.text, depth + 1);
|
|
75
|
-
}
|
|
76
|
-
return undefined;
|
|
77
|
-
}
|
|
78
|
-
/** Extract the final-answer text from one parsed JSON value, if any. */
|
|
79
|
-
function extractText(value) {
|
|
80
|
-
if (typeof value === "string")
|
|
81
|
-
return value;
|
|
82
|
-
if (!isRecord(value))
|
|
83
|
-
return undefined;
|
|
84
|
-
for (const key of TEXT_KEYS) {
|
|
85
|
-
if (!(key in value))
|
|
86
|
-
continue;
|
|
87
|
-
const text = textOf(value[key]);
|
|
88
|
-
if (text !== undefined)
|
|
89
|
-
return text;
|
|
90
|
-
}
|
|
91
|
-
return undefined;
|
|
92
|
-
}
|
|
93
|
-
/** Extract a harness-native session id from one parsed JSON value, if any. */
|
|
94
|
-
function extractSessionId(value) {
|
|
95
|
-
if (!isRecord(value))
|
|
96
|
-
return undefined;
|
|
97
|
-
for (const key of SESSION_KEYS) {
|
|
98
|
-
const candidate = value[key];
|
|
99
|
-
if (typeof candidate === "string" && candidate.length > 0)
|
|
100
|
-
return candidate;
|
|
101
|
-
}
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Normalize a raw gemini run result into `{ text, sessionId? }`.
|
|
106
|
-
* See the module doc for the three stdout shapes handled.
|
|
107
|
-
*/
|
|
108
|
-
export const geminiResultExtractor = (result) => {
|
|
109
|
-
// The raw result's own sessionId (SDK-style paths) is the fallback; an id
|
|
110
|
-
// found in the output stream wins because it is fresher.
|
|
111
|
-
const fallbackSessionId = result.sessionId;
|
|
112
|
-
const raw = result.stdout.trim();
|
|
113
|
-
// Shape 1 — whole stdout is one JSON document (spawn may have pre-parsed
|
|
114
|
-
// it when the profile requested parseOutput: "json").
|
|
115
|
-
const whole = result.parsed !== undefined ? result.parsed : raw.length > 0 ? tryParseJson(raw) : undefined;
|
|
116
|
-
if (whole !== undefined) {
|
|
117
|
-
const sessionId = extractSessionId(whole) ?? fallbackSessionId;
|
|
118
|
-
// Unknown envelope (no recognized text key — includes the error-only
|
|
119
|
-
// variant): fall back to raw stdout so downstream embedded-JSON parsing
|
|
120
|
-
// and failure handling still have the full material to work with.
|
|
121
|
-
const text = extractText(whole) ?? raw;
|
|
122
|
-
return { text, ...(sessionId ? { sessionId } : {}) };
|
|
123
|
-
}
|
|
124
|
-
// Shape 2 — JSONL event stream: last text-bearing event wins; first
|
|
125
|
-
// session-id-bearing event supplies the id. Non-JSON lines are banner
|
|
126
|
-
// noise and are skipped.
|
|
127
|
-
let lastText;
|
|
128
|
-
let streamSessionId;
|
|
129
|
-
let sawJsonLine = false;
|
|
130
|
-
for (const line of raw.split("\n")) {
|
|
131
|
-
const trimmed = line.trim();
|
|
132
|
-
if (trimmed.length === 0)
|
|
133
|
-
continue;
|
|
134
|
-
const event = tryParseJson(trimmed);
|
|
135
|
-
if (event === undefined)
|
|
136
|
-
continue;
|
|
137
|
-
sawJsonLine = true;
|
|
138
|
-
streamSessionId ??= extractSessionId(event);
|
|
139
|
-
const text = extractText(event);
|
|
140
|
-
if (text !== undefined)
|
|
141
|
-
lastText = text;
|
|
142
|
-
}
|
|
143
|
-
if (sawJsonLine) {
|
|
144
|
-
const sessionId = streamSessionId ?? fallbackSessionId;
|
|
145
|
-
return { text: lastText ?? raw, ...(sessionId ? { sessionId } : {}) };
|
|
146
|
-
}
|
|
147
|
-
// Shape 3 — plain text passthrough.
|
|
148
|
-
return { text: raw, ...(fallbackSessionId ? { sessionId: fallbackSessionId } : {}) };
|
|
149
|
-
};
|