@agent-native/core 0.136.0 → 0.136.3
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/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +31 -5
- package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +7 -0
- package/corpus/templates/analytics/.agents/skills/gong/SKILL.md +52 -19
- package/corpus/templates/analytics/.agents/skills/provider-api/SKILL.md +25 -3
- package/corpus/templates/analytics/AGENTS.md +6 -7
- package/corpus/templates/analytics/actions/gong-calls.ts +3 -3
- package/corpus/templates/analytics/actions/provider-api-catalog.ts +1 -1
- package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +1 -1
- package/corpus/templates/analytics/app/i18n-data.ts +46 -0
- package/corpus/templates/analytics/app/pages/Settings.tsx +67 -1
- package/corpus/templates/analytics/app/pages/settings/settings-search.ts +6 -0
- package/corpus/templates/analytics/changelog/2026-08-03-dashboard-builds-now-finish-without-an-extra-confirmation.md +6 -0
- package/corpus/templates/analytics/changelog/2026-08-03-error-alert-emails-are-opt-in.md +6 -0
- package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +10 -9
- package/corpus/templates/analytics/server/lib/error-capture.ts +38 -10
- package/corpus/templates/analytics/server/lib/gong.ts +27 -4
- package/corpus/templates/analytics/server/plugins/agent-chat.ts +64 -4
- package/corpus/templates/analytics/shared/analytics-user-prefs.ts +7 -0
- package/corpus/templates/clips/.agents/skills/video-sharing/SKILL.md +15 -6
- package/corpus/templates/clips/actions/apply-rewind-extension.ts +9 -0
- package/corpus/templates/clips/actions/cleanup-dictation.ts +2 -2
- package/corpus/templates/clips/actions/cleanup-transcript.ts +8 -11
- package/corpus/templates/clips/actions/clear-edits.ts +15 -2
- package/corpus/templates/clips/actions/create-recording-agent-link.ts +10 -0
- package/corpus/templates/clips/actions/finalize-meeting.ts +6 -6
- package/corpus/templates/clips/actions/finalize-recording.ts +33 -8
- package/corpus/templates/clips/actions/lib/ensure-seekable-video.ts +1 -3
- package/corpus/templates/clips/actions/list-recordings.ts +39 -24
- package/corpus/templates/clips/actions/list-transactional-email-ai-requests.ts +4 -1
- package/corpus/templates/clips/actions/regenerate-title.ts +2 -2
- package/corpus/templates/clips/actions/stitch-recordings.ts +36 -7
- package/corpus/templates/clips/app/components/editor/rewind-extension-dialog.tsx +1 -4
- package/corpus/templates/clips/app/components/editor/stitch-manager.tsx +3 -1
- package/corpus/templates/clips/app/components/library/recording-card.tsx +9 -0
- package/corpus/templates/clips/app/components/player/recording-views-badge.tsx +52 -7
- package/corpus/templates/clips/app/hooks/use-library.ts +1 -0
- package/corpus/templates/clips/app/hooks/use-transactional-email-bridge.ts +17 -10
- package/corpus/templates/clips/app/i18n/en-US.ts +3 -0
- package/corpus/templates/clips/app/lib/timestamp-mapping.ts +5 -0
- package/corpus/templates/clips/app/routes/r.$recordingId.tsx +1 -0
- package/corpus/templates/clips/app/routes/share.$shareId.tsx +2 -0
- package/corpus/templates/clips/changelog/2026-07-31-agent-views-now-show-the-agent-s-name-from-the-link-it-was-g.md +6 -0
- package/corpus/templates/clips/changelog/2026-07-31-clip-cards-and-the-watch-share-page-header-now-show-agent-vi.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-01-recordings-stored-in-private-s3-compatible-buckets-finalize-.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-03-clip-cleanup-titles-and-meeting-summaries-now-use-luna-by-de.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-03-get-a-monthly-recap-email-showing-how-many-people-and-ai-age.md +6 -0
- package/corpus/templates/clips/changelog/2026-08-03-get-an-email-the-first-time-an-ai-agent-reads-one-of-your-cl.md +6 -0
- package/corpus/templates/clips/learnings.defaults.md +2 -2
- package/corpus/templates/clips/package.json +1 -1
- package/corpus/templates/clips/scripts/send-real-recap.ts +165 -0
- package/corpus/templates/clips/scripts/send-test-emails.ts +60 -0
- package/corpus/templates/clips/server/db/schema.ts +4 -0
- package/corpus/templates/clips/server/jobs/transactional-emails.ts +256 -0
- package/corpus/templates/clips/server/lib/agent-views.ts +38 -11
- package/corpus/templates/clips/server/lib/media-storage-provenance.ts +16 -0
- package/corpus/templates/clips/server/lib/public-agent-context.ts +3 -1
- package/corpus/templates/clips/server/lib/recap-metrics.ts +373 -0
- package/corpus/templates/clips/server/lib/s3-upload-provider.ts +84 -4
- package/corpus/templates/clips/server/lib/transactional-email-store.ts +41 -2
- package/corpus/templates/clips/server/lib/transactional-email-templates.ts +245 -3
- package/corpus/templates/clips/server/plugins/db.ts +16 -0
- package/corpus/templates/clips/server/register-secrets.ts +2 -2
- package/corpus/templates/clips/server/routes/api/public-recording.get.ts +7 -2
- package/corpus/templates/clips/server/routes/api/video/[recordingId].get.ts +42 -1
- package/corpus/templates/design/actions/take-design-screenshot.ts +5 -3
- package/corpus/templates/design/package.json +1 -1
- package/corpus/templates/design/server/lib/playwright-runtime.ts +13 -5
- package/corpus/templates/mail/actions/get-automation-settings.ts +4 -12
- package/corpus/templates/mail/app/pages/SettingsPage.tsx +1 -1
- package/corpus/templates/mail/changelog/2026-08-03-inbox-automations-now-prefer-the-lowest-cost-luna-model-when.md +6 -0
- package/corpus/templates/mail/server/lib/automation-engine.ts +19 -14
- package/corpus/templates/mail/server/lib/automation-model.ts +110 -0
- package/corpus/templates/mail/server/plugins/agent-chat.ts +1 -1
- package/corpus/templates/slides/actions/generate-slides-ai.ts +92 -24
- package/corpus/templates/slides/changelog/2026-08-03-legacy-slide-outlines-now-prefer-the-lowest-cost-luna-model-.md +6 -0
- package/corpus/templates/tasks/package.json +2 -2
- package/dist/agent/production-agent.d.ts +2 -2
- package/dist/agent/production-agent.js +1 -1
- package/dist/catalog.json +2 -0
- package/dist/client/AgentTaskCard.js +4 -2
- package/dist/client/i18n.js +3 -0
- package/dist/client/settings/VoiceTranscriptionSection.js +2 -2
- package/dist/collab/awareness.d.ts +2 -2
- package/dist/collab/routes.d.ts +1 -1
- package/dist/collab/struct-routes.d.ts +1 -1
- package/dist/localization/default-messages.d.ts +5 -0
- package/dist/localization/default-messages.js +5 -0
- package/dist/mcp/oauth-client-metadata.d.ts +7 -0
- package/dist/mcp/oauth-client-metadata.js +47 -0
- package/dist/mcp/oauth-route.js +7 -3
- package/dist/mcp/oauth-store.d.ts +2 -0
- package/dist/mcp/oauth-store.js +25 -3
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +3 -3
- package/dist/observability/traces.d.ts +1 -1
- package/dist/observability/traces.js +2 -1
- package/dist/progress/routes.d.ts +1 -1
- package/dist/provider-api/index.js +29 -1
- package/dist/secrets/routes.d.ts +6 -6
- package/dist/server/agent-access.d.ts +3 -1
- package/dist/server/agent-access.js +2 -1
- package/dist/server/agent-chat/browser-team-tools.d.ts +1 -0
- package/dist/server/agent-chat/browser-team-tools.js +5 -4
- package/dist/server/agent-chat/context-tools.js +2 -2
- package/dist/server/agent-chat-plugin.js +13 -6
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-teams-run-queue.d.ts +2 -0
- package/dist/server/agent-teams.d.ts +2 -0
- package/dist/server/agent-teams.js +45 -2
- package/dist/server/request-context.d.ts +2 -0
- package/dist/server/short-lived-token.d.ts +7 -0
- package/dist/server/short-lived-token.js +7 -1
- package/dist/server/ssr-handler.js +19 -1
- package/dist/server/transcribe-voice.d.ts +1 -1
- package/dist/server/transcribe-voice.js +24 -16
- package/dist/vite/client.d.ts +37 -1
- package/dist/vite/client.js +110 -1
- package/docs/content/template-assets.mdx +14 -4
- package/package.json +3 -4
|
@@ -26,6 +26,7 @@ export interface OAuthClientRow {
|
|
|
26
26
|
grantTypes: string[];
|
|
27
27
|
responseTypes: string[];
|
|
28
28
|
tokenEndpointAuthMethod: string;
|
|
29
|
+
applicationType: "native" | "web";
|
|
29
30
|
createdAt: number | null;
|
|
30
31
|
}
|
|
31
32
|
export interface OAuthCodeRow {
|
|
@@ -66,6 +67,7 @@ export declare function registerOAuthClient(params: {
|
|
|
66
67
|
grantTypes?: string[];
|
|
67
68
|
responseTypes?: string[];
|
|
68
69
|
tokenEndpointAuthMethod?: string;
|
|
70
|
+
applicationType?: "native" | "web";
|
|
69
71
|
}): Promise<OAuthClientRow>;
|
|
70
72
|
export declare function getOAuthClient(clientId: string): Promise<OAuthClientRow | null>;
|
|
71
73
|
export declare function createOAuthCode(params: {
|
package/dist/mcp/oauth-store.js
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import { randomBytes, randomUUID, createHash } from "node:crypto";
|
|
9
9
|
import { getDbExec, isConnectionError, intType, isPostgres, } from "../db/client.js";
|
|
10
|
-
import { ensureTableExists } from "../db/ddl-guard.js";
|
|
10
|
+
import { ensureColumnExists, ensureTableExists } from "../db/ddl-guard.js";
|
|
11
|
+
import { applicationTypeForRedirectUris } from "./oauth-client-metadata.js";
|
|
11
12
|
let _initPromise;
|
|
12
13
|
export const MCP_OAUTH_CODE_TTL_MS = 10 * 60_000;
|
|
13
14
|
/**
|
|
@@ -76,6 +77,7 @@ async function ensureTable() {
|
|
|
76
77
|
grant_types TEXT,
|
|
77
78
|
response_types TEXT,
|
|
78
79
|
token_endpoint_auth_method TEXT,
|
|
80
|
+
application_type TEXT,
|
|
79
81
|
created_at ${intType()}
|
|
80
82
|
)
|
|
81
83
|
`;
|
|
@@ -118,6 +120,7 @@ async function ensureTable() {
|
|
|
118
120
|
// DDL when the table is actually missing, wrapped in a
|
|
119
121
|
// transaction-scoped lock_timeout so a contended lock fails fast.
|
|
120
122
|
await ensureTableExists("mcp_oauth_clients", createClientsSql);
|
|
123
|
+
await ensureColumnExists("mcp_oauth_clients", "application_type", `ALTER TABLE mcp_oauth_clients ADD COLUMN IF NOT EXISTS application_type TEXT`);
|
|
121
124
|
await ensureTableExists("mcp_oauth_codes", createCodesSql);
|
|
122
125
|
await ensureTableExists("mcp_oauth_refresh_tokens", createRefreshTokensSql);
|
|
123
126
|
return;
|
|
@@ -125,6 +128,17 @@ async function ensureTable() {
|
|
|
125
128
|
// SQLite (local dev): no ACCESS EXCLUSIVE lock problem — keep existing
|
|
126
129
|
// create-then-execute behaviour.
|
|
127
130
|
await client.execute(createClientsSql);
|
|
131
|
+
try {
|
|
132
|
+
await client.execute(`ALTER TABLE mcp_oauth_clients ADD COLUMN IF NOT EXISTS application_type TEXT`);
|
|
133
|
+
}
|
|
134
|
+
catch {
|
|
135
|
+
try {
|
|
136
|
+
await client.execute(`ALTER TABLE mcp_oauth_clients ADD COLUMN application_type TEXT`);
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
// Fresh and previously migrated databases already have the column.
|
|
140
|
+
}
|
|
141
|
+
}
|
|
128
142
|
await client.execute(createCodesSql);
|
|
129
143
|
await client.execute(createRefreshTokensSql);
|
|
130
144
|
})().catch((err) => {
|
|
@@ -160,16 +174,21 @@ function numOrNull(v) {
|
|
|
160
174
|
return Number.isFinite(n) ? n : null;
|
|
161
175
|
}
|
|
162
176
|
function mapClientRow(row) {
|
|
177
|
+
const redirectUris = parseJsonStringArray(row.redirect_uris ?? row.redirectUris);
|
|
178
|
+
const storedApplicationType = row.application_type ?? row.applicationType;
|
|
163
179
|
return {
|
|
164
180
|
clientId: row.client_id ?? row.clientId,
|
|
165
181
|
clientName: row.client_name ?? row.clientName ?? null,
|
|
166
|
-
redirectUris
|
|
182
|
+
redirectUris,
|
|
167
183
|
grantTypes: parseJsonStringArray(row.grant_types ?? row.grantTypes, [
|
|
168
184
|
"authorization_code",
|
|
169
185
|
"refresh_token",
|
|
170
186
|
]),
|
|
171
187
|
responseTypes: parseJsonStringArray(row.response_types ?? row.responseTypes, ["code"]),
|
|
172
188
|
tokenEndpointAuthMethod: row.token_endpoint_auth_method ?? row.tokenEndpointAuthMethod ?? "none",
|
|
189
|
+
applicationType: storedApplicationType === "native" || storedApplicationType === "web"
|
|
190
|
+
? storedApplicationType
|
|
191
|
+
: applicationTypeForRedirectUris(redirectUris),
|
|
173
192
|
createdAt: numOrNull(row.created_at ?? row.createdAt),
|
|
174
193
|
};
|
|
175
194
|
}
|
|
@@ -235,8 +254,9 @@ export async function registerOAuthClient(params) {
|
|
|
235
254
|
? params.responseTypes
|
|
236
255
|
: ["code"];
|
|
237
256
|
const tokenEndpointAuthMethod = params.tokenEndpointAuthMethod || "none";
|
|
257
|
+
const applicationType = params.applicationType ?? "web";
|
|
238
258
|
await client.execute({
|
|
239
|
-
sql: `INSERT INTO mcp_oauth_clients (client_id, client_name, redirect_uris, grant_types, response_types, token_endpoint_auth_method, created_at) VALUES (?, ?, ?, ?, ?, ?, ?)`,
|
|
259
|
+
sql: `INSERT INTO mcp_oauth_clients (client_id, client_name, redirect_uris, grant_types, response_types, token_endpoint_auth_method, application_type, created_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?)`,
|
|
240
260
|
args: [
|
|
241
261
|
clientId,
|
|
242
262
|
params.clientName ?? null,
|
|
@@ -244,6 +264,7 @@ export async function registerOAuthClient(params) {
|
|
|
244
264
|
JSON.stringify(grantTypes),
|
|
245
265
|
JSON.stringify(responseTypes),
|
|
246
266
|
tokenEndpointAuthMethod,
|
|
267
|
+
applicationType,
|
|
247
268
|
now,
|
|
248
269
|
],
|
|
249
270
|
});
|
|
@@ -254,6 +275,7 @@ export async function registerOAuthClient(params) {
|
|
|
254
275
|
grantTypes,
|
|
255
276
|
responseTypes,
|
|
256
277
|
tokenEndpointAuthMethod,
|
|
278
|
+
applicationType,
|
|
257
279
|
createdAt: now,
|
|
258
280
|
};
|
|
259
281
|
}
|
|
@@ -41,16 +41,16 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
41
41
|
thumbsUpRate: number;
|
|
42
42
|
avgEvalScore: number;
|
|
43
43
|
} | {
|
|
44
|
+
error?: undefined;
|
|
44
45
|
summary: import("./types.js").TraceSummary;
|
|
45
46
|
spans: import("./types.js").TraceSpan[];
|
|
46
47
|
id?: undefined;
|
|
47
|
-
error?: undefined;
|
|
48
48
|
ok?: undefined;
|
|
49
49
|
} | {
|
|
50
|
+
error?: undefined;
|
|
50
51
|
summary?: undefined;
|
|
51
52
|
spans?: undefined;
|
|
52
53
|
id: string;
|
|
53
|
-
error?: undefined;
|
|
54
54
|
ok?: undefined;
|
|
55
55
|
} | {
|
|
56
56
|
summary?: undefined;
|
|
@@ -59,10 +59,10 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
59
59
|
error: any;
|
|
60
60
|
ok?: undefined;
|
|
61
61
|
} | {
|
|
62
|
+
error?: undefined;
|
|
62
63
|
summary?: undefined;
|
|
63
64
|
spans?: undefined;
|
|
64
65
|
id?: undefined;
|
|
65
|
-
error?: undefined;
|
|
66
66
|
ok: boolean;
|
|
67
67
|
}>>;
|
|
68
68
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -87,7 +87,8 @@ function emitLlmGenerationTrackingEvent(args) {
|
|
|
87
87
|
delegated: args.delegation ? true : undefined,
|
|
88
88
|
delegation_protocol: args.delegation?.protocol,
|
|
89
89
|
caller_app: args.delegation?.callerApp,
|
|
90
|
-
|
|
90
|
+
delegation_task_id: args.delegation?.taskId,
|
|
91
|
+
a2a_task_id: args.delegation?.protocol === "a2a" ? args.delegation.taskId : undefined,
|
|
91
92
|
parent_run_id: args.delegation?.parentRunId,
|
|
92
93
|
parent_turn_id: args.delegation?.parentTurnId,
|
|
93
94
|
model_selection_source: args.modelSelectionSource,
|
|
@@ -462,9 +462,37 @@ const PROVIDER_CONFIGS = {
|
|
|
462
462
|
],
|
|
463
463
|
notes: [
|
|
464
464
|
"For broad corpus work, call /calls/extensive with provider-api-request and stageAs/saveToFile. Gong returns the next cursor at records.cursor and expects the next cursor in the POST body at cursor, so use pagination { nextCursorPath: 'records.cursor', cursorBodyPath: 'cursor' } for stageAs or fetchAllPages { cursorPath: 'records.cursor', cursorBodyPath: 'cursor' } for saveToFile.",
|
|
465
|
-
"
|
|
465
|
+
"The public Gong REST API does not expose an arbitrary transcript-text filter. Use configured keyword tracker results from /calls/extensive when they cover the requested term; otherwise batch transcripts with POST /calls/transcript and body { filter: { callIds: [...] } } after narrowing or staging call ids.",
|
|
466
466
|
],
|
|
467
467
|
corpusRecipes: [
|
|
468
|
+
{
|
|
469
|
+
label: "Stage Gong calls with configured keyword tracker hits",
|
|
470
|
+
useWhen: "Use when the requested term or phrase already exists as a Gong keyword tracker and the answer can use tracker matches instead of arbitrary transcript-text search.",
|
|
471
|
+
workflow: [
|
|
472
|
+
"Call /calls/extensive with the narrowest date, workspace, or owner filters available and contentSelector.exposedFields.content.trackers = true.",
|
|
473
|
+
"Stage the calls pages with provider-api-request stageAs or saveToFile; use the POST-body cursor at records.cursor for complete pagination.",
|
|
474
|
+
"Use query-staged-dataset or a Data Program to flatten content.trackers, filter by tracker id/name/phrase, and aggregate counts or occurrences.",
|
|
475
|
+
"Tracker results are provider-indexed evidence for configured trackers, not an arbitrary transcript search. For an unconfigured term, use Gong native Search when connected or the transcript batch recipe below.",
|
|
476
|
+
],
|
|
477
|
+
request: {
|
|
478
|
+
method: "POST",
|
|
479
|
+
path: "/calls/extensive",
|
|
480
|
+
body: {
|
|
481
|
+
filter: { fromDateTime: "<iso-date-time>" },
|
|
482
|
+
contentSelector: {
|
|
483
|
+
exposedFields: {
|
|
484
|
+
content: { trackers: true, trackerOccurrences: true },
|
|
485
|
+
},
|
|
486
|
+
},
|
|
487
|
+
},
|
|
488
|
+
},
|
|
489
|
+
pagination: {
|
|
490
|
+
itemsPath: "calls",
|
|
491
|
+
nextCursorPath: "records.cursor",
|
|
492
|
+
cursorBodyPath: "cursor",
|
|
493
|
+
maxPages: 200,
|
|
494
|
+
},
|
|
495
|
+
},
|
|
468
496
|
{
|
|
469
497
|
label: "Batch-search Gong call transcripts from staged call ids",
|
|
470
498
|
useWhen: "Use when the user asks to search, count, or prove absence across Gong transcript text for a bounded cohort of call ids.",
|
package/dist/secrets/routes.d.ts
CHANGED
|
@@ -37,17 +37,17 @@ export declare function createWriteSecretHandler(): import("h3").EventHandlerWit
|
|
|
37
37
|
status?: undefined;
|
|
38
38
|
ok?: undefined;
|
|
39
39
|
} | {
|
|
40
|
+
error?: undefined;
|
|
40
41
|
ok: boolean;
|
|
41
42
|
status: string;
|
|
42
|
-
error?: undefined;
|
|
43
43
|
} | {
|
|
44
44
|
error: string;
|
|
45
45
|
removed?: undefined;
|
|
46
46
|
ok?: undefined;
|
|
47
47
|
} | {
|
|
48
|
+
error?: undefined;
|
|
48
49
|
ok: boolean;
|
|
49
50
|
removed: boolean;
|
|
50
|
-
error?: undefined;
|
|
51
51
|
}>>;
|
|
52
52
|
/**
|
|
53
53
|
* POST /_agent-native/secrets/:key/test — re-run the validator against the
|
|
@@ -58,13 +58,13 @@ export declare function createTestSecretHandler(): import("h3").EventHandlerWith
|
|
|
58
58
|
note?: undefined;
|
|
59
59
|
ok?: undefined;
|
|
60
60
|
} | {
|
|
61
|
+
error?: undefined;
|
|
61
62
|
ok: boolean;
|
|
62
63
|
note?: undefined;
|
|
63
|
-
error?: undefined;
|
|
64
64
|
} | {
|
|
65
|
+
error?: undefined;
|
|
65
66
|
ok: boolean;
|
|
66
67
|
note: string;
|
|
67
|
-
error?: undefined;
|
|
68
68
|
} | {
|
|
69
69
|
note?: undefined;
|
|
70
70
|
ok: boolean;
|
|
@@ -95,12 +95,12 @@ export interface AdHocSecretPayload {
|
|
|
95
95
|
export declare function createAdHocSecretHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<AdHocSecretPayload[] | {
|
|
96
96
|
error: string;
|
|
97
97
|
} | {
|
|
98
|
+
error?: undefined;
|
|
98
99
|
ok: boolean;
|
|
99
100
|
key: string;
|
|
100
|
-
error?: undefined;
|
|
101
101
|
} | {
|
|
102
|
+
error?: undefined;
|
|
102
103
|
ok: boolean;
|
|
103
104
|
removed: boolean;
|
|
104
|
-
error?: undefined;
|
|
105
105
|
}>>;
|
|
106
106
|
//# sourceMappingURL=routes.d.ts.map
|
|
@@ -3,6 +3,8 @@ import { type VerifyResult } from "./short-lived-token.js";
|
|
|
3
3
|
export { AGENT_ACCESS_PARAM, DEFAULT_AGENT_ACCESS_TTL_SECONDS, appendAgentAccessParam, buildAgentAccessApiUrl, buildAgentAccessUrl, normalizeAgentAccessBasePath, normalizeAgentAccessOrigin, scopedAgentAccessResourceId, toAgentAccessUrl, type AgentAccessApiUrlOptions, type AgentAccessResourceScope, type AgentAccessUrlOptions, } from "../shared/agent-access.js";
|
|
4
4
|
export interface ScopedAgentAccessTokenOptions extends AgentAccessResourceScope {
|
|
5
5
|
viewerEmail?: string;
|
|
6
|
+
/** Display name of the agent the link is for. Signed, but display-only. */
|
|
7
|
+
agentLabel?: string;
|
|
6
8
|
ttlSeconds?: number;
|
|
7
9
|
}
|
|
8
10
|
export interface ScopedAgentAccessGrant {
|
|
@@ -10,7 +12,7 @@ export interface ScopedAgentAccessGrant {
|
|
|
10
12
|
expiresAt: string;
|
|
11
13
|
ttlSeconds: number;
|
|
12
14
|
}
|
|
13
|
-
export declare function signScopedAgentAccessToken({ resourceKind, resourceId, viewerEmail, ttlSeconds, }: ScopedAgentAccessTokenOptions): string;
|
|
15
|
+
export declare function signScopedAgentAccessToken({ resourceKind, resourceId, viewerEmail, agentLabel, ttlSeconds, }: ScopedAgentAccessTokenOptions): string;
|
|
14
16
|
export declare function verifyScopedAgentAccessToken(token: string, scope: AgentAccessResourceScope): VerifyResult;
|
|
15
17
|
export declare function createScopedAgentAccessGrant(options: ScopedAgentAccessTokenOptions): ScopedAgentAccessGrant;
|
|
16
18
|
//# sourceMappingURL=agent-access.d.ts.map
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { DEFAULT_AGENT_ACCESS_TTL_SECONDS, scopedAgentAccessResourceId, } from "../shared/agent-access.js";
|
|
2
2
|
import { signShortLivedToken, verifyShortLivedToken, } from "./short-lived-token.js";
|
|
3
3
|
export { AGENT_ACCESS_PARAM, DEFAULT_AGENT_ACCESS_TTL_SECONDS, appendAgentAccessParam, buildAgentAccessApiUrl, buildAgentAccessUrl, normalizeAgentAccessBasePath, normalizeAgentAccessOrigin, scopedAgentAccessResourceId, toAgentAccessUrl, } from "../shared/agent-access.js";
|
|
4
|
-
export function signScopedAgentAccessToken({ resourceKind, resourceId, viewerEmail, ttlSeconds = DEFAULT_AGENT_ACCESS_TTL_SECONDS, }) {
|
|
4
|
+
export function signScopedAgentAccessToken({ resourceKind, resourceId, viewerEmail, agentLabel, ttlSeconds = DEFAULT_AGENT_ACCESS_TTL_SECONDS, }) {
|
|
5
5
|
return signShortLivedToken({
|
|
6
6
|
resourceId: scopedAgentAccessResourceId(resourceKind, resourceId),
|
|
7
7
|
viewerEmail,
|
|
8
|
+
agentLabel,
|
|
8
9
|
ttlSeconds,
|
|
9
10
|
});
|
|
10
11
|
}
|
|
@@ -16,6 +16,7 @@ export declare function createTeamTools(deps: {
|
|
|
16
16
|
getEngine: () => AgentEngine;
|
|
17
17
|
getModel: () => string;
|
|
18
18
|
getParentThreadId: () => string;
|
|
19
|
+
getParentRunId?: () => string;
|
|
19
20
|
getSend: () => ((event: import("../../agent/types.js").AgentChatEvent) => void) | null;
|
|
20
21
|
}): Record<string, ActionEntry>;
|
|
21
22
|
//# sourceMappingURL=browser-team-tools.d.ts.map
|
|
@@ -316,7 +316,7 @@ export function createTeamTools(deps) {
|
|
|
316
316
|
return {
|
|
317
317
|
"agent-teams": {
|
|
318
318
|
tool: {
|
|
319
|
-
description: "Manage background
|
|
319
|
+
description: "Manage background tasks that run in their own task thread. Use action 'spawn' to start one, 'status' to check progress, 'read-result' to get a finished task's output, 'send' to message a running task, or 'list' to see all tasks. A successful spawn only means the task started and is running; do not report it as finished until status/read-result shows a terminal status. This is a background task, not a source-control branch.",
|
|
320
320
|
parameters: {
|
|
321
321
|
type: "object",
|
|
322
322
|
properties: {
|
|
@@ -335,7 +335,7 @@ export function createTeamTools(deps) {
|
|
|
335
335
|
},
|
|
336
336
|
name: {
|
|
337
337
|
type: "string",
|
|
338
|
-
description: "(spawn) Short name for the
|
|
338
|
+
description: "(spawn) Short name for the background task (e.g. 'Research', 'Draft email'). If omitted, derived from the task.",
|
|
339
339
|
},
|
|
340
340
|
agent: {
|
|
341
341
|
type: "string",
|
|
@@ -402,6 +402,7 @@ export function createTeamTools(deps) {
|
|
|
402
402
|
model: selectedModel,
|
|
403
403
|
name: selectedName || undefined,
|
|
404
404
|
parentThreadId: deps.getParentThreadId(),
|
|
405
|
+
parentRunId: deps.getParentRunId?.(),
|
|
405
406
|
parentSend: (event) => {
|
|
406
407
|
if (capturedSend)
|
|
407
408
|
capturedSend(event);
|
|
@@ -414,7 +415,7 @@ export function createTeamTools(deps) {
|
|
|
414
415
|
status: task.status,
|
|
415
416
|
parentThreadId: task.parentThreadId,
|
|
416
417
|
state: "launched_pending_completion",
|
|
417
|
-
message: "
|
|
418
|
+
message: "Background task launched in its own task thread and is still running. Use status or read-result later; do not describe this task as completed from the spawn response alone.",
|
|
418
419
|
description: task.description,
|
|
419
420
|
name: task.name ?? selectedName,
|
|
420
421
|
});
|
|
@@ -483,7 +484,7 @@ export function createTeamTools(deps) {
|
|
|
483
484
|
const { listTasks } = await import("../agent-teams.js");
|
|
484
485
|
const tasks = await listTasks();
|
|
485
486
|
if (tasks.length === 0) {
|
|
486
|
-
return "No
|
|
487
|
+
return "No background tasks.";
|
|
487
488
|
}
|
|
488
489
|
return JSON.stringify(tasks.map((t) => ({
|
|
489
490
|
taskId: t.taskId,
|
|
@@ -44,8 +44,8 @@ You can search and restore previous chat conversations using \`chat-history\`:
|
|
|
44
44
|
When the user asks to find a previous conversation, use \`chat-history\` with action "search" first to find matching threads, then action "open" to restore the one they want.`,
|
|
45
45
|
"agent-teams": `### Agent Teams — Orchestration
|
|
46
46
|
|
|
47
|
-
You can delegate to background
|
|
48
|
-
- \`agent-teams\` (action: "spawn") — Launch a
|
|
47
|
+
You can delegate to background tasks with the \`agent-teams\` tool. Call them background tasks or sub-agent tasks, never branches; reserve "branch" for source-control or Builder code handoffs:
|
|
48
|
+
- \`agent-teams\` (action: "spawn") — Launch a background task on a self-contained job. It runs in its own task thread with a clean context while you stay available; a live preview card appears in the chat. The spawn result confirms launch only, not completion. Optionally pass a custom agent profile from \`agents/*.md\` via the \`agent\` parameter.
|
|
49
49
|
- \`agent-teams\` (action: "status") — Check a running sub-agent's progress.
|
|
50
50
|
- \`agent-teams\` (action: "read-result") — Read a finished sub-agent's output.
|
|
51
51
|
- \`agent-teams\` (action: "send") — Message a running sub-agent.
|
|
@@ -2086,6 +2086,7 @@ export function createAgentChatPlugin(options) {
|
|
|
2086
2086
|
},
|
|
2087
2087
|
getModel: () => getRequestRunContext()?.model ?? resolvedModel,
|
|
2088
2088
|
getParentThreadId: () => getRequestRunContext()?.threadId ?? "",
|
|
2089
|
+
getParentRunId: () => getRequestRunContext()?.runId ?? "",
|
|
2089
2090
|
getSend: () => {
|
|
2090
2091
|
// Return the send for the current run's thread
|
|
2091
2092
|
const threadId = getRequestRunContext()?.threadId ?? "";
|
|
@@ -2517,12 +2518,14 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
2517
2518
|
}
|
|
2518
2519
|
},
|
|
2519
2520
|
onRunPrepared: persistSubmittedUserMessage,
|
|
2520
|
-
onRunStart: async (send, threadId) => {
|
|
2521
|
+
onRunStart: async (send, threadId, runId) => {
|
|
2521
2522
|
await recordPreRunGitStatus(threadId);
|
|
2522
2523
|
_runSendByThread.set(threadId, send);
|
|
2523
2524
|
const runCtx = ensureRequestRunContext();
|
|
2524
|
-
if (runCtx)
|
|
2525
|
+
if (runCtx) {
|
|
2525
2526
|
runCtx.threadId = threadId;
|
|
2527
|
+
runCtx.runId = runId;
|
|
2528
|
+
}
|
|
2526
2529
|
},
|
|
2527
2530
|
onRunComplete: async (run, threadId) => {
|
|
2528
2531
|
if (threadId)
|
|
@@ -2562,12 +2565,14 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
2562
2565
|
}
|
|
2563
2566
|
},
|
|
2564
2567
|
onRunPrepared: persistSubmittedUserMessage,
|
|
2565
|
-
onRunStart: async (send, threadId) => {
|
|
2568
|
+
onRunStart: async (send, threadId, runId) => {
|
|
2566
2569
|
await recordPreRunGitStatus(threadId);
|
|
2567
2570
|
_runSendByThread.set(threadId, send);
|
|
2568
2571
|
const runCtx = ensureRequestRunContext();
|
|
2569
|
-
if (runCtx)
|
|
2572
|
+
if (runCtx) {
|
|
2570
2573
|
runCtx.threadId = threadId;
|
|
2574
|
+
runCtx.runId = runId;
|
|
2575
|
+
}
|
|
2571
2576
|
},
|
|
2572
2577
|
onRunComplete: async (run, threadId) => {
|
|
2573
2578
|
if (threadId)
|
|
@@ -2710,12 +2715,14 @@ Non-code requests are still fine on this surface: read data, navigate the UI, su
|
|
|
2710
2715
|
}
|
|
2711
2716
|
},
|
|
2712
2717
|
onRunPrepared: persistSubmittedUserMessage,
|
|
2713
|
-
onRunStart: async (send, threadId) => {
|
|
2718
|
+
onRunStart: async (send, threadId, runId) => {
|
|
2714
2719
|
await recordPreRunGitStatus(threadId);
|
|
2715
2720
|
_runSendByThread.set(threadId, send);
|
|
2716
2721
|
const runCtx = ensureRequestRunContext();
|
|
2717
|
-
if (runCtx)
|
|
2722
|
+
if (runCtx) {
|
|
2718
2723
|
runCtx.threadId = threadId;
|
|
2724
|
+
runCtx.runId = runId;
|
|
2725
|
+
}
|
|
2719
2726
|
},
|
|
2720
2727
|
onRunComplete: async (run, threadId) => {
|
|
2721
2728
|
if (threadId)
|
|
@@ -27,11 +27,11 @@ export declare function resolveAgentEngineApiKeyWriteTarget(event: H3Event, scop
|
|
|
27
27
|
export declare function createAgentEngineApiKeyHandler(): import("h3").EventHandlerWithFetch<import("h3").EventHandlerRequest, Promise<{
|
|
28
28
|
error: any;
|
|
29
29
|
} | {
|
|
30
|
+
error?: undefined;
|
|
30
31
|
ok: boolean;
|
|
31
32
|
key: string;
|
|
32
33
|
baseUrlKey?: string;
|
|
33
34
|
scope: AgentEngineApiKeyScope;
|
|
34
|
-
error?: undefined;
|
|
35
35
|
}>>;
|
|
36
36
|
export {};
|
|
37
37
|
//# sourceMappingURL=agent-engine-api-key-route.d.ts.map
|
|
@@ -27,6 +27,8 @@ export interface AgentTeamRunPayload {
|
|
|
27
27
|
agentRef?: string;
|
|
28
28
|
/** Parent thread to post a completion recap to. */
|
|
29
29
|
parentThreadId?: string;
|
|
30
|
+
/** Parent run that launched this durable background task. */
|
|
31
|
+
parentRunId?: string;
|
|
30
32
|
/** Display name for the sub-agent tab. */
|
|
31
33
|
name?: string;
|
|
32
34
|
/** Logical-turn id, stable across continuation chunks so durable assistant
|
|
@@ -194,6 +194,8 @@ export interface SpawnTaskOptions {
|
|
|
194
194
|
parentSend: (event: AgentChatEvent) => void;
|
|
195
195
|
/** Parent thread ID — used to auto-respond when the sub-agent finishes */
|
|
196
196
|
parentThreadId?: string;
|
|
197
|
+
/** Parent run ID used to correlate child telemetry after durable handoff. */
|
|
198
|
+
parentRunId?: string;
|
|
197
199
|
/** Display name for the sub-agent tab (carried into the dispatch payload). */
|
|
198
200
|
name?: string;
|
|
199
201
|
/**
|
|
@@ -982,6 +982,7 @@ export async function spawnTask(opts) {
|
|
|
982
982
|
instructions: opts.instructions,
|
|
983
983
|
model: opts.model,
|
|
984
984
|
...(opts.parentThreadId ? { parentThreadId: opts.parentThreadId } : {}),
|
|
985
|
+
...(opts.parentRunId ? { parentRunId: opts.parentRunId } : {}),
|
|
985
986
|
...(opts.name ? { name: opts.name } : {}),
|
|
986
987
|
// Stable across continuation chunks so the durable assistant message folds.
|
|
987
988
|
turnId: runId,
|
|
@@ -1309,7 +1310,7 @@ export async function processAgentTeamRun(opts) {
|
|
|
1309
1310
|
// cap is hit. Fall back to depth 1 for legacy tasks persisted
|
|
1310
1311
|
// before delegationDepth was tracked.
|
|
1311
1312
|
() => runWithDelegationDepth(task.delegationDepth ?? 1, async () => {
|
|
1312
|
-
|
|
1313
|
+
const agentLoopOpts = {
|
|
1313
1314
|
engine: config.engine,
|
|
1314
1315
|
model: config.model,
|
|
1315
1316
|
// Agent-team runs are delegated turns too. Keep their
|
|
@@ -1328,7 +1329,49 @@ export async function processAgentTeamRun(opts) {
|
|
|
1328
1329
|
send: wrappedSend,
|
|
1329
1330
|
signal,
|
|
1330
1331
|
finalResponseGuard: createTaskMessageFinalGuard(opts.taskId),
|
|
1331
|
-
}
|
|
1332
|
+
};
|
|
1333
|
+
let instrumented = false;
|
|
1334
|
+
try {
|
|
1335
|
+
const { getObservabilityConfig, instrumentAgentLoop } = await import("../observability/traces.js");
|
|
1336
|
+
const observabilityConfig = await getObservabilityConfig();
|
|
1337
|
+
if (observabilityConfig.enabled) {
|
|
1338
|
+
instrumented = true;
|
|
1339
|
+
chunkUsage = await instrumentAgentLoop({
|
|
1340
|
+
runAgentLoop,
|
|
1341
|
+
loopOpts: agentLoopOpts,
|
|
1342
|
+
runId,
|
|
1343
|
+
threadId: task.threadId,
|
|
1344
|
+
userId: ownerEmail || null,
|
|
1345
|
+
config: observabilityConfig,
|
|
1346
|
+
metadata: {
|
|
1347
|
+
source: "agent_team",
|
|
1348
|
+
agent_team_task_id: opts.taskId,
|
|
1349
|
+
continuation_count: claimed.continuationCount,
|
|
1350
|
+
...(payload.parentThreadId
|
|
1351
|
+
? { parent_thread_id: payload.parentThreadId }
|
|
1352
|
+
: {}),
|
|
1353
|
+
},
|
|
1354
|
+
delegation: {
|
|
1355
|
+
protocol: "agent-team",
|
|
1356
|
+
callerApp: "agent-teams",
|
|
1357
|
+
taskId: opts.taskId,
|
|
1358
|
+
...(payload.parentRunId
|
|
1359
|
+
? { parentRunId: payload.parentRunId }
|
|
1360
|
+
: {}),
|
|
1361
|
+
},
|
|
1362
|
+
});
|
|
1363
|
+
}
|
|
1364
|
+
}
|
|
1365
|
+
catch (error) {
|
|
1366
|
+
// Configuration is best effort. Once the wrapper starts,
|
|
1367
|
+
// preserve its errors so a failed child is not reported
|
|
1368
|
+
// as a successful run with missing telemetry.
|
|
1369
|
+
if (instrumented)
|
|
1370
|
+
throw error;
|
|
1371
|
+
}
|
|
1372
|
+
if (!instrumented) {
|
|
1373
|
+
chunkUsage = await runAgentLoop(agentLoopOpts);
|
|
1374
|
+
}
|
|
1332
1375
|
}));
|
|
1333
1376
|
}, async (run) => {
|
|
1334
1377
|
clearInterval(heartbeat);
|
|
@@ -45,6 +45,8 @@ export interface RequestRunContext {
|
|
|
45
45
|
userApiKey?: string;
|
|
46
46
|
/** Thread ID for the current run (set by onRunStart). */
|
|
47
47
|
threadId?: string;
|
|
48
|
+
/** Run ID for the current run (set by onRunStart). */
|
|
49
|
+
runId?: string;
|
|
48
50
|
/** System prompt actually sent to the model for this run. */
|
|
49
51
|
systemPrompt?: string;
|
|
50
52
|
/** Engine instance for this run (set by onEngineResolved). */
|
|
@@ -26,6 +26,12 @@ export interface ShortLivedTokenClaims {
|
|
|
26
26
|
resourceId: string;
|
|
27
27
|
/** Optional viewer email for audit / analytics — not used for authorisation. */
|
|
28
28
|
viewerEmail?: string;
|
|
29
|
+
/**
|
|
30
|
+
* Optional display name of the agent the token was minted for. Signed so a
|
|
31
|
+
* reader cannot rename itself, but audit/display-only like `viewerEmail` —
|
|
32
|
+
* never consult it for authorisation.
|
|
33
|
+
*/
|
|
34
|
+
agentLabel?: string;
|
|
29
35
|
/** Override default TTL (seconds). */
|
|
30
36
|
ttlSeconds?: number;
|
|
31
37
|
}
|
|
@@ -36,6 +42,7 @@ export interface ShortLivedTokenClaims {
|
|
|
36
42
|
export type VerifyResult = {
|
|
37
43
|
ok: true;
|
|
38
44
|
viewerEmail?: string;
|
|
45
|
+
agentLabel?: string;
|
|
39
46
|
} | {
|
|
40
47
|
ok: false;
|
|
41
48
|
reason: string;
|
|
@@ -65,6 +65,8 @@ export function signShortLivedToken(claims) {
|
|
|
65
65
|
};
|
|
66
66
|
if (claims.viewerEmail)
|
|
67
67
|
payload.viewerEmail = claims.viewerEmail;
|
|
68
|
+
if (claims.agentLabel)
|
|
69
|
+
payload.agentLabel = claims.agentLabel;
|
|
68
70
|
const payloadStr = base64UrlEncode(JSON.stringify(payload));
|
|
69
71
|
const sig = base64UrlEncode(crypto.createHmac("sha256", getSigningKey()).update(payloadStr).digest());
|
|
70
72
|
return `${payloadStr}.${sig}`;
|
|
@@ -117,7 +119,11 @@ export function verifyShortLivedToken(token, expectedResourceId) {
|
|
|
117
119
|
if (claims.resourceId !== expectedResourceId) {
|
|
118
120
|
return { ok: false, reason: "wrong_resource" };
|
|
119
121
|
}
|
|
120
|
-
return {
|
|
122
|
+
return {
|
|
123
|
+
ok: true,
|
|
124
|
+
viewerEmail: claims.viewerEmail,
|
|
125
|
+
agentLabel: claims.agentLabel,
|
|
126
|
+
};
|
|
121
127
|
}
|
|
122
128
|
// ── Realtime subscribe tokens ────────────────────────────────────────────────
|
|
123
129
|
//
|
|
@@ -257,6 +257,24 @@ function removeDocumentCsp(headers) {
|
|
|
257
257
|
headers.delete("content-security-policy");
|
|
258
258
|
headers.delete("content-security-policy-report-only");
|
|
259
259
|
}
|
|
260
|
+
/**
|
|
261
|
+
* Render an error message safely as a `text/plain` body.
|
|
262
|
+
*
|
|
263
|
+
* Vite ids its virtual modules with a leading NUL (`\0virtual:react-router/…`),
|
|
264
|
+
* and those ids travel verbatim inside module-resolution error messages. One raw
|
|
265
|
+
* NUL is enough for curl to refuse to print the response as text, hiding the only
|
|
266
|
+
* line that says what broke. Escape the control bytes rather than deleting them:
|
|
267
|
+
* the NUL is part of the real resolved id, so a reader who greps for it or pastes
|
|
268
|
+
* it into a bug report must be able to see that it is there.
|
|
269
|
+
*/
|
|
270
|
+
function textSafeErrorMessage(err) {
|
|
271
|
+
const message = String(err?.message ?? err);
|
|
272
|
+
// C0 controls except tab, newline, and carriage return, which are real formatting.
|
|
273
|
+
return message.replace(/[\u0000-\u0008\u000b\u000c\u000e-\u001f]/g, (char) => {
|
|
274
|
+
const code = char.codePointAt(0) ?? 0;
|
|
275
|
+
return code === 0 ? "\\0" : `\\x${code.toString(16).padStart(2, "0")}`;
|
|
276
|
+
});
|
|
277
|
+
}
|
|
260
278
|
function isFrameworkOrAssetPath(pathname) {
|
|
261
279
|
return (isMcpPublicPath(pathname) ||
|
|
262
280
|
pathname.startsWith("/.well-known/") ||
|
|
@@ -368,7 +386,7 @@ export function createH3SSRHandler(getBuild) {
|
|
|
368
386
|
const isProd = process.env.NODE_ENV === "production";
|
|
369
387
|
const body = isProd
|
|
370
388
|
? "Internal Server Error"
|
|
371
|
-
: `Internal Server Error: ${err
|
|
389
|
+
: `Internal Server Error: ${textSafeErrorMessage(err)}`;
|
|
372
390
|
return new Response(body, {
|
|
373
391
|
status: 500,
|
|
374
392
|
headers: { "content-type": "text/plain" },
|