@agent-native/core 0.160.1 → 0.161.1

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 (101) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/actions/bigquery.ts +57 -0
  3. package/corpus/templates/analytics/actions/restore-analysis-revision.ts +5 -2
  4. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +5 -2
  5. package/corpus/templates/analytics/app/components/analysis/AnalysisHistoryPanel.tsx +14 -3
  6. package/corpus/templates/analytics/app/components/dashboard/DashboardHistoryPanel.tsx +14 -3
  7. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +3 -0
  8. package/corpus/templates/analytics/app/hooks/use-analysis-revisions.ts +1 -0
  9. package/corpus/templates/analytics/app/hooks/use-dashboard-revisions.ts +16 -1
  10. package/corpus/templates/analytics/app/lib/use-auto-focus-select.ts +19 -0
  11. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +0 -1
  12. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/dashboard-sync.ts +14 -0
  13. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/index.tsx +19 -0
  14. package/corpus/templates/analytics/changelog/2026-08-17-fixed-dashboard-editing-focus-history-recovery-panel-setup-f.md +6 -0
  15. package/corpus/templates/calendar/actions/create-event.ts +7 -3
  16. package/corpus/templates/calendar/actions/manage-event-draft.ts +8 -0
  17. package/corpus/templates/calendar/app/components/calendar/CreateEventDialog.tsx +64 -0
  18. package/corpus/templates/calendar/app/components/calendar/EventDetailPopover.tsx +5 -1
  19. package/corpus/templates/calendar/app/hooks/use-events.ts +1 -0
  20. package/corpus/templates/calendar/changelog/2026-08-17-booking-links-now-respect-each-required-host-s-saved-availab.md +6 -0
  21. package/corpus/templates/calendar/server/lib/booking-host-availability.ts +76 -0
  22. package/corpus/templates/calendar/server/lib/google-calendar.ts +2 -0
  23. package/corpus/templates/calendar/shared/api.ts +1 -1
  24. package/corpus/templates/clips/app/components/player/signed-out-share-actions.tsx +47 -0
  25. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +3 -1
  26. package/corpus/templates/clips/app/routes/share.$shareId.tsx +27 -19
  27. package/corpus/templates/clips/changelog/2026-08-17-shared-clips-sign-in-comment-no-audio.md +6 -0
  28. package/corpus/templates/clips/server/routes/api/public-recording.get.ts +6 -5
  29. package/corpus/templates/content/.agents/skills/document-editing/references/databases.md +13 -0
  30. package/corpus/templates/content/AGENTS.md +2 -0
  31. package/corpus/templates/content/actions/_blocks-field-identity.ts +17 -0
  32. package/corpus/templates/content/actions/_database-block-actions.ts +958 -0
  33. package/corpus/templates/content/actions/_database-row-mutation.ts +7 -7
  34. package/corpus/templates/content/actions/list-content-database-blocks.ts +31 -0
  35. package/corpus/templates/content/actions/mutate-content-database-block.ts +49 -0
  36. package/corpus/templates/content/changelog/2026-08-10-agents-can-safely-insert-update-upsert-delete-and-reorder-on.md +6 -0
  37. package/corpus/templates/content/docs/product/capabilities/content.object.block.md +6 -2
  38. package/corpus/templates/content/docs/product/capabilities/content.object.blocks-field.md +2 -1
  39. package/corpus/templates/content/parity/matrix.md +30 -30
  40. package/corpus/templates/content/parity/matrix.ts +4 -1
  41. package/corpus/templates/content/shared/blocks-field-identity.ts +114 -37
  42. package/corpus/templates/content/shared/database-block-actions.ts +82 -0
  43. package/corpus/templates/content/shared/database-block-mutations.ts +366 -0
  44. package/corpus/templates/content/shared/nfm.ts +3 -2
  45. package/corpus/templates/mail/.agents/skills/email-drafts/SKILL.md +24 -0
  46. package/corpus/templates/mail/actions/get-mail-settings.ts +1 -1
  47. package/corpus/templates/mail/actions/update-mail-settings.ts +7 -3
  48. package/corpus/templates/mail/app/i18n/en-US.ts +3 -1
  49. package/corpus/templates/mail/app/pages/SettingsPage.tsx +63 -0
  50. package/corpus/templates/mail/changelog/2026-08-17-gmail-signatures-now-preserve-images-and-support-paste-or-up.md +6 -0
  51. package/corpus/templates/mail/changelog/2026-08-17-mail-now-updates-durable-drafting-preferences-without-openin.md +6 -0
  52. package/corpus/templates/mail/server/plugins/agent-chat.ts +19 -0
  53. package/corpus/templates/mail/shared/gmail-signature.ts +14 -2
  54. package/corpus/templates/mail/shared/signature.ts +1 -10
  55. package/corpus/templates/slides/actions/generate-slides-ai.ts +2 -0
  56. package/corpus/templates/slides/actions/patch-deck.ts +1 -1
  57. package/corpus/templates/slides/app/components/ThemeToggle.tsx +1 -0
  58. package/corpus/templates/slides/app/components/editor/SlideThumbnailContextMenu.tsx +59 -0
  59. package/corpus/templates/slides/app/global.css +1 -0
  60. package/corpus/templates/slides/app/lib/normalize-slide-padding.ts +40 -11
  61. package/corpus/templates/slides/changelog/2026-08-17-stable-layout-and-slide-editing.md +6 -0
  62. package/corpus/templates/slides/shared/deck-title.ts +12 -4
  63. package/dist/agent/engine/builder-engine.js +6 -1
  64. package/dist/agent/engine/error-detail.d.ts +17 -0
  65. package/dist/agent/engine/error-detail.js +27 -0
  66. package/dist/agent/production-agent.js +23 -5
  67. package/dist/agent/thread-data-builder.js +5 -0
  68. package/dist/agent/tool-approval-migrations.d.ts +1 -0
  69. package/dist/agent/tool-approval-migrations.js +10 -0
  70. package/dist/agent/tool-approval-store.d.ts +12 -0
  71. package/dist/agent/tool-approval-store.js +46 -1
  72. package/dist/agent/types.d.ts +3 -1
  73. package/dist/client/AssistantChat.js +3 -1
  74. package/dist/client/error-format.js +15 -0
  75. package/dist/client/sse-event-processor.js +4 -0
  76. package/dist/collab/struct-routes.d.ts +1 -1
  77. package/dist/localization/core-messages/ar-SA.js +2 -0
  78. package/dist/localization/core-messages/de-DE.js +2 -0
  79. package/dist/localization/core-messages/en-US.d.ts +2 -0
  80. package/dist/localization/core-messages/en-US.js +2 -0
  81. package/dist/localization/core-messages/es-ES.js +2 -0
  82. package/dist/localization/core-messages/fr-FR.js +2 -0
  83. package/dist/localization/core-messages/hi-IN.js +2 -0
  84. package/dist/localization/core-messages/ja-JP.js +2 -0
  85. package/dist/localization/core-messages/ko-KR.js +2 -0
  86. package/dist/localization/core-messages/pt-BR.js +2 -0
  87. package/dist/localization/core-messages/zh-CN.js +2 -0
  88. package/dist/localization/core-messages/zh-TW.js +2 -0
  89. package/dist/localization/core-messages.d.ts +2 -0
  90. package/dist/observability/routes.d.ts +5 -5
  91. package/dist/resources/handlers.d.ts +1 -1
  92. package/dist/scripts/resources/read.js +4 -4
  93. package/dist/scripts/resources/save-memory.js +15 -2
  94. package/dist/scripts/resources/write.js +3 -3
  95. package/dist/secrets/routes.d.ts +9 -9
  96. package/dist/server/agent-chat/script-entries.d.ts +1 -0
  97. package/dist/server/agent-chat/script-entries.js +8 -0
  98. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  99. package/dist/server/transcribe-voice.d.ts +1 -1
  100. package/docs/content/onboarding.mdx +13 -2
  101. package/package.json +3 -3
