@agent-native/core 0.219.0 → 0.220.0-nightly-20261023212848
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/action.d.ts +23 -3
- package/dist/action.js +58 -3
- package/dist/agent/abort-reasons.d.ts +6 -0
- package/dist/agent/abort-reasons.js +6 -0
- package/dist/agent/execution-fence.js +5 -1
- package/dist/agent/production-agent.d.ts +22 -6
- package/dist/agent/production-agent.js +136 -37
- package/dist/agent/run-manager.js +92 -44
- package/dist/agent/run-store.d.ts +1 -0
- package/dist/agent/run-store.js +260 -31
- package/dist/agent/run-terminal-tracking.d.ts +29 -0
- package/dist/agent/run-terminal-tracking.js +56 -0
- package/dist/agent/run-turn-id-header.d.ts +9 -0
- package/dist/agent/run-turn-id-header.js +13 -0
- package/dist/agent/types.d.ts +11 -0
- package/dist/chat-threads/store.d.ts +23 -6
- package/dist/chat-threads/store.js +119 -36
- package/dist/cli/amplify-stream.js +1 -1
- package/dist/client/agent-chat/index.d.ts +2 -1
- package/dist/client/agent-chat/index.js +2 -1
- package/dist/client/agent-chat.d.ts +2 -0
- package/dist/client/agent-chat.js +31 -5
- package/dist/client/chat/agentkit-agent-native.js +8 -1
- package/dist/client/chat/agentkit-protocol.js +7 -1
- package/dist/client/chat/run-outcome-telemetry.js +1 -0
- package/dist/client/chat/run-outcome.d.ts +5 -0
- package/dist/client/chat/runtime.d.ts +34 -1
- package/dist/client/chat/runtime.js +96 -12
- package/dist/client/chat/turn-submitted-telemetry.d.ts +4 -0
- package/dist/client/chat/turn-submitted-telemetry.js +39 -0
- package/dist/client/chat/turn-submitted.d.ts +39 -0
- package/dist/client/chat/turn-submitted.js +16 -0
- package/dist/client/route-chunk-recovery.d.ts +3 -8
- package/dist/client/route-chunk-recovery.js +11 -9
- package/dist/client/use-chat-thread-list.d.ts +2 -0
- package/dist/client/use-chat-thread-list.js +48 -2
- package/dist/client/use-chat-threads.d.ts +13 -0
- package/dist/client/use-chat-threads.js +59 -4
- package/dist/collab/routes.d.ts +2 -2
- package/dist/db/client.d.ts +1 -0
- package/dist/db/client.js +28 -18
- package/dist/db/schema-snapshot.generated.js +5 -0
- package/dist/identity/rekey.d.ts +2 -0
- package/dist/identity/rekey.js +19 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/mcp/agent-connected.d.ts +5 -0
- package/dist/mcp/agent-connected.js +10 -3
- package/dist/mcp/analytics.d.ts +14 -1
- package/dist/mcp/analytics.js +54 -2
- package/dist/mcp/embed-app.js +2 -1
- package/dist/mcp/oauth-route.js +56 -1
- package/dist/notifications/routes.d.ts +1 -1
- package/dist/observability/routes.d.ts +7 -7
- package/dist/observability/traces.d.ts +2 -0
- package/dist/observability/traces.js +11 -2
- package/dist/provider-api/actions/custom-provider-registration.d.ts +16 -16
- package/dist/provider-api/actions/provider-api.d.ts +13 -13
- package/dist/provider-api/corpus-jobs.d.ts +2 -2
- package/dist/resources/handlers.d.ts +1 -1
- package/dist/review/index.d.ts +1 -1
- package/dist/review/index.js +1 -1
- package/dist/review/suggestions/actions.js +25 -17
- package/dist/review/suggestions/store.d.ts +14 -1
- package/dist/review/suggestions/store.js +16 -3
- package/dist/review/suggestions/types.d.ts +15 -1
- package/dist/scripts/chat/search-chats.js +14 -2
- package/dist/server/agent-chat/browser-team-tools.js +39 -6
- package/dist/server/agent-chat/script-entries.js +44 -9
- package/dist/server/agent-chat-plugin.d.ts +2 -0
- package/dist/server/agent-chat-plugin.js +66 -16
- package/dist/server/agent-engine-api-key-route.d.ts +1 -1
- package/dist/server/agent-engine-default-model-route.d.ts +1 -1
- package/dist/server/first-touch-route.d.ts +2 -2
- package/dist/shared/route-chunk-recovery-bootstrap.d.ts +9 -0
- package/dist/shared/route-chunk-recovery-bootstrap.js +25 -0
- package/dist/sharing/actions/list-resource-shares.d.ts +1 -1
- package/dist/templates/chat/.agents/skills/actions/SKILL.md +1 -0
- package/dist/templates/default/.agents/skills/actions/SKILL.md +1 -0
- package/dist/templates/factory/.agents/skills/review-prs/SKILL.md +27 -3
- package/dist/templates/headless/.agents/skills/actions/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -0
- package/dist/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +12 -5
- package/dist/tracking/providers.js +3 -0
- package/dist/triggers/actions/manage-automation.d.ts +2 -2
- package/docs/content/external-agents.mdx +1 -1
- package/docs/content/mcp-apps.mdx +3 -3
- package/docs/content/mcp-protocol.mdx +1 -1
- package/docs/content/sharing.mdx +1 -0
- package/docs/content/template-assets-integrations.mdx +5 -3
- package/package.json +3 -3
- package/src/templates/chat/.agents/skills/actions/SKILL.md +1 -0
- package/src/templates/default/.agents/skills/actions/SKILL.md +1 -0
- package/src/templates/factory/.agents/skills/review-prs/SKILL.md +27 -3
- package/src/templates/headless/.agents/skills/actions/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/actions/SKILL.md +1 -0
- package/src/templates/workspace-core/.agents/skills/external-agents/references/mcp-apps-embedding.md +12 -5
|
@@ -27,43 +27,43 @@ export declare function createObservabilityHandler(): import("h3").EventHandlerW
|
|
|
27
27
|
thumbsUpRate: number;
|
|
28
28
|
avgEvalScore: number;
|
|
29
29
|
} | {
|
|
30
|
-
ok?: undefined;
|
|
31
30
|
error: string;
|
|
32
31
|
message: string;
|
|
33
32
|
summary?: undefined;
|
|
34
33
|
spans?: undefined;
|
|
35
|
-
} | {
|
|
36
|
-
error?: undefined;
|
|
37
34
|
ok?: undefined;
|
|
35
|
+
} | {
|
|
38
36
|
message?: undefined;
|
|
39
37
|
summary: import("./types.js").TraceSummary;
|
|
40
38
|
spans: import("./types.js").TraceSpan[];
|
|
41
|
-
} | {
|
|
42
39
|
error?: undefined;
|
|
43
40
|
ok?: undefined;
|
|
41
|
+
} | {
|
|
44
42
|
message?: undefined;
|
|
45
43
|
summary?: undefined;
|
|
46
44
|
spans?: undefined;
|
|
47
45
|
traceMissing: true;
|
|
48
46
|
id: string;
|
|
49
|
-
} | {
|
|
50
47
|
error?: undefined;
|
|
51
48
|
ok?: undefined;
|
|
49
|
+
} | {
|
|
52
50
|
message?: undefined;
|
|
53
51
|
summary?: undefined;
|
|
54
52
|
spans?: undefined;
|
|
55
53
|
traceMissing?: undefined;
|
|
56
54
|
id: string;
|
|
57
|
-
|
|
55
|
+
error?: undefined;
|
|
58
56
|
ok?: undefined;
|
|
57
|
+
} | {
|
|
59
58
|
message?: undefined;
|
|
60
59
|
summary?: undefined;
|
|
61
60
|
spans?: undefined;
|
|
62
61
|
error: any;
|
|
62
|
+
ok?: undefined;
|
|
63
63
|
} | {
|
|
64
|
-
error?: undefined;
|
|
65
64
|
message?: undefined;
|
|
66
65
|
summary?: undefined;
|
|
67
66
|
spans?: undefined;
|
|
67
|
+
error?: undefined;
|
|
68
68
|
ok: boolean;
|
|
69
69
|
}>>;
|
|
@@ -37,6 +37,8 @@ export declare function instrumentAgentLoop(opts: {
|
|
|
37
37
|
};
|
|
38
38
|
runId: string;
|
|
39
39
|
threadId: string | null;
|
|
40
|
+
/** The agent turn this run serves; omitted from events when unknown. */
|
|
41
|
+
turnId?: string;
|
|
40
42
|
userId: string | null;
|
|
41
43
|
config: ObservabilityConfig;
|
|
42
44
|
spanName?: string;
|
|
@@ -211,6 +211,7 @@ function emitLlmGenerationTrackingEvent(args) {
|
|
|
211
211
|
span_type: "llm_call",
|
|
212
212
|
run_id: args.runId,
|
|
213
213
|
thread_id: args.threadId,
|
|
214
|
+
turn_id: args.turnId,
|
|
214
215
|
parent_span_id: args.parentSpanId,
|
|
215
216
|
span_id: args.llmSpanId,
|
|
216
217
|
model: args.model,
|
|
@@ -357,7 +358,7 @@ export async function getObservabilityConfig() {
|
|
|
357
358
|
return { ...config, ...resolveInferredSentimentConfig(config) };
|
|
358
359
|
}
|
|
359
360
|
export async function instrumentAgentLoop(opts) {
|
|
360
|
-
const { runAgentLoop, loopOpts, runId, threadId, userId, config } = opts;
|
|
361
|
+
const { runAgentLoop, loopOpts, runId, threadId, turnId, userId, config } = opts;
|
|
361
362
|
const engineName = typeof loopOpts.engine?.name === "string"
|
|
362
363
|
? loopOpts.engine.name
|
|
363
364
|
: undefined;
|
|
@@ -752,8 +753,13 @@ export async function instrumentAgentLoop(opts) {
|
|
|
752
753
|
error_class: !isError
|
|
753
754
|
? null
|
|
754
755
|
: explicitError
|
|
755
|
-
? "tool_error"
|
|
756
|
+
? (event.errorClass ?? "tool_error")
|
|
756
757
|
: "legacy_inferred_error",
|
|
758
|
+
outcome: event.outcomeUnknown
|
|
759
|
+
? "unknown"
|
|
760
|
+
: event.completedSideEffect === true
|
|
761
|
+
? "completed"
|
|
762
|
+
: "no_side_effect",
|
|
757
763
|
});
|
|
758
764
|
}
|
|
759
765
|
recordAgentToolCall({
|
|
@@ -927,6 +933,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
927
933
|
duration_ms: Math.max(0, runEnd - pending.startMs),
|
|
928
934
|
status: "error",
|
|
929
935
|
error_class: "interrupted",
|
|
936
|
+
outcome: "unknown",
|
|
930
937
|
});
|
|
931
938
|
}
|
|
932
939
|
if (pending.otelSpan) {
|
|
@@ -1149,6 +1156,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1149
1156
|
emitLlmGenerationTrackingEvent({
|
|
1150
1157
|
runId,
|
|
1151
1158
|
threadId,
|
|
1159
|
+
turnId,
|
|
1152
1160
|
userId,
|
|
1153
1161
|
parentSpanId,
|
|
1154
1162
|
llmSpanId: generation.spanId,
|
|
@@ -1263,6 +1271,7 @@ export async function instrumentAgentLoop(opts) {
|
|
|
1263
1271
|
source: "agent_observability",
|
|
1264
1272
|
run_id: runId,
|
|
1265
1273
|
thread_id: threadId,
|
|
1274
|
+
turn_id: turnId,
|
|
1266
1275
|
llm_calls: llmCallCount || undefined,
|
|
1267
1276
|
follow_up_ms: usage?.followUpMs,
|
|
1268
1277
|
follow_up_input_tokens: usage?.followUpInputTokens,
|
|
@@ -75,10 +75,9 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
75
75
|
user: "user";
|
|
76
76
|
}>>;
|
|
77
77
|
}, z.core.$strip>>, {
|
|
78
|
-
message?: undefined;
|
|
79
78
|
id?: undefined;
|
|
80
|
-
|
|
81
|
-
|
|
79
|
+
message?: undefined;
|
|
80
|
+
found?: undefined;
|
|
82
81
|
providers: {
|
|
83
82
|
id: string;
|
|
84
83
|
label: string;
|
|
@@ -89,45 +88,46 @@ export declare function createCustomProviderRegistrationAction<TSchema extends Z
|
|
|
89
88
|
updatedAt: number;
|
|
90
89
|
}[];
|
|
91
90
|
count: number;
|
|
92
|
-
|
|
91
|
+
provider?: undefined;
|
|
92
|
+
deleted?: undefined;
|
|
93
93
|
registered?: undefined;
|
|
94
94
|
label?: undefined;
|
|
95
95
|
} | {
|
|
96
|
-
message?: undefined;
|
|
97
96
|
id?: undefined;
|
|
98
|
-
|
|
99
|
-
deleted?: undefined;
|
|
97
|
+
message?: undefined;
|
|
100
98
|
providers?: undefined;
|
|
99
|
+
count?: undefined;
|
|
101
100
|
found: boolean;
|
|
102
101
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
102
|
+
deleted?: undefined;
|
|
103
103
|
registered?: undefined;
|
|
104
104
|
label?: undefined;
|
|
105
105
|
} | {
|
|
106
106
|
message?: undefined;
|
|
107
|
-
provider?: undefined;
|
|
108
|
-
count?: undefined;
|
|
109
|
-
deleted?: undefined;
|
|
110
107
|
providers?: undefined;
|
|
108
|
+
count?: undefined;
|
|
109
|
+
provider?: undefined;
|
|
111
110
|
found: boolean;
|
|
112
111
|
id: string;
|
|
112
|
+
deleted?: undefined;
|
|
113
113
|
registered?: undefined;
|
|
114
114
|
label?: undefined;
|
|
115
115
|
} | {
|
|
116
116
|
message?: undefined;
|
|
117
|
-
provider?: undefined;
|
|
118
|
-
count?: undefined;
|
|
119
|
-
providers?: undefined;
|
|
120
117
|
found?: undefined;
|
|
118
|
+
providers?: undefined;
|
|
119
|
+
count?: undefined;
|
|
120
|
+
provider?: undefined;
|
|
121
121
|
deleted: boolean;
|
|
122
122
|
id: string;
|
|
123
123
|
registered?: undefined;
|
|
124
124
|
label?: undefined;
|
|
125
125
|
} | {
|
|
126
|
-
|
|
126
|
+
found?: undefined;
|
|
127
|
+
providers?: undefined;
|
|
127
128
|
count?: undefined;
|
|
129
|
+
provider?: undefined;
|
|
128
130
|
deleted?: undefined;
|
|
129
|
-
providers?: undefined;
|
|
130
|
-
found?: undefined;
|
|
131
131
|
registered: boolean;
|
|
132
132
|
id: string;
|
|
133
133
|
label: string;
|
|
@@ -316,9 +316,8 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
316
316
|
notes?: string | undefined;
|
|
317
317
|
scope?: "org" | "user" | undefined;
|
|
318
318
|
}, {
|
|
319
|
-
|
|
319
|
+
found?: undefined;
|
|
320
320
|
deleted?: undefined;
|
|
321
|
-
provider?: undefined;
|
|
322
321
|
providers: {
|
|
323
322
|
id: string;
|
|
324
323
|
label: string;
|
|
@@ -329,46 +328,47 @@ export declare function createProviderApiActions(runtime: Pick<ProviderApiRuntim
|
|
|
329
328
|
updatedAt: number;
|
|
330
329
|
}[];
|
|
331
330
|
count: number;
|
|
332
|
-
|
|
331
|
+
provider?: undefined;
|
|
333
332
|
registered?: undefined;
|
|
333
|
+
id?: undefined;
|
|
334
334
|
label?: undefined;
|
|
335
335
|
message?: undefined;
|
|
336
336
|
} | {
|
|
337
|
-
id?: undefined;
|
|
338
337
|
deleted?: undefined;
|
|
339
|
-
count?: undefined;
|
|
340
338
|
providers?: undefined;
|
|
339
|
+
count?: undefined;
|
|
341
340
|
found: boolean;
|
|
342
341
|
provider: import("../custom-registry.js").CustomProviderConfig;
|
|
343
342
|
registered?: undefined;
|
|
343
|
+
id?: undefined;
|
|
344
344
|
label?: undefined;
|
|
345
345
|
message?: undefined;
|
|
346
346
|
} | {
|
|
347
347
|
deleted?: undefined;
|
|
348
|
-
provider?: undefined;
|
|
349
|
-
count?: undefined;
|
|
350
348
|
providers?: undefined;
|
|
349
|
+
count?: undefined;
|
|
350
|
+
provider?: undefined;
|
|
351
351
|
found: boolean;
|
|
352
352
|
id: string;
|
|
353
353
|
registered?: undefined;
|
|
354
354
|
label?: undefined;
|
|
355
355
|
message?: undefined;
|
|
356
356
|
} | {
|
|
357
|
-
provider?: undefined;
|
|
358
|
-
count?: undefined;
|
|
359
|
-
providers?: undefined;
|
|
360
357
|
found?: undefined;
|
|
358
|
+
providers?: undefined;
|
|
359
|
+
count?: undefined;
|
|
360
|
+
provider?: undefined;
|
|
361
361
|
deleted: boolean;
|
|
362
362
|
id: string;
|
|
363
363
|
registered?: undefined;
|
|
364
364
|
label?: undefined;
|
|
365
365
|
message?: undefined;
|
|
366
366
|
} | {
|
|
367
|
+
found?: undefined;
|
|
367
368
|
deleted?: undefined;
|
|
368
|
-
provider?: undefined;
|
|
369
|
-
count?: undefined;
|
|
370
369
|
providers?: undefined;
|
|
371
|
-
|
|
370
|
+
count?: undefined;
|
|
371
|
+
provider?: undefined;
|
|
372
372
|
registered: boolean;
|
|
373
373
|
id: string;
|
|
374
374
|
label: string;
|
|
@@ -73,7 +73,6 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
73
73
|
offset?: unknown;
|
|
74
74
|
limit?: unknown;
|
|
75
75
|
}, {
|
|
76
|
-
deleted?: undefined;
|
|
77
76
|
jobs: {
|
|
78
77
|
id: string;
|
|
79
78
|
name: string;
|
|
@@ -84,6 +83,7 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
84
83
|
updatedAt: string;
|
|
85
84
|
}[];
|
|
86
85
|
total: number;
|
|
86
|
+
deleted?: undefined;
|
|
87
87
|
jobId?: undefined;
|
|
88
88
|
} | {
|
|
89
89
|
jobs?: undefined;
|
|
@@ -91,9 +91,9 @@ export declare function createProviderCorpusJobAction(options: CreateProviderCor
|
|
|
91
91
|
deleted: boolean;
|
|
92
92
|
jobId: string;
|
|
93
93
|
} | {
|
|
94
|
-
deleted?: undefined;
|
|
95
94
|
jobs?: undefined;
|
|
96
95
|
total?: undefined;
|
|
96
|
+
deleted?: undefined;
|
|
97
97
|
jobId?: undefined;
|
|
98
98
|
hits: Record<string, unknown>[];
|
|
99
99
|
offset: number;
|
|
@@ -39,8 +39,8 @@ export declare function handleUpdateResource(event: any): Promise<import("./stor
|
|
|
39
39
|
error: string;
|
|
40
40
|
}>;
|
|
41
41
|
export declare function handleDeleteResource(event: any): Promise<{
|
|
42
|
-
ok?: undefined;
|
|
43
42
|
error: string;
|
|
43
|
+
ok?: undefined;
|
|
44
44
|
} | {
|
|
45
45
|
error?: undefined;
|
|
46
46
|
ok: boolean;
|
package/dist/review/index.d.ts
CHANGED
|
@@ -6,6 +6,6 @@ export { __resetReviewableResourcesForTests, assertReviewableResourceAccess, get
|
|
|
6
6
|
export { __resetReviewInitForTests, ensureReviewTables, getReviewCommentById, getReviewStatus, getReviewThreadSummary, getReviewThreadRoot, queryReviewComments, routeReviewThread, sendReviewThreadToAgent, } from "./store.js";
|
|
7
7
|
export * from "./suggestions/types.js";
|
|
8
8
|
export { registerSuggestionAdapter, getSuggestionAdapter, listSuggestionAdapters, __resetSuggestionAdaptersForTests, } from "./suggestions/registry.js";
|
|
9
|
-
export { ensureSuggestionTables, getDecision, getSuggestion, getSuggestionByCreationKey, listSuggestions, __resetSuggestionTablesForTests, } from "./suggestions/store.js";
|
|
9
|
+
export { ensureSuggestionTables, getDecision, getSuggestion, getSuggestionByCreationKey, listSuggestions, rebaseSuggestion, __resetSuggestionTablesForTests, } from "./suggestions/store.js";
|
|
10
10
|
export { suggestionActorKind, suggestionActorKindMatchesReceipt, } from "./suggestions/actor-kind.js";
|
|
11
11
|
export type { GetReviewThreadSummaryInput, ReviewThreadSummary, } from "./store.js";
|
package/dist/review/index.js
CHANGED
|
@@ -5,5 +5,5 @@ export { __resetReviewableResourcesForTests, assertReviewableResourceAccess, get
|
|
|
5
5
|
export { __resetReviewInitForTests, ensureReviewTables, getReviewCommentById, getReviewStatus, getReviewThreadSummary, getReviewThreadRoot, queryReviewComments, routeReviewThread, sendReviewThreadToAgent, } from "./store.js";
|
|
6
6
|
export * from "./suggestions/types.js";
|
|
7
7
|
export { registerSuggestionAdapter, getSuggestionAdapter, listSuggestionAdapters, __resetSuggestionAdaptersForTests, } from "./suggestions/registry.js";
|
|
8
|
-
export { ensureSuggestionTables, getDecision, getSuggestion, getSuggestionByCreationKey, listSuggestions, __resetSuggestionTablesForTests, } from "./suggestions/store.js";
|
|
8
|
+
export { ensureSuggestionTables, getDecision, getSuggestion, getSuggestionByCreationKey, listSuggestions, rebaseSuggestion, __resetSuggestionTablesForTests, } from "./suggestions/store.js";
|
|
9
9
|
export { suggestionActorKind, suggestionActorKindMatchesReceipt, } from "./suggestions/actor-kind.js";
|
|
@@ -435,7 +435,7 @@ export const decideResourceSuggestion = defineAction({
|
|
|
435
435
|
}
|
|
436
436
|
return { suggestion: latest, decision };
|
|
437
437
|
};
|
|
438
|
-
const
|
|
438
|
+
const decideIn = async (tx, coordination) => {
|
|
439
439
|
const current = await getSuggestion(args.id, tx);
|
|
440
440
|
if (!current)
|
|
441
441
|
throw new Error("Suggestion not found");
|
|
@@ -450,8 +450,7 @@ export const decideResourceSuggestion = defineAction({
|
|
|
450
450
|
errorCode: "suggestion_conflict",
|
|
451
451
|
});
|
|
452
452
|
}
|
|
453
|
-
if (!currentAdapter ||
|
|
454
|
-
currentAdapter.version !== current.adapterVersion)
|
|
453
|
+
if (!currentAdapter || currentAdapter.version !== current.adapterVersion)
|
|
455
454
|
throw new Error("Suggestion adapter version is unavailable");
|
|
456
455
|
// Withdrawing never applies the suggestion, so a base that moved on
|
|
457
456
|
// since the author last saw it is no conflict.
|
|
@@ -508,11 +507,14 @@ export const decideResourceSuggestion = defineAction({
|
|
|
508
507
|
resourceId: current.resourceId,
|
|
509
508
|
}, args.decision);
|
|
510
509
|
}
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
};
|
|
515
|
-
}
|
|
510
|
+
const decided = await getSuggestion(current.id, tx);
|
|
511
|
+
if (!decided)
|
|
512
|
+
throw new Error("Decided suggestion disappeared");
|
|
513
|
+
return { suggestion: decided, decision: prior.record };
|
|
514
|
+
};
|
|
515
|
+
const decide = (coordination, options = {}) => options.transaction
|
|
516
|
+
? decideIn(options.transaction, coordination)
|
|
517
|
+
: db.transaction((tx) => decideIn(tx, coordination));
|
|
516
518
|
if (args.decision === "accepted" && adapter.coordinateDecision) {
|
|
517
519
|
return adapter.coordinateDecision({
|
|
518
520
|
resourceType: suggestion.resourceType,
|
|
@@ -842,7 +844,7 @@ export const decideResourceSuggestionProposal = defineAction({
|
|
|
842
844
|
suggestions: suggestions,
|
|
843
845
|
};
|
|
844
846
|
};
|
|
845
|
-
const
|
|
847
|
+
const decideIn = async (tx, coordination) => {
|
|
846
848
|
const currentProposal = await getSuggestionProposal(tx, args.proposalId);
|
|
847
849
|
if (!currentProposal)
|
|
848
850
|
fail("Proposal not found", {
|
|
@@ -936,15 +938,20 @@ export const decideResourceSuggestionProposal = defineAction({
|
|
|
936
938
|
proposal: currentProposal,
|
|
937
939
|
suggestions: decided,
|
|
938
940
|
};
|
|
939
|
-
}
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
941
|
+
};
|
|
942
|
+
// A failure in the adapter's transaction aborts it, so the receipt of a
|
|
943
|
+
// decision that won meanwhile can't be read here; the adapter replays.
|
|
944
|
+
const decide = (coordination, options = {}) => options.transaction
|
|
945
|
+
? decideIn(options.transaction, coordination)
|
|
946
|
+
: db.transaction((tx) => decideIn(tx, coordination)).catch(async (error) => {
|
|
947
|
+
const prior = await getProposalDecision(db, args.idempotencyKey);
|
|
948
|
+
if (!prior)
|
|
949
|
+
throw error;
|
|
950
|
+
return db.transaction(async (tx) => {
|
|
951
|
+
await assertReviewableResourceAccess(proposal.resourceType, proposal.resourceId, { ...ctx, transaction: tx }, "editor");
|
|
952
|
+
return replayDecision(tx, prior);
|
|
953
|
+
});
|
|
946
954
|
});
|
|
947
|
-
});
|
|
948
955
|
if (args.decision === "accepted" && adapter.coordinateDecision) {
|
|
949
956
|
return adapter.coordinateDecision({
|
|
950
957
|
resourceType: proposal.resourceType,
|
|
@@ -953,6 +960,7 @@ export const decideResourceSuggestionProposal = defineAction({
|
|
|
953
960
|
operations: initial.operations,
|
|
954
961
|
decision: args.decision,
|
|
955
962
|
proposalDecision: true,
|
|
963
|
+
proposalMemberIds: members.map((member) => member.id),
|
|
956
964
|
access,
|
|
957
965
|
ctx: { ...ctx, suggestionAccess: access },
|
|
958
966
|
}, decide);
|
|
@@ -20,7 +20,20 @@ export declare function getSuggestionAmendment(client: DbExec, key: string): Pro
|
|
|
20
20
|
request: string;
|
|
21
21
|
suggestion: ResourceSuggestion;
|
|
22
22
|
}>;
|
|
23
|
-
export declare function amendSuggestion(client: DbExec, before: ResourceSuggestion, operations: SuggestionOperation[], summary: string, idempotencyKey: string, request: string): Promise<ResourceSuggestion | null>;
|
|
23
|
+
export declare function amendSuggestion(client: DbExec, before: ResourceSuggestion, operations: SuggestionOperation[], summary: string, idempotencyKey: string, request: string, baseRevision?: string): Promise<ResourceSuggestion | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Moves a pending suggestion onto `baseRevision` with `operations` that make
|
|
26
|
+
* the same change there, as when its resource was rewritten into an
|
|
27
|
+
* equivalent form. It is recorded as an amendment, so the suggestion's
|
|
28
|
+
* revision moves and anyone holding the old one refreshes before deciding.
|
|
29
|
+
* Null when the suggestion was decided or changed since `before` was read.
|
|
30
|
+
*/
|
|
31
|
+
export declare function rebaseSuggestion(client: DbExec, before: ResourceSuggestion, input: {
|
|
32
|
+
operations: SuggestionOperation[];
|
|
33
|
+
baseRevision: string;
|
|
34
|
+
idempotencyKey: string;
|
|
35
|
+
reason: string;
|
|
36
|
+
}): Promise<ResourceSuggestion | null>;
|
|
24
37
|
export declare function getSuggestion(suggestionId: string, client?: DbExec): Promise<ResourceSuggestion | null>;
|
|
25
38
|
/** Loads several suggestions in two queries; missing ids come back as null. */
|
|
26
39
|
export declare function getSuggestions(suggestionIds: readonly string[], client?: DbExec): Promise<(ResourceSuggestion | null)[]>;
|
|
@@ -205,11 +205,11 @@ export async function getSuggestionAmendment(client, key) {
|
|
|
205
205
|
}
|
|
206
206
|
: null;
|
|
207
207
|
}
|
|
208
|
-
export async function amendSuggestion(client, before, operations, summary, idempotencyKey, request) {
|
|
208
|
+
export async function amendSuggestion(client, before, operations, summary, idempotencyKey, request, baseRevision = before.baseRevision) {
|
|
209
209
|
const now = new Date().toISOString();
|
|
210
210
|
const claimed = await client.execute({
|
|
211
|
-
sql: "UPDATE agent_review_suggestions SET revision = revision + 1, summary = ?, updated_at = ? WHERE id = ? AND status = 'pending' AND revision = ?",
|
|
212
|
-
args: [summary, now, before.id, before.revision],
|
|
211
|
+
sql: "UPDATE agent_review_suggestions SET revision = revision + 1, summary = ?, base_revision = ?, updated_at = ? WHERE id = ? AND status = 'pending' AND revision = ?",
|
|
212
|
+
args: [summary, baseRevision, now, before.id, before.revision],
|
|
213
213
|
});
|
|
214
214
|
if (claimed.rowsAffected !== 1)
|
|
215
215
|
return null;
|
|
@@ -239,6 +239,19 @@ export async function amendSuggestion(client, before, operations, summary, idemp
|
|
|
239
239
|
});
|
|
240
240
|
return after;
|
|
241
241
|
}
|
|
242
|
+
/**
|
|
243
|
+
* Moves a pending suggestion onto `baseRevision` with `operations` that make
|
|
244
|
+
* the same change there, as when its resource was rewritten into an
|
|
245
|
+
* equivalent form. It is recorded as an amendment, so the suggestion's
|
|
246
|
+
* revision moves and anyone holding the old one refreshes before deciding.
|
|
247
|
+
* Null when the suggestion was decided or changed since `before` was read.
|
|
248
|
+
*/
|
|
249
|
+
export function rebaseSuggestion(client, before, input) {
|
|
250
|
+
return amendSuggestion(client, before, input.operations, before.summary, input.idempotencyKey, JSON.stringify({
|
|
251
|
+
rebase: input.reason,
|
|
252
|
+
baseRevision: input.baseRevision,
|
|
253
|
+
}), input.baseRevision);
|
|
254
|
+
}
|
|
242
255
|
export async function getSuggestion(suggestionId, client = getDbExec()) {
|
|
243
256
|
await ensureSuggestionTables(client);
|
|
244
257
|
const row = (await client.execute({
|
|
@@ -68,9 +68,23 @@ export interface SuggestionDecisionContext {
|
|
|
68
68
|
operations: SuggestionOperation[];
|
|
69
69
|
decision: SuggestionDecision;
|
|
70
70
|
proposalDecision?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* The members a proposal decision decides, in the order it calls `apply`
|
|
73
|
+
* for them. `suggestion` is the first.
|
|
74
|
+
*/
|
|
75
|
+
proposalMemberIds?: string[];
|
|
71
76
|
access: SuggestionAccess;
|
|
72
77
|
ctx?: Record<string, unknown>;
|
|
73
78
|
}
|
|
79
|
+
export interface SuggestionDecisionRunOptions {
|
|
80
|
+
/**
|
|
81
|
+
* Runs the decision in this transaction instead of its own, so the
|
|
82
|
+
* decision commits or rolls back with the adapter's write. A decision that
|
|
83
|
+
* replays an earlier one returns without calling `apply`; an adapter whose
|
|
84
|
+
* write must not commit without the decision has to check for that.
|
|
85
|
+
*/
|
|
86
|
+
transaction?: unknown;
|
|
87
|
+
}
|
|
74
88
|
export interface SuggestionAdapter {
|
|
75
89
|
kind: string;
|
|
76
90
|
version: number;
|
|
@@ -83,7 +97,7 @@ export interface SuggestionAdapter {
|
|
|
83
97
|
ctx?: Record<string, unknown>;
|
|
84
98
|
}): Promise<void | SuggestionOperation[]> | void | SuggestionOperation[];
|
|
85
99
|
preview?(context: SuggestionContext): Promise<unknown> | unknown;
|
|
86
|
-
coordinateDecision?<T>(context: SuggestionDecisionContext, run: (coordination?: unknown) => Promise<T>): Promise<T>;
|
|
100
|
+
coordinateDecision?<T>(context: SuggestionDecisionContext, run: (coordination?: unknown, options?: SuggestionDecisionRunOptions) => Promise<T>): Promise<T>;
|
|
87
101
|
finalizeProposalDecision?(context: {
|
|
88
102
|
resourceType: string;
|
|
89
103
|
resourceId: string;
|
|
@@ -31,6 +31,7 @@ Options:
|
|
|
31
31
|
--limit N Max results (default: 20)
|
|
32
32
|
--format json Output as JSON
|
|
33
33
|
--includeArchived Also include archived chats (excluded by default)
|
|
34
|
+
--includeHidden Also include chats hidden by you (excluded by default)
|
|
34
35
|
--help Show this help message
|
|
35
36
|
|
|
36
37
|
Examples:
|
|
@@ -45,10 +46,19 @@ Examples:
|
|
|
45
46
|
if (isNaN(limit) || limit < 1)
|
|
46
47
|
fail("--limit must be a positive integer");
|
|
47
48
|
const includeArchived = parsed.includeArchived === "true";
|
|
49
|
+
const includeHidden = parsed.includeHidden === "true";
|
|
48
50
|
const query = parsed.query;
|
|
49
51
|
const threads = query
|
|
50
|
-
? await searchThreads(owner, query, limit, {
|
|
51
|
-
|
|
52
|
+
? await searchThreads(owner, query, limit, {
|
|
53
|
+
includeArchived,
|
|
54
|
+
includeHidden,
|
|
55
|
+
})
|
|
56
|
+
: await listThreads(owner, {
|
|
57
|
+
limit,
|
|
58
|
+
offset: 0,
|
|
59
|
+
includeArchived,
|
|
60
|
+
includeHidden,
|
|
61
|
+
});
|
|
52
62
|
if (parsed.format === "json") {
|
|
53
63
|
console.log(JSON.stringify({
|
|
54
64
|
query: query ?? null,
|
|
@@ -60,6 +70,7 @@ Examples:
|
|
|
60
70
|
updatedAt: t.updatedAt,
|
|
61
71
|
pinnedAt: t.pinnedAt ?? null,
|
|
62
72
|
archivedAt: t.archivedAt ?? null,
|
|
73
|
+
hiddenAt: t.hiddenAt ?? null,
|
|
63
74
|
})),
|
|
64
75
|
count: threads.length,
|
|
65
76
|
}, null, 2));
|
|
@@ -80,6 +91,7 @@ Examples:
|
|
|
80
91
|
const flags = [
|
|
81
92
|
t.pinnedAt ? "pinned" : null,
|
|
82
93
|
t.archivedAt ? "archived" : null,
|
|
94
|
+
t.hiddenAt ? "hidden" : null,
|
|
83
95
|
].filter(Boolean);
|
|
84
96
|
console.log(` ${title}`);
|
|
85
97
|
console.log(` ID: ${t.id} | ${msgs} | ${time}${flags.length ? ` | ${flags.join(", ")}` : ""}`);
|
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
2
3
|
import { ACTION_CHAT_UI_AGENT_TEAM_PROGRESS_RENDERER, normalizeAgentTeamProgressResult, } from "../../action-ui.js";
|
|
4
|
+
import { fail } from "../../action.js";
|
|
3
5
|
import { getActiveFileUploadProviderForRequest } from "../../file-upload/registry.js";
|
|
4
6
|
import { areBuiltinMcpCapabilitiesSupported, setBuiltinMcpCapabilityEnabled, } from "../../mcp-client/index.js";
|
|
5
7
|
import { getBuilderBrowserConnectUrlForOwner, resolveBuilderBranchProjectId, } from "../builder-browser.js";
|
|
6
|
-
import { getRequestUserEmail } from "../request-context.js";
|
|
8
|
+
import { getRequestOrgId, getRequestUserEmail } from "../request-context.js";
|
|
7
9
|
import { getMcpManagerForCurrentRequest } from "./mcp-glue.js";
|
|
8
10
|
const MAX_EXTENSION_PROMOTION_CONTENT_CHARS = 200_000;
|
|
9
11
|
const MAX_AGENT_TEAM_PROGRESS_TASKS = 3;
|
|
@@ -367,8 +369,35 @@ export function createBuilderBrowserTool(deps) {
|
|
|
367
369
|
return entries;
|
|
368
370
|
}
|
|
369
371
|
export function createTeamTools(deps) {
|
|
372
|
+
const readTask = async (taskId, waitMs, context) => {
|
|
373
|
+
if (!Number.isInteger(waitMs) || waitMs < 0 || waitMs > 20_000)
|
|
374
|
+
fail("waitMs must be an integer between 0 and 20000.", {
|
|
375
|
+
errorCode: "invalid_input",
|
|
376
|
+
statusCode: 422,
|
|
377
|
+
});
|
|
378
|
+
const scope = {
|
|
379
|
+
ownerEmail: deps.getOwner(),
|
|
380
|
+
orgId: context?.orgId !== undefined
|
|
381
|
+
? context.orgId
|
|
382
|
+
: (getRequestOrgId() ?? null),
|
|
383
|
+
};
|
|
384
|
+
const signal = context?.signal;
|
|
385
|
+
signal?.throwIfAborted();
|
|
386
|
+
const { getTask } = await import("../agent-teams.js");
|
|
387
|
+
const deadline = Date.now() + waitMs;
|
|
388
|
+
let task = await getTask(taskId, scope);
|
|
389
|
+
signal?.throwIfAborted();
|
|
390
|
+
while (task?.status === "running" && Date.now() < deadline) {
|
|
391
|
+
await delay(Math.min(500, deadline - Date.now()), undefined, { signal });
|
|
392
|
+
signal?.throwIfAborted();
|
|
393
|
+
task = await getTask(taskId, scope);
|
|
394
|
+
signal?.throwIfAborted();
|
|
395
|
+
}
|
|
396
|
+
return task;
|
|
397
|
+
};
|
|
370
398
|
return {
|
|
371
399
|
"agent-teams": {
|
|
400
|
+
dedupe: false,
|
|
372
401
|
tool: {
|
|
373
402
|
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.",
|
|
374
403
|
parameters: {
|
|
@@ -403,6 +432,12 @@ export function createTeamTools(deps) {
|
|
|
403
432
|
type: "string",
|
|
404
433
|
description: "(send) Message to send to the sub-agent",
|
|
405
434
|
},
|
|
435
|
+
waitMs: {
|
|
436
|
+
type: "integer",
|
|
437
|
+
minimum: 0,
|
|
438
|
+
maximum: 20000,
|
|
439
|
+
description: "(status, read-result) Wait up to this many milliseconds for a terminal task. Defaults to 0 (immediate snapshot). A deadline can return queued/running; it does not mean completion or resume the parent automatically.",
|
|
440
|
+
},
|
|
406
441
|
},
|
|
407
442
|
required: ["action"],
|
|
408
443
|
},
|
|
@@ -423,7 +458,7 @@ export function createTeamTools(deps) {
|
|
|
423
458
|
allowedValues: { action: ["status", "read-result", "list"] },
|
|
424
459
|
description: "Plan mode allows listing tasks and reading their status or results.",
|
|
425
460
|
},
|
|
426
|
-
run: async (args) => {
|
|
461
|
+
run: async (args, context) => {
|
|
427
462
|
const action = args.action;
|
|
428
463
|
if (action === "spawn") {
|
|
429
464
|
if (!args.task)
|
|
@@ -481,8 +516,7 @@ export function createTeamTools(deps) {
|
|
|
481
516
|
if (action === "status") {
|
|
482
517
|
if (!args.taskId)
|
|
483
518
|
throw new Error("'taskId' is required for status");
|
|
484
|
-
const
|
|
485
|
-
const task = await getTask(args.taskId);
|
|
519
|
+
const task = await readTask(args.taskId, args.waitMs === undefined ? 0 : args.waitMs, context);
|
|
486
520
|
if (!task)
|
|
487
521
|
return JSON.stringify({ error: "Task not found" });
|
|
488
522
|
return JSON.stringify({
|
|
@@ -500,8 +534,7 @@ export function createTeamTools(deps) {
|
|
|
500
534
|
if (action === "read-result") {
|
|
501
535
|
if (!args.taskId)
|
|
502
536
|
throw new Error("'taskId' is required for read-result");
|
|
503
|
-
const
|
|
504
|
-
const task = await getTask(args.taskId);
|
|
537
|
+
const task = await readTask(args.taskId, args.waitMs === undefined ? 0 : args.waitMs, context);
|
|
505
538
|
if (!task)
|
|
506
539
|
return JSON.stringify({ error: "Task not found" });
|
|
507
540
|
if (task.status === "running") {
|