@tangle-network/agent-interface 3.1.2 → 3.2.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/README.md +67 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/learning-state.d.ts +488 -0
- package/dist/learning-state.js +154 -0
- package/package.json +6 -1
package/README.md
CHANGED
|
@@ -323,3 +323,70 @@ Adapters emit `native.session.observed` with `provider` and `nativeSessionId` af
|
|
|
323
323
|
The execution owner binds the observation to its execution and keeps it private.
|
|
324
324
|
Public `session.updated` events retain their resume-key semantics and do not establish native identity.
|
|
325
325
|
Native identity does not establish artifact capture completeness.
|
|
326
|
+
|
|
327
|
+
### Optional native learning state interchange
|
|
328
|
+
|
|
329
|
+
`@tangle-network/agent-interface/learning-state` describes an **opt-in** boundary
|
|
330
|
+
between a host's existing durable state owner and one explicitly configured
|
|
331
|
+
harness adapter. Native harness memory stays the default. This module creates no
|
|
332
|
+
store, tools, provider connection, profile fields, or automatic synchronization.
|
|
333
|
+
Hindsight memory branches and QMD source snapshots keep their existing
|
|
334
|
+
`agent-knowledge` owners and references; do not copy their facts into a second
|
|
335
|
+
file database to satisfy this contract.
|
|
336
|
+
|
|
337
|
+
`AgentLearningIdentity` names an authenticated workspace, stable state, and
|
|
338
|
+
personal member/agent or shared group/agent scope. A thread, native session,
|
|
339
|
+
profile revision, or authority digest is not that identity. The host derives it
|
|
340
|
+
from authenticated context and verifies the persisted root/volume binding;
|
|
341
|
+
passing schema validation does not authorize access. Session and turn IDs belong
|
|
342
|
+
in invocation provenance. Two turns need immutable per-turn state pins plus the
|
|
343
|
+
state owner's lease or compare-and-swap, not an uncoordinated shared writable home.
|
|
344
|
+
|
|
345
|
+
`AgentLearningManifest` references the existing owner's exact revision and
|
|
346
|
+
content digest. The `files` field is only a bounded, protected-home-compatible
|
|
347
|
+
text exchange subset: `USER.md` preferences, `MEMORY.md` facts,
|
|
348
|
+
`memory/YYYY-MM-DD.md` notes, and `skills/<slug>/SKILL.md` procedure sources. These
|
|
349
|
+
are interchange names, never a claim about a harness's actual native paths or a
|
|
350
|
+
universal memory model. An adapter must explicitly map and verify this subset.
|
|
351
|
+
A native-only adapter may leave `files` empty and preserve opaque native state
|
|
352
|
+
references instead. Opaque references must resolve privately to verified bytes;
|
|
353
|
+
they must not contain paths, credentials, or access tokens.
|
|
354
|
+
|
|
355
|
+
A manifest digest uses the existing canonical candidate JSON/SHA-256 primitives.
|
|
356
|
+
Inventory order is immaterial; exact text, provenance, scope and owner revision
|
|
357
|
+
are bound. Content digests establish bytes, not factual truth or authorization.
|
|
358
|
+
Imported content retains `source.trust: 'untrusted'`. Skill text may be retained
|
|
359
|
+
and exposed as personal context under the caller's existing policy; this never
|
|
360
|
+
automatically activates executable resources, expands permissions, or promotes a
|
|
361
|
+
shared skill catalog. Those effects remain behind the existing profile/authority
|
|
362
|
+
and promotion gates.
|
|
363
|
+
|
|
364
|
+
`AgentLearningExport` binds one idempotent operation to the exact immutable base
|
|
365
|
+
digest, harness, and adapter ID/revision. Files are explicit observed deltas;
|
|
366
|
+
omission is not deletion, and `content: null` is a tombstone. The durable owner
|
|
367
|
+
must retain deletion evidence or refuse a tombstone it cannot persist. Retrying
|
|
368
|
+
an operation requires the same bytes and digest. A three-way merge may retain
|
|
369
|
+
unrelated concurrent edits; edit/edit or edit/delete collisions must be explicit,
|
|
370
|
+
never last-writer-wins. Apply with CAS against the latest owner revision, record
|
|
371
|
+
the durable receipt through the existing owner's transaction/journal, then
|
|
372
|
+
publish success. A plan or local checkpoint is not a remote durability receipt.
|
|
373
|
+
Rollback creates a new guarded revision; historical pins remain immutable.
|
|
374
|
+
|
|
375
|
+
#### Adding a harness adapter
|
|
376
|
+
|
|
377
|
+
1. Declare exact harness and adapter ID/revision. Import and export kinds are
|
|
378
|
+
separate explicit lists. Missing support is refused; a new harness inherits
|
|
379
|
+
no learning capability from its session, filesystem, or skill support.
|
|
380
|
+
2. Bind authenticated stable identity to actual retained storage. Define native
|
|
381
|
+
scope, lease/exclusive-access rules, resume, relocation and cleanup behavior.
|
|
382
|
+
Keep native-only state intact without exporting the whole home or credentials.
|
|
383
|
+
3. Prefer native preservation. Add portable mappings only when intentionally
|
|
384
|
+
configured and lossless for the declared subset. State which native data is
|
|
385
|
+
opaque or unsupported; do not pretend every harness field maps one-to-one.
|
|
386
|
+
4. Exercise a real filesystem fixture across write, session restart and restored
|
|
387
|
+
root; cover stale CAS, concurrent edits, explicit deletion, replay, conflict,
|
|
388
|
+
rollback, malformed/oversized input, symlinks and cross-scope isolation.
|
|
389
|
+
5. Bind `nativeState.conformanceDigest` to retained evidence and label
|
|
390
|
+
`qualification: 'fixture'` or `'native-binary'` honestly. A fixture is not proof
|
|
391
|
+
of an external CLI binary or deployed volume. Complete native-binary and
|
|
392
|
+
deployment qualification before advertising those stronger guarantees.
|
package/dist/index.d.ts
CHANGED
|
@@ -43,3 +43,4 @@ export * from "./sandbox-size.js";
|
|
|
43
43
|
export { CONTRACT_MAX_ARRAY_LENGTH, CONTRACT_MAX_CONFIDENTIAL_ATTESTATION_QUOTE_LENGTH, CONTRACT_MAX_IDENTIFIER_LENGTH, CONTRACT_MAX_JSON_BYTES, CONTRACT_MAX_JSON_DEPTH, CONTRACT_MAX_JSON_NODES, CONTRACT_MAX_MAP_ENTRIES, CONTRACT_MAX_STRING_LENGTH, boundedEventContentJsonSchema, boundedEventContentRecordSchema, boundedEventContentStringSchema, isBoundedEventContentJson, } from "./contract-limits.js";
|
|
44
44
|
export { AgentEnvironmentEgressPolicySchema } from "./environment-requests.js";
|
|
45
45
|
export * from "./native-session-event.js";
|
|
46
|
+
export * from "./learning-state.js";
|
package/dist/index.js
CHANGED
|
@@ -45,3 +45,4 @@ export {
|
|
|
45
45
|
CONTRACT_MAX_ARRAY_LENGTH, CONTRACT_MAX_CONFIDENTIAL_ATTESTATION_QUOTE_LENGTH, CONTRACT_MAX_IDENTIFIER_LENGTH, CONTRACT_MAX_JSON_BYTES, CONTRACT_MAX_JSON_DEPTH, CONTRACT_MAX_JSON_NODES, CONTRACT_MAX_MAP_ENTRIES, CONTRACT_MAX_STRING_LENGTH, boundedEventContentJsonSchema, boundedEventContentRecordSchema, boundedEventContentStringSchema, isBoundedEventContentJson, } from "./contract-limits.js";
|
|
46
46
|
export { AgentEnvironmentEgressPolicySchema } from "./environment-requests.js";
|
|
47
47
|
export * from "./native-session-event.js";
|
|
48
|
+
export * from "./learning-state.js";
|
|
@@ -0,0 +1,488 @@
|
|
|
1
|
+
/** Optional protected-home-compatible text interchange, not a universal native-memory format.
|
|
2
|
+
* Native harness memory, optional provider adapters, AgentProfile and session history retain their owners.
|
|
3
|
+
* The host authenticates identity and resolves opaque references; schemas confer no authority.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import type { Sha256Digest } from "./agent-candidate.js";
|
|
7
|
+
export declare const AgentLearningIdentitySchema: z.ZodObject<{
|
|
8
|
+
workspaceId: z.ZodString;
|
|
9
|
+
stateId: z.ZodString;
|
|
10
|
+
scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
11
|
+
kind: z.ZodLiteral<"personal">;
|
|
12
|
+
memberId: z.ZodString;
|
|
13
|
+
agentId: z.ZodString;
|
|
14
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
15
|
+
kind: z.ZodLiteral<"shared">;
|
|
16
|
+
groupId: z.ZodString;
|
|
17
|
+
agentId: z.ZodString;
|
|
18
|
+
}, z.core.$strict>], "kind">;
|
|
19
|
+
}, z.core.$strict>;
|
|
20
|
+
export type AgentLearningIdentity = z.infer<typeof AgentLearningIdentitySchema>;
|
|
21
|
+
export declare const AGENT_LEARNING_FILE_KINDS: readonly ["fact", "preference", "note", "skill-source"];
|
|
22
|
+
export type AgentLearningFileKind = (typeof AGENT_LEARNING_FILE_KINDS)[number];
|
|
23
|
+
/** Exact allowlist, never a general filesystem or configuration mount. */
|
|
24
|
+
export declare function agentLearningFileKind(path: string): AgentLearningFileKind | null;
|
|
25
|
+
export declare const AgentLearningFileSchema: z.ZodObject<{
|
|
26
|
+
path: z.ZodString;
|
|
27
|
+
kind: z.ZodEnum<{
|
|
28
|
+
fact: "fact";
|
|
29
|
+
note: "note";
|
|
30
|
+
preference: "preference";
|
|
31
|
+
"skill-source": "skill-source";
|
|
32
|
+
}>;
|
|
33
|
+
content: z.ZodNullable<z.ZodString>;
|
|
34
|
+
source: z.ZodObject<{
|
|
35
|
+
harness: z.ZodEnum<{
|
|
36
|
+
acp: "acp";
|
|
37
|
+
amp: "amp";
|
|
38
|
+
"claude-code": "claude-code";
|
|
39
|
+
"cli-base": "cli-base";
|
|
40
|
+
codex: "codex";
|
|
41
|
+
cursor: "cursor";
|
|
42
|
+
"factory-droids": "factory-droids";
|
|
43
|
+
forge: "forge";
|
|
44
|
+
gemini: "gemini";
|
|
45
|
+
hermes: "hermes";
|
|
46
|
+
"kimi-code": "kimi-code";
|
|
47
|
+
nanoclaw: "nanoclaw";
|
|
48
|
+
openclaw: "openclaw";
|
|
49
|
+
opencode: "opencode";
|
|
50
|
+
pi: "pi";
|
|
51
|
+
prime: "prime";
|
|
52
|
+
}>;
|
|
53
|
+
revision: z.ZodString;
|
|
54
|
+
trust: z.ZodLiteral<"untrusted">;
|
|
55
|
+
}, z.core.$strict>;
|
|
56
|
+
}, z.core.$strict>;
|
|
57
|
+
export type AgentLearningFile = z.infer<typeof AgentLearningFileSchema>;
|
|
58
|
+
/** A host-resolved reference to exact native state, never a path or credential value. */
|
|
59
|
+
export declare const AgentLearningNativeRefSchema: z.ZodObject<{
|
|
60
|
+
harness: z.ZodEnum<{
|
|
61
|
+
acp: "acp";
|
|
62
|
+
amp: "amp";
|
|
63
|
+
"claude-code": "claude-code";
|
|
64
|
+
"cli-base": "cli-base";
|
|
65
|
+
codex: "codex";
|
|
66
|
+
cursor: "cursor";
|
|
67
|
+
"factory-droids": "factory-droids";
|
|
68
|
+
forge: "forge";
|
|
69
|
+
gemini: "gemini";
|
|
70
|
+
hermes: "hermes";
|
|
71
|
+
"kimi-code": "kimi-code";
|
|
72
|
+
nanoclaw: "nanoclaw";
|
|
73
|
+
openclaw: "openclaw";
|
|
74
|
+
opencode: "opencode";
|
|
75
|
+
pi: "pi";
|
|
76
|
+
prime: "prime";
|
|
77
|
+
}>;
|
|
78
|
+
format: z.ZodString;
|
|
79
|
+
revision: z.ZodString;
|
|
80
|
+
reference: z.ZodString;
|
|
81
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
82
|
+
}, z.core.$strict>;
|
|
83
|
+
export type AgentLearningNativeRef = z.infer<typeof AgentLearningNativeRefSchema>;
|
|
84
|
+
declare const materialSchema: z.ZodObject<{
|
|
85
|
+
version: z.ZodLiteral<1>;
|
|
86
|
+
identity: z.ZodObject<{
|
|
87
|
+
workspaceId: z.ZodString;
|
|
88
|
+
stateId: z.ZodString;
|
|
89
|
+
scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
90
|
+
kind: z.ZodLiteral<"personal">;
|
|
91
|
+
memberId: z.ZodString;
|
|
92
|
+
agentId: z.ZodString;
|
|
93
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
94
|
+
kind: z.ZodLiteral<"shared">;
|
|
95
|
+
groupId: z.ZodString;
|
|
96
|
+
agentId: z.ZodString;
|
|
97
|
+
}, z.core.$strict>], "kind">;
|
|
98
|
+
}, z.core.$strict>;
|
|
99
|
+
revision: z.ZodString;
|
|
100
|
+
files: z.ZodArray<z.ZodObject<{
|
|
101
|
+
path: z.ZodString;
|
|
102
|
+
kind: z.ZodEnum<{
|
|
103
|
+
fact: "fact";
|
|
104
|
+
note: "note";
|
|
105
|
+
preference: "preference";
|
|
106
|
+
"skill-source": "skill-source";
|
|
107
|
+
}>;
|
|
108
|
+
content: z.ZodNullable<z.ZodString>;
|
|
109
|
+
source: z.ZodObject<{
|
|
110
|
+
harness: z.ZodEnum<{
|
|
111
|
+
acp: "acp";
|
|
112
|
+
amp: "amp";
|
|
113
|
+
"claude-code": "claude-code";
|
|
114
|
+
"cli-base": "cli-base";
|
|
115
|
+
codex: "codex";
|
|
116
|
+
cursor: "cursor";
|
|
117
|
+
"factory-droids": "factory-droids";
|
|
118
|
+
forge: "forge";
|
|
119
|
+
gemini: "gemini";
|
|
120
|
+
hermes: "hermes";
|
|
121
|
+
"kimi-code": "kimi-code";
|
|
122
|
+
nanoclaw: "nanoclaw";
|
|
123
|
+
openclaw: "openclaw";
|
|
124
|
+
opencode: "opencode";
|
|
125
|
+
pi: "pi";
|
|
126
|
+
prime: "prime";
|
|
127
|
+
}>;
|
|
128
|
+
revision: z.ZodString;
|
|
129
|
+
trust: z.ZodLiteral<"untrusted">;
|
|
130
|
+
}, z.core.$strict>;
|
|
131
|
+
}, z.core.$strict>>;
|
|
132
|
+
native: z.ZodArray<z.ZodObject<{
|
|
133
|
+
harness: z.ZodEnum<{
|
|
134
|
+
acp: "acp";
|
|
135
|
+
amp: "amp";
|
|
136
|
+
"claude-code": "claude-code";
|
|
137
|
+
"cli-base": "cli-base";
|
|
138
|
+
codex: "codex";
|
|
139
|
+
cursor: "cursor";
|
|
140
|
+
"factory-droids": "factory-droids";
|
|
141
|
+
forge: "forge";
|
|
142
|
+
gemini: "gemini";
|
|
143
|
+
hermes: "hermes";
|
|
144
|
+
"kimi-code": "kimi-code";
|
|
145
|
+
nanoclaw: "nanoclaw";
|
|
146
|
+
openclaw: "openclaw";
|
|
147
|
+
opencode: "opencode";
|
|
148
|
+
pi: "pi";
|
|
149
|
+
prime: "prime";
|
|
150
|
+
}>;
|
|
151
|
+
format: z.ZodString;
|
|
152
|
+
revision: z.ZodString;
|
|
153
|
+
reference: z.ZodString;
|
|
154
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
155
|
+
}, z.core.$strict>>;
|
|
156
|
+
}, z.core.$strict>;
|
|
157
|
+
export type AgentLearningManifestMaterial = z.infer<typeof materialSchema>;
|
|
158
|
+
/** Canonical digest ignores inventory order; file bytes and provenance remain exact. */
|
|
159
|
+
export declare function agentLearningManifestDigest(value: AgentLearningManifestMaterial): Sha256Digest;
|
|
160
|
+
export declare const AgentLearningManifestSchema: z.ZodObject<{
|
|
161
|
+
version: z.ZodLiteral<1>;
|
|
162
|
+
identity: z.ZodObject<{
|
|
163
|
+
workspaceId: z.ZodString;
|
|
164
|
+
stateId: z.ZodString;
|
|
165
|
+
scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
166
|
+
kind: z.ZodLiteral<"personal">;
|
|
167
|
+
memberId: z.ZodString;
|
|
168
|
+
agentId: z.ZodString;
|
|
169
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
170
|
+
kind: z.ZodLiteral<"shared">;
|
|
171
|
+
groupId: z.ZodString;
|
|
172
|
+
agentId: z.ZodString;
|
|
173
|
+
}, z.core.$strict>], "kind">;
|
|
174
|
+
}, z.core.$strict>;
|
|
175
|
+
revision: z.ZodString;
|
|
176
|
+
files: z.ZodArray<z.ZodObject<{
|
|
177
|
+
path: z.ZodString;
|
|
178
|
+
kind: z.ZodEnum<{
|
|
179
|
+
fact: "fact";
|
|
180
|
+
note: "note";
|
|
181
|
+
preference: "preference";
|
|
182
|
+
"skill-source": "skill-source";
|
|
183
|
+
}>;
|
|
184
|
+
content: z.ZodNullable<z.ZodString>;
|
|
185
|
+
source: z.ZodObject<{
|
|
186
|
+
harness: z.ZodEnum<{
|
|
187
|
+
acp: "acp";
|
|
188
|
+
amp: "amp";
|
|
189
|
+
"claude-code": "claude-code";
|
|
190
|
+
"cli-base": "cli-base";
|
|
191
|
+
codex: "codex";
|
|
192
|
+
cursor: "cursor";
|
|
193
|
+
"factory-droids": "factory-droids";
|
|
194
|
+
forge: "forge";
|
|
195
|
+
gemini: "gemini";
|
|
196
|
+
hermes: "hermes";
|
|
197
|
+
"kimi-code": "kimi-code";
|
|
198
|
+
nanoclaw: "nanoclaw";
|
|
199
|
+
openclaw: "openclaw";
|
|
200
|
+
opencode: "opencode";
|
|
201
|
+
pi: "pi";
|
|
202
|
+
prime: "prime";
|
|
203
|
+
}>;
|
|
204
|
+
revision: z.ZodString;
|
|
205
|
+
trust: z.ZodLiteral<"untrusted">;
|
|
206
|
+
}, z.core.$strict>;
|
|
207
|
+
}, z.core.$strict>>;
|
|
208
|
+
native: z.ZodArray<z.ZodObject<{
|
|
209
|
+
harness: z.ZodEnum<{
|
|
210
|
+
acp: "acp";
|
|
211
|
+
amp: "amp";
|
|
212
|
+
"claude-code": "claude-code";
|
|
213
|
+
"cli-base": "cli-base";
|
|
214
|
+
codex: "codex";
|
|
215
|
+
cursor: "cursor";
|
|
216
|
+
"factory-droids": "factory-droids";
|
|
217
|
+
forge: "forge";
|
|
218
|
+
gemini: "gemini";
|
|
219
|
+
hermes: "hermes";
|
|
220
|
+
"kimi-code": "kimi-code";
|
|
221
|
+
nanoclaw: "nanoclaw";
|
|
222
|
+
openclaw: "openclaw";
|
|
223
|
+
opencode: "opencode";
|
|
224
|
+
pi: "pi";
|
|
225
|
+
prime: "prime";
|
|
226
|
+
}>;
|
|
227
|
+
format: z.ZodString;
|
|
228
|
+
revision: z.ZodString;
|
|
229
|
+
reference: z.ZodString;
|
|
230
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
231
|
+
}, z.core.$strict>>;
|
|
232
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
233
|
+
}, z.core.$strict>;
|
|
234
|
+
export type AgentLearningManifest = z.infer<typeof AgentLearningManifestSchema>;
|
|
235
|
+
/** Detach and freeze an exact turn pin. A retry must persist/reuse this pin, not reread head. */
|
|
236
|
+
export declare function snapshotAgentLearningManifest(value: unknown): AgentLearningManifest;
|
|
237
|
+
declare const exportMaterialSchema: z.ZodObject<{
|
|
238
|
+
version: z.ZodLiteral<1>;
|
|
239
|
+
operationId: z.ZodString;
|
|
240
|
+
identity: z.ZodObject<{
|
|
241
|
+
workspaceId: z.ZodString;
|
|
242
|
+
stateId: z.ZodString;
|
|
243
|
+
scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
244
|
+
kind: z.ZodLiteral<"personal">;
|
|
245
|
+
memberId: z.ZodString;
|
|
246
|
+
agentId: z.ZodString;
|
|
247
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
248
|
+
kind: z.ZodLiteral<"shared">;
|
|
249
|
+
groupId: z.ZodString;
|
|
250
|
+
agentId: z.ZodString;
|
|
251
|
+
}, z.core.$strict>], "kind">;
|
|
252
|
+
}, z.core.$strict>;
|
|
253
|
+
baseDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
254
|
+
harness: z.ZodEnum<{
|
|
255
|
+
acp: "acp";
|
|
256
|
+
amp: "amp";
|
|
257
|
+
"claude-code": "claude-code";
|
|
258
|
+
"cli-base": "cli-base";
|
|
259
|
+
codex: "codex";
|
|
260
|
+
cursor: "cursor";
|
|
261
|
+
"factory-droids": "factory-droids";
|
|
262
|
+
forge: "forge";
|
|
263
|
+
gemini: "gemini";
|
|
264
|
+
hermes: "hermes";
|
|
265
|
+
"kimi-code": "kimi-code";
|
|
266
|
+
nanoclaw: "nanoclaw";
|
|
267
|
+
openclaw: "openclaw";
|
|
268
|
+
opencode: "opencode";
|
|
269
|
+
pi: "pi";
|
|
270
|
+
prime: "prime";
|
|
271
|
+
}>;
|
|
272
|
+
adapter: z.ZodObject<{
|
|
273
|
+
id: z.ZodString;
|
|
274
|
+
revision: z.ZodString;
|
|
275
|
+
}, z.core.$strict>;
|
|
276
|
+
files: z.ZodArray<z.ZodObject<{
|
|
277
|
+
path: z.ZodString;
|
|
278
|
+
kind: z.ZodEnum<{
|
|
279
|
+
fact: "fact";
|
|
280
|
+
note: "note";
|
|
281
|
+
preference: "preference";
|
|
282
|
+
"skill-source": "skill-source";
|
|
283
|
+
}>;
|
|
284
|
+
content: z.ZodNullable<z.ZodString>;
|
|
285
|
+
source: z.ZodObject<{
|
|
286
|
+
harness: z.ZodEnum<{
|
|
287
|
+
acp: "acp";
|
|
288
|
+
amp: "amp";
|
|
289
|
+
"claude-code": "claude-code";
|
|
290
|
+
"cli-base": "cli-base";
|
|
291
|
+
codex: "codex";
|
|
292
|
+
cursor: "cursor";
|
|
293
|
+
"factory-droids": "factory-droids";
|
|
294
|
+
forge: "forge";
|
|
295
|
+
gemini: "gemini";
|
|
296
|
+
hermes: "hermes";
|
|
297
|
+
"kimi-code": "kimi-code";
|
|
298
|
+
nanoclaw: "nanoclaw";
|
|
299
|
+
openclaw: "openclaw";
|
|
300
|
+
opencode: "opencode";
|
|
301
|
+
pi: "pi";
|
|
302
|
+
prime: "prime";
|
|
303
|
+
}>;
|
|
304
|
+
revision: z.ZodString;
|
|
305
|
+
trust: z.ZodLiteral<"untrusted">;
|
|
306
|
+
}, z.core.$strict>;
|
|
307
|
+
}, z.core.$strict>>;
|
|
308
|
+
native: z.ZodArray<z.ZodObject<{
|
|
309
|
+
harness: z.ZodEnum<{
|
|
310
|
+
acp: "acp";
|
|
311
|
+
amp: "amp";
|
|
312
|
+
"claude-code": "claude-code";
|
|
313
|
+
"cli-base": "cli-base";
|
|
314
|
+
codex: "codex";
|
|
315
|
+
cursor: "cursor";
|
|
316
|
+
"factory-droids": "factory-droids";
|
|
317
|
+
forge: "forge";
|
|
318
|
+
gemini: "gemini";
|
|
319
|
+
hermes: "hermes";
|
|
320
|
+
"kimi-code": "kimi-code";
|
|
321
|
+
nanoclaw: "nanoclaw";
|
|
322
|
+
openclaw: "openclaw";
|
|
323
|
+
opencode: "opencode";
|
|
324
|
+
pi: "pi";
|
|
325
|
+
prime: "prime";
|
|
326
|
+
}>;
|
|
327
|
+
format: z.ZodString;
|
|
328
|
+
revision: z.ZodString;
|
|
329
|
+
reference: z.ZodString;
|
|
330
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
331
|
+
}, z.core.$strict>>;
|
|
332
|
+
}, z.core.$strict>;
|
|
333
|
+
export type AgentLearningExportMaterial = z.infer<typeof exportMaterialSchema>;
|
|
334
|
+
export declare function agentLearningExportDigest(value: AgentLearningExportMaterial): Sha256Digest;
|
|
335
|
+
export declare const AgentLearningExportSchema: z.ZodObject<{
|
|
336
|
+
version: z.ZodLiteral<1>;
|
|
337
|
+
operationId: z.ZodString;
|
|
338
|
+
identity: z.ZodObject<{
|
|
339
|
+
workspaceId: z.ZodString;
|
|
340
|
+
stateId: z.ZodString;
|
|
341
|
+
scope: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
342
|
+
kind: z.ZodLiteral<"personal">;
|
|
343
|
+
memberId: z.ZodString;
|
|
344
|
+
agentId: z.ZodString;
|
|
345
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
346
|
+
kind: z.ZodLiteral<"shared">;
|
|
347
|
+
groupId: z.ZodString;
|
|
348
|
+
agentId: z.ZodString;
|
|
349
|
+
}, z.core.$strict>], "kind">;
|
|
350
|
+
}, z.core.$strict>;
|
|
351
|
+
baseDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
352
|
+
harness: z.ZodEnum<{
|
|
353
|
+
acp: "acp";
|
|
354
|
+
amp: "amp";
|
|
355
|
+
"claude-code": "claude-code";
|
|
356
|
+
"cli-base": "cli-base";
|
|
357
|
+
codex: "codex";
|
|
358
|
+
cursor: "cursor";
|
|
359
|
+
"factory-droids": "factory-droids";
|
|
360
|
+
forge: "forge";
|
|
361
|
+
gemini: "gemini";
|
|
362
|
+
hermes: "hermes";
|
|
363
|
+
"kimi-code": "kimi-code";
|
|
364
|
+
nanoclaw: "nanoclaw";
|
|
365
|
+
openclaw: "openclaw";
|
|
366
|
+
opencode: "opencode";
|
|
367
|
+
pi: "pi";
|
|
368
|
+
prime: "prime";
|
|
369
|
+
}>;
|
|
370
|
+
adapter: z.ZodObject<{
|
|
371
|
+
id: z.ZodString;
|
|
372
|
+
revision: z.ZodString;
|
|
373
|
+
}, z.core.$strict>;
|
|
374
|
+
files: z.ZodArray<z.ZodObject<{
|
|
375
|
+
path: z.ZodString;
|
|
376
|
+
kind: z.ZodEnum<{
|
|
377
|
+
fact: "fact";
|
|
378
|
+
note: "note";
|
|
379
|
+
preference: "preference";
|
|
380
|
+
"skill-source": "skill-source";
|
|
381
|
+
}>;
|
|
382
|
+
content: z.ZodNullable<z.ZodString>;
|
|
383
|
+
source: z.ZodObject<{
|
|
384
|
+
harness: z.ZodEnum<{
|
|
385
|
+
acp: "acp";
|
|
386
|
+
amp: "amp";
|
|
387
|
+
"claude-code": "claude-code";
|
|
388
|
+
"cli-base": "cli-base";
|
|
389
|
+
codex: "codex";
|
|
390
|
+
cursor: "cursor";
|
|
391
|
+
"factory-droids": "factory-droids";
|
|
392
|
+
forge: "forge";
|
|
393
|
+
gemini: "gemini";
|
|
394
|
+
hermes: "hermes";
|
|
395
|
+
"kimi-code": "kimi-code";
|
|
396
|
+
nanoclaw: "nanoclaw";
|
|
397
|
+
openclaw: "openclaw";
|
|
398
|
+
opencode: "opencode";
|
|
399
|
+
pi: "pi";
|
|
400
|
+
prime: "prime";
|
|
401
|
+
}>;
|
|
402
|
+
revision: z.ZodString;
|
|
403
|
+
trust: z.ZodLiteral<"untrusted">;
|
|
404
|
+
}, z.core.$strict>;
|
|
405
|
+
}, z.core.$strict>>;
|
|
406
|
+
native: z.ZodArray<z.ZodObject<{
|
|
407
|
+
harness: z.ZodEnum<{
|
|
408
|
+
acp: "acp";
|
|
409
|
+
amp: "amp";
|
|
410
|
+
"claude-code": "claude-code";
|
|
411
|
+
"cli-base": "cli-base";
|
|
412
|
+
codex: "codex";
|
|
413
|
+
cursor: "cursor";
|
|
414
|
+
"factory-droids": "factory-droids";
|
|
415
|
+
forge: "forge";
|
|
416
|
+
gemini: "gemini";
|
|
417
|
+
hermes: "hermes";
|
|
418
|
+
"kimi-code": "kimi-code";
|
|
419
|
+
nanoclaw: "nanoclaw";
|
|
420
|
+
openclaw: "openclaw";
|
|
421
|
+
opencode: "opencode";
|
|
422
|
+
pi: "pi";
|
|
423
|
+
prime: "prime";
|
|
424
|
+
}>;
|
|
425
|
+
format: z.ZodString;
|
|
426
|
+
revision: z.ZodString;
|
|
427
|
+
reference: z.ZodString;
|
|
428
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
429
|
+
}, z.core.$strict>>;
|
|
430
|
+
digest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
431
|
+
}, z.core.$strict>;
|
|
432
|
+
export type AgentLearningExport = z.infer<typeof AgentLearningExportSchema>;
|
|
433
|
+
/** Capabilities are properties of a particular adapter and tested format, not harness folklore. */
|
|
434
|
+
export declare const AgentLearningCapabilitiesSchema: z.ZodObject<{
|
|
435
|
+
version: z.ZodLiteral<1>;
|
|
436
|
+
harness: z.ZodEnum<{
|
|
437
|
+
acp: "acp";
|
|
438
|
+
amp: "amp";
|
|
439
|
+
"claude-code": "claude-code";
|
|
440
|
+
"cli-base": "cli-base";
|
|
441
|
+
codex: "codex";
|
|
442
|
+
cursor: "cursor";
|
|
443
|
+
"factory-droids": "factory-droids";
|
|
444
|
+
forge: "forge";
|
|
445
|
+
gemini: "gemini";
|
|
446
|
+
hermes: "hermes";
|
|
447
|
+
"kimi-code": "kimi-code";
|
|
448
|
+
nanoclaw: "nanoclaw";
|
|
449
|
+
openclaw: "openclaw";
|
|
450
|
+
opencode: "opencode";
|
|
451
|
+
pi: "pi";
|
|
452
|
+
prime: "prime";
|
|
453
|
+
}>;
|
|
454
|
+
adapter: z.ZodObject<{
|
|
455
|
+
id: z.ZodString;
|
|
456
|
+
revision: z.ZodString;
|
|
457
|
+
}, z.core.$strict>;
|
|
458
|
+
importKinds: z.ZodArray<z.ZodEnum<{
|
|
459
|
+
fact: "fact";
|
|
460
|
+
note: "note";
|
|
461
|
+
preference: "preference";
|
|
462
|
+
"skill-source": "skill-source";
|
|
463
|
+
}>>;
|
|
464
|
+
exportKinds: z.ZodArray<z.ZodEnum<{
|
|
465
|
+
fact: "fact";
|
|
466
|
+
note: "note";
|
|
467
|
+
preference: "preference";
|
|
468
|
+
"skill-source": "skill-source";
|
|
469
|
+
}>>;
|
|
470
|
+
nativeState: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
471
|
+
status: z.ZodLiteral<"unsupported">;
|
|
472
|
+
reason: z.ZodString;
|
|
473
|
+
}, z.core.$strict>, z.ZodObject<{
|
|
474
|
+
status: z.ZodLiteral<"preserved">;
|
|
475
|
+
format: z.ZodString;
|
|
476
|
+
conformanceDigest: z.ZodType<`sha256:${string}`, unknown, z.core.$ZodTypeInternals<`sha256:${string}`, unknown>>;
|
|
477
|
+
qualification: z.ZodEnum<{
|
|
478
|
+
fixture: "fixture";
|
|
479
|
+
"native-binary": "native-binary";
|
|
480
|
+
}>;
|
|
481
|
+
}, z.core.$strict>], "status">;
|
|
482
|
+
}, z.core.$strict>;
|
|
483
|
+
export type AgentLearningCapabilities = z.infer<typeof AgentLearningCapabilitiesSchema>;
|
|
484
|
+
/** No capability by omission. Text preservation does not activate executable skills or profile authority. */
|
|
485
|
+
export declare function unsupportedAgentLearningCapabilities(input: Pick<AgentLearningCapabilities, "harness" | "adapter"> & {
|
|
486
|
+
reason: string;
|
|
487
|
+
}): AgentLearningCapabilities;
|
|
488
|
+
export {};
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
/** Optional protected-home-compatible text interchange, not a universal native-memory format.
|
|
2
|
+
* Native harness memory, optional provider adapters, AgentProfile and session history retain their owners.
|
|
3
|
+
* The host authenticates identity and resolves opaque references; schemas confer no authority.
|
|
4
|
+
*/
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { canonicalCandidateDigest, isWellFormedUnicode, sha256DigestSchema } from "./agent-candidate-schema-common.js";
|
|
7
|
+
import { harnessTypeSchema } from "./harness.js";
|
|
8
|
+
import { deepFreeze } from "./deep-freeze.js";
|
|
9
|
+
const id = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/);
|
|
10
|
+
const revision = z.string().min(1).max(128).regex(/^[A-Za-z0-9][A-Za-z0-9._:-]*$/);
|
|
11
|
+
const adapter = z.strictObject({ id, revision });
|
|
12
|
+
export const AgentLearningIdentitySchema = z.strictObject({
|
|
13
|
+
workspaceId: id,
|
|
14
|
+
stateId: id,
|
|
15
|
+
scope: z.discriminatedUnion("kind", [
|
|
16
|
+
z.strictObject({ kind: z.literal("personal"), memberId: id, agentId: id }),
|
|
17
|
+
z.strictObject({ kind: z.literal("shared"), groupId: id, agentId: id }),
|
|
18
|
+
]),
|
|
19
|
+
});
|
|
20
|
+
export const AGENT_LEARNING_FILE_KINDS = ["fact", "preference", "note", "skill-source"];
|
|
21
|
+
const fileKind = z.enum(AGENT_LEARNING_FILE_KINDS);
|
|
22
|
+
/** Exact allowlist, never a general filesystem or configuration mount. */
|
|
23
|
+
export function agentLearningFileKind(path) {
|
|
24
|
+
if (path === "MEMORY.md")
|
|
25
|
+
return "fact";
|
|
26
|
+
if (path === "USER.md")
|
|
27
|
+
return "preference";
|
|
28
|
+
if (/^skills\/[a-z0-9][a-z0-9-]{0,63}\/SKILL\.md$/.test(path))
|
|
29
|
+
return "skill-source";
|
|
30
|
+
const note = /^memory\/(\d{4}-\d{2}-\d{2})\.md$/.exec(path);
|
|
31
|
+
if (note) {
|
|
32
|
+
const date = new Date(`${note[1]}T00:00:00.000Z`);
|
|
33
|
+
if (Number.isFinite(date.getTime()) && date.toISOString().slice(0, 10) === note[1])
|
|
34
|
+
return "note";
|
|
35
|
+
}
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
export const AgentLearningFileSchema = z.strictObject({
|
|
39
|
+
path: z.string().min(1).max(100),
|
|
40
|
+
kind: fileKind,
|
|
41
|
+
/** Null is an explicit tombstone. Omission from an export never deletes a file. */
|
|
42
|
+
content: z.string().max(131_072).refine(isWellFormedUnicode).nullable(),
|
|
43
|
+
source: z.strictObject({
|
|
44
|
+
harness: harnessTypeSchema,
|
|
45
|
+
revision,
|
|
46
|
+
/** Origin metadata is evidence of provenance, not truth or trusted instructions. */
|
|
47
|
+
trust: z.literal("untrusted"),
|
|
48
|
+
}),
|
|
49
|
+
}).superRefine((file, ctx) => {
|
|
50
|
+
if (agentLearningFileKind(file.path) !== file.kind) {
|
|
51
|
+
ctx.addIssue({ code: "custom", path: ["path"], message: "learned file path does not match its portable kind" });
|
|
52
|
+
}
|
|
53
|
+
const limits = { fact: 16_000, preference: 4_000, note: 12_000, "skill-source": 32_000 };
|
|
54
|
+
if (file.content !== null && [...file.content].length > limits[file.kind]) {
|
|
55
|
+
ctx.addIssue({ code: "custom", path: ["content"], message: "learned file exceeds its character budget" });
|
|
56
|
+
}
|
|
57
|
+
});
|
|
58
|
+
/** A host-resolved reference to exact native state, never a path or credential value. */
|
|
59
|
+
export const AgentLearningNativeRefSchema = z.strictObject({
|
|
60
|
+
harness: harnessTypeSchema,
|
|
61
|
+
format: id,
|
|
62
|
+
revision,
|
|
63
|
+
reference: id,
|
|
64
|
+
digest: sha256DigestSchema,
|
|
65
|
+
});
|
|
66
|
+
const files = z.array(AgentLearningFileSchema).max(1_024).superRefine((value, ctx) => {
|
|
67
|
+
if (new Set(value.map((file) => file.path)).size !== value.length) {
|
|
68
|
+
ctx.addIssue({ code: "custom", message: "learned file paths must be unique" });
|
|
69
|
+
}
|
|
70
|
+
if (value.reduce((size, file) => size + new TextEncoder().encode(file.content ?? "").length, 0) > 8 * 1024 * 1024) {
|
|
71
|
+
ctx.addIssue({ code: "custom", message: "learned state exceeds its byte budget" });
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
const native = z.array(AgentLearningNativeRefSchema).max(64).superRefine((value, ctx) => {
|
|
75
|
+
if (new Set(value.map((ref) => `${ref.harness}:${ref.format}`)).size !== value.length) {
|
|
76
|
+
ctx.addIssue({ code: "custom", message: "native state references must be unique by harness and format" });
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
const materialSchema = z.strictObject({
|
|
80
|
+
version: z.literal(1),
|
|
81
|
+
identity: AgentLearningIdentitySchema,
|
|
82
|
+
/** Exact existing owner revision (e.g. protected-home Git commit), not a second revision store. */
|
|
83
|
+
revision,
|
|
84
|
+
files,
|
|
85
|
+
native,
|
|
86
|
+
});
|
|
87
|
+
/** Canonical digest ignores inventory order; file bytes and provenance remain exact. */
|
|
88
|
+
export function agentLearningManifestDigest(value) {
|
|
89
|
+
const parsed = materialSchema.parse(value);
|
|
90
|
+
return canonicalCandidateDigest({ ...parsed,
|
|
91
|
+
files: [...parsed.files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0),
|
|
92
|
+
native: [...parsed.native].sort((a, b) => `${a.harness}:${a.format}` < `${b.harness}:${b.format}` ? -1 : 1),
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
export const AgentLearningManifestSchema = materialSchema.extend({ digest: sha256DigestSchema })
|
|
96
|
+
.superRefine(({ digest, ...material }, ctx) => {
|
|
97
|
+
if (ctx.issues.length)
|
|
98
|
+
return;
|
|
99
|
+
if (digest !== agentLearningManifestDigest(material)) {
|
|
100
|
+
ctx.addIssue({ code: "custom", path: ["digest"], message: "learned manifest digest does not match its material" });
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
/** Detach and freeze an exact turn pin. A retry must persist/reuse this pin, not reread head. */
|
|
104
|
+
export function snapshotAgentLearningManifest(value) {
|
|
105
|
+
return deepFreeze(AgentLearningManifestSchema.parse(structuredClone(value)));
|
|
106
|
+
}
|
|
107
|
+
const exportMaterialSchema = z.strictObject({
|
|
108
|
+
version: z.literal(1),
|
|
109
|
+
operationId: id,
|
|
110
|
+
identity: AgentLearningIdentitySchema,
|
|
111
|
+
baseDigest: sha256DigestSchema,
|
|
112
|
+
harness: harnessTypeSchema,
|
|
113
|
+
adapter,
|
|
114
|
+
/** Explicit deltas only. Never infer deletion from absence or a partial native listing. */
|
|
115
|
+
files,
|
|
116
|
+
native,
|
|
117
|
+
});
|
|
118
|
+
export function agentLearningExportDigest(value) {
|
|
119
|
+
const parsed = exportMaterialSchema.parse(value);
|
|
120
|
+
return canonicalCandidateDigest({ ...parsed,
|
|
121
|
+
files: [...parsed.files].sort((a, b) => a.path < b.path ? -1 : a.path > b.path ? 1 : 0),
|
|
122
|
+
native: [...parsed.native].sort((a, b) => `${a.harness}:${a.format}` < `${b.harness}:${b.format}` ? -1 : 1),
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
export const AgentLearningExportSchema = exportMaterialSchema.extend({ digest: sha256DigestSchema })
|
|
126
|
+
.superRefine(({ digest, ...material }, ctx) => {
|
|
127
|
+
if (ctx.issues.length)
|
|
128
|
+
return;
|
|
129
|
+
if (digest !== agentLearningExportDigest(material)) {
|
|
130
|
+
ctx.addIssue({ code: "custom", path: ["digest"], message: "learned export digest does not match its material" });
|
|
131
|
+
}
|
|
132
|
+
if (material.files.some((file) => file.source.harness !== material.harness) || material.native.some((ref) => ref.harness !== material.harness)) {
|
|
133
|
+
ctx.addIssue({ code: "custom", message: "export provenance must name its declared harness" });
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
const kinds = z.array(fileKind).max(AGENT_LEARNING_FILE_KINDS.length).refine((value) => new Set(value).size === value.length);
|
|
137
|
+
/** Capabilities are properties of a particular adapter and tested format, not harness folklore. */
|
|
138
|
+
export const AgentLearningCapabilitiesSchema = z.strictObject({
|
|
139
|
+
version: z.literal(1),
|
|
140
|
+
harness: harnessTypeSchema,
|
|
141
|
+
adapter,
|
|
142
|
+
importKinds: kinds,
|
|
143
|
+
exportKinds: kinds,
|
|
144
|
+
nativeState: z.discriminatedUnion("status", [
|
|
145
|
+
z.strictObject({ status: z.literal("unsupported"), reason: z.string().min(1).max(512) }),
|
|
146
|
+
z.strictObject({ status: z.literal("preserved"), format: id, conformanceDigest: sha256DigestSchema,
|
|
147
|
+
qualification: z.enum(["fixture", "native-binary"]) }),
|
|
148
|
+
]),
|
|
149
|
+
});
|
|
150
|
+
/** No capability by omission. Text preservation does not activate executable skills or profile authority. */
|
|
151
|
+
export function unsupportedAgentLearningCapabilities(input) {
|
|
152
|
+
return deepFreeze(AgentLearningCapabilitiesSchema.parse({ version: 1, harness: input.harness, adapter: input.adapter, importKinds: [], exportKinds: [],
|
|
153
|
+
nativeState: { status: "unsupported", reason: input.reason } }));
|
|
154
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tangle-network/agent-interface",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"sideEffects": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -61,6 +61,11 @@
|
|
|
61
61
|
"import": "./dist/profile-kb/index.js",
|
|
62
62
|
"types": "./dist/profile-kb/index.d.ts",
|
|
63
63
|
"default": "./dist/profile-kb/index.js"
|
|
64
|
+
},
|
|
65
|
+
"./learning-state": {
|
|
66
|
+
"import": "./dist/learning-state.js",
|
|
67
|
+
"types": "./dist/learning-state.d.ts",
|
|
68
|
+
"default": "./dist/learning-state.js"
|
|
64
69
|
}
|
|
65
70
|
},
|
|
66
71
|
"repository": {
|