@@ -35,6 +35,8 @@ export const AGENT_TOOL_APPROVAL_INDEX_SQL = `CREATE INDEX IF NOT EXISTS idx_age
35
35
  ON agent_tool_approvals(owner_email, org_id, thread_id, tool_name, call_id, status)`;
36
36
  export const AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL = `CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_logical
37
37
  ON agent_tool_approvals(owner_email, org_id, thread_id, turn_id, tool_name, approval_key_hash, status)`;
38
+ export const AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL = `CREATE INDEX IF NOT EXISTS idx_agent_tool_approvals_recovery
39
+ ON agent_tool_approvals(owner_email, org_id, thread_id, approval_key_hash, status, turn_id)`;
38
40
  /**
39
41
  * Durable approval grants are created and consumed on request paths, but their
40
42
  * schema belongs to the release migration boundary in production.
@@ -58,4 +60,12 @@ ${AGENT_TOOL_APPROVAL_INDEX_SQL}`,
58
60
  sqlite: AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL,
59
61
  },
60
62
  },
63
+ {
64
+ version: 3,
65
+ name: "agent-tool-approvals-recovery-index",
66
+ sql: {
67
+ postgres: AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL,
68
+ sqlite: AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL,
69
+ },
70
+ },
61
71
  ];
@@ -9,6 +9,18 @@ export interface AgentToolApprovalBinding {
9
9
  expiresAt?: number;
10
10
  }
11
11
  export declare function hashAgentToolApprovalKey(approvalKey: string): string;
12
+ /**
13
+ * Recover the durable scope for an approval continuation when a transport
14
+ * drops the original turn id. A single pending logical turn is safe to
15
+ * recover; multiple turns are deliberately ambiguous and stay unmatched.
16
+ */
17
+ export declare function resolveAgentToolApprovalTurnId(binding: {
18
+ ownerEmail: string;
19
+ orgId?: string | null;
20
+ threadId?: string | null;
21
+ requestedTurnId?: string | null;
22
+ approvalKeys: readonly string[];
23
+ }): Promise<string | null>;
12
24
  export declare function createAgentToolApproval(binding: AgentToolApprovalBinding): Promise<void>;
