@aiwg/cli 2026.9.20 → 2026.9.21
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/agentic/code/providers/capability-matrix.yaml +58 -6
- package/agentic/code/providers/model-capabilities.v1.json +34 -0
- package/agentic/code/providers/model-catalog.v1.json +55 -13
- package/bin/aiwg.mjs +2 -0
- package/dist/src/api/index.d.ts +1 -0
- package/dist/src/api/index.js +1 -0
- package/dist/src/artifacts/enrichment/cli.js +1 -1
- package/dist/src/artifacts/views/cli.js +1 -1
- package/dist/src/audit/operator-decision.js +10 -0
- package/dist/src/auth/credential-store.js +127 -27
- package/dist/src/catalog/builtin-models.json +272 -40
- package/dist/src/catalog/cli.js +1 -1
- package/dist/src/catalog/cli.mjs +1 -1
- package/dist/src/cli/handlers/effect.js +872 -0
- package/dist/src/cli/handlers/help.js +2 -0
- package/dist/src/cli/handlers/index.js +4 -2
- package/dist/src/cli/handlers/models.js +41 -10
- package/dist/src/cli/handlers/ralph.js +1 -1
- package/dist/src/cli/handlers/sessions.js +113 -37
- package/dist/src/cli/handlers/subcommands.js +31 -0
- package/dist/src/cli/handlers/use.js +46 -9
- package/dist/src/cli/handlers/utilities.js +10 -0
- package/dist/src/cli/handlers/workspace.js +3 -1
- package/dist/src/cli/scope-resolver.js +112 -9
- package/dist/src/cli/services/deployment-verification.js +5 -0
- package/dist/src/config/aiwg-config.js +3 -0
- package/dist/src/decision/acceptance-rollout.js +93 -0
- package/dist/src/decision/acceptance.js +175 -0
- package/dist/src/decision/adapters/jev.js +234 -13
- package/dist/src/decision/adapters/llm-subagent.js +60 -12
- package/dist/src/decision/admission.js +550 -0
- package/dist/src/decision/batch-benchmark.js +47 -0
- package/dist/src/decision/batch-receipts/accounting.js +75 -0
- package/dist/src/decision/batch-receipts/export.js +40 -0
- package/dist/src/decision/batch-receipts/index.js +9 -0
- package/dist/src/decision/batch-receipts/protection.js +40 -0
- package/dist/src/decision/batch-receipts/receipt.js +44 -0
- package/dist/src/decision/batch-receipts/result-store.js +341 -0
- package/dist/src/decision/batch-receipts/store.js +362 -0
- package/dist/src/decision/batch-receipts/types.js +2 -0
- package/dist/src/decision/batch-receipts/validate.js +127 -0
- package/dist/src/decision/batch.js +68 -0
- package/dist/src/decision/calibration/index.js +4 -0
- package/dist/src/decision/calibration/receipts.js +130 -0
- package/dist/src/decision/calibration/registry.js +258 -0
- package/dist/src/decision/calibration/types.js +2 -0
- package/dist/src/decision/compile-cache/benchmark.js +62 -0
- package/dist/src/decision/compile-cache/compatibility.js +65 -0
- package/dist/src/decision/compile-cache/file-store.js +280 -0
- package/dist/src/decision/compile-cache/identity.js +26 -0
- package/dist/src/decision/compile-cache/index.js +9 -0
- package/dist/src/decision/compile-cache/prefix.js +21 -0
- package/dist/src/decision/compile-cache/records.js +86 -0
- package/dist/src/decision/compile-cache/runtime.js +68 -0
- package/dist/src/decision/compile-cache/store.js +108 -0
- package/dist/src/decision/compile-cache/types.js +2 -0
- package/dist/src/decision/context-plan.js +234 -0
- package/dist/src/decision/context-qualification.js +60 -0
- package/dist/src/decision/ensemble/aggregate.js +215 -0
- package/dist/src/decision/ensemble/contract.js +316 -0
- package/dist/src/decision/ensemble/drift.js +51 -0
- package/dist/src/decision/ensemble/index.js +6 -0
- package/dist/src/decision/ensemble/report.js +71 -0
- package/dist/src/decision/ensemble/types.js +2 -0
- package/dist/src/decision/evaluate.js +1024 -78
- package/dist/src/decision/file-lifecycle-store.js +168 -0
- package/dist/src/decision/graph-beam.js +40 -0
- package/dist/src/decision/graph-budget.js +110 -0
- package/dist/src/decision/graph-decision-bridge.js +93 -0
- package/dist/src/decision/graph-evidence.js +123 -0
- package/dist/src/decision/graph-flow-adapter.js +56 -0
- package/dist/src/decision/graph-flow.js +105 -0
- package/dist/src/decision/graph-parallel.js +79 -0
- package/dist/src/decision/graph-patterns.js +20 -0
- package/dist/src/decision/graph-run-store.js +66 -0
- package/dist/src/decision/graph-run.js +166 -0
- package/dist/src/decision/graph-skill-bridge.js +91 -0
- package/dist/src/decision/graph-templates.js +56 -0
- package/dist/src/decision/graph.js +115 -0
- package/dist/src/decision/index.js +35 -0
- package/dist/src/decision/job-accounting.js +93 -0
- package/dist/src/decision/job-contract.js +186 -0
- package/dist/src/decision/job-effects.js +95 -0
- package/dist/src/decision/job-evaluate.js +80 -0
- package/dist/src/decision/job-gateway.js +121 -0
- package/dist/src/decision/job-http.js +194 -0
- package/dist/src/decision/job-payload-store.js +258 -0
- package/dist/src/decision/job-poll-limiter.js +92 -0
- package/dist/src/decision/job-quota.js +158 -0
- package/dist/src/decision/job-runtime.js +240 -0
- package/dist/src/decision/job-scheduler.js +26 -0
- package/dist/src/decision/job-service.js +117 -0
- package/dist/src/decision/job-store.js +264 -0
- package/dist/src/decision/job-worker.js +141 -0
- package/dist/src/decision/lifecycle.js +148 -0
- package/dist/src/decision/patterns/artifacts.js +173 -0
- package/dist/src/decision/patterns/catalog.js +108 -0
- package/dist/src/decision/patterns/durable-review.js +237 -0
- package/dist/src/decision/patterns/index.js +8 -0
- package/dist/src/decision/patterns/playground.js +401 -0
- package/dist/src/decision/patterns/recorded.js +43 -0
- package/dist/src/decision/patterns/specs.js +174 -0
- package/dist/src/decision/patterns/types.js +2 -0
- package/dist/src/decision/portable-secrets.js +53 -0
- package/dist/src/decision/projection.js +210 -0
- package/dist/src/decision/qualification/capture.js +67 -0
- package/dist/src/decision/qualification/drift.js +68 -0
- package/dist/src/decision/qualification/gate-evidence.js +172 -0
- package/dist/src/decision/qualification/gates.js +83 -0
- package/dist/src/decision/qualification/index.js +12 -0
- package/dist/src/decision/qualification/load.js +275 -0
- package/dist/src/decision/qualification/manifest.js +37 -0
- package/dist/src/decision/qualification/privacy.js +41 -0
- package/dist/src/decision/qualification/quality.js +213 -0
- package/dist/src/decision/qualification/release.js +116 -0
- package/dist/src/decision/qualification/runner.js +408 -0
- package/dist/src/decision/qualification/types.js +2 -0
- package/dist/src/decision/receipts.js +30 -7
- package/dist/src/decision/result-cache/index.js +6 -0
- package/dist/src/decision/result-cache/integrity.js +28 -0
- package/dist/src/decision/result-cache/key.js +28 -0
- package/dist/src/decision/result-cache/service.js +92 -0
- package/dist/src/decision/result-cache/store.js +327 -0
- package/dist/src/decision/result-cache/types.js +3 -0
- package/dist/src/decision/review/authorization.js +110 -0
- package/dist/src/decision/review/effect-ledger-adapter.js +321 -0
- package/dist/src/decision/review/index.js +12 -0
- package/dist/src/decision/review/migrate.js +34 -0
- package/dist/src/decision/review/operator-audit.js +59 -0
- package/dist/src/decision/review/recovery-adapters.js +252 -0
- package/dist/src/decision/review/recovery.js +33 -0
- package/dist/src/decision/review/service.js +498 -0
- package/dist/src/decision/review/store.js +219 -0
- package/dist/src/decision/review/types.js +2 -0
- package/dist/src/decision/review/validate.js +205 -0
- package/dist/src/decision/scheduler.js +115 -0
- package/dist/src/decision/telemetry/context.js +42 -0
- package/dist/src/decision/telemetry/debug-sidecar.js +152 -0
- package/dist/src/decision/telemetry/exporter.js +77 -0
- package/dist/src/decision/telemetry/file-debug-backend.js +112 -0
- package/dist/src/decision/telemetry/index.js +13 -0
- package/dist/src/decision/telemetry/mapping.js +146 -0
- package/dist/src/decision/telemetry/metrics.js +164 -0
- package/dist/src/decision/telemetry/otlp-http.js +183 -0
- package/dist/src/decision/telemetry/redaction.js +93 -0
- package/dist/src/decision/telemetry/retention.js +109 -0
- package/dist/src/decision/telemetry/runtime.js +310 -0
- package/dist/src/decision/telemetry/trace.js +158 -0
- package/dist/src/decision/telemetry/types.js +3 -0
- package/dist/src/decision/validate.js +135 -5
- package/dist/src/effects/checkpoint-sinks.js +94 -0
- package/dist/src/effects/checkpoint.js +76 -0
- package/dist/src/effects/decision-links.js +54 -0
- package/dist/src/effects/errors.js +48 -0
- package/dist/src/effects/identity.js +178 -0
- package/dist/src/effects/index.js +25 -0
- package/dist/src/effects/keyring.js +160 -0
- package/dist/src/effects/keys.js +130 -0
- package/dist/src/effects/ledger.js +435 -0
- package/dist/src/effects/lifecycle.js +110 -0
- package/dist/src/effects/lock-recovery.js +269 -0
- package/dist/src/effects/reader.js +103 -0
- package/dist/src/effects/records.js +114 -0
- package/dist/src/effects/redaction.js +51 -0
- package/dist/src/effects/schema.js +73 -0
- package/dist/src/effects/store.js +239 -0
- package/dist/src/effects/types.js +49 -0
- package/dist/src/effects/verifiers/decision.js +168 -0
- package/dist/src/effects/verifiers/file.js +106 -0
- package/dist/src/effects/verifiers/git.js +206 -0
- package/dist/src/effects/verifiers/index.js +90 -0
- package/dist/src/effects/verifiers/registry.js +148 -0
- package/dist/src/effects/verifiers/review.js +123 -0
- package/dist/src/effects/verifiers/tracker.js +299 -0
- package/dist/src/effects/verifiers/types.js +21 -0
- package/dist/src/effects/verify.js +295 -0
- package/dist/src/evidence/bundle.js +2 -0
- package/dist/src/extensions/commands/definitions.js +28 -0
- package/dist/src/extensions/manifest.js +1 -0
- package/dist/src/marketplace/provenance.js +25 -27
- package/dist/src/mcp/cli.mjs +11 -1
- package/dist/src/mcp/grok-build-config.mjs +189 -0
- package/dist/src/mcp/registry.js +21 -1
- package/dist/src/mcp/registry.mjs +20 -1
- package/dist/src/models/grok-build-models.js +356 -0
- package/dist/src/models/index.js +1 -0
- package/dist/src/models/model-capabilities.v1.json +34 -0
- package/dist/src/models/model-catalog.v1.json +55 -13
- package/dist/src/models/model-discovery.js +41 -5
- package/dist/src/models/provider-policy.js +3 -2
- package/dist/src/plugin/skill-command-translator.js +1 -0
- package/dist/src/providers/capability-matrix.yaml +58 -6
- package/dist/src/providers/grok-build-acp.js +192 -0
- package/dist/src/providers/grok-build-dispatch.js +251 -0
- package/dist/src/providers/grok-build-headless.js +170 -0
- package/dist/src/providers/muse-paths.js +105 -0
- package/dist/src/providers/provider-definitions.js +93 -7
- package/dist/src/providers/provider-definitions.mjs +21 -1
- package/dist/src/providers/provider-inventory.js +3 -0
- package/dist/src/security/artifact-attestation.js +4 -8
- package/dist/src/security/signing.js +119 -0
- package/dist/src/sessions/adapters/grok-build.js +187 -0
- package/dist/src/sessions/adapters/muse.js +412 -0
- package/dist/src/sessions/contracts.js +1 -1
- package/dist/src/sessions/grok-build-cli.js +196 -0
- package/dist/src/sessions/index.js +3 -0
- package/dist/src/sessions/workspace-discovery.js +9 -5
- package/dist/src/skills/deployer.js +33 -5
- package/dist/src/smiths/context-pipeline/claude-hook.js +2 -0
- package/dist/src/smiths/context-pipeline/context-file-safety.js +18 -0
- package/dist/src/smiths/context-pipeline/finalization.js +1 -32
- package/dist/src/smiths/context-pipeline/generator.js +12 -0
- package/dist/src/smiths/context-pipeline/index.js +1 -1
- package/dist/src/smiths/context-pipeline/managed-hook.js +2 -0
- package/dist/src/smiths/context-pipeline/muse-bridge.js +50 -0
- package/dist/src/smiths/context-pipeline/provider-policy.js +5 -0
- package/dist/src/smiths/context-pipeline/workspace-context.js +22 -16
- package/dist/src/smiths/hook-bridge/grok-build-translator.js +64 -0
- package/dist/src/smiths/hook-bridge/index.js +3 -0
- package/dist/src/smiths/hook-bridge/shim.js +2 -0
- package/dist/src/smiths/hook-bridge/types.js +5 -0
- package/dist/src/smiths/skillsmith/collision-detector.js +1 -0
- package/dist/src/storage/protected-files.js +102 -0
- package/dist/src/tracker/forge-http.js +371 -0
- package/dist/src/tracker/project-inputs.js +41 -0
- package/package.json +2 -1
- package/schemas/decision/BatchReceipt.v1.schema.json +50 -0
- package/schemas/decision/CalibrationArtifact.v1.schema.json +76 -0
- package/schemas/decision/CalibrationCompatibility.v1.schema.json +18 -0
- package/schemas/decision/CalibrationGovernanceReceipt.v1.schema.json +44 -0
- package/schemas/decision/DecisionAdmissionEvidence.v1.schema.json +43 -0
- package/schemas/decision/DecisionBinding.schema.json +309 -0
- package/schemas/decision/DecisionBinding.v1alpha2.schema.json +369 -0
- package/schemas/decision/DecisionCacheTelemetry.v1.schema.json +20 -0
- package/schemas/decision/DecisionChampionChallenger.v1.schema.json +100 -0
- package/schemas/decision/DecisionCompileCacheEntry.v1.schema.json +35 -0
- package/schemas/decision/DecisionCompileCacheIdentity.v1.schema.json +26 -0
- package/schemas/decision/DecisionCompileCacheTombstone.v1.schema.json +31 -0
- package/schemas/decision/DecisionContextEvidence.v1.schema.json +136 -0
- package/schemas/decision/DecisionDefinition.schema.json +159 -0
- package/schemas/decision/DecisionDefinition.v1alpha2.schema.json +203 -0
- package/schemas/decision/DecisionDriftResponse.v1.schema.json +55 -0
- package/schemas/decision/DecisionEnsembleAggregate.v1.schema.json +86 -0
- package/schemas/decision/DecisionEnsembleIntegrityReport.v1.schema.json +64 -0
- package/schemas/decision/DecisionEnsemblePolicy.v1.schema.json +130 -0
- package/schemas/decision/DecisionGraph.v1.schema.json +77 -0
- package/schemas/decision/DecisionJob.v1.schema.json +71 -0
- package/schemas/decision/DecisionLifecyclePolicy.v1.schema.json +52 -0
- package/schemas/decision/DecisionProjectionPolicy.v1.schema.json +65 -0
- package/schemas/decision/DecisionProviderPrefixCompatibility.v1.schema.json +45 -0
- package/schemas/decision/DecisionProviderPrefixEvidence.v1.schema.json +17 -0
- package/schemas/decision/DecisionProviderPrefixIdentity.v1.schema.json +36 -0
- package/schemas/decision/DecisionResult.schema.json +524 -0
- package/schemas/decision/DecisionResult.v1alpha2.schema.json +619 -0
- package/schemas/decision/DecisionResultCacheEntry.v1.schema.json +53 -0
- package/schemas/decision/DecisionReview.schema.json +29 -0
- package/schemas/decision/DecisionRuleset.schema.json +313 -0
- package/schemas/decision/DecisionRuleset.v1alpha2.schema.json +313 -0
- package/schemas/decision/DecisionTelemetryTrace.v1.schema.json +95 -0
- package/schemas/decision/RulesetResult.schema.json +721 -0
- package/schemas/decision/RulesetResult.v1alpha2.schema.json +891 -0
- package/schemas/security/pr-evidence-receipt.v1.schema.json +77 -0
- package/schemas/security/threat-assessment-report.v1.schema.json +71 -1
- package/tools/agents/deploy-agents.mjs +21 -6
- package/tools/agents/providers/base.mjs +7 -4
- package/tools/agents/providers/codex.mjs +1 -1
- package/tools/agents/providers/grok-build.d.mts +7 -0
- package/tools/agents/providers/grok-build.mjs +249 -9
- package/tools/agents/providers/model-role.mjs +6 -3
- package/tools/agents/providers/muse-hooks.mjs +785 -0
- package/tools/agents/providers/muse-paths.mjs +112 -0
- package/tools/agents/providers/muse.mjs +336 -0
|
@@ -0,0 +1,187 @@
|
|
|
1
|
+
import { basename, extname } from 'node:path';
|
|
2
|
+
import { SessionContractError, } from '../contracts.js';
|
|
3
|
+
import { readBoundedText } from '../readers.js';
|
|
4
|
+
export const GROK_BUILD_ADAPTER_VERSION = '1.0.0';
|
|
5
|
+
export const GROK_BUILD_CLI_EXPORT_SCHEMA_VERSION = '1.0.0';
|
|
6
|
+
export const GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS = 'grok-build-cli-markdown-export';
|
|
7
|
+
/**
|
|
8
|
+
* Imports the documented `grok export <session-id> <file>` surface.
|
|
9
|
+
*
|
|
10
|
+
* The public export contract is intentionally lossy. Direct reads from
|
|
11
|
+
* $GROK_HOME/sessions are prohibited until a released native schema has been
|
|
12
|
+
* qualified independently.
|
|
13
|
+
*/
|
|
14
|
+
export class GrokBuildSessionAdapter {
|
|
15
|
+
limits;
|
|
16
|
+
provider = 'grok-build';
|
|
17
|
+
adapterVersion = GROK_BUILD_ADAPTER_VERSION;
|
|
18
|
+
disposition = 'implemented';
|
|
19
|
+
supportedOperations = ['inspect', 'stream'];
|
|
20
|
+
acquisitionModes = ['manual-export'];
|
|
21
|
+
constructor(limits) {
|
|
22
|
+
this.limits = limits;
|
|
23
|
+
}
|
|
24
|
+
async *discover(_scope) {
|
|
25
|
+
throw new SessionContractError('UNSUPPORTED_OPERATION', 'Grok Build native-store discovery is disabled. Run `grok sessions list`, then '
|
|
26
|
+
+ '`grok export <session-id> <session-id>.md` and import that authorized export.');
|
|
27
|
+
}
|
|
28
|
+
async inspect(source) {
|
|
29
|
+
await this.readSource(source);
|
|
30
|
+
return {
|
|
31
|
+
sourceSchemaVersion: GROK_BUILD_CLI_EXPORT_SCHEMA_VERSION,
|
|
32
|
+
consistency: 'complete',
|
|
33
|
+
operationalState: 'available',
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
async *stream(source, cursor) {
|
|
37
|
+
const parsed = await this.readSource(source);
|
|
38
|
+
const start = parseCursor(cursor?.value);
|
|
39
|
+
for (const [sequence, block] of parsed.blocks.entries()) {
|
|
40
|
+
if (sequence < start)
|
|
41
|
+
continue;
|
|
42
|
+
if (block.heading === 'Tools') {
|
|
43
|
+
for (const tool of parseTools(block.text, sequence))
|
|
44
|
+
yield {
|
|
45
|
+
nativeSessionId: parsed.sessionId,
|
|
46
|
+
nativeEventId: undefined,
|
|
47
|
+
sequence: tool.sequence,
|
|
48
|
+
kind: 'tool-call',
|
|
49
|
+
role: 'tool',
|
|
50
|
+
toolName: tool.name,
|
|
51
|
+
occurredAt: undefined,
|
|
52
|
+
text: tool.text,
|
|
53
|
+
rawReference: { locatorClass: source.locatorClass, sequence },
|
|
54
|
+
extensions: provenance(source, parsed.sessionId, 'Tools'),
|
|
55
|
+
};
|
|
56
|
+
continue;
|
|
57
|
+
}
|
|
58
|
+
yield {
|
|
59
|
+
nativeSessionId: parsed.sessionId,
|
|
60
|
+
nativeEventId: undefined,
|
|
61
|
+
sequence: sequence * 1_000,
|
|
62
|
+
kind: 'message',
|
|
63
|
+
role: block.heading === 'User' ? 'user' : 'assistant',
|
|
64
|
+
occurredAt: undefined,
|
|
65
|
+
text: block.text,
|
|
66
|
+
rawReference: { locatorClass: source.locatorClass, sequence },
|
|
67
|
+
extensions: provenance(source, parsed.sessionId, block.heading),
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async readSource(source) {
|
|
72
|
+
if (source.locatorClass !== GROK_BUILD_CLI_EXPORT_LOCATOR_CLASS) {
|
|
73
|
+
throw new SessionContractError('UNSUPPORTED_OPERATION', 'Grok Build accepts only a documented `grok export` Markdown transcript; '
|
|
74
|
+
+ 'native session files, Grok Bot exports, and Cursor stores are not supported.');
|
|
75
|
+
}
|
|
76
|
+
const filename = basename(source.locator, extname(source.locator));
|
|
77
|
+
if (extname(source.locator).toLowerCase() !== '.md' || !UUID.test(filename)) {
|
|
78
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Grok Build export filename must be <session-id>.md so the documented CLI session ID is preserved.');
|
|
79
|
+
}
|
|
80
|
+
const { value } = await readBoundedText({
|
|
81
|
+
selectedPath: source.locator,
|
|
82
|
+
allowedRoots: source.authorizedScope.allowedRoots,
|
|
83
|
+
}, this.limits);
|
|
84
|
+
const blocks = validateGrokBuildMarkdown(value);
|
|
85
|
+
return { sessionId: filename.toLowerCase(), blocks };
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
const UUID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
89
|
+
export function validateGrokBuildMarkdown(value) {
|
|
90
|
+
const blocks = parseBlocks(value);
|
|
91
|
+
for (const [sequence, block] of blocks.entries()) {
|
|
92
|
+
if (block.heading === 'Tools')
|
|
93
|
+
parseTools(block.text, sequence);
|
|
94
|
+
}
|
|
95
|
+
if (blocks.length === 0 || !blocks.some((block) => block.heading === 'User')) {
|
|
96
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'Unrecognized Grok Build CLI export; expected exact `## User`, `## Assistant`, or `## Tools` headings.');
|
|
97
|
+
}
|
|
98
|
+
return blocks;
|
|
99
|
+
}
|
|
100
|
+
function parseBlocks(value) {
|
|
101
|
+
const blocks = [];
|
|
102
|
+
let current;
|
|
103
|
+
const flush = () => {
|
|
104
|
+
if (!current)
|
|
105
|
+
return;
|
|
106
|
+
const text = current.lines.join('\n').trim();
|
|
107
|
+
if (!text && current.heading === 'Tools') {
|
|
108
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'Grok Build tools block is empty');
|
|
109
|
+
}
|
|
110
|
+
if (text)
|
|
111
|
+
blocks.push({ heading: current.heading, text });
|
|
112
|
+
};
|
|
113
|
+
for (const line of value.replace(/\r\n/g, '\n').split('\n')) {
|
|
114
|
+
const match = /^## (User|Assistant|Tools)$/.exec(line);
|
|
115
|
+
if (match) {
|
|
116
|
+
flush();
|
|
117
|
+
current = { heading: match[1], lines: [] };
|
|
118
|
+
}
|
|
119
|
+
else if (/^##\s+/.test(line)) {
|
|
120
|
+
throw new SessionContractError('SCHEMA_DRIFT', `unknown Grok Build CLI export heading: ${line}`);
|
|
121
|
+
}
|
|
122
|
+
else if (current) {
|
|
123
|
+
current.lines.push(line);
|
|
124
|
+
}
|
|
125
|
+
else if (line.trim()) {
|
|
126
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'unexpected content before the first Grok Build CLI export heading');
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
flush();
|
|
130
|
+
return blocks;
|
|
131
|
+
}
|
|
132
|
+
function parseTools(text, blockSequence) {
|
|
133
|
+
const lines = text.split('\n').filter((line) => line.trim());
|
|
134
|
+
if (lines.length === 0 || lines.length > 1_000) {
|
|
135
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'Grok Build tools block has no summaries or exceeds 1,000 summaries');
|
|
136
|
+
}
|
|
137
|
+
return lines.map((line, index) => {
|
|
138
|
+
const match = /^- (.+)$/.exec(line);
|
|
139
|
+
if (!match) {
|
|
140
|
+
throw new SessionContractError('SCHEMA_DRIFT', `unrecognized Grok Build tool summary: ${line}`);
|
|
141
|
+
}
|
|
142
|
+
const summary = match[1];
|
|
143
|
+
const name = summary.split(/:| \(/, 1)[0]?.trim();
|
|
144
|
+
if (!name) {
|
|
145
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'empty Grok Build tool summary');
|
|
146
|
+
}
|
|
147
|
+
return { sequence: blockSequence * 1_000 + index, name, text: summary };
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
function provenance(source, sessionId, heading) {
|
|
151
|
+
return {
|
|
152
|
+
lifecycle: 'unknown-at-import',
|
|
153
|
+
provenance: {
|
|
154
|
+
product: 'grok-build',
|
|
155
|
+
acquisition: 'grok-cli-export-markdown',
|
|
156
|
+
exportCommand: `grok export ${sessionId} ${sessionId}.md`,
|
|
157
|
+
sourceSchema: GROK_BUILD_CLI_EXPORT_SCHEMA_VERSION,
|
|
158
|
+
heading,
|
|
159
|
+
nativeStoreInspected: false,
|
|
160
|
+
originalFilename: basename(source.locator),
|
|
161
|
+
},
|
|
162
|
+
identity: {
|
|
163
|
+
nativeSessionIdKnown: true,
|
|
164
|
+
nativeEventIdKnown: false,
|
|
165
|
+
},
|
|
166
|
+
lossReport: {
|
|
167
|
+
lossless: false,
|
|
168
|
+
unavailableInCliExport: [
|
|
169
|
+
'timestamps', 'model', 'grokVersion', 'workingDirectory', 'toolResults',
|
|
170
|
+
'attachments', 'fileSnapshots', 'compaction', 'lineage', 'subagents',
|
|
171
|
+
],
|
|
172
|
+
},
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
function parseCursor(value) {
|
|
176
|
+
if (!value)
|
|
177
|
+
return 0;
|
|
178
|
+
if (!/^\d+$/.test(value)) {
|
|
179
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'invalid Grok Build export cursor');
|
|
180
|
+
}
|
|
181
|
+
const cursor = Number(value);
|
|
182
|
+
if (!Number.isSafeInteger(cursor)) {
|
|
183
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'invalid Grok Build export cursor');
|
|
184
|
+
}
|
|
185
|
+
return cursor;
|
|
186
|
+
}
|
|
187
|
+
//# sourceMappingURL=grok-build.js.map
|
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Muse Code session adapter — manual export only, trajectory-first.
|
|
3
|
+
*
|
|
4
|
+
* Muse Code journals model calls, tool runs, and approvals to an append-only
|
|
5
|
+
* session log and projects it into a self-contained JSON document via
|
|
6
|
+
* `muse export` (also surfaced as `/export trajectory`). The adapter ingests
|
|
7
|
+
* ONLY those explicit operator-supplied export documents, gated on the
|
|
8
|
+
* document's `export_schema_version` major (currently `1`); unknown majors
|
|
9
|
+
* fail closed with `UNKNOWN_SCHEMA_MAJOR`, as with peer native-export
|
|
10
|
+
* adapters.
|
|
11
|
+
*
|
|
12
|
+
* Auto-discovery is unsupported and must never scrape home directories or
|
|
13
|
+
* invent session roots. The documented candidate native root
|
|
14
|
+
* (`$XDG_DATA_HOME/muse/sessions/YYYY/MM/DD/<session-id>/session.jsonl`,
|
|
15
|
+
* default `~/.local/share/muse/sessions`) is NOT authorized or implemented
|
|
16
|
+
* here; a future evidence-gated `--muse-root` discover path remains the
|
|
17
|
+
* route to native discovery (#222 PR B).
|
|
18
|
+
*
|
|
19
|
+
* Trajectory shape follows the documented export format at
|
|
20
|
+
* https://dev.meta.ai/docs/cookbook/audit-agent-sessions: top-level
|
|
21
|
+
* `export_schema_version`, `redaction`, `exporter_version`, `session_build`,
|
|
22
|
+
* `session_terminated_abnormally`, per-stream `sessions` summaries, ordered
|
|
23
|
+
* `events` elements with `envelope`/`payload`, and `diagnostics` counters.
|
|
24
|
+
* Approval, tool, and model-lifecycle facts are preserved with provenance
|
|
25
|
+
* under `extensions['native.muse']`.
|
|
26
|
+
*
|
|
27
|
+
* Live-evidence notes (real `muse export`, Muse Code 1.3.0, build
|
|
28
|
+
* `3c572bc734`, 2026-09-24): the document carries exactly one `sessions[]`
|
|
29
|
+
* summary per exported parent session; subagents appear only inside
|
|
30
|
+
* `sessions[0].accepted_spawns[]` as spawn handles, never as extra summaries.
|
|
31
|
+
* Every merged record event carries its own `envelope.stream.id` (always the
|
|
32
|
+
* parent here), so attribution reads the envelope per event. Subagent tool
|
|
33
|
+
* runs are NOT merged — they live in `subagent/<child_session_id>/session.jsonl`
|
|
34
|
+
* under their own stream id; only `subagent.control.*` records (26 in the
|
|
35
|
+
* probe) are merged, linked via `child_session_bound.child_session_id` /
|
|
36
|
+
* `start_attested.subagent_session_id`. CRITICAL: `subagent_id` (spawn handle)
|
|
37
|
+
* and `child_session_id` (child session/dir identity) are distinct values and
|
|
38
|
+
* must never be conflated. Gap markers carry `"envelope": null` and are
|
|
39
|
+
* skipped, never fabricated into records.
|
|
40
|
+
*
|
|
41
|
+
* @see docs/providers/muse-sessions.md
|
|
42
|
+
* @issue #232
|
|
43
|
+
*/
|
|
44
|
+
import { z } from 'zod';
|
|
45
|
+
import { SessionContractError, assertSupportedSchemaMajor, } from '../contracts.js';
|
|
46
|
+
import { readBoundedJson } from '../readers.js';
|
|
47
|
+
export const MUSE_ADAPTER_VERSION = '1.0.0';
|
|
48
|
+
export const MUSE_EXPORT_SCHEMA_VERSION = '1.0.0';
|
|
49
|
+
export const MUSE_EXPORT_SCHEMA_MAJOR = 1;
|
|
50
|
+
export const MUSE_LOCATOR_CLASS = 'manual-export';
|
|
51
|
+
const Rfc3339Schema = z.string().refine((value) => /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/.test(value)
|
|
52
|
+
&& !Number.isNaN(Date.parse(value)), 'timestamp must be RFC 3339 with an explicit UTC offset');
|
|
53
|
+
/**
|
|
54
|
+
* One log line projected by `muse export`. Per the documented format, each
|
|
55
|
+
* record element is an envelope `{sequence, recorded_at, record_type,
|
|
56
|
+
* durability, payload_type, payload}`; the interesting content is
|
|
57
|
+
* `payload.event.kind` (a task-lifecycle or runtime event) or `payload_type`
|
|
58
|
+
* (a stream fact). Live exports (Muse Code 1.3.0) also carry `id`,
|
|
59
|
+
* `causation_id`, `schema_version`, `payload_schema_version`, and a
|
|
60
|
+
* `stream: {kind, id}` block on every record envelope; gap markers carry
|
|
61
|
+
* `"envelope": null` instead.
|
|
62
|
+
*/
|
|
63
|
+
const MuseStreamSchema = z.object({
|
|
64
|
+
kind: z.string().optional(),
|
|
65
|
+
id: z.string().optional(),
|
|
66
|
+
}).passthrough();
|
|
67
|
+
const MuseEnvelopeSchema = z.object({
|
|
68
|
+
sequence: z.number().int().nonnegative(),
|
|
69
|
+
id: z.string().optional(),
|
|
70
|
+
causation_id: z.string().nullish(),
|
|
71
|
+
schema_version: z.union([z.number(), z.string()]).optional(),
|
|
72
|
+
payload_schema_version: z.union([z.number(), z.string()]).optional(),
|
|
73
|
+
stream: MuseStreamSchema.optional(),
|
|
74
|
+
// Muse Code 1.4.0 exports epoch microseconds; RFC 3339 strings stay valid.
|
|
75
|
+
recorded_at: z.union([z.string(), z.number().int().nonnegative()]).optional(),
|
|
76
|
+
record_type: z.string().optional(),
|
|
77
|
+
durability: z.string().optional(),
|
|
78
|
+
payload_type: z.string().optional(),
|
|
79
|
+
payload: z.object({
|
|
80
|
+
event: z.object({ kind: z.string().min(1) }).passthrough().optional(),
|
|
81
|
+
}).passthrough().optional(),
|
|
82
|
+
}).passthrough();
|
|
83
|
+
/**
|
|
84
|
+
* Record events carry a record envelope, validated strictly. Every other
|
|
85
|
+
* event kind is an audit marker: `gap` carries `"envelope": null`, and
|
|
86
|
+
* `retained_frame` (Muse Code 1.4.0) carries a transaction frame
|
|
87
|
+
* (`children`, `transaction_id`, `content_sha256`) instead of a record.
|
|
88
|
+
* Markers are never fabricated into provider records.
|
|
89
|
+
*/
|
|
90
|
+
const MuseRecordEventSchema = z.object({
|
|
91
|
+
kind: z.literal('record'),
|
|
92
|
+
envelope: MuseEnvelopeSchema,
|
|
93
|
+
}).passthrough();
|
|
94
|
+
const MuseMarkerEventSchema = z.object({
|
|
95
|
+
kind: z.string().min(1).refine((kind) => kind !== 'record'),
|
|
96
|
+
envelope: z.record(z.string(), z.unknown()).nullish(),
|
|
97
|
+
}).passthrough();
|
|
98
|
+
const MuseExportEventSchema = z.union([MuseRecordEventSchema, MuseMarkerEventSchema]);
|
|
99
|
+
const MuseAcceptedSpawnSchema = z.object({
|
|
100
|
+
subagent_id: z.string().optional(),
|
|
101
|
+
agent_path: z.string().optional(),
|
|
102
|
+
role: z.string().optional(),
|
|
103
|
+
parent_session_id: z.string().optional(),
|
|
104
|
+
}).passthrough();
|
|
105
|
+
const MuseSessionSummarySchema = z.object({
|
|
106
|
+
session_id: z.string().min(1),
|
|
107
|
+
turn_count: z.number().int().nonnegative().optional(),
|
|
108
|
+
step_count: z.number().int().nonnegative().optional(),
|
|
109
|
+
// Live evidence: one summary per exported parent session; subagents appear
|
|
110
|
+
// only here, as spawn handles (subagent_id), never as extra summaries.
|
|
111
|
+
accepted_spawns: z.array(MuseAcceptedSpawnSchema).optional(),
|
|
112
|
+
session_end: z.object({
|
|
113
|
+
exit_reason: z.string().optional(),
|
|
114
|
+
uptime_ms: z.number().nonnegative().optional(),
|
|
115
|
+
}).passthrough().optional(),
|
|
116
|
+
}).passthrough();
|
|
117
|
+
const MuseDiagnosticsSchema = z.object({
|
|
118
|
+
unparseable_lines: z.number().int().nonnegative().optional(),
|
|
119
|
+
unknown_payload_kinds: z.number().int().nonnegative().optional(),
|
|
120
|
+
gaps: z.number().int().nonnegative().optional(),
|
|
121
|
+
omitted_live_only: z.number().int().nonnegative().optional(),
|
|
122
|
+
duplicate_records: z.number().int().nonnegative().optional(),
|
|
123
|
+
}).passthrough();
|
|
124
|
+
const MuseTrajectorySchema = z.object({
|
|
125
|
+
export_schema_version: z.number().int().nonnegative(),
|
|
126
|
+
redaction: z.string().optional(),
|
|
127
|
+
exporter_version: z.object({ display: z.string() }).passthrough().optional(),
|
|
128
|
+
session_build: z.object({ display: z.string() }).passthrough().optional(),
|
|
129
|
+
session_terminated_abnormally: z.boolean().optional(),
|
|
130
|
+
sessions: z.array(MuseSessionSummarySchema).min(1),
|
|
131
|
+
events: z.array(MuseExportEventSchema),
|
|
132
|
+
diagnostics: MuseDiagnosticsSchema.optional(),
|
|
133
|
+
}).passthrough();
|
|
134
|
+
function isRecordEvent(event) {
|
|
135
|
+
return event.kind === 'record';
|
|
136
|
+
}
|
|
137
|
+
export class MuseSessionAdapter {
|
|
138
|
+
limits;
|
|
139
|
+
provider = 'muse';
|
|
140
|
+
adapterVersion = MUSE_ADAPTER_VERSION;
|
|
141
|
+
disposition = 'manual-only';
|
|
142
|
+
supportedOperations = ['inspect', 'stream'];
|
|
143
|
+
acquisitionModes = ['manual-export'];
|
|
144
|
+
constructor(limits) {
|
|
145
|
+
this.limits = limits;
|
|
146
|
+
}
|
|
147
|
+
async *discover(_scope) {
|
|
148
|
+
throw new SessionContractError('UNSUPPORTED_OPERATION', 'Muse Code session auto-discover is unsupported: the native log under '
|
|
149
|
+
+ '$XDG_DATA_HOME/muse/sessions uses an internal format. Run `muse export --session '
|
|
150
|
+
+ '<id-or-session.jsonl>` and select that trajectory file. AIWG does not scrape home '
|
|
151
|
+
+ 'directories for this provider.');
|
|
152
|
+
}
|
|
153
|
+
async inspect(source) {
|
|
154
|
+
this.assertManualExport(source);
|
|
155
|
+
const { trajectory } = await this.readTrajectory(source);
|
|
156
|
+
for (const event of trajectory.events)
|
|
157
|
+
this.parseEvent(event);
|
|
158
|
+
return {
|
|
159
|
+
sourceSchemaVersion: MUSE_EXPORT_SCHEMA_VERSION,
|
|
160
|
+
consistency: trajectory.session_terminated_abnormally === false ? 'complete' : 'provisional',
|
|
161
|
+
operationalState: 'available',
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
async *stream(source, cursor) {
|
|
165
|
+
this.assertManualExport(source);
|
|
166
|
+
const { trajectory, bytesRead } = await this.readTrajectory(source);
|
|
167
|
+
const start = parseEventCursor(cursor?.value);
|
|
168
|
+
const spawns = acceptedSpawnsById(trajectory);
|
|
169
|
+
let index = 0;
|
|
170
|
+
for (const event of trajectory.events) {
|
|
171
|
+
// Cursor positions are raw event positions so resume stays aligned
|
|
172
|
+
// even when gap markers are skipped.
|
|
173
|
+
const position = index;
|
|
174
|
+
index += 1;
|
|
175
|
+
if (position < start)
|
|
176
|
+
continue;
|
|
177
|
+
// Gap/retained-frame markers carry no record payload: skip them, never
|
|
178
|
+
// fabricate a ProviderRecord for one.
|
|
179
|
+
if (!isRecordEvent(event))
|
|
180
|
+
continue;
|
|
181
|
+
yield this.toProviderRecord(trajectory, bytesRead, event.envelope, spawns, event, position);
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
async readTrajectory(source) {
|
|
185
|
+
let value;
|
|
186
|
+
let bytesRead;
|
|
187
|
+
try {
|
|
188
|
+
({ value, bytesRead } = await readBoundedJson({ selectedPath: source.locator, allowedRoots: source.authorizedScope.allowedRoots }, this.limits));
|
|
189
|
+
}
|
|
190
|
+
catch (error) {
|
|
191
|
+
if (error instanceof SessionContractError && error.code === 'SCHEMA_DRIFT') {
|
|
192
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'muse export document is not valid JSON');
|
|
193
|
+
}
|
|
194
|
+
throw error;
|
|
195
|
+
}
|
|
196
|
+
const parsed = MuseTrajectorySchema.safeParse(value);
|
|
197
|
+
if (!parsed.success) {
|
|
198
|
+
throw new SessionContractError('MALFORMED_SOURCE', 'input is not a declared muse export trajectory document');
|
|
199
|
+
}
|
|
200
|
+
assertSupportedSchemaMajor(`${parsed.data.export_schema_version}.0.0`, MUSE_EXPORT_SCHEMA_MAJOR);
|
|
201
|
+
return { trajectory: parsed.data, bytesRead };
|
|
202
|
+
}
|
|
203
|
+
parseEvent(event) {
|
|
204
|
+
eventKindOf(event);
|
|
205
|
+
}
|
|
206
|
+
toProviderRecord(trajectory, bytesRead, envelope, spawns, event, index) {
|
|
207
|
+
// Attribute by the event's own stream id; fall back to the document's
|
|
208
|
+
// first session summary only when the stream block is absent. Live
|
|
209
|
+
// evidence (Muse Code 1.3.0) shows merged events always carry the parent
|
|
210
|
+
// id here, so never assume sessions[0] without reading the envelope.
|
|
211
|
+
const nativeSessionId = streamSessionIdOf(envelope) ?? trajectory.sessions[0].session_id;
|
|
212
|
+
const payload = envelope.payload ?? {};
|
|
213
|
+
const payloadRecord = payload;
|
|
214
|
+
const eventKind = eventKindOf(event);
|
|
215
|
+
const toolName = toolNameOf(payloadRecord);
|
|
216
|
+
const policyDecision = stringField(payloadRecord, 'policy_decision');
|
|
217
|
+
const operation = stringField(payloadRecord, 'operation');
|
|
218
|
+
const decision = stringField(payloadRecord, 'decision');
|
|
219
|
+
const approvalOutcome = stringField(payloadRecord, 'outcome');
|
|
220
|
+
const decisionSource = objectField(payloadRecord, 'decision_source');
|
|
221
|
+
const linkage = subagentLinkageOf(payloadRecord);
|
|
222
|
+
const spawnContext = spawnContextOf(spawns, envelope.payload_type, linkage.subagentId);
|
|
223
|
+
return {
|
|
224
|
+
nativeSessionId,
|
|
225
|
+
nativeEventId: `muse-seq-${envelope.sequence}`,
|
|
226
|
+
sequence: index,
|
|
227
|
+
kind: eventKind,
|
|
228
|
+
role: undefined,
|
|
229
|
+
participant: undefined,
|
|
230
|
+
toolName: toolName ?? undefined,
|
|
231
|
+
toolCallId: undefined,
|
|
232
|
+
model: undefined,
|
|
233
|
+
entities: [],
|
|
234
|
+
occurredAt: occurredAtOf(envelope.recorded_at) ?? undefined,
|
|
235
|
+
text: describeEvent(eventKind, envelope.sequence, {
|
|
236
|
+
operation, policyDecision, decision, approvalOutcome, decisionSource,
|
|
237
|
+
}),
|
|
238
|
+
rawReference: { locatorClass: MUSE_LOCATOR_CLASS, sequence: index },
|
|
239
|
+
sourceCursor: String(index + 1),
|
|
240
|
+
sourceBytes: bytesRead,
|
|
241
|
+
extensions: {
|
|
242
|
+
'native.muse': compactObject({
|
|
243
|
+
eventKind,
|
|
244
|
+
recordType: event.kind,
|
|
245
|
+
payloadType: envelope.payload_type,
|
|
246
|
+
durability: envelope.durability,
|
|
247
|
+
streamKind: envelope.stream?.kind,
|
|
248
|
+
streamId: streamSessionIdOf(envelope),
|
|
249
|
+
envelopeSequence: envelope.sequence,
|
|
250
|
+
envelopeId: envelope.id,
|
|
251
|
+
causationId: envelope.causation_id,
|
|
252
|
+
exportSchemaVersion: trajectory.export_schema_version,
|
|
253
|
+
redaction: trajectory.redaction,
|
|
254
|
+
exporterVersion: trajectory.exporter_version?.display,
|
|
255
|
+
sessionBuild: trajectory.session_build?.display,
|
|
256
|
+
terminatedAbnormally: trajectory.session_terminated_abnormally,
|
|
257
|
+
operation,
|
|
258
|
+
policyDecision,
|
|
259
|
+
decision,
|
|
260
|
+
decisionSource,
|
|
261
|
+
approvalOutcome,
|
|
262
|
+
...linkage,
|
|
263
|
+
...spawnContext,
|
|
264
|
+
diagnostics: trajectory.diagnostics,
|
|
265
|
+
}),
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
assertManualExport(source) {
|
|
270
|
+
if (source.locatorClass !== MUSE_LOCATOR_CLASS) {
|
|
271
|
+
throw new SessionContractError('UNSUPPORTED_OPERATION', `Muse Code supports only locatorClass "${MUSE_LOCATOR_CLASS}" because its native log format is internal `
|
|
272
|
+
+ `(got "${source.locatorClass}"). Select an explicit \`muse export\` trajectory file.`);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Effective event kind per the documented jq projection:
|
|
278
|
+
* `payload.event.kind`, falling back to `payload_type` (a stream fact such
|
|
279
|
+
* as `approval_wait.effect.started`). Gap/retained-frame markers have no
|
|
280
|
+
* envelope, so fall back to the marker kind (e.g. `gap`).
|
|
281
|
+
*/
|
|
282
|
+
function eventKindOf(event) {
|
|
283
|
+
if (!isRecordEvent(event))
|
|
284
|
+
return event.kind;
|
|
285
|
+
const envelope = event.envelope;
|
|
286
|
+
const payload = envelope.payload;
|
|
287
|
+
const eventKind = payload?.event?.kind;
|
|
288
|
+
if (typeof eventKind === 'string' && eventKind.length > 0)
|
|
289
|
+
return eventKind;
|
|
290
|
+
const payloadType = envelope.payload_type;
|
|
291
|
+
if (typeof payloadType === 'string' && payloadType.length > 0)
|
|
292
|
+
return payloadType;
|
|
293
|
+
return event.kind;
|
|
294
|
+
}
|
|
295
|
+
/**
|
|
296
|
+
* Per-event stream session id from the envelope. Live evidence (Muse Code
|
|
297
|
+
* 1.3.0) shows this is always the exported parent session id for merged
|
|
298
|
+
* record events; subagent tool runs are not merged at all.
|
|
299
|
+
*/
|
|
300
|
+
function streamSessionIdOf(envelope) {
|
|
301
|
+
const streamId = envelope.stream?.id;
|
|
302
|
+
return typeof streamId === 'string' && streamId.length > 0 ? streamId : null;
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Spawn handles from `sessions[0].accepted_spawns[]`, keyed by subagent_id.
|
|
306
|
+
* These are the spawn-side keys for joining merged control-plane records to
|
|
307
|
+
* child sessions; they are NOT child session ids.
|
|
308
|
+
*/
|
|
309
|
+
function acceptedSpawnsById(trajectory) {
|
|
310
|
+
const spawns = new Map();
|
|
311
|
+
for (const spawn of trajectory.sessions[0].accepted_spawns ?? []) {
|
|
312
|
+
if (typeof spawn.subagent_id === 'string' && spawn.subagent_id.length > 0) {
|
|
313
|
+
spawns.set(spawn.subagent_id, { agentPath: spawn.agent_path, role: spawn.role });
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return spawns;
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Subagent spawn/child linkage from control-plane payloads. CRITICAL: live
|
|
320
|
+
* evidence (Muse Code 1.3.0) shows `subagent_id` is the spawn handle while
|
|
321
|
+
* `child_session_id` (from `child_session_bound`) and `subagent_session_id`
|
|
322
|
+
* (from `start_attested`) are the child session identity — distinct values,
|
|
323
|
+
* also naming the `subagent/<child-id>/session.jsonl` directories. Never
|
|
324
|
+
* conflate the two.
|
|
325
|
+
*/
|
|
326
|
+
function subagentLinkageOf(payload) {
|
|
327
|
+
const record = objectField(payload, 'record');
|
|
328
|
+
const event = objectField(payload, 'event');
|
|
329
|
+
return compactObject({
|
|
330
|
+
subagentId: record ? stringField(record, 'subagent_id') ?? undefined : undefined,
|
|
331
|
+
childSessionId: record ? stringField(record, 'child_session_id') ?? undefined : undefined,
|
|
332
|
+
subagentSessionId: record ? stringField(record, 'subagent_session_id') ?? undefined : undefined,
|
|
333
|
+
eventChildSessionId: event ? stringField(event, 'child_session_id') ?? undefined : undefined,
|
|
334
|
+
sourceSessionId: stringField(payload, 'source_session_id') ?? undefined,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Human context for a merged subagent control-plane record, joined against
|
|
339
|
+
* the document's accepted spawns. The join key is the spawn handle
|
|
340
|
+
* (subagent_id); the child session id stays separate.
|
|
341
|
+
*/
|
|
342
|
+
function spawnContextOf(spawns, payloadType, subagentId) {
|
|
343
|
+
if (payloadType == null || !payloadType.startsWith('subagent.control.'))
|
|
344
|
+
return {};
|
|
345
|
+
if (subagentId == null)
|
|
346
|
+
return {};
|
|
347
|
+
const spawn = spawns.get(subagentId);
|
|
348
|
+
if (!spawn)
|
|
349
|
+
return {};
|
|
350
|
+
return compactObject({ spawnAgentPath: spawn.agentPath, spawnRole: spawn.role });
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* `side_effect_intent` carries `operation: tool:<name>` (documented as
|
|
354
|
+
* `operation: tool:bash`); extract the tool name only from that documented
|
|
355
|
+
* shape.
|
|
356
|
+
*/
|
|
357
|
+
function toolNameOf(payload) {
|
|
358
|
+
const operation = stringField(payload, 'operation');
|
|
359
|
+
if (!operation)
|
|
360
|
+
return null;
|
|
361
|
+
const match = /^tool:(.+)$/.exec(operation);
|
|
362
|
+
return match ? match[1] : null;
|
|
363
|
+
}
|
|
364
|
+
function stringField(payload, key) {
|
|
365
|
+
const value = payload[key];
|
|
366
|
+
return typeof value === 'string' && value.length > 0 ? value : null;
|
|
367
|
+
}
|
|
368
|
+
function objectField(payload, key) {
|
|
369
|
+
const value = payload[key];
|
|
370
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
371
|
+
? value
|
|
372
|
+
: null;
|
|
373
|
+
}
|
|
374
|
+
function occurredAtOf(recordedAt) {
|
|
375
|
+
if (typeof recordedAt === 'number') {
|
|
376
|
+
// Epoch microseconds (Muse Code 1.4.0 export and native log).
|
|
377
|
+
const date = new Date(Math.floor(recordedAt / 1000));
|
|
378
|
+
return Number.isNaN(date.getTime()) ? null : date.toISOString();
|
|
379
|
+
}
|
|
380
|
+
if (!recordedAt)
|
|
381
|
+
return null;
|
|
382
|
+
return Rfc3339Schema.safeParse(recordedAt).success ? recordedAt : null;
|
|
383
|
+
}
|
|
384
|
+
function describeEvent(eventKind, sequence, provenance) {
|
|
385
|
+
const parts = [`muse export trajectory event ${eventKind} (sequence ${sequence})`];
|
|
386
|
+
if (provenance.operation)
|
|
387
|
+
parts.push(`operation=${provenance.operation}`);
|
|
388
|
+
if (provenance.policyDecision)
|
|
389
|
+
parts.push(`policy_decision=${provenance.policyDecision}`);
|
|
390
|
+
if (provenance.decision)
|
|
391
|
+
parts.push(`decision=${provenance.decision}`);
|
|
392
|
+
if (provenance.decisionSource) {
|
|
393
|
+
const sourceKind = provenance.decisionSource.kind;
|
|
394
|
+
if (typeof sourceKind === 'string' && sourceKind.length > 0) {
|
|
395
|
+
parts.push(`decision_source=${sourceKind}`);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
if (provenance.approvalOutcome)
|
|
399
|
+
parts.push(`outcome=${provenance.approvalOutcome}`);
|
|
400
|
+
return parts.join(' ');
|
|
401
|
+
}
|
|
402
|
+
function compactObject(value) {
|
|
403
|
+
return Object.fromEntries(Object.entries(value).filter(([, entry]) => entry !== undefined && entry !== null));
|
|
404
|
+
}
|
|
405
|
+
function parseEventCursor(value) {
|
|
406
|
+
if (value === undefined || value === '')
|
|
407
|
+
return 0;
|
|
408
|
+
if (!/^\d+$/.test(value))
|
|
409
|
+
throw new SessionContractError('SCHEMA_DRIFT', 'muse event cursor is invalid');
|
|
410
|
+
return Number(value);
|
|
411
|
+
}
|
|
412
|
+
//# sourceMappingURL=muse.js.map
|
|
@@ -3,7 +3,7 @@ import { z } from 'zod';
|
|
|
3
3
|
export const SESSION_CONTRACT_VERSION = '1.0.0';
|
|
4
4
|
export const SESSION_PROVIDER_IDS = [
|
|
5
5
|
'claude', 'codex', 'copilot', 'cursor', 'factory', 'hermes',
|
|
6
|
-
'opencode', 'openclaw', 'openhuman', 'grokbot', 'pi', 'omp', 'deepseek-harness', 'warp', 'devin-desktop', 'generic',
|
|
6
|
+
'opencode', 'openclaw', 'openhuman', 'grokbot', 'grok-build', 'pi', 'omp', 'deepseek-harness', 'warp', 'devin-desktop', 'muse', 'generic',
|
|
7
7
|
];
|
|
8
8
|
export const SessionProviderIdSchema = z.enum(SESSION_PROVIDER_IDS);
|
|
9
9
|
export const SESSION_PROVIDER_ALIASES = Object.freeze({
|