@agent-native/core 0.219.0 → 0.220.0-nightly-20261023212848

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 (97) hide show
  1. package/dist/action.d.ts +23 -3
  2. package/dist/action.js +58 -3
  3. package/dist/agent/abort-reasons.d.ts +6 -0
  4. package/dist/agent/abort-reasons.js +6 -0
  5. package/dist/agent/execution-fence.js +5 -1
  6. package/dist/agent/production-agent.d.ts +22 -6
  7. package/dist/agent/production-agent.js +136 -37
  8. package/dist/agent/run-manager.js +92 -44
  9. package/dist/agent/run-store.d.ts +1 -0
  10. package/dist/agent/run-store.js +260 -31
  11. package/dist/agent/run-terminal-tracking.d.ts +29 -0
  12. package/dist/agent/run-terminal-tracking.js +56 -0
  13. package/dist/agent/run-turn-id-header.d.ts +9 -0
  14. package/dist/agent/run-turn-id-header.js +13 -0
  15. package/dist/agent/types.d.ts +11 -0
  16. package/dist/chat-threads/store.d.ts +23 -6
  17. package/dist/chat-threads/store.js +119 -36
  18. package/dist/cli/amplify-stream.js +1 -1
  19. package/dist/client/agent-chat/index.d.ts +2 -1
  20. package/dist/client/agent-chat/index.js +2 -1
  21. package/dist/client/agent-chat.d.ts +2 -0
  22. package/dist/client/agent-chat.js +31 -5
  23. package/dist/client/chat/agentkit-agent-native.js +8 -1
  24. package/dist/client/chat/agentkit-protocol.js +7 -1
  25. package/dist/client/chat/run-outcome-telemetry.js +1 -0
  26. package/dist/client/chat/run-outcome.d.ts +5 -0
  27. package/dist/client/chat/runtime.d.ts +34 -1
  28. package/dist/client/chat/runtime.js +96 -12
  29. package/dist/client/chat/turn-submitted-telemetry.d.ts +4 -0
  30. package/dist/client/chat/turn-submitted-telemetry.js +39 -0
  31. package/dist/client/chat/turn-submitted.d.ts +39 -0
  32. package/dist/client/chat/turn-submitted.js +16 -0
  33. package/dist/client/route-chunk-recovery.d.ts +3 -8
  34. package/dist/client/route-chunk-recovery.js +11 -9
  35. package/dist/client/use-chat-thread-list.d.ts +2 -0
  36. package/dist/client/use-chat-thread-list.js +48 -2
  37. package/dist/client/use-chat-threads.d.ts +13 -0
  38. package/dist/client/use-chat-threads.js +59 -4
  39. package/dist/collab/routes.d.ts +2 -2
  40. package/dist/db/client.d.ts +1 -0
  41. package/dist/db/client.js +28 -18
  42. package/dist/db/schema-snapshot.generated.js +5 -0
  43. package/dist/identity/rekey.d.ts +2 -0
  44. package/dist/identity/rekey.js +19 -0
  45. package/dist/index.d.ts +1 -1
  46. package/dist/index.js +1 -1
  47. package/dist/mcp/agent-connected.d.ts +5 -0
  48. package/dist/mcp/agent-connected.js +10 -3
  49. package/dist/mcp/analytics.d.ts +14 -1
  50. package/dist/mcp/analytics.js +54 -2
  51. package/dist/mcp/embed-app.js +2 -1
  52. package/dist/mcp/oauth-route.js +56 -1
  53. package/dist/notifications/routes.d.ts +1 -1
  54. package/dist/observability/routes.d.ts +7 -7
  55. package/dist/observability/traces.d.ts +2 -0
  56. package/dist/observability/traces.js +11 -2
  57. package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
  58. package/dist/provider-api/actions/provider-api.d.ts +13 -13
  59. package/dist/provider-api/corpus-jobs.d.ts +2 -2
  60. package/dist/resources/handlers.d.ts +1 -1
  61. package/dist/review/index.d.ts +1 -1
  62. package/dist/review/index.js +1 -1
  63. package/dist/review/suggestions/actions.js +25 -17
  64. package/dist/review/suggestions/store.d.ts +14 -1
  65. package/dist/review/suggestions/store.js +16 -3
  66. package/dist/review/suggestions/types.d.ts +15 -1
  67. package/dist/scripts/chat/search-chats.js +14 -2
  68. package/dist/server/agent-chat/browser-team-tools.js +39 -6
  69. package/dist/server/agent-chat/script-entries.js +44 -9
  70. package/dist/server/agent-chat-plugin.d.ts +2 -0
  71. package/dist/server/agent-chat-plugin.js +66 -16
  72. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  73. package/dist/server/agent-engine-default-model-route.d.ts +1 -1
  74. package/dist/server/first-touch-route.d.ts +2 -2
  75. package/dist/shared/route-chunk-recovery-bootstrap.d.ts +9 -0
  76. package/dist/shared/route-chunk-recovery-bootstrap.js +25 -0
  77. package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
  78. package/dist/templates/chat/.agents/skills/actions/SKILL.md +1 -0
  79. package/dist/templates/default/.agents/skills/actions/SKILL.md +1 -0
  80. package/dist/templates/factory/.agents/skills/review-prs/SKILL.md +27 -3
  81. package/dist/templates/headless/.agents/skills/actions/SKILL.md +1 -0
  82. package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -0
  83. package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +12 -5
  84. package/dist/tracking/providers.js +3 -0
  85. package/dist/triggers/actions/manage-automation.d.ts +2 -2
  86. package/docs/content/external-agents.mdx +1 -1
  87. package/docs/content/mcp-apps.mdx +3 -3
  88. package/docs/content/mcp-protocol.mdx +1 -1
  89. package/docs/content/sharing.mdx +1 -0
  90. package/docs/content/template-assets-integrations.mdx +5 -3
  91. package/package.json +3 -3
  92. package/src/templates/chat/.agents/skills/actions/SKILL.md +1 -0
  93. package/src/templates/default/.agents/skills/actions/SKILL.md +1 -0
  94. package/src/templates/factory/.agents/skills/review-prs/SKILL.md +27 -3
  95. package/src/templates/headless/.agents/skills/actions/SKILL.md +1 -0
  96. package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -0
  97. package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +12 -5
