@agent-native/core 0.153.4 → 0.153.5

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 (67) hide show
  1. package/corpus/templates/analytics/actions/account-deep-dive.ts +1 -0
  2. package/corpus/templates/analytics/actions/bigquery-query.ts +1 -0
  3. package/corpus/templates/analytics/actions/bigquery.ts +1 -0
  4. package/corpus/templates/analytics/actions/content-calendar-schema.ts +1 -0
  5. package/corpus/templates/analytics/actions/content-calendar.ts +1 -0
  6. package/corpus/templates/analytics/actions/gcloud.ts +1 -0
  7. package/corpus/templates/analytics/actions/get-data-program.ts +1 -0
  8. package/corpus/templates/analytics/actions/get-error-issue.ts +1 -0
  9. package/corpus/templates/analytics/actions/get-monitor-stats.ts +1 -0
  10. package/corpus/templates/analytics/actions/get-monitor.ts +1 -0
  11. package/corpus/templates/analytics/actions/get-session-replay-events.ts +1 -0
  12. package/corpus/templates/analytics/actions/get-session-replay-summary.ts +1 -0
  13. package/corpus/templates/analytics/actions/get-session-replay-timeline.ts +1 -0
  14. package/corpus/templates/analytics/actions/gong-calls.ts +1 -0
  15. package/corpus/templates/analytics/actions/gong-native-insights.ts +1 -0
  16. package/corpus/templates/analytics/actions/grafana.ts +1 -0
  17. package/corpus/templates/analytics/actions/hubspot-deals.ts +1 -0
  18. package/corpus/templates/analytics/actions/hubspot-metrics.ts +1 -0
  19. package/corpus/templates/analytics/actions/hubspot-pipelines.ts +1 -0
  20. package/corpus/templates/analytics/actions/hubspot-records.ts +1 -0
  21. package/corpus/templates/analytics/actions/jira-search.ts +1 -0
  22. package/corpus/templates/analytics/actions/jira.ts +1 -0
  23. package/corpus/templates/analytics/actions/list-error-issues.ts +1 -0
  24. package/corpus/templates/analytics/actions/list-monitors.ts +1 -0
  25. package/corpus/templates/analytics/actions/list-session-recordings.ts +1 -0
  26. package/corpus/templates/analytics/actions/match-error-issues.ts +1 -0
  27. package/corpus/templates/analytics/actions/prometheus.ts +1 -0
  28. package/corpus/templates/analytics/actions/pylon-issues.ts +1 -0
  29. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -0
  30. package/corpus/templates/analytics/actions/query-dashboard-panel.ts +1 -0
  31. package/corpus/templates/analytics/actions/query-inbound-forms.ts +1 -0
  32. package/corpus/templates/analytics/actions/run-monitor-check.ts +1 -0
  33. package/corpus/templates/analytics/actions/sentry.ts +1 -0
  34. package/corpus/templates/analytics/actions/seo-blog-pages.ts +1 -0
  35. package/corpus/templates/analytics/actions/seo-page-keywords.ts +1 -0
  36. package/corpus/templates/analytics/actions/seo-top-keywords.ts +1 -0
  37. package/corpus/templates/analytics/actions/slack-messages.ts +1 -0
  38. package/corpus/templates/analytics/actions/stripe.ts +1 -0
  39. package/corpus/templates/analytics/actions/test-custom-api-connection.ts +1 -0
  40. package/corpus/templates/analytics/server/lib/real-data-actions.ts +38 -47
  41. package/corpus/templates/analytics/server/plugins/agent-chat.ts +40 -34
  42. package/dist/action.d.ts +13 -0
  43. package/dist/action.js +3 -0
  44. package/dist/agent/engine/tool-call-journal-seed.d.ts +27 -10
  45. package/dist/agent/engine/tool-call-journal-seed.js +46 -32
  46. package/dist/agent/production-agent.d.ts +33 -0
  47. package/dist/agent/production-agent.js +172 -57
  48. package/dist/agent/run-loop-with-resume.d.ts +1 -1
  49. package/dist/agent/run-loop-with-resume.js +49 -35
  50. package/dist/client/agent-chat-adapter.js +204 -273
  51. package/dist/client/sse-event-processor.d.ts +7 -0
  52. package/dist/client/sse-event-processor.js +21 -1
  53. package/dist/collab/awareness.d.ts +2 -2
  54. package/dist/collab/struct-routes.d.ts +1 -1
  55. package/dist/observability/routes.d.ts +5 -5
  56. package/dist/progress/routes.d.ts +1 -1
  57. package/dist/provider-api/actions/github-repo-files.js +1 -0
  58. package/dist/provider-api/actions/provider-api.js +1 -0
  59. package/dist/provider-api/actions/staged-datasets.js +1 -0
  60. package/dist/provider-api/corpus-jobs.js +1 -0
  61. package/dist/resources/handlers.d.ts +1 -1
  62. package/dist/secrets/routes.d.ts +9 -9
  63. package/dist/server/action-discovery.js +2 -0
  64. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  65. package/dist/server/realtime-token.d.ts +1 -1
  66. package/dist/server/transcribe-voice.d.ts +1 -1
  67. package/package.json +3 -3