13
25
  /**
14
26
  * Atomically consume the server-created approval for one logical tool call.
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomUUID } from "node:crypto";
2
2
  import { getDbExec, isPostgres, retryOnDdlRace } from "../db/client.js";
3
3
  import { ensureIndexExists, ensureTableExists } from "../db/ddl-guard.js";
4
- import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, AGENT_TOOL_APPROVAL_TABLE_SQL, } from "./tool-approval-migrations.js";
4
+ import { AGENT_TOOL_APPROVAL_INDEX_SQL, AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL, AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL, AGENT_TOOL_APPROVAL_TABLE_SQL, } from "./tool-approval-migrations.js";
5
5
  const APPROVAL_TTL_MS = 15 * 60_000;
6
6
  const APPROVAL_CLEANUP_AGE_MS = 24 * 60 * 60_000;
7
7
  let initPromise;
@@ -13,12 +13,14 @@ async function ensureAgentToolApprovalTable() {
13
13
  await ensureTableExists("agent_tool_approvals", createSql);
14
14
  await ensureIndexExists("idx_agent_tool_approvals_binding", AGENT_TOOL_APPROVAL_INDEX_SQL);
15
15
  await ensureIndexExists("idx_agent_tool_approvals_logical", AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL);
16
+ await ensureIndexExists("idx_agent_tool_approvals_recovery", AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL);
16
17
  return;
17
18
  }
18
19
  const client = getDbExec();
19
20
  await retryOnDdlRace(() => client.execute(createSql));
20
21
  await retryOnDdlRace(() => client.execute(AGENT_TOOL_APPROVAL_INDEX_SQL));
21
22
  await retryOnDdlRace(() => client.execute(AGENT_TOOL_APPROVAL_LOGICAL_INDEX_SQL));
23
+ await retryOnDdlRace(() => client.execute(AGENT_TOOL_APPROVAL_RECOVERY_INDEX_SQL));
22
24
  })().catch((error) => {
23
25
  initPromise = undefined;
24
26
  throw error;
@@ -29,6 +31,49 @@ async function ensureAgentToolApprovalTable() {
29
31
  export function hashAgentToolApprovalKey(approvalKey) {
30
32
  return createHash("sha256").update(approvalKey).digest("hex");
31
33
  }
34
+ /**
35
+ * Recover the durable scope for an approval continuation when a transport
36
+ * drops the original turn id. A single pending logical turn is safe to
37
+ * recover; multiple turns are deliberately ambiguous and stay unmatched.
38
+ */
39
+ export async function resolveAgentToolApprovalTurnId(binding) {
40
+ const approvalKeys = [...new Set(binding.approvalKeys)].slice(0, 200);
41
+ if (!binding.threadId || approvalKeys.length === 0)
42
+ return null;
43
+ await ensureAgentToolApprovalTable();
44
+ const now = Date.now();
45
+ const hashes = approvalKeys.map(hashAgentToolApprovalKey);
46
+ const placeholders = hashes.map(() => "?").join(", ");
47
+ const result = await getDbExec().execute({
48
+ sql: `SELECT turn_id FROM agent_tool_approvals
49
+ WHERE owner_email = ?
50
+ AND ((org_id IS NULL AND CAST(? AS TEXT) IS NULL) OR org_id = ?)
51
+ AND ((thread_id IS NULL AND CAST(? AS TEXT) IS NULL) OR thread_id = ?)
52
+ AND approval_key_hash IN (${placeholders})
53
+ AND status = 'pending'
54
+ AND expires_at > ?
55
+ AND turn_id IS NOT NULL`,
56
+ args: [
57
+ binding.ownerEmail,
58
+ binding.orgId ?? null,
59
+ binding.orgId ?? null,
60
+ binding.threadId,
61
+ binding.threadId,
62
+ ...hashes,
63
+ now,
64
+ ],
65
+ });
66
+ const turnIds = new Set((result.rows ?? [])
67
+ .map((row) => {
68
+ const value = row.turn_id;
69
+ return typeof value === "string" && value.trim() ? value.trim() : null;
70
+ })
71
+ .filter((turnId) => turnId !== null));
72
+ const requestedTurnId = binding.requestedTurnId?.trim();
73
+ if (requestedTurnId && turnIds.has(requestedTurnId))
74
+ return requestedTurnId;
75
+ return turnIds.size === 1 ? [...turnIds][0] : null;
76
+ }
32
77
  export async function createAgentToolApproval(binding) {
33
78
  await ensureAgentToolApprovalTable();
34
79
  const now = Date.now();
@@ -232,7 +232,9 @@ export interface AgentChatRequest {
232
232
  * `approval_required`; the client re-issues the turn (typically an empty
233
233
  * continuation) with the approved call's key here so the gate lets it run.
234
234
  * Keys not present here keep the action paused. The model never sees or sets
235
- * this — it is supplied by the human's approve affordance.
235
+ * this — it is supplied by the human's approve affordance. Clients should
236
+ * preserve the original turnId; the server can recover one uniquely pending
237
+ * durable grant when a transport drops it, but refuses ambiguous matches.
236
238
  */
237
239
  approvedToolCalls?: string[];
238
240
  }
@@ -4094,7 +4094,9 @@ const AssistantChatInner = forwardRef(function AssistantChatInner({ emptyStateTe
4094
4094
  !authError &&
4095
4095
  showEmptyState &&
4096
4096
  !isRestoring;
4097
- const threadRestoreErrorSurface = threadRestoreError ? (_jsxs("div", { role: "alert", className: "flex max-w-[320px] flex-col items-center gap-3 rounded-lg border border-border bg-muted/30 px-4 py-3 text-center", children: [_jsx(IconRefresh, { className: "h-5 w-5 text-muted-foreground" }), _jsx("p", { className: "text-sm text-muted-foreground", children: t("agentChat.message.restoreRequestFailed") }), _jsx("button", { type: "button", onClick: retryThreadRestore, className: "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", children: t("agentChat.common.retry") })] })) : null;
4097
+ const threadRestoreErrorSurface = threadRestoreError ? (_jsxs("div", { role: "alert", className: "flex max-w-[320px] flex-col items-center gap-3 rounded-lg border border-border bg-muted/30 px-4 py-3 text-center", children: [_jsx(IconRefresh, { className: "h-5 w-5 text-muted-foreground" }), _jsx("p", { className: "text-sm text-muted-foreground", children: threadRestoreError === "not-found"
4098
+ ? t("agentChat.message.threadNotFound")
4099
+ : t("agentChat.message.restoreRequestFailed") }), _jsx("button", { type: "button", onClick: retryThreadRestore, className: "rounded-md border border-border px-3 py-1.5 text-xs font-medium text-foreground hover:bg-accent", children: t("agentChat.common.retry") })] })) : null;
4098
4100
  // Clarifying-question surface: the `ask-question` action writes a
4099
4101
  // GuidedQuestionPayload to application_state under "guided-questions". The
4100
4102
  // hook polls that key, and on submit/skip composes the answer as a normal
@@ -1,4 +1,5 @@
1
1
  import { GATEWAY_UNAVAILABLE_VISITOR_MESSAGE } from "../agent/engine/credential-errors.js";
2
+ import { BUILDER_GATEWAY_INTERNAL_ERROR_CODE } from "../agent/engine/error-detail.js";
2
3
  /**
3
4
  * Append a Builder CTA markdown link to gateway errors that users can fix
4
5
  * outside the app. Used by both
@@ -21,6 +22,13 @@ const OPEN_BUILDER_SPACE_SETTINGS_LABEL = "Open Builder space settings";
21
22
  const START_NEW_CHAT_LABEL = "Start new chat";
22
23
  const UPGRADE_AT_BUILDER_LABEL = "Upgrade at builder.io";
23
24
  const BUILDER_AUTHENTICATION_ERROR = "Builder rejected the connected credentials. Reconnect Builder.io (free tier available) in Settings, then retry.";
25
+ /**
26
+ * The gateway's unhandled-500 envelope is an internal correlation id and an
27
+ * apology: nothing the reader can act on, and nothing that says whether the
28
+ * failure was theirs. Say where it broke and keep the raw sentence in
29
+ * `details`, which is the only place the error id is useful.
30
+ */
31
+ const GATEWAY_INTERNAL_ERROR_MESSAGE = "The model gateway hit an internal error before the agent could answer. Retry in a moment, and quote the error id below if it keeps happening.";
24
32
  function isSafeUpgradeUrl(url) {
25
33
  try {
26
34
  const parsed = new URL(url);
@@ -104,6 +112,10 @@ const KNOWN_CHAT_ERROR_KEYS = new Map([
104
112
  "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.",
105
113
  "agentChat.errorMessages.gatewayNoDetails",
106
114
  ],
115
+ [
116
+ GATEWAY_INTERNAL_ERROR_MESSAGE,
117
+ "agentChat.errorMessages.gatewayInternalError",
118
+ ],
107
119
  [
108
120
  "The agent connection timed out before it could finish. You can continue from the partial work or retry.",
109
121
  "agentChat.errorMessages.inactivityTimeout",
@@ -233,6 +245,9 @@ export function normalizeChatError(errorMessage, errorCode) {
233
245
  details: text,
234
246
  };
235
247
  }
248
+ if (code === BUILDER_GATEWAY_INTERNAL_ERROR_CODE) {
249
+ return { message: GATEWAY_INTERNAL_ERROR_MESSAGE, details: text };
250
+ }
236
251
  if (code === "builder_auth_error") {
237
252
  return {
238
253
  message: BUILDER_AUTHENTICATION_ERROR,
@@ -1,4 +1,5 @@
1
1
  import { LLM_MISSING_CREDENTIALS_ERROR_CODE, LLM_MISSING_CREDENTIALS_MESSAGE, } from "../agent/engine/credential-errors.js";
2
+ import { BUILDER_GATEWAY_INTERNAL_ERROR_CODE } from "../agent/engine/error-detail.js";
2
3
  import { emitChatFirstOpenApp } from "./chat-first.js";
3
4
  import { formatChatErrorText, normalizeChatError } from "./error-format.js";
4
5
  import { humanizeToolLabelText, humanizeToolName, isToolCallActive, runningToolLabel, } from "./tool-display.js";
@@ -529,6 +530,9 @@ function isAutoRecoverableError(ev, errMsg) {
529
530
  code === "http_408" ||
530
531
  code === "http_429" ||
531
532
  code === "http_500" ||
533
+ // The gateway's unhandled-500 envelope delivered in-stream instead of as a
534
+ // status. Recoverable for the same reason `http_500` is.
535
+ code === BUILDER_GATEWAY_INTERNAL_ERROR_CODE ||
532
536
  code === "http_502" ||
533
537
  code === "http_503" ||
534
538
  code === "http_504" ||
@@ -13,8 +13,8 @@
13
13
  * Body: { json: any, fieldName?: string, type?: "map"|"array", requestSource?: string }
14
14
  */
15
15
  export declare const postCollabJson: import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
16
- ok?: undefined;
17
16
  error: string;
17
+ ok?: undefined;
18
18
  } | {
19
19
  error?: undefined;
20
20
  ok: boolean;
@@ -260,6 +260,7 @@ const messages = {
260
260
  "errorMessages.builderAuthentication": "رفض Builder بيانات الاعتماد المتصلة. أعد الاتصال بـ Builder.io من الإعدادات، ثم أعد المحاولة.",
261
261
  "errorMessages.builderModelUnauthorized": "رفض المزوّد الذي يشغّل هذا النموذج الطلب. اختر نموذجًا آخر، ثم أعد المحاولة.",
262
262
  "errorMessages.errorPrefix": "خطأ: {{message}}",
263
+ "errorMessages.gatewayInternalError": "حدث خطأ داخلي في بوابة النموذج قبل أن يتمكن الوكيل من الإجابة. أعد المحاولة بعد قليل، وإذا تكرر الأمر فأرفق معرّف الخطأ الظاهر أدناه.",
263
264
  "errorMessages.gatewayNoDetails": "لم تُرجع بوابة النموذج أي تفاصيل عن الخطأ وتعذّر على المحادثة الاسترداد. انتظر قليلًا ثم أعد المحاولة، أو ابدأ محادثة جديدة إذا استمرت المشكلة.",
264
265
  "errorMessages.inactivityTimeout": "انتهت مهلة اتصال الوكيل قبل أن يتمكن من الإكمال. يمكنك المتابعة من العمل الجزئي أو إعادة المحاولة.",
265
266
  "errorMessages.invalidToolSchema": "كان مخطط إحدى الأدوات غير صالح، لذلك رفض النموذج الطلب قبل بدئه. يمكن تخطي الأداة غير الصالحة وإعادة محاولة الطلب.",
@@ -324,6 +325,7 @@ const messages = {
324
325
  "message.restoreFailed": "فشلت الاستعادة ({{status}}).",
325
326
  "message.restoreQuestion": "هل تريد الاستعادة إلى هنا؟",
326
327
  "message.restoreRequestFailed": "فشل طلب الاستعادة.",
328
+ "message.threadNotFound": "لم تعد سلسلة الدردشة هذه متاحة. ابدأ دردشة جديدة أو أعد المحاولة إذا كان ذلك غير متوقع.",
327
329
  "message.restoring": "جارٍ الاستعادة...",
328
330
  "message.revertHere": "الرجوع إلى هنا",
329
331
  "message.sentAt": "أُرسلت في {{time}}",
@@ -94,6 +94,7 @@ const messages = {
94
94
  "message.restoreFailed": "Wiederherstellung fehlgeschlagen ({{status}}).",
95
95
  "message.restoreQuestion": "Bis hierher wiederherstellen?",
96
96
  "message.restoreRequestFailed": "Wiederherstellungsanfrage fehlgeschlagen.",
97
+ "message.threadNotFound": "Dieser Chat-Thread ist nicht mehr verfügbar. Starte einen neuen Chat oder versuche es erneut, falls das unerwartet war.",
97
98
  "message.restoring": "Wird wiederhergestellt...",
98
99
  "message.revertHere": "Bis hierher zurücksetzen",
99
100
  "message.sentAt": "Gesendet {{time}}",
@@ -388,6 +389,7 @@ const messages = {
388
389
  "errorMessages.builderAuthentication": "Builder hat die verbundenen Anmeldedaten abgelehnt. Verbinde Builder.io in den Einstellungen erneut und versuche es dann noch einmal.",
389
390
  "errorMessages.builderModelUnauthorized": "Der Anbieter hinter diesem Modell hat die Anfrage abgelehnt. Wähle ein anderes Modell und versuche es erneut.",
390
391
  "errorMessages.errorPrefix": "Fehler: {{message}}",
392
+ "errorMessages.gatewayInternalError": "Das Modell-Gateway hat einen internen Fehler ausgelöst, bevor der Agent antworten konnte. Versuchen Sie es in einem Moment erneut und geben Sie die untenstehende Fehler-ID an, wenn es weiterhin auftritt.",
391
393
  "errorMessages.gatewayNoDetails": "Das Modell-Gateway hat keine Fehlerdetails zurückgegeben und der Chat konnte nicht fortgesetzt werden. Warte einen Moment und versuche es erneut. Falls das Problem bestehen bleibt, starte einen neuen Chat.",
392
394
  "errorMessages.inactivityTimeout": "Die Verbindung zum Agenten wurde wegen Zeitüberschreitung beendet, bevor er fertig war. Du kannst mit dem Teilergebnis fortfahren oder es erneut versuchen.",
393
395
  "errorMessages.invalidToolSchema": "Ein Tool-Schema war ungültig. Deshalb hat das Modell die Anfrage abgelehnt, bevor sie gestartet wurde. Das ungültige Tool kann übersprungen und die Anfrage erneut gesendet werden.",
@@ -252,6 +252,7 @@ declare const messages: {
252
252
  readonly "errorMessages.builderAuthentication": "Builder rejected the connected credentials. Reconnect Builder.io in Settings, then retry.";
253
253
  readonly "errorMessages.builderModelUnauthorized": "The provider behind this model rejected the request. Pick a different model, then retry.";
254
254
  readonly "errorMessages.errorPrefix": "Error: {{message}}";
255
+ readonly "errorMessages.gatewayInternalError": "The model gateway hit an internal error before the agent could answer. Retry in a moment, and quote the error id below if it keeps happening.";
255
256
  readonly "errorMessages.gatewayNoDetails": "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.";
256
257
  readonly "errorMessages.inactivityTimeout": "The agent connection timed out before it could finish. You can continue from the partial work or retry.";
257
258
  readonly "errorMessages.invalidToolSchema": "A tool schema was invalid, so the model rejected the request before it started. The invalid tool can be skipped and the request retried.";
@@ -312,6 +313,7 @@ declare const messages: {
312
313
  readonly "message.restoreFailed": "Restore failed ({{status}}).";
313
314
  readonly "message.restoreQuestion": "Restore to here?";
314
315
  readonly "message.restoreRequestFailed": "Restore request failed.";
316
+ readonly "message.threadNotFound": "This chat thread is no longer available. Start a new chat or retry if this was unexpected.";
315
317
  readonly "message.restoring": "Restoring...";
316
318
  readonly "message.revertHere": "Revert to here";
317
319
  readonly "message.sentAt": "Sent {{time}}";
@@ -252,6 +252,7 @@ const messages = {
252
252
  "errorMessages.builderAuthentication": "Builder rejected the connected credentials. Reconnect Builder.io in Settings, then retry.",
253
253
  "errorMessages.builderModelUnauthorized": "The provider behind this model rejected the request. Pick a different model, then retry.",
254
254
  "errorMessages.errorPrefix": "Error: {{message}}",
255
+ "errorMessages.gatewayInternalError": "The model gateway hit an internal error before the agent could answer. Retry in a moment, and quote the error id below if it keeps happening.",
255
256
  "errorMessages.gatewayNoDetails": "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.",
256
257
  "errorMessages.inactivityTimeout": "The agent connection timed out before it could finish. You can continue from the partial work or retry.",
257
258
  "errorMessages.invalidToolSchema": "A tool schema was invalid, so the model rejected the request before it started. The invalid tool can be skipped and the request retried.",
@@ -312,6 +313,7 @@ const messages = {
312
313
  "message.restoreFailed": "Restore failed ({{status}}).",
313
314
  "message.restoreQuestion": "Restore to here?",
314
315
  "message.restoreRequestFailed": "Restore request failed.",
316
+ "message.threadNotFound": "This chat thread is no longer available. Start a new chat or retry if this was unexpected.",
315
317
  "message.restoring": "Restoring...",
316
318
  "message.revertHere": "Revert to here",
317
319
  "message.sentAt": "Sent {{time}}",
@@ -94,6 +94,7 @@ const messages = {
94
94
  "message.restoreFailed": "Error al restaurar ({{status}}).",
95
95
  "message.restoreQuestion": "¿Restaurar hasta aquí?",
96
96
  "message.restoreRequestFailed": "Error en la solicitud de restauración.",
97
+ "message.threadNotFound": "Este hilo de chat ya no está disponible. Inicia un chat nuevo o inténtalo de nuevo si esto no era esperado.",
97
98
  "message.restoring": "Restaurando...",
98
99
  "message.revertHere": "Revertir hasta aquí",
99
100
  "message.sentAt": "Enviado a las {{time}}",
@@ -395,6 +396,7 @@ const messages = {
395
396
  "errorMessages.builderAuthentication": "Builder rechazó las credenciales conectadas. Vuelve a conectar Builder.io en Ajustes e inténtalo de nuevo.",
396
397
  "errorMessages.builderModelUnauthorized": "El proveedor de este modelo rechazó la solicitud. Elige otro modelo y vuelve a intentarlo.",
397
398
  "errorMessages.errorPrefix": "Error: {{message}}",
399
+ "errorMessages.gatewayInternalError": "La pasarela del modelo tuvo un error interno antes de que el agente pudiera responder. Vuelve a intentarlo en un momento e indica el id de error de abajo si sigue ocurriendo.",
398
400
  "errorMessages.gatewayNoDetails": "La pasarela del modelo no devolvió detalles del error y el chat no pudo recuperarse. Espera un momento y vuelve a intentarlo. Si el problema continúa, inicia un chat nuevo.",
399
401
  "errorMessages.inactivityTimeout": "La conexión del agente expiró antes de que pudiera finalizar. Puedes continuar desde el trabajo parcial o volver a intentarlo.",
400
402
  "errorMessages.invalidToolSchema": "El esquema de una herramienta no era válido, así que el modelo rechazó la solicitud antes de iniciarla. Puedes omitir la herramienta no válida y volver a intentarlo.",
@@ -94,6 +94,7 @@ const messages = {
94
94
  "message.restoreFailed": "Échec de la restauration ({{status}}).",
95
95
  "message.restoreQuestion": "Restaurer jusqu’ici ?",
96
96
  "message.restoreRequestFailed": "Échec de la demande de restauration.",
97
+ "message.threadNotFound": "Ce fil de discussion n’est plus disponible. Démarrez une nouvelle discussion ou réessayez si cela est inattendu.",
97
98
  "message.restoring": "Restauration...",
98
99
  "message.revertHere": "Revenir jusqu’ici",
99
100
  "message.sentAt": "Envoyé à {{time}}",
@@ -395,6 +396,7 @@ const messages = {
395
396
  "errorMessages.builderAuthentication": "Builder a rejeté les identifiants connectés. Reconnectez Builder.io dans les paramètres, puis réessayez.",
396
397
  "errorMessages.builderModelUnauthorized": "Le fournisseur de ce modèle a rejeté la demande. Choisissez un autre modèle, puis réessayez.",
397
398
  "errorMessages.errorPrefix": "Erreur : {{message}}",
399
+ "errorMessages.gatewayInternalError": "La passerelle du modèle a rencontré une erreur interne avant que l'agent puisse répondre. Réessayez dans un instant et indiquez l'identifiant d'erreur ci-dessous si cela persiste.",
398
400
  "errorMessages.gatewayNoDetails": "La passerelle du modèle n’a fourni aucun détail sur l’erreur et la discussion n’a pas pu reprendre. Patientez un instant et réessayez. Si le problème persiste, démarrez une nouvelle discussion.",
399
401
  "errorMessages.inactivityTimeout": "La connexion à l’agent a expiré avant la fin. Vous pouvez poursuivre à partir du travail partiel ou réessayer.",
400
402
  "errorMessages.invalidToolSchema": "Le schéma d’un outil n’était pas valide. Le modèle a donc rejeté la demande avant son démarrage. Vous pouvez ignorer cet outil et réessayer.",
@@ -252,6 +252,7 @@ const messages = {
252
252
  "errorMessages.builderAuthentication": "Builder ने कनेक्ट किए गए क्रेडेंशियल अस्वीकार कर दिए। सेटिंग्स में Builder.io को दोबारा कनेक्ट करें, फिर से प्रयास करें।",
253
253
  "errorMessages.builderModelUnauthorized": "इस मॉडल के पीछे मौजूद प्रदाता ने अनुरोध अस्वीकार कर दिया। कोई दूसरा मॉडल चुनें, फिर से प्रयास करें।",
254
254
  "errorMessages.errorPrefix": "त्रुटि: {{message}}",
255
+ "errorMessages.gatewayInternalError": "एजेंट के उत्तर देने से पहले मॉडल गेटवे में एक आंतरिक त्रुटि आई। कुछ देर में फिर कोशिश करें, और बार-बार होने पर नीचे दिया गया error id बताएं।",
255
256
  "errorMessages.gatewayNoDetails": "मॉडल गेटवे ने त्रुटि का कोई विवरण नहीं दिया और चैट रिकवर नहीं हो सकी। कुछ देर रुककर फिर से प्रयास करें या समस्या बनी रहने पर नई चैट शुरू करें।",
256
257
  "errorMessages.inactivityTimeout": "एजेंट का कनेक्शन काम पूरा होने से पहले समय सीमा पर पहुँच गया। आप आंशिक काम से जारी रख सकते हैं या फिर से प्रयास कर सकते हैं।",
257
258
  "errorMessages.invalidToolSchema": "एक टूल स्कीमा अमान्य था, इसलिए मॉडल ने अनुरोध शुरू होने से पहले ही अस्वीकार कर दिया। अमान्य टूल को छोड़कर अनुरोध दोबारा किया जा सकता है।",
@@ -312,6 +313,7 @@ const messages = {
312
313
  "message.restoreFailed": "पुनर्स्थापना विफल रही ({{status}})।",
313
314
  "message.restoreQuestion": "यहाँ तक पुनर्स्थापित करें?",
314
315
  "message.restoreRequestFailed": "पुनर्स्थापना अनुरोध विफल रहा।",
316
+ "message.threadNotFound": "यह चैट थ्रेड अब उपलब्ध नहीं है। नई चैट शुरू करें या यदि यह अप्रत्याशित है तो फिर कोशिश करें।",
315
317
  "message.restoring": "पुनर्स्थापित किया जा रहा है...",
316
318
  "message.revertHere": "यहाँ तक वापस जाएँ",
317
319
  "message.sentAt": "{{time}} पर भेजा गया",
@@ -250,6 +250,7 @@ const messages = {
250
250
  "errorMessages.builderAuthentication": "Builder が接続済みの認証情報を拒否しました。設定で Builder.io に再接続してから再試行してください。",
251
251
  "errorMessages.builderModelUnauthorized": "このモデルのプロバイダーがリクエストを拒否しました。別のモデルを選択して再試行してください。",
252
252
  "errorMessages.errorPrefix": "エラー:{{message}}",
253
+ "errorMessages.gatewayInternalError": "エージェントが応答する前にモデルゲートウェイで内部エラーが発生しました。少し待ってから再試行し、繰り返す場合は下のエラー ID を伝えてください。",
253
254
  "errorMessages.gatewayNoDetails": "モデルゲートウェイからエラーの詳細が返されず、チャットを復旧できませんでした。少し待ってから再試行し、繰り返し発生する場合は新しいチャットを開始してください。",
254
255
  "errorMessages.inactivityTimeout": "エージェントとの接続が完了前にタイムアウトしました。途中までの作業から続行するか、再試行できます。",
255
256
  "errorMessages.invalidToolSchema": "ツールのスキーマが無効だったため、モデルは開始前にリクエストを拒否しました。無効なツールをスキップして再試行できます。",
@@ -309,6 +310,7 @@ const messages = {
309
310
  "message.restoreFailed": "復元に失敗しました({{status}})。",
310
311
  "message.restoreQuestion": "ここまで復元しますか?",
311
312
  "message.restoreRequestFailed": "復元リクエストに失敗しました。",
313
+ "message.threadNotFound": "このチャットスレッドは利用できなくなりました。新しいチャットを開始するか、想定外の場合は再試行してください。",
312
314
  "message.restoring": "復元中...",
313
315
  "message.revertHere": "ここまで戻す",
314
316
  "message.sentAt": "{{time}} に送信",
@@ -250,6 +250,7 @@ const messages = {
250
250
  "errorMessages.builderAuthentication": "Builder가 연결된 자격 증명을 거부했습니다. 설정에서 Builder.io를 다시 연결한 후 다시 시도하세요.",
251
251
  "errorMessages.builderModelUnauthorized": "이 모델의 제공업체가 요청을 거부했습니다. 다른 모델을 선택한 후 다시 시도하세요.",
252
252
  "errorMessages.errorPrefix": "오류: {{message}}",
253
+ "errorMessages.gatewayInternalError": "에이전트가 답변하기 전에 모델 게이트웨이에서 내부 오류가 발생했습니다. 잠시 후 다시 시도하고, 계속 발생하면 아래 오류 ID를 알려 주세요.",
253
254
  "errorMessages.gatewayNoDetails": "모델 게이트웨이가 오류 세부 정보를 반환하지 않아 채팅을 복구할 수 없습니다. 잠시 후 다시 시도하고, 문제가 계속되면 새 채팅을 시작하세요.",
254
255
  "errorMessages.inactivityTimeout": "에이전트 연결이 완료 전에 시간 초과되었습니다. 부분적으로 완료된 작업에서 계속하거나 다시 시도할 수 있습니다.",
255
256
  "errorMessages.invalidToolSchema": "도구 스키마가 올바르지 않아 모델이 요청 시작 전에 거부했습니다. 올바르지 않은 도구를 건너뛰고 요청을 다시 시도할 수 있습니다.",
@@ -309,6 +310,7 @@ const messages = {
309
310
  "message.restoreFailed": "복원 실패({{status}}).",
310
311
  "message.restoreQuestion": "여기로 복원하시겠습니까?",
311
312
  "message.restoreRequestFailed": "복원 요청에 실패했습니다.",
313
+ "message.threadNotFound": "이 채팅 스레드는 더 이상 사용할 수 없습니다. 새 채팅을 시작하거나 예상치 못한 문제라면 다시 시도하세요.",
312
314
  "message.restoring": "복원 중...",
313
315
  "message.revertHere": "여기로 되돌리기",
314
316
  "message.sentAt": "{{time}}에 전송",
@@ -94,6 +94,7 @@ const messages = {
94
94
  "message.restoreFailed": "Falha ao restaurar ({{status}}).",
95
95
  "message.restoreQuestion": "Restaurar até aqui?",
96
96
  "message.restoreRequestFailed": "Falha na solicitação de restauração.",
97
+ "message.threadNotFound": "Esta conversa não está mais disponível. Inicie uma nova conversa ou tente novamente se isso for inesperado.",
97
98
  "message.restoring": "Restaurando...",
98
99
  "message.revertHere": "Reverter até aqui",
99
100
  "message.sentAt": "Enviado às {{time}}",
@@ -395,6 +396,7 @@ const messages = {
395
396
  "errorMessages.builderAuthentication": "O Builder rejeitou as credenciais conectadas. Reconecte Builder.io em Configurações e tente novamente.",
396
397
  "errorMessages.builderModelUnauthorized": "O provedor por trás deste modelo rejeitou a solicitação. Escolha um modelo diferente e tente novamente.",
397
398
  "errorMessages.errorPrefix": "Erro: {{message}}",
399
+ "errorMessages.gatewayInternalError": "O gateway do modelo teve um erro interno antes de o agente poder responder. Tente novamente em instantes e informe o id de erro abaixo se continuar acontecendo.",
398
400
  "errorMessages.gatewayNoDetails": "O gateway do modelo não retornou detalhes do erro, e o chat não pôde ser recuperado. Aguarde um momento e tente novamente. Se o problema persistir, inicie um novo chat.",
399
401
  "errorMessages.inactivityTimeout": "A conexão com o agente expirou antes da conclusão. Você pode continuar a partir do trabalho parcial ou tentar novamente.",
400
402
  "errorMessages.invalidToolSchema": "O esquema de uma ferramenta era inválido, então o modelo rejeitou a solicitação antes de iniciá-la. Você pode ignorar a ferramenta inválida e tentar novamente.",
@@ -250,6 +250,7 @@ const messages = {
250
250
  "errorMessages.builderAuthentication": "Builder 拒绝了已连接的凭据。请在设置中重新连接 Builder.io,然后重试。",
251
251
  "errorMessages.builderModelUnauthorized": "此模型背后的提供商拒绝了请求。请选择其他模型后重试。",
252
252
  "errorMessages.errorPrefix": "错误:{{message}}",
253
+ "errorMessages.gatewayInternalError": "模型网关在智能体作答前发生内部错误。请稍后重试;如果持续出现,请提供下方的错误 ID。",
253
254
  "errorMessages.gatewayNoDetails": "模型网关未返回错误详情,聊天无法恢复。请稍等片刻后重试;如果问题持续出现,请开始新聊天。",
254
255
  "errorMessages.inactivityTimeout": "智能体连接在完成前超时。您可以从已完成的部分继续,也可以重试。",
255
256
  "errorMessages.invalidToolSchema": "工具架构无效,因此模型在请求开始前拒绝了该请求。可以跳过无效工具并重试请求。",
@@ -309,6 +310,7 @@ const messages = {
309
310
  "message.restoreFailed": "恢复失败({{status}})。",
310
311
  "message.restoreQuestion": "恢复到此处?",
311
312
  "message.restoreRequestFailed": "恢复请求失败。",
313
+ "message.threadNotFound": "此聊天线程已不可用。请开始新聊天;如果这是意外情况,也可以重试。",
312
314
  "message.restoring": "正在恢复...",
313
315
  "message.revertHere": "还原到此处",
314
316
  "message.sentAt": "发送于 {{time}}",
@@ -250,6 +250,7 @@ const messages = {
250
250
  "errorMessages.builderAuthentication": "Builder 拒絕了已連線的憑證。請在設定中重新連線至 Builder.io,然後重試。",
251
251
  "errorMessages.builderModelUnauthorized": "這個模型背後的供應商拒絕了要求。請選擇其他模型後重試。",
252
252
  "errorMessages.errorPrefix": "錯誤:{{message}}",
253
+ "errorMessages.gatewayInternalError": "模型閘道在代理回答前發生內部錯誤。請稍後重試;若持續發生,請提供下方的錯誤 ID。",
253
254
  "errorMessages.gatewayNoDetails": "模型閘道未傳回錯誤詳細資訊,聊天無法復原。請稍候再試;如果問題持續發生,請開始新聊天。",
254
255
  "errorMessages.inactivityTimeout": "代理連線在完成前逾時。您可以從已完成的部分繼續,也可以重試。",
255
256
  "errorMessages.invalidToolSchema": "工具結構描述無效,因此模型在要求開始前便拒絕了要求。您可以略過無效工具並重試要求。",
@@ -309,6 +310,7 @@ const messages = {
309
310
  "message.restoreFailed": "還原失敗({{status}})。",
310
311
  "message.restoreQuestion": "要還原到這裡嗎?",
311
312
  "message.restoreRequestFailed": "還原要求失敗。",
313
+ "message.threadNotFound": "此聊天串已無法使用。請開始新的聊天;如果這是意外情況,也可以重試。",
312
314
  "message.restoring": "正在還原...",
313
315
  "message.revertHere": "還原到這裡",
314
316
  "message.sentAt": "傳送於 {{time}}",
@@ -254,6 +254,7 @@ export declare const englishAgentChatMessages: {
254
254
  readonly "errorMessages.builderAuthentication": "Builder rejected the connected credentials. Reconnect Builder.io in Settings, then retry.";
255
255
  readonly "errorMessages.builderModelUnauthorized": "The provider behind this model rejected the request. Pick a different model, then retry.";
256
256
  readonly "errorMessages.errorPrefix": "Error: {{message}}";
257
+ readonly "errorMessages.gatewayInternalError": "The model gateway hit an internal error before the agent could answer. Retry in a moment, and quote the error id below if it keeps happening.";
257
258
  readonly "errorMessages.gatewayNoDetails": "The model gateway returned no error details and the chat couldn't recover. Wait a moment and retry, or start a new chat if it keeps happening.";
258
259
  readonly "errorMessages.inactivityTimeout": "The agent connection timed out before it could finish. You can continue from the partial work or retry.";
259
260
  readonly "errorMessages.invalidToolSchema": "A tool schema was invalid, so the model rejected the request before it started. The invalid tool can be skipped and the request retried.";
@@ -314,6 +315,7 @@ export declare const englishAgentChatMessages: {
314
315
  readonly "message.restoreFailed": "Restore failed ({{status}}).";
315
316
  readonly "message.restoreQuestion": "Restore to here?";
316
317
  readonly "message.restoreRequestFailed": "Restore request failed.";
318
+ readonly "message.threadNotFound": "This chat thread is no longer available. Start a new chat or retry if this was unexpected.";
317
319
  readonly "message.restoring": "Restoring...";
318
320
  readonly "message.revertHere": "Revert to here";
319
321
  readonly "message.sentAt": "Sent {{time}}";
@@ -41,27 +41,27 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
41
41
  thumbsUpRate: number;
42
42
  avgEvalScore: number;
43
43
  } | {
44
- error?: undefined;
45
- ok?: undefined;
46
44
  summary: import("./types.js").TraceSummary;
47
45
  spans: import("./types.js").TraceSpan[];
48
46
  id?: undefined;
49
- } | {
50
47
  error?: undefined;
51
48
  ok?: undefined;
49
+ } | {
52
50
  summary?: undefined;
53
51
  spans?: undefined;
54
52
  id: string;
55
- } | {
53
+ error?: undefined;
56
54
  ok?: undefined;
55
+ } | {
57
56
  summary?: undefined;
58
57
  spans?: undefined;
59
58
  id?: undefined;
60
59
  error: any;
60
+ ok?: undefined;
61
61
  } | {
62
- error?: undefined;
63
62
  summary?: undefined;
64
63
  spans?: undefined;
65
64
  id?: undefined;
66
65
  ok: boolean;
66
+ error?: undefined;
67
67
  }>>;
@@ -48,8 +48,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
48
48
  }>;
49
49
  /** DELETE /_agent-native/resources/:id — delete a resource */
50
50
  export declare function handleDeleteResource(event: any): Promise<{
51
- error: string;
52
51
  ok?: undefined;
52
+ error: string;
53
53
  } | {
54
54
  error?: undefined;
55
55
  ok: boolean;
@@ -6,8 +6,8 @@
6
6
  * Usage:
7
7
  * pnpm action resource-read --path <path> [--scope personal|shared|workspace]
8
8
  */
9
- import { resourceGetByPath, ensurePersonalDefaults, SHARED_OWNER, WORKSPACE_OWNER, } from "../../resources/store.js";
10
- import { getAmbientUserEmail, getRequestUserEmail, } from "../../server/request-context.js";
9
+ import { resourceGetByPath, ensurePersonalDefaults, sharedResourceOwner, WORKSPACE_OWNER, } from "../../resources/store.js";
10
+ import { getAmbientUserEmail, getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
11
11
  import { parseArgs, fail } from "../utils.js";
12
12
  export default async function resourceReadScript(args) {
13
13
  const parsed = parseArgs(args);
@@ -44,7 +44,7 @@ Options:
44
44
  return;
45
45
  }
46
46
  if (scope === "shared") {
47
- const resource = await resourceGetByPath(SHARED_OWNER, resourcePath);
47
+ const resource = await resourceGetByPath(sharedResourceOwner(getRequestOrgId()), resourcePath);
48
48
  if (!resource) {
49
49
  console.log(`Resource not found: ${resourcePath} (scope: shared). You can create it with resource-write.`);
50
50
  return;
@@ -63,7 +63,7 @@ Options:
63
63
  console.log(`Resource not found: ${resourcePath} (scope: personal). You can create it with resource-write.`);
64
64
  return;
65
65
  }
66
- const shared = await resourceGetByPath(SHARED_OWNER, resourcePath);
66
+ const shared = await resourceGetByPath(sharedResourceOwner(getRequestOrgId()), resourcePath);
67
67
  if (shared) {
68
68
  process.stdout.write(shared.content);
69
69
  return;
@@ -6,7 +6,7 @@
6
6
  * and maintains a `memory/MEMORY.md` index.
7
7
  */
8
8
  import { resourcePut, resourceGetByPath } from "../../resources/store.js";
9
- import { getAmbientUserEmail, getRequestUserEmail, } from "../../server/request-context.js";
9
+ import { getAmbientUserEmail, getRequestRunContext, getRequestUserEmail, } from "../../server/request-context.js";
10
10
  import { parseArgs, fail } from "../utils.js";
11
11
  const VALID_TYPES = ["user", "feedback", "project", "reference"];
12
12
  const EMPTY_INDEX = `# Memory Index
@@ -26,7 +26,9 @@ export default async function saveMemoryScript(args) {
26
26
  const content = parsed.content;
27
27
  if (!content)
28
28
  fail("--content is required");
29
- const owner = getRequestUserEmail() ?? getAmbientUserEmail();
29
+ const owner = getRequestRunContext()?.owner ??
30
+ getRequestUserEmail() ??
31
+ getAmbientUserEmail();
30
32
  if (!owner) {
31
33
  fail("save-memory requires an authenticated user (request context or AGENT_USER_EMAIL env var).");
32
34
  }
@@ -76,5 +78,16 @@ ${content}`;
76
78
  console.log(`Warning: Memory index has ${lineCount} lines (recommended: <200). Consider consolidating or removing old memories.`);
77
79
  }
78
80
  await resourcePut(owner, indexPath, updatedIndex, "text/markdown");
81
+ // Do not report success until both writes are visible through the resource
82
+ // read path. This catches storage or ownership mismatches that would
83
+ // otherwise leave the caller believing a memory was saved.
84
+ const persistedMemory = await resourceGetByPath(owner, memoryPath);
85
+ if (persistedMemory?.content !== fileContent) {
86
+ fail(`save-memory could not verify persisted memory "${name}".`);
87
+ }
88
+ const persistedIndex = await resourceGetByPath(owner, indexPath);
89
+ if (persistedIndex?.content !== updatedIndex) {
90
+ fail("save-memory could not verify persisted memory index.");
91
+ }
79
92
  console.log(`Saved memory "${name}" (${type}): ${description}`);
80
93
  }
@@ -6,8 +6,8 @@
6
6
  * Usage:
7
7
  * pnpm action resource-write --path <path> --content <content> [--scope personal|shared] [--mime <mime-type>] [--visibility workspace|agent_scratch]
8
8
  */
9
- import { canWriteLocalWorkspaceResourcePath, resourcePut, SHARED_OWNER, WORKSPACE_OWNER, } from "../../resources/store.js";
10
- import { getAmbientUserEmail, getRequestUserEmail, } from "../../server/request-context.js";
9
+ import { canWriteLocalWorkspaceResourcePath, resourcePut, sharedResourceOwner, WORKSPACE_OWNER, } from "../../resources/store.js";
10
+ import { getAmbientUserEmail, getRequestOrgId, getRequestUserEmail, } from "../../server/request-context.js";
11
11
  import { parseArgs, fail } from "../utils.js";
12
12
  const EXTENSION_MIME_MAP = {
13
13
  ".md": "text/markdown",
@@ -101,7 +101,7 @@ Options:
101
101
  const expiresAt = parseOptionalNumber(parsed["expires-at"] ?? parsed.expiresAt, "--expires-at");
102
102
  let owner;
103
103
  if (scope === "shared") {
104
- owner = SHARED_OWNER;
104
+ owner = sharedResourceOwner(getRequestOrgId());
105
105
  }
106
106
  else if (scope === "workspace") {
107
107
  owner = WORKSPACE_OWNER;