package/dist/action.d.ts CHANGED
@@ -106,6 +106,20 @@ export interface FailOptions {
106
106
  details?: Record<string, unknown>;
107
107
  }
108
108
  export declare function fail(message: string, options?: FailOptions): never;
109
+ /**
110
+ * A rejection raised before the action's first write: a missing target, an
111
+ * edit that matches nothing, a patch identical to what is saved. A caller may
112
+ * then retry with corrected arguments instead of treating the call as
113
+ * possibly applied. The framework accepts the claim only for the call that
114
+ * raised it, and only when no write action nested in that call entered its
115
+ * handler; otherwise it reads as any other failure. It cannot see the
116
+ * handler's own database or provider writes, so throw it before the first.
117
+ */
118
+ export declare class NoWriteError extends ActionContractError {
119
+ readonly noWrite = true;
120
+ constructor(message: string, options?: FailOptions);
121
+ }
122
+ export declare function isNoWriteError(error: unknown): error is NoWriteError;
109
123
  export type { ActionMcpOutputContract } from "./action-output-contract.js";
110
124
  /** What a call that broke its output contract already did. `run` returned
111
125
  * before the check, so a non-read-only call's changes are applied. */
@@ -136,8 +150,9 @@ export declare function isActionOutputContractError(error: unknown): error is Ac
136
150
  /**
137
151
  * What a failed call had already done, when its failure came after `run`
138
152
  * returned: an output-contract error, or a stop or connection signal raised
139
- * while its result was checked. `undefined` when the failure carries no such
140
- * evidence, so the caller must not assume the call changed nothing.
153
+ * while its result was checked; or a verified `NoWriteError`. `undefined`
154
+ * when the failure carries no such evidence, so the caller must not assume
155
+ * the call changed nothing.
141
156
  */
142
157
  export declare function actionFailureEffect(error: unknown): ActionOutputEffect | undefined;
143
158
  /** What a dispatched call did, and whether other sessions must refresh. */
@@ -167,10 +182,15 @@ export declare function invocationEffect(entry: {
167
182
  receipt?: {
168
183
  changed: boolean;
169
184
  };
170
- /** It failed, with what it threw; `lost` when its result never came. */
185
+ /**
186
+ * It failed, with what it threw; `lost` when its result never came;
187
+ * `reported` when it returned an error result instead, such as an MCP
188
+ * tool's `isError`, which says the tool did not do its work.
189
+ */
171
190
  failed?: {
172
191
  error?: unknown;
173
192
  lost?: boolean;
193
+ reported?: boolean;
174
194
  };
175
195
  }): InvocationEffect;
176
196
  /** Whether a failed call must publish an action change. */
package/dist/action.js CHANGED
@@ -76,6 +76,32 @@ export function fail(message, options = {}) {
76
76
  ...(options.details === undefined ? {} : { details: options.details }),
77
77
  });
78
78
  }
