open-multi-agent-kit 0.92.0 → 0.94.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -1
- package/README.md +2 -2
- package/dist/core/agent-session.d.ts +36 -14
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +155 -357
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/compaction/branch-summarization.d.ts +5 -1
- package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
- package/dist/core/compaction/branch-summarization.js +5 -7
- package/dist/core/compaction/branch-summarization.js.map +1 -1
- package/dist/core/compaction/compaction.d.ts +12 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +28 -15
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/extensions/builtin/command-safety-gate.d.ts +8 -0
- package/dist/core/extensions/builtin/command-safety-gate.d.ts.map +1 -1
- package/dist/core/extensions/builtin/command-safety-gate.js +23 -0
- package/dist/core/extensions/builtin/command-safety-gate.js.map +1 -1
- package/dist/core/extensions/runner.d.ts.map +1 -1
- package/dist/core/extensions/runner.js +4 -0
- package/dist/core/extensions/runner.js.map +1 -1
- package/dist/core/extensions/types.d.ts +2 -0
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/keybindings.d.ts +5 -0
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +5 -0
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/model-resolver.d.ts +41 -3
- package/dist/core/model-resolver.d.ts.map +1 -1
- package/dist/core/model-resolver.js +17 -9
- package/dist/core/model-resolver.js.map +1 -1
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +11 -1
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +3 -1
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/reasoning-router-v4-weights.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4-weights.js +9 -3
- package/dist/core/reasoning-router-v4-weights.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +94 -24
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +11 -5
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/sandbox/default-policy.d.ts +14 -0
- package/dist/core/sandbox/default-policy.d.ts.map +1 -0
- package/dist/core/sandbox/default-policy.js +58 -0
- package/dist/core/sandbox/default-policy.js.map +1 -0
- package/dist/core/sdk.d.ts.map +1 -1
- package/dist/core/sdk.js +1 -1
- package/dist/core/sdk.js.map +1 -1
- package/dist/core/session-bash-runtime.d.ts +62 -0
- package/dist/core/session-bash-runtime.d.ts.map +1 -0
- package/dist/core/session-bash-runtime.js +167 -0
- package/dist/core/session-bash-runtime.js.map +1 -0
- package/dist/core/session-bash-service.d.ts +61 -0
- package/dist/core/session-bash-service.d.ts.map +1 -0
- package/dist/core/session-bash-service.js +155 -0
- package/dist/core/session-bash-service.js.map +1 -0
- package/dist/core/session-compaction-service.d.ts +48 -0
- package/dist/core/session-compaction-service.d.ts.map +1 -0
- package/dist/core/session-compaction-service.js +250 -0
- package/dist/core/session-compaction-service.js.map +1 -0
- package/dist/core/session-file-compaction.d.ts.map +1 -1
- package/dist/core/session-file-compaction.js +39 -5
- package/dist/core/session-file-compaction.js.map +1 -1
- package/dist/core/session-termination.d.ts.map +1 -1
- package/dist/core/session-termination.js +1 -1
- package/dist/core/session-termination.js.map +1 -1
- package/dist/core/settings-manager.d.ts +3 -0
- package/dist/core/settings-manager.d.ts.map +1 -1
- package/dist/core/settings-manager.js +8 -0
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/skills-catalog-cache.d.ts +25 -0
- package/dist/core/skills-catalog-cache.d.ts.map +1 -0
- package/dist/core/skills-catalog-cache.js +123 -0
- package/dist/core/skills-catalog-cache.js.map +1 -0
- package/dist/core/skills.d.ts +6 -0
- package/dist/core/skills.d.ts.map +1 -1
- package/dist/core/skills.js +25 -4
- package/dist/core/skills.js.map +1 -1
- package/dist/core/system-prompt.d.ts.map +1 -1
- package/dist/core/system-prompt.js +2 -2
- package/dist/core/system-prompt.js.map +1 -1
- package/dist/core/tools/bash.d.ts +5 -0
- package/dist/core/tools/bash.d.ts.map +1 -1
- package/dist/core/tools/bash.js +41 -13
- package/dist/core/tools/bash.js.map +1 -1
- package/dist/core/tools/diagnostics.d.ts +29 -0
- package/dist/core/tools/diagnostics.d.ts.map +1 -0
- package/dist/core/tools/diagnostics.js +325 -0
- package/dist/core/tools/diagnostics.js.map +1 -0
- package/dist/core/tools/index.d.ts +2 -1
- package/dist/core/tools/index.d.ts.map +1 -1
- package/dist/core/tools/index.js +18 -1
- package/dist/core/tools/index.js.map +1 -1
- package/dist/core/verified-bash-adapter.d.ts +18 -1
- package/dist/core/verified-bash-adapter.d.ts.map +1 -1
- package/dist/core/verified-bash-adapter.js +38 -1
- package/dist/core/verified-bash-adapter.js.map +1 -1
- package/dist/core/verified-bash-runtime.d.ts +13 -0
- package/dist/core/verified-bash-runtime.d.ts.map +1 -0
- package/dist/core/verified-bash-runtime.js +81 -0
- package/dist/core/verified-bash-runtime.js.map +1 -0
- package/dist/index.d.ts +4 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-box.d.ts +27 -0
- package/dist/modes/interactive/components/control-panel-box.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-box.js +60 -8
- package/dist/modes/interactive/components/control-panel-box.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-layout.js +100 -45
- package/dist/modes/interactive/components/control-panel-layout.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts +9 -0
- package/dist/modes/interactive/components/control-panel-runtime-status.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-runtime-status.js +10 -8
- package/dist/modes/interactive/components/control-panel-runtime-status.js.map +1 -1
- package/dist/modes/interactive/components/control-panel-sparkles.d.ts +5 -0
- package/dist/modes/interactive/components/control-panel-sparkles.d.ts.map +1 -1
- package/dist/modes/interactive/components/control-panel-sparkles.js +14 -9
- package/dist/modes/interactive/components/control-panel-sparkles.js.map +1 -1
- package/dist/modes/interactive/components/footer.d.ts +10 -0
- package/dist/modes/interactive/components/footer.d.ts.map +1 -1
- package/dist/modes/interactive/components/footer.js +3 -3
- package/dist/modes/interactive/components/footer.js.map +1 -1
- package/dist/modes/interactive/components/status-sidebar.d.ts +49 -0
- package/dist/modes/interactive/components/status-sidebar.d.ts.map +1 -0
- package/dist/modes/interactive/components/status-sidebar.js +253 -0
- package/dist/modes/interactive/components/status-sidebar.js.map +1 -0
- package/dist/modes/interactive/interactive-mode.d.ts +9 -0
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +94 -20
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/theme/omk-neon-control.json +13 -13
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +1 -0
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/types/evidence.d.ts +1 -1
- package/dist/types/evidence.d.ts.map +1 -1
- package/dist/types/evidence.js.map +1 -1
- package/dist/utils/clipboard.d.ts.map +1 -1
- package/dist/utils/clipboard.js +19 -8
- package/dist/utils/clipboard.js.map +1 -1
- package/dist/utils/frontmatter.d.ts.map +1 -1
- package/dist/utils/frontmatter.js +31 -5
- package/dist/utils/frontmatter.js.map +1 -1
- package/docs/compaction.md +7 -0
- package/docs/docs.json +4 -0
- package/docs/environment-variables.md +94 -0
- package/docs/index.md +1 -0
- package/docs/rpc.md +5 -2
- package/docs/sdk.md +10 -4
- package/docs/settings.md +1 -0
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/subagent/agents.test.ts +86 -0
- package/examples/extensions/subagent/agents.ts +18 -4
- package/examples/extensions/subagent/capabilities.ts +15 -1
- package/examples/extensions/subagent/domain-profiles.ts +272 -0
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +15 -15
- package/package.json +10 -7
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/types/evidence.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * Evidence and verification types for OMK v0.80.3+\n *\n * Defines contracts for agent completion evidence, replay persistence,\n * merge gating, and artifact validation.\n */\n\n// ============================================================================\n// Evidence Contract\n// ============================================================================\n\nexport type EvidenceCategory =\n\t| \"feature\"\n\t| \"bugfix\"\n\t| \"refactor\"\n\t| \"research\"\n\t| \"release\"\n\t| \"security\"\n\t| \"docs\"\n\t| \"orchestration\";\n\nexport type EvidenceStatus = \"pending\" | \"gathering\" | \"satisfied\" | \"failed\" | \"waived\";\n\nexport interface EvidenceItem {\n\t/** What this evidence proves. */\n\tclaim: string;\n\t/** Category of the task. */\n\tcategory: EvidenceCategory;\n\t/** Path to artifact or command that produced it. */\n\tartifactPath?: string;\n\t/** Command that can reproduce the evidence. */\n\tverificationCommand?: string;\n\t/** SHA-256 of the artifact for integrity. */\n\thash?: string;\n\t/** When the evidence was gathered. */\n\ttimestamp: string;\n\t/** Whether the evidence is available. */\n\tstatus: EvidenceStatus;\n\t/** Receipt v3 metadata consumed by receipt-aware evidence gates. */\n\treceiptId?: string;\n\treceiptSchemaVersion?: 3;\n\t/** Domain-separated digest of the exact structured command descriptor. */\n\treceiptCommandSha256?: Sha256Hex;\n\t/** Lane that executed the verification command, when lane-scoped. */\n\treceiptLaneId?: string;\n\t/** Reason if evidence is missing or waived. */\n\tgapReason?: string;\n}\n\nexport interface TaskContract {\n\t/** Unique task / goal identifier. */\n\tgoalId: string;\n\t/** One-sentence completion claim. */\n\tcompletionClaim: string;\n\t/** Required evidence items. */\n\trequiredEvidence: EvidenceItem[];\n\t/** Remaining risk note. */\n\tfinalRisk: string;\n\t/** Verdict: can the task be considered done? */\n\tverdict: \"pass\" | \"fail\" | \"conditional\";\n\t/** ISO-8601 timestamp of contract creation. */\n\tcreatedAt: string;\n\t/** ISO-8601 timestamp of last update. */\n\tupdatedAt: string;\n}\n\n// ============================================================================\n// Replay Ledger\n// ============================================================================\n\nexport type ReplayEventType =\n\t| \"session_start\"\n\t| \"tool_call\"\n\t| \"tool_result\"\n\t| \"message\"\n\t| \"guardrail_decision\"\n\t| \"lane_grant\"\n\t| \"merge_attempt\"\n\t| \"merge_blocked\"\n\t| \"evidence_gathered\"\n\t| \"evidence_receipt\"\n\t| \"contract_created\"\n\t| \"contract_updated\"\n\t| \"checkpoint\"\n\t| \"error\"\n\t| \"transcript_repaired\"\n\t| \"tool_timeout\"\n\t| \"tool_late_settlement\"\n\t| \"workspace_mutation\";\n\n/**\n * Payload contract for `workspace_mutation` replay events. Emitters live in the\n * agent runtime; evidence gates consume these fail-closed: an event whose payload\n * does not provably target other paths in the same workspace root is treated as\n * relevant to every scope.\n */\nexport interface WorkspaceMutationReplayPayload {\n\t/** Absolute workspace root the mutation applies to. */\n\treadonly root: string;\n\t/** Root-relative normalized paths that were mutated; empty means unknown/whole workspace. */\n\treadonly paths: readonly string[];\n}\n\n// ============================================================================\n// Execution-bound evidence receipts (v3)\n// ============================================================================\n\ndeclare const SHA256_HEX_BRAND: unique symbol;\n\n/** A validated lowercase SHA-256 digest encoded as exactly 64 hexadecimal characters. */\nexport type Sha256Hex = string & { readonly [SHA256_HEX_BRAND]: \"sha256-hex\" };\n\nexport interface ArgvCommandDescriptor {\n\treadonly kind: \"argv\";\n\t/** Exact executable identity supplied by the caller. */\n\treadonly executable: string;\n\t/** Exact argument boundaries; values are never joined or whitespace-normalized. */\n\treadonly argv: readonly string[];\n}\n\nexport interface ShellCommandDescriptor {\n\treadonly kind: \"shell\";\n\t/** Exact shell identity supplied by the caller. */\n\treadonly shell: string;\n\t/** Exact script bytes decoded as a string; whitespace is significant. */\n\treadonly script: string;\n}\n\nexport type EvidenceCommandDescriptor = ArgvCommandDescriptor | ShellCommandDescriptor;\n\nexport interface MissingArtifactState {\n\treadonly path: string;\n\treadonly state: \"missing\";\n}\n\nexport interface FileArtifactState {\n\treadonly path: string;\n\treadonly state: \"file\";\n\treadonly sha256: Sha256Hex;\n\treadonly size: number;\n}\n\nexport type ArtifactState = MissingArtifactState | FileArtifactState;\n\n/** Trusted caller-selected workspace root and root-relative artifact set. */\nexport interface WorkspaceScope {\n\treadonly root: string;\n\treadonly artifactPaths: readonly string[];\n}\n\n/** A point-in-time digest of only the selected artifact set; not an immutable-workspace proof. */\nexport interface ArtifactSetWorkspaceFingerprint {\n\treadonly kind: \"artifact-set\";\n\treadonly scope: WorkspaceScope;\n\treadonly artifacts: readonly ArtifactState[];\n\treadonly manifestSha256: Sha256Hex;\n}\n\n/** Scope-limited Git workspace facts committed by a git-kind fingerprint. */\nexport interface GitWorkspaceState {\n\t/** Full hex object name of HEAD, or null while HEAD is unborn. */\n\treadonly headCommit: string | null;\n\t/** Sorted root-relative paths git reports changed (staged, unstaged, or untracked) within scope. */\n\treadonly changedPaths: readonly string[];\n\t/** SHA-256 of the scope-limited staged diff bytes (index vs HEAD). */\n\treadonly stagedDiffSha256: Sha256Hex;\n\t/** SHA-256 of the scope-limited unstaged diff bytes (work tree vs index). */\n\treadonly unstagedDiffSha256: Sha256Hex;\n\t/** Canonical digest committing changed paths, both diff digests, and every selected artifact state. */\n\treadonly dirtySha256: Sha256Hex;\n}\n\n/**\n * A point-in-time digest of a Git work-tree root: HEAD, scope-limited staged and\n * unstaged diffs, and direct states for every selected path. Direct states keep\n * ignored and index-flagged work-tree bytes content-bound independently of Git.\n */\nexport interface GitWorkspaceFingerprint {\n\treadonly kind: \"git\";\n\treadonly scope: WorkspaceScope;\n\treadonly artifacts: readonly ArtifactState[];\n\treadonly git: GitWorkspaceState;\n\treadonly manifestSha256: Sha256Hex;\n}\n\nexport type WorkspaceFingerprint = ArtifactSetWorkspaceFingerprint | GitWorkspaceFingerprint;\n\nexport interface EvidenceOutputDigest {\n\treadonly sha256: Sha256Hex;\n\treadonly byteCount: number;\n}\n\n/** Digests only; receipt v3 never carries raw output or excerpts. */\nexport interface EvidenceOutputCapture {\n\treadonly redactionPolicyId: string;\n\treadonly stdout: EvidenceOutputDigest;\n\treadonly stderr: EvidenceOutputDigest;\n}\n\n/** CLI form that produced one or more `[REDACTED]` placeholders in a persisted command. */\nexport type CommandRedactionPlaceholderType =\n\t| \"api-key-header\"\n\t| \"authorization-header\"\n\t| \"basic-auth\"\n\t| \"bearer-token\"\n\t| \"cli-option-inline\"\n\t| \"cli-option-value\"\n\t| \"cookie-header\"\n\t| \"env-assignment\"\n\t| \"known-token\"\n\t| \"url-credential\"\n\t| \"url-query\";\n\nexport interface CommandRedactionPlaceholder {\n\treadonly type: CommandRedactionPlaceholderType;\n\treadonly count: number;\n}\n\n/** Bounded description of the placeholders applied to a persisted redacted command. */\nexport interface CommandRedactionSummary {\n\treadonly policyId: string;\n\t/** Unique types in ascending order; empty when nothing was redacted. */\n\treadonly placeholders: readonly CommandRedactionPlaceholder[];\n}\n\n/**\n * Keyed commitment to the original (pre-redaction) command. The HMAC key is\n * process-internal and never persisted or exported, so this value is not\n * verifiable (and not brute-forceable) outside the executing trust boundary.\n */\nexport interface CommandHmacBinding {\n\treadonly algorithm: \"hmac-sha256\";\n\t/** Identifies the ephemeral process key generation, not the key itself. */\n\treadonly keyId: string;\n\t/** Per-binding random nonce; makes persisted MACs non-comparable. */\n\treadonly nonce: string;\n\treadonly mac: Sha256Hex;\n}\n\nexport type EvidenceReceiptStatus = \"passed\" | \"failed\" | \"timeout\" | \"aborted\";\n\nexport type EvidenceReceiptDisposition =\n\t| { readonly status: \"passed\"; readonly exitCode: 0 }\n\t| { readonly status: \"failed\"; readonly exitCode: number }\n\t| { readonly status: \"timeout\"; readonly exitCode: null }\n\t| { readonly status: \"aborted\"; readonly exitCode: null };\n\nexport type EvidenceExecutor = \"bash-tool\" | \"ci-runner\" | \"mcp\" | \"internal\";\n\nexport interface EvidenceReceiptCoreFields {\n\treadonly schemaVersion: 3;\n\treadonly receiptId: string;\n\treadonly goalId: string;\n\treadonly laneId?: string;\n\treadonly claim: string;\n\treadonly command: EvidenceCommandDescriptor;\n\treadonly cwd: string;\n\treadonly timeoutMs: number | null;\n\treadonly startedAt: string;\n\treadonly finishedAt: string;\n\treadonly durationMs: number;\n\treadonly workspaceBefore: WorkspaceFingerprint;\n\treadonly workspaceAfter: WorkspaceFingerprint;\n\treadonly output: EvidenceOutputCapture;\n\treadonly executor: EvidenceExecutor;\n\treadonly toolCallId?: string;\n\t/** Redaction metadata for the persisted `command` representation. */\n\treadonly commandRedaction?: CommandRedactionSummary;\n\t/** Keyed binding of the ORIGINAL command; required when placeholders were applied. */\n\treadonly commandBinding?: CommandHmacBinding;\n}\n\n/** Immutable execution facts. Envelope metadata is deliberately excluded from this core. */\nexport type EvidenceReceiptCore = EvidenceReceiptCoreFields & EvidenceReceiptDisposition;\n\nexport interface EvidenceReceiptLedgerBinding {\n\treadonly seq: number;\n\treadonly eventHash: Sha256Hex;\n}\n\n/**\n * Opaque metadata for an attestation verified by a separately configured trust anchor.\n * Its presence alone does not make a receipt trusted proof.\n */\nexport interface TrustedEvidenceAttestation {\n\treadonly attesterId: string;\n\treadonly keyId: string;\n\treadonly algorithm: \"ed25519\";\n\treadonly signature: string;\n\treadonly issuedAt: string;\n}\n\nexport interface EvidenceReceiptEnvelope {\n\treadonly coreSha256: Sha256Hex;\n\treadonly ledgerBinding?: EvidenceReceiptLedgerBinding;\n\treadonly trustedAttestation?: TrustedEvidenceAttestation;\n}\n\nexport interface EvidenceReceipt {\n\treadonly core: EvidenceReceiptCore;\n\treadonly envelope: EvidenceReceiptEnvelope;\n}\n\n/** Replay payload intentionally commits only the immutable core, avoiding a ledger/hash cycle. */\nexport interface EvidenceReceiptReplayPayload {\n\treadonly receiptId: string;\n\treadonly coreSha256: Sha256Hex;\n}\n\nexport interface ReplayEvent {\n\t/** Monotonic sequence number within a session. */\n\tseq: number;\n\t/** Event type. */\n\ttype: ReplayEventType;\n\t/** ISO-8601 timestamp. */\n\ttimestamp: string;\n\t/** Goal or session identifier. */\n\tgoalId: string;\n\t/** Optional lane identifier. */\n\tlaneId?: string;\n\t/** Event-specific payload. */\n\tpayload: unknown;\n\t/** SHA-256 of the serialized payload for integrity. */\n\tpayloadHash: string;\n\t/** eventHash of the previous event in the chain (\"genesis\" for the first event). */\n\tprevHash: string;\n\t/** SHA-256 over [seq, type, timestamp, goalId, laneId, payloadHash, prevHash]. */\n\teventHash: string;\n}\n\nexport interface ReplayLedgerFileIdentity {\n\treadonly dev: string;\n\treadonly ino: string;\n}\n\n/** Durable CAS tuple published atomically beside the replay JSONL. */\nexport interface ReplayLedgerHead {\n\treadonly fileIdentity: ReplayLedgerFileIdentity | null;\n\treadonly size: number;\n\treadonly lastSeq: number;\n\treadonly lastHash: string;\n}\n\n/** One chain- and committed-head-verified point-in-time ledger source. */\nexport interface VerifiedReplayLedgerSnapshot {\n\treadonly events: readonly ReplayEvent[];\n\treadonly head: ReplayLedgerHead;\n}\n\nexport interface ReplayLedger {\n\t/** Session / goal this ledger belongs to. */\n\tgoalId: string;\n\t/** Ordered event log. */\n\tevents: ReplayEvent[];\n\t/** Path where the ledger is persisted. */\n\tledgerPath: string;\n\t/** Last persisted sequence number. */\n\tlastPersistedSeq: number;\n}\n\n// ============================================================================\n// Merge Gates\n// ============================================================================\n\nexport type MergeGateStatus = \"open\" | \"blocked\" | \"conditional\";\n\n/** Compatibility policy for execution-bound evidence receipts. */\nexport type EvidenceReceiptMode = \"strict\" | \"prefer\" | \"legacy\";\n\nexport interface MergeGateResult {\n\t/** Gate identifier. */\n\tgateId: string;\n\t/** Current status. */\n\tstatus: MergeGateStatus;\n\t/** Human-readable reason. */\n\treason: string;\n\t/** Suggested remediation. */\n\tsuggestion?: string;\n\t/** Evidence that was checked. */\n\tevidenceChecked: EvidenceItem[];\n}\n\nexport interface EvidenceGateCheck {\n\t/** Which evidence item was checked. */\n\tevidenceClaim: string;\n\t/** Whether it is satisfied. */\n\tsatisfied: boolean;\n\t/** Reason if not satisfied. */\n\treason?: string;\n}\n\n// ============================================================================\n// Verify Reporter v2\n// ============================================================================\n\nexport interface OmkVerifyResultV2 {\n\tgoalId: string;\n\tstatus: \"completed\" | \"failed\" | \"blocked\" | \"partial\";\n\tsummary: string;\n\tchangedFiles: string[];\n\tevidence: EvidenceItem[];\n\trisks: string[];\n\tnextAction: string;\n\t/** Associated task contract. */\n\tcontract?: TaskContract;\n\t/** Replay ledger path. */\n\treplayLedgerPath?: string;\n\t/** Merge gate results. */\n\tmergeGates: MergeGateResult[];\n}\n\nexport interface CiReportV2 {\n\tgoalId: string;\n\tstatus: string;\n\tsummary: string;\n\tchangedFilesCount: number;\n\tevidenceCount: number;\n\trisks: string[];\n\tmarkdown: string;\n\tcontractVerdict?: string;\n\tmergeGateStatus?: string;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../src/types/evidence.ts"],"names":[],"mappings":"AAAA;;;;;GAKG","sourcesContent":["/**\n * Evidence and verification types for OMK v0.80.3+\n *\n * Defines contracts for agent completion evidence, replay persistence,\n * merge gating, and artifact validation.\n */\n\n// ============================================================================\n// Evidence Contract\n// ============================================================================\n\nexport type EvidenceCategory =\n\t| \"feature\"\n\t| \"bugfix\"\n\t| \"refactor\"\n\t| \"research\"\n\t| \"release\"\n\t| \"security\"\n\t| \"docs\"\n\t| \"orchestration\";\n\nexport type EvidenceStatus = \"pending\" | \"gathering\" | \"satisfied\" | \"failed\" | \"waived\";\n\nexport interface EvidenceItem {\n\t/** What this evidence proves. */\n\tclaim: string;\n\t/** Category of the task. */\n\tcategory: EvidenceCategory;\n\t/** Path to artifact or command that produced it. */\n\tartifactPath?: string;\n\t/** Command that can reproduce the evidence. */\n\tverificationCommand?: string;\n\t/** SHA-256 of the artifact for integrity. */\n\thash?: string;\n\t/** When the evidence was gathered. */\n\ttimestamp: string;\n\t/** Whether the evidence is available. */\n\tstatus: EvidenceStatus;\n\t/** Receipt v3 metadata consumed by receipt-aware evidence gates. */\n\treceiptId?: string;\n\treceiptSchemaVersion?: 3;\n\t/** Domain-separated digest of the exact structured command descriptor. */\n\treceiptCommandSha256?: Sha256Hex;\n\t/** Lane that executed the verification command, when lane-scoped. */\n\treceiptLaneId?: string;\n\t/** Reason if evidence is missing or waived. */\n\tgapReason?: string;\n}\n\nexport interface TaskContract {\n\t/** Unique task / goal identifier. */\n\tgoalId: string;\n\t/** One-sentence completion claim. */\n\tcompletionClaim: string;\n\t/** Required evidence items. */\n\trequiredEvidence: EvidenceItem[];\n\t/** Remaining risk note. */\n\tfinalRisk: string;\n\t/** Verdict: can the task be considered done? */\n\tverdict: \"pass\" | \"fail\" | \"conditional\";\n\t/** ISO-8601 timestamp of contract creation. */\n\tcreatedAt: string;\n\t/** ISO-8601 timestamp of last update. */\n\tupdatedAt: string;\n}\n\n// ============================================================================\n// Replay Ledger\n// ============================================================================\n\nexport type ReplayEventType =\n\t| \"session_start\"\n\t| \"tool_call\"\n\t| \"tool_result\"\n\t| \"message\"\n\t| \"guardrail_decision\"\n\t| \"lane_grant\"\n\t| \"merge_attempt\"\n\t| \"merge_blocked\"\n\t| \"evidence_gathered\"\n\t| \"evidence_receipt\"\n\t| \"contract_created\"\n\t| \"contract_updated\"\n\t| \"checkpoint\"\n\t| \"error\"\n\t| \"transcript_repaired\"\n\t| \"tool_timeout\"\n\t| \"tool_late_settlement\"\n\t| \"workspace_mutation\"\n\t| \"sandbox_audit\";\n\n/**\n * Payload contract for `workspace_mutation` replay events. Emitters live in the\n * agent runtime; evidence gates consume these fail-closed: an event whose payload\n * does not provably target other paths in the same workspace root is treated as\n * relevant to every scope.\n */\nexport interface WorkspaceMutationReplayPayload {\n\t/** Absolute workspace root the mutation applies to. */\n\treadonly root: string;\n\t/** Root-relative normalized paths that were mutated; empty means unknown/whole workspace. */\n\treadonly paths: readonly string[];\n}\n\n// ============================================================================\n// Execution-bound evidence receipts (v3)\n// ============================================================================\n\ndeclare const SHA256_HEX_BRAND: unique symbol;\n\n/** A validated lowercase SHA-256 digest encoded as exactly 64 hexadecimal characters. */\nexport type Sha256Hex = string & { readonly [SHA256_HEX_BRAND]: \"sha256-hex\" };\n\nexport interface ArgvCommandDescriptor {\n\treadonly kind: \"argv\";\n\t/** Exact executable identity supplied by the caller. */\n\treadonly executable: string;\n\t/** Exact argument boundaries; values are never joined or whitespace-normalized. */\n\treadonly argv: readonly string[];\n}\n\nexport interface ShellCommandDescriptor {\n\treadonly kind: \"shell\";\n\t/** Exact shell identity supplied by the caller. */\n\treadonly shell: string;\n\t/** Exact script bytes decoded as a string; whitespace is significant. */\n\treadonly script: string;\n}\n\nexport type EvidenceCommandDescriptor = ArgvCommandDescriptor | ShellCommandDescriptor;\n\nexport interface MissingArtifactState {\n\treadonly path: string;\n\treadonly state: \"missing\";\n}\n\nexport interface FileArtifactState {\n\treadonly path: string;\n\treadonly state: \"file\";\n\treadonly sha256: Sha256Hex;\n\treadonly size: number;\n}\n\nexport type ArtifactState = MissingArtifactState | FileArtifactState;\n\n/** Trusted caller-selected workspace root and root-relative artifact set. */\nexport interface WorkspaceScope {\n\treadonly root: string;\n\treadonly artifactPaths: readonly string[];\n}\n\n/** A point-in-time digest of only the selected artifact set; not an immutable-workspace proof. */\nexport interface ArtifactSetWorkspaceFingerprint {\n\treadonly kind: \"artifact-set\";\n\treadonly scope: WorkspaceScope;\n\treadonly artifacts: readonly ArtifactState[];\n\treadonly manifestSha256: Sha256Hex;\n}\n\n/** Scope-limited Git workspace facts committed by a git-kind fingerprint. */\nexport interface GitWorkspaceState {\n\t/** Full hex object name of HEAD, or null while HEAD is unborn. */\n\treadonly headCommit: string | null;\n\t/** Sorted root-relative paths git reports changed (staged, unstaged, or untracked) within scope. */\n\treadonly changedPaths: readonly string[];\n\t/** SHA-256 of the scope-limited staged diff bytes (index vs HEAD). */\n\treadonly stagedDiffSha256: Sha256Hex;\n\t/** SHA-256 of the scope-limited unstaged diff bytes (work tree vs index). */\n\treadonly unstagedDiffSha256: Sha256Hex;\n\t/** Canonical digest committing changed paths, both diff digests, and every selected artifact state. */\n\treadonly dirtySha256: Sha256Hex;\n}\n\n/**\n * A point-in-time digest of a Git work-tree root: HEAD, scope-limited staged and\n * unstaged diffs, and direct states for every selected path. Direct states keep\n * ignored and index-flagged work-tree bytes content-bound independently of Git.\n */\nexport interface GitWorkspaceFingerprint {\n\treadonly kind: \"git\";\n\treadonly scope: WorkspaceScope;\n\treadonly artifacts: readonly ArtifactState[];\n\treadonly git: GitWorkspaceState;\n\treadonly manifestSha256: Sha256Hex;\n}\n\nexport type WorkspaceFingerprint = ArtifactSetWorkspaceFingerprint | GitWorkspaceFingerprint;\n\nexport interface EvidenceOutputDigest {\n\treadonly sha256: Sha256Hex;\n\treadonly byteCount: number;\n}\n\n/** Digests only; receipt v3 never carries raw output or excerpts. */\nexport interface EvidenceOutputCapture {\n\treadonly redactionPolicyId: string;\n\treadonly stdout: EvidenceOutputDigest;\n\treadonly stderr: EvidenceOutputDigest;\n}\n\n/** CLI form that produced one or more `[REDACTED]` placeholders in a persisted command. */\nexport type CommandRedactionPlaceholderType =\n\t| \"api-key-header\"\n\t| \"authorization-header\"\n\t| \"basic-auth\"\n\t| \"bearer-token\"\n\t| \"cli-option-inline\"\n\t| \"cli-option-value\"\n\t| \"cookie-header\"\n\t| \"env-assignment\"\n\t| \"known-token\"\n\t| \"url-credential\"\n\t| \"url-query\";\n\nexport interface CommandRedactionPlaceholder {\n\treadonly type: CommandRedactionPlaceholderType;\n\treadonly count: number;\n}\n\n/** Bounded description of the placeholders applied to a persisted redacted command. */\nexport interface CommandRedactionSummary {\n\treadonly policyId: string;\n\t/** Unique types in ascending order; empty when nothing was redacted. */\n\treadonly placeholders: readonly CommandRedactionPlaceholder[];\n}\n\n/**\n * Keyed commitment to the original (pre-redaction) command. The HMAC key is\n * process-internal and never persisted or exported, so this value is not\n * verifiable (and not brute-forceable) outside the executing trust boundary.\n */\nexport interface CommandHmacBinding {\n\treadonly algorithm: \"hmac-sha256\";\n\t/** Identifies the ephemeral process key generation, not the key itself. */\n\treadonly keyId: string;\n\t/** Per-binding random nonce; makes persisted MACs non-comparable. */\n\treadonly nonce: string;\n\treadonly mac: Sha256Hex;\n}\n\nexport type EvidenceReceiptStatus = \"passed\" | \"failed\" | \"timeout\" | \"aborted\";\n\nexport type EvidenceReceiptDisposition =\n\t| { readonly status: \"passed\"; readonly exitCode: 0 }\n\t| { readonly status: \"failed\"; readonly exitCode: number }\n\t| { readonly status: \"timeout\"; readonly exitCode: null }\n\t| { readonly status: \"aborted\"; readonly exitCode: null };\n\nexport type EvidenceExecutor = \"bash-tool\" | \"ci-runner\" | \"mcp\" | \"internal\";\n\nexport interface EvidenceReceiptCoreFields {\n\treadonly schemaVersion: 3;\n\treadonly receiptId: string;\n\treadonly goalId: string;\n\treadonly laneId?: string;\n\treadonly claim: string;\n\treadonly command: EvidenceCommandDescriptor;\n\treadonly cwd: string;\n\treadonly timeoutMs: number | null;\n\treadonly startedAt: string;\n\treadonly finishedAt: string;\n\treadonly durationMs: number;\n\treadonly workspaceBefore: WorkspaceFingerprint;\n\treadonly workspaceAfter: WorkspaceFingerprint;\n\treadonly output: EvidenceOutputCapture;\n\treadonly executor: EvidenceExecutor;\n\treadonly toolCallId?: string;\n\t/** Redaction metadata for the persisted `command` representation. */\n\treadonly commandRedaction?: CommandRedactionSummary;\n\t/** Keyed binding of the ORIGINAL command; required when placeholders were applied. */\n\treadonly commandBinding?: CommandHmacBinding;\n}\n\n/** Immutable execution facts. Envelope metadata is deliberately excluded from this core. */\nexport type EvidenceReceiptCore = EvidenceReceiptCoreFields & EvidenceReceiptDisposition;\n\nexport interface EvidenceReceiptLedgerBinding {\n\treadonly seq: number;\n\treadonly eventHash: Sha256Hex;\n}\n\n/**\n * Opaque metadata for an attestation verified by a separately configured trust anchor.\n * Its presence alone does not make a receipt trusted proof.\n */\nexport interface TrustedEvidenceAttestation {\n\treadonly attesterId: string;\n\treadonly keyId: string;\n\treadonly algorithm: \"ed25519\";\n\treadonly signature: string;\n\treadonly issuedAt: string;\n}\n\nexport interface EvidenceReceiptEnvelope {\n\treadonly coreSha256: Sha256Hex;\n\treadonly ledgerBinding?: EvidenceReceiptLedgerBinding;\n\treadonly trustedAttestation?: TrustedEvidenceAttestation;\n}\n\nexport interface EvidenceReceipt {\n\treadonly core: EvidenceReceiptCore;\n\treadonly envelope: EvidenceReceiptEnvelope;\n}\n\n/** Replay payload intentionally commits only the immutable core, avoiding a ledger/hash cycle. */\nexport interface EvidenceReceiptReplayPayload {\n\treadonly receiptId: string;\n\treadonly coreSha256: Sha256Hex;\n}\n\nexport interface ReplayEvent {\n\t/** Monotonic sequence number within a session. */\n\tseq: number;\n\t/** Event type. */\n\ttype: ReplayEventType;\n\t/** ISO-8601 timestamp. */\n\ttimestamp: string;\n\t/** Goal or session identifier. */\n\tgoalId: string;\n\t/** Optional lane identifier. */\n\tlaneId?: string;\n\t/** Event-specific payload. */\n\tpayload: unknown;\n\t/** SHA-256 of the serialized payload for integrity. */\n\tpayloadHash: string;\n\t/** eventHash of the previous event in the chain (\"genesis\" for the first event). */\n\tprevHash: string;\n\t/** SHA-256 over [seq, type, timestamp, goalId, laneId, payloadHash, prevHash]. */\n\teventHash: string;\n}\n\nexport interface ReplayLedgerFileIdentity {\n\treadonly dev: string;\n\treadonly ino: string;\n}\n\n/** Durable CAS tuple published atomically beside the replay JSONL. */\nexport interface ReplayLedgerHead {\n\treadonly fileIdentity: ReplayLedgerFileIdentity | null;\n\treadonly size: number;\n\treadonly lastSeq: number;\n\treadonly lastHash: string;\n}\n\n/** One chain- and committed-head-verified point-in-time ledger source. */\nexport interface VerifiedReplayLedgerSnapshot {\n\treadonly events: readonly ReplayEvent[];\n\treadonly head: ReplayLedgerHead;\n}\n\nexport interface ReplayLedger {\n\t/** Session / goal this ledger belongs to. */\n\tgoalId: string;\n\t/** Ordered event log. */\n\tevents: ReplayEvent[];\n\t/** Path where the ledger is persisted. */\n\tledgerPath: string;\n\t/** Last persisted sequence number. */\n\tlastPersistedSeq: number;\n}\n\n// ============================================================================\n// Merge Gates\n// ============================================================================\n\nexport type MergeGateStatus = \"open\" | \"blocked\" | \"conditional\";\n\n/** Compatibility policy for execution-bound evidence receipts. */\nexport type EvidenceReceiptMode = \"strict\" | \"prefer\" | \"legacy\";\n\nexport interface MergeGateResult {\n\t/** Gate identifier. */\n\tgateId: string;\n\t/** Current status. */\n\tstatus: MergeGateStatus;\n\t/** Human-readable reason. */\n\treason: string;\n\t/** Suggested remediation. */\n\tsuggestion?: string;\n\t/** Evidence that was checked. */\n\tevidenceChecked: EvidenceItem[];\n}\n\nexport interface EvidenceGateCheck {\n\t/** Which evidence item was checked. */\n\tevidenceClaim: string;\n\t/** Whether it is satisfied. */\n\tsatisfied: boolean;\n\t/** Reason if not satisfied. */\n\treason?: string;\n}\n\n// ============================================================================\n// Verify Reporter v2\n// ============================================================================\n\nexport interface OmkVerifyResultV2 {\n\tgoalId: string;\n\tstatus: \"completed\" | \"failed\" | \"blocked\" | \"partial\";\n\tsummary: string;\n\tchangedFiles: string[];\n\tevidence: EvidenceItem[];\n\trisks: string[];\n\tnextAction: string;\n\t/** Associated task contract. */\n\tcontract?: TaskContract;\n\t/** Replay ledger path. */\n\treplayLedgerPath?: string;\n\t/** Merge gate results. */\n\tmergeGates: MergeGateResult[];\n}\n\nexport interface CiReportV2 {\n\tgoalId: string;\n\tstatus: string;\n\tsummary: string;\n\tchangedFilesCount: number;\n\tevidenceCount: number;\n\trisks: string[];\n\tmarkdown: string;\n\tcontractVerdict?: string;\n\tmergeGateStatus?: string;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAkCA,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"clipboard.d.ts","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAkCA,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsGjE","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead.\n\t\t\t\t\t\t\t// Await the exit code and only claim success on a clean exit, so a\n\t\t\t\t\t\t\t// failed wl-copy falls through to the xclip/OSC 52 fallbacks.\n\t\t\t\t\t\t\tconst wlCopyExit = await new Promise<number>((resolve) => {\n\t\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\t\tproc.on(\"error\", () => resolve(1));\n\t\t\t\t\t\t\t\tproc.on(\"close\", (code) => resolve(code ?? 1));\n\t\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (wlCopyExit === 0) {\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
package/dist/utils/clipboard.js
CHANGED
|
@@ -78,15 +78,26 @@ export async function copyToClipboard(text) {
|
|
|
78
78
|
try {
|
|
79
79
|
// Verify wl-copy exists (spawn errors are async and won't be caught)
|
|
80
80
|
execSync("which wl-copy", { stdio: "ignore" });
|
|
81
|
-
// wl-copy with execSync hangs due to fork behavior; use spawn instead
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
// wl-copy with execSync hangs due to fork behavior; use spawn instead.
|
|
82
|
+
// Await the exit code and only claim success on a clean exit, so a
|
|
83
|
+
// failed wl-copy falls through to the xclip/OSC 52 fallbacks.
|
|
84
|
+
const wlCopyExit = await new Promise((resolve) => {
|
|
85
|
+
const proc = spawn("wl-copy", [], { stdio: ["pipe", "ignore", "ignore"] });
|
|
86
|
+
proc.on("error", () => resolve(1));
|
|
87
|
+
proc.on("close", (code) => resolve(code ?? 1));
|
|
88
|
+
proc.stdin.on("error", () => {
|
|
89
|
+
// Ignore EPIPE errors if wl-copy exits early
|
|
90
|
+
});
|
|
91
|
+
proc.stdin.write(text);
|
|
92
|
+
proc.stdin.end();
|
|
85
93
|
});
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
94
|
+
if (wlCopyExit === 0) {
|
|
95
|
+
copied = true;
|
|
96
|
+
}
|
|
97
|
+
else if (hasX11Display) {
|
|
98
|
+
copyToX11Clipboard(options);
|
|
99
|
+
copied = true;
|
|
100
|
+
}
|
|
90
101
|
}
|
|
91
102
|
catch {
|
|
92
103
|
if (hasX11Display) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"clipboard.js","sourceRoot":"","sources":["../../src/utils/clipboard.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,IAAI,CAAC;AAC9B,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAQlD,SAAS,kBAAkB,CAAC,OAAmC,EAAQ;IACtE,IAAI,CAAC;QACJ,QAAQ,CAAC,4BAA4B,EAAE,OAAO,CAAC,CAAC;IACjD,CAAC;IAAC,MAAM,CAAC;QACR,QAAQ,CAAC,0BAA0B,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;AAAA,CACD;AAED,MAAM,wBAAwB,GAAG,OAAO,CAAC;AAEzC,SAAS,eAAe,CAAC,GAAG,GAAsB,OAAO,CAAC,GAAG,EAAW;IACvE,OAAO,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,GAAG,CAAC,UAAU,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;AAAA,CAC5E;AAED,SAAS,SAAS,CAAC,IAAY,EAAW;IACzC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;IACrD,IAAI,OAAO,CAAC,MAAM,GAAG,wBAAwB,EAAE,CAAC;QAC/C,OAAO,KAAK,CAAC;IACd,CAAC;IACD,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,aAAa,OAAO,MAAM,CAAC,CAAC;IACjD,OAAO,IAAI,CAAC;AAAA,CACZ;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAiB;IAClE,IAAI,MAAM,GAAG,KAAK,CAAC;IAEnB,MAAM,CAAC,GAAG,QAAQ,EAAE,CAAC;IAErB,2EAA2E;IAC3E,8EAA8E;IAC9E,wDAAwD;IACxD,EAAE;IACF,0EAA0E;IAC1E,oEAAoE;IACpE,0EAA0E;IAC1E,0EAA0E;IAC1E,sEAAsE;IACtE,gCAAgC;IAChC,IAAI,CAAC;QACJ,IAAI,SAAS,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;YAChC,MAAM,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC9B,MAAM,GAAG,IAAI,CAAC;QACf,CAAC;IACF,CAAC;IAAC,MAAM,CAAC;QACR,qDAAqD;IACtD,CAAC;IAED,MAAM,MAAM,GAAG,eAAe,EAAE,CAAC;IACjC,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,OAAO;IACR,CAAC;IAED,MAAM,OAAO,GAA+B,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC;IAEhH,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,IAAI,CAAC;YACJ,IAAI,CAAC,KAAK,QAAQ,EAAE,CAAC;gBACpB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBAC5B,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,IAAI,CAAC,KAAK,OAAO,EAAE,CAAC;gBAC1B,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAC1B,MAAM,GAAG,IAAI,CAAC;YACf,CAAC;iBAAM,CAAC;gBACP,sDAAsD;gBACtD,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,CAAC;oBAChC,IAAI,CAAC;wBACJ,QAAQ,CAAC,sBAAsB,EAAE,OAAO,CAAC,CAAC;wBAC1C,MAAM,GAAG,IAAI,CAAC;oBACf,CAAC;oBAAC,MAAM,CAAC;wBACR,qCAAqC;oBACtC,CAAC;gBACF,CAAC;gBAED,IAAI,CAAC,MAAM,EAAE,CAAC;oBACb,MAAM,iBAAiB,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC;oBAC/D,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;oBACnD,MAAM,SAAS,GAAG,gBAAgB,EAAE,CAAC;oBACrC,IAAI,SAAS,IAAI,iBAAiB,EAAE,CAAC;wBACpC,IAAI,CAAC;4BACJ,qEAAqE;4BACrE,QAAQ,CAAC,eAAe,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC,CAAC;4BAC/C,uEAAuE;4BACvE,mEAAmE;4BACnE,8DAA8D;4BAC9D,MAAM,UAAU,GAAG,MAAM,IAAI,OAAO,CAAS,CAAC,OAAO,EAAE,EAAE,CAAC;gCACzD,MAAM,IAAI,GAAG,KAAK,CAAC,SAAS,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;gCAC3E,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;gCACnC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC;gCAC/C,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC;oCAC5B,6CAA6C;gCADhB,CAE7B,CAAC,CAAC;gCACH,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gCACvB,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC;4BAAA,CACjB,CAAC,CAAC;4BACH,IAAI,UAAU,KAAK,CAAC,EAAE,CAAC;gCACtB,MAAM,GAAG,IAAI,CAAC;4BACf,CAAC;iCAAM,IAAI,aAAa,EAAE,CAAC;gCAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAC;gCAC5B,MAAM,GAAG,IAAI,CAAC;4BACf,CAAC;wBACF,CAAC;wBAAC,MAAM,CAAC;4BACR,IAAI,aAAa,EAAE,CAAC;gCACnB,kBAAkB,CAAC,OAAO,CAAC,CAAC;gCAC5B,MAAM,GAAG,IAAI,CAAC;4BACf,CAAC;wBACF,CAAC;oBACF,CAAC;yBAAM,IAAI,aAAa,EAAE,CAAC;wBAC1B,kBAAkB,CAAC,OAAO,CAAC,CAAC;wBAC5B,MAAM,GAAG,IAAI,CAAC;oBACf,CAAC;gBACF,CAAC;YACF,CAAC;QACF,CAAC;QAAC,MAAM,CAAC;YACR,mCAAmC;QACpC,CAAC;IACF,CAAC;IAED,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,WAAW,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QACpC,MAAM,GAAG,MAAM,IAAI,WAAW,CAAC;IAChC,CAAC;IAED,IAAI,CAAC,MAAM,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,6BAA6B,CAAC,CAAC;IAChD,CAAC;AAAA,CACD","sourcesContent":["import { execSync, spawn } from \"child_process\";\nimport { platform } from \"os\";\nimport { isWaylandSession } from \"./clipboard-image.ts\";\nimport { clipboard } from \"./clipboard-native.ts\";\n\ntype NativeClipboardExecOptions = {\n\tinput: string;\n\ttimeout: number;\n\tstdio: [\"pipe\", \"ignore\", \"ignore\"];\n};\n\nfunction copyToX11Clipboard(options: NativeClipboardExecOptions): void {\n\ttry {\n\t\texecSync(\"xclip -selection clipboard\", options);\n\t} catch {\n\t\texecSync(\"xsel --clipboard --input\", options);\n\t}\n}\n\nconst MAX_OSC52_ENCODED_LENGTH = 100_000;\n\nfunction isRemoteSession(env: NodeJS.ProcessEnv = process.env): boolean {\n\treturn Boolean(env.SSH_CONNECTION || env.SSH_CLIENT || env.MOSH_CONNECTION);\n}\n\nfunction emitOsc52(text: string): boolean {\n\tconst encoded = Buffer.from(text).toString(\"base64\");\n\tif (encoded.length > MAX_OSC52_ENCODED_LENGTH) {\n\t\treturn false;\n\t}\n\tprocess.stdout.write(`\\x1b]52;c;${encoded}\\x07`);\n\treturn true;\n}\n\nexport async function copyToClipboard(text: string): Promise<void> {\n\tlet copied = false;\n\n\tconst p = platform();\n\n\t// Prefer direct clipboard writes. Emitting OSC 52 first can make terminals\n\t// write the same native clipboard concurrently with the addon, and very large\n\t// OSC 52 payloads can desynchronize terminal rendering.\n\t//\n\t// On Linux, skip the native addon. The underlying `clipboard-rs` crate is\n\t// X11-only and does not retain selection ownership after `set_text`\n\t// resolves, so on Wayland-only compositors (Hyprland, Niri, ...) and even\n\t// some X11 sessions the call resolves successfully without populating the\n\t// clipboard. The platform tools below (wl-copy, xclip, xsel) properly\n\t// daemonize and keep ownership.\n\ttry {\n\t\tif (clipboard && p !== \"linux\") {\n\t\t\tawait clipboard.setText(text);\n\t\t\tcopied = true;\n\t\t}\n\t} catch {\n\t\t// Fall through to platform-specific clipboard tools.\n\t}\n\n\tconst remote = isRemoteSession();\n\tif (copied && !remote) {\n\t\treturn;\n\t}\n\n\tconst options: NativeClipboardExecOptions = { input: text, timeout: 5000, stdio: [\"pipe\", \"ignore\", \"ignore\"] };\n\n\tif (!copied) {\n\t\ttry {\n\t\t\tif (p === \"darwin\") {\n\t\t\t\texecSync(\"pbcopy\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else if (p === \"win32\") {\n\t\t\t\texecSync(\"clip\", options);\n\t\t\t\tcopied = true;\n\t\t\t} else {\n\t\t\t\t// Linux. Try Termux, Wayland, or X11 clipboard tools.\n\t\t\t\tif (process.env.TERMUX_VERSION) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\texecSync(\"termux-clipboard-set\", options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Fall back to Wayland or X11 tools.\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif (!copied) {\n\t\t\t\t\tconst hasWaylandDisplay = Boolean(process.env.WAYLAND_DISPLAY);\n\t\t\t\t\tconst hasX11Display = Boolean(process.env.DISPLAY);\n\t\t\t\t\tconst isWayland = isWaylandSession();\n\t\t\t\t\tif (isWayland && hasWaylandDisplay) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t// Verify wl-copy exists (spawn errors are async and won't be caught)\n\t\t\t\t\t\t\texecSync(\"which wl-copy\", { stdio: \"ignore\" });\n\t\t\t\t\t\t\t// wl-copy with execSync hangs due to fork behavior; use spawn instead.\n\t\t\t\t\t\t\t// Await the exit code and only claim success on a clean exit, so a\n\t\t\t\t\t\t\t// failed wl-copy falls through to the xclip/OSC 52 fallbacks.\n\t\t\t\t\t\t\tconst wlCopyExit = await new Promise<number>((resolve) => {\n\t\t\t\t\t\t\t\tconst proc = spawn(\"wl-copy\", [], { stdio: [\"pipe\", \"ignore\", \"ignore\"] });\n\t\t\t\t\t\t\t\tproc.on(\"error\", () => resolve(1));\n\t\t\t\t\t\t\t\tproc.on(\"close\", (code) => resolve(code ?? 1));\n\t\t\t\t\t\t\t\tproc.stdin.on(\"error\", () => {\n\t\t\t\t\t\t\t\t\t// Ignore EPIPE errors if wl-copy exits early\n\t\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\t\tproc.stdin.write(text);\n\t\t\t\t\t\t\t\tproc.stdin.end();\n\t\t\t\t\t\t\t});\n\t\t\t\t\t\t\tif (wlCopyExit === 0) {\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} catch {\n\t\t\t\t\t\t\tif (hasX11Display) {\n\t\t\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if (hasX11Display) {\n\t\t\t\t\t\tcopyToX11Clipboard(options);\n\t\t\t\t\t\tcopied = true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} catch {\n\t\t\t// Fall through to OSC 52 fallback.\n\t\t}\n\t}\n\n\tif (remote || !copied) {\n\t\tconst osc52Copied = emitOsc52(text);\n\t\tcopied = copied || osc52Copied;\n\t}\n\n\tif (!copied) {\n\t\tthrow new Error(\"Failed to copy to clipboard\");\n\t}\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC3D,WAAW,EAAE,CAAC,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;
|
|
1
|
+
{"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAEA,KAAK,iBAAiB,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAAI;IAC3D,WAAW,EAAE,CAAC,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;CACb,CAAC;AAuDF,eAAO,MAAM,gBAAgB,GAAI,CAAC,oGASjC,CAAC;AAEF,eAAO,MAAM,gBAAgB,6BAA8D,CAAC","sourcesContent":["import { parse } from \"yaml\";\n\ntype ParsedFrontmatter<T extends Record<string, unknown>> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\nconst normalizeNewlines = (value: string): string => value.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\nconst FRONTMATTER_OPEN = /^---(?:[ \\t]*\\r?\\n|$)/m;\n\n/**\n * Locate YAML frontmatter even when a short preamble (comments/HTML) precedes the opening fence.\n * bigpowers and similar skill packs emit story markers before `---`.\n */\nconst extractFrontmatter = (content: string): { yamlString: string | null; body: string } => {\n\tconst normalized = normalizeNewlines(content);\n\n\tconst openMatch = FRONTMATTER_OPEN.exec(normalized);\n\tif (!openMatch || openMatch.index === undefined) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\t// Reject preambles that already look like document body (too long / has headings beyond comments).\n\tconst preamble = normalized.slice(0, openMatch.index);\n\tif (preamble.length > 0) {\n\t\tconst preambleLines = preamble.split(\"\\n\").filter((line) => line.trim().length > 0);\n\t\tconst onlyPreambleNoise = preambleLines.every(\n\t\t\t(line) =>\n\t\t\t\tline.trimStart().startsWith(\"#\") ||\n\t\t\t\tline.trimStart().startsWith(\"<!--\") ||\n\t\t\t\tline.trim() === \"-->\" ||\n\t\t\t\t/^ARCHIVED:/i.test(line.trim()),\n\t\t);\n\t\tif (!onlyPreambleNoise || preambleLines.length > 32) {\n\t\t\treturn { yamlString: null, body: normalized };\n\t\t}\n\t}\n\n\tconst yamlStart = openMatch.index + openMatch[0].length;\n\tconst endIndex = normalized.indexOf(\"\\n---\", yamlStart - 1);\n\tif (endIndex === -1 || endIndex < yamlStart) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\t// Closing fence must be a line that is exactly `---` (optional trailing spaces).\n\tconst afterClose = normalized.slice(endIndex + 1); // starts at ---\n\tif (!/^---[ \\t]*(?:\\n|$)/.test(afterClose)) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\tconst closeLineEnd = afterClose.search(/\\n/);\n\tconst bodyStart = closeLineEnd === -1 ? normalized.length : endIndex + 1 + closeLineEnd + 1;\n\n\treturn {\n\t\tyamlString: normalized.slice(yamlStart, endIndex),\n\t\tbody: normalized.slice(bodyStart).trim(),\n\t};\n};\n\nexport const parseFrontmatter = <T extends Record<string, unknown> = Record<string, unknown>>(\n\tcontent: string,\n): ParsedFrontmatter<T> => {\n\tconst { yamlString, body } = extractFrontmatter(content);\n\tif (!yamlString) {\n\t\treturn { frontmatter: {} as T, body };\n\t}\n\tconst parsed = parse(yamlString);\n\treturn { frontmatter: (parsed ?? {}) as T, body };\n};\n\nexport const stripFrontmatter = (content: string): string => parseFrontmatter(content).body;\n"]}
|
|
@@ -1,17 +1,43 @@
|
|
|
1
1
|
import { parse } from "yaml";
|
|
2
2
|
const normalizeNewlines = (value) => value.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
3
|
+
const FRONTMATTER_OPEN = /^---(?:[ \t]*\r?\n|$)/m;
|
|
4
|
+
/**
|
|
5
|
+
* Locate YAML frontmatter even when a short preamble (comments/HTML) precedes the opening fence.
|
|
6
|
+
* bigpowers and similar skill packs emit story markers before `---`.
|
|
7
|
+
*/
|
|
3
8
|
const extractFrontmatter = (content) => {
|
|
4
9
|
const normalized = normalizeNewlines(content);
|
|
5
|
-
|
|
10
|
+
const openMatch = FRONTMATTER_OPEN.exec(normalized);
|
|
11
|
+
if (!openMatch || openMatch.index === undefined) {
|
|
6
12
|
return { yamlString: null, body: normalized };
|
|
7
13
|
}
|
|
8
|
-
|
|
9
|
-
|
|
14
|
+
// Reject preambles that already look like document body (too long / has headings beyond comments).
|
|
15
|
+
const preamble = normalized.slice(0, openMatch.index);
|
|
16
|
+
if (preamble.length > 0) {
|
|
17
|
+
const preambleLines = preamble.split("\n").filter((line) => line.trim().length > 0);
|
|
18
|
+
const onlyPreambleNoise = preambleLines.every((line) => line.trimStart().startsWith("#") ||
|
|
19
|
+
line.trimStart().startsWith("<!--") ||
|
|
20
|
+
line.trim() === "-->" ||
|
|
21
|
+
/^ARCHIVED:/i.test(line.trim()));
|
|
22
|
+
if (!onlyPreambleNoise || preambleLines.length > 32) {
|
|
23
|
+
return { yamlString: null, body: normalized };
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
const yamlStart = openMatch.index + openMatch[0].length;
|
|
27
|
+
const endIndex = normalized.indexOf("\n---", yamlStart - 1);
|
|
28
|
+
if (endIndex === -1 || endIndex < yamlStart) {
|
|
29
|
+
return { yamlString: null, body: normalized };
|
|
30
|
+
}
|
|
31
|
+
// Closing fence must be a line that is exactly `---` (optional trailing spaces).
|
|
32
|
+
const afterClose = normalized.slice(endIndex + 1); // starts at ---
|
|
33
|
+
if (!/^---[ \t]*(?:\n|$)/.test(afterClose)) {
|
|
10
34
|
return { yamlString: null, body: normalized };
|
|
11
35
|
}
|
|
36
|
+
const closeLineEnd = afterClose.search(/\n/);
|
|
37
|
+
const bodyStart = closeLineEnd === -1 ? normalized.length : endIndex + 1 + closeLineEnd + 1;
|
|
12
38
|
return {
|
|
13
|
-
yamlString: normalized.slice(
|
|
14
|
-
body: normalized.slice(
|
|
39
|
+
yamlString: normalized.slice(yamlStart, endIndex),
|
|
40
|
+
body: normalized.slice(bodyStart).trim(),
|
|
15
41
|
};
|
|
16
42
|
};
|
|
17
43
|
export const parseFrontmatter = (content) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,MAAM,CAAC;AAO7B,MAAM,iBAAiB,GAAG,CAAC,KAAa,EAAU,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AAEvG,MAAM,kBAAkB,GAAG,CAAC,OAAe,EAA+C,EAAE,CAAC;IAC5F,MAAM,UAAU,GAAG,iBAAiB,CAAC,OAAO,CAAC,CAAC;IAE9C,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"frontmatter.js","sourceRoot":"","sources":["../../src/utils/frontmatter.ts"],"names":[],"mappings":"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","sourcesContent":["import { parse } from \"yaml\";\n\ntype ParsedFrontmatter<T extends Record<string, unknown>> = {\n\tfrontmatter: T;\n\tbody: string;\n};\n\nconst normalizeNewlines = (value: string): string => value.replace(/\\r\\n/g, \"\\n\").replace(/\\r/g, \"\\n\");\n\nconst FRONTMATTER_OPEN = /^---(?:[ \\t]*\\r?\\n|$)/m;\n\n/**\n * Locate YAML frontmatter even when a short preamble (comments/HTML) precedes the opening fence.\n * bigpowers and similar skill packs emit story markers before `---`.\n */\nconst extractFrontmatter = (content: string): { yamlString: string | null; body: string } => {\n\tconst normalized = normalizeNewlines(content);\n\n\tconst openMatch = FRONTMATTER_OPEN.exec(normalized);\n\tif (!openMatch || openMatch.index === undefined) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\t// Reject preambles that already look like document body (too long / has headings beyond comments).\n\tconst preamble = normalized.slice(0, openMatch.index);\n\tif (preamble.length > 0) {\n\t\tconst preambleLines = preamble.split(\"\\n\").filter((line) => line.trim().length > 0);\n\t\tconst onlyPreambleNoise = preambleLines.every(\n\t\t\t(line) =>\n\t\t\t\tline.trimStart().startsWith(\"#\") ||\n\t\t\t\tline.trimStart().startsWith(\"<!--\") ||\n\t\t\t\tline.trim() === \"-->\" ||\n\t\t\t\t/^ARCHIVED:/i.test(line.trim()),\n\t\t);\n\t\tif (!onlyPreambleNoise || preambleLines.length > 32) {\n\t\t\treturn { yamlString: null, body: normalized };\n\t\t}\n\t}\n\n\tconst yamlStart = openMatch.index + openMatch[0].length;\n\tconst endIndex = normalized.indexOf(\"\\n---\", yamlStart - 1);\n\tif (endIndex === -1 || endIndex < yamlStart) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\t// Closing fence must be a line that is exactly `---` (optional trailing spaces).\n\tconst afterClose = normalized.slice(endIndex + 1); // starts at ---\n\tif (!/^---[ \\t]*(?:\\n|$)/.test(afterClose)) {\n\t\treturn { yamlString: null, body: normalized };\n\t}\n\n\tconst closeLineEnd = afterClose.search(/\\n/);\n\tconst bodyStart = closeLineEnd === -1 ? normalized.length : endIndex + 1 + closeLineEnd + 1;\n\n\treturn {\n\t\tyamlString: normalized.slice(yamlStart, endIndex),\n\t\tbody: normalized.slice(bodyStart).trim(),\n\t};\n};\n\nexport const parseFrontmatter = <T extends Record<string, unknown> = Record<string, unknown>>(\n\tcontent: string,\n): ParsedFrontmatter<T> => {\n\tconst { yamlString, body } = extractFrontmatter(content);\n\tif (!yamlString) {\n\t\treturn { frontmatter: {} as T, body };\n\t}\n\tconst parsed = parse(yamlString);\n\treturn { frontmatter: (parsed ?? {}) as T, body };\n};\n\nexport const stripFrontmatter = (content: string): string => parseFrontmatter(content).body;\n"]}
|
package/docs/compaction.md
CHANGED
|
@@ -62,6 +62,13 @@ You can also trigger manually with `/compact [instructions]`, where optional ins
|
|
|
62
62
|
|
|
63
63
|
By default, compaction uses the active session model. Set `compaction.model` to an authenticated canonical `provider/model` reference when summaries should use a different model. For example, `zai/glm-5.2` keeps an interactive Claude session while using GLM only for auto-compaction and `/compact`.
|
|
64
64
|
|
|
65
|
+
### Summarization Requests
|
|
66
|
+
|
|
67
|
+
Every compaction and branch-summary LLM call flows through one choke point (`completeSummarization`):
|
|
68
|
+
|
|
69
|
+
- **Retries**: transient stream drops (`terminated`, socket close, 5xx, DNS/transport errors) follow the configured `retry` settings (`enabled`, `maxRetries`, `baseDelayMs`) with exponential backoff instead of failing the whole operation on the first attempt. Quota/billing errors fail fast, and aborts are never retried. Retry progress is emitted as `summarization_retry_scheduled` / `summarization_retry_attempt_start` / `summarization_retry_finished` session events (surfaced in the TUI and RPC stream).
|
|
70
|
+
- **Isolation**: each summarization request runs with prompt caching disabled (`cacheRetention: "none"`) and a fresh routing `sessionId`, so summaries never write unusable provider cache entries or inherit interactive session affinity.
|
|
71
|
+
|
|
65
72
|
### How It Works
|
|
66
73
|
|
|
67
74
|
1. **Find cut point**: Walk backwards from newest message, accumulating token estimates until `keepRecentTokens` (default 20k, configurable in `~/.omk/agent/settings.json` or `<project-dir>/.omk/settings.json`) is reached
|
package/docs/docs.json
CHANGED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
# Environment Variables
|
|
2
|
+
|
|
3
|
+
OMK uses environment variables in three ways:
|
|
4
|
+
|
|
5
|
+
- Variables such as `OMK_OFFLINE` configure the OMK process.
|
|
6
|
+
- OMK sets `OMK_CODING_AGENT` so child processes can detect that they run inside OMK.
|
|
7
|
+
- Commands run by the LLM-callable bash tool receive `PI_*` variables describing the current session.
|
|
8
|
+
|
|
9
|
+
Provider API-key variables are documented separately in [Providers](providers.md).
|
|
10
|
+
|
|
11
|
+
## Process Marker
|
|
12
|
+
|
|
13
|
+
The CLI and RPC entry points set `OMK_CODING_AGENT=true`. Child processes inherit it and can use it to detect that they run inside OMK. It is not session-specific and is not set automatically when OMK is embedded through the SDK.
|
|
14
|
+
|
|
15
|
+
## Bash Tool Session Environment
|
|
16
|
+
|
|
17
|
+
Commands run by the bash tool receive the current session state (the `PI_*` names are kept for upstream Pi compatibility):
|
|
18
|
+
|
|
19
|
+
| Variable | Description |
|
|
20
|
+
| --- | --- |
|
|
21
|
+
| `PI_SESSION_ID` | Current session ID |
|
|
22
|
+
| `PI_SESSION_FILE` | Absolute path to the current session JSONL file; unset for ephemeral sessions |
|
|
23
|
+
| `PI_PROVIDER` | Currently selected model provider |
|
|
24
|
+
| `PI_MODEL` | Currently selected model ID |
|
|
25
|
+
| `PI_REASONING_LEVEL` | Current effective reasoning level: `off`, `minimal`, `low`, `medium`, `high`, `xhigh`, or `max` |
|
|
26
|
+
|
|
27
|
+
The values are resolved when each command starts. Switching models or changing the reasoning level therefore affects the next bash command without restarting OMK. `PI_PROVIDER` and `PI_MODEL` identify the selected OMK model, not a different upstream model that a router may choose internally.
|
|
28
|
+
|
|
29
|
+
Inherited parent-process values for these variables are always stripped first, so a nested OMK session never exposes stale parent-session metadata.
|
|
30
|
+
|
|
31
|
+
When asked which model or provider is running, inspect these variables instead of inferring the answer from the system prompt:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
printf '%s/%s\n' "$PI_PROVIDER" "$PI_MODEL"
|
|
35
|
+
printf 'reasoning=%s session=%s\n' "$PI_REASONING_LEVEL" "$PI_SESSION_ID"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The session file can be inspected directly when the session is persistent:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
if [ -n "$PI_SESSION_FILE" ]; then
|
|
42
|
+
tail -n 1 "$PI_SESSION_FILE"
|
|
43
|
+
fi
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
These variables are injected into the LLM-callable bash tool. They are not injected into user-entered `!` or `!!` commands.
|
|
47
|
+
|
|
48
|
+
### Custom Bash Tools
|
|
49
|
+
|
|
50
|
+
Bash tools created with `createBashTool()` expose the session environment by default. Injection happens before `spawnHook`, so a hook receives the variables in `ctx.env`:
|
|
51
|
+
|
|
52
|
+
```typescript
|
|
53
|
+
const bashTool = createBashTool(cwd, {
|
|
54
|
+
spawnHook: (ctx) => ({
|
|
55
|
+
...ctx,
|
|
56
|
+
env: { ...ctx.env, CI: "1" },
|
|
57
|
+
}),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Disable session metadata independently of the spawn hook:
|
|
62
|
+
|
|
63
|
+
```typescript
|
|
64
|
+
const bashTool = createBashTool(cwd, {
|
|
65
|
+
exposeSessionEnvironment: false,
|
|
66
|
+
spawnHook: (ctx) => ctx,
|
|
67
|
+
});
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
When disabled, OMK removes inherited values for these variables so nested OMK processes do not expose stale parent-session metadata.
|
|
71
|
+
|
|
72
|
+
## OMK Process Configuration
|
|
73
|
+
|
|
74
|
+
These variables are read by OMK itself:
|
|
75
|
+
|
|
76
|
+
| Variable | Description |
|
|
77
|
+
| --- | --- |
|
|
78
|
+
| `OMK_CODING_AGENT_DIR` | Override the config directory; default is `~/.omk/agent` |
|
|
79
|
+
| `OMK_CODING_AGENT_SESSION_DIR` | Override session storage; overridden by `--session-dir` |
|
|
80
|
+
| `OMK_PACKAGE_DIR` | Override the package directory, useful for Nix/Guix store paths |
|
|
81
|
+
| `OMK_OFFLINE` | Disable startup network operations, including update checks and install/update telemetry |
|
|
82
|
+
| `OMK_SKIP_VERSION_CHECK` | Disable the latest-version request |
|
|
83
|
+
| `OMK_TELEMETRY` | Override install/update telemetry and provider attribution headers: `1`/`true`/`yes` or `0`/`false`/`no` |
|
|
84
|
+
| `OMK_SHARE_VIEWER_URL` | Override the base URL used by `/share` |
|
|
85
|
+
| `OMK_HARDWARE_CURSOR` | Set to `1` to show the hardware cursor; see [Terminal setup](terminal-setup.md) |
|
|
86
|
+
| `OMK_CONTEXT_GOVERNOR` | Configure the context-budget governor; see `context-budget-*` sources |
|
|
87
|
+
| `OMK_VERIFIED_BASH` | Default-on verified bash adapter for AgentSession/CLI bash. Set to `0` to opt out and use the legacy unverified path (see [SDK — Evidence and Verification](sdk.md#evidence-and-verification)) |
|
|
88
|
+
| `OMK_BASH_SANDBOX` | Bash sandbox mode: `audit` (default — unwrapped spawn, every decision recorded to the replay ledger), `enforce` (wrap with macOS `sandbox-exec` / Linux `bwrap`, fail closed when no backend), `0`/`off` to disable. `session.setBashSandboxMode()` overrides at runtime |
|
|
89
|
+
| `LIVE_E2E` | Test-only: keep provider credentials so live-API e2e suites run on purpose (default scrubbed for hermetic tests) |
|
|
90
|
+
| `OMK_OMP_SEAMS` | Default-on OMP pure seams for `read`/`grep`. Set to `0` to opt out |
|
|
91
|
+
| `VISUAL`, `EDITOR` | External editor fallback when `externalEditor` is unset |
|
|
92
|
+
| `HTTP_PROXY`, `HTTPS_PROXY` | Proxy outbound HTTP requests |
|
|
93
|
+
|
|
94
|
+
Provider credentials such as `ANTHROPIC_API_KEY`, `OPENAI_API_KEY`, and cloud-provider configuration are listed in [Providers](providers.md).
|
package/docs/index.md
CHANGED
|
@@ -37,6 +37,7 @@ For the full first-run flow, see [Quickstart](quickstart.md).
|
|
|
37
37
|
- [Providers](providers.md) - subscription and API-key setup for built-in providers.
|
|
38
38
|
- [Containerization](containerization.md) - sandbox omk with OpenShell, Gondolin, or Docker.
|
|
39
39
|
- [Settings](settings.md) - global and project settings.
|
|
40
|
+
- [Environment Variables](environment-variables.md) - process configuration and bash-tool session environment.
|
|
40
41
|
- [Keybindings](keybindings.md) - default shortcuts and custom keybindings.
|
|
41
42
|
- [Sessions](sessions.md) - session management, branching, and tree navigation.
|
|
42
43
|
- [Compaction](compaction.md) - context compaction and branch summarization.
|
package/docs/rpc.md
CHANGED
|
@@ -424,12 +424,14 @@ Response:
|
|
|
424
424
|
|
|
425
425
|
#### bash
|
|
426
426
|
|
|
427
|
-
Execute a shell command and add output to conversation context.
|
|
427
|
+
Execute a shell command and add output to conversation context. Output streams as `bash_execution_update` events while the command runs; the response contains the final result.
|
|
428
428
|
|
|
429
429
|
```json
|
|
430
|
-
{"type": "bash", "command": "ls -la"}
|
|
430
|
+
{"id": "req-1", "type": "bash", "command": "ls -la"}
|
|
431
431
|
```
|
|
432
432
|
|
|
433
|
+
Include an `id` to associate streamed `bash_execution_update` events with this command.
|
|
434
|
+
|
|
433
435
|
Response:
|
|
434
436
|
```json
|
|
435
437
|
{
|
|
@@ -753,6 +755,7 @@ Events are streamed to stdout as JSON lines during agent operation. Events do NO
|
|
|
753
755
|
| `message_start` | Message begins |
|
|
754
756
|
| `message_update` | Streaming update (text/thinking/toolcall deltas) |
|
|
755
757
|
| `message_end` | Message completes |
|
|
758
|
+
| `bash_execution_update` | Direct RPC bash command output chunk (includes originating command `id`) |
|
|
756
759
|
| `tool_execution_start` | Tool begins execution |
|
|
757
760
|
| `tool_execution_update` | Tool execution progress (streaming output) |
|
|
758
761
|
| `tool_execution_end` | Tool completes |
|
package/docs/sdk.md
CHANGED
|
@@ -505,14 +505,16 @@ const { session } = await createAgentSession({ resourceLoader: loader });
|
|
|
505
505
|
|
|
506
506
|
Specify which built-in tools to enable:
|
|
507
507
|
|
|
508
|
-
- Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`
|
|
509
|
-
- Default built-ins: `read`, `bash`, `edit`, `write`
|
|
508
|
+
- Built-in tool names: `read`, `bash`, `edit`, `write`, `grep`, `find`, `ls`, `diagnostics`
|
|
509
|
+
- Default built-ins: `read`, `bash`, `edit`, `write`, `diagnostics`
|
|
510
510
|
- `noTools: "all"` disables all tools
|
|
511
511
|
- `noTools: "builtin"` disables default built-ins while keeping extension and custom tools enabled
|
|
512
512
|
- `excludeTools` disables specific built-in, extension, or custom tool names after any `tools` allowlist is applied
|
|
513
513
|
|
|
514
514
|
The `edit` tool returns `details.diff` for OMK's TUI display and `details.patch` as a standard unified patch for SDK consumers.
|
|
515
515
|
|
|
516
|
+
The `diagnostics` tool runs the project's own checkers and normalizes the result — `tsc --noEmit` for TypeScript, `pyright`/`ruff` for Python, `go vet` for Go, `cargo check` for Rust. Missing checkers or project markers are reported as `skipped` in the tool result instead of failing. Output is capped at 50 diagnostics and cached for 5 s.
|
|
517
|
+
|
|
516
518
|
```typescript
|
|
517
519
|
import { createAgentSession } from "open-multi-agent-kit";
|
|
518
520
|
|
|
@@ -1130,7 +1132,11 @@ RPC mode is preferred when:
|
|
|
1130
1132
|
|
|
1131
1133
|
## Evidence and Verification
|
|
1132
1134
|
|
|
1133
|
-
Execution-bound evidence
|
|
1135
|
+
Execution-bound evidence records a declared verification command and reported outcome between two artifact-set snapshots, then binds that record to a tamper-evident ledger. `VerifiedEvidenceExecutor` never executes the declared command. `executeVerifiedBash()` invokes caller-supplied `BashOperations`; `executeVerifiedLocalBash()` derives the shell identity and runner from OMK's built-in local backend.
|
|
1136
|
+
|
|
1137
|
+
**Default path (opt-out):** when an AgentSession has a replay ledger (persisted sessions create one automatically), LLM-callable `bash` and interactive/RPC `executeBash` bind through `executeVerifiedBash` with `executor: "bash-tool"` and receipts under `<sessionFile>.evidence/receipts` (or `cwd/.omk/session-evidence/<goalId>/receipts` for ephemeral sessions). Session workspace scope is git-aware: inside a worktree, the receipt binds the toplevel plus the sorted dirty set (capped at 32 paths, 1 s TTL). Set `OMK_VERIFIED_BASH=0` to restore the legacy unverified path. Custom `createBashTool()` calls stay unverified unless the caller wraps operations with `createVerifiedBashOperations()`. CI still runs release-consistency through `executeVerifiedLocalBash()` with `executor: "ci-runner"`.
|
|
1138
|
+
|
|
1139
|
+
**Default sandbox (opt-out):** session bash also carries a default `audit`-mode sandbox preflight (workspace-write policy rooted at the session cwd). The spawn stays unwrapped, but every decision is appended to the replay ledger as a `sandbox_audit` event, giving a tamper-evident audit trail. `OMK_BASH_SANDBOX=enforce` activates the real OS backend — macOS `sandbox-exec` seatbelt or Linux `bwrap` bubblewrap — and fails closed when neither is installed; `OMK_BASH_SANDBOX=0` disables the preflight entirely.
|
|
1134
1140
|
|
|
1135
1141
|
### Recorded and invoked inputs
|
|
1136
1142
|
|
|
@@ -1164,7 +1170,7 @@ Injected runners must follow the built-in terminal protocol: return an integer e
|
|
|
1164
1170
|
|
|
1165
1171
|
`.github/workflows/ci.yml` invokes the compiled `dist/verify-ci.js` entry after the normal repository check. That entry runs only `node scripts/check-release-consistency.mjs` through `executeVerifiedLocalBash()` with `executor: "ci-runner"`, applies a strict `EvidenceGate`, writes receipts, ledger, and report under `.omk/ci-evidence`, and returns a non-zero process exit when the gate is blocked. CI uploads that directory as `verified-release-consistency`.
|
|
1166
1172
|
|
|
1167
|
-
This callsite does not wrap the full build, check, or test suite
|
|
1173
|
+
This callsite does not wrap the full build, check, or test suite. Session bash receipts (default-on above) use an empty artifact set and do not replace CI's manifest-scoped release-consistency gate. CI workspace freshness remains limited to the root and coding-agent package manifests.
|
|
1168
1174
|
|
|
1169
1175
|
### Execution ordering
|
|
1170
1176
|
|
package/docs/settings.md
CHANGED
|
@@ -77,6 +77,7 @@ Advisory-only hint source for the v4 auto thinking-level resolver. Read from the
|
|
|
77
77
|
| `editorPaddingX` | number | `0` | Horizontal padding for input editor (0-3) |
|
|
78
78
|
| `autocompleteMaxVisible` | number | `5` | Max visible items in autocomplete dropdown (3-20) |
|
|
79
79
|
| `showHardwareCursor` | boolean | `false` | Show the terminal cursor while TUI positions it for IME support |
|
|
80
|
+
| `pinStatusSidebar` | boolean | `false` | Pin the bottom status bar as a responsive right rail (opencode-style): width scales with the terminal (~26%, 34–48 cols), the MCP roster grows on taller terminals, and the content column shrinks to match so the prompt is never covered. Toggle anytime with `Ctrl+Q`. Also enabled by `OMK_PIN_STATUS_SIDEBAR=1` |
|
|
80
81
|
|
|
81
82
|
### Telemetry and update checks
|
|
82
83
|
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omk-extension-custom-provider-anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.94.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omk-extension-custom-provider-anthropic",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.94.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sdk": "0.52.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omk-extension-gondolin",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.94.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omk-extension-gondolin",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.94.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@earendil-works/gondolin": "0.12.0"
|
|
12
12
|
}
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "omk-extension-sandbox",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.94.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "omk-extension-sandbox",
|
|
9
|
-
"version": "0.
|
|
9
|
+
"version": "0.94.0",
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"@anthropic-ai/sandbox-runtime": "0.0.26"
|
|
12
12
|
}
|