@dsh-enhanced/personal-memory 0.1.24 → 0.1.31
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 +46 -6
- package/lib/evidence-filesystem.d.ts +13 -0
- package/lib/evidence-filesystem.d.ts.map +1 -0
- package/lib/evidence-filesystem.js +115 -0
- package/lib/evidence-filesystem.js.map +1 -0
- package/lib/evidence-ledger.d.ts +33 -0
- package/lib/evidence-ledger.d.ts.map +1 -0
- package/lib/evidence-ledger.js +216 -0
- package/lib/evidence-ledger.js.map +1 -0
- package/lib/evidence-runtime.d.ts +28 -0
- package/lib/evidence-runtime.d.ts.map +1 -0
- package/lib/evidence-runtime.js +114 -0
- package/lib/evidence-runtime.js.map +1 -0
- package/lib/evidence-service.d.ts +50 -0
- package/lib/evidence-service.d.ts.map +1 -0
- package/lib/evidence-service.js +162 -0
- package/lib/evidence-service.js.map +1 -0
- package/lib/knowledge.d.ts +6 -0
- package/lib/knowledge.d.ts.map +1 -0
- package/lib/knowledge.js +55 -0
- package/lib/knowledge.js.map +1 -0
- package/lib/service.d.ts +12 -0
- package/lib/service.d.ts.map +1 -1
- package/lib/service.js +101 -1
- package/lib/service.js.map +1 -1
- package/lib/sqlite.d.ts +1 -1
- package/lib/sqlite.d.ts.map +1 -1
- package/lib/sqlite.js +54 -3
- package/lib/sqlite.js.map +1 -1
- package/lib/store.d.ts +2 -0
- package/lib/store.d.ts.map +1 -1
- package/lib/store.js +179 -33
- package/lib/store.js.map +1 -1
- package/lib/tools.d.ts.map +1 -1
- package/lib/tools.js +64 -3
- package/lib/tools.js.map +1 -1
- package/lib/types.d.ts +25 -1
- package/lib/types.d.ts.map +1 -1
- package/lib/version.d.ts +1 -1
- package/lib/version.js +1 -1
- package/package.json +30 -16
package/README.md
CHANGED
|
@@ -52,11 +52,47 @@ dsh --profile web --dump-config
|
|
|
52
52
|
- `ctx.personalMemory.exportJson(agent)`:导出版本化 JSON,不包含哈希、状态、时间戳、token 表或审计表。
|
|
53
53
|
- `ctx.personalMemory.proposeImport(...)`:先验证整个有界文档,再为每条记录创建审批提案;Agent 路径同样由 Delivery 派生审批 authority,未批准前不会写入 memory record。仅在未组合 Delivery 的可信本地/headless 集成中,程序化调用方可以显式传入 principal;一旦 Delivery 可用就不能用该字段覆盖绑定 owner。
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
安装了原生 `systemPrompt` 服务时,每次模型步骤组装上下文都会重新检查当前 owner、Policy 和记忆状态,并从 Session 当前有效消息中提取最近的用户输入或 Automation 任务(最多 2048 字符)进行关键词召回。任务相关记录优先,再补充用户确认的偏好与约定;工具结果、历史快照和自动补全文本不会替代当前任务。召回合并 user-global、当前 workspace、当前 agent-global 和当前 agent-workspace,受 top-K、字节和粗略 token 三重预算约束;`sensitive` 记录在 top-K 之前排除。每条包含 id、版本、来源、观测时间及可选原始引用、失效时间与替代关系。原生工具证据恢复见下节;普通 Memory 召回不自动批准历史工具内容。
|
|
56
|
+
|
|
57
|
+
同一 Host 安装 `assistant-goals` 时,Memory 还会在每步读取可选 `taskContext()`,按当前步骤 → 最近用户输入 → 目标 objective 的顺序召回并去重,再补确认的偏好和约定。Goals 每次检查 live owner 与 `snapshot` 授权;Memory 再核对 principal record/version/digest、workspace 和 preset,不能由模型选择别人的 namespace。同 owner 的显式 focus 可提供跨会话检索上下文,但不转移原生 Goal 执行权。checkpoint 的 nextStep 仅是规划文本,用作检索关键词,不成为可信事实或新权限。
|
|
58
|
+
|
|
59
|
+
该组合的可选 peer 为 `@dsh-enhanced/assistant-goals >=0.1.0 <0.2.0`;它不会自动启用 Goals。旧版本未提供 `goal-task-context/v1`、服务缺失/卸载、读取失败或身份不匹配时继续按原用户 query 召回。每个 query 字段最多 2048 字符,合并结果仍共用原有 top-K、字节和 token 预算。原生 AgentLoop 回归覆盖步骤改变和记忆撤回后的下一次模型请求;这证明动态检索接线,不代表已经测得真实模型决策收益。
|
|
60
|
+
|
|
61
|
+
内容被包在 `<memory_source>` 中并明确标为“不可信数据而非指令”;XML 元字符和模板花括号在预算计算前转义。原生 Host 持久保存发生变化的新快照,用它取代先前快照的有效语义;撤回、过期或权限撤销会影响下一步的当前快照,**不会删除 Session 中已经提供过的历史快照、工具结果或模型输出**。因此不能把本功能当作会话历史的数据擦除或跨 owner 会话迁移保护。没有 `systemPrompt` 的程序化集成保留旧的 `agent/session-start` 一次性冻结快照,不能承诺逐步更新。`memory_search`、`memory_search_confirmed` 与 `memory_manage` 的模型可见结果也使用有界、转义的独立 framing。缺少绝对 cwd、agent preset 或已验证 owner 时不搜索、不提案、不贡献新快照,也不会退化到共享域。
|
|
62
|
+
|
|
63
|
+
## 压缩后的原始文件证据
|
|
64
|
+
|
|
65
|
+
默认启用 `toolEvidence` 时,插件只索引当前可信 owner 由模型直接调用的原生成功 `read` 结果;`run_code`/PTC 子调度及其他嵌套调用暂不索引。记录绑定 owner namespace/version、workspace、preset、Session、原始事件序号、call id、原始 FS 观测的规范路径/目标身份摘要和内容摘要;摘要同时覆盖原始参数与模型可见结果。复制的 result、压缩 replacement、Memory 工具、其他自定义工具、shell 和图片均不成为新原始证据。原文只存在于原生 Session,不另存入 Memory,也不自动获得长期记忆审批。
|
|
66
|
+
|
|
67
|
+
原生 pruner/compaction 把原始结果移出当前上下文后,每步最多注入有界 `<session_tool_evidence>` 引用清单。`memory_read_evidence` 接受精确 `reference`,按 `offset` 分页,或用最长 256 字符的 `query` 定位(两者互斥);每页最多 4096 UTF-16 code units,保留完整 Unicode 字符。它检查原始事件及摘要,再通过当前 FS provider 解析原路径、校验普通文件及其与原始 FS 观测的身份一致性,以规范绝对 `processPath` 检查 Policy `read / filesystem` 权限,并通过当前 ToolRuntime 嵌套执行只读 `read`。原工具的作用域限制、正常 guard、取消信号均继续生效;返回前再次检查 owner、服务代际、工具注册、路径别名和读取期间的文件版本。需要 Host 提供 `fs` 与 `read`;本包不会自动安装或启用文件系统插件。
|
|
68
|
+
|
|
69
|
+
`integrity: matched` 仅证明历史观察和原始参数未被修改。输出仍标记 `freshness: historical-unverified`:当前授权检查中的重读不把旧正文变为当前事实;应显式读取当前内容再决策。文件删除、当前资源/工具权限撤销、工具卸载、摘要不符和任一检查失败均不返回历史正文。文件路径授权应显式配置,例如允许 `actions: [read]`、`resource: {kind: filesystem, id: /absolute/workspace/journal.txt}`;只允许工具名称不足以授予历史正文访问。原始 `read` 的 execute 和文件 read 若依赖预算,当前回读因缺少独立预留凭证而保守拒绝,写入授权审计但不预留/消费预算。
|
|
70
|
+
|
|
71
|
+
JSONL 冷恢复只使用先前 owner 绑定的索引,不按新 owner 回填旧会话。每个 owner/workspace/preset 最多保留 `maxRecordsPerIdentity` 条引用,跨 Session 淘汰最旧观察。索引和 Session 没有跨库原子事务:Session 缺失时引用不可用;索引缺失时不自动从历史补建。索引不是历史数据擦除机制,不支持跨 owner 迁移,不能隔离同进程受信任插件或同 UID 修改两个存储的代码。自定义远端 FS provider 可能执行网络读取;其授权和资源边界由该 provider 与正常工具管线负责。
|
|
72
|
+
|
|
73
|
+
## 适用条件、反例与事实分歧
|
|
74
|
+
|
|
75
|
+
`memory_manage` 的 entry 可带有界 `knowledge`,例如:
|
|
76
|
+
|
|
77
|
+
```json
|
|
78
|
+
{
|
|
79
|
+
"applicability": ["仅适用于 schema v2,且迁移日志已核验"],
|
|
80
|
+
"counterexamples": ["schema v1 没有迁移日志;曾因照搬此流程恢复失败"],
|
|
81
|
+
"claim": { "key": "atlas.recovery.mode", "value": "journal" }
|
|
82
|
+
}
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
条件和反例各最多 4 条,每条 1–256 UTF-8 字节;claim key 是 1–128 字符的小写 ASCII 标识符(字母、数字、`.`、`_`、`:`、`-`),value 最多 256 UTF-8 字节。内容与完整 knowledge 共用 `maxContentBytes`。完整字段进入审批 diff、幂等指纹、版本 CAS 和保存结果;修改条件或反例需要新的提案,不能复用原审批。条件不同的同文经验可分别保存,不会因正文相同而被去重。
|
|
86
|
+
|
|
87
|
+
检索也索引条件、反例和 claim,所以当前任务能找到相关的失败经验。快照和工具结果保留这些原文及 provenance;快照明确标记适用性尚未核验。关键词命中只说明相关,不证明条件成立,也不会自动把某条经验判为事实或赋予新权限。
|
|
88
|
+
|
|
89
|
+
每次检索与快照的排名、状态和冲突伙伴使用同一 SQLite 读视图,不阻塞其他 WAL writer;并发修改会在下一次读取体现。同一可见 claim key 有不同记录值时,快照会共同呈现来源和条件;预算无法容纳所有相关记录时,只给出分歧提示与有界记录引用,不留下看似无争议的单一正文。显式搜索的 `disagreement` 包含 key、记录数及最多 4 个记录 ID,在 query/top-K 截断前计算。自动补充的分歧信息仅来自当前 owner/scope 内有效、非敏感的记录;撤回、到期和身份变更会在下次读取生效。相同 key 的不同值可能源于不同适用条件,应核对当前系统和原始证据;本功能不解析任意自然语言矛盾,也不自行决定哪个值正确。
|
|
90
|
+
|
|
91
|
+
带 knowledge 的导出文档使用版本 2,导入仍须逐条批准;没有 knowledge 的导出继续使用版本 1,当前版本同时接受两种格式。旧 reader 会拒绝版本 2,避免悄悄丢掉条件后复用经验。升级到数据库 schema 6 前应停止旧 Host writer;v4→v5 新增 nullable knowledge 列,v5→v6 新增独立工具证据索引表,保留旧记录、pending 提案和既有回执指纹,不能让旧版本继续写入新库。
|
|
56
92
|
|
|
57
93
|
## 数据与一致性
|
|
58
94
|
|
|
59
|
-
SQLite 使用 WAL、`busy_timeout`、外键、FULL synchronous 和前向 schema 版本;目录为 `0700`,数据库为 `0600`。记录包含 stable id、内容哈希、provenance、trust、confidence、sensitivity、TTL、supersedes 和 version。replace/remove 在批准后重新读取 target version 并以 CAS 提交;审批与内存位于两个数据库,若进程恰好在 policy 批准后退出,可用原决定安全重放。并发变化会把提案标为 `conflicted`,不会覆盖新值。
|
|
95
|
+
SQLite 使用 WAL、`busy_timeout`、外键、FULL synchronous 和前向 schema 版本;目录为 `0700`,数据库为 `0600`。记录包含 stable id、内容哈希、provenance、trust、confidence、sensitivity、TTL、supersedes、可选 knowledge 和 version。replace/remove 在批准后重新读取 target version 并以 CAS 提交;审批与内存位于两个数据库,若进程恰好在 policy 批准后退出,可用原决定安全重放。并发变化会把提案标为 `conflicted`,不会覆盖新值。
|
|
60
96
|
|
|
61
97
|
创建提案时先在 Memory 数据库持久化 creation intent,再调用 Policy 原子创建 proposal + dispatch,最后在
|
|
62
98
|
同一个本地事务 attach Policy ID 并删除 intent。任一步崩溃后,reconcile 都能从 intent 自动续做,不依赖
|
|
@@ -79,9 +115,13 @@ JSON 导入是一组独立、可重放的提案,不承诺跨所有记录的一
|
|
|
79
115
|
| `maxContentBytes` | 4096 | 单条内容最大 UTF-8 字节数 |
|
|
80
116
|
| `maxRecordsPerIdentity` | 1000 | 每个完整身份域的活动记录上限 |
|
|
81
117
|
| `searchLimit` | 20 | 未显式指定时的搜索上限 |
|
|
82
|
-
| `snapshotLimit` | 20 |
|
|
118
|
+
| `snapshotLimit` | 20 | 当前快照记录上限 |
|
|
83
119
|
| `snapshotMaxBytes` | 8192 | 快照最大 UTF-8 字节数 |
|
|
84
120
|
| `snapshotMaxTokens` | 2048 | 快照粗略 token 上限 |
|
|
121
|
+
| `toolEvidence` | `true` | 索引当前成功的原生 `read`,提供压缩后历史原文回读 |
|
|
122
|
+
| `evidenceMaxSourceBytes` | 1048576 | 原始参数与结果总字节上限,最大 4194304 |
|
|
123
|
+
| `evidenceManifestMaxBytes` | 2048 | 引用清单最大 UTF-8 字节数,最大 8192 |
|
|
124
|
+
| `evidenceManifestLimit` | 8 | 清单最多引用数,最大 20,同时受每身份记录上限限制 |
|
|
85
125
|
| `defaultProposalTtlMs` | 900000 | 默认提案有效期(15 分钟) |
|
|
86
126
|
| `maxImportRecords` | 100 | 单次导入最大记录数 |
|
|
87
127
|
| `reconcileIntervalMs` | 15000 | 提交“会话结束后才被批准”的提案的轮询间隔;`0` 关闭定时器,上限为 Node timer 的 `2147483647` ms |
|
|
@@ -105,12 +145,12 @@ JSON 导入是一组独立、可重放的提案,不承诺跨所有记录的一
|
|
|
105
145
|
|
|
106
146
|
## 权限与非目标
|
|
107
147
|
|
|
108
|
-
-
|
|
109
|
-
-
|
|
148
|
+
- 文件系统:读写配置的 SQLite 数据库及其 WAL/SHM 辅助文件;工具证据功能另读取当前 Session 原始事件,并经 Host FS 与原生 `read` 管线重读显式授权文件。它不写用户文件。
|
|
149
|
+
- 网络:本插件不直接发网络请求;工具证据重读可调用 Host 配置的远端 FS provider。组合 Delivery 时只写 durable dispatch,由 channel 插件负责发送审批卡片。
|
|
110
150
|
- 子进程、凭据、浏览器、安装脚本:无。
|
|
111
151
|
- 数据敏感性:`sensitive` 只表示禁止环境快照;显式、已授权的搜索仍可能把内容发送给当前模型。真正的密码/API key 应放在后续 `credentials-keychain`,不要写入 memory。
|
|
112
152
|
- 非目标:向量数据库、自动无审批写入、自动遗忘/dreaming、知识图谱、Wiki 长文、跨设备同步和多用户 ACL。
|
|
113
153
|
|
|
114
154
|
## 兼容性
|
|
115
155
|
|
|
116
|
-
已针对 DeepSeek Harness `0.1.
|
|
156
|
+
已针对 DeepSeek Harness `0.1.2-rc.1` 验证。详见仓库[兼容性基线](../../docs/compatibility.md)。
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type Context } from '@deepseek-ai/cordis';
|
|
2
|
+
import type { ToolExecution } from '@deepseek-ai/dsh-tools';
|
|
3
|
+
import type { AssistantPolicyService } from '@dsh-enhanced/assistant-policy';
|
|
4
|
+
import type { EvidenceAnchor } from './evidence-ledger.js';
|
|
5
|
+
import type { OriginalToolEvidence } from './evidence-runtime.js';
|
|
6
|
+
/**
|
|
7
|
+
* Re-run an original `read` through the live tool pipeline. Policy resources
|
|
8
|
+
* use the filesystem provider's canonical process path, rather than
|
|
9
|
+
* `displayPath`: `displayPath` is presentation text and may be relative or a
|
|
10
|
+
* URI, while `processPath()` is the provider's absolute execution-world path.
|
|
11
|
+
*/
|
|
12
|
+
export declare function revalidateFileEvidence(ctx: Context, policy: AssistantPolicyService, exec: ToolExecution, source: OriginalToolEvidence, anchor: EvidenceAnchor): Promise<boolean>;
|
|
13
|
+
//# sourceMappingURL=evidence-filesystem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-filesystem.d.ts","sourceRoot":"","sources":["../src/evidence-filesystem.ts"],"names":[],"mappings":"AACA,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,qBAAqB,CAAA;AAG3D,OAAO,KAAK,EAAE,aAAa,EAAe,MAAM,wBAAwB,CAAA;AACxE,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,gCAAgC,CAAA;AAC5E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAA;AAC1D,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAA;AAqCjE;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAC1C,GAAG,EAAE,OAAO,EACZ,MAAM,EAAE,sBAAsB,EAC9B,IAAI,EAAE,aAAa,EACnB,MAAM,EAAE,oBAAoB,EAC5B,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,OAAO,CAAC,CAwDlB"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import { isAbsolute, resolve as normalizePath } from 'node:path';
|
|
2
|
+
import { Service } from '@deepseek-ai/cordis';
|
|
3
|
+
import { ToolCallId } from '@deepseek-ai/dsh-llm';
|
|
4
|
+
function parseReadArguments(value) {
|
|
5
|
+
let parsed;
|
|
6
|
+
try {
|
|
7
|
+
parsed = JSON.parse(value);
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
13
|
+
return undefined;
|
|
14
|
+
const record = parsed;
|
|
15
|
+
if (!Object.keys(record).every(key => key === 'file_path' || key === 'offset' || key === 'limit'))
|
|
16
|
+
return undefined;
|
|
17
|
+
const offset = record.offset;
|
|
18
|
+
const limit = record.limit;
|
|
19
|
+
if (typeof record.file_path !== 'string' || record.file_path.trim() === '' || record.file_path.length > 4_096)
|
|
20
|
+
return undefined;
|
|
21
|
+
if ((offset !== undefined && (typeof offset !== 'number' || !Number.isSafeInteger(offset) || offset <= 0))
|
|
22
|
+
|| (limit !== undefined && (typeof limit !== 'number' || !Number.isSafeInteger(limit) || limit <= 0)))
|
|
23
|
+
return undefined;
|
|
24
|
+
return Object.freeze({
|
|
25
|
+
file_path: record.file_path,
|
|
26
|
+
...(offset === undefined ? {} : { offset }),
|
|
27
|
+
...(limit === undefined ? {} : { limit }),
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
function currentAgent(ctx, exec) {
|
|
31
|
+
const agent = exec.agent;
|
|
32
|
+
return agent !== undefined && agent.status === 'running'
|
|
33
|
+
&& ctx.get('agents', false)?.get(agent.id) === agent
|
|
34
|
+
&& ctx.get('sessions', false)?.get(agent.session.id) === agent.session;
|
|
35
|
+
}
|
|
36
|
+
function regularFile(info) {
|
|
37
|
+
return info?.type === 'file';
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Re-run an original `read` through the live tool pipeline. Policy resources
|
|
41
|
+
* use the filesystem provider's canonical process path, rather than
|
|
42
|
+
* `displayPath`: `displayPath` is presentation text and may be relative or a
|
|
43
|
+
* URI, while `processPath()` is the provider's absolute execution-world path.
|
|
44
|
+
*/
|
|
45
|
+
export async function revalidateFileEvidence(ctx, policy, exec, source, anchor) {
|
|
46
|
+
if (source.toolName !== 'read' || source.failed || anchor.toolName !== 'read'
|
|
47
|
+
|| exec.signal.aborted || !currentAgent(ctx, exec))
|
|
48
|
+
return false;
|
|
49
|
+
const args = parseReadArguments(source.callArguments);
|
|
50
|
+
if (args === undefined)
|
|
51
|
+
return false;
|
|
52
|
+
const fs = ctx.get('fs', false);
|
|
53
|
+
const tools = ctx.get('tools', false);
|
|
54
|
+
const agent = exec.agent;
|
|
55
|
+
const cwd = agent?.session.header.cwd;
|
|
56
|
+
if (fs === undefined || tools === undefined || agent === undefined || cwd === undefined)
|
|
57
|
+
return false;
|
|
58
|
+
const readDefinition = tools.get('read', agent);
|
|
59
|
+
if (readDefinition === undefined)
|
|
60
|
+
return false;
|
|
61
|
+
try {
|
|
62
|
+
const target = await fs.resolve(args.file_path, { cwd, signal: exec.signal });
|
|
63
|
+
const processPath = fs.processPath(target);
|
|
64
|
+
if (!isAbsolute(processPath) || normalizePath(processPath) !== processPath)
|
|
65
|
+
return false;
|
|
66
|
+
if (processPath !== anchor.sourcePath || digestTarget(target) !== anchor.sourceTargetDigest)
|
|
67
|
+
return false;
|
|
68
|
+
const before = await fs.stat(target, exec.signal);
|
|
69
|
+
if (!regularFile(before) || exec.signal.aborted)
|
|
70
|
+
return false;
|
|
71
|
+
if (policy.authorizeAgent(agent, 'read', { kind: 'filesystem', id: processPath }).effect !== 'allow')
|
|
72
|
+
return false;
|
|
73
|
+
const result = await tools.execute({
|
|
74
|
+
callId: ToolCallId(`${exec.callId}:evidence-revalidate`),
|
|
75
|
+
rootCallId: exec.rootCallId,
|
|
76
|
+
parent: exec.token,
|
|
77
|
+
name: 'read',
|
|
78
|
+
agent,
|
|
79
|
+
signal: exec.signal,
|
|
80
|
+
arguments: { file_path: processPath, ...(args.offset === undefined ? {} : { offset: args.offset }),
|
|
81
|
+
...(args.limit === undefined ? {} : { limit: args.limit }) },
|
|
82
|
+
});
|
|
83
|
+
if (result.isError || exec.signal.aborted)
|
|
84
|
+
return false;
|
|
85
|
+
// Re-resolve the original spelling to detect an alias/symlink replacement
|
|
86
|
+
// while the nested read ran. The opaque target key and version are the
|
|
87
|
+
// backend-owned identity and freshness proof; neither is parsed here.
|
|
88
|
+
const currentFs = ctx.get('fs', false);
|
|
89
|
+
const currentTools = ctx.get('tools', false);
|
|
90
|
+
// Cordis returns a fresh trace proxy on each lookup; its per-instance
|
|
91
|
+
// tracker is stable across proxies and changes with service replacement.
|
|
92
|
+
if (currentFs === undefined || currentTools === undefined
|
|
93
|
+
|| Reflect.get(fs, Service.tracker) === undefined || Reflect.get(tools, Service.tracker) === undefined
|
|
94
|
+
|| Reflect.get(currentFs, Service.tracker) !== Reflect.get(fs, Service.tracker)
|
|
95
|
+
|| Reflect.get(currentTools, Service.tracker) !== Reflect.get(tools, Service.tracker)
|
|
96
|
+
|| currentTools.get('read', agent) !== readDefinition)
|
|
97
|
+
return false;
|
|
98
|
+
const finalTarget = await fs.resolve(args.file_path, { cwd, signal: exec.signal });
|
|
99
|
+
if (finalTarget.targetKey !== target.targetKey || fs.processPath(finalTarget) !== processPath
|
|
100
|
+
|| fs.processPath(finalTarget) !== anchor.sourcePath || digestTarget(finalTarget) !== anchor.sourceTargetDigest)
|
|
101
|
+
return false;
|
|
102
|
+
const after = await fs.stat(finalTarget, exec.signal);
|
|
103
|
+
if (!regularFile(after) || after.version !== before.version || exec.signal.aborted)
|
|
104
|
+
return false;
|
|
105
|
+
return policy.authorizeAgent(agent, 'read', { kind: 'filesystem', id: processPath }).effect === 'allow';
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
function digestTarget(target) {
|
|
112
|
+
return createHash('sha256').update(String(target.targetKey)).digest('hex');
|
|
113
|
+
}
|
|
114
|
+
import { createHash } from 'node:crypto';
|
|
115
|
+
//# sourceMappingURL=evidence-filesystem.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-filesystem.js","sourceRoot":"","sources":["../src/evidence-filesystem.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import type { MemoryOwnerNamespace } from './types.js';
|
|
3
|
+
export interface EvidenceScope {
|
|
4
|
+
namespace: MemoryOwnerNamespace;
|
|
5
|
+
workspace: string;
|
|
6
|
+
agentPreset: string;
|
|
7
|
+
sessionId: string;
|
|
8
|
+
}
|
|
9
|
+
export interface EvidenceAnchor {
|
|
10
|
+
reference: string;
|
|
11
|
+
eventSeq: number;
|
|
12
|
+
toolName: string;
|
|
13
|
+
callId: string;
|
|
14
|
+
contentDigest: string;
|
|
15
|
+
sourcePath: string;
|
|
16
|
+
sourceTargetDigest: string;
|
|
17
|
+
observedAt: number;
|
|
18
|
+
}
|
|
19
|
+
export declare class MemoryEvidenceLedgerError extends Error {
|
|
20
|
+
readonly code: 'conflict' | 'invalid-anchor' | 'invalid-scope';
|
|
21
|
+
constructor(code: 'conflict' | 'invalid-anchor' | 'invalid-scope', message: string);
|
|
22
|
+
}
|
|
23
|
+
export declare class MemoryEvidenceLedger {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(database: DatabaseSync, options?: Readonly<{
|
|
26
|
+
maxRows?: number;
|
|
27
|
+
}>);
|
|
28
|
+
record(scope: EvidenceScope, input: Omit<EvidenceAnchor, 'reference'>): EvidenceAnchor;
|
|
29
|
+
list(scope: EvidenceScope, limit: number): readonly EvidenceAnchor[];
|
|
30
|
+
get(scope: EvidenceScope, reference: string): EvidenceAnchor | undefined;
|
|
31
|
+
private checkedRow;
|
|
32
|
+
}
|
|
33
|
+
//# sourceMappingURL=evidence-ledger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-ledger.d.ts","sourceRoot":"","sources":["../src/evidence-ledger.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAK/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAA;AAKtD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,oBAAoB,CAAA;IAC/B,SAAS,EAAE,MAAM,CAAA;IACjB,WAAW,EAAE,MAAM,CAAA;IACnB,SAAS,EAAE,MAAM,CAAA;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,SAAS,EAAE,MAAM,CAAA;IACjB,QAAQ,EAAE,MAAM,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,aAAa,EAAE,MAAM,CAAA;IACrB,UAAU,EAAE,MAAM,CAAA;IAClB,kBAAkB,EAAE,MAAM,CAAA;IAC1B,UAAU,EAAE,MAAM,CAAA;CACnB;AAED,qBAAa,yBAA0B,SAAQ,KAAK;IACtC,QAAQ,CAAC,IAAI,EAAE,UAAU,GAAG,gBAAgB,GAAG,eAAe;gBAArD,IAAI,EAAE,UAAU,GAAG,gBAAgB,GAAG,eAAe,EAAE,OAAO,EAAE,MAAM;CAI5F;AAsID,qBAAa,oBAAoB;;gBAInB,QAAQ,EAAE,YAAY,EAAE,OAAO,GAAE,QAAQ,CAAC;QAAE,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAM;IAQhF,MAAM,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,GAAG,cAAc;IAiEtF,IAAI,CAAC,KAAK,EAAE,aAAa,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,cAAc,EAAE;IAuBpE,GAAG,CAAC,KAAK,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS;IAqBxE,OAAO,CAAC,UAAU;CAMnB"}
|
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
import { createHash } from 'node:crypto';
|
|
2
|
+
import { isAbsolute } from 'node:path';
|
|
3
|
+
import { memoryOwnerNamespaceKey, normalizeMemoryOwnerNamespace, } from './store.js';
|
|
4
|
+
const SHA_256 = /^[0-9a-f]{64}$/u;
|
|
5
|
+
const MAX_TEXT_BYTES = 512;
|
|
6
|
+
export class MemoryEvidenceLedgerError extends Error {
|
|
7
|
+
code;
|
|
8
|
+
constructor(code, message) {
|
|
9
|
+
super(message);
|
|
10
|
+
this.code = code;
|
|
11
|
+
this.name = 'MemoryEvidenceLedgerError';
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
function stableValue(value) {
|
|
15
|
+
if (Array.isArray(value))
|
|
16
|
+
return value.map(stableValue);
|
|
17
|
+
if (typeof value !== 'object' || value === null)
|
|
18
|
+
return value;
|
|
19
|
+
return Object.fromEntries(Object.entries(value).sort(([left], [right]) => left < right ? -1 : left > right ? 1 : 0)
|
|
20
|
+
.map(([key, nested]) => [key, stableValue(nested)]));
|
|
21
|
+
}
|
|
22
|
+
function stableJson(value) {
|
|
23
|
+
return JSON.stringify(stableValue(value));
|
|
24
|
+
}
|
|
25
|
+
function boundedText(value, label) {
|
|
26
|
+
if (typeof value !== 'string' || value === '' || value.normalize('NFC').trim() !== value
|
|
27
|
+
|| Buffer.byteLength(value, 'utf8') > MAX_TEXT_BYTES) {
|
|
28
|
+
throw new MemoryEvidenceLedgerError('invalid-scope', `${label} is invalid`);
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function boundedAnchorText(value, label) {
|
|
33
|
+
try {
|
|
34
|
+
return boundedText(value, label);
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', `${label} is invalid`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function assertNonnegativeSafeInteger(value, label) {
|
|
41
|
+
if (typeof value !== 'number' || !Number.isSafeInteger(value) || value < 0) {
|
|
42
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', `${label} is invalid`);
|
|
43
|
+
}
|
|
44
|
+
return value;
|
|
45
|
+
}
|
|
46
|
+
function normalizeScope(scope) {
|
|
47
|
+
if (typeof scope !== 'object' || scope === null || typeof scope.workspace !== 'string'
|
|
48
|
+
|| !isAbsolute(scope.workspace)) {
|
|
49
|
+
throw new MemoryEvidenceLedgerError('invalid-scope', 'evidence scope workspace is invalid');
|
|
50
|
+
}
|
|
51
|
+
const namespace = normalizeMemoryOwnerNamespace(scope.namespace);
|
|
52
|
+
return {
|
|
53
|
+
namespaceMode: namespace.mode,
|
|
54
|
+
namespaceKey: memoryOwnerNamespaceKey(namespace),
|
|
55
|
+
principalDigest: namespace.principalDigest,
|
|
56
|
+
principalRecordId: namespace.mode === 'delivery' ? namespace.principalRecordId : null,
|
|
57
|
+
principalVersion: namespace.mode === 'delivery' ? namespace.principalVersion : null,
|
|
58
|
+
headlessLineageId: namespace.mode === 'headless' ? namespace.lineageId : null,
|
|
59
|
+
headlessLineageVersion: namespace.mode === 'headless' ? namespace.lineageVersion : null,
|
|
60
|
+
workspace: boundedText(scope.workspace, 'evidence workspace'),
|
|
61
|
+
agentPreset: boundedText(scope.agentPreset, 'evidence agent preset'),
|
|
62
|
+
sessionId: boundedText(scope.sessionId, 'evidence session id'),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function normalizeAnchor(input) {
|
|
66
|
+
if (typeof input !== 'object' || input === null || typeof input.contentDigest !== 'string' || !SHA_256.test(input.contentDigest)) {
|
|
67
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'evidence anchor content digest is invalid');
|
|
68
|
+
}
|
|
69
|
+
if (typeof input.sourceTargetDigest !== 'string' || !SHA_256.test(input.sourceTargetDigest)
|
|
70
|
+
|| typeof input.sourcePath !== 'string' || !isAbsolute(input.sourcePath)) {
|
|
71
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'evidence filesystem origin is invalid');
|
|
72
|
+
}
|
|
73
|
+
return Object.freeze({
|
|
74
|
+
sourcePath: boundedAnchorText(input.sourcePath, 'evidence source path'),
|
|
75
|
+
sourceTargetDigest: input.sourceTargetDigest,
|
|
76
|
+
eventSeq: assertNonnegativeSafeInteger(input.eventSeq, 'evidence event sequence'),
|
|
77
|
+
toolName: boundedAnchorText(input.toolName, 'evidence tool name'),
|
|
78
|
+
callId: boundedAnchorText(input.callId, 'evidence call id'),
|
|
79
|
+
contentDigest: input.contentDigest,
|
|
80
|
+
observedAt: assertNonnegativeSafeInteger(input.observedAt, 'evidence observed time'),
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
function referenceFor(scope, anchor) {
|
|
84
|
+
const canonicalScope = {
|
|
85
|
+
namespace: scope.namespaceMode === 'delivery'
|
|
86
|
+
? {
|
|
87
|
+
mode: scope.namespaceMode,
|
|
88
|
+
principalDigest: scope.principalDigest,
|
|
89
|
+
principalRecordId: scope.principalRecordId,
|
|
90
|
+
principalVersion: scope.principalVersion,
|
|
91
|
+
}
|
|
92
|
+
: {
|
|
93
|
+
mode: scope.namespaceMode,
|
|
94
|
+
principalDigest: scope.principalDigest,
|
|
95
|
+
lineageId: scope.headlessLineageId,
|
|
96
|
+
lineageVersion: scope.headlessLineageVersion,
|
|
97
|
+
},
|
|
98
|
+
workspace: scope.workspace,
|
|
99
|
+
agentPreset: scope.agentPreset,
|
|
100
|
+
sessionId: scope.sessionId,
|
|
101
|
+
};
|
|
102
|
+
return `dsh-evidence:v1:${createHash('sha256').update(stableJson({ anchor, scope: canonicalScope })).digest('hex')}`;
|
|
103
|
+
}
|
|
104
|
+
function anchorFromRow(row) {
|
|
105
|
+
return Object.freeze({
|
|
106
|
+
reference: row.reference,
|
|
107
|
+
eventSeq: row.event_seq,
|
|
108
|
+
toolName: row.tool_name,
|
|
109
|
+
callId: row.call_id,
|
|
110
|
+
contentDigest: row.content_digest,
|
|
111
|
+
sourcePath: row.source_path,
|
|
112
|
+
sourceTargetDigest: row.source_target_digest,
|
|
113
|
+
observedAt: row.observed_at,
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
export class MemoryEvidenceLedger {
|
|
117
|
+
#database;
|
|
118
|
+
#maxRows;
|
|
119
|
+
constructor(database, options = {}) {
|
|
120
|
+
this.#database = database;
|
|
121
|
+
this.#maxRows = options.maxRows ?? 1_000;
|
|
122
|
+
if (!Number.isSafeInteger(this.#maxRows) || this.#maxRows <= 0) {
|
|
123
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'evidence row limit is invalid');
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
record(scope, input) {
|
|
127
|
+
const normalizedScope = normalizeScope(scope);
|
|
128
|
+
const anchor = normalizeAnchor(input);
|
|
129
|
+
const reference = referenceFor(normalizedScope, anchor);
|
|
130
|
+
this.#database.exec('BEGIN IMMEDIATE');
|
|
131
|
+
try {
|
|
132
|
+
const duplicate = this.get(scope, reference);
|
|
133
|
+
if (duplicate !== undefined) {
|
|
134
|
+
this.#database.exec('COMMIT');
|
|
135
|
+
return duplicate;
|
|
136
|
+
}
|
|
137
|
+
const conflict = this.#database.prepare(`
|
|
138
|
+
SELECT reference FROM memory_evidence_anchors
|
|
139
|
+
WHERE namespace_mode = ? AND namespace_key = ? AND principal_digest = ?
|
|
140
|
+
AND principal_record_id IS ? AND principal_version IS ?
|
|
141
|
+
AND headless_lineage_id IS ? AND headless_lineage_version IS ?
|
|
142
|
+
AND workspace = ? AND agent_preset = ?
|
|
143
|
+
AND session_id = ? AND event_seq = ?
|
|
144
|
+
`).get(normalizedScope.namespaceMode, normalizedScope.namespaceKey, normalizedScope.principalDigest, normalizedScope.principalRecordId, normalizedScope.principalVersion, normalizedScope.headlessLineageId, normalizedScope.headlessLineageVersion, normalizedScope.workspace, normalizedScope.agentPreset, normalizedScope.sessionId, anchor.eventSeq);
|
|
145
|
+
if (conflict !== undefined) {
|
|
146
|
+
throw new MemoryEvidenceLedgerError('conflict', 'evidence session event sequence conflicts with immutable metadata');
|
|
147
|
+
}
|
|
148
|
+
this.#database.prepare(`
|
|
149
|
+
INSERT INTO memory_evidence_anchors(
|
|
150
|
+
reference, namespace_mode, namespace_key, principal_digest, principal_record_id, principal_version,
|
|
151
|
+
headless_lineage_id, headless_lineage_version, workspace, agent_preset, session_id, event_seq,
|
|
152
|
+
tool_name, call_id, content_digest, source_path, source_target_digest, observed_at
|
|
153
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
154
|
+
`).run(reference, normalizedScope.namespaceMode, normalizedScope.namespaceKey, normalizedScope.principalDigest, normalizedScope.principalRecordId, normalizedScope.principalVersion, normalizedScope.headlessLineageId, normalizedScope.headlessLineageVersion, normalizedScope.workspace, normalizedScope.agentPreset, normalizedScope.sessionId, anchor.eventSeq, anchor.toolName, anchor.callId, anchor.contentDigest, anchor.sourcePath, anchor.sourceTargetDigest, anchor.observedAt);
|
|
155
|
+
this.#database.prepare(`
|
|
156
|
+
DELETE FROM memory_evidence_anchors
|
|
157
|
+
WHERE reference IN (
|
|
158
|
+
SELECT reference FROM memory_evidence_anchors
|
|
159
|
+
WHERE namespace_key = ? AND workspace = ? AND agent_preset = ?
|
|
160
|
+
ORDER BY observed_at ASC, reference ASC
|
|
161
|
+
LIMIT CASE WHEN (SELECT count(*) FROM memory_evidence_anchors
|
|
162
|
+
WHERE namespace_key = ? AND workspace = ? AND agent_preset = ?) > ?
|
|
163
|
+
THEN (SELECT count(*) FROM memory_evidence_anchors
|
|
164
|
+
WHERE namespace_key = ? AND workspace = ? AND agent_preset = ?) - ?
|
|
165
|
+
ELSE 0 END
|
|
166
|
+
)
|
|
167
|
+
`).run(normalizedScope.namespaceKey, normalizedScope.workspace, normalizedScope.agentPreset, normalizedScope.namespaceKey, normalizedScope.workspace, normalizedScope.agentPreset, this.#maxRows, normalizedScope.namespaceKey, normalizedScope.workspace, normalizedScope.agentPreset, this.#maxRows);
|
|
168
|
+
this.#database.exec('COMMIT');
|
|
169
|
+
return Object.freeze({ reference, ...anchor });
|
|
170
|
+
}
|
|
171
|
+
catch (error) {
|
|
172
|
+
this.#database.exec('ROLLBACK');
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
list(scope, limit) {
|
|
177
|
+
const normalizedScope = normalizeScope(scope);
|
|
178
|
+
if (!Number.isSafeInteger(limit) || limit <= 0 || limit > this.#maxRows) {
|
|
179
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'evidence list limit is invalid');
|
|
180
|
+
}
|
|
181
|
+
const rows = this.#database.prepare(`
|
|
182
|
+
SELECT reference, event_seq, tool_name, call_id, content_digest, source_path, source_target_digest, observed_at
|
|
183
|
+
FROM memory_evidence_anchors
|
|
184
|
+
WHERE namespace_mode = ? AND namespace_key = ? AND principal_digest = ?
|
|
185
|
+
AND principal_record_id IS ? AND principal_version IS ?
|
|
186
|
+
AND headless_lineage_id IS ? AND headless_lineage_version IS ?
|
|
187
|
+
AND workspace = ? AND agent_preset = ? AND session_id = ?
|
|
188
|
+
ORDER BY observed_at DESC, reference DESC
|
|
189
|
+
LIMIT ?
|
|
190
|
+
`).all(normalizedScope.namespaceMode, normalizedScope.namespaceKey, normalizedScope.principalDigest, normalizedScope.principalRecordId, normalizedScope.principalVersion, normalizedScope.headlessLineageId, normalizedScope.headlessLineageVersion, normalizedScope.workspace, normalizedScope.agentPreset, normalizedScope.sessionId, limit);
|
|
191
|
+
return Object.freeze(rows.map(row => this.checkedRow(normalizedScope, row)));
|
|
192
|
+
}
|
|
193
|
+
get(scope, reference) {
|
|
194
|
+
const normalizedScope = normalizeScope(scope);
|
|
195
|
+
if (typeof reference !== 'string' || !/^dsh-evidence:v1:[0-9a-f]{64}$/u.test(reference)) {
|
|
196
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'evidence reference is invalid');
|
|
197
|
+
}
|
|
198
|
+
const row = this.#database.prepare(`
|
|
199
|
+
SELECT reference, event_seq, tool_name, call_id, content_digest, source_path, source_target_digest, observed_at
|
|
200
|
+
FROM memory_evidence_anchors
|
|
201
|
+
WHERE reference = ? AND namespace_mode = ? AND namespace_key = ? AND principal_digest = ?
|
|
202
|
+
AND principal_record_id IS ? AND principal_version IS ?
|
|
203
|
+
AND headless_lineage_id IS ? AND headless_lineage_version IS ?
|
|
204
|
+
AND workspace = ? AND agent_preset = ? AND session_id = ?
|
|
205
|
+
`).get(reference, normalizedScope.namespaceMode, normalizedScope.namespaceKey, normalizedScope.principalDigest, normalizedScope.principalRecordId, normalizedScope.principalVersion, normalizedScope.headlessLineageId, normalizedScope.headlessLineageVersion, normalizedScope.workspace, normalizedScope.agentPreset, normalizedScope.sessionId);
|
|
206
|
+
return row === undefined ? undefined : this.checkedRow(normalizedScope, row);
|
|
207
|
+
}
|
|
208
|
+
checkedRow(scope, row) {
|
|
209
|
+
const value = anchorFromRow(row);
|
|
210
|
+
const anchor = normalizeAnchor(value);
|
|
211
|
+
if (referenceFor(scope, anchor) !== value.reference)
|
|
212
|
+
throw new MemoryEvidenceLedgerError('invalid-anchor', 'stored evidence reference does not match immutable metadata');
|
|
213
|
+
return value;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
//# sourceMappingURL=evidence-ledger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-ledger.js","sourceRoot":"","sources":["../src/evidence-ledger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Session } from '@deepseek-ai/dsh-session';
|
|
2
|
+
export interface OriginalToolEvidence {
|
|
3
|
+
readonly eventSeq: number;
|
|
4
|
+
readonly toolName: string;
|
|
5
|
+
readonly callId: string;
|
|
6
|
+
/** Original arguments stay in the Session only; never put them in a manifest. */
|
|
7
|
+
readonly callArguments: string;
|
|
8
|
+
readonly contentDigest: string;
|
|
9
|
+
readonly observedAt: number;
|
|
10
|
+
/** Canonical JSON of the model-visible result content and error flag. */
|
|
11
|
+
readonly text: string;
|
|
12
|
+
readonly failed: boolean;
|
|
13
|
+
}
|
|
14
|
+
export interface ToolEvidencePage {
|
|
15
|
+
readonly text: string;
|
|
16
|
+
readonly offset: number;
|
|
17
|
+
readonly nextOffset: number | null;
|
|
18
|
+
readonly totalChars: number;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Return immutable evidence from the original append-only tool result, never a
|
|
22
|
+
* model-surface replacement or a summary. This deliberately has no ownership
|
|
23
|
+
* or authorization policy: callers must apply those checks before exposing it.
|
|
24
|
+
*/
|
|
25
|
+
export declare function originalToolEvidence(session: Session, eventSeq: number, maxSourceBytes?: number): OriginalToolEvidence | undefined;
|
|
26
|
+
/** Page canonical evidence without returning an invalid half-surrogate. */
|
|
27
|
+
export declare function pageToolEvidence(value: Pick<OriginalToolEvidence, 'text'>, offset: number, maxChars?: number): ToolEvidencePage;
|
|
28
|
+
//# sourceMappingURL=evidence-runtime.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"evidence-runtime.d.ts","sourceRoot":"","sources":["../src/evidence-runtime.ts"],"names":[],"mappings":"AACA,OAAO,EAAwB,KAAK,OAAO,EAAE,MAAM,0BAA0B,CAAA;AAM7E,MAAM,WAAW,oBAAoB;IACnC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,iFAAiF;IACjF,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAA;IAC9B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;IAC3B,yEAAyE;IACzE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IAClC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC5B;AAsBD;;;;GAIG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,OAAO,EAChB,QAAQ,EAAE,MAAM,EAChB,cAAc,GAAE,MAAiC,GAChD,oBAAoB,GAAG,SAAS,CAyClC;AAgBD,2EAA2E;AAC3E,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,IAAI,CAAC,oBAAoB,EAAE,MAAM,CAAC,EACzC,MAAM,EAAE,MAAM,EACd,QAAQ,GAAE,MAAuB,GAChC,gBAAgB,CAmBlB"}
|