79
+ /**
80
+ * A rejection raised before the action's first write: a missing target, an
81
+ * edit that matches nothing, a patch identical to what is saved. A caller may
82
+ * then retry with corrected arguments instead of treating the call as
83
+ * possibly applied. The framework accepts the claim only for the call that
84
+ * raised it, and only when no write action nested in that call entered its
85
+ * handler; otherwise it reads as any other failure. It cannot see the
86
+ * handler's own database or provider writes, so throw it before the first.
87
+ */
88
+ export class NoWriteError extends ActionContractError {
89
+ noWrite = true;
90
+ constructor(message, options = {}) {
91
+ super(message, {
92
+ errorCode: options.errorCode ?? "action_failed",
93
+ statusCode: options.statusCode ?? 400,
94
+ ...(options.details === undefined ? {} : { details: options.details }),
95
+ });
96
+ this.name = "NoWriteError";
97
+ }
98
+ }
99
+ export function isNoWriteError(error) {
100
+ return (isActionContractError(error) &&
101
+ error.noWrite === true);
102
+ }
103
+ /** Each `NoWriteError` the call that raised it was verified to have written nothing in. */
104
+ const verifiedNoWrites = new WeakSet();
79
105
  const MAX_REPORTED_OUTPUT_ISSUES = 5;
80
106
  const MAX_DETAILED_OUTPUT_ISSUES = 50;
