@sentry/junior 0.139.0 → 0.141.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.
Files changed (77) hide show
  1. package/dist/{agent-hooks-MJXMD7JP.js → agent-hooks-HIRVKUQJ.js} +10 -10
  2. package/dist/api/conversations/detail.d.ts +1 -0
  3. package/dist/api/conversations/event-list.d.ts +1 -0
  4. package/dist/api/schema/conversation.d.ts +4 -0
  5. package/dist/api/schema/task.d.ts +4 -0
  6. package/dist/api/schema.js +1 -1
  7. package/dist/api.js +20 -20
  8. package/dist/app.js +117 -36
  9. package/dist/{catalog-runtime-GCCFYPIK.js → catalog-runtime-XVLED5UH.js} +5 -5
  10. package/dist/chat/agent/repository-context.d.ts +1 -0
  11. package/dist/chat/conversations/history.d.ts +2 -0
  12. package/dist/chat/conversations/projection.d.ts +8 -0
  13. package/dist/chat/conversations/store.d.ts +5 -0
  14. package/dist/chat/conversations/structured-events.d.ts +11 -0
  15. package/dist/chat/runtime/thread-state.d.ts +3 -1
  16. package/dist/chat/scheduled-tasks/telemetry.d.ts +7 -0
  17. package/dist/chat/scheduled-tasks/tool-support.d.ts +10 -2
  18. package/dist/chat/scheduled-tasks/tools/create.d.ts +4 -2
  19. package/dist/chat/scheduled-tasks/tools/delete.d.ts +4 -2
  20. package/dist/chat/scheduled-tasks/tools/list.d.ts +4 -2
  21. package/dist/chat/scheduled-tasks/tools/run-now.d.ts +4 -2
  22. package/dist/chat/scheduled-tasks/tools/update.d.ts +4 -2
  23. package/dist/chat/scheduled-tasks/types.d.ts +1 -1
  24. package/dist/chat/services/guardian-action-policy.d.ts +1 -1
  25. package/dist/chat/slack/dashboard-link.d.ts +2 -0
  26. package/dist/chat/state/turn-session-keys.d.ts +2 -2
  27. package/dist/chat/state/turn-session.d.ts +18 -13
  28. package/dist/{chunk-GI52BW74.js → chunk-2DOVDDZJ.js} +3 -3
  29. package/dist/{chunk-UDBUS533.js → chunk-3H42HMA2.js} +1 -1
  30. package/dist/{chunk-U7CMWQ7Z.js → chunk-43OPSFUY.js} +1 -1
  31. package/dist/{chunk-J3S57AXY.js → chunk-44NWPKY3.js} +1 -1
  32. package/dist/{chunk-DW4PMHNW.js → chunk-5LPWHC7Q.js} +148 -87
  33. package/dist/{chunk-QTBKPZDA.js → chunk-5MFCEKR6.js} +19 -3
  34. package/dist/{chunk-GWQSZT4C.js → chunk-6FRAWWGR.js} +2 -2
  35. package/dist/{chunk-MXTVUV3I.js → chunk-6U44QGXL.js} +1 -1
  36. package/dist/{chunk-IIESAYDL.js → chunk-7ULXCNOZ.js} +17 -8
  37. package/dist/{chunk-AEQISMMU.js → chunk-A2O7SGK5.js} +15 -17
  38. package/dist/{chunk-75I3UBIL.js → chunk-BBLO66XT.js} +29 -29
  39. package/dist/{chunk-WQRX57EA.js → chunk-DBKS7JR2.js} +3 -3
  40. package/dist/{chunk-U27DSXKB.js → chunk-DK3GQWJK.js} +6 -6
  41. package/dist/{chunk-5GSZWRE2.js → chunk-DKH4WGZU.js} +8 -8
  42. package/dist/{chunk-6SU2DT27.js → chunk-DVIJ6DP6.js} +2 -2
  43. package/dist/{chunk-6OHTDR4F.js → chunk-EYD523BV.js} +1 -1
  44. package/dist/{chunk-4V4QIYJH.js → chunk-FWXSPJRN.js} +1 -1
  45. package/dist/{chunk-G52UXKGO.js → chunk-FZFJZZR3.js} +4 -4
  46. package/dist/{chunk-WZH4JV7R.js → chunk-H4WNQFBH.js} +5 -5
  47. package/dist/{chunk-CDQ4YIZM.js → chunk-HLXXQI5Q.js} +55 -1
  48. package/dist/{chunk-3T2JAGRH.js → chunk-HN4UZTG7.js} +2 -2
  49. package/dist/{chunk-MXVD2BDS.js → chunk-HQAFIN6O.js} +1 -1
  50. package/dist/{chunk-J6EJQCHY.js → chunk-LIVSCWI5.js} +15 -15
  51. package/dist/{chunk-CXH25EL4.js → chunk-LMGKSDO4.js} +1 -1
  52. package/dist/{chunk-MQ5RYATN.js → chunk-NFL4FRIU.js} +4 -4
  53. package/dist/{chunk-C2N6MNO4.js → chunk-OFQBDHVG.js} +1 -1
  54. package/dist/{chunk-ZYQSPQYR.js → chunk-OHO46E7F.js} +50 -19
  55. package/dist/{chunk-YGZ2OLXL.js → chunk-PGJUJCOQ.js} +1 -1
  56. package/dist/{chunk-PJW6U46K.js → chunk-PIQKV7IR.js} +212 -149
  57. package/dist/{chunk-2ECYPYKP.js → chunk-UFEU4UX6.js} +1 -1
  58. package/dist/{chunk-ZQCGQMF2.js → chunk-UONUDOJP.js} +7 -7
  59. package/dist/{chunk-YCTDA7BD.js → chunk-YWM6MJT4.js} +1 -1
  60. package/dist/cli/chat.js +31 -31
  61. package/dist/cli/check.js +6 -6
  62. package/dist/cli/plugins.js +13 -13
  63. package/dist/cli/snapshot-create.js +9 -9
  64. package/dist/cli/upgrade.js +7 -7
  65. package/dist/{db-UXPPGHDF.js → db-PSMQZR4P.js} +7 -7
  66. package/dist/instrumentation.js +4 -4
  67. package/dist/nitro.js +2 -2
  68. package/dist/{oauth-callback-server-4ZYMD5UA.js → oauth-callback-server-XZUK2AT6.js} +22 -22
  69. package/dist/{runner-MZSEONRZ.js → runner-5EKJCQWP.js} +14 -14
  70. package/dist/{skills-IMVPXSQ7.js → skills-2PRM42SE.js} +6 -6
  71. package/dist/spawn-UGTLRTFP.js +38 -0
  72. package/dist/{validation-ZKCY2BVR.js → validation-XLXAIRTR.js} +6 -6
  73. package/dist/version.js +1 -1
  74. package/dist/{work-GG3XDYRX.js → work-CNTNEQ2Q.js} +17 -17
  75. package/dist/{worker-23AUELCJ.js → worker-BGW7CKZ7.js} +10 -10
  76. package/package.json +5 -5
  77. package/dist/spawn-S5LSVOCE.js +0 -38
