@agent-native/core 0.77.8 → 0.77.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/corpus/README.md +1 -1
- package/corpus/core/CHANGELOG.md +29 -0
- package/corpus/core/package.json +1 -1
- package/corpus/core/src/a2a/task-store.ts +25 -3
- package/corpus/core/src/agent/harness/store.ts +89 -55
- package/corpus/core/src/agent/observational-memory/store.ts +40 -14
- package/corpus/core/src/agent/run-store.ts +116 -59
- package/corpus/core/src/application-state/store.ts +36 -2
- package/corpus/core/src/audit/store.ts +37 -6
- package/corpus/core/src/browser-sessions/store.ts +31 -12
- package/corpus/core/src/chat-threads/store.ts +67 -3
- package/corpus/core/src/checkpoints/store.ts +14 -3
- package/corpus/core/src/cli/create.ts +9 -0
- package/corpus/core/src/collab/storage.ts +20 -2
- package/corpus/core/src/db/ddl-guard.ts +112 -0
- package/corpus/core/src/extensions/store.ts +76 -3
- package/corpus/core/src/integrations/a2a-continuations-store.ts +69 -26
- package/corpus/core/src/integrations/config-store.ts +19 -18
- package/corpus/core/src/integrations/pending-tasks-store.ts +40 -16
- package/corpus/core/src/integrations/remote-commands-store.ts +37 -23
- package/corpus/core/src/integrations/remote-devices-store.ts +64 -20
- package/corpus/core/src/integrations/remote-push-store.ts +75 -35
- package/corpus/core/src/integrations/remote-run-events-store.ts +38 -12
- package/corpus/core/src/integrations/thread-mapping-store.ts +11 -2
- package/corpus/core/src/mcp/connect-store.ts +53 -16
- package/corpus/core/src/mcp/oauth-store.ts +32 -7
- package/corpus/core/src/notifications/store.ts +20 -4
- package/corpus/core/src/oauth-tokens/store.ts +45 -2
- package/corpus/core/src/observability/store.ts +154 -47
- package/corpus/core/src/progress/store.ts +36 -21
- package/corpus/core/src/provider-api/corpus-jobs-store.ts +25 -5
- package/corpus/core/src/provider-api/custom-registry.ts +15 -4
- package/corpus/core/src/provider-api/quota-governor.ts +15 -3
- package/corpus/core/src/provider-api/staged-datasets-store.ts +22 -5
- package/corpus/core/src/resources/store.ts +66 -31
- package/corpus/core/src/secrets/storage.ts +18 -22
- package/corpus/core/src/server/agent-teams-run-queue.ts +22 -10
- package/corpus/core/src/server/auth.ts +22 -4
- package/corpus/core/src/server/better-auth-instance.ts +49 -15
- package/corpus/core/src/server/embed-session.ts +19 -4
- package/corpus/core/src/server/identity-sso-store.ts +40 -11
- package/corpus/core/src/server/recap-image-store.ts +28 -9
- package/corpus/core/src/settings/store.ts +14 -19
- package/corpus/core/src/usage/store.ts +51 -16
- package/corpus/core/src/workspace-connections/store.ts +200 -22
- package/corpus/templates/calendar/changelog/2026-06-25-booking-link-previews-now-show-the-content-directly-on-the-g.md +6 -0
- package/corpus/templates/calendar/server/lib/booking-og-image.ts +0 -2
- package/corpus/templates/forms/changelog/2026-06-25-form-previews-now-show-the-content-directly-on-the-grid-back.md +6 -0
- package/corpus/templates/forms/server/lib/form-og-image.ts +0 -2
- package/corpus/templates/plan/app/global.css +6 -11
- package/corpus/templates/plan/app/pages/PlansPage.tsx +12 -10
- package/corpus/templates/plan/changelog/2026-06-25-plan-access-request-pages-stay-visible-during-background-ref.md +6 -0
- package/corpus/templates/plan/changelog/2026-06-25-plan-documents-keep-their-full-reading-width-below-1200px-an.md +6 -0
- package/dist/a2a/task-store.d.ts.map +1 -1
- package/dist/a2a/task-store.js +19 -3
- package/dist/a2a/task-store.js.map +1 -1
- package/dist/agent/harness/store.d.ts.map +1 -1
- package/dist/agent/harness/store.js +63 -34
- package/dist/agent/harness/store.js.map +1 -1
- package/dist/agent/observational-memory/store.d.ts.map +1 -1
- package/dist/agent/observational-memory/store.js +30 -8
- package/dist/agent/observational-memory/store.js.map +1 -1
- package/dist/agent/run-store.d.ts.map +1 -1
- package/dist/agent/run-store.js +103 -46
- package/dist/agent/run-store.js.map +1 -1
- package/dist/application-state/store.d.ts.map +1 -1
- package/dist/application-state/store.js +28 -2
- package/dist/application-state/store.js.map +1 -1
- package/dist/audit/store.d.ts.map +1 -1
- package/dist/audit/store.js +18 -3
- package/dist/audit/store.js.map +1 -1
- package/dist/browser-sessions/store.d.ts.map +1 -1
- package/dist/browser-sessions/store.js +22 -7
- package/dist/browser-sessions/store.js.map +1 -1
- package/dist/chat-threads/store.d.ts.map +1 -1
- package/dist/chat-threads/store.js +51 -3
- package/dist/chat-threads/store.js.map +1 -1
- package/dist/checkpoints/store.d.ts.map +1 -1
- package/dist/checkpoints/store.js +12 -3
- package/dist/checkpoints/store.js.map +1 -1
- package/dist/cli/create.d.ts.map +1 -1
- package/dist/cli/create.js +9 -0
- package/dist/cli/create.js.map +1 -1
- package/dist/collab/routes.d.ts +2 -2
- package/dist/collab/storage.d.ts.map +1 -1
- package/dist/collab/storage.js +14 -2
- package/dist/collab/storage.js.map +1 -1
- package/dist/db/ddl-guard.d.ts +63 -0
- package/dist/db/ddl-guard.d.ts.map +1 -1
- package/dist/db/ddl-guard.js +85 -0
- package/dist/db/ddl-guard.js.map +1 -1
- package/dist/extensions/store.d.ts.map +1 -1
- package/dist/extensions/store.js +32 -3
- package/dist/extensions/store.js.map +1 -1
- package/dist/file-upload/actions/upload-image.d.ts +2 -2
- package/dist/integrations/a2a-continuations-store.d.ts.map +1 -1
- package/dist/integrations/a2a-continuations-store.js +44 -24
- package/dist/integrations/a2a-continuations-store.js.map +1 -1
- package/dist/integrations/config-store.d.ts.map +1 -1
- package/dist/integrations/config-store.js +17 -11
- package/dist/integrations/config-store.js.map +1 -1
- package/dist/integrations/pending-tasks-store.d.ts.map +1 -1
- package/dist/integrations/pending-tasks-store.js +24 -16
- package/dist/integrations/pending-tasks-store.js.map +1 -1
- package/dist/integrations/remote-commands-store.d.ts.map +1 -1
- package/dist/integrations/remote-commands-store.js +29 -21
- package/dist/integrations/remote-commands-store.js.map +1 -1
- package/dist/integrations/remote-devices-store.d.ts.map +1 -1
- package/dist/integrations/remote-devices-store.js +33 -18
- package/dist/integrations/remote-devices-store.js.map +1 -1
- package/dist/integrations/remote-push-store.d.ts.map +1 -1
- package/dist/integrations/remote-push-store.js +53 -31
- package/dist/integrations/remote-push-store.js.map +1 -1
- package/dist/integrations/remote-run-events-store.d.ts.map +1 -1
- package/dist/integrations/remote-run-events-store.js +26 -10
- package/dist/integrations/remote-run-events-store.js.map +1 -1
- package/dist/integrations/thread-mapping-store.d.ts.map +1 -1
- package/dist/integrations/thread-mapping-store.js +10 -2
- package/dist/integrations/thread-mapping-store.js.map +1 -1
- package/dist/mcp/connect-store.d.ts.map +1 -1
- package/dist/mcp/connect-store.js +34 -16
- package/dist/mcp/connect-store.js.map +1 -1
- package/dist/mcp/oauth-store.d.ts.map +1 -1
- package/dist/mcp/oauth-store.js +22 -7
- package/dist/mcp/oauth-store.js.map +1 -1
- package/dist/notifications/routes.d.ts +2 -2
- package/dist/notifications/store.d.ts.map +1 -1
- package/dist/notifications/store.js +15 -3
- package/dist/notifications/store.js.map +1 -1
- package/dist/oauth-tokens/store.d.ts.map +1 -1
- package/dist/oauth-tokens/store.js +33 -2
- package/dist/oauth-tokens/store.js.map +1 -1
- package/dist/observability/routes.d.ts +7 -7
- package/dist/observability/store.d.ts.map +1 -1
- package/dist/observability/store.js +72 -29
- package/dist/observability/store.js.map +1 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/progress/store.d.ts.map +1 -1
- package/dist/progress/store.js +31 -16
- package/dist/progress/store.js.map +1 -1
- package/dist/provider-api/corpus-jobs-store.d.ts.map +1 -1
- package/dist/provider-api/corpus-jobs-store.js +16 -5
- package/dist/provider-api/corpus-jobs-store.js.map +1 -1
- package/dist/provider-api/custom-registry.d.ts.map +1 -1
- package/dist/provider-api/custom-registry.js +14 -4
- package/dist/provider-api/custom-registry.js.map +1 -1
- package/dist/provider-api/quota-governor.d.ts.map +1 -1
- package/dist/provider-api/quota-governor.js +12 -3
- package/dist/provider-api/quota-governor.js.map +1 -1
- package/dist/provider-api/staged-datasets-store.d.ts.map +1 -1
- package/dist/provider-api/staged-datasets-store.js +16 -5
- package/dist/provider-api/staged-datasets-store.js.map +1 -1
- package/dist/resources/handlers.d.ts +3 -3
- package/dist/resources/store.d.ts.map +1 -1
- package/dist/resources/store.js +56 -25
- package/dist/resources/store.js.map +1 -1
- package/dist/secrets/storage.d.ts.map +1 -1
- package/dist/secrets/storage.js +10 -14
- package/dist/secrets/storage.js.map +1 -1
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams-run-queue.d.ts.map +1 -1
- package/dist/server/agent-teams-run-queue.js +15 -4
- package/dist/server/agent-teams-run-queue.js.map +1 -1
- package/dist/server/auth.d.ts.map +1 -1
- package/dist/server/auth.js +16 -2
- package/dist/server/auth.js.map +1 -1
- package/dist/server/better-auth-instance.d.ts.map +1 -1
- package/dist/server/better-auth-instance.js +55 -21
- package/dist/server/better-auth-instance.js.map +1 -1
- package/dist/server/embed-session.d.ts.map +1 -1
- package/dist/server/embed-session.js +15 -4
- package/dist/server/embed-session.js.map +1 -1
- package/dist/server/identity-sso-store.d.ts.map +1 -1
- package/dist/server/identity-sso-store.js +30 -11
- package/dist/server/identity-sso-store.js.map +1 -1
- package/dist/server/recap-image-store.d.ts.map +1 -1
- package/dist/server/recap-image-store.js +21 -7
- package/dist/server/recap-image-store.js.map +1 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/settings/store.d.ts.map +1 -1
- package/dist/settings/store.js +11 -13
- package/dist/settings/store.js.map +1 -1
- package/dist/usage/store.d.ts.map +1 -1
- package/dist/usage/store.js +36 -11
- package/dist/usage/store.js.map +1 -1
- package/dist/workspace-connections/store.d.ts.map +1 -1
- package/dist/workspace-connections/store.js +57 -7
- package/dist/workspace-connections/store.js.map +1 -1
- package/package.json +1 -1
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* Cost is stored as "centicents" (1/100th of a cent) for integer precision.
|
|
9
9
|
*/
|
|
10
10
|
import { getDbExec, intType, isPostgres } from "../db/client.js";
|
|
11
|
+
import {
|
|
12
|
+
ensureColumnExists,
|
|
13
|
+
ensureIndexExists,
|
|
14
|
+
ensureTableExists,
|
|
15
|
+
} from "../db/ddl-guard.js";
|
|
11
16
|
import { widenIntColumnsToBigInt } from "../db/widen-columns.js";
|
|
12
17
|
|
|
13
18
|
/**
|
|
@@ -191,7 +196,7 @@ async function ensureUsageTable(): Promise<void> {
|
|
|
191
196
|
if (!_initPromise) {
|
|
192
197
|
_initPromise = (async () => {
|
|
193
198
|
const client = getDbExec();
|
|
194
|
-
|
|
199
|
+
const createSql = `
|
|
195
200
|
CREATE TABLE IF NOT EXISTS token_usage (
|
|
196
201
|
id ${intType()} PRIMARY KEY,
|
|
197
202
|
owner_email TEXT NOT NULL,
|
|
@@ -206,11 +211,9 @@ async function ensureUsageTable(): Promise<void> {
|
|
|
206
211
|
ref_id TEXT NOT NULL DEFAULT '',
|
|
207
212
|
created_at ${intType()} NOT NULL
|
|
208
213
|
)
|
|
209
|
-
|
|
214
|
+
`;
|
|
210
215
|
|
|
211
|
-
//
|
|
212
|
-
// fields. Each ALTER is wrapped so a dialect without IF NOT EXISTS
|
|
213
|
-
// (SQLite) still makes progress if only some columns are missing.
|
|
216
|
+
// Additive columns for older deployments that pre-date the label/cache fields.
|
|
214
217
|
const additions: Array<[string, string]> = [
|
|
215
218
|
["cache_read_tokens", `${intType()} NOT NULL DEFAULT 0`],
|
|
216
219
|
["cache_write_tokens", `${intType()} NOT NULL DEFAULT 0`],
|
|
@@ -218,27 +221,59 @@ async function ensureUsageTable(): Promise<void> {
|
|
|
218
221
|
["app", `TEXT NOT NULL DEFAULT ''`],
|
|
219
222
|
["ref_id", `TEXT NOT NULL DEFAULT ''`],
|
|
220
223
|
];
|
|
224
|
+
|
|
225
|
+
if (isPostgres()) {
|
|
226
|
+
// Hot path: the `token_usage` table and its index are virtually always
|
|
227
|
+
// already present in production. Issuing `CREATE TABLE`/`ALTER TABLE`/
|
|
228
|
+
// `CREATE INDEX` still takes a lock that, in a fresh background-worker
|
|
229
|
+
// process behind a concurrent connection on the shared Neon DB, can
|
|
230
|
+
// block ~indefinitely. The ensure* wrappers probe `information_schema`/
|
|
231
|
+
// `pg_indexes` first (plain reads, no lock) and run DDL ONLY for what is
|
|
232
|
+
// actually missing, bounded by a transaction-scoped `lock_timeout`. If a
|
|
233
|
+
// swallowed lock-timeout leaves the schema still missing they RE-PROBE
|
|
234
|
+
// and THROW rather than letting init memoize success against absent
|
|
235
|
+
// schema.
|
|
236
|
+
await ensureTableExists("token_usage", createSql);
|
|
237
|
+
// Add columns on older deployments — guarded so the hot path (columns
|
|
238
|
+
// already present) skips the ACCESS EXCLUSIVE ALTER.
|
|
239
|
+
for (const [col, def] of additions) {
|
|
240
|
+
await ensureColumnExists(
|
|
241
|
+
"token_usage",
|
|
242
|
+
col,
|
|
243
|
+
`ALTER TABLE token_usage ADD COLUMN IF NOT EXISTS ${col} ${def}`,
|
|
244
|
+
);
|
|
245
|
+
}
|
|
246
|
+
// Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres
|
|
247
|
+
// the `Date.now()` written per run by recordUsage() overflows int4. Widen
|
|
248
|
+
// it in place (no-op once done / on fresh BIGINT databases).
|
|
249
|
+
await widenIntColumnsToBigInt("token_usage", ["created_at"]);
|
|
250
|
+
// Probe pg_indexes first (no lock) and skip the SHARE-locking CREATE
|
|
251
|
+
// INDEX when the index is already present.
|
|
252
|
+
await ensureIndexExists(
|
|
253
|
+
"idx_token_usage_owner_created",
|
|
254
|
+
`CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,
|
|
255
|
+
);
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// SQLite (local dev): no lock problem — keep the original behaviour.
|
|
260
|
+
await client.execute(createSql);
|
|
261
|
+
// Add columns on older deployments that pre-date the label/cache
|
|
262
|
+
// fields. Each ALTER is wrapped so a dialect without IF NOT EXISTS
|
|
263
|
+
// (SQLite) still makes progress if only some columns are missing.
|
|
221
264
|
for (const [col, def] of additions) {
|
|
222
265
|
try {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
);
|
|
227
|
-
} else {
|
|
228
|
-
await client.execute(
|
|
229
|
-
`ALTER TABLE token_usage ADD COLUMN ${col} ${def}`,
|
|
230
|
-
);
|
|
231
|
-
}
|
|
266
|
+
await client.execute(
|
|
267
|
+
`ALTER TABLE token_usage ADD COLUMN ${col} ${def}`,
|
|
268
|
+
);
|
|
232
269
|
} catch {
|
|
233
270
|
// Column already exists — ignore
|
|
234
271
|
}
|
|
235
272
|
}
|
|
236
|
-
|
|
237
273
|
// Older deployments created `created_at` as 32-bit `INTEGER`; on Postgres
|
|
238
274
|
// the `Date.now()` written per run by recordUsage() overflows int4. Widen
|
|
239
275
|
// it in place (no-op once done / on fresh BIGINT databases).
|
|
240
276
|
await widenIntColumnsToBigInt("token_usage", ["created_at"]);
|
|
241
|
-
|
|
242
277
|
try {
|
|
243
278
|
await client.execute(
|
|
244
279
|
`CREATE INDEX IF NOT EXISTS idx_token_usage_owner_created ON token_usage (owner_email, created_at)`,
|
|
@@ -15,6 +15,11 @@ import {
|
|
|
15
15
|
safeJsonParse,
|
|
16
16
|
type DbExec,
|
|
17
17
|
} from "../db/client.js";
|
|
18
|
+
import {
|
|
19
|
+
ensureColumnExists,
|
|
20
|
+
ensureIndexExists,
|
|
21
|
+
ensureTableExists,
|
|
22
|
+
} from "../db/ddl-guard.js";
|
|
18
23
|
import {
|
|
19
24
|
getRequestOrgId,
|
|
20
25
|
getRequestUserEmail,
|
|
@@ -459,8 +464,8 @@ export async function ensureWorkspaceConnectionsTable(): Promise<void> {
|
|
|
459
464
|
const client = getDbExec();
|
|
460
465
|
const table = workspaceConnectionsTable();
|
|
461
466
|
const grantsTable = workspaceConnectionGrantsTable();
|
|
462
|
-
|
|
463
|
-
|
|
467
|
+
|
|
468
|
+
const createConnectionsSql = `
|
|
464
469
|
CREATE TABLE IF NOT EXISTS ${table} (
|
|
465
470
|
id TEXT PRIMARY KEY,
|
|
466
471
|
provider TEXT NOT NULL DEFAULT '',
|
|
@@ -480,23 +485,8 @@ export async function ensureWorkspaceConnectionsTable(): Promise<void> {
|
|
|
480
485
|
last_checked_at ${intType()},
|
|
481
486
|
last_error TEXT
|
|
482
487
|
)
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
await ensureWorkspaceConnectionColumns(client, table);
|
|
487
|
-
|
|
488
|
-
await retryOnDdlRace(() =>
|
|
489
|
-
client.execute(
|
|
490
|
-
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_scope_provider ON ${table} (org_id, owner_email, provider)`,
|
|
491
|
-
),
|
|
492
|
-
);
|
|
493
|
-
await retryOnDdlRace(() =>
|
|
494
|
-
client.execute(
|
|
495
|
-
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_updated_at ON ${table} (updated_at)`,
|
|
496
|
-
),
|
|
497
|
-
);
|
|
498
|
-
await retryOnDdlRace(() =>
|
|
499
|
-
client.execute(`
|
|
488
|
+
`;
|
|
489
|
+
const createGrantsSql = `
|
|
500
490
|
CREATE TABLE IF NOT EXISTS ${grantsTable} (
|
|
501
491
|
id TEXT PRIMARY KEY,
|
|
502
492
|
connection_id TEXT NOT NULL DEFAULT '',
|
|
@@ -512,11 +502,199 @@ export async function ensureWorkspaceConnectionsTable(): Promise<void> {
|
|
|
512
502
|
updated_at ${intType()} NOT NULL DEFAULT 0,
|
|
513
503
|
last_used_at ${intType()}
|
|
514
504
|
)
|
|
515
|
-
|
|
516
|
-
|
|
505
|
+
`;
|
|
506
|
+
|
|
507
|
+
if (isPostgres()) {
|
|
508
|
+
// PG-guard: probe information_schema / pg_indexes first (no lock) and
|
|
509
|
+
// only issue DDL when the table/column/index is actually missing,
|
|
510
|
+
// wrapped in a transaction-scoped lock_timeout so a contended lock
|
|
511
|
+
// fails fast. Uses unqualified table names for the probe (the helpers
|
|
512
|
+
// always search the `public` schema).
|
|
513
|
+
|
|
514
|
+
// --- workspace_connections ---
|
|
515
|
+
await ensureTableExists("workspace_connections", createConnectionsSql);
|
|
516
|
+
await ensureColumnExists(
|
|
517
|
+
"workspace_connections",
|
|
518
|
+
"provider",
|
|
519
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS provider TEXT NOT NULL DEFAULT ''`,
|
|
520
|
+
);
|
|
521
|
+
await ensureColumnExists(
|
|
522
|
+
"workspace_connections",
|
|
523
|
+
"label",
|
|
524
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS label TEXT NOT NULL DEFAULT ''`,
|
|
525
|
+
);
|
|
526
|
+
await ensureColumnExists(
|
|
527
|
+
"workspace_connections",
|
|
528
|
+
"account_id",
|
|
529
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS account_id TEXT`,
|
|
530
|
+
);
|
|
531
|
+
await ensureColumnExists(
|
|
532
|
+
"workspace_connections",
|
|
533
|
+
"account_label",
|
|
534
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS account_label TEXT`,
|
|
535
|
+
);
|
|
536
|
+
await ensureColumnExists(
|
|
537
|
+
"workspace_connections",
|
|
538
|
+
"status",
|
|
539
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS status TEXT NOT NULL DEFAULT 'connected'`,
|
|
540
|
+
);
|
|
541
|
+
await ensureColumnExists(
|
|
542
|
+
"workspace_connections",
|
|
543
|
+
"scopes_json",
|
|
544
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS scopes_json TEXT NOT NULL DEFAULT '[]'`,
|
|
545
|
+
);
|
|
546
|
+
await ensureColumnExists(
|
|
547
|
+
"workspace_connections",
|
|
548
|
+
"config_json",
|
|
549
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS config_json TEXT NOT NULL DEFAULT '{}'`,
|
|
550
|
+
);
|
|
551
|
+
await ensureColumnExists(
|
|
552
|
+
"workspace_connections",
|
|
553
|
+
"allowed_apps_json",
|
|
554
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS allowed_apps_json TEXT NOT NULL DEFAULT '[]'`,
|
|
555
|
+
);
|
|
556
|
+
await ensureColumnExists(
|
|
557
|
+
"workspace_connections",
|
|
558
|
+
"credential_refs_json",
|
|
559
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS credential_refs_json TEXT NOT NULL DEFAULT '[]'`,
|
|
560
|
+
);
|
|
561
|
+
await ensureColumnExists(
|
|
562
|
+
"workspace_connections",
|
|
563
|
+
"owner_email",
|
|
564
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS owner_email TEXT NOT NULL DEFAULT ''`,
|
|
565
|
+
);
|
|
566
|
+
await ensureColumnExists(
|
|
567
|
+
"workspace_connections",
|
|
568
|
+
"org_id",
|
|
569
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS org_id TEXT`,
|
|
570
|
+
);
|
|
571
|
+
await ensureColumnExists(
|
|
572
|
+
"workspace_connections",
|
|
573
|
+
"created_at",
|
|
574
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS created_at ${intType()} NOT NULL DEFAULT 0`,
|
|
575
|
+
);
|
|
576
|
+
await ensureColumnExists(
|
|
577
|
+
"workspace_connections",
|
|
578
|
+
"updated_at",
|
|
579
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS updated_at ${intType()} NOT NULL DEFAULT 0`,
|
|
580
|
+
);
|
|
581
|
+
await ensureColumnExists(
|
|
582
|
+
"workspace_connections",
|
|
583
|
+
"last_checked_at",
|
|
584
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS last_checked_at ${intType()}`,
|
|
585
|
+
);
|
|
586
|
+
await ensureColumnExists(
|
|
587
|
+
"workspace_connections",
|
|
588
|
+
"last_used_at",
|
|
589
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS last_used_at ${intType()}`,
|
|
590
|
+
);
|
|
591
|
+
await ensureColumnExists(
|
|
592
|
+
"workspace_connections",
|
|
593
|
+
"last_error",
|
|
594
|
+
`ALTER TABLE workspace_connections ADD COLUMN IF NOT EXISTS last_error TEXT`,
|
|
595
|
+
);
|
|
596
|
+
await ensureIndexExists(
|
|
597
|
+
"idx_workspace_connections_scope_provider",
|
|
598
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_scope_provider ON ${table} (org_id, owner_email, provider)`,
|
|
599
|
+
);
|
|
600
|
+
await ensureIndexExists(
|
|
601
|
+
"idx_workspace_connections_updated_at",
|
|
602
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_updated_at ON ${table} (updated_at)`,
|
|
603
|
+
);
|
|
517
604
|
|
|
518
|
-
|
|
605
|
+
// --- workspace_connection_grants ---
|
|
606
|
+
await ensureTableExists("workspace_connection_grants", createGrantsSql);
|
|
607
|
+
await ensureColumnExists(
|
|
608
|
+
"workspace_connection_grants",
|
|
609
|
+
"connection_id",
|
|
610
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS connection_id TEXT NOT NULL DEFAULT ''`,
|
|
611
|
+
);
|
|
612
|
+
await ensureColumnExists(
|
|
613
|
+
"workspace_connection_grants",
|
|
614
|
+
"provider",
|
|
615
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS provider TEXT NOT NULL DEFAULT ''`,
|
|
616
|
+
);
|
|
617
|
+
await ensureColumnExists(
|
|
618
|
+
"workspace_connection_grants",
|
|
619
|
+
"app_id",
|
|
620
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS app_id TEXT NOT NULL DEFAULT ''`,
|
|
621
|
+
);
|
|
622
|
+
await ensureColumnExists(
|
|
623
|
+
"workspace_connection_grants",
|
|
624
|
+
"scopes_json",
|
|
625
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS scopes_json TEXT NOT NULL DEFAULT '[]'`,
|
|
626
|
+
);
|
|
627
|
+
await ensureColumnExists(
|
|
628
|
+
"workspace_connection_grants",
|
|
629
|
+
"config_json",
|
|
630
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS config_json TEXT NOT NULL DEFAULT '{}'`,
|
|
631
|
+
);
|
|
632
|
+
await ensureColumnExists(
|
|
633
|
+
"workspace_connection_grants",
|
|
634
|
+
"credential_refs_json",
|
|
635
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS credential_refs_json TEXT NOT NULL DEFAULT '[]'`,
|
|
636
|
+
);
|
|
637
|
+
await ensureColumnExists(
|
|
638
|
+
"workspace_connection_grants",
|
|
639
|
+
"granted_by_email",
|
|
640
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS granted_by_email TEXT NOT NULL DEFAULT ''`,
|
|
641
|
+
);
|
|
642
|
+
await ensureColumnExists(
|
|
643
|
+
"workspace_connection_grants",
|
|
644
|
+
"owner_email",
|
|
645
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS owner_email TEXT NOT NULL DEFAULT ''`,
|
|
646
|
+
);
|
|
647
|
+
await ensureColumnExists(
|
|
648
|
+
"workspace_connection_grants",
|
|
649
|
+
"org_id",
|
|
650
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS org_id TEXT`,
|
|
651
|
+
);
|
|
652
|
+
await ensureColumnExists(
|
|
653
|
+
"workspace_connection_grants",
|
|
654
|
+
"created_at",
|
|
655
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS created_at ${intType()} NOT NULL DEFAULT 0`,
|
|
656
|
+
);
|
|
657
|
+
await ensureColumnExists(
|
|
658
|
+
"workspace_connection_grants",
|
|
659
|
+
"updated_at",
|
|
660
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS updated_at ${intType()} NOT NULL DEFAULT 0`,
|
|
661
|
+
);
|
|
662
|
+
await ensureColumnExists(
|
|
663
|
+
"workspace_connection_grants",
|
|
664
|
+
"last_used_at",
|
|
665
|
+
`ALTER TABLE workspace_connection_grants ADD COLUMN IF NOT EXISTS last_used_at ${intType()}`,
|
|
666
|
+
);
|
|
667
|
+
await ensureIndexExists(
|
|
668
|
+
"idx_workspace_connection_grants_connection_app",
|
|
669
|
+
`CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_connection_grants_connection_app ON ${grantsTable} (connection_id, app_id)`,
|
|
670
|
+
);
|
|
671
|
+
await ensureIndexExists(
|
|
672
|
+
"idx_workspace_connection_grants_scope_app",
|
|
673
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connection_grants_scope_app ON ${grantsTable} (org_id, owner_email, app_id)`,
|
|
674
|
+
);
|
|
675
|
+
await ensureIndexExists(
|
|
676
|
+
"idx_workspace_connection_grants_updated_at",
|
|
677
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connection_grants_updated_at ON ${grantsTable} (updated_at)`,
|
|
678
|
+
);
|
|
679
|
+
return;
|
|
680
|
+
}
|
|
519
681
|
|
|
682
|
+
// SQLite (local dev): no ACCESS EXCLUSIVE lock problem — keep existing
|
|
683
|
+
// retryOnDdlRace + ensureColumn behaviour.
|
|
684
|
+
await retryOnDdlRace(() => client.execute(createConnectionsSql));
|
|
685
|
+
await ensureWorkspaceConnectionColumns(client, table);
|
|
686
|
+
await retryOnDdlRace(() =>
|
|
687
|
+
client.execute(
|
|
688
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_scope_provider ON ${table} (org_id, owner_email, provider)`,
|
|
689
|
+
),
|
|
690
|
+
);
|
|
691
|
+
await retryOnDdlRace(() =>
|
|
692
|
+
client.execute(
|
|
693
|
+
`CREATE INDEX IF NOT EXISTS idx_workspace_connections_updated_at ON ${table} (updated_at)`,
|
|
694
|
+
),
|
|
695
|
+
);
|
|
696
|
+
await retryOnDdlRace(() => client.execute(createGrantsSql));
|
|
697
|
+
await ensureWorkspaceConnectionGrantColumns(client, grantsTable);
|
|
520
698
|
await retryOnDdlRace(() =>
|
|
521
699
|
client.execute(
|
|
522
700
|
`CREATE UNIQUE INDEX IF NOT EXISTS idx_workspace_connection_grants_connection_app ON ${grantsTable} (connection_id, app_id)`,
|
|
@@ -267,8 +267,6 @@ export function renderBookingOgImageSvg(input: BookingOgImageInput): string {
|
|
|
267
267
|
</defs>
|
|
268
268
|
<rect width="${WIDTH}" height="${HEIGHT}" fill="${BG}"/>
|
|
269
269
|
<rect width="${WIDTH}" height="${HEIGHT}" fill="url(#grid)"/>
|
|
270
|
-
<rect x="64" y="64" width="1072" height="502" rx="28" fill="${BG}" fill-opacity="0.72" stroke="${BORDER}" stroke-width="1"/>
|
|
271
|
-
<path d="M80 154 H1120" stroke="${BORDER}"/>
|
|
272
270
|
<g transform="translate(80 86)">
|
|
273
271
|
<g transform="scale(0.62)">
|
|
274
272
|
${LOGO_MARK}
|
|
@@ -168,8 +168,6 @@ export function renderFormOgImageSvg(input: FormOgImageInput = {}): string {
|
|
|
168
168
|
</defs>
|
|
169
169
|
<rect width="${WIDTH}" height="${HEIGHT}" fill="${BG}"/>
|
|
170
170
|
<rect width="${WIDTH}" height="${HEIGHT}" fill="url(#grid)"/>
|
|
171
|
-
<rect x="64" y="64" width="1072" height="502" rx="28" fill="${BG}" fill-opacity="0.72" stroke="${BORDER}" stroke-width="1"/>
|
|
172
|
-
<path d="M80 154 H1120" stroke="${BORDER}"/>
|
|
173
171
|
<g transform="translate(80 86)">
|
|
174
172
|
<g transform="scale(0.62)">
|
|
175
173
|
${LOGO_MARK}
|
|
@@ -486,8 +486,10 @@
|
|
|
486
486
|
padding-inline-start: 0.75rem;
|
|
487
487
|
}
|
|
488
488
|
|
|
489
|
-
/*
|
|
489
|
+
/* Hidden below the rail breakpoint: the document should use the full reading
|
|
490
|
+
* width instead of replacing the rail with an inline contents widget. */
|
|
490
491
|
.plan-document-toc-inline {
|
|
492
|
+
display: none;
|
|
491
493
|
margin-top: 1.25rem;
|
|
492
494
|
border: 1px solid var(--plan-line);
|
|
493
495
|
border-radius: 0.75rem;
|
|
@@ -548,23 +550,16 @@
|
|
|
548
550
|
list-style: none;
|
|
549
551
|
}
|
|
550
552
|
|
|
551
|
-
/* Hide the accordion
|
|
553
|
+
/* Hide the accordion in screenshot capture too. */
|
|
552
554
|
.plan-content-surface[data-recap-screenshot-theme] .plan-document-toc-inline {
|
|
553
555
|
display: none;
|
|
554
556
|
}
|
|
555
|
-
@container plan-doc (min-width: 48rem) {
|
|
556
|
-
.plan-content-surface:not([data-recap-screenshot-theme])
|
|
557
|
-
.plan-document-body[data-has-toc]
|
|
558
|
-
> .plan-document-toc-inline {
|
|
559
|
-
display: none;
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
557
|
|
|
563
558
|
/* Wide layout: the contents rail is a real grid column. A matching empty left
|
|
564
559
|
* column balances the rail so the document itself remains visually centered. */
|
|
565
560
|
|
|
566
561
|
/* Shared cell placement. Inert until the parent is a grid. */
|
|
567
|
-
@container plan-doc (min-width:
|
|
562
|
+
@container plan-doc (min-width: 1200px) {
|
|
568
563
|
.plan-content-surface:not([data-recap-screenshot-theme])
|
|
569
564
|
.plan-document-body
|
|
570
565
|
> header {
|
|
@@ -588,7 +583,7 @@
|
|
|
588
583
|
}
|
|
589
584
|
|
|
590
585
|
/* Document + contents rail. The empty first column balances the right rail. */
|
|
591
|
-
@container plan-doc (min-width:
|
|
586
|
+
@container plan-doc (min-width: 1200px) {
|
|
592
587
|
.plan-content-surface:not([data-recap-screenshot-theme])
|
|
593
588
|
.plan-document-body[data-has-toc] {
|
|
594
589
|
display: grid;
|
|
@@ -593,22 +593,25 @@ export function shouldShowPlanLoadError(input: {
|
|
|
593
593
|
hasSelectedId: boolean;
|
|
594
594
|
localPlanMode: boolean;
|
|
595
595
|
hasBundle: boolean;
|
|
596
|
-
|
|
596
|
+
planQueryInitialPending: boolean;
|
|
597
597
|
planQueryError: boolean;
|
|
598
598
|
planQueryPaused: boolean;
|
|
599
|
-
|
|
599
|
+
accessStatusInitialPending: boolean;
|
|
600
600
|
accessStatusPaused: boolean;
|
|
601
601
|
accessDenied: boolean;
|
|
602
602
|
}): boolean {
|
|
603
603
|
if (!input.hasSelectedId || input.localPlanMode || input.hasBundle) {
|
|
604
604
|
return false;
|
|
605
605
|
}
|
|
606
|
-
// While a read is actively in flight, keep showing the skeleton.
|
|
607
|
-
if (input.planQueryPending) return false;
|
|
608
606
|
if (input.planQueryError) return true;
|
|
607
|
+
if (!input.accessStatusInitialPending && input.accessDenied) return true;
|
|
608
|
+
// While the first read is actively in flight, keep showing the skeleton.
|
|
609
|
+
// Background refetches must not hide a settled access/error card.
|
|
610
|
+
if (input.planQueryInitialPending || input.accessStatusInitialPending) {
|
|
611
|
+
return false;
|
|
612
|
+
}
|
|
609
613
|
// Paused/stalled read that will never settle on its own input.
|
|
610
614
|
if (input.planQueryPaused || input.accessStatusPaused) return true;
|
|
611
|
-
if (!input.accessStatusPending && input.accessDenied) return true;
|
|
612
615
|
return false;
|
|
613
616
|
}
|
|
614
617
|
|
|
@@ -3120,17 +3123,16 @@ export function PlansPage({ localPlanSlug }: { localPlanSlug?: string } = {}) {
|
|
|
3120
3123
|
Boolean(selectedId && !bundle && !localPlanMode),
|
|
3121
3124
|
);
|
|
3122
3125
|
const planAccessStatus = planAccessStatusQuery.data ?? null;
|
|
3123
|
-
const
|
|
3124
|
-
const
|
|
3125
|
-
planAccessStatusQuery.isLoading || planAccessStatusQuery.isFetching;
|
|
3126
|
+
const planQueryInitialPending = planQuery.isLoading;
|
|
3127
|
+
const planAccessStatusInitialPending = planAccessStatusQuery.isLoading;
|
|
3126
3128
|
const showPlanLoadError = shouldShowPlanLoadError({
|
|
3127
3129
|
hasSelectedId: Boolean(selectedId),
|
|
3128
3130
|
localPlanMode,
|
|
3129
3131
|
hasBundle: Boolean(bundle),
|
|
3130
|
-
|
|
3132
|
+
planQueryInitialPending,
|
|
3131
3133
|
planQueryError: planQuery.isError,
|
|
3132
3134
|
planQueryPaused: planQuery.isPaused,
|
|
3133
|
-
|
|
3135
|
+
accessStatusInitialPending: planAccessStatusInitialPending,
|
|
3134
3136
|
accessStatusPaused: planAccessStatusQuery.isPaused,
|
|
3135
3137
|
accessDenied: Boolean(planAccessStatus && !planAccessStatus.hasAccess),
|
|
3136
3138
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/a2a/task-store.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"task-store.d.ts","sourceRoot":"","sources":["../../src/a2a/task-store.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAgGrE,wBAAsB,UAAU,CAC9B,OAAO,EAAE,OAAO,EAChB,SAAS,CAAC,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAClC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,IAAI,CAAC,CAiCf;AAED;;;;;;;GAOG;AACH,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAUrE;AAED;;;;;;;;GAQG;AACH,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,GACT,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAwBtB;AAED,wBAAsB,uBAAuB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC;IACjE,EAAE,EAAE,MAAM,CAAC;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,SAAS,CAAC;IAC9C,SAAS,EAAE,MAAM,CAAC;CACnB,GAAG,IAAI,CAAC,CAeR;AAED,wBAAsB,0BAA0B,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAa7E;AAED,wBAAsB,sBAAsB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAazE;AAED,wBAAsB,yBAAyB,CAC7C,EAAE,EAAE,MAAM,EACV,gBAAgB,EAAE,MAAM,GACvB,OAAO,CAAC,OAAO,CAAC,CAiBlB;AAED,wBAAsB,gBAAgB,CACpC,EAAE,EAAE,MAAM,EACV,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAAC,OAAO,CAAC,CAsBlB;AAED,wBAAsB,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CAS9D;AAED,wBAAsB,UAAU,CAC9B,EAAE,EAAE,MAAM,EACV,MAAM,EAAE;IACN,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,QAAQ,EAAE,CAAC;CACxB,GACA,OAAO,CAAC,IAAI,GAAG,IAAI,CAAC,CA4CtB;AAED,wBAAsB,uBAAuB,CAC3C,EAAE,EAAE,MAAM,EACV,OAAO,EAAE,OAAO,GACf,OAAO,CAAC,IAAI,CAAC,CAcf;AAED,wBAAsB,SAAS,CAAC,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC,CAgBnE"}
|
package/dist/a2a/task-store.js
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import crypto from "crypto";
|
|
2
|
-
import { getDbExec, intType } from "../db/client.js";
|
|
2
|
+
import { getDbExec, intType, isPostgres } from "../db/client.js";
|
|
3
|
+
import { ensureTableExists, ensureColumnExists } from "../db/ddl-guard.js";
|
|
3
4
|
let _initPromise;
|
|
4
5
|
async function ensureTable() {
|
|
5
6
|
if (!_initPromise) {
|
|
6
7
|
_initPromise = (async () => {
|
|
7
8
|
const client = getDbExec();
|
|
8
|
-
|
|
9
|
+
const createSql = `
|
|
9
10
|
CREATE TABLE IF NOT EXISTS a2a_tasks (
|
|
10
11
|
id TEXT PRIMARY KEY,
|
|
11
12
|
context_id TEXT,
|
|
@@ -18,7 +19,22 @@ async function ensureTable() {
|
|
|
18
19
|
created_at ${intType()} NOT NULL,
|
|
19
20
|
updated_at ${intType()} NOT NULL
|
|
20
21
|
)
|
|
21
|
-
|
|
22
|
+
`;
|
|
23
|
+
if (isPostgres()) {
|
|
24
|
+
// PG-guard: probe information_schema before issuing DDL to avoid ACCESS
|
|
25
|
+
// EXCLUSIVE lock contention in fresh background-worker processes.
|
|
26
|
+
await ensureTableExists("a2a_tasks", createSql);
|
|
27
|
+
// Additive migration: owner_email column. Bound to the JWT-verified
|
|
28
|
+
// caller at task-creation time so handleGet / handleCancel can reject
|
|
29
|
+
// mismatched callers (the IDOR class fixed in PR #369). Existing rows
|
|
30
|
+
// have NULL owner_email and remain accessible to legacy callers via
|
|
31
|
+
// the legacy-token apiKeyEnv path; new rows are scoped from this point
|
|
32
|
+
// forward.
|
|
33
|
+
await ensureColumnExists("a2a_tasks", "owner_email", `ALTER TABLE a2a_tasks ADD COLUMN IF NOT EXISTS owner_email TEXT`);
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
// SQLite (local dev): no lock problem — keep the original behaviour.
|
|
37
|
+
await client.execute(createSql);
|
|
22
38
|
// Additive migration: owner_email column. Bound to the JWT-verified
|
|
23
39
|
// caller at task-creation time so handleGet / handleCancel can reject
|
|
24
40
|
// mismatched callers (the IDOR class fixed in PR #369). Existing rows
|