@sentry/junior 0.94.0 → 0.96.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/{agent-hooks-ZG7IDOIN.js → agent-hooks-5URSMY3O.js} +10 -11
- package/dist/api/people/list.js +8 -8
- package/dist/api/people/profile.js +8 -8
- package/dist/api/people/shared.d.ts +2 -2
- package/dist/api-reference.d.ts +2 -2
- package/dist/app.js +434 -199
- package/dist/{catalog-runtime-NZHMSMYC.js → catalog-runtime-MSMAYYIK.js} +4 -4
- package/dist/chat/advisor-request.d.ts +4 -0
- package/dist/chat/agent/request.d.ts +2 -0
- package/dist/chat/agent/resume.d.ts +2 -0
- package/dist/chat/conversations/history.d.ts +128 -0
- package/dist/chat/conversations/legacy-import.d.ts +38 -0
- package/dist/chat/conversations/messages.d.ts +39 -0
- package/dist/chat/conversations/projection.d.ts +94 -0
- package/dist/chat/conversations/retention.d.ts +36 -0
- package/dist/chat/conversations/sql/conversation-row.d.ts +14 -0
- package/dist/chat/conversations/sql/history.d.ts +4 -0
- package/dist/chat/conversations/sql/legacy-history-import.d.ts +55 -0
- package/dist/chat/conversations/sql/messages.d.ts +4 -0
- package/dist/chat/conversations/sql/migrations.d.ts +14 -3
- package/dist/chat/conversations/sql/purge.d.ts +53 -0
- package/dist/chat/conversations/sql/store.d.ts +7 -2
- package/dist/chat/conversations/store.d.ts +19 -0
- package/dist/chat/conversations/visible-compactions.d.ts +11 -0
- package/dist/chat/conversations/visible-messages.d.ts +47 -0
- package/dist/chat/db.d.ts +12 -1
- package/dist/chat/identities/sql.d.ts +1 -1
- package/dist/chat/logging.d.ts +4 -3
- package/dist/chat/plugins/auth/oauth-request.d.ts +2 -0
- package/dist/chat/resource-events/notification.d.ts +2 -0
- package/dist/chat/resource-events/store.d.ts +2 -1
- package/dist/chat/runtime/agent-run-outcome.d.ts +3 -0
- package/dist/chat/runtime/reply-executor.d.ts +8 -0
- package/dist/chat/runtime/thread-state.d.ts +2 -0
- package/dist/chat/sandbox/resources.d.ts +4 -0
- package/dist/chat/sentry.d.ts +1 -1
- package/dist/chat/services/mcp-auth-orchestration.d.ts +8 -0
- package/dist/chat/services/plugin-auth-orchestration.d.ts +12 -0
- package/dist/chat/services/turn-session-record.d.ts +14 -2
- package/dist/chat/sleep.d.ts +2 -0
- package/dist/chat/state/conversation.d.ts +7 -4
- package/dist/chat/state/session-log.d.ts +23 -1
- package/dist/chat/state/turn-session.d.ts +9 -1
- package/dist/chat/tool-support/private-trace-result.d.ts +4 -0
- package/dist/chat/tool-support/zod-tool.d.ts +1 -0
- package/dist/chat/tools/advisor/tool.d.ts +9 -4
- package/dist/chat/tools/definition.d.ts +2 -0
- package/dist/chat/tools/execution/tool-error-handler.d.ts +2 -2
- package/dist/chat/tools/system-time.d.ts +8 -0
- package/dist/chat/usage.d.ts +27 -13
- package/dist/chat/xml.d.ts +2 -0
- package/dist/{chunk-TNUUATT7.js → chunk-2NAZZPPS.js} +2 -2
- package/dist/{chunk-NYWPISSO.js → chunk-2XXEKR44.js} +1 -1
- package/dist/chunk-5C6XTTFI.js +1037 -0
- package/dist/{chunk-3DA7X2U3.js → chunk-6GWA276C.js} +15 -0
- package/dist/{chunk-LFLTJQVR.js → chunk-7FBGKXPE.js} +4 -0
- package/dist/{chunk-LNCREA5Z.js → chunk-AAZXTVJT.js} +4 -128
- package/dist/{chunk-GHGPTPBL.js → chunk-B7PUBQQM.js} +1 -1
- package/dist/{chunk-6H4PP63X.js → chunk-BYZWPRJA.js} +24 -14
- package/dist/chunk-CM5EZD5F.js +17 -0
- package/dist/{chunk-G3E7SCME.js → chunk-CZEX6KIQ.js} +23 -0
- package/dist/{chunk-YJ4OPVNA.js → chunk-DZENG5ML.js} +1 -1
- package/dist/{chunk-QGEWC27H.js → chunk-GQ3GK22G.js} +5 -7
- package/dist/{chunk-YYBX2BD5.js → chunk-GY34VGP5.js} +1 -1
- package/dist/{chunk-S6QKIGRM.js → chunk-I35CTGPO.js} +71 -29
- package/dist/{chunk-KRMANDHI.js → chunk-IYM2SIVG.js} +1489 -355
- package/dist/{chunk-BTH37NCU.js → chunk-L7CDEIVJ.js} +12 -4
- package/dist/chunk-MNTINMWR.js +865 -0
- package/dist/{chunk-MAVOJ54A.js → chunk-P3YFQLEN.js} +25 -388
- package/dist/{chunk-YTNPU7I2.js → chunk-PMNN6ST4.js} +2 -2
- package/dist/{chunk-PFXC67GJ.js → chunk-RAIB6WSG.js} +6 -80
- package/dist/{chunk-NFXSLTYG.js → chunk-RITD7E5L.js} +864 -62
- package/dist/{chunk-UUB3D2XI.js → chunk-S5KZ5LPG.js} +8 -10
- package/dist/{chunk-HDNWZMUN.js → chunk-UKHVMPX5.js} +112 -103
- package/dist/chunk-WM6KHPBQ.js +48 -0
- package/dist/{chunk-MC4ZZE4Q.js → chunk-YDT7SNCN.js} +1 -1
- package/dist/{chunk-NAPITCZ6.js → chunk-YDVEH3SB.js} +251 -6
- package/dist/cli/chat.js +25 -24
- package/dist/cli/check.js +5 -5
- package/dist/cli/main.js +1 -1
- package/dist/cli/plugins.js +12 -13
- package/dist/cli/snapshot-warmup.js +8 -9
- package/dist/cli/upgrade.js +79 -18
- package/dist/db/schema/agent-steps.d.ts +134 -0
- package/dist/db/schema/conversation-messages.d.ts +153 -0
- package/dist/{chat/conversations/sql → db}/schema/conversations.d.ts +34 -0
- package/dist/{chat/conversations/sql → db}/schema.d.ts +319 -8
- package/dist/db-2D6RMG67.js +24 -0
- package/dist/deployment.d.ts +2 -0
- package/dist/handlers/retention.d.ts +6 -0
- package/dist/instrumentation.js +17 -4
- package/dist/legacy-import-VZ2MEGP7.js +17 -0
- package/dist/nitro.js +14 -4
- package/dist/reporting/conversations/activity.d.ts +40 -0
- package/dist/reporting/conversations/context.d.ts +8 -0
- package/dist/reporting/conversations/details.d.ts +6 -0
- package/dist/reporting/conversations/index.d.ts +4 -0
- package/dist/reporting/conversations/shared.d.ts +9 -0
- package/dist/reporting/conversations/statistics.d.ts +4 -0
- package/dist/reporting/conversations/summaries.d.ts +20 -0
- package/dist/reporting/conversations/transcript.d.ts +28 -0
- package/dist/reporting/conversations/types.d.ts +191 -0
- package/dist/reporting/conversations.d.ts +1 -178
- package/dist/reporting.d.ts +5 -4
- package/dist/reporting.js +703 -837
- package/dist/{runner-XAZPJNAQ.js → runner-JZBRQP4F.js} +36 -42
- package/dist/{sentry-EGFOV3DH.js → sentry-JMWTS32N.js} +11 -1
- package/dist/{validation-KYAWETI4.js → validation-6XOOQGME.js} +5 -5
- package/migrations/README.md +32 -0
- package/migrations/meta/0000_snapshot.json +978 -0
- package/migrations/meta/_journal.json +13 -0
- package/package.json +10 -7
- package/dist/chat/sql/schema.d.ts +0 -1049
- package/dist/chat/state/conversation-details.d.ts +0 -47
- package/dist/chunk-7STN2ZSK.js +0 -250
- package/dist/chunk-LE5ANBUZ.js +0 -1040
- package/dist/chunk-QL66APYJ.js +0 -1377
- package/dist/db-YDN6AFJH.js +0 -18
- /package/dist/{chat/sql → db}/db.d.ts +0 -0
- /package/dist/{chat/sql → db}/executor.d.ts +0 -0
- /package/dist/{chat/sql → db}/neon.d.ts +0 -0
- /package/dist/{chat/sql → db}/postgres.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/destinations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/identities.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/migrations.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/timestamps.d.ts +0 -0
- /package/dist/{chat/conversations/sql → db}/schema/users.d.ts +0 -0
package/dist/chunk-QL66APYJ.js
DELETED
|
@@ -1,1377 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getConnectedStateContext,
|
|
3
|
-
getStateAdapter
|
|
4
|
-
} from "./chunk-7STN2ZSK.js";
|
|
5
|
-
import {
|
|
6
|
-
getConversationStore
|
|
7
|
-
} from "./chunk-NFXSLTYG.js";
|
|
8
|
-
import {
|
|
9
|
-
getChatConfig
|
|
10
|
-
} from "./chunk-NAPITCZ6.js";
|
|
11
|
-
import {
|
|
12
|
-
parseDestination
|
|
13
|
-
} from "./chunk-GHGPTPBL.js";
|
|
14
|
-
import {
|
|
15
|
-
logWarn,
|
|
16
|
-
parseActor,
|
|
17
|
-
storedSlackActorSchema,
|
|
18
|
-
toStoredSlackActor
|
|
19
|
-
} from "./chunk-S6QKIGRM.js";
|
|
20
|
-
import {
|
|
21
|
-
isRecord
|
|
22
|
-
} from "./chunk-OB42YVAE.js";
|
|
23
|
-
|
|
24
|
-
// src/chat/state/session-log.ts
|
|
25
|
-
import { isDeepStrictEqual } from "util";
|
|
26
|
-
import { z as z2 } from "zod";
|
|
27
|
-
import { actorSchema } from "@sentry/junior-plugin-api";
|
|
28
|
-
|
|
29
|
-
// src/chat/pi/messages.ts
|
|
30
|
-
import { z } from "zod";
|
|
31
|
-
var piMessageSchema = z.object({
|
|
32
|
-
role: z.string()
|
|
33
|
-
}).passthrough().transform((value) => value);
|
|
34
|
-
var piContentMessageSchema = z.object({
|
|
35
|
-
content: z.array(z.unknown()),
|
|
36
|
-
role: z.string().min(1)
|
|
37
|
-
}).passthrough().transform((value) => value);
|
|
38
|
-
|
|
39
|
-
// src/chat/state/session-log.ts
|
|
40
|
-
var AGENT_SESSION_LOG_PREFIX = "junior:agent-session-log";
|
|
41
|
-
var AGENT_SESSION_LOG_SCHEMA_VERSION = 2;
|
|
42
|
-
var INITIAL_SESSION_ID = "session_0";
|
|
43
|
-
var SESSION_ID_PREFIX = "session_";
|
|
44
|
-
var STATE_STORE_LOCK_TTL_MS = 5e3;
|
|
45
|
-
var schemaVersionSchema = z2.union([z2.literal(1), z2.literal(2)]);
|
|
46
|
-
var piMessageAuthoritySchema = z2.union([
|
|
47
|
-
z2.literal("instruction"),
|
|
48
|
-
z2.literal("context")
|
|
49
|
-
]);
|
|
50
|
-
var piMessageProvenanceSchema = z2.object({
|
|
51
|
-
authority: piMessageAuthoritySchema,
|
|
52
|
-
actor: actorSchema.optional()
|
|
53
|
-
}).strict();
|
|
54
|
-
var unattributedContextProvenance = {
|
|
55
|
-
authority: "context"
|
|
56
|
-
};
|
|
57
|
-
function instructionProvenance(actor) {
|
|
58
|
-
return actor ? { authority: "instruction", actor } : { authority: "instruction" };
|
|
59
|
-
}
|
|
60
|
-
function isDefaultContextProvenance(provenance) {
|
|
61
|
-
return provenance.authority === "context" && !provenance.actor;
|
|
62
|
-
}
|
|
63
|
-
function legacyActorProvenance(actor) {
|
|
64
|
-
if (actor.teamId && actor.slackUserId && actor.platform) {
|
|
65
|
-
return instructionProvenance({
|
|
66
|
-
platform: "slack",
|
|
67
|
-
teamId: actor.teamId,
|
|
68
|
-
userId: actor.slackUserId,
|
|
69
|
-
...actor.slackUserName ? { userName: actor.slackUserName } : {},
|
|
70
|
-
...actor.fullName ? { fullName: actor.fullName } : {},
|
|
71
|
-
...actor.email ? { email: actor.email } : {}
|
|
72
|
-
});
|
|
73
|
-
}
|
|
74
|
-
return unattributedContextProvenance;
|
|
75
|
-
}
|
|
76
|
-
var piMessageEntrySchema = z2.object({
|
|
77
|
-
schemaVersion: schemaVersionSchema,
|
|
78
|
-
type: z2.literal("pi_message"),
|
|
79
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
80
|
-
message: piMessageSchema,
|
|
81
|
-
provenance: piMessageProvenanceSchema.optional(),
|
|
82
|
-
// Legacy v1 latest-wins actor, decoded into provenance on read.
|
|
83
|
-
actor: storedSlackActorSchema.optional()
|
|
84
|
-
});
|
|
85
|
-
var projectionResetEntrySchema = z2.object({
|
|
86
|
-
schemaVersion: schemaVersionSchema,
|
|
87
|
-
type: z2.literal("projection_reset"),
|
|
88
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
89
|
-
messages: z2.array(piMessageSchema),
|
|
90
|
-
provenance: z2.array(piMessageProvenanceSchema).optional(),
|
|
91
|
-
// Legacy v1 latest-wins actor; v1 resets carry no per-message provenance.
|
|
92
|
-
actor: storedSlackActorSchema.optional()
|
|
93
|
-
});
|
|
94
|
-
var actorRecordedEntrySchema = z2.object({
|
|
95
|
-
schemaVersion: schemaVersionSchema,
|
|
96
|
-
type: z2.literal("actor_recorded"),
|
|
97
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
98
|
-
actor: storedSlackActorSchema
|
|
99
|
-
});
|
|
100
|
-
var mcpProviderConnectedEntrySchema = z2.object({
|
|
101
|
-
schemaVersion: schemaVersionSchema,
|
|
102
|
-
type: z2.literal("mcp_provider_connected"),
|
|
103
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
104
|
-
provider: z2.string().min(1)
|
|
105
|
-
});
|
|
106
|
-
var authorizationKindSchema = z2.union([
|
|
107
|
-
z2.literal("plugin"),
|
|
108
|
-
z2.literal("mcp")
|
|
109
|
-
]);
|
|
110
|
-
var authorizationRequestedEntrySchema = z2.object({
|
|
111
|
-
schemaVersion: schemaVersionSchema,
|
|
112
|
-
type: z2.literal("authorization_requested"),
|
|
113
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
114
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
115
|
-
kind: authorizationKindSchema,
|
|
116
|
-
provider: z2.string().min(1),
|
|
117
|
-
actorId: z2.string().min(1),
|
|
118
|
-
authorizationId: z2.string().min(1),
|
|
119
|
-
delivery: z2.union([
|
|
120
|
-
z2.literal("private_link_sent"),
|
|
121
|
-
z2.literal("private_link_reused")
|
|
122
|
-
])
|
|
123
|
-
});
|
|
124
|
-
var authorizationCompletedEntrySchema = z2.object({
|
|
125
|
-
schemaVersion: schemaVersionSchema,
|
|
126
|
-
type: z2.literal("authorization_completed"),
|
|
127
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
128
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
129
|
-
kind: authorizationKindSchema,
|
|
130
|
-
provider: z2.string().min(1),
|
|
131
|
-
actorId: z2.string().min(1),
|
|
132
|
-
authorizationId: z2.string().min(1)
|
|
133
|
-
});
|
|
134
|
-
var transcriptRefSchema = z2.object({
|
|
135
|
-
type: z2.literal("advisor_session"),
|
|
136
|
-
parentConversationId: z2.string().min(1),
|
|
137
|
-
key: z2.string().min(1)
|
|
138
|
-
});
|
|
139
|
-
var toolExecutionStartedEntrySchema = z2.object({
|
|
140
|
-
schemaVersion: schemaVersionSchema,
|
|
141
|
-
type: z2.literal("tool_execution_started"),
|
|
142
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
143
|
-
createdAtMs: z2.number().int().nonnegative(),
|
|
144
|
-
toolCallId: z2.string().min(1),
|
|
145
|
-
toolName: z2.string().min(1),
|
|
146
|
-
args: z2.unknown().optional()
|
|
147
|
-
});
|
|
148
|
-
var subagentStartedEntrySchema = z2.object({
|
|
149
|
-
schemaVersion: schemaVersionSchema,
|
|
150
|
-
type: z2.literal("subagent_started"),
|
|
151
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
152
|
-
subagentInvocationId: z2.string().min(1),
|
|
153
|
-
subagentKind: z2.string().min(1),
|
|
154
|
-
parentToolCallId: z2.string().min(1).optional(),
|
|
155
|
-
parentConversationId: z2.string().min(1),
|
|
156
|
-
parentSessionId: z2.string().min(1).optional(),
|
|
157
|
-
transcriptRef: transcriptRefSchema,
|
|
158
|
-
historyMode: z2.literal("shared"),
|
|
159
|
-
createdAtMs: z2.number().int().nonnegative()
|
|
160
|
-
});
|
|
161
|
-
var subagentEndedEntrySchema = z2.object({
|
|
162
|
-
schemaVersion: schemaVersionSchema,
|
|
163
|
-
type: z2.literal("subagent_ended"),
|
|
164
|
-
sessionId: z2.string().min(1).default(INITIAL_SESSION_ID),
|
|
165
|
-
subagentInvocationId: z2.string().min(1),
|
|
166
|
-
outcome: z2.union([
|
|
167
|
-
z2.literal("success"),
|
|
168
|
-
z2.literal("error"),
|
|
169
|
-
z2.literal("aborted")
|
|
170
|
-
]),
|
|
171
|
-
errorCode: z2.string().min(1).optional(),
|
|
172
|
-
transcriptEndMessageIndex: z2.number().int().nonnegative().optional(),
|
|
173
|
-
transcriptStartMessageIndex: z2.number().int().nonnegative().optional(),
|
|
174
|
-
createdAtMs: z2.number().int().nonnegative()
|
|
175
|
-
});
|
|
176
|
-
var sessionLogEntrySchema = z2.discriminatedUnion("type", [
|
|
177
|
-
piMessageEntrySchema,
|
|
178
|
-
projectionResetEntrySchema,
|
|
179
|
-
actorRecordedEntrySchema,
|
|
180
|
-
mcpProviderConnectedEntrySchema,
|
|
181
|
-
authorizationRequestedEntrySchema,
|
|
182
|
-
authorizationCompletedEntrySchema,
|
|
183
|
-
toolExecutionStartedEntrySchema,
|
|
184
|
-
subagentStartedEntrySchema,
|
|
185
|
-
subagentEndedEntrySchema
|
|
186
|
-
]);
|
|
187
|
-
function key(scope) {
|
|
188
|
-
const prefix = getChatConfig().state.keyPrefix;
|
|
189
|
-
return [
|
|
190
|
-
...prefix ? [prefix] : [],
|
|
191
|
-
AGENT_SESSION_LOG_PREFIX,
|
|
192
|
-
scope.conversationId
|
|
193
|
-
].join(":");
|
|
194
|
-
}
|
|
195
|
-
function rawKey(scope) {
|
|
196
|
-
return [AGENT_SESSION_LOG_PREFIX, scope.conversationId].join(":");
|
|
197
|
-
}
|
|
198
|
-
function storedRecord(value) {
|
|
199
|
-
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : void 0;
|
|
200
|
-
}
|
|
201
|
-
function migrateStoredEntry(value) {
|
|
202
|
-
const record = storedRecord(value);
|
|
203
|
-
if (!record) {
|
|
204
|
-
return value;
|
|
205
|
-
}
|
|
206
|
-
const migrated = { ...record };
|
|
207
|
-
if ("requester" in migrated && !("actor" in migrated)) {
|
|
208
|
-
migrated.actor = migrated.requester;
|
|
209
|
-
}
|
|
210
|
-
delete migrated.requester;
|
|
211
|
-
if (migrated.type === "requester_recorded") {
|
|
212
|
-
migrated.type = "actor_recorded";
|
|
213
|
-
}
|
|
214
|
-
if ("requesterId" in migrated && !("actorId" in migrated)) {
|
|
215
|
-
migrated.actorId = migrated.requesterId;
|
|
216
|
-
}
|
|
217
|
-
delete migrated.requesterId;
|
|
218
|
-
return migrated;
|
|
219
|
-
}
|
|
220
|
-
function normalizeMessageCount(value) {
|
|
221
|
-
return Number.isFinite(value) ? Math.max(0, Math.floor(value)) : 0;
|
|
222
|
-
}
|
|
223
|
-
function countMatchingPrefix(left, right) {
|
|
224
|
-
const limit = Math.min(left.length, right.length);
|
|
225
|
-
for (let index = 0; index < limit; index += 1) {
|
|
226
|
-
if (!isDeepStrictEqual(left[index], right[index])) {
|
|
227
|
-
return index;
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
return limit;
|
|
231
|
-
}
|
|
232
|
-
function entrySessionId(entry) {
|
|
233
|
-
return entry.sessionId ?? INITIAL_SESSION_ID;
|
|
234
|
-
}
|
|
235
|
-
function isActivityEntry(entry) {
|
|
236
|
-
return entry.type === "tool_execution_started" || entry.type === "subagent_started" || entry.type === "subagent_ended";
|
|
237
|
-
}
|
|
238
|
-
function latestProjectionResetIndex(entries) {
|
|
239
|
-
for (let index = entries.length - 1; index >= 0; index -= 1) {
|
|
240
|
-
if (entries[index]?.type === "projection_reset") {
|
|
241
|
-
return index;
|
|
242
|
-
}
|
|
243
|
-
}
|
|
244
|
-
return -1;
|
|
245
|
-
}
|
|
246
|
-
function currentSessionId(entries) {
|
|
247
|
-
const resetIndex = latestProjectionResetIndex(entries);
|
|
248
|
-
if (resetIndex < 0) {
|
|
249
|
-
return INITIAL_SESSION_ID;
|
|
250
|
-
}
|
|
251
|
-
return entrySessionId(entries[resetIndex]);
|
|
252
|
-
}
|
|
253
|
-
function nextSessionId(entries) {
|
|
254
|
-
const resetCount = entries.filter(
|
|
255
|
-
(entry) => entry.type === "projection_reset"
|
|
256
|
-
).length;
|
|
257
|
-
return `${SESSION_ID_PREFIX}${resetCount + 1}`;
|
|
258
|
-
}
|
|
259
|
-
function projectionEntries(entries, sessionId) {
|
|
260
|
-
if (sessionId) {
|
|
261
|
-
const sessionEntries = [];
|
|
262
|
-
let started = false;
|
|
263
|
-
for (const entry of entries) {
|
|
264
|
-
const entryId = entrySessionId(entry);
|
|
265
|
-
if (!started) {
|
|
266
|
-
if (entryId !== sessionId) {
|
|
267
|
-
continue;
|
|
268
|
-
}
|
|
269
|
-
started = true;
|
|
270
|
-
} else if (entry.type === "projection_reset" && entryId !== sessionId) {
|
|
271
|
-
break;
|
|
272
|
-
}
|
|
273
|
-
if (entryId === sessionId) {
|
|
274
|
-
sessionEntries.push(entry);
|
|
275
|
-
}
|
|
276
|
-
}
|
|
277
|
-
return sessionEntries;
|
|
278
|
-
}
|
|
279
|
-
const resetIndex = latestProjectionResetIndex(entries);
|
|
280
|
-
const startIndex = resetIndex < 0 ? 0 : resetIndex;
|
|
281
|
-
const currentId = resetIndex < 0 ? INITIAL_SESSION_ID : entrySessionId(entries[resetIndex]);
|
|
282
|
-
return entries.slice(startIndex).filter((entry) => entrySessionId(entry) === currentId);
|
|
283
|
-
}
|
|
284
|
-
function piEntry(message, sessionId, provenance) {
|
|
285
|
-
return {
|
|
286
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
287
|
-
type: "pi_message",
|
|
288
|
-
sessionId,
|
|
289
|
-
message,
|
|
290
|
-
// Ambient context is the decode default, so only attributed/instruction
|
|
291
|
-
// provenance needs to be persisted on the entry.
|
|
292
|
-
...provenance && !isDefaultContextProvenance(provenance) ? { provenance } : {}
|
|
293
|
-
};
|
|
294
|
-
}
|
|
295
|
-
function resetEntry(messages, sessionId, provenance) {
|
|
296
|
-
if (provenance.length !== messages.length) {
|
|
297
|
-
throw new Error(
|
|
298
|
-
"projection_reset provenance must align one-to-one with messages"
|
|
299
|
-
);
|
|
300
|
-
}
|
|
301
|
-
return {
|
|
302
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
303
|
-
type: "projection_reset",
|
|
304
|
-
sessionId,
|
|
305
|
-
messages,
|
|
306
|
-
provenance
|
|
307
|
-
};
|
|
308
|
-
}
|
|
309
|
-
function mcpProviderConnectedEntry(provider, sessionId) {
|
|
310
|
-
return {
|
|
311
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
312
|
-
type: "mcp_provider_connected",
|
|
313
|
-
sessionId,
|
|
314
|
-
provider
|
|
315
|
-
};
|
|
316
|
-
}
|
|
317
|
-
function authorizationObservationMessage(entry) {
|
|
318
|
-
const label = entry.kind === "mcp" ? "MCP authorization" : "Authorization";
|
|
319
|
-
return {
|
|
320
|
-
role: "user",
|
|
321
|
-
content: [
|
|
322
|
-
{
|
|
323
|
-
type: "text",
|
|
324
|
-
text: `${label} completed for provider "${entry.provider}". Continue the blocked request and retry the provider operation if needed.`
|
|
325
|
-
}
|
|
326
|
-
],
|
|
327
|
-
timestamp: entry.createdAtMs
|
|
328
|
-
};
|
|
329
|
-
}
|
|
330
|
-
function authorizationRequestedEntry(args) {
|
|
331
|
-
return {
|
|
332
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
333
|
-
type: "authorization_requested",
|
|
334
|
-
sessionId: args.sessionId,
|
|
335
|
-
createdAtMs: args.createdAtMs,
|
|
336
|
-
kind: args.kind,
|
|
337
|
-
provider: args.provider,
|
|
338
|
-
actorId: args.actorId,
|
|
339
|
-
authorizationId: args.authorizationId,
|
|
340
|
-
delivery: args.delivery
|
|
341
|
-
};
|
|
342
|
-
}
|
|
343
|
-
function authorizationCompletedEntry(args) {
|
|
344
|
-
return {
|
|
345
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
346
|
-
type: "authorization_completed",
|
|
347
|
-
sessionId: args.sessionId,
|
|
348
|
-
createdAtMs: args.createdAtMs,
|
|
349
|
-
kind: args.kind,
|
|
350
|
-
provider: args.provider,
|
|
351
|
-
actorId: args.actorId,
|
|
352
|
-
authorizationId: args.authorizationId
|
|
353
|
-
};
|
|
354
|
-
}
|
|
355
|
-
function toolExecutionStartedEntry(args) {
|
|
356
|
-
return {
|
|
357
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
358
|
-
type: "tool_execution_started",
|
|
359
|
-
sessionId: args.sessionId,
|
|
360
|
-
createdAtMs: args.createdAtMs,
|
|
361
|
-
toolCallId: args.toolCallId,
|
|
362
|
-
toolName: args.toolName,
|
|
363
|
-
...args.args !== void 0 ? { args: args.args } : {}
|
|
364
|
-
};
|
|
365
|
-
}
|
|
366
|
-
function subagentStartedEntry(args) {
|
|
367
|
-
return {
|
|
368
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
369
|
-
type: "subagent_started",
|
|
370
|
-
sessionId: args.sessionId,
|
|
371
|
-
subagentInvocationId: args.subagentInvocationId,
|
|
372
|
-
subagentKind: args.subagentKind,
|
|
373
|
-
...args.parentToolCallId ? { parentToolCallId: args.parentToolCallId } : {},
|
|
374
|
-
parentConversationId: args.parentConversationId,
|
|
375
|
-
...args.parentSessionId ? { parentSessionId: args.parentSessionId } : {},
|
|
376
|
-
transcriptRef: args.transcriptRef,
|
|
377
|
-
historyMode: args.historyMode,
|
|
378
|
-
createdAtMs: args.createdAtMs
|
|
379
|
-
};
|
|
380
|
-
}
|
|
381
|
-
function subagentEndedEntry(args) {
|
|
382
|
-
return {
|
|
383
|
-
schemaVersion: AGENT_SESSION_LOG_SCHEMA_VERSION,
|
|
384
|
-
type: "subagent_ended",
|
|
385
|
-
sessionId: args.sessionId,
|
|
386
|
-
subagentInvocationId: args.subagentInvocationId,
|
|
387
|
-
outcome: args.outcome,
|
|
388
|
-
...args.errorCode ? { errorCode: args.errorCode } : {},
|
|
389
|
-
...args.transcriptEndMessageIndex !== void 0 ? { transcriptEndMessageIndex: args.transcriptEndMessageIndex } : {},
|
|
390
|
-
...args.transcriptStartMessageIndex !== void 0 ? { transcriptStartMessageIndex: args.transcriptStartMessageIndex } : {},
|
|
391
|
-
createdAtMs: args.createdAtMs
|
|
392
|
-
};
|
|
393
|
-
}
|
|
394
|
-
function decode(value) {
|
|
395
|
-
if (typeof value === "string") {
|
|
396
|
-
return decode(JSON.parse(value));
|
|
397
|
-
}
|
|
398
|
-
const parsed = sessionLogEntrySchema.safeParse(migrateStoredEntry(value));
|
|
399
|
-
if (parsed.success) {
|
|
400
|
-
return parsed.data;
|
|
401
|
-
}
|
|
402
|
-
return piEntry(piMessageSchema.parse(value), INITIAL_SESSION_ID);
|
|
403
|
-
}
|
|
404
|
-
function piEntryProvenance(entry) {
|
|
405
|
-
if (entry.provenance) {
|
|
406
|
-
return entry.provenance;
|
|
407
|
-
}
|
|
408
|
-
if (entry.actor) {
|
|
409
|
-
return legacyActorProvenance(entry.actor);
|
|
410
|
-
}
|
|
411
|
-
return unattributedContextProvenance;
|
|
412
|
-
}
|
|
413
|
-
function project(entries, sessionId) {
|
|
414
|
-
let messages = [];
|
|
415
|
-
let provenance = [];
|
|
416
|
-
for (const entry of projectionEntries(entries, sessionId)) {
|
|
417
|
-
if (entry.type === "pi_message") {
|
|
418
|
-
messages.push(entry.message);
|
|
419
|
-
provenance.push(piEntryProvenance(entry));
|
|
420
|
-
continue;
|
|
421
|
-
}
|
|
422
|
-
if (entry.type === "authorization_completed") {
|
|
423
|
-
messages.push(authorizationObservationMessage(entry));
|
|
424
|
-
provenance.push(unattributedContextProvenance);
|
|
425
|
-
continue;
|
|
426
|
-
}
|
|
427
|
-
if (entry.type === "projection_reset") {
|
|
428
|
-
const resetProvenance = entry.provenance ?? entry.messages.map(() => unattributedContextProvenance);
|
|
429
|
-
if (resetProvenance.length !== entry.messages.length) {
|
|
430
|
-
throw new Error(
|
|
431
|
-
"projection_reset provenance must align one-to-one with messages"
|
|
432
|
-
);
|
|
433
|
-
}
|
|
434
|
-
messages = [...entry.messages];
|
|
435
|
-
provenance = [...resetProvenance];
|
|
436
|
-
continue;
|
|
437
|
-
}
|
|
438
|
-
}
|
|
439
|
-
return { messages, provenance };
|
|
440
|
-
}
|
|
441
|
-
function actorIdentityKey(actor) {
|
|
442
|
-
if (actor.platform === "system") {
|
|
443
|
-
return `system ${actor.name}`;
|
|
444
|
-
}
|
|
445
|
-
return actor.platform === "slack" ? `slack\0${actor.teamId}\0${actor.userId}` : `${actor.platform}\0${actor.userId}`;
|
|
446
|
-
}
|
|
447
|
-
function instructionActors(provenance) {
|
|
448
|
-
const seen = /* @__PURE__ */ new Set();
|
|
449
|
-
const actors = [];
|
|
450
|
-
for (const entry of provenance) {
|
|
451
|
-
if (entry.authority !== "instruction" || !entry.actor) {
|
|
452
|
-
continue;
|
|
453
|
-
}
|
|
454
|
-
const identity = actorIdentityKey(entry.actor);
|
|
455
|
-
if (seen.has(identity)) {
|
|
456
|
-
continue;
|
|
457
|
-
}
|
|
458
|
-
seen.add(identity);
|
|
459
|
-
actors.push(entry.actor);
|
|
460
|
-
}
|
|
461
|
-
return actors;
|
|
462
|
-
}
|
|
463
|
-
function connectedMcpProviders(entries, sessionId) {
|
|
464
|
-
const providers = /* @__PURE__ */ new Set();
|
|
465
|
-
for (const entry of projectionEntries(entries, sessionId)) {
|
|
466
|
-
if (entry.type === "mcp_provider_connected") {
|
|
467
|
-
providers.add(entry.provider);
|
|
468
|
-
}
|
|
469
|
-
}
|
|
470
|
-
return [...providers].sort((left, right) => left.localeCompare(right));
|
|
471
|
-
}
|
|
472
|
-
function isUserMessage(message) {
|
|
473
|
-
return message.role === "user";
|
|
474
|
-
}
|
|
475
|
-
function resolveCommitProvenance(args) {
|
|
476
|
-
if (args.explicitProvenance) {
|
|
477
|
-
if (args.explicitProvenance.length !== args.nextMessages.length) {
|
|
478
|
-
throw new Error("commit provenance must align one-to-one with messages");
|
|
479
|
-
}
|
|
480
|
-
return args.explicitProvenance;
|
|
481
|
-
}
|
|
482
|
-
const matchingPrefix = countMatchingPrefix(
|
|
483
|
-
args.existing.messages,
|
|
484
|
-
args.nextMessages
|
|
485
|
-
);
|
|
486
|
-
const provenance = args.nextMessages.map(
|
|
487
|
-
(_, index) => index < matchingPrefix ? args.existing.provenance[index] ?? unattributedContextProvenance : unattributedContextProvenance
|
|
488
|
-
);
|
|
489
|
-
if (args.newMessageProvenance) {
|
|
490
|
-
for (let index = args.nextMessages.length - 1; index >= matchingPrefix; index -= 1) {
|
|
491
|
-
if (isUserMessage(args.nextMessages[index])) {
|
|
492
|
-
provenance[index] = args.newMessageProvenance;
|
|
493
|
-
break;
|
|
494
|
-
}
|
|
495
|
-
}
|
|
496
|
-
}
|
|
497
|
-
if (args.trailingMessageProvenance) {
|
|
498
|
-
if (args.trailingMessageProvenance.length > provenance.length) {
|
|
499
|
-
throw new Error(
|
|
500
|
-
"trailing commit provenance cannot exceed committed messages"
|
|
501
|
-
);
|
|
502
|
-
}
|
|
503
|
-
const newMessageCount = args.nextMessages.length - matchingPrefix;
|
|
504
|
-
if (args.trailingMessageProvenance.length > newMessageCount) {
|
|
505
|
-
throw new Error(
|
|
506
|
-
"trailing commit provenance must align to newly committed messages"
|
|
507
|
-
);
|
|
508
|
-
}
|
|
509
|
-
const start = provenance.length - args.trailingMessageProvenance.length;
|
|
510
|
-
args.trailingMessageProvenance.forEach((entry, offset) => {
|
|
511
|
-
provenance[start + offset] = entry;
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
return provenance;
|
|
515
|
-
}
|
|
516
|
-
function commitEntries(existing, nextMessages, nextProvenance, sessionId, entries) {
|
|
517
|
-
const matchingPrefix = countMatchingPrefix(existing.messages, nextMessages);
|
|
518
|
-
if (matchingPrefix === existing.messages.length) {
|
|
519
|
-
const newMessages = nextMessages.slice(matchingPrefix);
|
|
520
|
-
const newProvenance = nextProvenance.slice(matchingPrefix);
|
|
521
|
-
return {
|
|
522
|
-
entries: newMessages.map(
|
|
523
|
-
(message, index) => piEntry(message, sessionId, newProvenance[index])
|
|
524
|
-
),
|
|
525
|
-
sessionId
|
|
526
|
-
};
|
|
527
|
-
}
|
|
528
|
-
const resetSessionId = nextSessionId(entries);
|
|
529
|
-
return {
|
|
530
|
-
entries: [resetEntry(nextMessages, resetSessionId, nextProvenance)],
|
|
531
|
-
sessionId: resetSessionId
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
function redisStore(redisStateAdapter) {
|
|
535
|
-
const client = redisStateAdapter.getClient();
|
|
536
|
-
return {
|
|
537
|
-
async append({ entries, scope, ttlMs }) {
|
|
538
|
-
const listKey = key(scope);
|
|
539
|
-
if (entries.length > 0) {
|
|
540
|
-
await client.rPush(
|
|
541
|
-
listKey,
|
|
542
|
-
entries.map((entry) => JSON.stringify(entry))
|
|
543
|
-
);
|
|
544
|
-
}
|
|
545
|
-
await client.pExpire(listKey, Math.max(1, ttlMs));
|
|
546
|
-
},
|
|
547
|
-
async read(scope) {
|
|
548
|
-
const values = await client.lRange(key(scope), 0, -1);
|
|
549
|
-
return values.map(decode);
|
|
550
|
-
}
|
|
551
|
-
};
|
|
552
|
-
}
|
|
553
|
-
function stateStore() {
|
|
554
|
-
const stateAdapter = getStateAdapter();
|
|
555
|
-
return {
|
|
556
|
-
async append({ entries, scope, ttlMs }) {
|
|
557
|
-
const listKey = rawKey(scope);
|
|
558
|
-
const lock = await stateAdapter.acquireLock(
|
|
559
|
-
`${listKey}:commit`,
|
|
560
|
-
STATE_STORE_LOCK_TTL_MS
|
|
561
|
-
);
|
|
562
|
-
if (!lock) {
|
|
563
|
-
throw new Error("Could not acquire session log commit lock");
|
|
564
|
-
}
|
|
565
|
-
try {
|
|
566
|
-
const existingValue = await stateAdapter.get(listKey);
|
|
567
|
-
const existingEntries = Array.isArray(existingValue) ? existingValue.map(decode) : (await stateAdapter.getList(listKey)).map(decode);
|
|
568
|
-
await stateAdapter.set(
|
|
569
|
-
listKey,
|
|
570
|
-
[...existingEntries, ...entries],
|
|
571
|
-
Math.max(1, ttlMs)
|
|
572
|
-
);
|
|
573
|
-
} finally {
|
|
574
|
-
await stateAdapter.releaseLock(lock);
|
|
575
|
-
}
|
|
576
|
-
},
|
|
577
|
-
async read(scope) {
|
|
578
|
-
const listKey = rawKey(scope);
|
|
579
|
-
const value = await stateAdapter.get(listKey);
|
|
580
|
-
if (Array.isArray(value)) {
|
|
581
|
-
return value.map(decode);
|
|
582
|
-
}
|
|
583
|
-
const values = await stateAdapter.getList(listKey);
|
|
584
|
-
return values.map(decode);
|
|
585
|
-
}
|
|
586
|
-
};
|
|
587
|
-
}
|
|
588
|
-
async function defaultStore() {
|
|
589
|
-
const { redisStateAdapter, stateAdapter } = await getConnectedStateContext();
|
|
590
|
-
if (redisStateAdapter) {
|
|
591
|
-
return redisStore(redisStateAdapter);
|
|
592
|
-
}
|
|
593
|
-
await stateAdapter.connect();
|
|
594
|
-
return stateStore();
|
|
595
|
-
}
|
|
596
|
-
async function loadEntries(args) {
|
|
597
|
-
const store = args.store ?? await defaultStore();
|
|
598
|
-
return (await store.read(args)).map(decode);
|
|
599
|
-
}
|
|
600
|
-
async function loadActivityEntries(args) {
|
|
601
|
-
const entries = await loadEntries(args);
|
|
602
|
-
return projectionEntries(entries, args.sessionId).filter(isActivityEntry);
|
|
603
|
-
}
|
|
604
|
-
async function loadMessagesWithProvenance(args) {
|
|
605
|
-
const messageCount = normalizeMessageCount(args.messageCount);
|
|
606
|
-
if (messageCount === 0) {
|
|
607
|
-
return { messages: [], provenance: [] };
|
|
608
|
-
}
|
|
609
|
-
const projection = project(await loadEntries(args), args.sessionId);
|
|
610
|
-
return projection.messages.length >= messageCount ? {
|
|
611
|
-
messages: projection.messages.slice(0, messageCount),
|
|
612
|
-
provenance: projection.provenance.slice(0, messageCount)
|
|
613
|
-
} : void 0;
|
|
614
|
-
}
|
|
615
|
-
async function loadProjection(args) {
|
|
616
|
-
return project(await loadEntries(args), args.sessionId).messages;
|
|
617
|
-
}
|
|
618
|
-
async function loadProjectionWithProvenance(args) {
|
|
619
|
-
return project(await loadEntries(args), args.sessionId);
|
|
620
|
-
}
|
|
621
|
-
async function loadConnectedMcpProviders(args) {
|
|
622
|
-
return connectedMcpProviders(await loadEntries(args));
|
|
623
|
-
}
|
|
624
|
-
async function recordMcpProviderConnected(args) {
|
|
625
|
-
const store = args.store ?? await defaultStore();
|
|
626
|
-
const entries = await store.read(args);
|
|
627
|
-
const sessionId = currentSessionId(entries);
|
|
628
|
-
if (connectedMcpProviders(entries).includes(args.provider)) {
|
|
629
|
-
return;
|
|
630
|
-
}
|
|
631
|
-
await store.append({
|
|
632
|
-
scope: args,
|
|
633
|
-
entries: [mcpProviderConnectedEntry(args.provider, sessionId)],
|
|
634
|
-
ttlMs: args.ttlMs
|
|
635
|
-
});
|
|
636
|
-
}
|
|
637
|
-
async function recordAuthorizationRequested(args) {
|
|
638
|
-
const store = args.store ?? await defaultStore();
|
|
639
|
-
const entries = await store.read(args);
|
|
640
|
-
const sessionId = currentSessionId(entries);
|
|
641
|
-
if (projectionEntries(entries).some(
|
|
642
|
-
(entry) => entry.type === "authorization_requested" && entry.authorizationId === args.authorizationId
|
|
643
|
-
)) {
|
|
644
|
-
return;
|
|
645
|
-
}
|
|
646
|
-
await store.append({
|
|
647
|
-
scope: args,
|
|
648
|
-
entries: [
|
|
649
|
-
authorizationRequestedEntry({
|
|
650
|
-
createdAtMs: Date.now(),
|
|
651
|
-
kind: args.kind,
|
|
652
|
-
sessionId,
|
|
653
|
-
provider: args.provider,
|
|
654
|
-
actorId: args.actorId,
|
|
655
|
-
authorizationId: args.authorizationId,
|
|
656
|
-
delivery: args.delivery
|
|
657
|
-
})
|
|
658
|
-
],
|
|
659
|
-
ttlMs: args.ttlMs
|
|
660
|
-
});
|
|
661
|
-
}
|
|
662
|
-
async function recordAuthorizationCompleted(args) {
|
|
663
|
-
const store = args.store ?? await defaultStore();
|
|
664
|
-
const entries = await store.read(args);
|
|
665
|
-
const sessionId = currentSessionId(entries);
|
|
666
|
-
if (projectionEntries(entries).some(
|
|
667
|
-
(entry) => entry.type === "authorization_completed" && entry.authorizationId === args.authorizationId
|
|
668
|
-
)) {
|
|
669
|
-
return;
|
|
670
|
-
}
|
|
671
|
-
await store.append({
|
|
672
|
-
scope: args,
|
|
673
|
-
entries: [
|
|
674
|
-
authorizationCompletedEntry({
|
|
675
|
-
createdAtMs: Date.now(),
|
|
676
|
-
kind: args.kind,
|
|
677
|
-
sessionId,
|
|
678
|
-
provider: args.provider,
|
|
679
|
-
actorId: args.actorId,
|
|
680
|
-
authorizationId: args.authorizationId
|
|
681
|
-
})
|
|
682
|
-
],
|
|
683
|
-
ttlMs: args.ttlMs
|
|
684
|
-
});
|
|
685
|
-
}
|
|
686
|
-
async function recordToolExecutionStarted(args) {
|
|
687
|
-
const store = args.store ?? await defaultStore();
|
|
688
|
-
const entries = await store.read(args);
|
|
689
|
-
const sessionId = args.sessionId ?? currentSessionId(entries);
|
|
690
|
-
await store.append({
|
|
691
|
-
scope: args,
|
|
692
|
-
entries: [
|
|
693
|
-
toolExecutionStartedEntry({
|
|
694
|
-
args: args.args,
|
|
695
|
-
createdAtMs: args.createdAtMs ?? Date.now(),
|
|
696
|
-
sessionId,
|
|
697
|
-
toolCallId: args.toolCallId,
|
|
698
|
-
toolName: args.toolName
|
|
699
|
-
})
|
|
700
|
-
],
|
|
701
|
-
ttlMs: args.ttlMs
|
|
702
|
-
});
|
|
703
|
-
}
|
|
704
|
-
async function recordSubagentStarted(args) {
|
|
705
|
-
const store = args.store ?? await defaultStore();
|
|
706
|
-
const entries = await store.read(args);
|
|
707
|
-
const sessionId = args.sessionId ?? currentSessionId(entries);
|
|
708
|
-
await store.append({
|
|
709
|
-
scope: args,
|
|
710
|
-
entries: [
|
|
711
|
-
subagentStartedEntry({
|
|
712
|
-
createdAtMs: args.createdAtMs ?? Date.now(),
|
|
713
|
-
historyMode: args.historyMode,
|
|
714
|
-
parentConversationId: args.parentConversationId,
|
|
715
|
-
parentSessionId: args.parentSessionId,
|
|
716
|
-
parentToolCallId: args.parentToolCallId,
|
|
717
|
-
sessionId,
|
|
718
|
-
subagentInvocationId: args.subagentInvocationId,
|
|
719
|
-
subagentKind: args.subagentKind,
|
|
720
|
-
transcriptRef: args.transcriptRef
|
|
721
|
-
})
|
|
722
|
-
],
|
|
723
|
-
ttlMs: args.ttlMs
|
|
724
|
-
});
|
|
725
|
-
}
|
|
726
|
-
async function recordSubagentEnded(args) {
|
|
727
|
-
const store = args.store ?? await defaultStore();
|
|
728
|
-
const entries = await store.read(args);
|
|
729
|
-
const sessionId = args.sessionId ?? currentSessionId(entries);
|
|
730
|
-
await store.append({
|
|
731
|
-
scope: args,
|
|
732
|
-
entries: [
|
|
733
|
-
subagentEndedEntry({
|
|
734
|
-
createdAtMs: args.createdAtMs ?? Date.now(),
|
|
735
|
-
errorCode: args.errorCode,
|
|
736
|
-
outcome: args.outcome,
|
|
737
|
-
sessionId,
|
|
738
|
-
subagentInvocationId: args.subagentInvocationId,
|
|
739
|
-
transcriptEndMessageIndex: args.transcriptEndMessageIndex,
|
|
740
|
-
transcriptStartMessageIndex: args.transcriptStartMessageIndex
|
|
741
|
-
})
|
|
742
|
-
],
|
|
743
|
-
ttlMs: args.ttlMs
|
|
744
|
-
});
|
|
745
|
-
}
|
|
746
|
-
async function commitMessages(args) {
|
|
747
|
-
const store = args.store ?? await defaultStore();
|
|
748
|
-
const entries = await store.read(args);
|
|
749
|
-
const existingProjection = project(entries);
|
|
750
|
-
const currentId = currentSessionId(entries);
|
|
751
|
-
const nextProvenance = resolveCommitProvenance({
|
|
752
|
-
existing: existingProjection,
|
|
753
|
-
nextMessages: args.messages,
|
|
754
|
-
...args.provenance ? { explicitProvenance: args.provenance } : {},
|
|
755
|
-
...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
|
|
756
|
-
...args.newMessageProvenance ? { newMessageProvenance: args.newMessageProvenance } : {}
|
|
757
|
-
});
|
|
758
|
-
const commit = commitEntries(
|
|
759
|
-
existingProjection,
|
|
760
|
-
args.messages,
|
|
761
|
-
nextProvenance,
|
|
762
|
-
currentId,
|
|
763
|
-
entries
|
|
764
|
-
);
|
|
765
|
-
await store.append({
|
|
766
|
-
scope: args,
|
|
767
|
-
entries: commit.entries,
|
|
768
|
-
ttlMs: args.ttlMs
|
|
769
|
-
});
|
|
770
|
-
return {
|
|
771
|
-
sessionId: commit.sessionId,
|
|
772
|
-
provenance: nextProvenance
|
|
773
|
-
};
|
|
774
|
-
}
|
|
775
|
-
function instructionProvenanceFor(actor) {
|
|
776
|
-
return instructionProvenance(actor);
|
|
777
|
-
}
|
|
778
|
-
var contextProvenance = unattributedContextProvenance;
|
|
779
|
-
function parseStoredMessageProvenance(value, expectedLength) {
|
|
780
|
-
if (value === void 0) {
|
|
781
|
-
return Array.from(
|
|
782
|
-
{ length: expectedLength },
|
|
783
|
-
() => unattributedContextProvenance
|
|
784
|
-
);
|
|
785
|
-
}
|
|
786
|
-
const parsed = z2.array(piMessageProvenanceSchema).safeParse(value);
|
|
787
|
-
if (!parsed.success || parsed.data.length !== expectedLength) {
|
|
788
|
-
return void 0;
|
|
789
|
-
}
|
|
790
|
-
return parsed.data;
|
|
791
|
-
}
|
|
792
|
-
|
|
793
|
-
// src/chat/state/turn-session.ts
|
|
794
|
-
import { THREAD_STATE_TTL_MS } from "chat";
|
|
795
|
-
import {
|
|
796
|
-
sourceSchema
|
|
797
|
-
} from "@sentry/junior-plugin-api";
|
|
798
|
-
var AGENT_TURN_SESSION_PREFIX = "junior:agent_turn_session";
|
|
799
|
-
var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
|
|
800
|
-
var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
|
|
801
|
-
var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
|
|
802
|
-
function agentTurnSessionKey(conversationId, sessionId) {
|
|
803
|
-
return `${AGENT_TURN_SESSION_PREFIX}:${conversationId}:${sessionId}`;
|
|
804
|
-
}
|
|
805
|
-
function agentTurnSessionConversationIndexKey(conversationId) {
|
|
806
|
-
return `${AGENT_TURN_SESSION_PREFIX}:conversation:${conversationId}:index`;
|
|
807
|
-
}
|
|
808
|
-
function toFiniteNonNegativeNumber(value) {
|
|
809
|
-
return typeof value === "number" && Number.isFinite(value) ? Math.max(0, Math.floor(value)) : void 0;
|
|
810
|
-
}
|
|
811
|
-
function toNonNegativeInteger(value) {
|
|
812
|
-
return typeof value === "number" && Number.isInteger(value) && value >= 0 ? value : void 0;
|
|
813
|
-
}
|
|
814
|
-
function parseAgentTurnUsage(value) {
|
|
815
|
-
if (!isRecord(value)) {
|
|
816
|
-
return void 0;
|
|
817
|
-
}
|
|
818
|
-
const usage = {};
|
|
819
|
-
for (const field of [
|
|
820
|
-
"inputTokens",
|
|
821
|
-
"outputTokens",
|
|
822
|
-
"cachedInputTokens",
|
|
823
|
-
"cacheCreationTokens",
|
|
824
|
-
"totalTokens"
|
|
825
|
-
]) {
|
|
826
|
-
const count = toFiniteNonNegativeNumber(value[field]);
|
|
827
|
-
if (count !== void 0) {
|
|
828
|
-
usage[field] = count;
|
|
829
|
-
}
|
|
830
|
-
}
|
|
831
|
-
return Object.keys(usage).length > 0 ? usage : void 0;
|
|
832
|
-
}
|
|
833
|
-
function parseStoredRecord(value) {
|
|
834
|
-
if (isRecord(value)) {
|
|
835
|
-
return value;
|
|
836
|
-
}
|
|
837
|
-
if (typeof value !== "string") {
|
|
838
|
-
return void 0;
|
|
839
|
-
}
|
|
840
|
-
try {
|
|
841
|
-
const parsed = JSON.parse(value);
|
|
842
|
-
return isRecord(parsed) ? parsed : void 0;
|
|
843
|
-
} catch {
|
|
844
|
-
return void 0;
|
|
845
|
-
}
|
|
846
|
-
}
|
|
847
|
-
function parseAgentTurnSessionStatus(parsed) {
|
|
848
|
-
const status = parsed.state;
|
|
849
|
-
if (status === "running" || status === "awaiting_resume" || status === "completed" || status === "failed" || status === "abandoned") {
|
|
850
|
-
return status;
|
|
851
|
-
}
|
|
852
|
-
return void 0;
|
|
853
|
-
}
|
|
854
|
-
function parseAgentTurnSurface(value) {
|
|
855
|
-
return value === "slack" || value === "api" || value === "scheduler" || value === "internal" ? value : void 0;
|
|
856
|
-
}
|
|
857
|
-
function conversationExecutionFromSummary(summary) {
|
|
858
|
-
const status = summary.state === "completed" || summary.state === "abandoned" ? "idle" : summary.state;
|
|
859
|
-
return {
|
|
860
|
-
status,
|
|
861
|
-
runId: summary.sessionId,
|
|
862
|
-
updatedAtMs: summary.updatedAtMs
|
|
863
|
-
};
|
|
864
|
-
}
|
|
865
|
-
function parseSource(value) {
|
|
866
|
-
const result = sourceSchema.safeParse(value);
|
|
867
|
-
return result.success ? result.data : void 0;
|
|
868
|
-
}
|
|
869
|
-
function sessionLogActor(actor) {
|
|
870
|
-
return actor?.platform === "slack" ? toStoredSlackActor(actor) : void 0;
|
|
871
|
-
}
|
|
872
|
-
function parseAgentTurnSessionFields(parsed) {
|
|
873
|
-
const status = parseAgentTurnSessionStatus(parsed);
|
|
874
|
-
if (!status) {
|
|
875
|
-
return void 0;
|
|
876
|
-
}
|
|
877
|
-
const channelName = typeof parsed.channelName === "string" && parsed.channelName.trim() ? parsed.channelName.trim() : void 0;
|
|
878
|
-
const conversationId = parsed.conversationId;
|
|
879
|
-
const sessionId = parsed.sessionId;
|
|
880
|
-
const sliceId = toFiniteNonNegativeNumber(parsed.sliceId);
|
|
881
|
-
const version = toFiniteNonNegativeNumber(parsed.version);
|
|
882
|
-
const updatedAtMs = toFiniteNonNegativeNumber(parsed.updatedAtMs);
|
|
883
|
-
const cumulativeDurationMs = toFiniteNonNegativeNumber(parsed.cumulativeDurationMs) ?? 0;
|
|
884
|
-
const cumulativeUsage = parseAgentTurnUsage(parsed.cumulativeUsage);
|
|
885
|
-
const lastProgressAtMs = toFiniteNonNegativeNumber(parsed.lastProgressAtMs);
|
|
886
|
-
const logSessionId = typeof parsed.logSessionId === "string" ? parsed.logSessionId : void 0;
|
|
887
|
-
const actorValue = parsed.actor !== void 0 ? parsed.actor : parsed.requester;
|
|
888
|
-
const actor = actorValue === void 0 ? void 0 : parseActor(actorValue);
|
|
889
|
-
const startedAtMs = toFiniteNonNegativeNumber(parsed.startedAtMs);
|
|
890
|
-
const surface = parseAgentTurnSurface(parsed.surface);
|
|
891
|
-
const turnStartMessageIndex = toNonNegativeInteger(
|
|
892
|
-
parsed.turnStartMessageIndex
|
|
893
|
-
);
|
|
894
|
-
const destination = parsed.destination === void 0 ? void 0 : parseDestination(parsed.destination);
|
|
895
|
-
const source = parsed.source === void 0 ? void 0 : parseSource(parsed.source);
|
|
896
|
-
if (typeof conversationId !== "string" || typeof sessionId !== "string" || sliceId === void 0 || version === void 0 || updatedAtMs === void 0 || parsed.destination !== void 0 && !destination || parsed.source !== void 0 && !source || actorValue !== void 0 && !actor) {
|
|
897
|
-
return void 0;
|
|
898
|
-
}
|
|
899
|
-
return {
|
|
900
|
-
version,
|
|
901
|
-
...channelName ? { channelName } : {},
|
|
902
|
-
conversationId,
|
|
903
|
-
sessionId,
|
|
904
|
-
sliceId,
|
|
905
|
-
state: status,
|
|
906
|
-
startedAtMs: startedAtMs ?? updatedAtMs,
|
|
907
|
-
lastProgressAtMs: lastProgressAtMs ?? updatedAtMs,
|
|
908
|
-
updatedAtMs,
|
|
909
|
-
cumulativeDurationMs,
|
|
910
|
-
...logSessionId ? { logSessionId } : {},
|
|
911
|
-
...cumulativeUsage ? { cumulativeUsage } : {},
|
|
912
|
-
...destination ? { destination } : {},
|
|
913
|
-
...source ? { source } : {},
|
|
914
|
-
...actor ? { actor } : {},
|
|
915
|
-
...Array.isArray(parsed.loadedSkillNames) ? {
|
|
916
|
-
loadedSkillNames: parsed.loadedSkillNames.filter(
|
|
917
|
-
(value) => typeof value === "string"
|
|
918
|
-
)
|
|
919
|
-
} : {},
|
|
920
|
-
...parsed.resumeReason === "timeout" || parsed.resumeReason === "auth" || parsed.resumeReason === "yield" ? { resumeReason: parsed.resumeReason } : {},
|
|
921
|
-
...typeof parsed.errorMessage === "string" ? { errorMessage: parsed.errorMessage } : {},
|
|
922
|
-
...typeof parsed.resumedFromSliceId === "number" ? { resumedFromSliceId: parsed.resumedFromSliceId } : {},
|
|
923
|
-
...surface ? { surface } : {},
|
|
924
|
-
...turnStartMessageIndex !== void 0 ? { turnStartMessageIndex } : {},
|
|
925
|
-
...typeof parsed.traceId === "string" ? { traceId: parsed.traceId } : {}
|
|
926
|
-
};
|
|
927
|
-
}
|
|
928
|
-
function parseAgentTurnSessionRecord(value) {
|
|
929
|
-
const parsed = parseStoredRecord(value);
|
|
930
|
-
if (!parsed) {
|
|
931
|
-
return void 0;
|
|
932
|
-
}
|
|
933
|
-
const fields = parseAgentTurnSessionFields(parsed);
|
|
934
|
-
const committedMessageCount = toFiniteNonNegativeNumber(
|
|
935
|
-
parsed.committedMessageCount
|
|
936
|
-
);
|
|
937
|
-
if (!fields || committedMessageCount === void 0) {
|
|
938
|
-
return void 0;
|
|
939
|
-
}
|
|
940
|
-
const committedMessageProvenance = parseStoredMessageProvenance(
|
|
941
|
-
parsed.committedMessageProvenance,
|
|
942
|
-
committedMessageCount
|
|
943
|
-
);
|
|
944
|
-
if (!committedMessageProvenance) {
|
|
945
|
-
return void 0;
|
|
946
|
-
}
|
|
947
|
-
return {
|
|
948
|
-
...fields,
|
|
949
|
-
committedMessageCount,
|
|
950
|
-
committedMessageProvenance
|
|
951
|
-
};
|
|
952
|
-
}
|
|
953
|
-
function parseAgentTurnSessionSummary(value) {
|
|
954
|
-
const stored = parseStoredRecord(value);
|
|
955
|
-
if (!stored) {
|
|
956
|
-
return void 0;
|
|
957
|
-
}
|
|
958
|
-
const parsed = parseAgentTurnSessionFields(stored);
|
|
959
|
-
if (!parsed) {
|
|
960
|
-
return void 0;
|
|
961
|
-
}
|
|
962
|
-
const {
|
|
963
|
-
errorMessage: _errorMessage,
|
|
964
|
-
logSessionId: _logSessionId,
|
|
965
|
-
turnStartMessageIndex: _turnStartMessageIndex,
|
|
966
|
-
...summary
|
|
967
|
-
} = parsed;
|
|
968
|
-
return summary;
|
|
969
|
-
}
|
|
970
|
-
async function appendAgentTurnSessionSummary(summary, ttlMs) {
|
|
971
|
-
const stateAdapter = getStateAdapter();
|
|
972
|
-
await Promise.all([
|
|
973
|
-
stateAdapter.appendToList(AGENT_TURN_SESSION_INDEX_KEY, summary, {
|
|
974
|
-
maxLength: AGENT_TURN_SESSION_INDEX_MAX_LENGTH,
|
|
975
|
-
ttlMs
|
|
976
|
-
}),
|
|
977
|
-
stateAdapter.appendToList(
|
|
978
|
-
agentTurnSessionConversationIndexKey(summary.conversationId),
|
|
979
|
-
summary,
|
|
980
|
-
{ ttlMs }
|
|
981
|
-
)
|
|
982
|
-
]);
|
|
983
|
-
}
|
|
984
|
-
async function recordConversationActivityMetadata(args) {
|
|
985
|
-
const conversationStore = args.conversationStore ?? getConversationStore();
|
|
986
|
-
const source = args.summary.destination?.platform === "local" ? "local" : args.summary.surface;
|
|
987
|
-
try {
|
|
988
|
-
await conversationStore.recordActivity({
|
|
989
|
-
activityAtMs: args.summary.updatedAtMs,
|
|
990
|
-
channelName: args.summary.channelName,
|
|
991
|
-
conversationId: args.summary.conversationId,
|
|
992
|
-
destination: args.summary.destination,
|
|
993
|
-
nowMs: args.nowMs,
|
|
994
|
-
actor: sessionLogActor(args.summary.actor),
|
|
995
|
-
source,
|
|
996
|
-
visibility: args.destinationVisibility
|
|
997
|
-
});
|
|
998
|
-
await conversationStore.recordExecution({
|
|
999
|
-
channelName: args.summary.channelName,
|
|
1000
|
-
conversationId: args.summary.conversationId,
|
|
1001
|
-
createdAtMs: args.summary.startedAtMs,
|
|
1002
|
-
destination: args.summary.destination,
|
|
1003
|
-
execution: conversationExecutionFromSummary(args.summary),
|
|
1004
|
-
lastActivityAtMs: args.summary.updatedAtMs,
|
|
1005
|
-
actor: sessionLogActor(args.summary.actor),
|
|
1006
|
-
source,
|
|
1007
|
-
updatedAtMs: args.nowMs,
|
|
1008
|
-
visibility: args.destinationVisibility
|
|
1009
|
-
});
|
|
1010
|
-
} catch (error) {
|
|
1011
|
-
logWarn(
|
|
1012
|
-
"conversation_activity_metadata_update_failed",
|
|
1013
|
-
{ conversationId: args.summary.conversationId },
|
|
1014
|
-
{
|
|
1015
|
-
"exception.message": error instanceof Error ? error.message : String(error)
|
|
1016
|
-
},
|
|
1017
|
-
"Failed to update conversation activity metadata"
|
|
1018
|
-
);
|
|
1019
|
-
}
|
|
1020
|
-
}
|
|
1021
|
-
function materializePiProjection(committedMessageCount, includeProjectionTail, sessionMessages, sessionProjection) {
|
|
1022
|
-
if (committedMessageCount === 0) {
|
|
1023
|
-
return sessionProjection;
|
|
1024
|
-
}
|
|
1025
|
-
if (includeProjectionTail && sessionProjection.messages.length >= committedMessageCount) {
|
|
1026
|
-
return sessionProjection;
|
|
1027
|
-
}
|
|
1028
|
-
if (sessionMessages) {
|
|
1029
|
-
return sessionMessages;
|
|
1030
|
-
}
|
|
1031
|
-
if (sessionProjection.messages.length >= committedMessageCount) {
|
|
1032
|
-
return {
|
|
1033
|
-
messages: sessionProjection.messages.slice(0, committedMessageCount),
|
|
1034
|
-
provenance: sessionProjection.provenance.slice(0, committedMessageCount)
|
|
1035
|
-
};
|
|
1036
|
-
}
|
|
1037
|
-
return void 0;
|
|
1038
|
-
}
|
|
1039
|
-
function materializeAgentTurnSessionRecord(stored, piProjection) {
|
|
1040
|
-
return {
|
|
1041
|
-
version: stored.version,
|
|
1042
|
-
...stored.channelName ? { channelName: stored.channelName } : {},
|
|
1043
|
-
conversationId: stored.conversationId,
|
|
1044
|
-
sessionId: stored.sessionId,
|
|
1045
|
-
sliceId: stored.sliceId,
|
|
1046
|
-
state: stored.state,
|
|
1047
|
-
startedAtMs: stored.startedAtMs,
|
|
1048
|
-
lastProgressAtMs: stored.lastProgressAtMs,
|
|
1049
|
-
updatedAtMs: stored.updatedAtMs,
|
|
1050
|
-
piMessages: piProjection.messages,
|
|
1051
|
-
piMessageProvenance: piProjection.provenance,
|
|
1052
|
-
actors: instructionActors(piProjection.provenance),
|
|
1053
|
-
cumulativeDurationMs: stored.cumulativeDurationMs,
|
|
1054
|
-
...stored.destination ? { destination: stored.destination } : {},
|
|
1055
|
-
...stored.source ? { source: stored.source } : {},
|
|
1056
|
-
...stored.cumulativeUsage ? { cumulativeUsage: stored.cumulativeUsage } : {},
|
|
1057
|
-
...stored.resumeReason ? { resumeReason: stored.resumeReason } : {},
|
|
1058
|
-
...stored.errorMessage ? { errorMessage: stored.errorMessage } : {},
|
|
1059
|
-
...stored.loadedSkillNames ? { loadedSkillNames: stored.loadedSkillNames } : {},
|
|
1060
|
-
...stored.actor ? { actor: stored.actor } : {},
|
|
1061
|
-
...stored.resumedFromSliceId !== void 0 ? { resumedFromSliceId: stored.resumedFromSliceId } : {},
|
|
1062
|
-
...stored.surface ? { surface: stored.surface } : {},
|
|
1063
|
-
...stored.traceId ? { traceId: stored.traceId } : {},
|
|
1064
|
-
...stored.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: stored.turnStartMessageIndex } : {}
|
|
1065
|
-
};
|
|
1066
|
-
}
|
|
1067
|
-
async function getStoredAgentTurnSessionRecord(conversationId, sessionId) {
|
|
1068
|
-
const stateAdapter = getStateAdapter();
|
|
1069
|
-
await stateAdapter.connect();
|
|
1070
|
-
const value = await stateAdapter.get(
|
|
1071
|
-
agentTurnSessionKey(conversationId, sessionId)
|
|
1072
|
-
);
|
|
1073
|
-
return parseAgentTurnSessionRecord(value);
|
|
1074
|
-
}
|
|
1075
|
-
async function getAgentTurnSessionRecord(conversationId, sessionId) {
|
|
1076
|
-
const parsed = await getStoredAgentTurnSessionRecord(
|
|
1077
|
-
conversationId,
|
|
1078
|
-
sessionId
|
|
1079
|
-
);
|
|
1080
|
-
if (!parsed) {
|
|
1081
|
-
return void 0;
|
|
1082
|
-
}
|
|
1083
|
-
const sessionMessages = await loadMessagesWithProvenance({
|
|
1084
|
-
conversationId,
|
|
1085
|
-
messageCount: parsed.committedMessageCount,
|
|
1086
|
-
...parsed.logSessionId ? { sessionId: parsed.logSessionId } : {}
|
|
1087
|
-
});
|
|
1088
|
-
const sessionProjection = await loadProjectionWithProvenance({
|
|
1089
|
-
conversationId,
|
|
1090
|
-
...parsed.logSessionId ? { sessionId: parsed.logSessionId } : {}
|
|
1091
|
-
});
|
|
1092
|
-
const piProjection = materializePiProjection(
|
|
1093
|
-
parsed.committedMessageCount,
|
|
1094
|
-
parsed.state === "running" || parsed.state === "awaiting_resume",
|
|
1095
|
-
sessionMessages,
|
|
1096
|
-
sessionProjection
|
|
1097
|
-
);
|
|
1098
|
-
if (!piProjection) {
|
|
1099
|
-
return void 0;
|
|
1100
|
-
}
|
|
1101
|
-
return materializeAgentTurnSessionRecord(parsed, piProjection);
|
|
1102
|
-
}
|
|
1103
|
-
function buildStoredRecord(args) {
|
|
1104
|
-
const nowMs = Date.now();
|
|
1105
|
-
return {
|
|
1106
|
-
version: (args.previousVersion ?? 0) + 1,
|
|
1107
|
-
...args.channelName ? { channelName: args.channelName } : {},
|
|
1108
|
-
conversationId: args.conversationId,
|
|
1109
|
-
sessionId: args.sessionId,
|
|
1110
|
-
sliceId: args.sliceId,
|
|
1111
|
-
state: args.state,
|
|
1112
|
-
startedAtMs: args.startedAtMs ?? nowMs,
|
|
1113
|
-
lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
|
|
1114
|
-
updatedAtMs: nowMs,
|
|
1115
|
-
committedMessageCount: args.committedMessageCount,
|
|
1116
|
-
committedMessageProvenance: args.committedMessageProvenance,
|
|
1117
|
-
...args.logSessionId ? { logSessionId: args.logSessionId } : {},
|
|
1118
|
-
cumulativeDurationMs: args.cumulativeDurationMs,
|
|
1119
|
-
...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
|
|
1120
|
-
...args.destination ? { destination: args.destination } : {},
|
|
1121
|
-
...args.source ? { source: args.source } : {},
|
|
1122
|
-
...args.actor ? { actor: args.actor } : {},
|
|
1123
|
-
...Array.isArray(args.loadedSkillNames) ? {
|
|
1124
|
-
loadedSkillNames: args.loadedSkillNames.filter(
|
|
1125
|
-
(value) => typeof value === "string"
|
|
1126
|
-
)
|
|
1127
|
-
} : {},
|
|
1128
|
-
...args.resumeReason ? { resumeReason: args.resumeReason } : {},
|
|
1129
|
-
...args.errorMessage ? { errorMessage: args.errorMessage } : {},
|
|
1130
|
-
...typeof args.resumedFromSliceId === "number" ? { resumedFromSliceId: args.resumedFromSliceId } : {},
|
|
1131
|
-
...args.surface ? { surface: args.surface } : {},
|
|
1132
|
-
...args.traceId ? { traceId: args.traceId } : {},
|
|
1133
|
-
...args.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: args.turnStartMessageIndex } : {}
|
|
1134
|
-
};
|
|
1135
|
-
}
|
|
1136
|
-
async function setStoredRecord(args) {
|
|
1137
|
-
const stateAdapter = getStateAdapter();
|
|
1138
|
-
await stateAdapter.connect();
|
|
1139
|
-
await stateAdapter.set(
|
|
1140
|
-
agentTurnSessionKey(args.record.conversationId, args.record.sessionId),
|
|
1141
|
-
args.record,
|
|
1142
|
-
args.ttlMs
|
|
1143
|
-
);
|
|
1144
|
-
const {
|
|
1145
|
-
committedMessageCount: _committedMessageCount,
|
|
1146
|
-
committedMessageProvenance: _committedMessageProvenance,
|
|
1147
|
-
errorMessage: _errorMessage,
|
|
1148
|
-
logSessionId: _logSessionId,
|
|
1149
|
-
turnStartMessageIndex: _turnStartMessageIndex,
|
|
1150
|
-
...summary
|
|
1151
|
-
} = args.record;
|
|
1152
|
-
await appendAgentTurnSessionSummary(summary, args.ttlMs);
|
|
1153
|
-
await recordConversationActivityMetadata({
|
|
1154
|
-
conversationStore: args.conversationStore,
|
|
1155
|
-
destinationVisibility: args.destinationVisibility,
|
|
1156
|
-
nowMs: Date.now(),
|
|
1157
|
-
summary
|
|
1158
|
-
});
|
|
1159
|
-
return materializeAgentTurnSessionRecord(args.record, {
|
|
1160
|
-
messages: [...args.piMessages],
|
|
1161
|
-
provenance: [...args.piMessageProvenance]
|
|
1162
|
-
});
|
|
1163
|
-
}
|
|
1164
|
-
async function updateAgentTurnSessionState(args) {
|
|
1165
|
-
const parsed = await getStoredAgentTurnSessionRecord(
|
|
1166
|
-
args.existing.conversationId,
|
|
1167
|
-
args.existing.sessionId
|
|
1168
|
-
);
|
|
1169
|
-
if (!parsed || parsed.version !== args.existing.version) {
|
|
1170
|
-
return void 0;
|
|
1171
|
-
}
|
|
1172
|
-
return await setStoredRecord({
|
|
1173
|
-
piMessages: args.existing.piMessages,
|
|
1174
|
-
piMessageProvenance: args.existing.piMessageProvenance,
|
|
1175
|
-
ttlMs: AGENT_TURN_SESSION_TTL_MS,
|
|
1176
|
-
record: buildStoredRecord({
|
|
1177
|
-
conversationId: args.existing.conversationId,
|
|
1178
|
-
sessionId: args.existing.sessionId,
|
|
1179
|
-
sliceId: args.existing.sliceId,
|
|
1180
|
-
state: args.state,
|
|
1181
|
-
committedMessageCount: parsed.committedMessageCount,
|
|
1182
|
-
committedMessageProvenance: parsed.committedMessageProvenance,
|
|
1183
|
-
...parsed.channelName ? { channelName: parsed.channelName } : {},
|
|
1184
|
-
startedAtMs: parsed.startedAtMs,
|
|
1185
|
-
lastProgressAtMs: parsed.lastProgressAtMs,
|
|
1186
|
-
previousVersion: parsed.version,
|
|
1187
|
-
...parsed.logSessionId ? { logSessionId: parsed.logSessionId } : {},
|
|
1188
|
-
cumulativeDurationMs: args.existing.cumulativeDurationMs,
|
|
1189
|
-
...args.existing.cumulativeUsage ? { cumulativeUsage: args.existing.cumulativeUsage } : {},
|
|
1190
|
-
...args.existing.destination ? { destination: args.existing.destination } : {},
|
|
1191
|
-
...args.existing.source ? { source: args.existing.source } : {},
|
|
1192
|
-
...args.existing.loadedSkillNames ? { loadedSkillNames: args.existing.loadedSkillNames } : {},
|
|
1193
|
-
...args.existing.actor ? { actor: args.existing.actor } : {},
|
|
1194
|
-
...args.existing.resumeReason ? { resumeReason: args.existing.resumeReason } : {},
|
|
1195
|
-
...args.existing.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.existing.resumedFromSliceId } : {},
|
|
1196
|
-
...args.existing.surface ? { surface: args.existing.surface } : {},
|
|
1197
|
-
...args.existing.traceId ? { traceId: args.existing.traceId } : {},
|
|
1198
|
-
...args.existing.turnStartMessageIndex !== void 0 ? { turnStartMessageIndex: args.existing.turnStartMessageIndex } : {},
|
|
1199
|
-
...args.errorMessage ?? args.existing.errorMessage ? { errorMessage: args.errorMessage ?? args.existing.errorMessage } : {}
|
|
1200
|
-
})
|
|
1201
|
-
});
|
|
1202
|
-
}
|
|
1203
|
-
async function upsertAgentTurnSessionRecord(args) {
|
|
1204
|
-
const existingRecord = await getStoredAgentTurnSessionRecord(
|
|
1205
|
-
args.conversationId,
|
|
1206
|
-
args.sessionId
|
|
1207
|
-
);
|
|
1208
|
-
const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
|
|
1209
|
-
const instructionActor = args.actor ?? existingRecord?.actor;
|
|
1210
|
-
const commit = await commitMessages({
|
|
1211
|
-
conversationId: args.conversationId,
|
|
1212
|
-
messages: args.piMessages,
|
|
1213
|
-
...instructionActor ? { newMessageProvenance: instructionProvenanceFor(instructionActor) } : {},
|
|
1214
|
-
...args.trailingMessageProvenance ? { trailingMessageProvenance: args.trailingMessageProvenance } : {},
|
|
1215
|
-
ttlMs
|
|
1216
|
-
});
|
|
1217
|
-
return await setStoredRecord({
|
|
1218
|
-
conversationStore: args.conversationStore,
|
|
1219
|
-
destinationVisibility: args.destinationVisibility,
|
|
1220
|
-
piMessages: args.piMessages,
|
|
1221
|
-
piMessageProvenance: commit.provenance,
|
|
1222
|
-
ttlMs,
|
|
1223
|
-
record: buildStoredRecord({
|
|
1224
|
-
committedMessageProvenance: commit.provenance,
|
|
1225
|
-
...args.channelName ?? existingRecord?.channelName ? { channelName: args.channelName ?? existingRecord?.channelName } : {},
|
|
1226
|
-
conversationId: args.conversationId,
|
|
1227
|
-
sessionId: args.sessionId,
|
|
1228
|
-
sliceId: args.sliceId,
|
|
1229
|
-
state: args.state,
|
|
1230
|
-
...existingRecord?.startedAtMs !== void 0 ? { startedAtMs: existingRecord.startedAtMs } : {},
|
|
1231
|
-
...args.lastProgressAtMs !== void 0 ? { lastProgressAtMs: args.lastProgressAtMs } : {},
|
|
1232
|
-
committedMessageCount: args.piMessages.length,
|
|
1233
|
-
logSessionId: commit.sessionId,
|
|
1234
|
-
previousVersion: existingRecord?.version,
|
|
1235
|
-
cumulativeDurationMs: toFiniteNonNegativeNumber(args.cumulativeDurationMs) ?? existingRecord?.cumulativeDurationMs ?? 0,
|
|
1236
|
-
...args.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage } : {},
|
|
1237
|
-
...args.destination ?? existingRecord?.destination ? { destination: args.destination ?? existingRecord?.destination } : {},
|
|
1238
|
-
...args.source ?? existingRecord?.source ? { source: args.source ?? existingRecord?.source } : {},
|
|
1239
|
-
...args.loadedSkillNames ? { loadedSkillNames: args.loadedSkillNames } : {},
|
|
1240
|
-
...args.actor ?? existingRecord?.actor ? { actor: args.actor ?? existingRecord?.actor } : {},
|
|
1241
|
-
...args.resumeReason ? { resumeReason: args.resumeReason } : {},
|
|
1242
|
-
...args.errorMessage ? { errorMessage: args.errorMessage } : {},
|
|
1243
|
-
...args.resumedFromSliceId !== void 0 ? { resumedFromSliceId: args.resumedFromSliceId } : {},
|
|
1244
|
-
...args.surface ?? existingRecord?.surface ? { surface: args.surface ?? existingRecord?.surface } : {},
|
|
1245
|
-
...args.traceId ?? existingRecord?.traceId ? { traceId: args.traceId ?? existingRecord?.traceId } : {},
|
|
1246
|
-
...(args.turnStartMessageIndex ?? existingRecord?.turnStartMessageIndex) !== void 0 ? {
|
|
1247
|
-
turnStartMessageIndex: args.turnStartMessageIndex ?? existingRecord?.turnStartMessageIndex
|
|
1248
|
-
} : {}
|
|
1249
|
-
})
|
|
1250
|
-
});
|
|
1251
|
-
}
|
|
1252
|
-
async function recordAgentTurnSessionSummary(args) {
|
|
1253
|
-
const existing = await getStoredAgentTurnSessionRecord(
|
|
1254
|
-
args.conversationId,
|
|
1255
|
-
args.sessionId
|
|
1256
|
-
);
|
|
1257
|
-
const nowMs = Date.now();
|
|
1258
|
-
const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
|
|
1259
|
-
const summary = {
|
|
1260
|
-
version: existing?.version ?? 0,
|
|
1261
|
-
...args.channelName ?? existing?.channelName ? { channelName: args.channelName ?? existing?.channelName } : {},
|
|
1262
|
-
conversationId: args.conversationId,
|
|
1263
|
-
sessionId: args.sessionId,
|
|
1264
|
-
sliceId: args.sliceId,
|
|
1265
|
-
startedAtMs: existing?.startedAtMs ?? args.startedAtMs ?? nowMs,
|
|
1266
|
-
lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
|
|
1267
|
-
state: args.state,
|
|
1268
|
-
updatedAtMs: nowMs,
|
|
1269
|
-
cumulativeDurationMs: toFiniteNonNegativeNumber(args.cumulativeDurationMs) ?? existing?.cumulativeDurationMs ?? 0,
|
|
1270
|
-
...args.cumulativeUsage ?? existing?.cumulativeUsage ? { cumulativeUsage: args.cumulativeUsage ?? existing?.cumulativeUsage } : {},
|
|
1271
|
-
...args.destination ?? existing?.destination ? { destination: args.destination ?? existing?.destination } : {},
|
|
1272
|
-
...args.source ?? existing?.source ? { source: args.source ?? existing?.source } : {},
|
|
1273
|
-
...args.actor ?? existing?.actor ? { actor: args.actor ?? existing?.actor } : {},
|
|
1274
|
-
...Array.isArray(args.loadedSkillNames) ? {
|
|
1275
|
-
loadedSkillNames: args.loadedSkillNames.filter(
|
|
1276
|
-
(value) => typeof value === "string"
|
|
1277
|
-
)
|
|
1278
|
-
} : existing?.loadedSkillNames ? { loadedSkillNames: existing.loadedSkillNames } : {},
|
|
1279
|
-
...args.resumeReason ? { resumeReason: args.resumeReason } : {},
|
|
1280
|
-
...args.surface ?? existing?.surface ? { surface: args.surface ?? existing?.surface } : {},
|
|
1281
|
-
...args.traceId ?? existing?.traceId ? { traceId: args.traceId ?? existing?.traceId } : {}
|
|
1282
|
-
};
|
|
1283
|
-
await appendAgentTurnSessionSummary(summary, ttlMs);
|
|
1284
|
-
await recordConversationActivityMetadata({
|
|
1285
|
-
conversationStore: args.conversationStore,
|
|
1286
|
-
destinationVisibility: args.destinationVisibility,
|
|
1287
|
-
nowMs,
|
|
1288
|
-
summary
|
|
1289
|
-
});
|
|
1290
|
-
}
|
|
1291
|
-
async function readAgentTurnSessionSummariesFromIndex(key2) {
|
|
1292
|
-
const stateAdapter = getStateAdapter();
|
|
1293
|
-
await stateAdapter.connect();
|
|
1294
|
-
const values = await stateAdapter.getList(key2);
|
|
1295
|
-
const summaries = /* @__PURE__ */ new Map();
|
|
1296
|
-
for (const value of [...values].reverse()) {
|
|
1297
|
-
const summary = parseAgentTurnSessionSummary(value);
|
|
1298
|
-
if (!summary) {
|
|
1299
|
-
continue;
|
|
1300
|
-
}
|
|
1301
|
-
const key3 = `${summary.conversationId}:${summary.sessionId}`;
|
|
1302
|
-
if (!summaries.has(key3)) {
|
|
1303
|
-
summaries.set(key3, summary);
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
return [...summaries.values()].sort(
|
|
1307
|
-
(left, right) => right.updatedAtMs - left.updatedAtMs
|
|
1308
|
-
);
|
|
1309
|
-
}
|
|
1310
|
-
async function listAgentTurnSessionSummariesForConversation(conversationId) {
|
|
1311
|
-
const summaries = await readAgentTurnSessionSummariesFromIndex(
|
|
1312
|
-
agentTurnSessionConversationIndexKey(conversationId)
|
|
1313
|
-
);
|
|
1314
|
-
if (summaries.length > 0) {
|
|
1315
|
-
return summaries;
|
|
1316
|
-
}
|
|
1317
|
-
return (await readAgentTurnSessionSummariesFromIndex(AGENT_TURN_SESSION_INDEX_KEY)).filter((summary) => summary.conversationId === conversationId);
|
|
1318
|
-
}
|
|
1319
|
-
async function abandonAgentTurnSessionRecord(args) {
|
|
1320
|
-
const existing = await getAgentTurnSessionRecord(
|
|
1321
|
-
args.conversationId,
|
|
1322
|
-
args.sessionId
|
|
1323
|
-
);
|
|
1324
|
-
if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned") {
|
|
1325
|
-
return void 0;
|
|
1326
|
-
}
|
|
1327
|
-
return await updateAgentTurnSessionState({
|
|
1328
|
-
existing,
|
|
1329
|
-
state: "abandoned",
|
|
1330
|
-
errorMessage: args.errorMessage ?? existing.errorMessage
|
|
1331
|
-
});
|
|
1332
|
-
}
|
|
1333
|
-
async function failAgentTurnSessionRecord(args) {
|
|
1334
|
-
const existing = await getAgentTurnSessionRecord(
|
|
1335
|
-
args.conversationId,
|
|
1336
|
-
args.sessionId
|
|
1337
|
-
);
|
|
1338
|
-
if (!existing || existing.state === "completed" || existing.state === "failed" || existing.state === "abandoned" || existing.version !== args.expectedVersion) {
|
|
1339
|
-
return void 0;
|
|
1340
|
-
}
|
|
1341
|
-
return await updateAgentTurnSessionState({
|
|
1342
|
-
existing,
|
|
1343
|
-
state: "failed",
|
|
1344
|
-
errorMessage: args.errorMessage ?? existing.errorMessage
|
|
1345
|
-
});
|
|
1346
|
-
}
|
|
1347
|
-
|
|
1348
|
-
// src/chat/interruption-marker.ts
|
|
1349
|
-
var INTERRUPTED_MARKER = "\n\n[Response interrupted before completion]";
|
|
1350
|
-
function getInterruptionMarker() {
|
|
1351
|
-
return INTERRUPTED_MARKER;
|
|
1352
|
-
}
|
|
1353
|
-
|
|
1354
|
-
export {
|
|
1355
|
-
piContentMessageSchema,
|
|
1356
|
-
instructionActors,
|
|
1357
|
-
loadActivityEntries,
|
|
1358
|
-
loadProjection,
|
|
1359
|
-
loadProjectionWithProvenance,
|
|
1360
|
-
loadConnectedMcpProviders,
|
|
1361
|
-
recordMcpProviderConnected,
|
|
1362
|
-
recordAuthorizationRequested,
|
|
1363
|
-
recordAuthorizationCompleted,
|
|
1364
|
-
recordToolExecutionStarted,
|
|
1365
|
-
recordSubagentStarted,
|
|
1366
|
-
recordSubagentEnded,
|
|
1367
|
-
commitMessages,
|
|
1368
|
-
instructionProvenanceFor,
|
|
1369
|
-
contextProvenance,
|
|
1370
|
-
getAgentTurnSessionRecord,
|
|
1371
|
-
upsertAgentTurnSessionRecord,
|
|
1372
|
-
recordAgentTurnSessionSummary,
|
|
1373
|
-
listAgentTurnSessionSummariesForConversation,
|
|
1374
|
-
abandonAgentTurnSessionRecord,
|
|
1375
|
-
failAgentTurnSessionRecord,
|
|
1376
|
-
getInterruptionMarker
|
|
1377
|
-
};
|