@@ -5,10 +5,10 @@ import {
5
5
  JUNIOR_NATIVE_EVENT_NAMESPACE,
6
6
  ToolInputError,
7
7
  addAgentTurnUsage,
8
- agentTurnUsageSchema,
8
+ agentsInstructionsUpdatedEvent,
9
9
  authenticationLinkedEvent,
10
10
  authenticationUnlinkedEvent
11
- } from "./chunk-CDQ4YIZM.js";
11
+ } from "./chunk-HLXXQI5Q.js";
12
12
  import {
13
13
  agentHistoryItemSchema,
14
14
  bindProviderConversation,
@@ -21,20 +21,20 @@ import {
21
21
  instructionProvenanceFor,
22
22
  sanitizePostgresJson,
23
23
  withConversationEventLock
24
- } from "./chunk-QTBKPZDA.js";
24
+ } from "./chunk-5MFCEKR6.js";
25
25
  import {
26
26
  SANDBOX_WORKSPACE_ROOT,
27
27
  sleep
28
28
  } from "./chunk-EM225ITJ.js";
29
29
  import {
30
30
  getStateAdapter
31
- } from "./chunk-MXTVUV3I.js";
31
+ } from "./chunk-6U44QGXL.js";
32
32
  import {
33
33
  botConfig,
34
34
  escapeXml,
35
35
  resolveGatewayModel,
36
36
  unwrapCurrentInstruction
37
- } from "./chunk-75I3UBIL.js";
37
+ } from "./chunk-BBLO66XT.js";
38
38
  import {
39
39
  toStoredSlackActor
40
40
  } from "./chunk-HZF5P5UN.js";
@@ -49,7 +49,7 @@ import {
49
49
  setSpanAttributes,
50
50
  toOptionalNumber,
51
51
  toOptionalString
52
- } from "./chunk-2ECYPYKP.js";
52
+ } from "./chunk-UFEU4UX6.js";
53
53
 
54
54
  // src/chat/turn-context-tag.ts
55
55
  var TURN_CONTEXT_TAG = "runtime-turn-context";
