@tangle-network/agent-runtime 0.105.0 → 0.106.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/dist/activation-CRjVfOiy.js +203 -0
- package/dist/activation-CRjVfOiy.js.map +1 -0
- package/dist/activation-DyWB0K6E.d.ts +98 -0
- package/dist/agent.d.ts +216 -234
- package/dist/agent.js +615 -547
- package/dist/agent.js.map +1 -1
- package/dist/analyst-loop-DGdtVENg.js +517 -0
- package/dist/analyst-loop-DGdtVENg.js.map +1 -0
- package/dist/analyst-loop.d.ts +10 -43
- package/dist/analyst-loop.js +2 -11
- package/dist/backends-CiOCyRHb.js +743 -0
- package/dist/backends-CiOCyRHb.js.map +1 -0
- package/dist/candidate-execution/index.d.ts +4 -192
- package/dist/candidate-execution/index.js +5 -66
- package/dist/candidate-execution-DqMbv1rU.js +488 -0
- package/dist/candidate-execution-DqMbv1rU.js.map +1 -0
- package/dist/coder-yhVWbdWc.js +40 -0
- package/dist/coder-yhVWbdWc.js.map +1 -0
- package/dist/conversation-BpLQZGPH.js +1265 -0
- package/dist/conversation-BpLQZGPH.js.map +1 -0
- package/dist/conversation.d.ts +2 -804
- package/dist/conversation.js +2 -55
- package/dist/environment-provider-CfLUmKmf.js +1168 -0
- package/dist/environment-provider-CfLUmKmf.js.map +1 -0
- package/dist/environment-provider-IUGU3epE.d.ts +964 -0
- package/dist/environment-provider.d.ts +2 -78
- package/dist/environment-provider.js +2 -18
- package/dist/errors-DEAvWQPy.js +111 -0
- package/dist/errors-DEAvWQPy.js.map +1 -0
- package/dist/improvement-adapter-Cr5TBSji.d.ts +166 -0
- package/dist/improvement-cycle-C095kS_g.js +2624 -0
- package/dist/improvement-cycle-C095kS_g.js.map +1 -0
- package/dist/index-BGdxAwfO.d.ts +838 -0
- package/dist/index-C-FYUuFG.d.ts +193 -0
- package/dist/index-CbNM40xG.d.ts +140 -0
- package/dist/index-DruSKs3Z.d.ts +7224 -0
- package/dist/index-Efjb3nrQ.d.ts +671 -0
- package/dist/index.d.ts +14 -1058
- package/dist/index.js +2106 -2082
- package/dist/index.js.map +1 -1
- package/dist/intelligence.d.ts +768 -889
- package/dist/intelligence.js +1466 -1367
- package/dist/intelligence.js.map +1 -1
- package/dist/{kb-gate-CwHO0vz6.d.ts → kb-gate-C8z2juK8.d.ts} +33 -31
- package/dist/kb-gate-DpaSwXVx.js +80 -0
- package/dist/kb-gate-DpaSwXVx.js.map +1 -0
- package/dist/knowledge-Ku-mPP4f.js +433 -0
- package/dist/knowledge-Ku-mPP4f.js.map +1 -0
- package/dist/knowledge.d.ts +2 -150
- package/dist/knowledge.js +2 -40
- package/dist/local-harness-Dh8PJ0ot.d.ts +455 -0
- package/dist/loop-runner-bin-BXsFEUcf.d.ts +162 -0
- package/dist/loop-runner-bin-CRagyuNb.js +268 -0
- package/dist/loop-runner-bin-CRagyuNb.js.map +1 -0
- package/dist/loop-runner-bin.d.ts +2 -15
- package/dist/loop-runner-bin.js +2 -24
- package/dist/loops.d.ts +5 -4164
- package/dist/loops.js +8 -419
- package/dist/mcp/bin.d.ts +1 -1
- package/dist/mcp/bin.js +116 -146
- package/dist/mcp/bin.js.map +1 -1
- package/dist/mcp/index.d.ts +295 -436
- package/dist/mcp/index.js +1242 -1177
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/memory-bin.d.ts +1 -1
- package/dist/mcp/memory-bin.js +37 -16
- package/dist/mcp/memory-bin.js.map +1 -1
- package/dist/memory-server-DL6cE2Ag.js +234 -0
- package/dist/memory-server-DL6cE2Ag.js.map +1 -0
- package/dist/model-resolution-Btd9iIKV.js +98 -0
- package/dist/model-resolution-Btd9iIKV.js.map +1 -0
- package/dist/openai-tools-B68JaOCx.d.ts +24 -0
- package/dist/openai-tools-CKLy1C7M.js +44 -0
- package/dist/openai-tools-CKLy1C7M.js.map +1 -0
- package/dist/otel-export-D34IQW1C.js +843 -0
- package/dist/otel-export-D34IQW1C.js.map +1 -0
- package/dist/platform.d.ts +188 -185
- package/dist/platform.js +185 -218
- package/dist/platform.js.map +1 -1
- package/dist/prepare-B53sPV7M.js +4292 -0
- package/dist/prepare-B53sPV7M.js.map +1 -0
- package/dist/primeintellect/index.d.ts +149 -145
- package/dist/primeintellect/index.js +626 -1003
- package/dist/primeintellect/index.js.map +1 -1
- package/dist/profiles.d.ts +296 -490
- package/dist/profiles.js +722 -749
- package/dist/profiles.js.map +1 -1
- package/dist/protected-model-port-BLPH5VVv.js +722 -0
- package/dist/protected-model-port-BLPH5VVv.js.map +1 -0
- package/dist/protected-model-port-BP6Z4eau.d.ts +283 -0
- package/dist/protected-redaction--F3v1oo8.js +200 -0
- package/dist/protected-redaction--F3v1oo8.js.map +1 -0
- package/dist/redact-D-u-rrcn.js +82 -0
- package/dist/redact-D-u-rrcn.js.map +1 -0
- package/dist/redact-kbIOjfjM.d.ts +452 -0
- package/dist/researcher-CoVqNhfI.js +433 -0
- package/dist/researcher-CoVqNhfI.js.map +1 -0
- package/dist/runtime-5zM5XxLr.js +5408 -0
- package/dist/runtime-5zM5XxLr.js.map +1 -0
- package/dist/sandbox-events-DeI5xX8P.js +316 -0
- package/dist/sandbox-events-DeI5xX8P.js.map +1 -0
- package/dist/spawn-journal-CwPvKUTa.js +456 -0
- package/dist/spawn-journal-CwPvKUTa.js.map +1 -0
- package/dist/structural-rollout-IXUEplky.js +1445 -0
- package/dist/structural-rollout-IXUEplky.js.map +1 -0
- package/dist/substrate-B0TYNrXn.js +27 -0
- package/dist/substrate-B0TYNrXn.js.map +1 -0
- package/dist/{substrate-Dyiqmd3o.d.ts → substrate-BcnuSHXm.d.ts} +57 -54
- package/dist/supervise-BiRutHS9.js +7321 -0
- package/dist/supervise-BiRutHS9.js.map +1 -0
- package/dist/supervisor-DTKhF-RV.js +3826 -0
- package/dist/supervisor-DTKhF-RV.js.map +1 -0
- package/dist/testing.d.ts +4 -3
- package/dist/testing.js +2478 -2637
- package/dist/testing.js.map +1 -1
- package/dist/tool-server-RcWgLIsL.js +141 -0
- package/dist/tool-server-RcWgLIsL.js.map +1 -0
- package/dist/trace-propagation-CJJC7SVB.js +57 -0
- package/dist/trace-propagation-CJJC7SVB.js.map +1 -0
- package/dist/types-BaIpb0XT.d.ts +492 -0
- package/dist/types-BevOjfTY.d.ts +765 -0
- package/dist/types-C9j4qg6l.d.ts +500 -0
- package/dist/types-Cja5OTGh.d.ts +190 -0
- package/dist/util-MVgdwuIS.js +145 -0
- package/dist/util-MVgdwuIS.js.map +1 -0
- package/dist/workspace-archive-BosQiotA.js +575 -0
- package/dist/workspace-archive-BosQiotA.js.map +1 -0
- package/package.json +44 -56
- package/skills/build-with-agent-runtime/SKILL.md +1 -0
- package/dist/activation-Cm-9MMX1.d.ts +0 -69
- package/dist/analyst-loop.js.map +0 -1
- package/dist/backends-BO4Jqoe2.d.ts +0 -134
- package/dist/candidate-execution/index.js.map +0 -1
- package/dist/chunk-2KGAN2HM.js +0 -1256
- package/dist/chunk-2KGAN2HM.js.map +0 -1
- package/dist/chunk-2VZYRB55.js +0 -834
- package/dist/chunk-2VZYRB55.js.map +0 -1
- package/dist/chunk-3MDZX7YU.js +0 -125
- package/dist/chunk-3MDZX7YU.js.map +0 -1
- package/dist/chunk-5IBQAPVB.js +0 -29
- package/dist/chunk-5IBQAPVB.js.map +0 -1
- package/dist/chunk-5QOB7H74.js +0 -387
- package/dist/chunk-5QOB7H74.js.map +0 -1
- package/dist/chunk-C5RTIBNZ.js +0 -48
- package/dist/chunk-C5RTIBNZ.js.map +0 -1
- package/dist/chunk-CTRA64LY.js +0 -680
- package/dist/chunk-CTRA64LY.js.map +0 -1
- package/dist/chunk-DPEUKJRO.js +0 -27
- package/dist/chunk-DPEUKJRO.js.map +0 -1
- package/dist/chunk-FD2MBMOH.js +0 -494
- package/dist/chunk-FD2MBMOH.js.map +0 -1
- package/dist/chunk-H5QPIZNX.js +0 -907
- package/dist/chunk-H5QPIZNX.js.map +0 -1
- package/dist/chunk-HLKC4UYB.js +0 -3514
- package/dist/chunk-HLKC4UYB.js.map +0 -1
- package/dist/chunk-HNP72PNU.js +0 -192
- package/dist/chunk-HNP72PNU.js.map +0 -1
- package/dist/chunk-ISPWRSEC.js +0 -408
- package/dist/chunk-ISPWRSEC.js.map +0 -1
- package/dist/chunk-KRBFHMV6.js +0 -1228
- package/dist/chunk-KRBFHMV6.js.map +0 -1
- package/dist/chunk-M22PL4GH.js +0 -171
- package/dist/chunk-M22PL4GH.js.map +0 -1
- package/dist/chunk-NURIQBJQ.js +0 -72
- package/dist/chunk-NURIQBJQ.js.map +0 -1
- package/dist/chunk-OPVWXJ2H.js +0 -75
- package/dist/chunk-OPVWXJ2H.js.map +0 -1
- package/dist/chunk-PZZKQVQV.js +0 -52
- package/dist/chunk-PZZKQVQV.js.map +0 -1
- package/dist/chunk-Q2JSAVQ3.js +0 -671
- package/dist/chunk-Q2JSAVQ3.js.map +0 -1
- package/dist/chunk-RDOAVVHY.js +0 -699
- package/dist/chunk-RDOAVVHY.js.map +0 -1
- package/dist/chunk-SGKPNBXE.js +0 -60
- package/dist/chunk-SGKPNBXE.js.map +0 -1
- package/dist/chunk-SMQXZGLZ.js +0 -351
- package/dist/chunk-SMQXZGLZ.js.map +0 -1
- package/dist/chunk-UHEZW5BU.js +0 -2918
- package/dist/chunk-UHEZW5BU.js.map +0 -1
- package/dist/chunk-UPWGXKXB.js +0 -254
- package/dist/chunk-UPWGXKXB.js.map +0 -1
- package/dist/chunk-VISA6CI3.js +0 -200
- package/dist/chunk-VISA6CI3.js.map +0 -1
- package/dist/chunk-WMTCUOQL.js +0 -474
- package/dist/chunk-WMTCUOQL.js.map +0 -1
- package/dist/chunk-WRTOVNN4.js +0 -4728
- package/dist/chunk-WRTOVNN4.js.map +0 -1
- package/dist/chunk-WSTRQZYQ.js +0 -5576
- package/dist/chunk-WSTRQZYQ.js.map +0 -1
- package/dist/chunk-XBG2W2VW.js +0 -6434
- package/dist/chunk-XBG2W2VW.js.map +0 -1
- package/dist/chunk-YEJR7IXO.js +0 -68
- package/dist/chunk-YEJR7IXO.js.map +0 -1
- package/dist/chunk-YJZA2BIK.js +0 -1338
- package/dist/chunk-YJZA2BIK.js.map +0 -1
- package/dist/completion-gate-BMy5LGoP.d.ts +0 -256
- package/dist/conversation.js.map +0 -1
- package/dist/coordination-BZZSVYpZ.d.ts +0 -2570
- package/dist/environment-provider.js.map +0 -1
- package/dist/improvement-adapter-HAZz-7vK.d.ts +0 -203
- package/dist/knowledge.js.map +0 -1
- package/dist/local-harness-BDNcl6jI.d.ts +0 -175
- package/dist/loop-runner-bin-68aoM9-7.d.ts +0 -199
- package/dist/loop-runner-bin.js.map +0 -1
- package/dist/loops.js.map +0 -1
- package/dist/openai-tools-fnj6SRVg.d.ts +0 -46
- package/dist/protected-model-port-B4t-OQjL.d.ts +0 -271
- package/dist/redact-BuFjxBUJ.d.ts +0 -481
- package/dist/sanitize-DEbPNtyI.d.ts +0 -328
- package/dist/structural-rollout-DEh6CEsa.d.ts +0 -446
- package/dist/supervise-4_48wwvy.d.ts +0 -379
- package/dist/types-BCoemcXU.d.ts +0 -802
- package/dist/types-BwoZWq-i.d.ts +0 -510
- package/dist/types-Cbp72qyu.d.ts +0 -491
- package/dist/types-CmYCMbFT.d.ts +0 -203
- package/dist/types-CvNwMzQt.d.ts +0 -957
- package/dist/worktree-fanout-DxhAWr5Z.d.ts +0 -999
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/candidate-execution/bundle.ts","../src/candidate-execution/workspace-archive.ts"],"sourcesContent":["import type { AgentCandidateBundle } from '@tangle-network/agent-interface'\nimport { agentCandidateBundleSchema } from '@tangle-network/agent-interface'\n\nimport { canonicalCandidateDigest, immutableCandidateValue, omitTopLevelDigest } from './digest'\n\n/** Exact candidate wire shape before the runtime computes its canonical digest. */\nexport type AgentCandidateBundleInput = Omit<AgentCandidateBundle, 'digest'>\n\n/** Validate and content-address a candidate bundle before it crosses an approval boundary. */\nexport function sealAgentCandidateBundle(input: AgentCandidateBundleInput): AgentCandidateBundle {\n const digest = canonicalCandidateDigest(input)\n const parsed = agentCandidateBundleSchema.parse({ ...input, digest })\n const parsedDigest = canonicalCandidateDigest(omitTopLevelDigest(parsed))\n if (parsedDigest !== digest) {\n throw new Error('candidate bundle changed while validating its canonical wire shape')\n }\n return immutableCandidateValue(parsed)\n}\n","import { randomUUID } from 'node:crypto'\nimport { constants as fsConstants } from 'node:fs'\nimport {\n lstat,\n mkdir,\n mkdtemp,\n open,\n readdir,\n readFile,\n realpath,\n rename,\n rm,\n writeFile,\n} from 'node:fs/promises'\nimport { tmpdir } from 'node:os'\nimport { dirname, isAbsolute, join, resolve, sep, win32 } from 'node:path'\nimport { isAnyArrayBuffer, isSharedArrayBuffer } from 'node:util/types'\n\nimport type {\n AgentCandidateCapturedArtifact,\n AgentCandidateWorkspaceSnapshotEvidence,\n} from '@tangle-network/agent-interface'\nimport { type Entry, extract, type Pack, pack } from 'tar-stream'\n\nimport {\n candidateWorkspaceManifest,\n captureMaterializedWorkspace,\n verifyBytes,\n verifyMaterializedWorkspace,\n} from './artifacts'\nimport {\n canonicalCandidateBytes,\n canonicalCandidateDigest,\n deepFreezeCandidate,\n embeddedCandidateArtifact,\n sha256Bytes,\n} from './digest'\nimport {\n assertNoGitIndirection,\n readCandidateGitTreeFiles,\n runCandidateGit,\n} from './git-materialize'\nimport { persistCandidateOutputArtifact } from './output-artifacts'\nimport type {\n AgentCandidateExecutorWorkspaceFile,\n AgentCandidateOutputArtifactPort,\n AgentCandidateWorkspacePort,\n} from './types'\n\nconst archiveKind = 'agent-candidate-workspace-archive' as const\nconst workspaceEntryPrefix = 'workspace/'\nconst repositoryMetadataEntry = 'metadata/repository.json'\nconst repositoryBundleEntry = 'metadata/repository.bundle'\nconst fixedTarTime = new Date(0)\n\nexport interface AgentCandidateWorkspaceArchiveLimits {\n maxArchiveBytes: number\n maxEmbeddedArtifactBytes: number\n maxFiles: number\n maxFileBytes: number\n maxTotalFileBytes: number\n maxPathBytes: number\n maxRepositoryBundleBytes: number\n}\n\nconst defaultLimits: AgentCandidateWorkspaceArchiveLimits = Object.freeze({\n maxArchiveBytes: 512 * 1024 * 1024,\n maxEmbeddedArtifactBytes: 1024 * 1024,\n maxFiles: 50_000,\n maxFileBytes: 128 * 1024 * 1024,\n maxTotalFileBytes: 256 * 1024 * 1024,\n maxPathBytes: 4_096,\n maxRepositoryBundleBytes: 128 * 1024 * 1024,\n})\n\ninterface WorkspaceArchiveRepository {\n headCommit: string\n headTree: string\n bundle: {\n sha256: `sha256:${string}`\n byteLength: number\n bytes: Uint8Array\n }\n}\n\ninterface WorkspaceArchiveRepositoryMetadata {\n kind: typeof archiveKind\n headCommit: string\n headTree: string\n bundle: {\n sha256: `sha256:${string}`\n byteLength: number\n }\n}\n\ninterface DecodedWorkspaceArchive {\n files: Array<{ path: string; mode: number; bytes: Uint8Array }>\n repository?: WorkspaceArchiveRepository\n}\n\nexport interface CaptureAgentCandidateWorkspaceOptions {\n /** Include Git HEAD so task preparation can prove its exact commit and tree. */\n includeRepository?: boolean\n limits?: Partial<AgentCandidateWorkspaceArchiveLimits>\n /** Use the evaluator-owned artifact store when manifest or archive bytes should not be embedded. */\n artifactPersistence?: {\n executionId: string\n outputArtifacts: AgentCandidateOutputArtifactPort\n signal?: AbortSignal\n }\n}\n\nexport interface CreateAgentCandidateWorkspacePortOptions {\n limits?: Partial<AgentCandidateWorkspaceArchiveLimits>\n}\n\nexport interface CapturedAgentCandidateWorkspace {\n readonly snapshot: AgentCandidateWorkspaceSnapshotEvidence\n /** Caller-owned bytes accepted by createAgentCandidateWorkspacePort. */\n readonly archive: Uint8Array\n}\n\n/** Capture one exact regular-file workspace for immutable candidate execution. */\nexport async function captureAgentCandidateWorkspace(\n rootInput: string,\n options: CaptureAgentCandidateWorkspaceOptions = {},\n): Promise<CapturedAgentCandidateWorkspace> {\n const root = resolve(rootInput)\n const limits = workspaceLimits(options.limits)\n const captured = options.includeRepository\n ? await captureRepository(root, limits)\n : await captureMaterializedWorkspace(root, {\n limits: {\n maxFiles: limits.maxFiles,\n maxFileBytes: limits.maxFileBytes,\n maxTotalFileBytes: limits.maxTotalFileBytes,\n },\n })\n assertWorkspaceFilesWithinLimits(captured.files, limits)\n const repository = 'repository' in captured ? captured.repository : undefined\n return captureWorkspaceFiles(captured.files, repository, limits, options.artifactPersistence)\n}\n\n/** Capture detached files returned by a remote executor into the standard archive. */\nexport async function captureAgentCandidateWorkspaceFiles(\n input: readonly AgentCandidateExecutorWorkspaceFile[],\n options: Omit<CaptureAgentCandidateWorkspaceOptions, 'includeRepository'> = {},\n): Promise<CapturedAgentCandidateWorkspace> {\n const limits = workspaceLimits(options.limits)\n return captureWorkspaceFiles(\n normalizeWorkspaceFiles(input, limits),\n undefined,\n limits,\n options.artifactPersistence,\n )\n}\n\nasync function captureWorkspaceFiles(\n files: readonly AgentCandidateExecutorWorkspaceFile[],\n repository: WorkspaceArchiveRepository | undefined,\n limits: AgentCandidateWorkspaceArchiveLimits,\n artifactPersistence: CaptureAgentCandidateWorkspaceOptions['artifactPersistence'],\n): Promise<CapturedAgentCandidateWorkspace> {\n const material = candidateWorkspaceManifest(files)\n const manifest = canonicalCandidateBytes(material)\n const archive = await encodeWorkspaceArchive(files, repository, limits.maxArchiveBytes)\n if (\n !artifactPersistence &&\n (manifest.byteLength > limits.maxEmbeddedArtifactBytes ||\n archive.byteLength > limits.maxEmbeddedArtifactBytes)\n ) {\n throw new Error(\n 'candidate workspace artifacts exceed maxEmbeddedArtifactBytes; artifactPersistence is required',\n )\n }\n const manifestArtifact = await captureWorkspaceArtifact('manifest', manifest, artifactPersistence)\n const archiveArtifact = await captureWorkspaceArtifact('archive', archive, artifactPersistence)\n const snapshot = deepFreezeCandidate({\n kind: 'agent-candidate-workspace-snapshot',\n digest: canonicalCandidateDigest(material),\n material,\n manifest: manifestArtifact,\n archive: archiveArtifact,\n } satisfies AgentCandidateWorkspaceSnapshotEvidence)\n return Object.freeze({ snapshot, archive })\n}\n\nasync function captureWorkspaceArtifact(\n kind: 'manifest' | 'archive',\n bytes: Uint8Array,\n persistence: CaptureAgentCandidateWorkspaceOptions['artifactPersistence'],\n): Promise<AgentCandidateCapturedArtifact> {\n if (!persistence) return embeddedCandidateArtifact(bytes)\n if (!persistence.executionId.trim()) {\n throw new Error('candidate workspace artifact persistence requires an executionId')\n }\n return persistCandidateOutputArtifact(persistence.outputArtifacts, {\n executionId: persistence.executionId,\n purpose: kind === 'manifest' ? 'candidate-workspace-manifest' : 'candidate-workspace-archive',\n bytes,\n ...(persistence.signal ? { signal: persistence.signal } : {}),\n })\n}\n\n/** Create the standard bounded materializer for candidate execution ports. */\nexport function createAgentCandidateWorkspacePort(\n options: CreateAgentCandidateWorkspacePortOptions = {},\n): AgentCandidateWorkspacePort {\n const limits = workspaceLimits(options.limits)\n const port: AgentCandidateWorkspacePort = {\n materialize: async ({ role, snapshot, archive, destination }) => {\n await materializeAgentCandidateWorkspace({\n role,\n snapshot,\n archive,\n destination,\n limits,\n })\n },\n }\n return Object.freeze(port)\n}\n\nasync function materializeAgentCandidateWorkspace(input: {\n role: 'task' | 'candidate' | 'knowledge' | 'memory'\n snapshot: AgentCandidateWorkspaceSnapshotEvidence\n archive: Uint8Array\n destination: string\n limits: AgentCandidateWorkspaceArchiveLimits\n}): Promise<void> {\n verifyBytes(\n input.archive,\n input.snapshot.archive.sha256,\n input.snapshot.archive.byteLength,\n 'candidate workspace archive',\n )\n const decoded = await parseWorkspaceArchive(input.archive, input.limits)\n if (decoded.repository && input.role !== 'task') {\n throw new Error('only task workspaces may carry a Git repository')\n }\n assertArchiveMatchesSnapshot(decoded.files, input.snapshot)\n const destination = resolve(input.destination)\n await prepareEmptyDestination(destination)\n const staging = await mkdtemp(`${destination}.materializing-`)\n try {\n await writeWorkspaceFiles(staging, decoded.files)\n if (decoded.repository) {\n await materializeRepository(decoded.repository, staging)\n }\n await verifyMaterializedWorkspace(staging, input.snapshot.material, {\n ignoredProtectedRootEntries: decoded.repository ? ['.git'] : [],\n })\n await rename(staging, destination)\n } catch (error) {\n await rm(staging, { recursive: true, force: true })\n await rm(destination, { recursive: true, force: true })\n throw error\n }\n}\n\nasync function captureRepository(\n root: string,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): Promise<{\n files: Array<{ path: string; mode: number; bytes: Uint8Array }>\n repository: WorkspaceArchiveRepository\n}> {\n const stats = await lstat(root)\n if (!stats.isDirectory() || stats.isSymbolicLink() || (await realpath(root)) !== root) {\n throw new Error('candidate repository root must be a real directory')\n }\n const topLevel = (await runCandidateGit(root, ['rev-parse', '--show-toplevel'])).stdout\n .toString('utf8')\n .trim()\n if (resolve(topLevel) !== root) {\n throw new Error('candidate repository capture must start at the Git worktree root')\n }\n const gitDir = resolve(\n (await runCandidateGit(root, ['rev-parse', '--absolute-git-dir'])).stdout\n .toString('utf8')\n .trim(),\n )\n if ((await realpath(gitDir)) !== gitDir || gitDir.includes(':')) {\n throw new Error('candidate repository Git object store has an unsupported path')\n }\n await assertNoGitIndirection(root, gitDir, 'candidate repository')\n const headCommit = (await runCandidateGit(root, ['rev-parse', 'HEAD'])).stdout\n .toString('utf8')\n .trim()\n const headTree = (await runCandidateGit(root, ['rev-parse', 'HEAD^{tree}'])).stdout\n .toString('utf8')\n .trim()\n assertGitObjectId(headCommit, 'HEAD')\n assertGitObjectId(headTree, 'HEAD tree')\n if (headCommit.length !== headTree.length) {\n throw new Error('candidate repository HEAD and tree use different object formats')\n }\n const files = await readCandidateGitTreeFiles(root, headTree, {}, limits)\n assertWorkspaceFilesWithinLimits(files, limits)\n const reachableBytesText = (\n await runCandidateGit(root, ['rev-list', '--disk-usage', '--objects', 'HEAD'])\n ).stdout\n .toString('utf8')\n .trim()\n const reachableBytes = Number(reachableBytesText)\n if (!Number.isSafeInteger(reachableBytes) || reachableBytes < 0) {\n throw new Error('candidate repository reachable size is invalid')\n }\n if (reachableBytes > limits.maxRepositoryBundleBytes) {\n throw new Error('candidate repository exceeds maxRepositoryBundleBytes')\n }\n const temporary = await mkdtemp(join(tmpdir(), 'agent-candidate-workspace-bundle-'))\n const bundlePath = join(temporary, `${randomUUID()}.bundle`)\n try {\n await runCandidateGit(root, ['bundle', 'create', bundlePath, 'HEAD'])\n const bundle = Uint8Array.from(await readFile(bundlePath))\n if (bundle.byteLength > limits.maxRepositoryBundleBytes) {\n throw new Error('candidate repository bundle exceeds maxRepositoryBundleBytes')\n }\n return {\n files,\n repository: {\n headCommit,\n headTree,\n bundle: {\n sha256: sha256Bytes(bundle),\n byteLength: bundle.byteLength,\n bytes: bundle,\n },\n },\n }\n } finally {\n await rm(temporary, { recursive: true, force: true })\n }\n}\n\nasync function encodeWorkspaceArchive(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n maxArchiveBytes: number,\n): Promise<Uint8Array> {\n const archive = pack()\n const output = collectStream(archive, maxArchiveBytes, 'candidate workspace archive')\n try {\n await writeWorkspaceArchiveEntries(archive, files, repository)\n archive.finalize()\n return await output\n } catch (error) {\n archive.destroy(error instanceof Error ? error : new Error(String(error)))\n await output.catch(() => undefined)\n throw error\n }\n}\n\nasync function verifyCanonicalWorkspaceArchive(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n expected: Uint8Array,\n maxArchiveBytes: number,\n): Promise<void> {\n const archive = pack()\n const comparison = streamEqualsBytes(\n archive,\n expected,\n maxArchiveBytes,\n 'candidate workspace archive',\n )\n try {\n await writeWorkspaceArchiveEntries(archive, files, repository)\n archive.finalize()\n if (!(await comparison)) throw new Error('candidate workspace tar is not canonical')\n } catch (error) {\n archive.destroy(error instanceof Error ? error : new Error(String(error)))\n await comparison.catch(() => undefined)\n throw error\n }\n}\n\nasync function writeWorkspaceArchiveEntries(\n archive: Pack,\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n repository: WorkspaceArchiveRepository | undefined,\n): Promise<void> {\n for (const file of files) {\n await writeTarEntry(archive, `${workspaceEntryPrefix}${file.path}`, file.mode, file.bytes)\n }\n if (!repository) return\n const metadata = canonicalCandidateBytes({\n kind: archiveKind,\n headCommit: repository.headCommit,\n headTree: repository.headTree,\n bundle: {\n sha256: repository.bundle.sha256,\n byteLength: repository.bundle.byteLength,\n },\n } satisfies WorkspaceArchiveRepositoryMetadata)\n await writeTarEntry(archive, repositoryMetadataEntry, 0o600, metadata)\n await writeTarEntry(archive, repositoryBundleEntry, 0o600, repository.bundle.bytes)\n}\n\nasync function parseWorkspaceArchive(\n bytes: Uint8Array,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): Promise<DecodedWorkspaceArchive> {\n if (bytes.byteLength > limits.maxArchiveBytes) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes')\n }\n const parser = extract()\n const files: DecodedWorkspaceArchive['files'] = []\n const observedEntryNames = new Set<string>()\n const observedPaths = new Set<string>()\n let totalBytes = 0\n let retainedEntryBytes = 0\n let previousPath: string | undefined\n let repositoryMetadata: WorkspaceArchiveRepositoryMetadata | undefined\n let repositoryBundle: Uint8Array | undefined\n const decoded = (async () => {\n for await (const entry of parser) {\n const name = entry.header.name\n if (\n entry.header.type !== 'file' ||\n typeof name !== 'string' ||\n observedEntryNames.has(name)\n ) {\n throw new Error('candidate workspace tar contains an invalid entry')\n }\n observedEntryNames.add(name)\n if (name.startsWith(workspaceEntryPrefix)) {\n if (files.length >= limits.maxFiles) {\n throw new Error('candidate workspace archive has an invalid file count')\n }\n const path = safeArchivePath(name.slice(workspaceEntryPrefix.length), limits.maxPathBytes)\n if (!isWorkspaceFileMode(entry.header.mode)) {\n throw new Error(`candidate workspace archive has an unsupported mode: ${path}`)\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n const fileBytes = await readTarEntry(entry, limits.maxFileBytes, `workspace file ${path}`)\n retainedEntryBytes += fileBytes.byteLength\n assertWorkspacePathOrder(\n path,\n previousPath,\n observedPaths,\n 'candidate workspace archive paths must be unique and sorted',\n )\n previousPath = path\n if (fileBytes.byteLength > limits.maxTotalFileBytes - totalBytes) {\n throw new Error('candidate workspace archive exceeds maxTotalFileBytes')\n }\n totalBytes += fileBytes.byteLength\n files.push({ path, mode: entry.header.mode, bytes: fileBytes })\n } else if (name === repositoryMetadataEntry) {\n if (entry.header.mode !== 0o600 || repositoryMetadata) {\n throw new Error('candidate workspace archive repository metadata is invalid')\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n const metadataBytes = await readTarEntry(\n entry,\n limits.maxPathBytes,\n 'candidate repository metadata',\n )\n retainedEntryBytes += metadataBytes.byteLength\n repositoryMetadata = parseRepositoryMetadata(metadataBytes, limits.maxRepositoryBundleBytes)\n } else if (name === repositoryBundleEntry) {\n if (entry.header.mode !== 0o600 || repositoryBundle) {\n throw new Error('candidate workspace archive repository bundle is invalid')\n }\n assertRetainedArchiveSize(bytes.byteLength, retainedEntryBytes, entry.header.size, limits)\n repositoryBundle = await readTarEntry(\n entry,\n limits.maxRepositoryBundleBytes,\n 'candidate Git bundle',\n )\n retainedEntryBytes += repositoryBundle.byteLength\n } else {\n throw new Error(`candidate workspace tar contains an unsupported entry: ${name}`)\n }\n }\n if (Boolean(repositoryMetadata) !== Boolean(repositoryBundle)) {\n throw new Error('candidate workspace archive repository evidence is incomplete')\n }\n const repository =\n repositoryMetadata && repositoryBundle\n ? repositoryFromTar(repositoryMetadata, repositoryBundle)\n : undefined\n return { files, ...(repository ? { repository } : {}) }\n })()\n parser.end(Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength))\n const result = await decoded\n await verifyCanonicalWorkspaceArchive(\n result.files,\n result.repository,\n bytes,\n limits.maxArchiveBytes,\n )\n return result\n}\n\nfunction assertRetainedArchiveSize(\n archiveBytes: number,\n retainedEntryBytes: number,\n entryBytes: number | undefined,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): void {\n if (\n !Number.isSafeInteger(entryBytes) ||\n entryBytes === undefined ||\n entryBytes < 0 ||\n entryBytes > limits.maxArchiveBytes - archiveBytes - retainedEntryBytes\n ) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes while decoding')\n }\n}\n\nfunction parseRepositoryMetadata(\n bytes: Uint8Array,\n maxBundleBytes: number,\n): WorkspaceArchiveRepositoryMetadata {\n let value: unknown\n try {\n value = JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes))\n } catch (error) {\n throw new Error('candidate workspace archive repository metadata is invalid', { cause: error })\n }\n if (\n !isRecord(value) ||\n Object.keys(value).sort().join(',') !== 'bundle,headCommit,headTree,kind' ||\n value.kind !== archiveKind ||\n typeof value.headCommit !== 'string' ||\n typeof value.headTree !== 'string' ||\n !isRecord(value.bundle) ||\n Object.keys(value.bundle).sort().join(',') !== 'byteLength,sha256' ||\n typeof value.bundle.sha256 !== 'string' ||\n !/^sha256:[a-f0-9]{64}$/.test(value.bundle.sha256) ||\n !Number.isSafeInteger(value.bundle.byteLength) ||\n (value.bundle.byteLength as number) <= 0 ||\n (value.bundle.byteLength as number) > maxBundleBytes\n ) {\n throw new Error('candidate workspace archive repository is invalid')\n }\n if (!Buffer.from(canonicalCandidateBytes(value)).equals(Buffer.from(bytes))) {\n throw new Error('candidate workspace archive repository metadata is not canonical')\n }\n assertGitObjectId(value.headCommit, 'repository HEAD')\n assertGitObjectId(value.headTree, 'repository HEAD tree')\n if (value.headCommit.length !== value.headTree.length) {\n throw new Error('candidate repository HEAD and tree use different object formats')\n }\n return {\n kind: archiveKind,\n headCommit: value.headCommit,\n headTree: value.headTree,\n bundle: {\n sha256: value.bundle.sha256 as `sha256:${string}`,\n byteLength: value.bundle.byteLength as number,\n },\n }\n}\n\nfunction repositoryFromTar(\n metadata: WorkspaceArchiveRepositoryMetadata,\n bundle: Uint8Array,\n): WorkspaceArchiveRepository {\n verifyBytes(bundle, metadata.bundle.sha256, metadata.bundle.byteLength, 'candidate Git bundle')\n return {\n headCommit: metadata.headCommit,\n headTree: metadata.headTree,\n bundle: { ...metadata.bundle, bytes: bundle },\n }\n}\n\nasync function writeTarEntry(\n archive: Pack,\n name: string,\n mode: number,\n bytes: Uint8Array,\n): Promise<void> {\n await new Promise<void>((resolveEntry, rejectEntry) => {\n archive.entry(\n {\n name,\n mode,\n uid: 0,\n gid: 0,\n size: bytes.byteLength,\n mtime: fixedTarTime,\n type: 'file',\n uname: '',\n gname: '',\n },\n Buffer.from(bytes.buffer, bytes.byteOffset, bytes.byteLength),\n (error) => (error ? rejectEntry(error) : resolveEntry()),\n )\n })\n}\n\nasync function readTarEntry(entry: Entry, maxBytes: number, label: string): Promise<Uint8Array> {\n const size = entry.header.size\n if (!Number.isSafeInteger(size) || size === undefined || size < 0 || size > maxBytes) {\n throw new Error(`${label} has an invalid tar size`)\n }\n const bytes = await collectStream(entry, maxBytes, label)\n if (bytes.byteLength !== size) throw new Error(`${label} differs from its tar size`)\n return bytes\n}\n\nasync function collectStream(\n stream: AsyncIterable<Uint8Array>,\n maxBytes: number,\n label: string,\n): Promise<Uint8Array> {\n const chunks: Buffer[] = []\n let totalBytes = 0\n for await (const chunk of stream) {\n if (chunk.byteLength > maxBytes - totalBytes) {\n const error = new Error(`${label} exceeds its size limit`)\n if ('destroy' in stream && typeof stream.destroy === 'function') stream.destroy(error)\n throw error\n }\n const bytes = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)\n chunks.push(bytes)\n totalBytes += bytes.byteLength\n }\n return Buffer.concat(chunks, totalBytes)\n}\n\nasync function streamEqualsBytes(\n stream: AsyncIterable<Uint8Array>,\n expected: Uint8Array,\n maxBytes: number,\n label: string,\n): Promise<boolean> {\n const expectedBuffer = Buffer.from(expected.buffer, expected.byteOffset, expected.byteLength)\n let equal = true\n let offset = 0\n for await (const chunk of stream) {\n if (chunk.byteLength > maxBytes - offset) {\n const error = new Error(`${label} exceeds its size limit`)\n if ('destroy' in stream && typeof stream.destroy === 'function') stream.destroy(error)\n throw error\n }\n const observed = Buffer.from(chunk.buffer, chunk.byteOffset, chunk.byteLength)\n if (\n offset + observed.byteLength > expectedBuffer.byteLength ||\n !observed.equals(expectedBuffer.subarray(offset, offset + observed.byteLength))\n ) {\n equal = false\n }\n offset += observed.byteLength\n }\n return equal && offset === expectedBuffer.byteLength\n}\n\nasync function prepareEmptyDestination(destination: string): Promise<void> {\n await mkdir(destination, { recursive: true, mode: 0o700 })\n const stats = await lstat(destination)\n if (\n !stats.isDirectory() ||\n stats.isSymbolicLink() ||\n (await realpath(destination)) !== destination\n ) {\n throw new Error('candidate workspace destination must be a real directory')\n }\n if ((await readdir(destination)).length > 0) {\n throw new Error('candidate workspace destination must be empty')\n }\n}\n\nasync function writeWorkspaceFiles(\n destination: string,\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n): Promise<void> {\n for (const file of files) {\n const path = workspacePath(destination, file.path)\n await mkdir(dirname(path), { recursive: true, mode: 0o700 })\n const descriptor = await open(\n path,\n fsConstants.O_WRONLY |\n fsConstants.O_CREAT |\n fsConstants.O_EXCL |\n (typeof fsConstants.O_NOFOLLOW === 'number' ? fsConstants.O_NOFOLLOW : 0),\n 0o600,\n )\n try {\n await descriptor.writeFile(file.bytes)\n const stats = await descriptor.stat()\n if (!stats.isFile() || stats.nlink !== 1) {\n throw new Error(`candidate workspace file identity changed while writing: ${file.path}`)\n }\n await descriptor.chmod(file.mode)\n } finally {\n await descriptor.close()\n }\n }\n}\n\nasync function materializeRepository(\n repository: WorkspaceArchiveRepository,\n destination: string,\n): Promise<void> {\n const temporary = await mkdtemp(join(tmpdir(), 'agent-candidate-workspace-bundle-'))\n const bundlePath = join(temporary, `${randomUUID()}.bundle`)\n try {\n await writeFile(bundlePath, repository.bundle.bytes, { flag: 'wx', mode: 0o600 })\n await runCandidateGit(destination, [\n 'init',\n '--quiet',\n '--initial-branch=candidate',\n `--object-format=${repository.headCommit.length === 64 ? 'sha256' : 'sha1'}`,\n ])\n await runCandidateGit(destination, ['bundle', 'verify', bundlePath])\n await runCandidateGit(destination, ['bundle', 'unbundle', bundlePath])\n const objectType = (\n await runCandidateGit(destination, ['cat-file', '-t', repository.headCommit])\n ).stdout\n .toString('utf8')\n .trim()\n if (objectType !== 'commit') throw new Error('candidate repository HEAD is not a commit')\n const observedTree = (\n await runCandidateGit(destination, ['rev-parse', `${repository.headCommit}^{tree}`])\n ).stdout\n .toString('utf8')\n .trim()\n if (observedTree !== repository.headTree) {\n throw new Error('candidate repository bundle HEAD tree changed')\n }\n await runCandidateGit(destination, ['update-ref', '--no-deref', 'HEAD', repository.headCommit])\n await runCandidateGit(destination, ['read-tree', repository.headTree])\n const status = (\n await runCandidateGit(destination, ['status', '--porcelain=v1', '--untracked-files=all'])\n ).stdout\n .toString('utf8')\n .trim()\n if (status) throw new Error('candidate repository files do not exactly match HEAD')\n } finally {\n await rm(temporary, { recursive: true, force: true })\n }\n}\n\nfunction assertArchiveMatchesSnapshot(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n snapshot: AgentCandidateWorkspaceSnapshotEvidence,\n): void {\n const material = candidateWorkspaceManifest(files)\n const materialBytes = canonicalCandidateBytes(material)\n verifyBytes(\n materialBytes,\n snapshot.manifest.sha256,\n snapshot.manifest.byteLength,\n 'candidate workspace manifest',\n )\n if (\n canonicalCandidateDigest(material) !== snapshot.digest ||\n !Buffer.from(materialBytes).equals(Buffer.from(canonicalCandidateBytes(snapshot.material)))\n ) {\n throw new Error('candidate workspace archive does not match its snapshot manifest')\n }\n}\n\nfunction assertWorkspaceFilesWithinLimits(\n files: ReadonlyArray<{ path: string; mode: number; bytes: Uint8Array }>,\n limits: AgentCandidateWorkspaceArchiveLimits,\n): void {\n if (files.length > limits.maxFiles) {\n throw new Error('candidate workspace exceeds maxFiles')\n }\n let totalBytes = 0\n let previousPath: string | undefined\n const observedPaths = new Set<string>()\n for (const file of files) {\n const path = safeArchivePath(file.path, limits.maxPathBytes)\n assertWorkspacePathOrder(\n path,\n previousPath,\n observedPaths,\n 'candidate workspace paths must be unique and sorted',\n )\n previousPath = path\n if (!isWorkspaceFileMode(file.mode)) {\n throw new Error(`candidate workspace file has unsupported mode: ${path}`)\n }\n if (file.bytes.byteLength > limits.maxFileBytes) {\n throw new Error(`candidate workspace file exceeds maxFileBytes: ${path}`)\n }\n totalBytes += file.bytes.byteLength\n if (totalBytes > limits.maxTotalFileBytes) {\n throw new Error('candidate workspace exceeds maxTotalFileBytes')\n }\n }\n}\n\nfunction normalizeWorkspaceFiles(\n input: readonly AgentCandidateExecutorWorkspaceFile[],\n limits: AgentCandidateWorkspaceArchiveLimits,\n): AgentCandidateExecutorWorkspaceFile[] {\n if (!Array.isArray(input)) {\n throw new Error('candidate workspace files must be an array')\n }\n const fileCount = input.length\n if (fileCount > limits.maxFiles) {\n throw new Error('candidate workspace exceeds maxFiles')\n }\n let totalBytes = 0\n const files: AgentCandidateExecutorWorkspaceFile[] = []\n for (let index = 0; index < fileCount; index++) {\n const inputFile = input[index]\n if (!isRecord(inputFile) || Object.keys(inputFile).sort().join(',') !== 'bytes,mode,path') {\n throw new Error(`candidate workspace file ${index} is invalid`)\n }\n const descriptors = Object.getOwnPropertyDescriptors(inputFile)\n if (\n !('value' in (descriptors.path ?? {})) ||\n !('value' in (descriptors.mode ?? {})) ||\n !('value' in (descriptors.bytes ?? {}))\n ) {\n throw new Error(`candidate workspace file ${index} must use fixed values`)\n }\n const path = safeArchivePath(descriptors.path?.value, limits.maxPathBytes)\n const mode = descriptors.mode?.value\n const inputBytes = descriptors.bytes?.value\n if (!isWorkspaceFileMode(mode)) {\n throw new Error(`candidate workspace file has unsupported mode: ${path}`)\n }\n const view = inspectWorkspaceBytes(inputBytes, path)\n if (view.byteLength > limits.maxFileBytes) {\n throw new Error(`candidate workspace file exceeds maxFileBytes: ${path}`)\n }\n if (view.byteLength > limits.maxTotalFileBytes - totalBytes) {\n throw new Error('candidate workspace exceeds maxTotalFileBytes')\n }\n if (view.byteLength > Math.max(0, limits.maxArchiveBytes - 1024)) {\n throw new Error('candidate workspace archive exceeds maxArchiveBytes')\n }\n totalBytes += view.byteLength\n files.push({ path, mode, bytes: detachWorkspaceBytes(view) })\n }\n files.sort((left, right) => (left.path < right.path ? -1 : left.path > right.path ? 1 : 0))\n assertWorkspaceFilesWithinLimits(files, limits)\n return files\n}\n\nfunction isWorkspaceFileMode(value: unknown): value is number {\n return Number.isSafeInteger(value) && (value as number) >= 0 && (value as number) <= 0o777\n}\n\nfunction workspaceLimits(\n overrides: Partial<AgentCandidateWorkspaceArchiveLimits> | undefined,\n): AgentCandidateWorkspaceArchiveLimits {\n const limits = { ...defaultLimits, ...overrides }\n for (const [name, value] of Object.entries(limits)) {\n if (!Number.isSafeInteger(value) || value <= 0) {\n throw new Error(`candidate workspace ${name} must be a positive safe integer`)\n }\n }\n return Object.freeze(limits)\n}\n\nfunction safeArchivePath(value: unknown, maxPathBytes: number): string {\n if (\n typeof value !== 'string' ||\n !value ||\n !isWellFormedUnicode(value) ||\n Buffer.byteLength(value, 'utf8') > maxPathBytes ||\n isAbsolute(value) ||\n win32.isAbsolute(value) ||\n value.includes('\\\\') ||\n value.includes('\\0') ||\n hasControlCharacter(value) ||\n value.split('/').some((part) => !part || part === '.' || part === '..') ||\n ['.git', '.sidecar'].includes(value.split('/')[0]?.toLowerCase() ?? '')\n ) {\n throw new Error(`candidate workspace archive contains an unsafe path: ${String(value)}`)\n }\n return value\n}\n\nfunction assertWorkspacePathOrder(\n path: string,\n previousPath: string | undefined,\n observedPaths: Set<string>,\n errorMessage: string,\n): void {\n if (previousPath !== undefined && previousPath >= path) throw new Error(errorMessage)\n for (let slash = path.indexOf('/'); slash !== -1; slash = path.indexOf('/', slash + 1)) {\n if (observedPaths.has(path.slice(0, slash))) throw new Error(errorMessage)\n }\n observedPaths.add(path)\n}\n\nfunction inspectWorkspaceBytes(\n input: unknown,\n path: string,\n): { buffer: ArrayBuffer; byteOffset: number; byteLength: number } {\n let buffer: ArrayBufferLike\n let byteOffset: number\n let byteLength: number\n try {\n buffer = typedArrayBufferGetter.call(input as Uint8Array) as ArrayBufferLike\n byteOffset = typedArrayByteOffsetGetter.call(input as Uint8Array) as number\n byteLength = typedArrayByteLengthGetter.call(input as Uint8Array) as number\n } catch {\n throw new Error(`candidate workspace file bytes are invalid: ${path}`)\n }\n if (isSharedArrayBuffer(buffer)) {\n throw new Error(`candidate workspace file uses shared bytes: ${path}`)\n }\n if (!isAnyArrayBuffer(buffer)) {\n throw new Error(`candidate workspace file bytes are invalid: ${path}`)\n }\n return { buffer, byteOffset, byteLength }\n}\n\nfunction detachWorkspaceBytes(input: {\n buffer: ArrayBuffer\n byteOffset: number\n byteLength: number\n}): Uint8Array {\n const { buffer, byteOffset, byteLength } = input\n const copy = new Uint8Array(byteLength)\n Uint8Array.prototype.set.call(copy, new Uint8Array(buffer, byteOffset, byteLength))\n return copy\n}\n\nfunction isWellFormedUnicode(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const code = value.charCodeAt(index)\n if (code >= 0xd800 && code <= 0xdbff) {\n const next = value.charCodeAt(index + 1)\n if (!(next >= 0xdc00 && next <= 0xdfff)) return false\n index++\n } else if (code >= 0xdc00 && code <= 0xdfff) {\n return false\n }\n }\n return true\n}\n\nfunction workspacePath(root: string, relativePath: string): string {\n const path = resolve(root, relativePath)\n if (!path.startsWith(`${root}${sep}`)) {\n throw new Error(`candidate workspace archive path escapes its destination: ${relativePath}`)\n }\n return path\n}\n\nfunction assertGitObjectId(value: string, label: string): void {\n if (!/^(?:[a-f0-9]{40}|[a-f0-9]{64})$/.test(value)) {\n throw new Error(`candidate repository ${label} is not a Git object id`)\n }\n}\n\nfunction hasControlCharacter(value: string): boolean {\n for (let index = 0; index < value.length; index++) {\n const code = value.charCodeAt(index)\n if (code < 0x20 || code === 0x7f) return true\n }\n return false\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\ntype TypedArrayGetter = (this: Uint8Array) => unknown\n\nfunction requireTypedArrayGetter(name: 'buffer' | 'byteOffset' | 'byteLength'): TypedArrayGetter {\n const typedArrayPrototype = Object.getPrototypeOf(Uint8Array.prototype) as object\n const getter = Object.getOwnPropertyDescriptor(typedArrayPrototype, name)?.get\n if (!getter) throw new Error(`typed array intrinsic ${name} accessor is unavailable`)\n return getter\n}\n\nconst typedArrayBufferGetter = requireTypedArrayGetter('buffer')\nconst typedArrayByteOffsetGetter = requireTypedArrayGetter('byteOffset')\nconst typedArrayByteLengthGetter = requireTypedArrayGetter('byteLength')\n"],"mappings":"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","names":[]}
|
package/dist/chunk-SGKPNBXE.js
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
// src/mcp/kb-gate.ts
|
|
2
|
-
var norm = (s) => s.toLowerCase().replace(/\s+/g, " ").trim();
|
|
3
|
-
function valueAppears(value, passageNorm) {
|
|
4
|
-
if (passageNorm.includes(norm(String(value)))) return true;
|
|
5
|
-
if (typeof value !== "number" || !Number.isFinite(value)) return false;
|
|
6
|
-
const forms = [value.toLocaleString("en-US")];
|
|
7
|
-
if (Math.abs(value) >= 1e9) forms.push(`${trimZero(value / 1e9)} billion`);
|
|
8
|
-
if (Math.abs(value) >= 1e6) forms.push(`${trimZero(value / 1e6)} million`);
|
|
9
|
-
return forms.some((f) => passageNorm.includes(norm(f)));
|
|
10
|
-
}
|
|
11
|
-
function trimZero(n) {
|
|
12
|
-
return Number.isInteger(n) ? String(n) : String(Number(n.toFixed(2)));
|
|
13
|
-
}
|
|
14
|
-
function builtinJudges(minPassageChars, selfArtifactKinds) {
|
|
15
|
-
const kinds = selfArtifactKinds.map((k) => k.toLowerCase());
|
|
16
|
-
return [
|
|
17
|
-
{
|
|
18
|
-
name: "passage-non-empty",
|
|
19
|
-
judge: (c) => c.verbatimPassage.trim().length >= minPassageChars ? { accept: true } : { accept: false, reason: `passage shorter than ${minPassageChars} chars` }
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
// THE anti-hallucination floor — the passage must literally be in the source.
|
|
23
|
-
name: "passage-present",
|
|
24
|
-
judge: (c) => norm(c.sourceText).includes(norm(c.verbatimPassage)) ? { accept: true } : { accept: false, reason: "verbatim passage not found in source (unbacked fact)" }
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
name: "value-in-passage",
|
|
28
|
-
judge: (c) => c.value === void 0 || valueAppears(c.value, norm(c.verbatimPassage)) ? { accept: true } : { accept: false, reason: `value ${JSON.stringify(c.value)} not present in passage` }
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
name: "no-circular-citation",
|
|
32
|
-
judge: (c) => {
|
|
33
|
-
if (!c.citation || kinds.length === 0) return { accept: true };
|
|
34
|
-
const cite = c.citation.toLowerCase();
|
|
35
|
-
const hit = kinds.find((k) => cite.includes(k));
|
|
36
|
-
return hit ? { accept: false, reason: `circular citation to self-generated artifact "${hit}"` } : { accept: true };
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
];
|
|
40
|
-
}
|
|
41
|
-
function createKbGate(options = {}) {
|
|
42
|
-
const judges = [
|
|
43
|
-
...builtinJudges(options.minPassageChars ?? 12, options.selfArtifactKinds ?? []),
|
|
44
|
-
...options.judges ?? []
|
|
45
|
-
];
|
|
46
|
-
return async (candidate) => {
|
|
47
|
-
for (const j of judges) {
|
|
48
|
-
const verdict = await j.judge(candidate);
|
|
49
|
-
if (!verdict.accept) {
|
|
50
|
-
return { accepted: false, vetoedBy: j.name, reason: verdict.reason };
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
return { accepted: true };
|
|
54
|
-
};
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
export {
|
|
58
|
-
createKbGate
|
|
59
|
-
};
|
|
60
|
-
//# sourceMappingURL=chunk-SGKPNBXE.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/kb-gate.ts"],"sourcesContent":["/**\n *\n * `createKbGate` — the valid-only knowledge-base growth gate, distilled from\n * physim's KB-research subsystem. A research-in-a-loop delegate (or any KB\n * writer) runs candidate facts through this before persisting, so the KB grows\n * with ONLY grounded facts — hallucinated, unsourced, or laundered claims are\n * vetoed at the gate.\n *\n * Fail-closed by construction: every judge must `accept`; the FIRST veto wins\n * and the fact is rejected. The non-negotiable floor (always on, can't be\n * disabled) is the **passage-present guard** — a fact's `verbatimPassage` MUST\n * literally appear in its `sourceText`. That single check kills the dominant\n * failure mode (a confident claim decoupled from any real source).\n *\n * Pure + dependency-free: it operates on fact candidates, not on a store, so it\n * composes with `@tangle-network/agent-knowledge` or any persistence layer\n * without importing it. The remediation policy (correct-on-veto vs\n * escalate-as-unverified) is the caller's — this returns the verdict; it never\n * drops a fact silently.\n *\n * @experimental\n */\n\n/** @experimental A fact proposed for the KB, with its grounding. */\nexport interface FactCandidate {\n /** The atomic claim text. */\n claim: string\n /** Optional extracted value (number or string) the claim asserts. */\n value?: string | number\n /** Verbatim span lifted from the source that backs the claim. */\n verbatimPassage: string\n /** The raw source text the passage must be grounded in. */\n sourceText: string\n /** Where the fact claims to come from — checked for circular/self citations. */\n citation?: string\n}\n\n/** @experimental */\nexport interface FactJudgeVerdict {\n accept: boolean\n reason?: string\n}\n\n/** @experimental A pluggable fact validator. Throw is NOT allowed — return a\n * verdict; a thrown judge is a programmer error, not a veto. */\nexport interface FactJudge {\n name: string\n judge(candidate: FactCandidate): FactJudgeVerdict | Promise<FactJudgeVerdict>\n}\n\n/** @experimental */\nexport interface KbGateResult {\n accepted: boolean\n /** Name of the judge that vetoed; undefined when accepted. */\n vetoedBy?: string\n reason?: string\n}\n\n/** @experimental */\nexport interface CreateKbGateOptions {\n /** Extra judges appended after the built-in floor (e.g. an LLM judge). */\n judges?: FactJudge[]\n /** Minimum verbatim-passage length. Default 12 — kills empty/stub passages. */\n minPassageChars?: number\n /**\n * Citation tokens that denote a SELF-generated artifact (e.g. `'spec'`,\n * `'cad_params'`, `'requirements'`). A citation naming one is circular\n * (laundering) — the fact cites a derived artifact, not a real source.\n * Default `[]` (no circular check unless the consumer declares its kinds).\n */\n selfArtifactKinds?: string[]\n}\n\nconst norm = (s: string): string => s.toLowerCase().replace(/\\s+/g, ' ').trim()\n\n/** Does `value` appear in the (normalized) passage — literally, comma-grouped,\n * or in billion/million shorthand (the forms a source actually writes). */\nfunction valueAppears(value: string | number, passageNorm: string): boolean {\n if (passageNorm.includes(norm(String(value)))) return true\n if (typeof value !== 'number' || !Number.isFinite(value)) return false\n const forms = [value.toLocaleString('en-US')]\n if (Math.abs(value) >= 1e9) forms.push(`${trimZero(value / 1e9)} billion`)\n if (Math.abs(value) >= 1e6) forms.push(`${trimZero(value / 1e6)} million`)\n return forms.some((f) => passageNorm.includes(norm(f)))\n}\n\nfunction trimZero(n: number): string {\n return Number.isInteger(n) ? String(n) : String(Number(n.toFixed(2)))\n}\n\n/** The always-on floor judges. Order matters: cheapest / most-fundamental first. */\nfunction builtinJudges(minPassageChars: number, selfArtifactKinds: string[]): FactJudge[] {\n const kinds = selfArtifactKinds.map((k) => k.toLowerCase())\n return [\n {\n name: 'passage-non-empty',\n judge: (c) =>\n c.verbatimPassage.trim().length >= minPassageChars\n ? { accept: true }\n : { accept: false, reason: `passage shorter than ${minPassageChars} chars` },\n },\n {\n // THE anti-hallucination floor — the passage must literally be in the source.\n name: 'passage-present',\n judge: (c) =>\n norm(c.sourceText).includes(norm(c.verbatimPassage))\n ? { accept: true }\n : { accept: false, reason: 'verbatim passage not found in source (unbacked fact)' },\n },\n {\n name: 'value-in-passage',\n judge: (c) =>\n c.value === undefined || valueAppears(c.value, norm(c.verbatimPassage))\n ? { accept: true }\n : { accept: false, reason: `value ${JSON.stringify(c.value)} not present in passage` },\n },\n {\n name: 'no-circular-citation',\n judge: (c) => {\n if (!c.citation || kinds.length === 0) return { accept: true }\n const cite = c.citation.toLowerCase()\n const hit = kinds.find((k) => cite.includes(k))\n return hit\n ? { accept: false, reason: `circular citation to self-generated artifact \"${hit}\"` }\n : { accept: true }\n },\n },\n ]\n}\n\n/**\n *\n * Build a fail-closed KB gate. The returned function runs the built-in floor\n * (passage-non-empty → passage-present → value-in-passage → no-circular-citation)\n * then any consumer judges, returning on the first veto.\n *\n * @experimental\n */\nexport function createKbGate(\n options: CreateKbGateOptions = {},\n): (candidate: FactCandidate) => Promise<KbGateResult> {\n const judges = [\n ...builtinJudges(options.minPassageChars ?? 12, options.selfArtifactKinds ?? []),\n ...(options.judges ?? []),\n ]\n return async (candidate) => {\n for (const j of judges) {\n const verdict = await j.judge(candidate)\n if (!verdict.accept) {\n return { accepted: false, vetoedBy: j.name, reason: verdict.reason }\n }\n }\n return { accepted: true }\n }\n}\n"],"mappings":";AAyEA,IAAM,OAAO,CAAC,MAAsB,EAAE,YAAY,EAAE,QAAQ,QAAQ,GAAG,EAAE,KAAK;AAI9E,SAAS,aAAa,OAAwB,aAA8B;AAC1E,MAAI,YAAY,SAAS,KAAK,OAAO,KAAK,CAAC,CAAC,EAAG,QAAO;AACtD,MAAI,OAAO,UAAU,YAAY,CAAC,OAAO,SAAS,KAAK,EAAG,QAAO;AACjE,QAAM,QAAQ,CAAC,MAAM,eAAe,OAAO,CAAC;AAC5C,MAAI,KAAK,IAAI,KAAK,KAAK,IAAK,OAAM,KAAK,GAAG,SAAS,QAAQ,GAAG,CAAC,UAAU;AACzE,MAAI,KAAK,IAAI,KAAK,KAAK,IAAK,OAAM,KAAK,GAAG,SAAS,QAAQ,GAAG,CAAC,UAAU;AACzE,SAAO,MAAM,KAAK,CAAC,MAAM,YAAY,SAAS,KAAK,CAAC,CAAC,CAAC;AACxD;AAEA,SAAS,SAAS,GAAmB;AACnC,SAAO,OAAO,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,OAAO,OAAO,EAAE,QAAQ,CAAC,CAAC,CAAC;AACtE;AAGA,SAAS,cAAc,iBAAyB,mBAA0C;AACxF,QAAM,QAAQ,kBAAkB,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC;AAC1D,SAAO;AAAA,IACL;AAAA,MACE,MAAM;AAAA,MACN,OAAO,CAAC,MACN,EAAE,gBAAgB,KAAK,EAAE,UAAU,kBAC/B,EAAE,QAAQ,KAAK,IACf,EAAE,QAAQ,OAAO,QAAQ,wBAAwB,eAAe,SAAS;AAAA,IACjF;AAAA,IACA;AAAA;AAAA,MAEE,MAAM;AAAA,MACN,OAAO,CAAC,MACN,KAAK,EAAE,UAAU,EAAE,SAAS,KAAK,EAAE,eAAe,CAAC,IAC/C,EAAE,QAAQ,KAAK,IACf,EAAE,QAAQ,OAAO,QAAQ,uDAAuD;AAAA,IACxF;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO,CAAC,MACN,EAAE,UAAU,UAAa,aAAa,EAAE,OAAO,KAAK,EAAE,eAAe,CAAC,IAClE,EAAE,QAAQ,KAAK,IACf,EAAE,QAAQ,OAAO,QAAQ,SAAS,KAAK,UAAU,EAAE,KAAK,CAAC,0BAA0B;AAAA,IAC3F;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,OAAO,CAAC,MAAM;AACZ,YAAI,CAAC,EAAE,YAAY,MAAM,WAAW,EAAG,QAAO,EAAE,QAAQ,KAAK;AAC7D,cAAM,OAAO,EAAE,SAAS,YAAY;AACpC,cAAM,MAAM,MAAM,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC;AAC9C,eAAO,MACH,EAAE,QAAQ,OAAO,QAAQ,iDAAiD,GAAG,IAAI,IACjF,EAAE,QAAQ,KAAK;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;AAUO,SAAS,aACd,UAA+B,CAAC,GACqB;AACrD,QAAM,SAAS;AAAA,IACb,GAAG,cAAc,QAAQ,mBAAmB,IAAI,QAAQ,qBAAqB,CAAC,CAAC;AAAA,IAC/E,GAAI,QAAQ,UAAU,CAAC;AAAA,EACzB;AACA,SAAO,OAAO,cAAc;AAC1B,eAAW,KAAK,QAAQ;AACtB,YAAM,UAAU,MAAM,EAAE,MAAM,SAAS;AACvC,UAAI,CAAC,QAAQ,QAAQ;AACnB,eAAO,EAAE,UAAU,OAAO,UAAU,EAAE,MAAM,QAAQ,QAAQ,OAAO;AAAA,MACrE;AAAA,IACF;AACA,WAAO,EAAE,UAAU,KAAK;AAAA,EAC1B;AACF;","names":[]}
|
package/dist/chunk-SMQXZGLZ.js
DELETED
|
@@ -1,351 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
ValidationError
|
|
3
|
-
} from "./chunk-YEJR7IXO.js";
|
|
4
|
-
|
|
5
|
-
// src/mcp/tool-server.ts
|
|
6
|
-
import { createInterface } from "readline";
|
|
7
|
-
var PROTOCOL_VERSION = "2024-11-05";
|
|
8
|
-
function createStdioToolServer(options) {
|
|
9
|
-
const tools = /* @__PURE__ */ new Map();
|
|
10
|
-
for (const tool of options.tools) {
|
|
11
|
-
if (tools.has(tool.name)) {
|
|
12
|
-
throw new ValidationError(`createStdioToolServer: duplicate tool name "${tool.name}"`);
|
|
13
|
-
}
|
|
14
|
-
tools.set(tool.name, tool);
|
|
15
|
-
}
|
|
16
|
-
let stopped = false;
|
|
17
|
-
let activeReadline;
|
|
18
|
-
async function handle(message) {
|
|
19
|
-
if (stopped) {
|
|
20
|
-
return rpcError(message.id ?? null, -32099, "server stopped");
|
|
21
|
-
}
|
|
22
|
-
if (message.method === "initialize") {
|
|
23
|
-
return rpcResult(message.id ?? null, {
|
|
24
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
25
|
-
capabilities: { tools: {} },
|
|
26
|
-
serverInfo: { name: options.serverName, version: options.serverVersion }
|
|
27
|
-
});
|
|
28
|
-
}
|
|
29
|
-
if (message.method === "notifications/initialized") {
|
|
30
|
-
return null;
|
|
31
|
-
}
|
|
32
|
-
if (message.method === "tools/list") {
|
|
33
|
-
return rpcResult(message.id ?? null, {
|
|
34
|
-
tools: [...tools.values()].map((tool) => ({
|
|
35
|
-
name: tool.name,
|
|
36
|
-
description: tool.description,
|
|
37
|
-
inputSchema: tool.inputSchema
|
|
38
|
-
}))
|
|
39
|
-
});
|
|
40
|
-
}
|
|
41
|
-
if (message.method === "tools/call") {
|
|
42
|
-
const params = message.params ?? {};
|
|
43
|
-
const name = typeof params.name === "string" ? params.name : "";
|
|
44
|
-
const tool = tools.get(name);
|
|
45
|
-
if (!tool) {
|
|
46
|
-
return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`);
|
|
47
|
-
}
|
|
48
|
-
try {
|
|
49
|
-
const output = await tool.handler(params.arguments ?? {});
|
|
50
|
-
return rpcResult(message.id ?? null, {
|
|
51
|
-
content: [{ type: "text", text: JSON.stringify(output) }],
|
|
52
|
-
structuredContent: output,
|
|
53
|
-
isError: false
|
|
54
|
-
});
|
|
55
|
-
} catch (err) {
|
|
56
|
-
const reason = err instanceof Error ? err.message : String(err);
|
|
57
|
-
const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32e3;
|
|
58
|
-
return rpcError(message.id ?? null, code, reason);
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
if (message.id === void 0 || message.id === null) return null;
|
|
62
|
-
return rpcError(message.id, -32601, `unknown method: ${message.method}`);
|
|
63
|
-
}
|
|
64
|
-
async function serve(transport) {
|
|
65
|
-
const input = transport?.input ?? process.stdin;
|
|
66
|
-
const output = transport?.output ?? process.stdout;
|
|
67
|
-
const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY });
|
|
68
|
-
activeReadline = rl;
|
|
69
|
-
return new Promise((resolve, reject) => {
|
|
70
|
-
rl.on("line", (line) => {
|
|
71
|
-
const trimmed = line.trim();
|
|
72
|
-
if (!trimmed) return;
|
|
73
|
-
let parsed;
|
|
74
|
-
try {
|
|
75
|
-
parsed = JSON.parse(trimmed);
|
|
76
|
-
} catch (err) {
|
|
77
|
-
writeResponse(output, rpcError(null, -32700, `parse error: ${err.message}`));
|
|
78
|
-
return;
|
|
79
|
-
}
|
|
80
|
-
if (!parsed || parsed.jsonrpc !== "2.0" || typeof parsed.method !== "string") {
|
|
81
|
-
writeResponse(output, rpcError(parsed?.id ?? null, -32600, "invalid request"));
|
|
82
|
-
return;
|
|
83
|
-
}
|
|
84
|
-
void handle(parsed).then((response) => {
|
|
85
|
-
if (response) writeResponse(output, response);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
rl.on("close", () => resolve());
|
|
89
|
-
rl.on("error", (err) => reject(err));
|
|
90
|
-
if (stopped) {
|
|
91
|
-
rl.close();
|
|
92
|
-
resolve();
|
|
93
|
-
}
|
|
94
|
-
});
|
|
95
|
-
}
|
|
96
|
-
function stop() {
|
|
97
|
-
stopped = true;
|
|
98
|
-
activeReadline?.close();
|
|
99
|
-
activeReadline = void 0;
|
|
100
|
-
}
|
|
101
|
-
return { tools, handle, serve, stop };
|
|
102
|
-
}
|
|
103
|
-
function rpcResult(id, result) {
|
|
104
|
-
return { jsonrpc: "2.0", id, result };
|
|
105
|
-
}
|
|
106
|
-
function rpcError(id, code, message, data) {
|
|
107
|
-
return {
|
|
108
|
-
jsonrpc: "2.0",
|
|
109
|
-
id,
|
|
110
|
-
error: data === void 0 ? { code, message } : { code, message, data }
|
|
111
|
-
};
|
|
112
|
-
}
|
|
113
|
-
function writeResponse(output, response) {
|
|
114
|
-
output.write(`${JSON.stringify(response)}
|
|
115
|
-
`);
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
// src/mcp/memory-server.ts
|
|
119
|
-
import { appendFileSync, mkdirSync, readFileSync } from "fs";
|
|
120
|
-
import { dirname } from "path";
|
|
121
|
-
var MEMORY_FILE_ENV = "AGENT_MEMORY_FILE";
|
|
122
|
-
var MEMORY_ITEMS_ENV = "AGENT_MEMORY_ITEMS";
|
|
123
|
-
var MEMORY_LOG_ENV = "AGENT_MEMORY_LOG";
|
|
124
|
-
var MEMORY_NAME_ENV = "AGENT_MEMORY_NAME";
|
|
125
|
-
function createMemoryToolServer(opts) {
|
|
126
|
-
if (opts.items.length === 0) {
|
|
127
|
-
throw new ValidationError(
|
|
128
|
-
"createMemoryToolServer: refusing to serve an EMPTY memory \u2014 a profile without memory omits the artifact; serving zero rows would fake the with/without ablation"
|
|
129
|
-
);
|
|
130
|
-
}
|
|
131
|
-
const byId = /* @__PURE__ */ new Map();
|
|
132
|
-
for (const item of opts.items) {
|
|
133
|
-
if (byId.has(item.id)) {
|
|
134
|
-
throw new ValidationError(`createMemoryToolServer: duplicate memory item id '${item.id}'`);
|
|
135
|
-
}
|
|
136
|
-
byId.set(item.id, item);
|
|
137
|
-
}
|
|
138
|
-
const items = [...byId.values()];
|
|
139
|
-
const defaultK = opts.defaultK ?? 5;
|
|
140
|
-
const logPath = opts.logPath;
|
|
141
|
-
if (logPath) mkdirSync(dirname(logPath), { recursive: true });
|
|
142
|
-
const search = {
|
|
143
|
-
name: "memory_search",
|
|
144
|
-
description: "Search the agent memory of lessons learned from prior runs. Give what you are about to do or the problem you face; returns the top-k lessons ranked by relevance. Consult it BEFORE repeating work a prior run already learned from.",
|
|
145
|
-
inputSchema: {
|
|
146
|
-
type: "object",
|
|
147
|
-
properties: {
|
|
148
|
-
query: {
|
|
149
|
-
type: "string",
|
|
150
|
-
description: "The task/problem at hand \u2014 matched against lesson text and tags."
|
|
151
|
-
},
|
|
152
|
-
k: { type: "number", description: `Max results (default ${defaultK}).` },
|
|
153
|
-
tags: {
|
|
154
|
-
type: "array",
|
|
155
|
-
items: { type: "string" },
|
|
156
|
-
description: "Only return items carrying at least one of these tags."
|
|
157
|
-
}
|
|
158
|
-
},
|
|
159
|
-
required: ["query"]
|
|
160
|
-
},
|
|
161
|
-
handler: async (raw) => {
|
|
162
|
-
const args = raw ?? {};
|
|
163
|
-
if (typeof args.query !== "string" || args.query.trim().length === 0) {
|
|
164
|
-
throw new TypeError("memory_search: query must be a non-empty string");
|
|
165
|
-
}
|
|
166
|
-
const k = args.k === void 0 ? defaultK : Math.floor(Number(args.k));
|
|
167
|
-
if (!Number.isFinite(k) || k < 1) {
|
|
168
|
-
throw new TypeError("memory_search: k must be a positive integer");
|
|
169
|
-
}
|
|
170
|
-
let tagFilter;
|
|
171
|
-
if (args.tags !== void 0) {
|
|
172
|
-
if (!Array.isArray(args.tags) || args.tags.some((t) => typeof t !== "string")) {
|
|
173
|
-
throw new TypeError("memory_search: tags must be an array of strings");
|
|
174
|
-
}
|
|
175
|
-
tagFilter = args.tags;
|
|
176
|
-
}
|
|
177
|
-
const queryTokens = tokenize(args.query);
|
|
178
|
-
const pool = tagFilter ? items.filter((i) => (i.tags ?? []).some((t) => tagFilter.includes(t))) : items;
|
|
179
|
-
const results = pool.map((item) => ({ item, score: scoreItem(queryTokens, item) })).filter((r) => r.score > 0).sort((a, b) => b.score - a.score).slice(0, k).map(({ item, score }) => ({
|
|
180
|
-
id: item.id,
|
|
181
|
-
text: item.text,
|
|
182
|
-
score: Number(score.toFixed(4)),
|
|
183
|
-
...item.tags ? { tags: item.tags } : {},
|
|
184
|
-
...item.source ? { source: item.source } : {}
|
|
185
|
-
}));
|
|
186
|
-
if (logPath) {
|
|
187
|
-
appendFileSync(
|
|
188
|
-
logPath,
|
|
189
|
-
`${JSON.stringify({
|
|
190
|
-
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
191
|
-
query: args.query,
|
|
192
|
-
k,
|
|
193
|
-
returned: results.map((r) => ({ id: r.id, score: r.score }))
|
|
194
|
-
})}
|
|
195
|
-
`
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
return { query: args.query, results };
|
|
199
|
-
}
|
|
200
|
-
};
|
|
201
|
-
const get = {
|
|
202
|
-
name: "memory_get",
|
|
203
|
-
description: "Fetch one memory item verbatim by its id (ids come from memory_search results).",
|
|
204
|
-
inputSchema: {
|
|
205
|
-
type: "object",
|
|
206
|
-
properties: { id: { type: "string", description: "The memory item id." } },
|
|
207
|
-
required: ["id"]
|
|
208
|
-
},
|
|
209
|
-
handler: async (raw) => {
|
|
210
|
-
const args = raw ?? {};
|
|
211
|
-
if (typeof args.id !== "string" || args.id.trim().length === 0) {
|
|
212
|
-
throw new TypeError("memory_get: id must be a non-empty string");
|
|
213
|
-
}
|
|
214
|
-
const item = byId.get(args.id);
|
|
215
|
-
if (!item) throw new Error(`memory_get: no memory item with id '${args.id}'`);
|
|
216
|
-
return item;
|
|
217
|
-
}
|
|
218
|
-
};
|
|
219
|
-
return createStdioToolServer({
|
|
220
|
-
serverName: opts.serverName ?? "agent-memory",
|
|
221
|
-
serverVersion: opts.serverVersion ?? "0",
|
|
222
|
-
tools: [search, get]
|
|
223
|
-
});
|
|
224
|
-
}
|
|
225
|
-
function parseMemoryItems(value, source) {
|
|
226
|
-
if (!Array.isArray(value)) {
|
|
227
|
-
throw new ValidationError(`${source}: expected a JSON array of memory items`);
|
|
228
|
-
}
|
|
229
|
-
return value.map((row, i) => coerceMemoryItem(row, `${source}[${i}]`));
|
|
230
|
-
}
|
|
231
|
-
function readMemoryItemsFile(path) {
|
|
232
|
-
let raw;
|
|
233
|
-
try {
|
|
234
|
-
raw = readFileSync(path, "utf8");
|
|
235
|
-
} catch (err) {
|
|
236
|
-
throw new ValidationError(
|
|
237
|
-
`readMemoryItemsFile: cannot read '${path}': ${err instanceof Error ? err.message : String(err)}`
|
|
238
|
-
);
|
|
239
|
-
}
|
|
240
|
-
const trimmed = raw.trim();
|
|
241
|
-
if (trimmed.length === 0) return [];
|
|
242
|
-
if (trimmed.startsWith("[")) {
|
|
243
|
-
let parsed;
|
|
244
|
-
try {
|
|
245
|
-
parsed = JSON.parse(trimmed);
|
|
246
|
-
} catch (err) {
|
|
247
|
-
throw new ValidationError(
|
|
248
|
-
`readMemoryItemsFile: '${path}' is not valid JSON: ${err.message}`
|
|
249
|
-
);
|
|
250
|
-
}
|
|
251
|
-
return parseMemoryItems(parsed, path);
|
|
252
|
-
}
|
|
253
|
-
return trimmed.split("\n").map((line) => line.trim()).filter((line) => line.length > 0).map((line, i) => {
|
|
254
|
-
let parsed;
|
|
255
|
-
try {
|
|
256
|
-
parsed = JSON.parse(line);
|
|
257
|
-
} catch (err) {
|
|
258
|
-
throw new ValidationError(
|
|
259
|
-
`readMemoryItemsFile: '${path}' line ${i + 1} is not valid JSON: ${err.message}`
|
|
260
|
-
);
|
|
261
|
-
}
|
|
262
|
-
return coerceMemoryItem(parsed, `${path}:${i + 1}`);
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
function resolveMemoryFromEnv(env) {
|
|
266
|
-
const filePath = env[MEMORY_FILE_ENV];
|
|
267
|
-
const inlineRaw = env[MEMORY_ITEMS_ENV];
|
|
268
|
-
const fromFile = filePath ? readMemoryItemsFile(filePath) : [];
|
|
269
|
-
let inline = [];
|
|
270
|
-
if (inlineRaw) {
|
|
271
|
-
let parsed;
|
|
272
|
-
try {
|
|
273
|
-
parsed = JSON.parse(inlineRaw);
|
|
274
|
-
} catch (err) {
|
|
275
|
-
throw new ValidationError(
|
|
276
|
-
`${MEMORY_ITEMS_ENV} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`
|
|
277
|
-
);
|
|
278
|
-
}
|
|
279
|
-
inline = parseMemoryItems(parsed, MEMORY_ITEMS_ENV);
|
|
280
|
-
}
|
|
281
|
-
const byId = /* @__PURE__ */ new Map();
|
|
282
|
-
for (const item of fromFile) byId.set(item.id, item);
|
|
283
|
-
for (const item of inline) byId.set(item.id, item);
|
|
284
|
-
if (byId.size === 0) {
|
|
285
|
-
throw new ValidationError(
|
|
286
|
-
`memory bin: no memory items \u2014 set ${MEMORY_FILE_ENV} and/or ${MEMORY_ITEMS_ENV}; an EMPTY memory must never be served (a profile without memory omits the artifact)`
|
|
287
|
-
);
|
|
288
|
-
}
|
|
289
|
-
const serverName = env[MEMORY_NAME_ENV];
|
|
290
|
-
const logPath = env[MEMORY_LOG_ENV];
|
|
291
|
-
return {
|
|
292
|
-
items: [...byId.values()],
|
|
293
|
-
...serverName ? { serverName } : {},
|
|
294
|
-
...logPath ? { logPath } : {}
|
|
295
|
-
};
|
|
296
|
-
}
|
|
297
|
-
function coerceMemoryItem(row, at) {
|
|
298
|
-
if (!row || typeof row !== "object" || Array.isArray(row)) {
|
|
299
|
-
throw new ValidationError(`${at}: memory item must be an object`);
|
|
300
|
-
}
|
|
301
|
-
const r = row;
|
|
302
|
-
if (typeof r.id !== "string" || r.id.trim().length === 0) {
|
|
303
|
-
throw new ValidationError(`${at}: 'id' must be a non-empty string`);
|
|
304
|
-
}
|
|
305
|
-
if (typeof r.text !== "string" || r.text.trim().length === 0) {
|
|
306
|
-
throw new ValidationError(`${at}: 'text' must be a non-empty string`);
|
|
307
|
-
}
|
|
308
|
-
let tags;
|
|
309
|
-
if (r.tags !== void 0) {
|
|
310
|
-
if (!Array.isArray(r.tags) || r.tags.some((t) => typeof t !== "string")) {
|
|
311
|
-
throw new ValidationError(`${at}: 'tags' must be an array of strings`);
|
|
312
|
-
}
|
|
313
|
-
tags = r.tags;
|
|
314
|
-
}
|
|
315
|
-
if (r.source !== void 0 && typeof r.source !== "string") {
|
|
316
|
-
throw new ValidationError(`${at}: 'source' must be a string`);
|
|
317
|
-
}
|
|
318
|
-
return {
|
|
319
|
-
id: r.id,
|
|
320
|
-
text: r.text,
|
|
321
|
-
...tags ? { tags } : {},
|
|
322
|
-
...typeof r.source === "string" ? { source: r.source } : {}
|
|
323
|
-
};
|
|
324
|
-
}
|
|
325
|
-
function tokenize(text) {
|
|
326
|
-
return [
|
|
327
|
-
...new Set(
|
|
328
|
-
text.toLowerCase().split(/[^a-z0-9]+/).filter((t) => t.length >= 2)
|
|
329
|
-
)
|
|
330
|
-
];
|
|
331
|
-
}
|
|
332
|
-
function scoreItem(queryTokens, item) {
|
|
333
|
-
if (queryTokens.length === 0) return 0;
|
|
334
|
-
const hay = new Set(tokenize(`${item.text} ${(item.tags ?? []).join(" ")}`));
|
|
335
|
-
let hit = 0;
|
|
336
|
-
for (const t of queryTokens) if (hay.has(t)) hit += 1;
|
|
337
|
-
return hit / queryTokens.length;
|
|
338
|
-
}
|
|
339
|
-
|
|
340
|
-
export {
|
|
341
|
-
createStdioToolServer,
|
|
342
|
-
MEMORY_FILE_ENV,
|
|
343
|
-
MEMORY_ITEMS_ENV,
|
|
344
|
-
MEMORY_LOG_ENV,
|
|
345
|
-
MEMORY_NAME_ENV,
|
|
346
|
-
createMemoryToolServer,
|
|
347
|
-
parseMemoryItems,
|
|
348
|
-
readMemoryItemsFile,
|
|
349
|
-
resolveMemoryFromEnv
|
|
350
|
-
};
|
|
351
|
-
//# sourceMappingURL=chunk-SMQXZGLZ.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/mcp/tool-server.ts","../src/mcp/memory-server.ts"],"sourcesContent":["/**\n * `createStdioToolServer` — the generic newline-delimited JSON-RPC 2.0 MCP\n * server core: `initialize` / `notifications/initialized` / `tools/list` /\n * `tools/call` over a stdio-shaped transport, protocol 2024-11-05.\n *\n * Extracted from `createMcpServer` (server.ts) so every in-repo MCP server —\n * the delegation server, the memory server — serves the ONE wire protocol the\n * same-host client (`connectStdioMcp`, runtime/stdio-mcp-client.ts) speaks.\n * A second hand-rolled serve loop could drift from what the client expects;\n * this core makes that impossible by construction.\n *\n * @experimental\n */\n\nimport { createInterface, type Interface as ReadlineInterface } from 'node:readline'\nimport { ValidationError } from '../errors'\n\nconst PROTOCOL_VERSION = '2024-11-05'\n\n/** @experimental */\nexport interface McpToolDescriptor {\n name: string\n description: string\n inputSchema: Record<string, unknown>\n handler: (raw: unknown) => Promise<unknown>\n}\n\n/** @experimental */\nexport interface McpTransport {\n input: NodeJS.ReadableStream\n output: NodeJS.WritableStream\n}\n\n/** @experimental */\nexport interface JsonRpcMessage {\n jsonrpc: '2.0'\n id?: number | string | null\n method: string\n params?: unknown\n}\n\n/** @experimental */\nexport interface JsonRpcResponse {\n jsonrpc: '2.0'\n id: number | string | null\n result?: unknown\n error?: { code: number; message: string; data?: unknown }\n}\n\n/** @experimental */\nexport interface StdioToolServerOptions {\n /** Server display name surfaced via `initialize`. */\n serverName: string\n /** Server version surfaced via `initialize`. */\n serverVersion: string\n /** The tools to serve. Duplicate names throw — a silent shadow would hide a tool. */\n tools: readonly McpToolDescriptor[]\n}\n\n/** @experimental */\nexport interface StdioToolServer {\n /** Tools currently registered, keyed by name. */\n readonly tools: ReadonlyMap<string, McpToolDescriptor>\n /** Handle a single parsed JSON-RPC message. Returns the response object (or `null` for notifications). */\n handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null>\n /** Drive the server on a stdio-shaped transport until `stop()` is called. */\n serve(transport?: McpTransport): Promise<void>\n /** Stop a `serve` call. Subsequent requests are rejected. */\n stop(): void\n}\n\n/** Build the generic stdio JSON-RPC tool server. */\nexport function createStdioToolServer(options: StdioToolServerOptions): StdioToolServer {\n const tools = new Map<string, McpToolDescriptor>()\n for (const tool of options.tools) {\n if (tools.has(tool.name)) {\n throw new ValidationError(`createStdioToolServer: duplicate tool name \"${tool.name}\"`)\n }\n tools.set(tool.name, tool)\n }\n\n let stopped = false\n let activeReadline: ReadlineInterface | undefined\n\n async function handle(message: JsonRpcMessage): Promise<JsonRpcResponse | null> {\n if (stopped) {\n return rpcError(message.id ?? null, -32099, 'server stopped')\n }\n if (message.method === 'initialize') {\n return rpcResult(message.id ?? null, {\n protocolVersion: PROTOCOL_VERSION,\n capabilities: { tools: {} },\n serverInfo: { name: options.serverName, version: options.serverVersion },\n })\n }\n if (message.method === 'notifications/initialized') {\n // MCP clients send this after the handshake; it has no id and expects\n // no response.\n return null\n }\n if (message.method === 'tools/list') {\n return rpcResult(message.id ?? null, {\n tools: [...tools.values()].map((tool) => ({\n name: tool.name,\n description: tool.description,\n inputSchema: tool.inputSchema,\n })),\n })\n }\n if (message.method === 'tools/call') {\n const params = (message.params ?? {}) as { name?: unknown; arguments?: unknown }\n const name = typeof params.name === 'string' ? params.name : ''\n const tool = tools.get(name)\n if (!tool) {\n return rpcError(message.id ?? null, -32601, `unknown tool: ${name}`)\n }\n try {\n const output = await tool.handler(params.arguments ?? {})\n return rpcResult(message.id ?? null, {\n content: [{ type: 'text', text: JSON.stringify(output) }],\n structuredContent: output,\n isError: false,\n })\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err)\n const code = err instanceof TypeError || err instanceof RangeError ? -32602 : -32000\n return rpcError(message.id ?? null, code, reason)\n }\n }\n if (message.id === undefined || message.id === null) return null\n return rpcError(message.id, -32601, `unknown method: ${message.method}`)\n }\n\n async function serve(transport?: McpTransport): Promise<void> {\n const input = transport?.input ?? process.stdin\n const output = transport?.output ?? process.stdout\n const rl = createInterface({ input, crlfDelay: Number.POSITIVE_INFINITY })\n activeReadline = rl\n return new Promise<void>((resolve, reject) => {\n rl.on('line', (line) => {\n const trimmed = line.trim()\n if (!trimmed) return\n let parsed: JsonRpcMessage | undefined\n try {\n parsed = JSON.parse(trimmed) as JsonRpcMessage\n } catch (err) {\n writeResponse(output, rpcError(null, -32700, `parse error: ${(err as Error).message}`))\n return\n }\n if (!parsed || parsed.jsonrpc !== '2.0' || typeof parsed.method !== 'string') {\n writeResponse(output, rpcError(parsed?.id ?? null, -32600, 'invalid request'))\n return\n }\n void handle(parsed).then((response) => {\n if (response) writeResponse(output, response)\n })\n })\n rl.on('close', () => resolve())\n rl.on('error', (err) => reject(err))\n if (stopped) {\n rl.close()\n resolve()\n }\n })\n }\n\n function stop(): void {\n stopped = true\n activeReadline?.close()\n activeReadline = undefined\n }\n\n return { tools, handle, serve, stop }\n}\n\nfunction rpcResult(id: number | string | null, result: unknown): JsonRpcResponse {\n return { jsonrpc: '2.0', id, result }\n}\n\nfunction rpcError(\n id: number | string | null,\n code: number,\n message: string,\n data?: unknown,\n): JsonRpcResponse {\n return {\n jsonrpc: '2.0',\n id,\n error: data === undefined ? { code, message } : { code, message, data },\n }\n}\n\nfunction writeResponse(output: NodeJS.WritableStream, response: JsonRpcResponse): void {\n output.write(`${JSON.stringify(response)}\\n`)\n}\n","/**\n * Memory MCP server — the LIVE serving half of the `memory` profile surface\n * (Phase 5). A curated memory (lessons distilled from prior runs) is only\n * real if the DRIVEN agent can query it mid-task; this module serves a flat\n * store of `MemoryItem` rows as `memory_search` / `memory_get` tools over the\n * ONE in-repo stdio JSON-RPC core (`createStdioToolServer`), so the exact\n * wire protocol the same-host client (`connectStdioMcp` /\n * `materializeLocalMcp`, runtime/stdio-mcp-client.ts) speaks is guaranteed by\n * construction — serve and consume cannot drift.\n *\n * Retrieval is DETERMINISTIC lexical overlap (no vectors, no LLM): a lift\n * measured with this memory mounted is attributable to the lessons\n * themselves, never to retrieval-model noise. Every\n * `memory_search` can append one JSONL row to a retrieval log (`logPath`) —\n * the per-query record an off-policy retrieval estimator (agent-knowledge's\n * `RetrievalHoldout`) consumes. agent-knowledge is NOT a dependency of this\n * repo, so the log file is the flagged cross-package seam, not an import.\n *\n * Fail-loud discipline (mirrors `materializeLocalMcp`): an EMPTY memory is\n * never served — a profile without memory simply omits the artifact, and\n * silently serving zero rows would fake the with/without ablation.\n *\n * @experimental\n */\n\nimport { appendFileSync, mkdirSync, readFileSync } from 'node:fs'\nimport { dirname } from 'node:path'\nimport type { AgentProfileMcpServer } from '@tangle-network/agent-interface'\nimport { ValidationError } from '../errors'\nimport { createStdioToolServer, type McpToolDescriptor, type StdioToolServer } from './tool-server'\n\n/** One row of agent memory: a crisp lesson/fact with provenance. */\nexport interface MemoryItem {\n /** Stable id (content-hash by convention; see `memoryArtifactFromLessons`). */\n id: string\n /** The lesson itself — one imperative or observation the agent should recall. */\n text: string\n /** Optional retrieval tags, matched by `memory_search` alongside the text. */\n tags?: string[]\n /** Provenance: the finding / trace / curation pass this row came from. */\n source?: string\n}\n\n/**\n * The `memory` artifact payload — HOW a profile's memory is stored and served:\n *\n * - `store: 'file'` — served by the in-repo memory bin\n * (`agent-runtime-memory-mcp`, src/mcp/memory-bin.ts): rows load from\n * `path` (a JSON array or JSONL file of `MemoryItem`) and/or the inline\n * `items` seed (inline wins on id collision). At least one of\n * `path`/`items` is required.\n * - `store: 'mcp'` — an EXTERNAL, already-runnable MCP server that exposes\n * the memory tools itself; `server` is required and mounts verbatim.\n *\n * `logPath` makes the served memory append one JSONL row per `memory_search`\n * — the retrieval log a holdout estimator reads (see module doc).\n */\nexport interface AgentMemorySpec {\n store: 'file' | 'mcp'\n /** `store:'file'` — host path to the durable row store (JSON array or JSONL). */\n path?: string\n /** Inline seed rows, served alongside (and winning over) `path` rows. */\n items?: MemoryItem[]\n /** `store:'mcp'` — the external server that already serves memory tools. */\n server?: AgentProfileMcpServer\n /** JSONL retrieval log: one row per `memory_search` (ts, query, k, returned). */\n logPath?: string\n}\n\n/** Env var naming the durable row store file the memory bin loads (the\n * `memoryMcpServer` ↔ memory-bin contract). */\nexport const MEMORY_FILE_ENV = 'AGENT_MEMORY_FILE'\n/** Env var carrying inline JSON `MemoryItem` rows (win over file rows on id). */\nexport const MEMORY_ITEMS_ENV = 'AGENT_MEMORY_ITEMS'\n/** Env var naming the JSONL retrieval log (one row per `memory_search`). */\nexport const MEMORY_LOG_ENV = 'AGENT_MEMORY_LOG'\n/** Env var overriding the served display name (default 'agent-memory'). */\nexport const MEMORY_NAME_ENV = 'AGENT_MEMORY_NAME'\n\nexport interface CreateMemoryToolServerOptions {\n /** The rows to serve. MUST be non-empty (an empty memory is never served). */\n items: readonly MemoryItem[]\n /** Server display name surfaced via `initialize`. Default 'agent-memory'. */\n serverName?: string\n /** Server version surfaced via `initialize`. Default '0'. */\n serverVersion?: string\n /** Default result count for `memory_search`. Default 5. */\n defaultK?: number\n /** Append one JSONL row per `memory_search` (the retrieval-holdout seam). */\n logPath?: string\n}\n\n/**\n * Build the memory MCP server: `memory_search` (lexical top-k over the rows)\n * and `memory_get` (one row by id) on the generic stdio JSON-RPC core.\n */\nexport function createMemoryToolServer(opts: CreateMemoryToolServerOptions): StdioToolServer {\n if (opts.items.length === 0) {\n throw new ValidationError(\n 'createMemoryToolServer: refusing to serve an EMPTY memory — a profile without memory omits the artifact; serving zero rows would fake the with/without ablation',\n )\n }\n const byId = new Map<string, MemoryItem>()\n for (const item of opts.items) {\n if (byId.has(item.id)) {\n throw new ValidationError(`createMemoryToolServer: duplicate memory item id '${item.id}'`)\n }\n byId.set(item.id, item)\n }\n const items = [...byId.values()]\n const defaultK = opts.defaultK ?? 5\n const logPath = opts.logPath\n if (logPath) mkdirSync(dirname(logPath), { recursive: true })\n\n const search: McpToolDescriptor = {\n name: 'memory_search',\n description:\n 'Search the agent memory of lessons learned from prior runs. Give what you are about to do or the problem you face; returns the top-k lessons ranked by relevance. Consult it BEFORE repeating work a prior run already learned from.',\n inputSchema: {\n type: 'object',\n properties: {\n query: {\n type: 'string',\n description: 'The task/problem at hand — matched against lesson text and tags.',\n },\n k: { type: 'number', description: `Max results (default ${defaultK}).` },\n tags: {\n type: 'array',\n items: { type: 'string' },\n description: 'Only return items carrying at least one of these tags.',\n },\n },\n required: ['query'],\n },\n handler: async (raw) => {\n const args = (raw ?? {}) as { query?: unknown; k?: unknown; tags?: unknown }\n if (typeof args.query !== 'string' || args.query.trim().length === 0) {\n throw new TypeError('memory_search: query must be a non-empty string')\n }\n const k = args.k === undefined ? defaultK : Math.floor(Number(args.k))\n if (!Number.isFinite(k) || k < 1) {\n throw new TypeError('memory_search: k must be a positive integer')\n }\n let tagFilter: string[] | undefined\n if (args.tags !== undefined) {\n if (!Array.isArray(args.tags) || args.tags.some((t) => typeof t !== 'string')) {\n throw new TypeError('memory_search: tags must be an array of strings')\n }\n tagFilter = args.tags as string[]\n }\n const queryTokens = tokenize(args.query)\n const pool = tagFilter\n ? items.filter((i) => (i.tags ?? []).some((t) => tagFilter.includes(t)))\n : items\n const results = pool\n .map((item) => ({ item, score: scoreItem(queryTokens, item) }))\n .filter((r) => r.score > 0)\n // Highest score first; stable on ties (curation order is the tiebreak).\n .sort((a, b) => b.score - a.score)\n .slice(0, k)\n .map(({ item, score }) => ({\n id: item.id,\n text: item.text,\n score: Number(score.toFixed(4)),\n ...(item.tags ? { tags: item.tags } : {}),\n ...(item.source ? { source: item.source } : {}),\n }))\n if (logPath) {\n // The retrieval log: what was asked, what came back, at what rank —\n // exactly the per-query record an off-policy estimator needs.\n appendFileSync(\n logPath,\n `${JSON.stringify({\n ts: new Date().toISOString(),\n query: args.query,\n k,\n returned: results.map((r) => ({ id: r.id, score: r.score })),\n })}\\n`,\n )\n }\n return { query: args.query, results }\n },\n }\n\n const get: McpToolDescriptor = {\n name: 'memory_get',\n description: 'Fetch one memory item verbatim by its id (ids come from memory_search results).',\n inputSchema: {\n type: 'object',\n properties: { id: { type: 'string', description: 'The memory item id.' } },\n required: ['id'],\n },\n handler: async (raw) => {\n const args = (raw ?? {}) as { id?: unknown }\n if (typeof args.id !== 'string' || args.id.trim().length === 0) {\n throw new TypeError('memory_get: id must be a non-empty string')\n }\n const item = byId.get(args.id)\n if (!item) throw new Error(`memory_get: no memory item with id '${args.id}'`)\n return item\n },\n }\n\n return createStdioToolServer({\n serverName: opts.serverName ?? 'agent-memory',\n serverVersion: opts.serverVersion ?? '0',\n tools: [search, get],\n })\n}\n\n/** Coerce an untrusted JSON array into validated `MemoryItem` rows. */\nexport function parseMemoryItems(value: unknown, source: string): MemoryItem[] {\n if (!Array.isArray(value)) {\n throw new ValidationError(`${source}: expected a JSON array of memory items`)\n }\n return value.map((row, i) => coerceMemoryItem(row, `${source}[${i}]`))\n}\n\n/** Read a memory store file: a JSON array, or JSONL (one `MemoryItem` per line). */\nexport function readMemoryItemsFile(path: string): MemoryItem[] {\n let raw: string\n try {\n raw = readFileSync(path, 'utf8')\n } catch (err) {\n throw new ValidationError(\n `readMemoryItemsFile: cannot read '${path}': ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n const trimmed = raw.trim()\n if (trimmed.length === 0) return []\n if (trimmed.startsWith('[')) {\n let parsed: unknown\n try {\n parsed = JSON.parse(trimmed)\n } catch (err) {\n throw new ValidationError(\n `readMemoryItemsFile: '${path}' is not valid JSON: ${(err as Error).message}`,\n )\n }\n return parseMemoryItems(parsed, path)\n }\n return trimmed\n .split('\\n')\n .map((line) => line.trim())\n .filter((line) => line.length > 0)\n .map((line, i) => {\n let parsed: unknown\n try {\n parsed = JSON.parse(line)\n } catch (err) {\n throw new ValidationError(\n `readMemoryItemsFile: '${path}' line ${i + 1} is not valid JSON: ${(err as Error).message}`,\n )\n }\n return coerceMemoryItem(parsed, `${path}:${i + 1}`)\n })\n}\n\n/** What the memory bin resolved from its environment. */\nexport interface ResolvedMemoryEnv {\n items: MemoryItem[]\n serverName?: string\n logPath?: string\n}\n\n/**\n * Resolve the bin's memory from `AGENT_MEMORY_FILE` (durable store) and/or\n * `AGENT_MEMORY_ITEMS` (inline JSON rows; wins on id collision). Zero rows is\n * a boot FAILURE, matching the fail-closed materialization discipline.\n */\nexport function resolveMemoryFromEnv(env: Record<string, string | undefined>): ResolvedMemoryEnv {\n const filePath = env[MEMORY_FILE_ENV]\n const inlineRaw = env[MEMORY_ITEMS_ENV]\n const fromFile = filePath ? readMemoryItemsFile(filePath) : []\n let inline: MemoryItem[] = []\n if (inlineRaw) {\n let parsed: unknown\n try {\n parsed = JSON.parse(inlineRaw)\n } catch (err) {\n throw new ValidationError(\n `${MEMORY_ITEMS_ENV} is not valid JSON: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n inline = parseMemoryItems(parsed, MEMORY_ITEMS_ENV)\n }\n const byId = new Map<string, MemoryItem>()\n for (const item of fromFile) byId.set(item.id, item)\n for (const item of inline) byId.set(item.id, item)\n if (byId.size === 0) {\n throw new ValidationError(\n `memory bin: no memory items — set ${MEMORY_FILE_ENV} and/or ${MEMORY_ITEMS_ENV}; an EMPTY memory must never be served (a profile without memory omits the artifact)`,\n )\n }\n const serverName = env[MEMORY_NAME_ENV]\n const logPath = env[MEMORY_LOG_ENV]\n return {\n items: [...byId.values()],\n ...(serverName ? { serverName } : {}),\n ...(logPath ? { logPath } : {}),\n }\n}\n\nfunction coerceMemoryItem(row: unknown, at: string): MemoryItem {\n if (!row || typeof row !== 'object' || Array.isArray(row)) {\n throw new ValidationError(`${at}: memory item must be an object`)\n }\n const r = row as Record<string, unknown>\n if (typeof r.id !== 'string' || r.id.trim().length === 0) {\n throw new ValidationError(`${at}: 'id' must be a non-empty string`)\n }\n if (typeof r.text !== 'string' || r.text.trim().length === 0) {\n throw new ValidationError(`${at}: 'text' must be a non-empty string`)\n }\n let tags: string[] | undefined\n if (r.tags !== undefined) {\n if (!Array.isArray(r.tags) || r.tags.some((t) => typeof t !== 'string')) {\n throw new ValidationError(`${at}: 'tags' must be an array of strings`)\n }\n tags = r.tags as string[]\n }\n if (r.source !== undefined && typeof r.source !== 'string') {\n throw new ValidationError(`${at}: 'source' must be a string`)\n }\n return {\n id: r.id,\n text: r.text,\n ...(tags ? { tags } : {}),\n ...(typeof r.source === 'string' ? { source: r.source } : {}),\n }\n}\n\n/** Unique lowercase alphanumeric tokens of length >= 2. */\nfunction tokenize(text: string): string[] {\n return [\n ...new Set(\n text\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length >= 2),\n ),\n ]\n}\n\n/** Fraction of query tokens present in the item's text + tags (0..1). */\nfunction scoreItem(queryTokens: readonly string[], item: MemoryItem): number {\n if (queryTokens.length === 0) return 0\n const hay = new Set(tokenize(`${item.text} ${(item.tags ?? []).join(' ')}`))\n let hit = 0\n for (const t of queryTokens) if (hay.has(t)) hit += 1\n return hit / queryTokens.length\n}\n"],"mappings":"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","names":[]}
|