@guuey/threads 0.30.0 → 0.31.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/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/rows.d.ts +20 -0
- package/dist/rows.d.ts.map +1 -1
- package/dist/store.d.ts +7 -1
- package/dist/store.d.ts.map +1 -1
- package/dist/store.js +22 -3
- package/dist/stored-row.d.ts +57 -0
- package/dist/stored-row.d.ts.map +1 -0
- package/dist/stored-row.js +79 -0
- package/package.json +6 -3
package/dist/index.d.ts
CHANGED
|
@@ -17,9 +17,10 @@
|
|
|
17
17
|
* - `@guuey/threads/testing` — the port contract suite: run it against
|
|
18
18
|
* your binding for the same guarantees the hosted one carries.
|
|
19
19
|
*/
|
|
20
|
-
export type { HandoffEvent, ReportEvent, StoredHistoryMessage, ThreadMessageEvent, ThreadMessageKind, ThreadMessageRole, ThreadMessageRow, ThreadPersistencePort, ThreadRow, ThreadSnapshotRow, } from "./rows.js";
|
|
20
|
+
export type { HandoffEvent, ReportEvent, StoredHistoryMessage, ThreadMessageEvent, ThreadMessageKind, ThreadMessageRole, ThreadMessageRow, ThreadPersistencePort, ThreadRow, ThreadSnapshotRow, TurnOrigin, ClientClass, } from "./rows.js";
|
|
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
|
+
export { AGENT_ERROR_ROW_SUFFIX, classifyStoredRow, isBlankBlock, isInformationless, type StoredRowClass, } from "./stored-row.js";
|
|
23
24
|
export { HttpThreadPersistence, HttpThreadStoreError, type HttpThreadPersistenceOptions, type ThreadScope, } from "./http.js";
|
|
24
25
|
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageFullText, messageNarration, messageText, producingToolName, storedTextParts, type StoredTextParts, joinStoredThreadMemory, reassembleFold, rowToAgMessage, seedEventsForReducer, splitStoredThreadMemory, toolNamesByCallId, uiCardArtifactsFromMessages, type RowCtx, } from "./fold-rows.js";
|
|
25
26
|
//# 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,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,iBAAiB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,YAAY,EACV,YAAY,EACZ,WAAW,EACX,oBAAoB,EACpB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,gBAAgB,EAChB,qBAAqB,EACrB,SAAS,EACT,iBAAiB,EACjB,UAAU,EACV,WAAW,GACZ,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,sBAAsB,EACtB,iBAAiB,EACjB,YAAY,EACZ,iBAAiB,EACjB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,qBAAqB,EACrB,oBAAoB,EACpB,KAAK,4BAA4B,EACjC,KAAK,WAAW,GACjB,MAAM,WAAW,CAAC;AACnB,OAAO,EACL,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,eAAe,EACf,gBAAgB,EAChB,WAAW,EACX,iBAAiB,EACjB,eAAe,EACf,KAAK,eAAe,EACpB,sBAAsB,EACtB,cAAc,EACd,cAAc,EACd,oBAAoB,EACpB,uBAAuB,EACvB,iBAAiB,EACjB,2BAA2B,EAC3B,KAAK,MAAM,GACZ,MAAM,gBAAgB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ThreadStore, } from "./store.js";
|
|
2
2
|
export { InMemoryThreadPersistence } from "./in-memory.js";
|
|
3
|
+
export { AGENT_ERROR_ROW_SUFFIX, classifyStoredRow, isBlankBlock, isInformationless, } from "./stored-row.js";
|
|
3
4
|
export { HttpThreadPersistence, HttpThreadStoreError, } from "./http.js";
|
|
4
5
|
export { agArtifactToCardRow, agMessageToRow, cardRowToAgArtifact, messageFullText, messageNarration, messageText, producingToolName, storedTextParts, joinStoredThreadMemory, reassembleFold, rowToAgMessage, seedEventsForReducer, splitStoredThreadMemory, toolNamesByCallId, uiCardArtifactsFromMessages, } from "./fold-rows.js";
|
package/dist/rows.d.ts
CHANGED
|
@@ -12,6 +12,20 @@
|
|
|
12
12
|
import type { AgMemoryRecord, JsonValue } from "@silverprotocol/core";
|
|
13
13
|
export type ThreadMessageRole = "user" | "agent" | "system";
|
|
14
14
|
export type ThreadMessageKind = "text" | "card" | "event";
|
|
15
|
+
/**
|
|
16
|
+
* How a user turn was started: a gesture on a card (`card_action`), a
|
|
17
|
+
* suggested-prompt chip (`chip`), or typed input (`typed`). Stamped by the
|
|
18
|
+
* runtime on user rows; absent on rows written before the stamp existed.
|
|
19
|
+
*/
|
|
20
|
+
export type TurnOrigin = "card_action" | "chip" | "typed";
|
|
21
|
+
/**
|
|
22
|
+
* The kind of client that sent a user turn, from its User-Agent at request
|
|
23
|
+
* time (the agent string is never stored): the hosting operator's own
|
|
24
|
+
* automated clients, such as health checks and smoke tests (`operator`); a
|
|
25
|
+
* third-party crawler or automated client (`bot`); or anything else
|
|
26
|
+
* (`browser`).
|
|
27
|
+
*/
|
|
28
|
+
export type ClientClass = "operator" | "bot" | "browser";
|
|
15
29
|
export interface ThreadRow {
|
|
16
30
|
id: string;
|
|
17
31
|
userId: string;
|
|
@@ -116,6 +130,12 @@ export interface ThreadMessageRow {
|
|
|
116
130
|
* the row types never carried it). Absent on every non-event row.
|
|
117
131
|
*/
|
|
118
132
|
event?: ThreadMessageEvent;
|
|
133
|
+
/** On a user row: how the turn was started. Absent on older rows. */
|
|
134
|
+
turnOrigin?: TurnOrigin;
|
|
135
|
+
/** On a `card_action` user row: the render session id of the card the gesture answered. */
|
|
136
|
+
answeredCardSessionId?: string;
|
|
137
|
+
/** On a user row: the sending client's class. Absent on older rows. */
|
|
138
|
+
clientClass?: ClientClass;
|
|
119
139
|
}
|
|
120
140
|
/** Latest-replace fold snapshot for a thread. */
|
|
121
141
|
export interface ThreadSnapshotRow {
|
package/dist/rows.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtE,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,CAAC;AAC5D,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;
|
|
1
|
+
{"version":3,"file":"rows.d.ts","sourceRoot":"","sources":["../src/rows.ts"],"names":[],"mappings":"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"}
|
package/dist/store.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { AgMemoryRecord, AgReduceResult, JsonValue } from "@silverprotocol/core";
|
|
2
|
-
import type { ThreadMessageEvent, StoredHistoryMessage, ThreadMessageKind, ThreadMessageRole, ThreadPersistencePort, ThreadSnapshotRow } from "./rows.js";
|
|
2
|
+
import type { ThreadMessageEvent, StoredHistoryMessage, ThreadMessageKind, ThreadMessageRole, ThreadPersistencePort, ThreadSnapshotRow, TurnOrigin, ClientClass } from "./rows.js";
|
|
3
3
|
export interface EnsureThreadInput {
|
|
4
4
|
/** Client-supplied thread id (localStorage). Absent on first contact. */
|
|
5
5
|
threadId?: string;
|
|
@@ -33,6 +33,12 @@ export interface AppendMessageInput {
|
|
|
33
33
|
* store does not infer one from the other.
|
|
34
34
|
*/
|
|
35
35
|
event?: ThreadMessageEvent;
|
|
36
|
+
/** A user row's origin (see {@link ThreadMessageRow.turnOrigin}); carried verbatim. */
|
|
37
|
+
turnOrigin?: TurnOrigin;
|
|
38
|
+
/** A `card_action` user row's answered card session id; carried verbatim. */
|
|
39
|
+
answeredCardSessionId?: string;
|
|
40
|
+
/** A user row's client class (see {@link ThreadMessageRow.clientClass}); carried verbatim. */
|
|
41
|
+
clientClass?: ClientClass;
|
|
36
42
|
}
|
|
37
43
|
export interface AppendMessageResult {
|
|
38
44
|
seq: number;
|
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,cAAc,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
|
package/dist/store.js
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import { randomUUID } from "node:crypto";
|
|
11
11
|
import { agMessageToRow, agArtifactToCardRow, keepUnchangedThreadMemory, producingToolName, toolNamesByCallId, uiCardArtifactsFromMessages, storedTextParts, } from "./fold-rows.js";
|
|
12
|
+
import { classifyStoredRow } from "./stored-row.js";
|
|
12
13
|
/** Max history messages fed back as context — bounds latency on long threads. */
|
|
13
14
|
const DEFAULT_HISTORY_LIMIT = 40;
|
|
14
15
|
const PREVIEW_MAX_LEN = 240;
|
|
@@ -91,7 +92,18 @@ export class ThreadStore {
|
|
|
91
92
|
// the model is replayed. For rows written before the split, `all` is the same
|
|
92
93
|
// bytes their `text` holds. A row whose content is not a stored AgMessage
|
|
93
94
|
// (an event, a managed-adapter row) keeps its `text`.
|
|
94
|
-
|
|
95
|
+
//
|
|
96
|
+
// Only CONVERSATION reaches this lane: a failed turn's reader line, a
|
|
97
|
+
// framework notice and a blank agent message are stored rows, never words
|
|
98
|
+
// the agent said, so replaying them made the model (and a hook's
|
|
99
|
+
// transcript) read them as its own ({@link classifyStoredRow}).
|
|
100
|
+
// Two user turns can now sit side by side (the agent row between them
|
|
101
|
+
// dropped). That is fine: every runner renders this history as TEXT lines
|
|
102
|
+
// into its system prompt (`@guuey/host` `withContextPreamble`), never as a
|
|
103
|
+
// role-alternating message list a provider could refuse.
|
|
104
|
+
const conversation = rows
|
|
105
|
+
.filter((r) => r.kind !== 'card' && classifyStoredRow(r).kind === 'conversation')
|
|
106
|
+
.map((r) => ({
|
|
95
107
|
seq: r.seq,
|
|
96
108
|
authorRole: r.authorRole,
|
|
97
109
|
kind: r.kind,
|
|
@@ -99,6 +111,7 @@ export class ThreadStore {
|
|
|
99
111
|
content: r.content ?? null,
|
|
100
112
|
at: r.at,
|
|
101
113
|
}));
|
|
114
|
+
return conversation;
|
|
102
115
|
}
|
|
103
116
|
/**
|
|
104
117
|
* Append one message with an atomic, gap-free seq. Idempotent on
|
|
@@ -125,6 +138,9 @@ export class ThreadStore {
|
|
|
125
138
|
content: input.content,
|
|
126
139
|
...(input.untrustedOrigin === true ? { untrustedOrigin: true } : {}),
|
|
127
140
|
...(input.event !== undefined ? { event: input.event } : {}),
|
|
141
|
+
...(input.turnOrigin !== undefined ? { turnOrigin: input.turnOrigin } : {}),
|
|
142
|
+
...(input.answeredCardSessionId !== undefined ? { answeredCardSessionId: input.answeredCardSessionId } : {}),
|
|
143
|
+
...(input.clientClass !== undefined ? { clientClass: input.clientClass } : {}),
|
|
128
144
|
};
|
|
129
145
|
await this.db.putMessage(row);
|
|
130
146
|
return { seq, deduped: false };
|
|
@@ -167,8 +183,11 @@ export class ThreadStore {
|
|
|
167
183
|
const msg = fold.messages[i];
|
|
168
184
|
const clientMessageId = sentinelClaimed ? `${clientMessageIdBase}#agent#${i}` : sentinelKey;
|
|
169
185
|
sentinelClaimed = true;
|
|
170
|
-
// The preview is the ANSWER: interim narration (`phase: "interim"`) never becomes a thread's preview
|
|
171
|
-
|
|
186
|
+
// The preview is the ANSWER: interim narration (`phase: "interim"`) never becomes a thread's preview,
|
|
187
|
+
// and neither does a framework notice (a non-conversational row).
|
|
188
|
+
const text = msg.role === 'notice'
|
|
189
|
+
? ''
|
|
190
|
+
: msg.content.reduce((acc, b) => (b.type === 'text' && b.phase !== 'interim' ? acc + b.text : acc), '');
|
|
172
191
|
const now = new Date().toISOString();
|
|
173
192
|
// Text-less agent messages (tool-call + tool-result only — the canonical
|
|
174
193
|
// card-producing turn) must not blank the preview: '' takes the SET
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a stored thread row IS, for every reader that turns rows back into
|
|
3
|
+
* conversation. Some stored rows are not "the agent said this", and reading
|
|
4
|
+
* them as such replays them to the model as the agent's own words and draws
|
|
5
|
+
* them as answer bubbles:
|
|
6
|
+
*
|
|
7
|
+
* - a FAILURE row: the runtime's reader line for a failed turn, keyed
|
|
8
|
+
* `…#agentError`. It carries `content.error.code` from the runtime release
|
|
9
|
+
* that added codes; rows written before it carry only `{kind:'text', text}`,
|
|
10
|
+
* so the key suffix alone must classify them too;
|
|
11
|
+
* - a NOTICE row: a stored message with `role: "notice"` (a framework notice
|
|
12
|
+
* the agent facet emits), a non-conversational, user-facing row;
|
|
13
|
+
* - a BLANK row: an agent message whose every block shows the reader nothing
|
|
14
|
+
* (an empty text part, or a provider carry with nothing in it).
|
|
15
|
+
*
|
|
16
|
+
* The reader is lenient: it reads the stored `content` through the core's
|
|
17
|
+
* stored-record reader, so a row written before any of this is classified the
|
|
18
|
+
* same way, with no migration.
|
|
19
|
+
*/
|
|
20
|
+
import { type AgBlock, type JsonValue } from "@silverprotocol/core";
|
|
21
|
+
import type { ThreadMessageRow } from "./rows.js";
|
|
22
|
+
/** The clientMessageId suffix the runtime gives a failed turn's reader-line row. */
|
|
23
|
+
export declare const AGENT_ERROR_ROW_SUFFIX = "#agentError";
|
|
24
|
+
/**
|
|
25
|
+
* True when a JSON value carries no information a reader could act on:
|
|
26
|
+
* `null`/`undefined`, the empty string, an empty array or object, or an
|
|
27
|
+
* array/object whose every member is itself informationless. Numbers and
|
|
28
|
+
* booleans are information. The same rule `@guuey/chat` applies to a provider
|
|
29
|
+
* carry it hides from the transcript.
|
|
30
|
+
*/
|
|
31
|
+
export declare function isInformationless(value: JsonValue | undefined): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* A block the reader's transcript shows nothing for: an empty text part, or a
|
|
34
|
+
* `provider-raw` carry whose payload is informationless. Every other block,
|
|
35
|
+
* reasoning included, is something a reader can see. ONE predicate for the
|
|
36
|
+
* runtime's turn watch, its stored fold, and this classifier.
|
|
37
|
+
*/
|
|
38
|
+
export declare function isBlankBlock(block: AgBlock): boolean;
|
|
39
|
+
/** The class of one stored row. */
|
|
40
|
+
export type StoredRowClass = {
|
|
41
|
+
kind: "conversation";
|
|
42
|
+
}
|
|
43
|
+
/** A failed turn's reader line. `code` is null on a row stored before codes were persisted. */
|
|
44
|
+
| {
|
|
45
|
+
kind: "failure";
|
|
46
|
+
code: string | null;
|
|
47
|
+
}
|
|
48
|
+
/** A framework notice. `source` is the injecting layer when the row names one. */
|
|
49
|
+
| {
|
|
50
|
+
kind: "notice";
|
|
51
|
+
source: string | null;
|
|
52
|
+
} | {
|
|
53
|
+
kind: "blank";
|
|
54
|
+
};
|
|
55
|
+
/** Classify one stored row (see the module doc). */
|
|
56
|
+
export declare function classifyStoredRow(row: Pick<ThreadMessageRow, "clientMessageId" | "authorRole" | "content">): StoredRowClass;
|
|
57
|
+
//# sourceMappingURL=stored-row.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stored-row.d.ts","sourceRoot":"","sources":["../src/stored-row.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAuB,KAAK,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACzF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAElD,oFAAoF;AACpF,eAAO,MAAM,sBAAsB,gBAAgB,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,GAAG,OAAO,CAMvE;AAED;;;;;GAKG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAIpD;AAED,mCAAmC;AACnC,MAAM,MAAM,cAAc,GACtB;IAAE,IAAI,EAAE,cAAc,CAAA;CAAE;AAC1B,+FAA+F;GAC7F;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE;AAC1C,kFAAkF;GAChF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,GACzC;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAUtB,oDAAoD;AACpD,wBAAgB,iBAAiB,CAC/B,GAAG,EAAE,IAAI,CAAC,gBAAgB,EAAE,iBAAiB,GAAG,YAAY,GAAG,SAAS,CAAC,GACxE,cAAc,CAWhB"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a stored thread row IS, for every reader that turns rows back into
|
|
3
|
+
* conversation. Some stored rows are not "the agent said this", and reading
|
|
4
|
+
* them as such replays them to the model as the agent's own words and draws
|
|
5
|
+
* them as answer bubbles:
|
|
6
|
+
*
|
|
7
|
+
* - a FAILURE row: the runtime's reader line for a failed turn, keyed
|
|
8
|
+
* `…#agentError`. It carries `content.error.code` from the runtime release
|
|
9
|
+
* that added codes; rows written before it carry only `{kind:'text', text}`,
|
|
10
|
+
* so the key suffix alone must classify them too;
|
|
11
|
+
* - a NOTICE row: a stored message with `role: "notice"` (a framework notice
|
|
12
|
+
* the agent facet emits), a non-conversational, user-facing row;
|
|
13
|
+
* - a BLANK row: an agent message whose every block shows the reader nothing
|
|
14
|
+
* (an empty text part, or a provider carry with nothing in it).
|
|
15
|
+
*
|
|
16
|
+
* The reader is lenient: it reads the stored `content` through the core's
|
|
17
|
+
* stored-record reader, so a row written before any of this is classified the
|
|
18
|
+
* same way, with no migration.
|
|
19
|
+
*/
|
|
20
|
+
import { readStoredAgMessage } from "@silverprotocol/core";
|
|
21
|
+
/** The clientMessageId suffix the runtime gives a failed turn's reader-line row. */
|
|
22
|
+
export const AGENT_ERROR_ROW_SUFFIX = "#agentError";
|
|
23
|
+
/**
|
|
24
|
+
* True when a JSON value carries no information a reader could act on:
|
|
25
|
+
* `null`/`undefined`, the empty string, an empty array or object, or an
|
|
26
|
+
* array/object whose every member is itself informationless. Numbers and
|
|
27
|
+
* booleans are information. The same rule `@guuey/chat` applies to a provider
|
|
28
|
+
* carry it hides from the transcript.
|
|
29
|
+
*/
|
|
30
|
+
export function isInformationless(value) {
|
|
31
|
+
if (value === undefined || value === null)
|
|
32
|
+
return true;
|
|
33
|
+
if (typeof value === "string")
|
|
34
|
+
return value === "";
|
|
35
|
+
if (typeof value === "number" || typeof value === "boolean")
|
|
36
|
+
return false;
|
|
37
|
+
if (Array.isArray(value))
|
|
38
|
+
return value.every((v) => isInformationless(v));
|
|
39
|
+
return Object.values(value).every((v) => isInformationless(v));
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* A block the reader's transcript shows nothing for: an empty text part, or a
|
|
43
|
+
* `provider-raw` carry whose payload is informationless. Every other block,
|
|
44
|
+
* reasoning included, is something a reader can see. ONE predicate for the
|
|
45
|
+
* runtime's turn watch, its stored fold, and this classifier.
|
|
46
|
+
*/
|
|
47
|
+
export function isBlankBlock(block) {
|
|
48
|
+
if (block.type === "text")
|
|
49
|
+
return block.text === "";
|
|
50
|
+
if (block.type === "provider-raw")
|
|
51
|
+
return isInformationless(block.raw);
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
/** The failure code a row's content carries (`content.error.code`), when it carries one. */
|
|
55
|
+
function failureCodeOf(content) {
|
|
56
|
+
if (typeof content !== "object" || content === null || !("error" in content))
|
|
57
|
+
return undefined;
|
|
58
|
+
const error = content.error;
|
|
59
|
+
if (typeof error !== "object" || error === null || !("code" in error))
|
|
60
|
+
return undefined;
|
|
61
|
+
return typeof error.code === "string" && error.code !== "" ? error.code : undefined;
|
|
62
|
+
}
|
|
63
|
+
/** Classify one stored row (see the module doc). */
|
|
64
|
+
export function classifyStoredRow(row) {
|
|
65
|
+
const code = failureCodeOf(row.content);
|
|
66
|
+
if (row.clientMessageId.endsWith(AGENT_ERROR_ROW_SUFFIX) || code !== undefined) {
|
|
67
|
+
return { kind: "failure", code: code ?? null };
|
|
68
|
+
}
|
|
69
|
+
if (row.authorRole === "user")
|
|
70
|
+
return { kind: "conversation" };
|
|
71
|
+
const stored = readStoredAgMessage(row.content).value;
|
|
72
|
+
if (stored === undefined)
|
|
73
|
+
return { kind: "conversation" };
|
|
74
|
+
if (stored.role === "notice")
|
|
75
|
+
return { kind: "notice", source: stored.noticeSource ?? null };
|
|
76
|
+
if (stored.content.every(isBlankBlock))
|
|
77
|
+
return { kind: "blank" };
|
|
78
|
+
return { kind: "conversation" };
|
|
79
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@guuey/threads",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
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",
|
|
@@ -10,6 +10,9 @@
|
|
|
10
10
|
"dist",
|
|
11
11
|
"README.md"
|
|
12
12
|
],
|
|
13
|
+
"engines": {
|
|
14
|
+
"node": ">=22.12.0"
|
|
15
|
+
},
|
|
13
16
|
"exports": {
|
|
14
17
|
".": {
|
|
15
18
|
"types": "./dist/index.d.ts",
|
|
@@ -22,8 +25,8 @@
|
|
|
22
25
|
}
|
|
23
26
|
},
|
|
24
27
|
"dependencies": {
|
|
25
|
-
"@silverprotocol/core": "0.
|
|
26
|
-
"@guuey/mcp-apps-host": "0.
|
|
28
|
+
"@silverprotocol/core": "0.12.1",
|
|
29
|
+
"@guuey/mcp-apps-host": "0.31.0"
|
|
27
30
|
},
|
|
28
31
|
"devDependencies": {
|
|
29
32
|
"@types/node": "^24.0.0",
|