@@ -1214,6 +1214,59 @@ async function recordAuthenticationAccountChange(action, args) {
1214
1214
  async function recordAuthenticationLinked(args) {
1215
1215
  await recordAuthenticationAccountChange("linked", args);
1216
1216
  }
1217
+ async function loadAgentsEvent(conversationId) {
1218
+ const event = await getConversationEventStore().loadLatestStructuredEvent(
1219
+ conversationId,
1220
+ JUNIOR_NATIVE_EVENT_NAMESPACE,
1221
+ agentsInstructionsUpdatedEvent.eventName
1222
+ );
1223
+ if (!event || event.data.type !== "structured_event") return void 0;
1224
+ return {
1225
+ content: agentsInstructionsUpdatedEvent.parse(
1226
+ event.data.content
1227
+ ),
1228
+ seq: event.seq
1229
+ };
1230
+ }
1231
+ function agentsInstructionsIdempotencyKey(args) {
1232
+ const previous = args.previousSeq ?? "none";
1233
+ return `native:${JUNIOR_NATIVE_EVENT_NAMESPACE}:agents_instructions_updated:${args.turnId}:${args.action}:${previous}->${args.fingerprint}`;
1234
+ }
1235
+ async function recordAgentsInstructionsUpdated(args) {
1236
+ const previous = await loadAgentsEvent(args.conversationId);
1237
+ const instructions = args.instructions;
1238
+ if (previous && (!instructions && previous.content.action === "cleared" || instructions && previous.content.action !== "cleared" && previous.content.fingerprint === instructions.fingerprint && previous.content.directory === instructions.directory)) {
1239
+ return;
1240
+ }
1241
+ const action = !instructions ? "cleared" : previous && previous.content.action !== "cleared" ? "replaced" : "loaded";
1242
+ const fingerprint = instructions?.fingerprint ?? "cleared";
1243
+ const content = agentsInstructionsUpdatedEvent.parse({
1244
+ action,
1245
+ fingerprint,
1246
+ sources: instructions?.sources ?? [],
1247
+ ...instructions ? { directory: instructions.directory } : {},
1248
+ ...instructions ? { textBytes: Buffer.byteLength(instructions.text, "utf8") } : {}
1249
+ });
1250
+ await getConversationEventStore().append(args.conversationId, [
1251
+ {
1252
+ createdAtMs: Date.now(),
1253
+ idempotencyKey: agentsInstructionsIdempotencyKey({
1254
+ action,
1255
+ fingerprint,
1256
+ previousSeq: previous?.seq,
1257
+ turnId: args.turnId
1258
+ }),
1259
+ data: {
1260
+ type: "structured_event",
1261
+ namespace: JUNIOR_NATIVE_EVENT_NAMESPACE,
1262
+ name: agentsInstructionsUpdatedEvent.eventName,
1263
+ version: agentsInstructionsUpdatedEvent.version,
1264
+ turnId: args.turnId,
1265
+ content
1266
+ }
1267
+ }
1268
+ ]);
1269
+ }
1217
1270
  async function loadTurnRoute(args) {
1218
1271
  const event = await getConversationEventStore().loadByIdempotencyKey(
1219
1272
  args.conversationId,
@@ -1402,10 +1455,6 @@ function getAssistantReplyText(message) {
1402
1455
  }
1403
1456
 
1404
1457
  // src/chat/state/turn-session.ts
1405
- import { THREAD_STATE_TTL_MS } from "chat";
1406
- import {
1407
- actorSchema
1408
- } from "@sentry/junior-plugin-api";
1409
1458
  import { z as z2 } from "zod";
1410
1459
 
1411
1460
  // src/chat/repository-instructions.ts
@@ -1766,9 +1815,11 @@ function agentTurnSessionConversationIndexKey(conversationId) {
1766
1815
  }
1767
1816
 
1768
1817
  // src/chat/state/turn-session.ts
1769
- var AGENT_TURN_SESSION_INDEX_KEY = `${AGENT_TURN_SESSION_PREFIX}:index`;
1770
- var AGENT_TURN_SESSION_INDEX_MAX_LENGTH = 5e3;
1771
- var AGENT_TURN_SESSION_TTL_MS = THREAD_STATE_TTL_MS;
1818
+ var AGENT_TURN_SESSION_RESUME_TTL_MS = 24 * 60 * 60 * 1e3;
1819
+ var AGENT_TURN_SESSION_TERMINAL_TTL_MS = 60 * 60 * 1e3;
1820
+ function executionMetricsForSession(conversation, sessionId) {
1821
+ return conversation?.executionMetrics?.runId === sessionId ? conversation.executionMetrics : void 0;
1822
+ }
1772
1823
  function definedProps(values) {
1773
1824
  return Object.fromEntries(
1774
1825
  Object.entries(values).filter(([, value]) => value !== void 0)
@@ -1796,18 +1847,25 @@ var agentTurnResumeReasonSchema = z2.enum([
1796
1847
  var nonNegativeNumberSchema = z2.number().finite().nonnegative();
1797
1848
  var seqCursorSchema = z2.number().int().min(-1);
1798
1849
  var agentTurnSessionSummarySchema = z2.object({
1799
- channelName: z2.string().min(1).optional(),
1800
1850
  version: z2.number().int().nonnegative(),
1801
1851
  conversationId: z2.string().min(1),
1802
- cumulativeDurationMs: nonNegativeNumberSchema,
1803
- cumulativeUsage: agentTurnUsageSchema.optional(),
1852
+ dispatchId: z2.string().min(1).optional(),
1853
+ dispatchOutcome: z2.enum(["blocked", "completed", "failed"]).optional(),
1854
+ resultMessageId: z2.string().min(1).optional(),
1855
+ resumeReason: agentTurnResumeReasonSchema.optional(),
1856
+ sessionId: z2.string().min(1),
1857
+ sliceId: z2.number().int().nonnegative(),
1858
+ state: agentTurnSessionStatusSchema,
1859
+ surface: agentTurnSurfaceSchema.optional(),
1860
+ updatedAtMs: nonNegativeNumberSchema
1861
+ }).strip();
1862
+ var storedAgentTurnSessionRecordSchema = z2.object({
1863
+ version: z2.number().int().nonnegative(),
1864
+ conversationId: z2.string().min(1),
1804
1865
  dispatchId: z2.string().min(1).optional(),
1805
1866
  dispatchOutcome: z2.enum(["blocked", "completed", "failed"]).optional(),
1806
1867
  resultMessageId: z2.string().min(1).optional(),
1807
1868
  lastProgressAtMs: nonNegativeNumberSchema,
1808
- loadedSkillNames: z2.array(z2.string()).optional(),
1809
- modelId: z2.string().min(1).optional(),
1810
- reasoningLevel: z2.string().min(1).optional(),
1811
1869
  resumeReason: agentTurnResumeReasonSchema.optional(),
1812
1870
  resumedFromSliceId: z2.number().int().nonnegative().optional(),
1813
1871
  sessionId: z2.string().min(1),
@@ -1816,10 +1874,7 @@ var agentTurnSessionSummarySchema = z2.object({
1816
1874
  state: agentTurnSessionStatusSchema,
1817
1875
  surface: agentTurnSurfaceSchema.optional(),
1818
1876
  traceId: z2.string().optional(),
1819
- updatedAtMs: nonNegativeNumberSchema
1820
- }).strip();
1821
- var storedAgentTurnSessionRecordSchema = agentTurnSessionSummarySchema.extend({
1822
- actors: z2.array(actorSchema).optional(),
1877
+ updatedAtMs: nonNegativeNumberSchema,
1823
1878
  committedSeq: seqCursorSchema,
1824
1879
  historyVersion: z2.number().int().nonnegative().optional(),
1825
1880
  errorMessage: z2.string().optional(),
@@ -1843,20 +1898,25 @@ function parseAgentTurnSessionRecord(value) {
1843
1898
  function parseAgentTurnSessionSummary(value) {
1844
1899
  return agentTurnSessionSummarySchema.parse(value);
1845
1900
  }
1901
+ function agentTurnSessionRecordTtlMs(state, ttlMs) {
1902
+ if (ttlMs !== void 0) {
1903
+ return Math.max(1, ttlMs);
1904
+ }
1905
+ return state === "running" || state === "awaiting_resume" ? AGENT_TURN_SESSION_RESUME_TTL_MS : AGENT_TURN_SESSION_TERMINAL_TTL_MS;
1906
+ }
1907
+ function agentTurnSessionIndexTtlMs(ttlMs) {
1908
+ return Math.max(1, ttlMs ?? AGENT_TURN_SESSION_RESUME_TTL_MS);
1909
+ }
1910
+ function projectAgentTurnSessionSummary(record) {
1911
+ return agentTurnSessionSummarySchema.parse(record);
1912
+ }
1846
1913
  async function appendAgentTurnSessionSummary(summary, ttlMs) {
1847
- const projectedSummary = agentTurnSessionSummarySchema.parse(summary);
1848
1914
  const stateAdapter = getStateAdapter();
1849
- await Promise.all([
1850
- stateAdapter.appendToList(AGENT_TURN_SESSION_INDEX_KEY, projectedSummary, {
1851
- maxLength: AGENT_TURN_SESSION_INDEX_MAX_LENGTH,
1852
- ttlMs
1853
- }),
1854
- stateAdapter.appendToList(
1855
- agentTurnSessionConversationIndexKey(projectedSummary.conversationId),
1856
- projectedSummary,
1857
- { ttlMs }
1858
- )
1859
- ]);
1915
+ await stateAdapter.appendToList(
1916
+ agentTurnSessionConversationIndexKey(summary.conversationId),
1917
+ agentTurnSessionSummarySchema.parse(summary),
1918
+ { ttlMs }
1919
+ );
1860
1920
  }
1861
1921
  async function recordConversationActivityMetadata(args) {
1862
1922
  const conversationStore = args.conversationStore ?? getConversationStore();
@@ -1894,7 +1954,7 @@ async function recordConversationActivityMetadata(args) {
1894
1954
  visibility: isChild ? void 0 : args.destinationVisibility
1895
1955
  });
1896
1956
  }
1897
- function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex, restoreVolatileContext = true) {
1957
+ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessageIndex, restoreVolatileContext = true, runtimeMetadata) {
1898
1958
  const restoredProjection = restoreVolatileContext && (stored.state === "running" || stored.state === "awaiting_resume") ? restoreRuntimeContext(piProjection, stored.runtimeContext) : piProjection;
1899
1959
  return {
1900
1960
  version: stored.version,
@@ -1907,17 +1967,17 @@ function materializeAgentTurnSessionRecord(stored, piProjection, turnStartMessag
1907
1967
  updatedAtMs: stored.updatedAtMs,
1908
1968
  piMessages: restoredProjection.messages,
1909
1969
  piMessageProvenance: restoredProjection.provenance,
1910
- actors: stored.actors ?? instructionActors(piProjection.provenance),
1911
- cumulativeDurationMs: stored.cumulativeDurationMs,
1970
+ actors: instructionActors(piProjection.provenance),
1971
+ cumulativeDurationMs: runtimeMetadata?.cumulativeDurationMs ?? 0,
1912
1972
  ...definedProps({
1913
- channelName: stored.channelName,
1914
- cumulativeUsage: stored.cumulativeUsage,
1973
+ channelName: runtimeMetadata?.channelName,
1974
+ cumulativeUsage: runtimeMetadata?.cumulativeUsage,
1975
+ loadedSkillNames: runtimeMetadata?.loadedSkillNames,
1976
+ modelId: runtimeMetadata?.modelId,
1977
+ reasoningLevel: runtimeMetadata?.reasoningLevel,
1915
1978
  dispatchId: stored.dispatchId,
1916
1979
  dispatchOutcome: stored.dispatchOutcome,
1917
1980
  errorMessage: stored.errorMessage,
1918
- loadedSkillNames: stored.loadedSkillNames,
1919
- modelId: stored.modelId,
1920
- reasoningLevel: stored.reasoningLevel,
1921
1981
  resumeReason: stored.resumeReason,
1922
1982
  resultMessageId: stored.resultMessageId,
1923
1983
  resumedFromSliceId: stored.resumedFromSliceId,
@@ -1994,11 +2054,18 @@ async function materializeStoredAgentTurnSessionRecord(conversationId, sessionId
1994
2054
  const followsReplacement = followCurrentReplacement && (parsed.state === "running" || parsed.state === "awaiting_resume") && parsed.historyVersion !== void 0 && parsed.historyVersion !== currentHistoryVersion;
1995
2055
  const piProjection = followsReplacement ? projectConversationEvents(currentHistory) : pinnedProjection;
1996
2056
  const turnStartMessageIndex = followsReplacement ? 0 : parsed.turnStartSeq === void 0 ? void 0 : piProjection.seqs.filter((seq) => seq <= parsed.turnStartSeq).length;
2057
+ const conversation = await getConversationStore().get({ conversationId });
2058
+ const executionMetrics = executionMetricsForSession(conversation, sessionId);
1997
2059
  return materializeAgentTurnSessionRecord(
1998
2060
  parsed,
1999
2061
  piProjection,
2000
2062
  turnStartMessageIndex,
2001
- !followsReplacement && (parsed.historyVersion === void 0 || parsed.historyVersion === currentHistoryVersion)
2063
+ !followsReplacement && (parsed.historyVersion === void 0 || parsed.historyVersion === currentHistoryVersion),
2064
+ {
2065
+ channelName: conversation?.channelName,
2066
+ cumulativeDurationMs: executionMetrics?.durationMs,
2067
+ cumulativeUsage: executionMetrics?.usage
2068
+ }
2002
2069
  );
2003
2070
  }
2004
2071
  async function getAgentTurnSessionRecord(conversationId, sessionId) {
@@ -2027,18 +2094,11 @@ function buildStoredRecord(args) {
2027
2094
  lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
2028
2095
  updatedAtMs: nowMs,
2029
2096
  committedSeq: args.committedSeq,
2030
- cumulativeDurationMs: args.cumulativeDurationMs,
2031
2097
  ...definedProps({
2032
- actors: args.actors,
2033
- channelName: args.channelName,
2034
- cumulativeUsage: args.cumulativeUsage,
2035
2098
  dispatchId: args.dispatchId,
2036
2099
  dispatchOutcome: args.dispatchOutcome,
2037
2100
  errorMessage: args.errorMessage,
2038
2101
  historyVersion: args.historyVersion,
2039
- loadedSkillNames: args.loadedSkillNames,
2040
- modelId: args.modelId,
2041
- reasoningLevel: args.reasoningLevel,
2042
2102
  resumeReason: args.resumeReason,
2043
2103
  resultMessageId: args.resultMessageId,
2044
2104
  resumedFromSliceId: args.resumedFromSliceId,
@@ -2060,30 +2120,26 @@ async function setStoredRecord(args) {
2060
2120
  destinationVisibility: args.destinationVisibility,
2061
2121
  nowMs: Date.now(),
2062
2122
  source: args.source,
2063
- summary: storedRecord
2123
+ summary: { ...storedRecord, ...args.runtimeMetadata }
2064
2124
  });
2065
2125
  await stateAdapter.set(
2066
2126
  agentTurnSessionKey(storedRecord.conversationId, storedRecord.sessionId),
2067
2127
  storedRecord,
2068
2128
  args.ttlMs
2069
2129
  );
2070
- const {
2071
- actors: _actors,
2072
- committedSeq: _committedSeq,
2073
- historyVersion: _historyVersion,
2074
- errorMessage: _errorMessage,
2075
- turnStartSeq: _turnStartSeq,
2076
- runtimeContext: _runtimeContext,
2077
- ...summary
2078
- } = storedRecord;
2079
- await appendAgentTurnSessionSummary(summary, args.ttlMs);
2130
+ await appendAgentTurnSessionSummary(
2131
+ projectAgentTurnSessionSummary(storedRecord),
2132
+ agentTurnSessionIndexTtlMs(args.indexTtlMs)
2133
+ );
2080
2134
  return materializeAgentTurnSessionRecord(
2081
2135
  storedRecord,
2082
2136
  {
2083
2137
  messages: [...args.piMessages],
2084
2138
  provenance: [...args.piMessageProvenance]
2085
2139
  },
2086
- args.turnStartMessageIndex
2140
+ args.turnStartMessageIndex,
2141
+ true,
2142
+ args.runtimeMetadata
2087
2143
  );
2088
2144
  }
2089
2145
  async function updateAgentTurnSessionState(args) {
@@ -2097,7 +2153,17 @@ async function updateAgentTurnSessionState(args) {
2097
2153
  return await setStoredRecord({
2098
2154
  piMessages: args.existing.piMessages,
2099
2155
  piMessageProvenance: args.existing.piMessageProvenance,
2100
- ttlMs: AGENT_TURN_SESSION_TTL_MS,
2156
+ ttlMs: agentTurnSessionRecordTtlMs(args.state),
2157
+ runtimeMetadata: {
2158
+ cumulativeDurationMs: args.existing.cumulativeDurationMs,
2159
+ ...definedProps({
2160
+ channelName: args.existing.channelName,
2161
+ cumulativeUsage: args.existing.cumulativeUsage,
2162
+ loadedSkillNames: args.existing.loadedSkillNames,
2163
+ modelId: args.existing.modelId,
2164
+ reasoningLevel: args.existing.reasoningLevel
2165
+ })
2166
+ },
2101
2167
  ...definedProps({
2102
2168
  turnStartMessageIndex: args.existing.turnStartMessageIndex
2103
2169
  }),
@@ -2110,22 +2176,14 @@ async function updateAgentTurnSessionState(args) {
2110
2176
  startedAtMs: parsed.startedAtMs,
2111
2177
  lastProgressAtMs: parsed.lastProgressAtMs,
2112
2178
  previousVersion: parsed.version,
2113
- cumulativeDurationMs: args.existing.cumulativeDurationMs,
2114
- actors: args.existing.actors,
2115
2179
  ...definedProps({
2116
- channelName: parsed.channelName,
2117
- cumulativeUsage: args.existing.cumulativeUsage,
2118
2180
  dispatchId: args.existing.dispatchId,
2119
2181
  dispatchOutcome: args.existing.dispatchOutcome,
2120
2182
  errorMessage: args.errorMessage ?? args.existing.errorMessage,
2121
2183
  historyVersion: parsed.historyVersion,
2122
- loadedSkillNames: args.existing.loadedSkillNames,
2123
- modelId: args.existing.modelId,
2124
- reasoningLevel: args.existing.reasoningLevel,
2125
2184
  resumeReason: args.existing.resumeReason,
2126
2185
  resultMessageId: args.existing.resultMessageId,
2127
2186
  resumedFromSliceId: args.existing.resumedFromSliceId,
2128
- runtimeContext: parsed.runtimeContext,
2129
2187
  surface: args.existing.surface,
2130
2188
  traceId: args.existing.traceId,
2131
2189
  turnStartSeq: parsed.turnStartSeq
@@ -2138,13 +2196,20 @@ async function upsertAgentTurnSessionRecord(args) {
2138
2196
  args.conversationId,
2139
2197
  args.sessionId
2140
2198
  );
2199
+ const conversation = await (args.conversationStore ?? getConversationStore()).get({
2200
+ conversationId: args.conversationId
2201
+ });
2202
+ const executionMetrics = executionMetricsForSession(
2203
+ conversation,
2204
+ args.sessionId
2205
+ );
2141
2206
  const existingDispatchId = existingRecord?.dispatchId ?? (await listAgentTurnSessionSummariesForConversation(args.conversationId)).find((summary) => summary.sessionId === args.sessionId)?.dispatchId;
2142
2207
  if (existingDispatchId && args.dispatchId && existingDispatchId !== args.dispatchId) {
2143
2208
  throw new Error(
2144
2209
  `Turn session ${args.sessionId} dispatchId cannot be changed`
2145
2210
  );
2146
2211
  }
2147
- const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
2212
+ const ttlMs = agentTurnSessionRecordTtlMs(args.state, args.ttlMs);
2148
2213
  const instructionActor = args.actor;
2149
2214
  const commit = await commitMessages({
2150
2215
  conversationId: args.conversationId,
@@ -2174,6 +2239,19 @@ async function upsertAgentTurnSessionRecord(args) {
2174
2239
  piMessages: commit.messages,
2175
2240
  piMessageProvenance: commit.provenance,
2176
2241
  ttlMs,
2242
+ // TODO(#1267): remove the temporary caller-to-SQL metadata write once the
2243
+ // SQL-only turn-session readers have completed rollout.
2244
+ runtimeMetadata: {
2245
+ channelName: args.channelName ?? conversation?.channelName,
2246
+ cumulativeDurationMs: args.cumulativeDurationMs ?? executionMetrics?.durationMs ?? 0,
2247
+ cumulativeUsage: args.cumulativeUsage ?? executionMetrics?.usage,
2248
+ loadedSkillNames: args.loadedSkillNames,
2249
+ modelId: args.modelId,
2250
+ reasoningLevel: args.reasoningLevel
2251
+ },
2252
+ // Pass through only an explicit override so indexes stay on the resume window
2253
+ // by default even when the record takes a short terminal TTL.
2254
+ ...definedProps({ indexTtlMs: args.ttlMs }),
2177
2255
  turnStartMessageIndex,
2178
2256
  record: buildStoredRecord({
2179
2257
  conversationId: args.conversationId,
@@ -2183,26 +2261,15 @@ async function upsertAgentTurnSessionRecord(args) {
2183
2261
  committedSeq: commit.committedSeq,
2184
2262
  historyVersion: commit.historyVersion,
2185
2263
  previousVersion: existingRecord?.version,
2186
- cumulativeDurationMs: args.cumulativeDurationMs ?? existingRecord?.cumulativeDurationMs ?? 0,
2187
- modelId: args.modelId,
2188
- actors: instructionActors([
2189
- ...(existingRecord?.actors ?? []).map(instructionProvenanceFor),
2190
- ...(args.actors ?? []).map(instructionProvenanceFor),
2191
- ...commit.provenance
2192
- ]),
2193
2264
  ...definedProps({
2194
- channelName: args.channelName ?? existingRecord?.channelName,
2195
- cumulativeUsage: args.cumulativeUsage,
2196
2265
  dispatchId: args.dispatchId ?? existingRecord?.dispatchId,
2197
2266
  dispatchOutcome: args.dispatchOutcome ?? existingRecord?.dispatchOutcome,
2198
2267
  errorMessage: args.errorMessage,
2199
2268
  lastProgressAtMs: args.lastProgressAtMs,
2200
- loadedSkillNames: args.loadedSkillNames,
2201
- reasoningLevel: args.reasoningLevel ?? existingRecord?.reasoningLevel,
2202
2269
  resumeReason: args.resumeReason,
2203
2270
  resultMessageId: args.resultMessageId ?? existingRecord?.resultMessageId,
2204
2271
  resumedFromSliceId: args.resumedFromSliceId,
2205
- runtimeContext: retainedRuntimeContext,
2272
+ runtimeContext: args.state === "running" || args.state === "awaiting_resume" ? retainedRuntimeContext : void 0,
2206
2273
  startedAtMs: existingRecord?.startedAtMs,
2207
2274
  surface: args.surface ?? existingRecord?.surface,
2208
2275
  traceId: args.traceId ?? existingRecord?.traceId,
@@ -2216,6 +2283,14 @@ async function recordAgentTurnSessionSummary(args) {
2216
2283
  args.conversationId,
2217
2284
  args.sessionId
2218
2285
  );
2286
+ const conversationStore = args.conversationStore ?? getConversationStore();
2287
+ const conversation = await conversationStore.get({
2288
+ conversationId: args.conversationId
2289
+ });
2290
+ const executionMetrics = executionMetricsForSession(
2291
+ conversation,
2292
+ args.sessionId
2293
+ );
2219
2294
  const priorSummary = (await listAgentTurnSessionSummariesForConversation(args.conversationId)).find((summary2) => summary2.sessionId === args.sessionId);
2220
2295
  const existing = stored ?? priorSummary;
2221
2296
  const existingDispatchId = existing?.dispatchId;
@@ -2227,43 +2302,41 @@ async function recordAgentTurnSessionSummary(args) {
2227
2302
  );
2228
2303
  }
2229
2304
  const nowMs = Date.now();
2230
- const ttlMs = Math.max(1, args.ttlMs ?? AGENT_TURN_SESSION_TTL_MS);
2305
+ const ttlMs = agentTurnSessionIndexTtlMs(args.ttlMs);
2231
2306
  const summary = {
2232
2307
  version: existing?.version ?? 0,
2233
2308
  conversationId: args.conversationId,
2234
2309
  sessionId: args.sessionId,
2235
2310
  sliceId: args.sliceId,
2236
- startedAtMs: existing?.startedAtMs ?? args.startedAtMs ?? nowMs,
2237
- lastProgressAtMs: args.lastProgressAtMs ?? nowMs,
2238
2311
  state: args.state,
2239
2312
  updatedAtMs: nowMs,
2240
- cumulativeDurationMs: args.cumulativeDurationMs ?? existing?.cumulativeDurationMs ?? 0,
2241
2313
  ...definedProps({
2242
- channelName: args.channelName ?? existing?.channelName,
2243
- cumulativeUsage: args.cumulativeUsage ?? existing?.cumulativeUsage,
2244
2314
  dispatchId: args.dispatchId ?? existingDispatchId,
2245
2315
  dispatchOutcome: args.dispatchOutcome ?? existingDispatchOutcome,
2246
- loadedSkillNames: args.loadedSkillNames ?? existing?.loadedSkillNames,
2247
- modelId: args.modelId ?? existing?.modelId,
2248
- reasoningLevel: args.reasoningLevel ?? existing?.reasoningLevel,
2249
2316
  resumeReason: args.resumeReason,
2250
2317
  resultMessageId: args.resultMessageId ?? existingResultMessageId,
2251
- surface: args.surface ?? existing?.surface,
2252
- traceId: args.traceId ?? existing?.traceId
2318
+ surface: args.surface ?? existing?.surface
2253
2319
  })
2254
2320
  };
2255
2321
  await recordConversationActivityMetadata({
2256
2322
  actor: args.actor,
2257
- conversationStore: args.conversationStore,
2323
+ conversationStore,
2258
2324
  destination: args.destination,
2259
2325
  destinationVisibility: args.destinationVisibility,
2260
2326
  nowMs,
2261
2327
  source: args.source,
2262
- summary
2328
+ summary: {
2329
+ ...summary,
2330
+ channelName: args.channelName ?? conversation?.channelName,
2331
+ cumulativeDurationMs: args.cumulativeDurationMs ?? executionMetrics?.durationMs ?? 0,
2332
+ cumulativeUsage: args.cumulativeUsage ?? executionMetrics?.usage,
2333
+ startedAtMs: stored?.startedAtMs ?? args.startedAtMs ?? nowMs
2334
+ }
2263
2335
  });
2264
2336
  await appendAgentTurnSessionSummary(summary, ttlMs);
2265
2337
  }
2266
- async function readAgentTurnSessionSummariesFromIndex(key, stateAdapter) {
2338
+ async function readAgentTurnSessionSummariesFromIndex(key) {
2339
+ const stateAdapter = getStateAdapter();
2267
2340
  await stateAdapter.connect();
2268
2341
  const values = await stateAdapter.getList(key);
2269
2342
  const summaries = /* @__PURE__ */ new Map();
@@ -2271,11 +2344,7 @@ async function readAgentTurnSessionSummariesFromIndex(key, stateAdapter) {
2271
2344
  let summary;
2272
2345
  try {
2273
2346
  summary = parseAgentTurnSessionSummary(value);
2274
- } catch (error) {
2275
- logWarn("agent.turn.session_summary_parse.failed", {
2276
- "app.state.key": key,
2277
- "exception.message": error instanceof Error ? error.message : String(error)
2278
- });
2347
+ } catch {
2279
2348
  continue;
2280
2349
  }
2281
2350
  const summaryKey = `${summary.conversationId}:${summary.sessionId}`;
@@ -2288,20 +2357,8 @@ async function readAgentTurnSessionSummariesFromIndex(key, stateAdapter) {
2288
2357
  );
2289
2358
  }
2290
2359
  async function listAgentTurnSessionSummariesForConversation(conversationId) {
2291
- const stateAdapter = getStateAdapter();
2292
- const summaries = await listBoundedAgentTurnSessionSummariesForConversation(conversationId);
2293
- if (summaries.length > 0) {
2294
- return summaries;
2295
- }
2296
- return (await readAgentTurnSessionSummariesFromIndex(
2297
- AGENT_TURN_SESSION_INDEX_KEY,
2298
- stateAdapter
2299
- )).filter((summary) => summary.conversationId === conversationId);
2300
- }
2301
- async function listBoundedAgentTurnSessionSummariesForConversation(conversationId) {
2302
2360
  return readAgentTurnSessionSummariesFromIndex(
2303
- agentTurnSessionConversationIndexKey(conversationId),
2304
- getStateAdapter()
2361
+ agentTurnSessionConversationIndexKey(conversationId)
2305
2362
  );
2306
2363
  }
2307
2364
  async function abandonAgentTurnSessionRecord(args) {
@@ -2501,9 +2558,9 @@ async function persistCompletedSessionRecord(args) {
2501
2558
  destination: args.destination,
2502
2559
  destinationVisibility: args.destinationVisibility,
2503
2560
  dispatchId: args.dispatchId,
2504
- loadedSkillNames: args.loadedSkillNames ?? latestSessionRecord?.loadedSkillNames,
2561
+ loadedSkillNames: args.loadedSkillNames,
2505
2562
  modelId: args.modelId,
2506
- reasoningLevel: args.reasoningLevel ?? latestSessionRecord?.reasoningLevel,
2563
+ reasoningLevel: args.reasoningLevel,
2507
2564
  sessionId: args.sessionId,
2508
2565
  source: args.source,
2509
2566
  surface: args.surface,
@@ -2582,7 +2639,7 @@ async function persistAuthPauseSessionRecord(args) {
2582
2639
  // Auth-pause keeps caller-owned skill names only.
2583
2640
  loadedSkillNames: args.loadedSkillNames,
2584
2641
  modelId: args.modelId,
2585
- reasoningLevel: args.reasoningLevel ?? latestSessionRecord?.reasoningLevel,
2642
+ reasoningLevel: args.reasoningLevel,
2586
2643
  sessionId: args.sessionId,
2587
2644
  source: args.source,
2588
2645
  surface: args.surface
@@ -2653,7 +2710,7 @@ async function persistContinuationSessionRecord(args) {
2653
2710
  // Continuation keeps caller-owned skill names only.
2654
2711
  loadedSkillNames: args.loadedSkillNames,
2655
2712
  modelId: args.modelId,
2656
- reasoningLevel: args.reasoningLevel ?? latestSessionRecord?.reasoningLevel,
2713
+ reasoningLevel: args.reasoningLevel,
2657
2714
  sessionId: args.sessionId,
2658
2715
  source: args.source,
2659
2716
  surface: args.surface
@@ -2721,7 +2778,7 @@ async function persistYieldSessionRecord(args) {
2721
2778
  // Yield keeps caller-owned skill names only.
2722
2779
  loadedSkillNames: args.loadedSkillNames,
2723
2780
  modelId: args.modelId,
2724
- reasoningLevel: args.reasoningLevel ?? latestSessionRecord?.reasoningLevel,
2781
+ reasoningLevel: args.reasoningLevel,
2725
2782
  sessionId: args.sessionId,
2726
2783
  source: args.source,
2727
2784
  surface: args.surface
@@ -3144,6 +3201,19 @@ function buildThreadStatePayload(patch) {
3144
3201
  }
3145
3202
  return payload;
3146
3203
  }
3204
+ async function mergePersistedState(key, payload) {
3205
+ if (Object.keys(payload).length === 0) {
3206
+ return;
3207
+ }
3208
+ const stateAdapter = getStateAdapter();
3209
+ await stateAdapter.connect();
3210
+ const existing = await stateAdapter.get(key) ?? {};
3211
+ await stateAdapter.set(
3212
+ key,
3213
+ { ...existing, ...payload },
3214
+ JUNIOR_THREAD_STATE_TTL_MS
3215
+ );
3216
+ }
3147
3217
  function mergeArtifactsState(artifacts, patch) {
3148
3218
  if (!patch) {
3149
3219
  return artifacts;
@@ -3180,11 +3250,14 @@ async function persistThreadState(thread, patch) {
3180
3250
  await persistThreadRuntimeState(thread, patch);
3181
3251
  }
3182
3252
  async function persistThreadRuntimeState(thread, patch) {
3183
- const payload = buildThreadStatePayload(patch);
3184
- if (Object.keys(payload).length === 0) {
3185
- return;
3253
+ const threadId = toOptionalString(thread.id) ?? toOptionalString(thread.runId);
3254
+ if (!threadId) {
3255
+ throw new Error("thread id is required to persist runtime scratch");
3186
3256
  }
3187
- await thread.setState(payload);
3257
+ await mergePersistedState(
3258
+ threadStateKey(threadId),
3259
+ buildThreadStatePayload(patch)
3260
+ );
3188
3261
  }
3189
3262
  async function getPersistedThreadState(threadId) {
3190
3263
  const stateAdapter = getStateAdapter();
@@ -3207,26 +3280,21 @@ async function persistThreadStateById(threadId, patch) {
3207
3280
  conversationId: threadId
3208
3281
  });
3209
3282
  }
3210
- const payload = buildThreadStatePayload(patch);
3211
- if (Object.keys(payload).length === 0) {
3212
- return;
3213
- }
3214
- const stateAdapter = getStateAdapter();
3215
- await stateAdapter.connect();
3216
- const key = threadStateKey(threadId);
3217
- const existing = await stateAdapter.get(key) ?? {};
3218
- await stateAdapter.set(
3219
- key,
3220
- { ...existing, ...payload },
3221
- JUNIOR_THREAD_STATE_TTL_MS
3283
+ await mergePersistedState(
3284
+ threadStateKey(threadId),
3285
+ buildThreadStatePayload(patch)
3222
3286
  );
3223
3287
  }
3224
3288
  function getChannelConfigurationService(thread) {
3225
3289
  const channel = thread.channel;
3290
+ const channelId = toOptionalString(thread.channelId) ?? toOptionalString(channel.id);
3291
+ if (!channelId) {
3292
+ throw new Error("channel id is required to load channel configuration");
3293
+ }
3226
3294
  return createChannelConfigurationService({
3227
- load: async () => channel.state,
3295
+ load: async () => await channel.state,
3228
3296
  save: async (state) => {
3229
- await channel.setState({
3297
+ await mergePersistedState(channelStateKey(channelId), {
3230
3298
  configuration: state
3231
3299
  });
3232
3300
  }
@@ -3236,15 +3304,9 @@ function getChannelConfigurationServiceById(channelId) {
3236
3304
  return createChannelConfigurationService({
3237
3305
  load: async () => await getPersistedChannelState(channelId),
3238
3306
  save: async (state) => {
3239
- const stateAdapter = getStateAdapter();
3240
- await stateAdapter.connect();
3241
- const key = channelStateKey(channelId);
3242
- const existing = await stateAdapter.get(key) ?? {};
3243
- await stateAdapter.set(
3244
- key,
3245
- { ...existing, configuration: state },
3246
- JUNIOR_THREAD_STATE_TTL_MS
3247
- );
3307
+ await mergePersistedState(channelStateKey(channelId), {
3308
+ configuration: state
3309
+ });
3248
3310
  }
3249
3311
  });
3250
3312
  }
@@ -3357,6 +3419,7 @@ export {
3357
3419
  recordAuthorizationRequested,
3358
3420
  recordAuthorizationCompleted,
3359
3421
  recordAuthenticationLinked,
3422
+ recordAgentsInstructionsUpdated,
3360
3423
  loadTurnRoute,
3361
3424
  recordTurnRoute,
3362
3425
  recordToolExecutionStarted,
@@ -9,7 +9,7 @@ import {
9
9
  } from "./chunk-6GWA276C.js";
10
10
  import {
11
11
  getDeploymentTelemetryAttributes
12
- } from "./chunk-C2N6MNO4.js";
12
+ } from "./chunk-OFQBDHVG.js";
13
13
 
14
14
  // src/chat/logging.ts
15
15
  import path from "path";