@agentclientprotocol/claude-agent-acp 0.94.1-preview.1 → 0.94.1-preview.11
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/README.md +21 -9
- package/dist/acp-agent.d.ts +39 -3
- package/dist/acp-agent.d.ts.map +1 -1
- package/dist/acp-agent.js +178 -66
- package/dist/acp-subagents.d.ts +2 -1
- package/dist/acp-subagents.d.ts.map +1 -1
- package/dist/air-extension.d.ts +5 -0
- package/dist/air-extension.d.ts.map +1 -1
- package/dist/air-extension.js +5 -0
- package/dist/async-tasks.d.ts +6 -3
- package/dist/async-tasks.d.ts.map +1 -1
- package/dist/async-tasks.js +13 -5
- package/dist/clear-context-coordinator.d.ts +1 -0
- package/dist/clear-context-coordinator.d.ts.map +1 -1
- package/dist/clear-context-coordinator.js +1 -0
- package/dist/index.js +2 -3
- package/dist/native-subagents.d.ts +64 -0
- package/dist/native-subagents.d.ts.map +1 -1
- package/dist/native-subagents.js +224 -9
- package/dist/permissions/options/shared.d.ts +3 -0
- package/dist/permissions/options/shared.d.ts.map +1 -1
- package/dist/permissions/options/tools.js +1 -1
- package/dist/serve.d.ts +19 -11
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +26 -18
- package/dist/session-index/activity.d.ts +4 -0
- package/dist/session-index/activity.d.ts.map +1 -1
- package/dist/session-index/activity.js +16 -0
- package/dist/session-index/background-tasks.d.ts +69 -0
- package/dist/session-index/background-tasks.d.ts.map +1 -0
- package/dist/session-index/background-tasks.js +173 -0
- package/dist/session-index/service.d.ts +2 -0
- package/dist/session-index/service.d.ts.map +1 -1
- package/dist/session-index/service.js +6 -1
- package/dist/session-index/session-index.d.ts +14 -0
- package/dist/session-index/session-index.d.ts.map +1 -1
- package/dist/session-index/session-index.js +25 -2
- package/dist/session-index/transcript-scan.d.ts +8 -1
- package/dist/session-index/transcript-scan.d.ts.map +1 -1
- package/dist/session-index/transcript-scan.js +22 -1
- package/dist/session-titles.d.ts +44 -16
- package/dist/session-titles.d.ts.map +1 -1
- package/dist/session-titles.js +89 -27
- package/dist/subagent-history.d.ts +7 -3
- package/dist/subagent-history.d.ts.map +1 -1
- package/dist/subagent-history.js +7 -3
- package/dist/subagent-replay.d.ts +21 -1
- package/dist/subagent-replay.d.ts.map +1 -1
- package/dist/subagent-replay.js +51 -3
- package/dist/task-notifications.d.ts +30 -0
- package/dist/task-notifications.d.ts.map +1 -0
- package/dist/task-notifications.js +62 -0
- package/dist/usage-markdown.d.ts.map +1 -1
- package/dist/usage-markdown.js +18 -0
- package/package.json +6 -6
|
@@ -41,6 +41,8 @@ export type NativeSubagent = {
|
|
|
41
41
|
promptIds?: Set<string>;
|
|
42
42
|
/** The RFD form: the calls that delegated to the child, whose runs ended. */
|
|
43
43
|
endedRuns?: Set<string>;
|
|
44
|
+
/** The RFD form: the calls that delegated to the child, whose runs handed back a report. */
|
|
45
|
+
handedBack?: Set<string>;
|
|
44
46
|
announced?: boolean;
|
|
45
47
|
terminalState?: SubagentState;
|
|
46
48
|
/** Connection-local single-flight state; never serialized on the wire. */
|
|
@@ -127,6 +129,18 @@ export declare class NativeSubagentRuntime {
|
|
|
127
129
|
private readonly taskFinishPromises;
|
|
128
130
|
/** The session that made each SendMessage call. */
|
|
129
131
|
private readonly senderByToolUse;
|
|
132
|
+
/**
|
|
133
|
+
* The RFD form: the Agent/Task calls that the client is not shown, until
|
|
134
|
+
* their final update. Kept by id because the adapter's own report that
|
|
135
|
+
* closes an unfinished call has no `toolName` to recognize it by.
|
|
136
|
+
*/
|
|
137
|
+
private readonly hiddenLaunches;
|
|
138
|
+
/**
|
|
139
|
+
* The RFD form: the SubagentHandback calls of announced children that the
|
|
140
|
+
* client is not shown yet, with their first report, the report from their
|
|
141
|
+
* input, and the call that delegated the run.
|
|
142
|
+
*/
|
|
143
|
+
private readonly handbacks;
|
|
130
144
|
private readonly generationByTaskId;
|
|
131
145
|
private readonly pending;
|
|
132
146
|
private pendingCount;
|
|
@@ -331,6 +345,25 @@ export declare class NativeSubagentRuntime {
|
|
|
331
345
|
* sender of the prompt when the call resumes a child.
|
|
332
346
|
*/
|
|
333
347
|
private rememberSendMessage;
|
|
348
|
+
/**
|
|
349
|
+
* The RFD form: an update of the Agent/Task call that launches `child`,
|
|
350
|
+
* which the parent's session messages replace. Only a launch whose child
|
|
351
|
+
* was never exposed stays a tool call of the parent, with its final status,
|
|
352
|
+
* since the RFD lets the Agent represent unexposed work through the parent.
|
|
353
|
+
* A background launch completes before its child starts, so its completion
|
|
354
|
+
* is not such a case.
|
|
355
|
+
*/
|
|
356
|
+
private routeRfdLaunch;
|
|
357
|
+
/**
|
|
358
|
+
* The RFD form: an update of a SubagentHandback call of the announced
|
|
359
|
+
* `child`, which its report replaces: the child's message to its parent,
|
|
360
|
+
* see {@link linkedSessionMessages}. A failed call delivered nothing, so the
|
|
361
|
+
* child is shown the call after all. `undefined` for any other update.
|
|
362
|
+
*/
|
|
363
|
+
private routeRfdHandback;
|
|
364
|
+
/** Whether `update` is of an Agent/Task call, by its tool name or, in the
|
|
365
|
+
* RFD form, by the id of a call the client is not shown. */
|
|
366
|
+
private isControlUpdate;
|
|
334
367
|
private rememberToolCallOwner;
|
|
335
368
|
/**
|
|
336
369
|
* The RFD form: how many cancels the client sent for `child`, its
|
|
@@ -384,6 +417,37 @@ export declare class NativeSubagentRuntime {
|
|
|
384
417
|
*/
|
|
385
418
|
export declare function announceNativeSubagent(child: NativeSubagent, publish: Publish, form: SubagentForm): Promise<void>;
|
|
386
419
|
export declare function finishNativeSubagent(session: NativeSubagentSession, taskId: string, state: SubagentState, publish: Publish): Promise<void>;
|
|
420
|
+
/**
|
|
421
|
+
* The RFD form: a message that a tool call sent, which the client is not
|
|
422
|
+
* shown, as two session messages: the sender's outgoing view, then the
|
|
423
|
+
* recipient's incoming one. That call is a launch's Agent/Task call, whose
|
|
424
|
+
* prompt goes from the parent to the child, or a child's SubagentHandback
|
|
425
|
+
* call, whose report goes from the child to the parent. Both views use the
|
|
426
|
+
* call's tool use id, and each names the other with the draft RFD's
|
|
427
|
+
* `recipientMessageId` and `senderMessageId`.
|
|
428
|
+
*/
|
|
429
|
+
export declare function linkedSessionMessages(toolUseId: string, senderSessionId: string, recipientSessionId: string, text: string): AcpSessionNotification[];
|
|
430
|
+
/**
|
|
431
|
+
* The tool with which a child hands its report to its parent, when Claude
|
|
432
|
+
* Code runs in hand-back mode. The Agent/Task result then only says that the
|
|
433
|
+
* report was delivered as a message, with `handback: "send"` in its
|
|
434
|
+
* structured result.
|
|
435
|
+
*/
|
|
436
|
+
export declare const HANDBACK_TOOL = "SubagentHandback";
|
|
437
|
+
/** The report of a SubagentHandback call, from its input. */
|
|
438
|
+
export declare function handbackMessage(input: unknown): string | undefined;
|
|
439
|
+
/**
|
|
440
|
+
* The RFD form: the answer of a foreground child, from the completed result
|
|
441
|
+
* of the Agent/Task call `launchId` that launched it, as the child's message
|
|
442
|
+
* in the parent's transcript (its incoming view). It replaces that call's
|
|
443
|
+
* result, which the parent is not shown. The child's transcript has its
|
|
444
|
+
* answer as its own agent message, not as a session message, so this view
|
|
445
|
+
* links to no other. `undefined` for a result without text. Not used for a
|
|
446
|
+
* run whose child handed back its report: the result has no report then.
|
|
447
|
+
*/
|
|
448
|
+
export declare function launchReply(launchId: string, childSessionId: string, parentSessionId: string, result: Extract<AcpSessionNotification["update"], {
|
|
449
|
+
sessionUpdate: "tool_call_update" | "tool_call";
|
|
450
|
+
}>): AcpSessionNotification | undefined;
|
|
387
451
|
/**
|
|
388
452
|
* The RFD form: the work state at the end of a child's work.
|
|
389
453
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native-subagents.d.ts","sourceRoot":"","sources":["../src/native-subagents.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,mCAAmC,CAAC;AAC3F,OAAO,KAAK,EAAE,sBAAsB,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"native-subagents.d.ts","sourceRoot":"","sources":["../src/native-subagents.ts"],"names":[],"mappings":"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"}
|
package/dist/native-subagents.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { RequestError } from "@agentclientprotocol/sdk/unstable";
|
|
2
2
|
import { AIR_SUBAGENT_KEY, airExtensionMeta } from "./air-extension.js";
|
|
3
|
+
import { isFinalToolCallStatus } from "./tool-calls/renderer.js";
|
|
3
4
|
const MAX_PENDING_PARENTS = 64;
|
|
4
5
|
const MAX_PENDING_UPDATES = 256;
|
|
5
6
|
const MAX_PENDING_UPDATES_PER_PARENT = 32;
|
|
@@ -34,6 +35,18 @@ export class NativeSubagentRuntime {
|
|
|
34
35
|
taskFinishPromises = new Map();
|
|
35
36
|
/** The session that made each SendMessage call. */
|
|
36
37
|
senderByToolUse = new Map();
|
|
38
|
+
/**
|
|
39
|
+
* The RFD form: the Agent/Task calls that the client is not shown, until
|
|
40
|
+
* their final update. Kept by id because the adapter's own report that
|
|
41
|
+
* closes an unfinished call has no `toolName` to recognize it by.
|
|
42
|
+
*/
|
|
43
|
+
hiddenLaunches = new Map();
|
|
44
|
+
/**
|
|
45
|
+
* The RFD form: the SubagentHandback calls of announced children that the
|
|
46
|
+
* client is not shown yet, with their first report, the report from their
|
|
47
|
+
* input, and the call that delegated the run.
|
|
48
|
+
*/
|
|
49
|
+
handbacks = new Map();
|
|
37
50
|
generationByTaskId = new Map();
|
|
38
51
|
pending = new Map();
|
|
39
52
|
pendingCount = 0;
|
|
@@ -83,7 +96,7 @@ export class NativeSubagentRuntime {
|
|
|
83
96
|
async routeUpdate(notification, deliver, forcedSessionId) {
|
|
84
97
|
const { update } = notification;
|
|
85
98
|
const claudeMeta = update._meta?.claudeCode;
|
|
86
|
-
const isControl =
|
|
99
|
+
const isControl = this.isControlUpdate(update);
|
|
87
100
|
if (!this.enabled)
|
|
88
101
|
return notification;
|
|
89
102
|
if (this.enabled && isControl) {
|
|
@@ -126,12 +139,18 @@ export class NativeSubagentRuntime {
|
|
|
126
139
|
if (forcedSessionId) {
|
|
127
140
|
return { ...notification, sessionId: forcedSessionId };
|
|
128
141
|
}
|
|
129
|
-
return
|
|
142
|
+
return unexposedControlFallback(initial, notification, parentSessionId ?? this.rootSessionId);
|
|
130
143
|
}
|
|
131
144
|
return forcedSessionId ? { ...notification, sessionId: forcedSessionId } : null;
|
|
132
145
|
}
|
|
133
|
-
// The RFD form: the
|
|
134
|
-
//
|
|
146
|
+
// The RFD form: the parent's session messages replace the Agent/Task
|
|
147
|
+
// tool call, its prompt as the parent's outgoing message (see
|
|
148
|
+
// `linkedSessionMessages`) and its result as the child's reply (see
|
|
149
|
+
// `launchReply`). A call made inside a child that is not announced yet
|
|
150
|
+
// is buffered below, as any update of that child.
|
|
151
|
+
if (!parentPending) {
|
|
152
|
+
return this.routeRfdLaunch(notification, child, parentSessionId ?? this.rootSessionId, forcedSessionId);
|
|
153
|
+
}
|
|
135
154
|
}
|
|
136
155
|
const toolCallId = update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update"
|
|
137
156
|
? update.toolCallId
|
|
@@ -147,6 +166,15 @@ export class NativeSubagentRuntime {
|
|
|
147
166
|
return { ...notification, sessionId: forcedSessionId };
|
|
148
167
|
}
|
|
149
168
|
const owner = toolCallId ? this.childByToolCall.get(toolCallId) : undefined;
|
|
169
|
+
const announcedChild = owner ??
|
|
170
|
+
(claudeMeta?.parentToolUseId
|
|
171
|
+
? this.childByParentToolUse.get(claudeMeta.parentToolUseId)
|
|
172
|
+
: undefined);
|
|
173
|
+
if (this.form === "rfd" && announcedChild?.announced) {
|
|
174
|
+
const handback = await this.routeRfdHandback(notification, announcedChild);
|
|
175
|
+
if (handback !== undefined)
|
|
176
|
+
return handback;
|
|
177
|
+
}
|
|
150
178
|
if (owner)
|
|
151
179
|
return this.toChild(owner, notification, toolCallId);
|
|
152
180
|
if (this.enabled && claudeMeta?.parentToolUseId) {
|
|
@@ -762,6 +790,94 @@ export class NativeSubagentRuntime {
|
|
|
762
790
|
this.senderByToolUse.delete(oldest);
|
|
763
791
|
}
|
|
764
792
|
}
|
|
793
|
+
/**
|
|
794
|
+
* The RFD form: an update of the Agent/Task call that launches `child`,
|
|
795
|
+
* which the parent's session messages replace. Only a launch whose child
|
|
796
|
+
* was never exposed stays a tool call of the parent, with its final status,
|
|
797
|
+
* since the RFD lets the Agent represent unexposed work through the parent.
|
|
798
|
+
* A background launch completes before its child starts, so its completion
|
|
799
|
+
* is not such a case.
|
|
800
|
+
*/
|
|
801
|
+
async routeRfdLaunch(notification, child, parentSessionId, forcedSessionId) {
|
|
802
|
+
const { update } = notification;
|
|
803
|
+
if (update.sessionUpdate !== "tool_call" && update.sessionUpdate !== "tool_call_update") {
|
|
804
|
+
return null;
|
|
805
|
+
}
|
|
806
|
+
const toolCallId = update.toolCallId;
|
|
807
|
+
// A permission request already showed the call to the client, so it
|
|
808
|
+
// keeps getting its updates.
|
|
809
|
+
if (forcedSessionId)
|
|
810
|
+
return { ...notification, sessionId: forcedSessionId };
|
|
811
|
+
const launch = this.hiddenLaunches.get(toolCallId) ?? { background: false };
|
|
812
|
+
if (isBackgroundLaunch(update.rawInput))
|
|
813
|
+
launch.background = true;
|
|
814
|
+
if (!isFinalToolCallStatus(update.status)) {
|
|
815
|
+
this.hiddenLaunches.set(toolCallId, launch);
|
|
816
|
+
return null;
|
|
817
|
+
}
|
|
818
|
+
this.hiddenLaunches.delete(toolCallId);
|
|
819
|
+
if (child?.announcePromise)
|
|
820
|
+
await child.announcePromise;
|
|
821
|
+
const background = launch.background;
|
|
822
|
+
if (child?.announced) {
|
|
823
|
+
const reply = update.status === "completed" && !background && !child.handedBack?.has(toolCallId)
|
|
824
|
+
? launchReply(toolCallId, child.sessionId, child.parentSessionId, update)
|
|
825
|
+
: undefined;
|
|
826
|
+
if (reply)
|
|
827
|
+
await this.publish(reply);
|
|
828
|
+
return null;
|
|
829
|
+
}
|
|
830
|
+
if (background && update.status === "completed")
|
|
831
|
+
return null;
|
|
832
|
+
this.takePending(toolCallId);
|
|
833
|
+
const initial = this.controlByToolUse.get(toolCallId);
|
|
834
|
+
this.cleanupControl(toolCallId);
|
|
835
|
+
return unexposedControlFallback(initial, notification, parentSessionId);
|
|
836
|
+
}
|
|
837
|
+
/**
|
|
838
|
+
* The RFD form: an update of a SubagentHandback call of the announced
|
|
839
|
+
* `child`, which its report replaces: the child's message to its parent,
|
|
840
|
+
* see {@link linkedSessionMessages}. A failed call delivered nothing, so the
|
|
841
|
+
* child is shown the call after all. `undefined` for any other update.
|
|
842
|
+
*/
|
|
843
|
+
async routeRfdHandback(notification, child) {
|
|
844
|
+
const { update } = notification;
|
|
845
|
+
if (update.sessionUpdate !== "tool_call" && update.sessionUpdate !== "tool_call_update") {
|
|
846
|
+
return undefined;
|
|
847
|
+
}
|
|
848
|
+
const claudeMeta = update._meta?.claudeCode;
|
|
849
|
+
let handback = this.handbacks.get(update.toolCallId);
|
|
850
|
+
if (!handback) {
|
|
851
|
+
if (claudeMeta?.toolName !== HANDBACK_TOOL)
|
|
852
|
+
return undefined;
|
|
853
|
+
handback = {
|
|
854
|
+
initial: notification,
|
|
855
|
+
delegationId: claudeMeta.parentToolUseId ?? child.parentToolUseId,
|
|
856
|
+
};
|
|
857
|
+
this.handbacks.set(update.toolCallId, handback);
|
|
858
|
+
}
|
|
859
|
+
handback.message = handbackMessage(update.rawInput) ?? handback.message;
|
|
860
|
+
if (!isFinalToolCallStatus(update.status))
|
|
861
|
+
return null;
|
|
862
|
+
this.handbacks.delete(update.toolCallId);
|
|
863
|
+
if (update.status === "completed" && handback.message) {
|
|
864
|
+
for (const view of linkedSessionMessages(update.toolCallId, child.sessionId, child.parentSessionId, handback.message)) {
|
|
865
|
+
await this.publish(view);
|
|
866
|
+
}
|
|
867
|
+
if (handback.delegationId)
|
|
868
|
+
(child.handedBack ??= new Set()).add(handback.delegationId);
|
|
869
|
+
return null;
|
|
870
|
+
}
|
|
871
|
+
return unexposedControlFallback(handback.initial, notification, child.sessionId);
|
|
872
|
+
}
|
|
873
|
+
/** Whether `update` is of an Agent/Task call, by its tool name or, in the
|
|
874
|
+
* RFD form, by the id of a call the client is not shown. */
|
|
875
|
+
isControlUpdate(update) {
|
|
876
|
+
if (update.sessionUpdate !== "tool_call" && update.sessionUpdate !== "tool_call_update") {
|
|
877
|
+
return false;
|
|
878
|
+
}
|
|
879
|
+
return this.hiddenLaunches.has(update.toolCallId) || isNativeSubagentControlUpdate(update);
|
|
880
|
+
}
|
|
765
881
|
rememberToolCallOwner(toolCallId, child) {
|
|
766
882
|
this.childByToolCall.delete(toolCallId);
|
|
767
883
|
this.childByToolCall.set(toolCallId, child);
|
|
@@ -808,6 +924,8 @@ export class NativeSubagentRuntime {
|
|
|
808
924
|
this.childByParentToolUse.clear();
|
|
809
925
|
this.taskFinishPromises.clear();
|
|
810
926
|
this.senderByToolUse.clear();
|
|
927
|
+
this.hiddenLaunches.clear();
|
|
928
|
+
this.handbacks.clear();
|
|
811
929
|
this.generationByTaskId.clear();
|
|
812
930
|
this.pending.clear();
|
|
813
931
|
this.pendingCount = 0;
|
|
@@ -949,7 +1067,7 @@ export async function announceNativeSubagent(child, publish, form) {
|
|
|
949
1067
|
child.announced = true;
|
|
950
1068
|
// The immediate parent made the Agent/Task call that launched the child.
|
|
951
1069
|
if (child.prompt) {
|
|
952
|
-
await publishPrompt(child, child.prompt, child.parentToolUseId, child.parentSessionId, publish);
|
|
1070
|
+
await publishPrompt(child, child.prompt, child.parentToolUseId, child.parentSessionId, publish, { replacesLaunch: true });
|
|
953
1071
|
}
|
|
954
1072
|
return;
|
|
955
1073
|
}
|
|
@@ -1008,13 +1126,23 @@ export async function finishNativeSubagent(session, taskId, state, publish) {
|
|
|
1008
1126
|
* Agent/Task call or a SendMessage, so a prompt whose id is already in the
|
|
1009
1127
|
* transcript is the same delegation and is not sent again. `sender` is the
|
|
1010
1128
|
* session that made that call, when known.
|
|
1129
|
+
*
|
|
1130
|
+
* A launch's prompt (`replacesLaunch`) also goes to the parent, see
|
|
1131
|
+
* {@link linkedSessionMessages}. A SendMessage call stays a tool call of the
|
|
1132
|
+
* sender, so its message has only the incoming view.
|
|
1011
1133
|
*/
|
|
1012
|
-
async function publishPrompt(child, prompt, toolUseId, sender, publish) {
|
|
1134
|
+
async function publishPrompt(child, prompt, toolUseId, sender, publish, { replacesLaunch = false } = {}) {
|
|
1013
1135
|
child.promptIds ??= new Set();
|
|
1014
1136
|
const messageId = toolUseId ?? `${child.sessionId}:prompt:${child.promptIds.size + 1}`;
|
|
1015
1137
|
if (child.promptIds.has(messageId))
|
|
1016
1138
|
return;
|
|
1017
1139
|
child.promptIds.add(messageId);
|
|
1140
|
+
if (replacesLaunch && sender !== undefined && toolUseId !== undefined) {
|
|
1141
|
+
for (const view of linkedSessionMessages(toolUseId, sender, child.sessionId, prompt)) {
|
|
1142
|
+
await publish(view);
|
|
1143
|
+
}
|
|
1144
|
+
return;
|
|
1145
|
+
}
|
|
1018
1146
|
await publish({
|
|
1019
1147
|
sessionId: child.sessionId,
|
|
1020
1148
|
update: {
|
|
@@ -1026,6 +1154,87 @@ async function publishPrompt(child, prompt, toolUseId, sender, publish) {
|
|
|
1026
1154
|
},
|
|
1027
1155
|
});
|
|
1028
1156
|
}
|
|
1157
|
+
/**
|
|
1158
|
+
* The RFD form: a message that a tool call sent, which the client is not
|
|
1159
|
+
* shown, as two session messages: the sender's outgoing view, then the
|
|
1160
|
+
* recipient's incoming one. That call is a launch's Agent/Task call, whose
|
|
1161
|
+
* prompt goes from the parent to the child, or a child's SubagentHandback
|
|
1162
|
+
* call, whose report goes from the child to the parent. Both views use the
|
|
1163
|
+
* call's tool use id, and each names the other with the draft RFD's
|
|
1164
|
+
* `recipientMessageId` and `senderMessageId`.
|
|
1165
|
+
*/
|
|
1166
|
+
export function linkedSessionMessages(toolUseId, senderSessionId, recipientSessionId, text) {
|
|
1167
|
+
const message = {
|
|
1168
|
+
sessionUpdate: "session_message",
|
|
1169
|
+
messageId: toolUseId,
|
|
1170
|
+
senderSessionId,
|
|
1171
|
+
recipientSessionId,
|
|
1172
|
+
content: [{ type: "text", text }],
|
|
1173
|
+
};
|
|
1174
|
+
return [
|
|
1175
|
+
{
|
|
1176
|
+
sessionId: senderSessionId,
|
|
1177
|
+
update: { ...message, recipientMessageId: toolUseId },
|
|
1178
|
+
},
|
|
1179
|
+
{
|
|
1180
|
+
sessionId: recipientSessionId,
|
|
1181
|
+
update: { ...message, senderMessageId: toolUseId },
|
|
1182
|
+
},
|
|
1183
|
+
];
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* The tool with which a child hands its report to its parent, when Claude
|
|
1187
|
+
* Code runs in hand-back mode. The Agent/Task result then only says that the
|
|
1188
|
+
* report was delivered as a message, with `handback: "send"` in its
|
|
1189
|
+
* structured result.
|
|
1190
|
+
*/
|
|
1191
|
+
export const HANDBACK_TOOL = "SubagentHandback";
|
|
1192
|
+
/** The report of a SubagentHandback call, from its input. */
|
|
1193
|
+
export function handbackMessage(input) {
|
|
1194
|
+
const message = input?.message;
|
|
1195
|
+
return typeof message === "string" && message.trim() ? message : undefined;
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* The RFD form: the answer of a foreground child, from the completed result
|
|
1199
|
+
* of the Agent/Task call `launchId` that launched it, as the child's message
|
|
1200
|
+
* in the parent's transcript (its incoming view). It replaces that call's
|
|
1201
|
+
* result, which the parent is not shown. The child's transcript has its
|
|
1202
|
+
* answer as its own agent message, not as a session message, so this view
|
|
1203
|
+
* links to no other. `undefined` for a result without text. Not used for a
|
|
1204
|
+
* run whose child handed back its report: the result has no report then.
|
|
1205
|
+
*/
|
|
1206
|
+
export function launchReply(launchId, childSessionId, parentSessionId, result) {
|
|
1207
|
+
const content = replyContent(result);
|
|
1208
|
+
if (content.length === 0)
|
|
1209
|
+
return undefined;
|
|
1210
|
+
return {
|
|
1211
|
+
sessionId: parentSessionId,
|
|
1212
|
+
update: {
|
|
1213
|
+
sessionUpdate: "session_message",
|
|
1214
|
+
messageId: `${launchId}:reply`,
|
|
1215
|
+
senderSessionId: childSessionId,
|
|
1216
|
+
recipientSessionId: parentSessionId,
|
|
1217
|
+
content,
|
|
1218
|
+
},
|
|
1219
|
+
};
|
|
1220
|
+
}
|
|
1221
|
+
/**
|
|
1222
|
+
* The text of a completed launch's result, from the tool call's `content`:
|
|
1223
|
+
* `AgentReporter` removed the parts meant for the model there (the
|
|
1224
|
+
* `agentId: … (use SendMessage …)` line, the `<usage>` block and the hand-back
|
|
1225
|
+
* frame), which `rawOutput` still has.
|
|
1226
|
+
*/
|
|
1227
|
+
function replyContent(result) {
|
|
1228
|
+
return (result.content ?? []).flatMap((item) => item.type === "content" && item.content.type === "text" && item.content.text.trim()
|
|
1229
|
+
? [{ type: "text", text: item.content.text }]
|
|
1230
|
+
: []);
|
|
1231
|
+
}
|
|
1232
|
+
/** Whether an Agent/Task call's input runs its child in the background. */
|
|
1233
|
+
function isBackgroundLaunch(rawInput) {
|
|
1234
|
+
return (typeof rawInput === "object" &&
|
|
1235
|
+
rawInput !== null &&
|
|
1236
|
+
rawInput.run_in_background === true);
|
|
1237
|
+
}
|
|
1029
1238
|
/** The RFD form: whether the child's foreground work is in progress. */
|
|
1030
1239
|
function isWorking(child) {
|
|
1031
1240
|
return child.workState === "running" || child.workState === "requires_action";
|
|
@@ -1165,7 +1374,13 @@ function isFailedToolCallUpdate(update) {
|
|
|
1165
1374
|
return ((update.sessionUpdate === "tool_call" || update.sessionUpdate === "tool_call_update") &&
|
|
1166
1375
|
update.status === "failed");
|
|
1167
1376
|
}
|
|
1168
|
-
|
|
1377
|
+
/**
|
|
1378
|
+
* A tool call that the client was not shown, as one `tool_call` with its
|
|
1379
|
+
* final status, shown after all: an Agent/Task call whose child was never
|
|
1380
|
+
* exposed (AIR's draft shows only a failed one, the RFD form also a completed
|
|
1381
|
+
* one), or a failed SubagentHandback call.
|
|
1382
|
+
*/
|
|
1383
|
+
function unexposedControlFallback(initial, terminal, sessionId) {
|
|
1169
1384
|
if (terminal.update.sessionUpdate !== "tool_call" &&
|
|
1170
1385
|
terminal.update.sessionUpdate !== "tool_call_update") {
|
|
1171
1386
|
return { ...terminal, sessionId };
|
|
@@ -1178,7 +1393,7 @@ function failedControlFallback(initial, terminal, sessionId) {
|
|
|
1178
1393
|
update: {
|
|
1179
1394
|
...terminal.update,
|
|
1180
1395
|
sessionUpdate: "tool_call",
|
|
1181
|
-
status: "failed",
|
|
1396
|
+
status: terminal.update.status ?? "failed",
|
|
1182
1397
|
// The synthesized tool_call is this call's first report, so give it
|
|
1183
1398
|
// the standard `name` the initial one would have carried.
|
|
1184
1399
|
...(typeof claudeMeta?.toolName === "string" ? { name: claudeMeta.toolName } : {}),
|
|
@@ -1198,7 +1413,7 @@ function failedControlFallback(initial, terminal, sessionId) {
|
|
|
1198
1413
|
...initial.update,
|
|
1199
1414
|
...terminal.update,
|
|
1200
1415
|
sessionUpdate: "tool_call",
|
|
1201
|
-
status: "failed",
|
|
1416
|
+
status: terminal.update.status ?? "failed",
|
|
1202
1417
|
title: typeof terminal.update.title === "string" && terminal.update.title.trim().length > 0
|
|
1203
1418
|
? terminal.update.title
|
|
1204
1419
|
: initial.update.title,
|
|
@@ -28,6 +28,9 @@ export interface PermissionOptionContext {
|
|
|
28
28
|
/** The mode the session left when it entered plan mode. */
|
|
29
29
|
prePlanMode?: string;
|
|
30
30
|
contextUsedPercent?: number;
|
|
31
|
+
/** False when no ACP turn can continue an accepted plan in a fresh
|
|
32
|
+
* context. Then an ExitPlanMode request offers no clear-context option. */
|
|
33
|
+
allowContextReset?: boolean;
|
|
31
34
|
}
|
|
32
35
|
export declare function allowOnce(name?: string): PermissionOption;
|
|
33
36
|
export declare function allowWithUpdates(name: string): PermissionOption;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/permissions/options/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;CAavB,CAAC;AAEX,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;IAC9C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;wEACoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,IAAI,SAAQ,GAAG,gBAAgB,CAExD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAE/D;AAED,wBAAgB,MAAM,CAAC,IAAI,SAAO,GAAG,gBAAgB,CAEpD;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,SAAQ,EACjB,UAAU,SAAO,GAChB,gBAAgB,EAAE,CAKpB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE9D;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAkBT;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,QAAQ,EAAE,MAAM,GACf,OAAO,CAYT;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAO,GAAG,gBAAgB,EAAE,CAEvF"}
|
|
1
|
+
{"version":3,"file":"shared.d.ts","sourceRoot":"","sources":["../../../src/permissions/options/shared.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AAC1E,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAC;AAEtE,eAAO,MAAM,oBAAoB;;;;;;;;;;;;;CAavB,CAAC;AAEX,MAAM,WAAW,uBAAuB;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,gBAAgB,CAAC,EAAE,0BAA0B,CAAC;IAC9C,sBAAsB,CAAC,EAAE,OAAO,CAAC;IACjC;wEACoE;IACpE,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,cAAc,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACnC,2DAA2D;IAC3D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kBAAkB,CAAC,EAAE,MAAM,CAAC;IAC5B;gFAC4E;IAC5E,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,wBAAgB,SAAS,CAAC,IAAI,SAAQ,GAAG,gBAAgB,CAExD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,CAE/D;AAED,wBAAgB,MAAM,CAAC,IAAI,SAAO,GAAG,gBAAgB,CAEpD;AAED,wBAAgB,kBAAkB,CAChC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,UAAU,EAAE,MAAM,GAAG,SAAS,EAC9B,SAAS,SAAQ,EACjB,UAAU,SAAO,GAChB,gBAAgB,EAAE,CAKpB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAE9D;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,QAAQ,EAAE,MAAM,EAChB,WAAW,CAAC,EAAE,MAAM,GACnB,OAAO,CAkBT;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,0BAA0B,GAAG,SAAS,EACjD,QAAQ,EAAE,MAAM,GACf,OAAO,CAYT;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,SAAO,GAAG,gBAAgB,EAAE,CAEvF"}
|
|
@@ -50,7 +50,7 @@ export function buildExitPlanModePermissionOptions(context) {
|
|
|
50
50
|
? ["bypassPermissions", "auto"]
|
|
51
51
|
: ["auto", "bypassPermissions"]).filter((mode) => modes.has(mode));
|
|
52
52
|
const preferredMode = elevatedModes[0] ?? "acceptEdits";
|
|
53
|
-
if (plainString(context.input.plan)) {
|
|
53
|
+
if (context.allowContextReset !== false && plainString(context.input.plan)) {
|
|
54
54
|
const usage = context.contextUsedPercent === undefined ? "" : ` (${context.contextUsedPercent}% used)`;
|
|
55
55
|
options.push(preferredMode === "auto"
|
|
56
56
|
? {
|
package/dist/serve.d.ts
CHANGED
|
@@ -1,23 +1,31 @@
|
|
|
1
|
-
import * as v2 from "@agentclientprotocol/sdk/experimental/v2
|
|
1
|
+
import * as v2 from "@agentclientprotocol/sdk/experimental/v2";
|
|
2
2
|
import { type ClaudeAcpAgent, type Logger } from "./acp-agent.js";
|
|
3
3
|
/**
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* With `experimentalV2`, the connection goes through {@link acpProtocolRouter}.
|
|
7
|
-
* Without it, the adapter serves ACP v1 alone and never routes by protocol
|
|
8
|
-
* version, exactly as before.
|
|
4
|
+
* The ACP versions that the adapter serves: `v1` or `v2` alone, or both with
|
|
5
|
+
* `auto`, where the client's `initialize` picks the version.
|
|
9
6
|
*/
|
|
7
|
+
export type AcpProtocols = "auto" | "v1" | "v2";
|
|
8
|
+
/**
|
|
9
|
+
* Reads `CLAUDE_AGENT_ACP_PROTOCOL`: unset, empty, or `auto` serves both
|
|
10
|
+
* versions, and `v1` or `v2` serves that version alone. Throws on any other
|
|
11
|
+
* value, so that a typo such as `CLAUDE_AGENT_ACP_PROTOCOL=1` fails at startup
|
|
12
|
+
* instead of silently serving both.
|
|
13
|
+
*/
|
|
14
|
+
export declare function acpProtocolsFromEnv(value: string | undefined): AcpProtocols;
|
|
15
|
+
/** Serves ACP on stdio through {@link acpProtocolRouter}. */
|
|
10
16
|
export declare function serveAcp(logger: Logger | undefined, options: {
|
|
11
|
-
|
|
17
|
+
protocols: AcpProtocols;
|
|
12
18
|
}): {
|
|
13
19
|
closed: Promise<void>;
|
|
14
20
|
dispose(): Promise<void>;
|
|
15
21
|
};
|
|
16
22
|
/**
|
|
17
23
|
* Routes a connection to the protocol version that the client negotiates in
|
|
18
|
-
* `initialize
|
|
19
|
-
*
|
|
20
|
-
*
|
|
24
|
+
* `initialize`. With `auto`, a client that requests version 2 or later gets
|
|
25
|
+
* the draft ACP v2, and every other client gets ACP v1. With `v1`, a v2
|
|
26
|
+
* client is negotiated down to v1. With `v2`, the router rejects the
|
|
27
|
+
* `initialize` of a v1 client as an unsupported protocol version. `onAgent`
|
|
28
|
+
* receives the agent of the connection once the router has opened it.
|
|
21
29
|
*/
|
|
22
|
-
export declare function acpProtocolRouter(logger: Logger | undefined, onAgent: (agent: ClaudeAcpAgent) => void): v2.AgentProtocolRouter;
|
|
30
|
+
export declare function acpProtocolRouter(logger: Logger | undefined, onAgent: (agent: ClaudeAcpAgent) => void, protocols?: AcpProtocols): v2.AgentProtocolRouter;
|
|
23
31
|
//# sourceMappingURL=serve.d.ts.map
|
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,0CAA0C,CAAC;AAC/D,OAAO,EAAc,KAAK,cAAc,EAAE,KAAK,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAI9E;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,IAAI,GAAG,IAAI,CAAC;AAEhD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,YAAY,CAM3E;AAED,6DAA6D;AAC7D,wBAAgB,QAAQ,CACtB,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE;IAAE,SAAS,EAAE,YAAY,CAAA;CAAE,GACnC;IAAE,MAAM,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAAC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAkBrD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,GAAG,SAAS,EAC1B,OAAO,EAAE,CAAC,KAAK,EAAE,cAAc,KAAK,IAAI,EACxC,SAAS,GAAE,YAAqB,GAC/B,EAAE,CAAC,mBAAmB,CAKxB"}
|
package/dist/serve.js
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
|
-
import
|
|
2
|
-
import * as v2 from "@agentclientprotocol/sdk/experimental/v2/unstable";
|
|
1
|
+
import * as v2 from "@agentclientprotocol/sdk/experimental/v2";
|
|
3
2
|
import { v1AgentApp } from "./acp-agent.js";
|
|
4
3
|
import { nodeToWebReadable, nodeToWebWritable } from "./utils.js";
|
|
5
4
|
import { v2AgentApp } from "./v2/agent.js";
|
|
6
5
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
* version, exactly as before.
|
|
6
|
+
* Reads `CLAUDE_AGENT_ACP_PROTOCOL`: unset, empty, or `auto` serves both
|
|
7
|
+
* versions, and `v1` or `v2` serves that version alone. Throws on any other
|
|
8
|
+
* value, so that a typo such as `CLAUDE_AGENT_ACP_PROTOCOL=1` fails at startup
|
|
9
|
+
* instead of silently serving both.
|
|
12
10
|
*/
|
|
11
|
+
export function acpProtocolsFromEnv(value) {
|
|
12
|
+
if (value === undefined || value === "")
|
|
13
|
+
return "auto";
|
|
14
|
+
if (value === "auto" || value === "v1" || value === "v2")
|
|
15
|
+
return value;
|
|
16
|
+
throw new Error(`CLAUDE_AGENT_ACP_PROTOCOL must be "auto", "v1", or "v2", not ${JSON.stringify(value)}`);
|
|
17
|
+
}
|
|
18
|
+
/** Serves ACP on stdio through {@link acpProtocolRouter}. */
|
|
13
19
|
export function serveAcp(logger, options) {
|
|
14
20
|
const output = nodeToWebWritable(process.stdout);
|
|
15
21
|
const input = nodeToWebReadable(process.stdin);
|
|
@@ -19,9 +25,7 @@ export function serveAcp(logger, options) {
|
|
|
19
25
|
const onAgent = (created) => {
|
|
20
26
|
agent = created;
|
|
21
27
|
};
|
|
22
|
-
const { closed } = options.
|
|
23
|
-
? acpProtocolRouter(logger, onAgent).connect(v2.ndJsonStream(output, input))
|
|
24
|
-
: v1AgentApp(logger, onAgent).connect(ndJsonStream(output, input));
|
|
28
|
+
const { closed } = acpProtocolRouter(logger, onAgent, options.protocols).connect(v2.ndJsonStream(output, input));
|
|
25
29
|
return {
|
|
26
30
|
closed,
|
|
27
31
|
dispose: async () => {
|
|
@@ -31,13 +35,17 @@ export function serveAcp(logger, options) {
|
|
|
31
35
|
}
|
|
32
36
|
/**
|
|
33
37
|
* Routes a connection to the protocol version that the client negotiates in
|
|
34
|
-
* `initialize
|
|
35
|
-
*
|
|
36
|
-
*
|
|
38
|
+
* `initialize`. With `auto`, a client that requests version 2 or later gets
|
|
39
|
+
* the draft ACP v2, and every other client gets ACP v1. With `v1`, a v2
|
|
40
|
+
* client is negotiated down to v1. With `v2`, the router rejects the
|
|
41
|
+
* `initialize` of a v1 client as an unsupported protocol version. `onAgent`
|
|
42
|
+
* receives the agent of the connection once the router has opened it.
|
|
37
43
|
*/
|
|
38
|
-
export function acpProtocolRouter(logger, onAgent) {
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
.withV1(v1AgentApp(logger, onAgent))
|
|
42
|
-
|
|
44
|
+
export function acpProtocolRouter(logger, onAgent, protocols = "auto") {
|
|
45
|
+
const router = v2.agentProtocolRouter();
|
|
46
|
+
if (protocols !== "v2")
|
|
47
|
+
router.withV1(v1AgentApp(logger, onAgent));
|
|
48
|
+
if (protocols !== "v1")
|
|
49
|
+
router.withV2(v2AgentApp(logger, onAgent));
|
|
50
|
+
return router;
|
|
43
51
|
}
|
|
@@ -11,6 +11,10 @@
|
|
|
11
11
|
* - an interactive CLI that is not driven by an SDK holds it, and its registry
|
|
12
12
|
* status is newer than the transcript: the registry status (an idle one is
|
|
13
13
|
* `error` after such a turn);
|
|
14
|
+
* - a turn that ended with an open background task is `running`, also after
|
|
15
|
+
* 10 minutes: Claude Code wakes the session again when the task ends. The
|
|
16
|
+
* wait ends when the registry status is `idle`, because a task can end
|
|
17
|
+
* without a transcript record (a stop in the task UI);
|
|
14
18
|
* - otherwise the transcript tail: a finished turn is `idle` (`error` after
|
|
15
19
|
* an API error), an unfinished turn written in the last 10 minutes is
|
|
16
20
|
* `running`, and anything else has no known state.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/session-index/activity.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"activity.d.ts","sourceRoot":"","sources":["../../src/session-index/activity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,iBAAiB,GAAG,OAAO,CAAC;AAE7E,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF,0DAA0D;AAC1D,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,aAAa,CAAC;IACtB,4CAA4C;IAC5C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,2CAA2C;IAC3C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;gEAE4D;IAC5D,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB,CAAC;AAuCF,wBAAgB,cAAc,CAAC,KAAK,EAAE;IACpC,GAAG,CAAC,EAAE,eAAe,CAAC;IACtB,IAAI,CAAC,EAAE,UAAU,CAAC;IAClB,KAAK,EAAE,eAAe,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,GAAG,EAAE,MAAM,CAAC;CACb,GAAG,eAAe,GAAG,SAAS,CAwC9B;AAED;;eAEe;AACf,wBAAgB,UAAU,CAAC,GAAG,EAAE,eAAe,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAG/E"}
|