@guuey/threads 0.16.6 → 0.16.8
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/dist/fold-rows.d.ts +17 -1
- package/dist/fold-rows.d.ts.map +1 -1
- package/dist/fold-rows.js +40 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/rows.d.ts +9 -0
- package/dist/rows.d.ts.map +1 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +7 -2
- package/dist/testing/contract-suite.d.ts.map +1 -1
- package/dist/testing/contract-suite.js +20 -0
- package/package.json +3 -3
package/dist/fold-rows.d.ts
CHANGED
|
@@ -25,7 +25,23 @@ export declare function agMessageToRow(msg: AgMessage, ctx: RowCtx & {
|
|
|
25
25
|
turnRecord?: AgTurnRecord;
|
|
26
26
|
}): ThreadMessageRow;
|
|
27
27
|
export declare function uiCardArtifactsFromMessages(messages: AgMessage[]): AgArtifact[];
|
|
28
|
-
|
|
28
|
+
/**
|
|
29
|
+
* toolCallId → tool name, read off every `tool-call` block in the fold's
|
|
30
|
+
* messages (guuey#402). The name rides ONLY the tool-call block; results
|
|
31
|
+
* carry just the id, so this map is how a card row learns which tool
|
|
32
|
+
* produced it. First writer wins on a duplicate id (ids are unique per
|
|
33
|
+
* provider contract; a collision would be the provider's bug).
|
|
34
|
+
*/
|
|
35
|
+
export declare function toolNamesByCallId(messages: AgMessage[]): Map<string, string>;
|
|
36
|
+
/**
|
|
37
|
+
* The producing tool's name for a card artifact: the first tool-result part
|
|
38
|
+
* whose `toolCallId` the fold's tool-call blocks named (guuey#402).
|
|
39
|
+
* `undefined` when unresolvable — a first-class `artifact.*` event with no
|
|
40
|
+
* tool-result part, or a call outside this fold. Callers persist absence,
|
|
41
|
+
* never a guess (humanization and fallbacks are the kit's, one owner).
|
|
42
|
+
*/
|
|
43
|
+
export declare function producingToolName(art: AgArtifact, toolNames: ReadonlyMap<string, string>): string | undefined;
|
|
44
|
+
export declare function agArtifactToCardRow(art: AgArtifact, ctx: RowCtx, toolName?: string): ThreadMessageRow;
|
|
29
45
|
/**
|
|
30
46
|
* Reconstruct an AgMessage from a row. Agent-fold rows store the verbatim
|
|
31
47
|
* AgMessage in `content`; user/system rows (persisted up-front) store plain
|
package/dist/fold-rows.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fold-rows.d.ts","sourceRoot":"","sources":["../src/fold-rows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,YAAY,EAEZ,cAAc,EACd,OAAO,EACP,cAAc,EACd,SAAS,EACV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,gBAAgB,EAAwC,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3G,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;CACzB;AASD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAMlD;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,MAAM,GAAG;IAAE,UAAU,CAAC,EAAE,YAAY,CAAA;CAAE,GAC1C,gBAAgB,CAyBlB;AAkDD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAmC/E;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,GAAG,gBAAgB,
|
|
1
|
+
{"version":3,"file":"fold-rows.d.ts","sourceRoot":"","sources":["../src/fold-rows.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EACV,SAAS,EACT,UAAU,EACV,YAAY,EAEZ,cAAc,EACd,OAAO,EACP,cAAc,EACd,SAAS,EACV,MAAM,sBAAsB,CAAC;AAE9B,OAAO,KAAK,EAAE,gBAAgB,EAAwC,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAG3G,MAAM,WAAW,MAAM;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,EAAE,EAAE,MAAM,CAAC;IACX,eAAe,EAAE,MAAM,CAAC;CACzB;AASD;;;;;;GAMG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,CAMlD;AAED,wBAAgB,cAAc,CAC5B,GAAG,EAAE,SAAS,EACd,GAAG,EAAE,MAAM,GAAG;IAAE,UAAU,CAAC,EAAE,YAAY,CAAA;CAAE,GAC1C,gBAAgB,CAyBlB;AAkDD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,UAAU,EAAE,CAmC/E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAU5E;AAED;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,UAAU,EACf,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GACrC,MAAM,GAAG,SAAS,CAQpB;AAED,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,UAAU,EAAE,GAAG,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,gBAAgB,CAyBrG;AAOD;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,gBAAgB,GAAG,SAAS,CAY/D;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,gBAAgB,GAAG,UAAU,GAAG,SAAS,CAMjF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,gBAAgB,EAAE,EACxB,QAAQ,EAAE,iBAAiB,GAAG,SAAS,GACtC,cAAc,CA2BhB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,SAAS,GAAG,SAAS,EACjC,iBAAiB,EAAE,cAAc,EAAE,GAClC,OAAO,EAAE,CAmBX"}
|
package/dist/fold-rows.js
CHANGED
|
@@ -130,7 +130,42 @@ export function uiCardArtifactsFromMessages(messages) {
|
|
|
130
130
|
}
|
|
131
131
|
return artifacts;
|
|
132
132
|
}
|
|
133
|
-
|
|
133
|
+
/**
|
|
134
|
+
* toolCallId → tool name, read off every `tool-call` block in the fold's
|
|
135
|
+
* messages (guuey#402). The name rides ONLY the tool-call block; results
|
|
136
|
+
* carry just the id, so this map is how a card row learns which tool
|
|
137
|
+
* produced it. First writer wins on a duplicate id (ids are unique per
|
|
138
|
+
* provider contract; a collision would be the provider's bug).
|
|
139
|
+
*/
|
|
140
|
+
export function toolNamesByCallId(messages) {
|
|
141
|
+
const names = new Map();
|
|
142
|
+
for (const msg of messages) {
|
|
143
|
+
for (const block of msg.content) {
|
|
144
|
+
if (block.type === "tool-call" && !names.has(block.toolCallId)) {
|
|
145
|
+
names.set(block.toolCallId, block.name);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return names;
|
|
150
|
+
}
|
|
151
|
+
/**
|
|
152
|
+
* The producing tool's name for a card artifact: the first tool-result part
|
|
153
|
+
* whose `toolCallId` the fold's tool-call blocks named (guuey#402).
|
|
154
|
+
* `undefined` when unresolvable — a first-class `artifact.*` event with no
|
|
155
|
+
* tool-result part, or a call outside this fold. Callers persist absence,
|
|
156
|
+
* never a guess (humanization and fallbacks are the kit's, one owner).
|
|
157
|
+
*/
|
|
158
|
+
export function producingToolName(art, toolNames) {
|
|
159
|
+
for (const part of art.parts) {
|
|
160
|
+
if (isJsonObjectLike(part) && part.type === "tool-result" && typeof part.toolCallId === "string") {
|
|
161
|
+
const name = toolNames.get(part.toolCallId);
|
|
162
|
+
if (name !== undefined)
|
|
163
|
+
return name;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return undefined;
|
|
167
|
+
}
|
|
168
|
+
export function agArtifactToCardRow(art, ctx, toolName) {
|
|
134
169
|
// guuey#122: the projection lane strips tool-result _meta upstream, but
|
|
135
170
|
// REAL artifact.* events land here verbatim — apply the same persistence
|
|
136
171
|
// boundary to any tool-result-typed part (and the artifact-level _meta),
|
|
@@ -148,6 +183,10 @@ export function agArtifactToCardRow(art, ctx) {
|
|
|
148
183
|
authorRole: "agent",
|
|
149
184
|
content: { producedInTurnId: art.turnId },
|
|
150
185
|
cardSnapshot: snapshot,
|
|
186
|
+
// guuey#402: the RAW producing tool name, resolved by the caller from
|
|
187
|
+
// the fold's tool-call blocks. Absent stays absent — old rows and
|
|
188
|
+
// unresolvable producers keep the reader's fallback honest.
|
|
189
|
+
...(toolName !== undefined ? { toolName } : {}),
|
|
151
190
|
};
|
|
152
191
|
}
|
|
153
192
|
/** Local structural check (narrow enough for the strip dispatch above). */
|
package/dist/index.d.ts
CHANGED
|
@@ -21,5 +21,5 @@ export type { StoredHistoryMessage, ThreadMessageKind, ThreadMessageRole, Thread
|
|
|
21
21
|
export { ThreadStore, type AppendFoldInput, type AppendFoldResult, type AppendMessageInput, type AppendMessageResult, type EnsureThreadInput, } from "./store.js";
|
|
22
22
|
export { InMemoryThreadPersistence } from "./in-memory.js";
|
|
23
23
|
export { HttpThreadPersistence, HttpThreadStoreError, type HttpThreadPersistenceOptions, type ThreadScope, } from "./http.js";
|
|
24
|
-
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageText, reassembleFold, rowToAgMessage, seedEventsForReducer, uiCardArtifactsFromMessages, type RowCtx, } from "./fold-rows.js";
|
|
24
|
+
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageText, producingToolName, reassembleFold, rowToAgMessage, seedEventsForReducer, toolNamesByCallId, uiCardArtifactsFromMessages, type RowCtx, } from "./fold-rows.js";
|
|
25
25
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,4BAA4B,EACjC,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,2BAA2B,EAC3B,KAAK,MAAM,GACZ,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,iBAAiB,GAClB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,WAAW,EACX,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACrB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,GACvB,MAAM,YAAY,CAAC;AACpB,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,4BAA4B,EACjC,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,WAAW,EACX,iBAAiB,EACjB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,iBAAiB,EACjB,2BAA2B,EAC3B,KAAK,MAAM,GACZ,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
export { ThreadStore, } from "./store.js";
|
|
2
2
|
export { InMemoryThreadPersistence } from "./in-memory.js";
|
|
3
3
|
export { HttpThreadPersistence, HttpThreadStoreError, } from "./http.js";
|
|
4
|
-
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageText, reassembleFold, rowToAgMessage, seedEventsForReducer, uiCardArtifactsFromMessages, } from "./fold-rows.js";
|
|
4
|
+
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageText, producingToolName, reassembleFold, rowToAgMessage, seedEventsForReducer, toolNamesByCallId, uiCardArtifactsFromMessages, } from "./fold-rows.js";
|
package/dist/rows.d.ts
CHANGED
|
@@ -40,6 +40,15 @@ export interface ThreadMessageRow {
|
|
|
40
40
|
content?: unknown;
|
|
41
41
|
/** Verbatim `AgArtifact` stored on kind='card' rows. */
|
|
42
42
|
cardSnapshot?: unknown;
|
|
43
|
+
/**
|
|
44
|
+
* The producing tool's RAW wire name on kind='card' rows (guuey#402) —
|
|
45
|
+
* resolved at fold time from the paired `tool-call` block, which is the
|
|
46
|
+
* only place the name rides (the tool-RESULT block carries just the
|
|
47
|
+
* `toolCallId`). Raw on purpose: humanization is the kit's #307 voice
|
|
48
|
+
* layer, one owner. Absent on pre-enabler rows and when the producing
|
|
49
|
+
* call is not in the fold — readers fall back, never invent.
|
|
50
|
+
*/
|
|
51
|
+
toolName?: string;
|
|
43
52
|
/** `AgTurnRecord` stored on agent-fold rows for context recovery. */
|
|
44
53
|
aiContext?: unknown;
|
|
45
54
|
}
|
package/dist/rows.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAQ3D,OAAO,KAAK,EACV,oBAAoB,EACpB,iBAAiB,EACjB,iBAAiB,EAEjB,qBAAqB,EAErB,iBAAiB,EAClB,MAAM,WAAW,CAAC;AAOnB,MAAM,WAAW,iBAAiB;IAChC,yEAAyE;IACzE,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,yCAAyC;IACzC,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,wEAAwE;IACxE,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,iBAAiB,CAAC;IACxB,yEAAyE;IACzE,OAAO,EAAE,OAAO,CAAC;IACjB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,+EAA+E;IAC/E,eAAe,EAAE,MAAM,CAAC;IACxB,IAAI,CAAC,EAAE,iBAAiB,CAAC;CAC1B;AAED,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,MAAM,CAAC;IACZ,0EAA0E;IAC1E,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,cAAc,CAAC;IACrB,2EAA2E;IAC3E,mBAAmB,EAAE,MAAM,CAAC;IAC5B;;;;;OAKG;IACH,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,MAAM,WAAW,gBAAgB;IAC/B,WAAW,EAAE,MAAM,EAAE,CAAC;IACtB,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,kEAAkE;IAClE,oBAAoB,EAAE,MAAM,CAAC;IAC7B;;;OAGG;IACH,OAAO,EAAE,OAAO,CAAC;CAClB;AAMD,qBAAa,WAAW;IACV,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,qBAAqB;IAEtD;;;;;;;;;;;;;OAaG;IACG,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IA4B7D;;;;;;;OAOG;IACG,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKpE,4EAA4E;IACtE,WAAW,CACf,QAAQ,EAAE,MAAM,EAChB,KAAK,GAAE,MAA8B,GACpC,OAAO,CAAC,oBAAoB,EAAE,CAAC;IAqBlC;;;;OAIG;IACG,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,OAAO,CAAC,mBAAmB,CAAC;IA4B5E,+EAA+E;IACzE,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC;IAI3E;;;;;;;;;;;;;;;;;OAiBG;IACG,UAAU,CAAC,KAAK,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAyFpE"}
|
package/dist/store.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* DynamoDB).
|
|
9
9
|
*/
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
|
-
import { agMessageToRow, agArtifactToCardRow, uiCardArtifactsFromMessages } from "./fold-rows.js";
|
|
11
|
+
import { agMessageToRow, agArtifactToCardRow, producingToolName, toolNamesByCallId, uiCardArtifactsFromMessages, } from "./fold-rows.js";
|
|
12
12
|
/** Max history messages fed back as context — bounds latency on long threads. */
|
|
13
13
|
const DEFAULT_HISTORY_LIMIT = 40;
|
|
14
14
|
const PREVIEW_MAX_LEN = 240;
|
|
@@ -186,13 +186,18 @@ export class ThreadStore {
|
|
|
186
186
|
const knownArtifactIds = new Set(fold.artifacts.map((a) => a.artifactId));
|
|
187
187
|
const projected = uiCardArtifactsFromMessages(fold.messages).filter((a) => !knownArtifactIds.has(a.artifactId));
|
|
188
188
|
const cardArtifacts = [...fold.artifacts, ...projected];
|
|
189
|
+
// guuey#402: the fold has the tool-CALL blocks in hand — the only place
|
|
190
|
+
// the producing tool's name rides — so resolve it here and persist it
|
|
191
|
+
// beside the snapshot. Unresolvable (a first-class artifact event with
|
|
192
|
+
// no tool-result part) persists no name; readers fall back.
|
|
193
|
+
const toolNames = toolNamesByCallId(fold.messages);
|
|
189
194
|
for (let i = 0; i < cardArtifacts.length; i++) {
|
|
190
195
|
const art = cardArtifacts[i];
|
|
191
196
|
const clientMessageId = sentinelClaimed ? `${clientMessageIdBase}#card#${i}` : sentinelKey;
|
|
192
197
|
sentinelClaimed = true;
|
|
193
198
|
const now = new Date().toISOString();
|
|
194
199
|
const seq = await this.db.incrementSeq(threadId, art.name ?? null, now);
|
|
195
|
-
await this.db.putMessage(agArtifactToCardRow(art, { threadId, userId, seq, at: now, clientMessageId }));
|
|
200
|
+
await this.db.putMessage(agArtifactToCardRow(art, { threadId, userId, seq, at: now, clientMessageId }, producingToolName(art, toolNames)));
|
|
196
201
|
artifactSeqs.push(seq);
|
|
197
202
|
}
|
|
198
203
|
const threadMemory = fold.memory.filter((m) => m.scope === 'thread');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract-suite.d.ts","sourceRoot":"","sources":["../../src/testing/contract-suite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,qBAAqB,EAAa,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAiCD;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,GAC5C,IAAI,
|
|
1
|
+
{"version":3,"file":"contract-suite.d.ts","sourceRoot":"","sources":["../../src/testing/contract-suite.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,qBAAqB,EAAa,MAAM,YAAY,CAAC;AAEnE,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,qBAAqB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAiCD;;;GAGG;AACH,wBAAgB,iCAAiC,CAC/C,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,GAC5C,IAAI,CAmJN"}
|
|
@@ -113,6 +113,26 @@ export function runThreadPersistenceContractSuite(name, make) {
|
|
|
113
113
|
expect(rows.map((r) => r.seq)).toEqual([3, 4, 5]);
|
|
114
114
|
});
|
|
115
115
|
});
|
|
116
|
+
it("a card row round-trips cardSnapshot + toolName; absence stays absent (guuey#402)", async () => {
|
|
117
|
+
await withHarness(make, async (port) => {
|
|
118
|
+
await port.createThread(threadRow("t1"));
|
|
119
|
+
const base = {
|
|
120
|
+
threadId: "t1",
|
|
121
|
+
userId: "g_contract",
|
|
122
|
+
at: "2026-08-07T00:00:01.000Z",
|
|
123
|
+
kind: "card",
|
|
124
|
+
authorRole: "agent",
|
|
125
|
+
cardSnapshot: { artifactId: "a1", turnId: "turn1", parts: [] },
|
|
126
|
+
};
|
|
127
|
+
await port.putMessage({ ...base, seq: 1, clientMessageId: "c1", toolName: "render" });
|
|
128
|
+
await port.putMessage({ ...base, seq: 2, clientMessageId: "c2" });
|
|
129
|
+
const rows = await port.listRecentMessages("t1", 5);
|
|
130
|
+
expect(rows[0]?.toolName).toBe("render");
|
|
131
|
+
expect(rows[0]?.cardSnapshot).toEqual(base.cardSnapshot);
|
|
132
|
+
// A pre-#402 row must come back WITHOUT the key materialized.
|
|
133
|
+
expect(rows[1] && "toolName" in rows[1]).toBe(false);
|
|
134
|
+
});
|
|
135
|
+
});
|
|
116
136
|
it("findByClientMessageId resolves the idempotency key within its thread only", async () => {
|
|
117
137
|
await withHarness(make, async (port) => {
|
|
118
138
|
await port.createThread(threadRow("t1"));
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/threads",
|
|
3
|
-
"version": "0.16.
|
|
3
|
+
"version": "0.16.8",
|
|
4
4
|
"description": "Universal session/thread persistence for AgJSON agents — the ThreadStore contract (append-fold, history, snapshots), the fold↔row mapping, and an in-memory binding. Guuey's hosted runtime is one binding; implement the port against your own store and run the exported contract suite for the same guarantees.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -22,8 +22,8 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@silverprotocol/core": "0.5.
|
|
26
|
-
"@guuey/mcp-apps-host": "0.16.
|
|
25
|
+
"@silverprotocol/core": "0.5.3",
|
|
26
|
+
"@guuey/mcp-apps-host": "0.16.8"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^24.0.0",
|