@namzu/sdk 39.0.0 → 41.0.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 +328 -0
- package/dist/bridge/a2a/mapper.d.ts.map +1 -1
- package/dist/bridge/a2a/mapper.js +8 -0
- package/dist/bridge/a2a/mapper.js.map +1 -1
- package/dist/bridge/sse/mapper.d.ts.map +1 -1
- package/dist/bridge/sse/mapper.js +11 -0
- package/dist/bridge/sse/mapper.js.map +1 -1
- package/dist/connector/index.d.ts +2 -2
- package/dist/connector/index.d.ts.map +1 -1
- package/dist/connector/index.js +1 -1
- package/dist/connector/index.js.map +1 -1
- package/dist/connector/mcp/adapter.d.ts.map +1 -1
- package/dist/connector/mcp/adapter.js +112 -10
- package/dist/connector/mcp/adapter.js.map +1 -1
- package/dist/connector/mcp/audio-admission.d.ts +17 -0
- package/dist/connector/mcp/audio-admission.d.ts.map +1 -0
- package/dist/connector/mcp/audio-admission.js +171 -0
- package/dist/connector/mcp/audio-admission.js.map +1 -0
- package/dist/connector/mcp/client.d.ts +252 -1
- package/dist/connector/mcp/client.d.ts.map +1 -1
- package/dist/connector/mcp/client.js +611 -39
- package/dist/connector/mcp/client.js.map +1 -1
- package/dist/connector/mcp/envelope.d.ts +91 -0
- package/dist/connector/mcp/envelope.d.ts.map +1 -0
- package/dist/connector/mcp/envelope.js +173 -0
- package/dist/connector/mcp/envelope.js.map +1 -0
- package/dist/connector/mcp/era.d.ts +130 -0
- package/dist/connector/mcp/era.d.ts.map +1 -0
- package/dist/connector/mcp/era.js +304 -0
- package/dist/connector/mcp/era.js.map +1 -0
- package/dist/connector/mcp/errors.d.ts +106 -0
- package/dist/connector/mcp/errors.d.ts.map +1 -0
- package/dist/connector/mcp/errors.js +154 -0
- package/dist/connector/mcp/errors.js.map +1 -0
- package/dist/connector/mcp/http-sse.d.ts +11 -0
- package/dist/connector/mcp/http-sse.d.ts.map +1 -1
- package/dist/connector/mcp/http-sse.js +21 -6
- package/dist/connector/mcp/http-sse.js.map +1 -1
- package/dist/connector/mcp/index.d.ts +7 -0
- package/dist/connector/mcp/index.d.ts.map +1 -1
- package/dist/connector/mcp/index.js +10 -0
- package/dist/connector/mcp/index.js.map +1 -1
- package/dist/connector/mcp/streamable-http.d.ts +83 -0
- package/dist/connector/mcp/streamable-http.d.ts.map +1 -1
- package/dist/connector/mcp/streamable-http.js +177 -11
- package/dist/connector/mcp/streamable-http.js.map +1 -1
- package/dist/connector/mcp/x-mcp-header.d.ts +56 -0
- package/dist/connector/mcp/x-mcp-header.d.ts.map +1 -0
- package/dist/connector/mcp/x-mcp-header.js +254 -0
- package/dist/connector/mcp/x-mcp-header.js.map +1 -0
- package/dist/constants/mcp/index.d.ts +123 -15
- package/dist/constants/mcp/index.d.ts.map +1 -1
- package/dist/constants/mcp/index.js +135 -16
- package/dist/constants/mcp/index.js.map +1 -1
- package/dist/manager/agent/lifecycle.d.ts.map +1 -1
- package/dist/manager/agent/lifecycle.js +23 -0
- package/dist/manager/agent/lifecycle.js.map +1 -1
- package/dist/manager/run/persistence.d.ts +8 -0
- package/dist/manager/run/persistence.d.ts.map +1 -1
- package/dist/manager/run/persistence.js +12 -0
- package/dist/manager/run/persistence.js.map +1 -1
- package/dist/prompt/coding-agent-doctrine.d.ts +20 -0
- package/dist/prompt/coding-agent-doctrine.d.ts.map +1 -1
- package/dist/prompt/coding-agent-doctrine.js +19 -3
- package/dist/prompt/coding-agent-doctrine.js.map +1 -1
- package/dist/prompt/index.d.ts +1 -1
- package/dist/prompt/index.d.ts.map +1 -1
- package/dist/prompt/index.js +1 -1
- package/dist/prompt/index.js.map +1 -1
- package/dist/public-runtime.d.ts +6 -4
- package/dist/public-runtime.d.ts.map +1 -1
- package/dist/public-runtime.js +8 -4
- package/dist/public-runtime.js.map +1 -1
- package/dist/public-tools.d.ts +11 -0
- package/dist/public-tools.d.ts.map +1 -1
- package/dist/public-tools.js +14 -0
- package/dist/public-tools.js.map +1 -1
- package/dist/registry/tool/execute.d.ts.map +1 -1
- package/dist/registry/tool/execute.js +2 -3
- package/dist/registry/tool/execute.js.map +1 -1
- package/dist/registry/tool/portable.d.ts +65 -0
- package/dist/registry/tool/portable.d.ts.map +1 -0
- package/dist/registry/tool/portable.js +244 -0
- package/dist/registry/tool/portable.js.map +1 -0
- package/dist/registry/tool/schema.d.ts +32 -5
- package/dist/registry/tool/schema.d.ts.map +1 -1
- package/dist/registry/tool/schema.js +35 -9
- package/dist/registry/tool/schema.js.map +1 -1
- package/dist/registry/toolset/catalog.js +8 -8
- package/dist/registry/toolset/catalog.js.map +1 -1
- package/dist/runtime/jobs/awaited-jobs.d.ts +215 -0
- package/dist/runtime/jobs/awaited-jobs.d.ts.map +1 -0
- package/dist/runtime/jobs/awaited-jobs.js +259 -0
- package/dist/runtime/jobs/awaited-jobs.js.map +1 -0
- package/dist/runtime/jobs/registry.d.ts +33 -2
- package/dist/runtime/jobs/registry.d.ts.map +1 -1
- package/dist/runtime/jobs/registry.js +37 -0
- package/dist/runtime/jobs/registry.js.map +1 -1
- package/dist/runtime/query/executor.d.ts +28 -0
- package/dist/runtime/query/executor.d.ts.map +1 -1
- package/dist/runtime/query/executor.js +39 -1
- package/dist/runtime/query/executor.js.map +1 -1
- package/dist/runtime/query/file-evidence-context.d.ts.map +1 -1
- package/dist/runtime/query/file-evidence-context.js +159 -43
- package/dist/runtime/query/file-evidence-context.js.map +1 -1
- package/dist/runtime/query/file-evidence-replay.d.ts +260 -0
- package/dist/runtime/query/file-evidence-replay.d.ts.map +1 -0
- package/dist/runtime/query/file-evidence-replay.js +647 -0
- package/dist/runtime/query/file-evidence-replay.js.map +1 -0
- package/dist/runtime/query/file-evidence-seed.d.ts +50 -0
- package/dist/runtime/query/file-evidence-seed.d.ts.map +1 -0
- package/dist/runtime/query/file-evidence-seed.js +100 -0
- package/dist/runtime/query/file-evidence-seed.js.map +1 -0
- package/dist/runtime/query/index.d.ts.map +1 -1
- package/dist/runtime/query/index.js +94 -2
- package/dist/runtime/query/index.js.map +1 -1
- package/dist/runtime/query/iteration/index.d.ts +87 -9
- package/dist/runtime/query/iteration/index.d.ts.map +1 -1
- package/dist/runtime/query/iteration/index.js +193 -28
- package/dist/runtime/query/iteration/index.js.map +1 -1
- package/dist/runtime/query/iteration/phases/context.d.ts +10 -0
- package/dist/runtime/query/iteration/phases/context.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/context.js.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.d.ts.map +1 -1
- package/dist/runtime/query/iteration/phases/tool-review.js +5 -1
- package/dist/runtime/query/iteration/phases/tool-review.js.map +1 -1
- package/dist/runtime/query/plugin-hooks.d.ts +14 -0
- package/dist/runtime/query/plugin-hooks.d.ts.map +1 -1
- package/dist/runtime/query/plugin-hooks.js +18 -0
- package/dist/runtime/query/plugin-hooks.js.map +1 -1
- package/dist/runtime/query/repeat-call.d.ts +17 -4
- package/dist/runtime/query/repeat-call.d.ts.map +1 -1
- package/dist/runtime/query/repeat-call.js +26 -19
- package/dist/runtime/query/repeat-call.js.map +1 -1
- package/dist/runtime/query/steering.d.ts +11 -1
- package/dist/runtime/query/steering.d.ts.map +1 -1
- package/dist/runtime/query/steering.js +12 -1
- package/dist/runtime/query/steering.js.map +1 -1
- package/dist/runtime/query/tooling.d.ts +2 -0
- package/dist/runtime/query/tooling.d.ts.map +1 -1
- package/dist/runtime/query/tooling.js +1 -0
- package/dist/runtime/query/tooling.js.map +1 -1
- package/dist/sandbox/provider/local.d.ts.map +1 -1
- package/dist/sandbox/provider/local.js +46 -3
- package/dist/sandbox/provider/local.js.map +1 -1
- package/dist/scheduler/completion-inbox.d.ts +48 -2
- package/dist/scheduler/completion-inbox.d.ts.map +1 -1
- package/dist/scheduler/completion-inbox.js +102 -10
- package/dist/scheduler/completion-inbox.js.map +1 -1
- package/dist/scheduler/local.d.ts.map +1 -1
- package/dist/scheduler/local.js +8 -0
- package/dist/scheduler/local.js.map +1 -1
- package/dist/store/run/disk.d.ts +35 -1
- package/dist/store/run/disk.d.ts.map +1 -1
- package/dist/store/run/disk.js +100 -0
- package/dist/store/run/disk.js.map +1 -1
- package/dist/tools/builtins/bash.d.ts.map +1 -1
- package/dist/tools/builtins/bash.js +4 -10
- package/dist/tools/builtins/bash.js.map +1 -1
- package/dist/tools/builtins/edit-apply.d.ts +126 -0
- package/dist/tools/builtins/edit-apply.d.ts.map +1 -0
- package/dist/tools/builtins/edit-apply.js +360 -0
- package/dist/tools/builtins/edit-apply.js.map +1 -0
- package/dist/tools/builtins/edit.d.ts +143 -1
- package/dist/tools/builtins/edit.d.ts.map +1 -1
- package/dist/tools/builtins/edit.js +37 -219
- package/dist/tools/builtins/edit.js.map +1 -1
- package/dist/tools/builtins/index.d.ts +1 -0
- package/dist/tools/builtins/index.d.ts.map +1 -1
- package/dist/tools/builtins/index.js +9 -3
- package/dist/tools/builtins/index.js.map +1 -1
- package/dist/tools/builtins/job.js +1 -1
- package/dist/tools/builtins/job.js.map +1 -1
- package/dist/tools/builtins/read-file.d.ts +2 -2
- package/dist/tools/builtins/read-file.d.ts.map +1 -1
- package/dist/tools/builtins/read-file.js +50 -65
- package/dist/tools/builtins/read-file.js.map +1 -1
- package/dist/tools/builtins/read-render.d.ts +56 -0
- package/dist/tools/builtins/read-render.d.ts.map +1 -0
- package/dist/tools/builtins/read-render.js +73 -0
- package/dist/tools/builtins/read-render.js.map +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts +67 -0
- package/dist/tools/builtins/wait-for-job-bounds.d.ts.map +1 -0
- package/dist/tools/builtins/wait-for-job-bounds.js +108 -0
- package/dist/tools/builtins/wait-for-job-bounds.js.map +1 -0
- package/dist/tools/builtins/wait-for-job.d.ts +6 -0
- package/dist/tools/builtins/wait-for-job.d.ts.map +1 -0
- package/dist/tools/builtins/wait-for-job.js +162 -0
- package/dist/tools/builtins/wait-for-job.js.map +1 -0
- package/dist/tools/builtins/write-file.js +5 -0
- package/dist/tools/builtins/write-file.js.map +1 -1
- package/dist/tools/coordinator/index.d.ts.map +1 -1
- package/dist/tools/coordinator/index.js +1 -7
- package/dist/tools/coordinator/index.js.map +1 -1
- package/dist/tools/file-read-tracker.d.ts.map +1 -1
- package/dist/tools/file-read-tracker.js +88 -10
- package/dist/tools/file-read-tracker.js.map +1 -1
- package/dist/types/agent/scheduler.d.ts +20 -0
- package/dist/types/agent/scheduler.d.ts.map +1 -1
- package/dist/types/agent/task.d.ts +20 -0
- package/dist/types/agent/task.d.ts.map +1 -1
- package/dist/types/connector/mcp.d.ts +205 -0
- package/dist/types/connector/mcp.d.ts.map +1 -1
- package/dist/types/message/index.d.ts +1 -1
- package/dist/types/message/index.d.ts.map +1 -1
- package/dist/types/message/index.js +2 -0
- package/dist/types/message/index.js.map +1 -1
- package/dist/types/run/entity.d.ts +13 -0
- package/dist/types/run/entity.d.ts.map +1 -1
- package/dist/types/run/events.d.ts +56 -0
- package/dist/types/run/events.d.ts.map +1 -1
- package/dist/types/run/events.js.map +1 -1
- package/dist/types/run/store.d.ts +41 -0
- package/dist/types/run/store.d.ts.map +1 -1
- package/dist/types/sandbox/index.d.ts +83 -15
- package/dist/types/sandbox/index.d.ts.map +1 -1
- package/dist/types/sandbox/index.js.map +1 -1
- package/dist/types/tool/index.d.ts +109 -0
- package/dist/types/tool/index.d.ts.map +1 -1
- package/dist/types/tool/index.js.map +1 -1
- package/dist/utils/env.d.ts +19 -0
- package/dist/utils/env.d.ts.map +1 -0
- package/dist/utils/env.js +25 -0
- package/dist/utils/env.js.map +1 -0
- package/package.json +1 -1
- package/src/bridge/a2a/mapper.ts +8 -0
- package/src/bridge/sse/mapper.ts +11 -0
- package/src/connector/index.ts +27 -0
- package/src/connector/mcp/adapter.ts +123 -10
- package/src/connector/mcp/audio-admission.ts +173 -0
- package/src/connector/mcp/client.ts +694 -45
- package/src/connector/mcp/envelope.ts +235 -0
- package/src/connector/mcp/era.ts +400 -0
- package/src/connector/mcp/errors.ts +171 -0
- package/src/connector/mcp/http-sse.ts +23 -6
- package/src/connector/mcp/index.ts +37 -0
- package/src/connector/mcp/streamable-http.ts +199 -11
- package/src/connector/mcp/x-mcp-header.ts +322 -0
- package/src/constants/mcp/index.ts +145 -16
- package/src/manager/agent/lifecycle.ts +29 -0
- package/src/manager/run/persistence.ts +12 -0
- package/src/prompt/coding-agent-doctrine.ts +31 -4
- package/src/prompt/index.ts +1 -0
- package/src/public-runtime.ts +37 -1
- package/src/public-tools.ts +18 -0
- package/src/registry/tool/execute.ts +2 -4
- package/src/registry/tool/portable.ts +264 -0
- package/src/registry/tool/schema.ts +38 -8
- package/src/registry/toolset/catalog.ts +8 -9
- package/src/runtime/jobs/awaited-jobs.ts +271 -0
- package/src/runtime/jobs/registry.ts +50 -0
- package/src/runtime/query/executor.ts +49 -1
- package/src/runtime/query/file-evidence-context.ts +190 -46
- package/src/runtime/query/file-evidence-replay.ts +776 -0
- package/src/runtime/query/file-evidence-seed.ts +126 -0
- package/src/runtime/query/index.ts +104 -2
- package/src/runtime/query/iteration/index.ts +202 -28
- package/src/runtime/query/iteration/phases/context.ts +10 -0
- package/src/runtime/query/iteration/phases/tool-review.ts +4 -0
- package/src/runtime/query/plugin-hooks.ts +20 -0
- package/src/runtime/query/repeat-call.ts +28 -18
- package/src/runtime/query/steering.ts +11 -0
- package/src/runtime/query/tooling.ts +3 -0
- package/src/sandbox/provider/local.ts +45 -2
- package/src/scheduler/completion-inbox.ts +105 -9
- package/src/scheduler/local.ts +8 -0
- package/src/store/run/disk.ts +108 -0
- package/src/tools/builtins/bash.ts +4 -10
- package/src/tools/builtins/edit-apply.ts +456 -0
- package/src/tools/builtins/edit.ts +39 -270
- package/src/tools/builtins/index.ts +9 -3
- package/src/tools/builtins/job.ts +1 -1
- package/src/tools/builtins/read-file.ts +56 -77
- package/src/tools/builtins/read-render.ts +104 -0
- package/src/tools/builtins/wait-for-job-bounds.ts +179 -0
- package/src/tools/builtins/wait-for-job.ts +184 -0
- package/src/tools/builtins/write-file.ts +5 -0
- package/src/tools/coordinator/index.ts +1 -7
- package/src/tools/file-read-tracker.ts +85 -7
- package/src/types/agent/scheduler.ts +21 -0
- package/src/types/agent/task.ts +21 -0
- package/src/types/connector/mcp.ts +205 -1
- package/src/types/message/index.ts +2 -0
- package/src/types/run/entity.ts +14 -0
- package/src/types/run/events.ts +56 -0
- package/src/types/run/store.ts +42 -0
- package/src/types/sandbox/index.ts +84 -15
- package/src/types/tool/index.ts +104 -0
- package/src/utils/env.ts +23 -0
|
@@ -1,9 +1,42 @@
|
|
|
1
|
-
import { resolve } from 'node:path'
|
|
2
|
-
import { isClearedToolResult } from '../../compaction/tool-result-editing.js'
|
|
3
1
|
import { fingerprintContent } from '../../tools/builtins/content-fingerprint.js'
|
|
4
|
-
import {
|
|
5
|
-
import type { Message
|
|
2
|
+
import { ReadFileTool } from '../../tools/builtins/read-file.js'
|
|
3
|
+
import type { Message } from '../../types/message/index.js'
|
|
6
4
|
import type { FileReadTracker } from '../../types/tool/index.js'
|
|
5
|
+
import {
|
|
6
|
+
MAX_EDIT_CALLS,
|
|
7
|
+
MAX_PATH_UNITS,
|
|
8
|
+
MAX_WITNESSED_PATHS,
|
|
9
|
+
type ReplayBudget,
|
|
10
|
+
type VisibleHistory,
|
|
11
|
+
createReplayBudget,
|
|
12
|
+
indexVisibleHistory,
|
|
13
|
+
knownStale,
|
|
14
|
+
lexicalFileKeys,
|
|
15
|
+
replayHop,
|
|
16
|
+
spend,
|
|
17
|
+
visibleCall,
|
|
18
|
+
visibleEdit,
|
|
19
|
+
visibleWrite,
|
|
20
|
+
} from './file-evidence-replay.js'
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Receipt text a read entry may point at.
|
|
24
|
+
*
|
|
25
|
+
* The same class of bound as the one on a write call's arguments, and set to
|
|
26
|
+
* the same number for the same reason: past it the text is not read at all. A
|
|
27
|
+
* bigger file is simply not admitted this way — the model re-reads it, which is
|
|
28
|
+
* what it does today.
|
|
29
|
+
*/
|
|
30
|
+
const MAX_RECEIPT_UNITS = 32_000
|
|
31
|
+
|
|
32
|
+
interface FileEvidence {
|
|
33
|
+
readonly path: string
|
|
34
|
+
/** Absent on the write-rooted entries; `'read'` on a body that is a receipt. */
|
|
35
|
+
readonly kind?: 'read'
|
|
36
|
+
readonly bodyInCall: string
|
|
37
|
+
readonly editsInCalls?: readonly string[]
|
|
38
|
+
readonly observedFingerprint: string
|
|
39
|
+
}
|
|
7
40
|
|
|
8
41
|
/** Join visible call bodies, successful receipts and this executor's observation ledger. */
|
|
9
42
|
export function describeVisibleFileEvidence(
|
|
@@ -14,52 +47,163 @@ export function describeVisibleFileEvidence(
|
|
|
14
47
|
): string | undefined {
|
|
15
48
|
// Execution-owned witnesses survive transparent wrappers; a name alone proves nothing.
|
|
16
49
|
if (!tracker.writeCallId || !tracker.fingerprint) return
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
const files = new Map<string, { path: string; bodyInCall: string; observedFingerprint: string }>()
|
|
29
|
-
for (const [id, call] of calls) {
|
|
30
|
-
const receipt = results.get(id)
|
|
31
|
-
if (
|
|
32
|
-
!call ||
|
|
33
|
-
call.function.name !== 'write' ||
|
|
34
|
-
call.metadata?.inputTruncated ||
|
|
35
|
-
call.function.arguments.length > 32_000 ||
|
|
36
|
-
id.length > 256 ||
|
|
37
|
-
!receipt ||
|
|
38
|
-
receipt.role !== 'tool' ||
|
|
39
|
-
receipt.isError ||
|
|
40
|
-
typeof receipt.content !== 'string' ||
|
|
41
|
-
isClearedToolResult(receipt.content)
|
|
42
|
-
)
|
|
43
|
-
continue
|
|
50
|
+
// Lexical, as this projection has always looked entries up: a spelling that
|
|
51
|
+
// does not resolve to the tool's canonical key finds nothing and the path is
|
|
52
|
+
// simply not admitted. Writing the ledger is the side that has to key the
|
|
53
|
+
// way the tools do — see `file-evidence-seed.ts`.
|
|
54
|
+
const history = indexVisibleHistory(messages, lexicalFileKeys(workingDirectory, sandboxed))
|
|
55
|
+
const budget = createReplayBudget()
|
|
56
|
+
const files = new Map<string, FileEvidence>()
|
|
57
|
+
for (const [id, call] of history.calls) {
|
|
58
|
+
const name = call?.function.name
|
|
59
|
+
if (name !== 'write' && name !== 'edit' && name !== 'read') continue
|
|
44
60
|
try {
|
|
45
|
-
const
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
if (
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
61
|
+
const admitted =
|
|
62
|
+
name === 'write'
|
|
63
|
+
? writeEvidence(id, tracker, history)
|
|
64
|
+
: name === 'edit'
|
|
65
|
+
? chainEvidence(id, tracker, history, budget)
|
|
66
|
+
: readEvidence(id, tracker, history)
|
|
67
|
+
if (!admitted) continue
|
|
68
|
+
// A write-rooted entry outranks a read of the same file: it names a
|
|
69
|
+
// body the model composed itself, and edits can be replayed onto it.
|
|
70
|
+
// The ledger already withholds a read witness where one survives; this
|
|
71
|
+
// keeps a read that ran BEFORE the write from taking the path back.
|
|
72
|
+
const held = files.get(admitted.key)
|
|
73
|
+
if (admitted.evidence.kind === 'read' && held && held.kind !== 'read') continue
|
|
74
|
+
files.delete(admitted.key)
|
|
75
|
+
files.set(admitted.key, admitted.evidence)
|
|
76
|
+
if (files.size > MAX_WITNESSED_PATHS) files.delete(files.keys().next().value as string)
|
|
59
77
|
} catch {
|
|
60
78
|
// Malformed retained inputs or a custom tracker cannot establish evidence.
|
|
61
79
|
}
|
|
62
80
|
}
|
|
63
81
|
if (files.size === 0) return
|
|
64
|
-
return `Visible file evidence (this request only): each complete body
|
|
82
|
+
return `Visible file evidence (this request only): each entry's current body is the complete body in the named successful write call, with the edit calls in editsInCalls — when present — applied in that order. An entry marked kind:"read" instead names a successful read call whose own receipt shows the file WHOLE, rendered with every line behind its own N<tab> prefix; that receipt is the body, and such an entry never carries editsInCalls. This runtime performed that reconstruction and checked it against its own file observation; it is not a derivation left to you. Reuse the body for a targeted edit; a read solely to recall it is unnecessary. This is NOT a fresh disk check, and after a resume the observation behind an entry may itself have been rebuilt from this conversation's own earlier calls rather than made while this process ran. Built-in edit/write still compare the disk body at mutation admission and refuse observed drift; on refusal inspect the current file and replan. Missing entries establish nothing.\n${JSON.stringify([...files.values()])}`
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A full body that arrived whole in one call and is still the file's body. */
|
|
86
|
+
function writeEvidence(
|
|
87
|
+
id: string,
|
|
88
|
+
tracker: FileReadTracker,
|
|
89
|
+
history: VisibleHistory,
|
|
90
|
+
): { key: string; evidence: FileEvidence } | undefined {
|
|
91
|
+
const written = visibleWrite(history, id)
|
|
92
|
+
if (!written || knownStale(tracker, written.key)) return
|
|
93
|
+
const fingerprint = fingerprintContent(written.body)
|
|
94
|
+
if (
|
|
95
|
+
tracker.writeCallId?.(written.key) !== id ||
|
|
96
|
+
tracker.fingerprint?.(written.key) !== fingerprint
|
|
97
|
+
)
|
|
98
|
+
return
|
|
99
|
+
return {
|
|
100
|
+
key: written.key,
|
|
101
|
+
evidence: {
|
|
102
|
+
path: written.path,
|
|
103
|
+
bodyInCall: id,
|
|
104
|
+
observedFingerprint: fingerprint,
|
|
105
|
+
},
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
/**
|
|
110
|
+
* A full body plus the visible edits since, replayed and then checked.
|
|
111
|
+
*
|
|
112
|
+
* Only the chain's TIP establishes the path: a middle hop is validated as part
|
|
113
|
+
* of the walk below, and admitting one on its own would claim the file stops
|
|
114
|
+
* at an edit later calls have already moved past. The replay runs the same
|
|
115
|
+
* apply core the tool ran at mutation time, over call arguments that are
|
|
116
|
+
* already in the conversation — no filesystem read, and the result is compared
|
|
117
|
+
* to the ledger's disk-derived fingerprint, never written into it.
|
|
118
|
+
*/
|
|
119
|
+
function chainEvidence(
|
|
120
|
+
id: string,
|
|
121
|
+
tracker: FileReadTracker,
|
|
122
|
+
history: VisibleHistory,
|
|
123
|
+
budget: ReplayBudget,
|
|
124
|
+
): { key: string; evidence: FileEvidence } | undefined {
|
|
125
|
+
const tip = visibleEdit(history, id)
|
|
126
|
+
if (!tip || knownStale(tracker, tip.key)) return
|
|
127
|
+
const key = tip.key
|
|
128
|
+
const chain = tracker.editChain?.(key)
|
|
129
|
+
const observed = tracker.fingerprint?.(key)
|
|
130
|
+
if (!chain || observed === undefined || chain.editCallIds.at(-1) !== id) return
|
|
131
|
+
// The call bound before the walk, the unit bound before each operation it
|
|
132
|
+
// pays for. Neither is measured by doing the work it exists to refuse.
|
|
133
|
+
if (chain.editCallIds.length > MAX_EDIT_CALLS) return
|
|
134
|
+
const rootId = chain.rootWriteCallId
|
|
135
|
+
const root = visibleWrite(history, rootId)
|
|
136
|
+
// A root naming a different file is an ambiguity, not a base: the ledger
|
|
137
|
+
// and the visible call disagree about what was written where.
|
|
138
|
+
if (!root || root.key !== key) return
|
|
139
|
+
let content = root.body
|
|
140
|
+
if (!spend(budget, content.length)) return
|
|
141
|
+
for (const editId of chain.editCallIds) {
|
|
142
|
+
const hop = editId === id ? tip : visibleEdit(history, editId)
|
|
143
|
+
if (!hop || hop.key !== key) return
|
|
144
|
+
// Each of this hop's operations is measured against the body it is about
|
|
145
|
+
// to be applied to, charged, and only then applied — so a hop over the
|
|
146
|
+
// ceiling is refused before it is built rather than after, and one that
|
|
147
|
+
// fits is never turned away for a ceiling that guessed high. A hop the
|
|
148
|
+
// budget refuses, or one whose anchors no longer match, reconstructs
|
|
149
|
+
// nothing and withholds the whole path.
|
|
150
|
+
const replayed = replayHop(content, hop.input, budget)
|
|
151
|
+
if (replayed === undefined) return
|
|
152
|
+
content = replayed
|
|
153
|
+
}
|
|
154
|
+
if (fingerprintContent(content) !== observed) return
|
|
155
|
+
return {
|
|
156
|
+
key,
|
|
157
|
+
evidence: {
|
|
158
|
+
path: root.path,
|
|
159
|
+
bodyInCall: rootId,
|
|
160
|
+
editsInCalls: [...chain.editCallIds],
|
|
161
|
+
observedFingerprint: observed,
|
|
162
|
+
},
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* A body the model can still see because a read of the whole file put it there.
|
|
168
|
+
*
|
|
169
|
+
* Structurally unlike the two above, and deliberately so. They name a body the
|
|
170
|
+
* model itself composed, in arguments this projection can parse and replay; this
|
|
171
|
+
* names a RESULT, and the only thing anyone is allowed to do with it is compare
|
|
172
|
+
* it. The tool fingerprinted the exact string it emitted, and the entry is
|
|
173
|
+
* admitted only while the receipt still fingerprints to that — so a receipt the
|
|
174
|
+
* output budget elided or spilled, one compaction cleared, or one changed in any
|
|
175
|
+
* other way withholds the path rather than pointing the model at a body that is
|
|
176
|
+
* no longer in front of it. Nothing here undoes the line numbering to recover
|
|
177
|
+
* text: the numbering is what makes the comparison conclusive, not an encoding
|
|
178
|
+
* to be reversed.
|
|
179
|
+
*
|
|
180
|
+
* No chain, ever. A read roots nothing, so an entry here is the file as that one
|
|
181
|
+
* call showed it, and the ledger drops the witness the moment an edit lands.
|
|
182
|
+
*/
|
|
183
|
+
function readEvidence(
|
|
184
|
+
id: string,
|
|
185
|
+
tracker: FileReadTracker,
|
|
186
|
+
history: VisibleHistory,
|
|
187
|
+
): { key: string; evidence: FileEvidence } | undefined {
|
|
188
|
+
if (!tracker.readWitness) return
|
|
189
|
+
const call = visibleCall(history, id, 'read')
|
|
190
|
+
const shown = history.results.get(id)?.content
|
|
191
|
+
if (!call || typeof shown !== 'string' || shown.length > MAX_RECEIPT_UNITS) return
|
|
192
|
+
const input = ReadFileTool.inputSchema.safeParse(JSON.parse(call.function.arguments))
|
|
193
|
+
if (!input.success || input.data.path.length > MAX_PATH_UNITS) return
|
|
194
|
+
const key = history.keyOf(input.data.path)
|
|
195
|
+
if (key === undefined || knownStale(tracker, key)) return
|
|
196
|
+
const witness = tracker.readWitness(key)
|
|
197
|
+
const observed = tracker.fingerprint?.(key)
|
|
198
|
+
if (!witness || witness.callId !== id || observed === undefined) return
|
|
199
|
+
if (fingerprintContent(shown) !== witness.renderedFingerprint) return
|
|
200
|
+
return {
|
|
201
|
+
key,
|
|
202
|
+
evidence: {
|
|
203
|
+
path: input.data.path,
|
|
204
|
+
kind: 'read',
|
|
205
|
+
bodyInCall: id,
|
|
206
|
+
observedFingerprint: observed,
|
|
207
|
+
},
|
|
208
|
+
}
|
|
65
209
|
}
|