81
107
  function actionSubject(actionName) {
@@ -126,10 +152,16 @@ export function isActionOutputContractError(error) {
126
152
  /**
127
153
  * What a failed call had already done, when its failure came after `run`
128
154
  * returned: an output-contract error, or a stop or connection signal raised
129
- * while its result was checked. `undefined` when the failure carries no such
130
- * evidence, so the caller must not assume the call changed nothing.
155
+ * while its result was checked; or a verified `NoWriteError`. `undefined`
156
+ * when the failure carries no such evidence, so the caller must not assume
157
+ * the call changed nothing.
131
158
  */
132
159
  export function actionFailureEffect(error) {
160
+ if (error !== null &&
161
+ typeof error === "object" &&
162
+ verifiedNoWrites.has(error)) {
163
+ return "none";
164
+ }
133
165
  if (isActionOutputContractError(error))
134
166
  return error.effect;
135
167
  if (!isAgentActionStopError(error))
@@ -170,6 +202,10 @@ export function invocationEffect(entry, outcome, settled) {
170
202
  return { effect: "none", changed: false };
171
203
  if (outcome.keyed && !record)
172
204
  return { effect: "unknown", changed: true };
205
+ // The report speaks for the tool, not for a write nested in the call.
206
+ if (failed?.reported && !failed.lost && !evidence?.nestedWriteEntered) {
207
+ return { effect: "none", changed: false };
208
+ }
173
209
  // A typed effect speaks for the call that raised it, not for one it passed
174
210
  // through. Untracked, nothing names that call, so it stands.
175
211
  const typed = failed && !failed.lost && (!evidence || evidence.raised === failed.error)
@@ -183,7 +219,7 @@ export function invocationEffect(entry, outcome, settled) {
183
219
  }
184
220
  const wrote = record ? record.evidence.writeEntered : readOnly !== true;
185
221
  const changed = record
186
- ? record.evidence.changeEntered
222
+ ? record.evidence.changeEntered && !(failed && typed === "none")
187
223
  : entry.changeEvents !== false && (failed ? typed === "committed" : wrote);
188
224
  const effect = !failed
189
225
  ? (settled.receipt?.changed ?? wrote)
@@ -346,6 +382,14 @@ function postRunSignal(signal, failure) {
346
382
  function withCommittedEffect(error) {
347
383
  if (actionFailureEffect(error) !== "none")
348
384
  return error;
385
+ // Its claim holds only for the call that raised it.
386
+ if (isNoWriteError(error)) {
387
+ return new ActionContractError(error.message, {
388
+ errorCode: error.errorCode,
389
+ statusCode: error.statusCode,
390
+ ...(error.details === undefined ? {} : { details: error.details }),
391
+ });
392
+ }
349
393
  if (isActionOutputContractError(error)) {
350
394
  return new ActionOutputContractError({
351
395
  actionName: error.actionName,
@@ -507,6 +551,17 @@ export function defineAction(options) {
507
551
  }
508
552
  catch (thrown) {
509
553
  const error = readableFailure(thrown);
554
+ // Raised by this handler, not passed up through a nested call's
555
+ // boundary, with no nested write entered.
556
+ if (!ran &&
557
+ frame &&
558
+ isNoWriteError(error) &&
559
+ !frame.nestedWriteEntered &&
560
+ actionExecutionStorage?.getStore()?.failures.get(error) === undefined) {
561
+ verifiedNoWrites.add(error);
562
+ frame.raised = error;
563
+ throw error;
564
+ }
510
565
  if (!ran && effect() !== "committed")
511
566
  throw error;
512
567
  const raised = ran ? error : withCommittedEffect(error);
@@ -1,4 +1,10 @@
1
1
  export declare const SERVER_OWNED_ABORT_REASONS: Set<string>;
2
+ /**
3
+ * Finalization skips the terminal write for this reason because the worker's
4
+ * fence is already stale; an abort for lost ownership spelled any other way
5
+ * makes finalization attempt a fenced write that must fail.
6
+ */
7
+ export declare const EXECUTION_LEASE_LOST_ABORT_REASON = "execution_lease_lost";
2
8
  /** A person (or a newer run they started) asked this run to stop. */
3
9
  export declare function isRequestedStopAbortReason(reason: string): boolean;
4
10
  export declare function clientAbortReason(raw: unknown): string;
@@ -3,6 +3,12 @@ export const SERVER_OWNED_ABORT_REASONS = new Set([
3
3
  "run_timeout",
4
4
  "background_automation_hard_timeout",
5
5
  ]);
6
+ /**
7
+ * Finalization skips the terminal write for this reason because the worker's
8
+ * fence is already stale; an abort for lost ownership spelled any other way
9
+ * makes finalization attempt a fenced write that must fail.
10
+ */
11
+ export const EXECUTION_LEASE_LOST_ABORT_REASON = "execution_lease_lost";
6
12
  /** A person (or a newer run they started) asked this run to stop. */
7
13
  export function isRequestedStopAbortReason(reason) {
8
14
  return (reason === "user" ||
@@ -1,5 +1,5 @@
1
1
  import { AsyncLocalStorage } from "node:async_hooks";
2
- import { getDbExec } from "../db/client.js";
2
+ import { getDbExec, getScopedTransactionDbExec, } from "../db/client.js";
3
3
  export class ExecutionFenceError extends Error {
4
4
  code;
5
5
  constructor(code, message) {
@@ -106,6 +106,10 @@ export async function withFencedExecutionWrite(write, scope) {
106
106
  if (!scopedFence) {
107
107
  throw new StaleExecutionFenceError(fence);
108
108
  }
109
+ if (getScopedTransactionDbExec() === client) {
110
+ await lockAndAssertCurrentExecutionFences(client);
111
+ return write(client);
112
+ }
109
113
  if (!client.transaction) {
110
114
  throw new Error("Fenced execution writes require transaction support");
111
115
  }
@@ -384,7 +384,7 @@ export interface ProductionAgentOptions {
384
384
  runSoftTimeoutMs?: number;
385
385
  runNoProgressTimeoutMs?: number;
386
386
  durableBackgroundRuns?: boolean;
387
- onRunStart?: (send: (event: AgentChatEvent) => void, threadId: string, runId: string) => void | Promise<void>;
387
+ onRunStart?: (send: (event: AgentChatEvent) => void, threadId: string, runId: string, turnId: string) => void | Promise<void>;
388
388
  /**
389
389
  * Called when the run's engine, model, and effort resolve, and again before
390
390
  * each model call, because a call can run on a rate-limit fallback model or
@@ -579,18 +579,34 @@ export interface TerminalActionStop {
579
579
  transcriptMessage?: string;
580
580
  errorCode?: string;
581
581
  details?: string;
582
+ /** For `write_tool_outcome_unknown`: the call held back, and why. */
583
+ blockedTool?: string;
584
+ blockedBy?: UnknownOutcomeCause;
582
585
  }
583
586
  /**
584
- * Earlier calls whose outcome is unknown, counted by tool and by the exact
585
- * arguments each was prepared with. Any of them holds back every later write
586
- * of its tool, whatever its arguments; a read only when it is prepared
587
- * exactly as one of them was, which a call recorded without an identity
588
- * never is.
587
+ * Earlier calls whose outcome is unknown, counted by tool, by the exact
588
+ * arguments each was prepared with, by the arguments the model sent, and by
589
+ * tool again for those recorded without an identity. A call prepared exactly
590
+ * as one of them was stops the turn: running it again could apply it twice.
591
+ * So does a write sent with the same arguments, which a default can prepare
592
+ * differently, and any write of a tool with an unidentified one, which it may
593
+ * repeat. A write of the tool with other arguments is declined, and the turn
594
+ * goes on.
589
595
  */
590
596
  interface UnknownOutcomes {
591
597
  tools: Map<string, number>;
592
598
  calls: Map<string, number>;
599
+ inputs: Map<string, number>;
600
+ unidentified: Map<string, number>;
601
+ /** By tool, what made the latest one unknown. */
602
+ causes: Map<string, UnknownOutcomeCause>;
593
603
  }
604
+ /**
605
+ * `rejection`: the call failed and said so, but nothing showed it wrote
606
+ * nothing. `interruption`: its result never came (a timeout, a stop, a
607
+ * continuation boundary or a lost process).
608
+ */
609
+ type UnknownOutcomeCause = "rejection" | "interruption";
594
610
  export declare function actionsToEngineTools(actions: Record<string, ActionEntry>): EngineTool[];
595
611
  export type AgentToolCallExecutionResult = {
596
612
  status: "completed";