@@ -24,23 +24,35 @@ import { runAgentLoop, appendAgentLoopContinuation, isResumableEngineError, isTr
24
24
  import { resolveRunSoftTimeoutMs } from "./run-manager.js";
25
25
  import { getCurrentTurnEventsForThread } from "./run-store.js";
26
26
  import { classifyToolCallJournal, buildResumeJournalNote, } from "./tool-call-journal.js";
27
- async function readCurrentTurnEventsForResume(threadId, localEvents = []) {
27
+ /**
28
+ * `persisted: false` means the durable half of the turn could not be read, so
29
+ * `events` holds only what this invocation saw. Callers that decide whether to
30
+ * DISCARD user-visible output must not read that as "nothing else happened".
31
+ */
32
+ async function readCurrentTurnEventsForResume(threadId, turnId, localEvents = []) {
28
33
  let persistedEvents = [];
34
+ let persisted = true;
29
35
  try {
36
+ // Without the turnId this can return the PREVIOUS turn's events — see
37
+ // `getCurrentTurnEventsForThread`, whose run row is written without await.
30
38
  persistedEvents = threadId
31
- ? await getCurrentTurnEventsForThread(threadId)
39
+ ? await getCurrentTurnEventsForThread(threadId, turnId)
32
40
  : [];
33
41
  }
34
- catch {
35
- persistedEvents = [];
42
+ catch (err) {
43
+ persisted = false;
44
+ console.warn("[run-loop] current-turn ledger read failed:", err instanceof Error ? err.message : String(err));
36
45
  }
37
46
  if (localEvents.length === 0)
38
- return persistedEvents;
47
+ return { events: persistedEvents, persisted };
39
48
  const seen = new Set(persistedEvents.map((event) => JSON.stringify(event)));
40
- return [
41
- ...persistedEvents,
42
- ...localEvents.filter((event) => !seen.has(JSON.stringify(event))),
43
- ];
49
+ return {
50
+ events: [
51
+ ...persistedEvents,
52
+ ...localEvents.filter((event) => !seen.has(JSON.stringify(event))),
53
+ ],
54
+ persisted,
55
+ };
44
56
  }
45
57
  function actionPreparationContinuationOptions(events) {
46
58
  const actionPreparationTool = lastUnfinishedPreparingActionToolFromEvents(events);
@@ -86,8 +98,8 @@ function appendToolCallJournalNote(messages, events) {
86
98
  // up — the model still continues, just without the structured journal.
87
99
  }
88
100
  }
89
- async function appendContinuationAndJournal(messages, reason, threadId, localEvents = []) {
90
- const events = await readCurrentTurnEventsForResume(threadId, localEvents);
101
+ async function appendContinuationAndJournal(messages, reason, threadId, turnId, localEvents = []) {
102
+ const { events } = await readCurrentTurnEventsForResume(threadId, turnId, localEvents);
91
103
  appendAgentLoopContinuation(messages, reason, actionPreparationContinuationOptions(events));
92
104
  appendToolCallJournalNote(messages, events);
93
105
  }
@@ -95,21 +107,23 @@ async function appendContinuationAndJournal(messages, reason, threadId, localEve
95
107
  * Rebuild the same safe continuation context for a logical turn that resumes
96
108
  * in a fresh hosted invocation.
97
109
  */
98
- export async function appendDurableContinuationContext(messages, reason, threadId) {
99
- await appendContinuationAndJournal(messages, reason, threadId);
110
+ export async function appendDurableContinuationContext(messages, reason, threadId, turnId) {
111
+ await appendContinuationAndJournal(messages, reason, threadId, turnId);
100
112
  }
101
- async function hasCompletedSideEffectToolCallInCurrentTurn(threadId, localEvents = []) {
102
- try {
103
- const events = await readCurrentTurnEventsForResume(threadId, localEvents);
104
- if (events.length === 0)
105
- return false;
106
- return events.some((event) => event.type === "tool_done" &&
107
- event.completedSideEffect === true &&
108
- event.isError !== true);
109
- }
110
- catch {
111
- return false;
112
- }
113
+ /**
114
+ * `"unknown"` is not `"none"`: the only caller uses this to decide whether to
115
+ * emit `clear`, and `clear` WIPES user-visible output. A transient ledger error
116
+ * must not delete the tool cards that are the user's only proof a side effect
117
+ * landed.
118
+ */
119
+ async function completedSideEffectInCurrentTurn(threadId, turnId, localEvents = []) {
120
+ const { events, persisted } = await readCurrentTurnEventsForResume(threadId, turnId, localEvents);
121
+ const found = events.some((event) => event.type === "tool_done" &&
122
+ event.completedSideEffect === true &&
123
+ event.isError !== true);
124
+ if (found)
125
+ return "some";
126
+ return persisted ? "none" : "unknown";
113
127
  }
114
128
  function internalContinuationReasonForAttempt(events) {
115
129
  const last = events.at(-1);
@@ -362,15 +376,15 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
362
376
  if (internalContinuationReason && !upstreamSignal.aborted) {
363
377
  lastAttemptWasUnfinishedContinuation = true;
364
378
  const continuationEvents = [...localTurnEvents];
365
- if (!(await hasCompletedSideEffectToolCallInCurrentTurn(opts.threadId, continuationEvents))) {
379
+ if ((await completedSideEffectInCurrentTurn(opts.threadId, opts.turnId, continuationEvents)) === "none") {
366
380
  opts.send({ type: "clear" });
367
381
  }
368
- await appendContinuationAndJournal(opts.messages, internalContinuationReason, opts.threadId, continuationEvents);
382
+ await appendContinuationAndJournal(opts.messages, internalContinuationReason, opts.threadId, opts.turnId, continuationEvents);
369
383
  continue;
370
384
  }
371
385
  if (softTimedOut && !upstreamSignal.aborted) {
372
386
  lastAttemptWasUnfinishedContinuation = true;
373
- await appendContinuationAndJournal(opts.messages, "run_timeout", opts.threadId, localTurnEvents);
387
+ await appendContinuationAndJournal(opts.messages, "run_timeout", opts.threadId, opts.turnId, localTurnEvents);
374
388
  continue;
375
389
  }
376
390
  reportFinalOutcome(upstreamSignal.aborted
@@ -383,10 +397,10 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
383
397
  // Clear partial text the client received before the abort so the
384
398
  // resumed model doesn't re-emit it and produce duplicated output.
385
399
  lastAttemptWasUnfinishedContinuation = true;
386
- if (!(await hasCompletedSideEffectToolCallInCurrentTurn(opts.threadId, localTurnEvents))) {
400
+ if ((await completedSideEffectInCurrentTurn(opts.threadId, opts.turnId, localTurnEvents)) === "none") {
387
401
  opts.send({ type: "clear" });
388
402
  }
389
- await appendContinuationAndJournal(opts.messages, "run_timeout", opts.threadId, localTurnEvents);
403
+ await appendContinuationAndJournal(opts.messages, "run_timeout", opts.threadId, opts.turnId, localTurnEvents);
390
404
  continue;
391
405
  }
392
406
  const transientRateLimit = isTransientProviderRateLimitError(err);
@@ -402,10 +416,10 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
402
416
  rateLimitRetryFitsBudget) {
403
417
  lastAttemptWasUnfinishedContinuation = true;
404
418
  backgroundRateLimitContinuations++;
405
- if (!(await hasCompletedSideEffectToolCallInCurrentTurn(opts.threadId, localTurnEvents))) {
419
+ if ((await completedSideEffectInCurrentTurn(opts.threadId, opts.turnId, localTurnEvents)) === "none") {
406
420
  opts.send({ type: "clear" });
407
421
  }
408
- await appendContinuationAndJournal(opts.messages, "rate_limited", opts.threadId, localTurnEvents);
422
+ await appendContinuationAndJournal(opts.messages, "rate_limited", opts.threadId, opts.turnId, localTurnEvents);
409
423
  await waitForBackgroundRateLimitCooldown(upstreamSignal);
410
424
  continue;
411
425
  }
@@ -424,10 +438,10 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
424
438
  // the in-memory messages array, so the next attempt re-emits it).
425
439
  if (!upstreamSignal.aborted && isResumableEngineError(err)) {
426
440
  lastAttemptWasUnfinishedContinuation = true;
427
- if (!(await hasCompletedSideEffectToolCallInCurrentTurn(opts.threadId, localTurnEvents))) {
441
+ if ((await completedSideEffectInCurrentTurn(opts.threadId, opts.turnId, localTurnEvents)) === "none") {
428
442
  opts.send({ type: "clear" });
429
443
  }
430
- await appendContinuationAndJournal(opts.messages, continuationReasonForResumableError(err), opts.threadId, localTurnEvents);
444
+ await appendContinuationAndJournal(opts.messages, continuationReasonForResumableError(err), opts.threadId, opts.turnId, localTurnEvents);
431
445
  continue;
432
446
  }
433
447
  if (upstreamSignal.aborted) {
@@ -467,7 +481,7 @@ export async function runAgentLoopDirectWithSoftTimeout(opts, softTimeoutMs, tim
467
481
  // the terminal message stands alone instead of trailing a half sentence.
468
482
  // Preserve completed tool cards: they are the user's only durable proof
469
483
  // that a side effect landed before the final assistant note timed out.
470
- if (!(await hasCompletedSideEffectToolCallInCurrentTurn(opts.threadId, localTurnEvents))) {
484
+ if ((await completedSideEffectInCurrentTurn(opts.threadId, opts.turnId, localTurnEvents)) === "none") {
471
485
  opts.send({ type: "clear" });
472
486
  }
473
487
  opts.send({