@ours.network/fleet 0.16.0 → 0.17.0
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 +8 -1
- package/dist/application/role-creation-service.d.ts +2 -2
- package/dist/config.d.ts +4 -2
- package/dist/config.js +3 -2
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +9 -4
- package/dist/monitor.d.ts +4 -3
- package/dist/monitor.js +11 -2
- package/dist/owner-channel/channel.js +4 -1
- package/dist/runner.js +20 -5
- package/dist/session/acp.d.ts +23 -0
- package/dist/session/acp.js +183 -10
- package/dist/session/arbiter.d.ts +5 -0
- package/dist/session/arbiter.js +8 -0
- package/dist/session/conversation-normalizer.d.ts +6 -0
- package/dist/session/conversation-normalizer.js +4 -3
- package/dist/session/conversation-types.d.ts +9 -2
- package/dist/session/types.d.ts +13 -1
- package/dist/web-app/assets/{TerminalView-Mxxypj9w.js → TerminalView-B3rnVWbo.js} +1 -1
- package/dist/web-app/assets/{index-CsHEL0f6.js → index-CliHATFt.js} +4 -4
- package/dist/web-app/index.html +1 -1
- package/package.json +1 -1
package/dist/session/acp.js
CHANGED
|
@@ -13,6 +13,9 @@ const CANCEL_SETTLE_GRACE_MS = 15_000;
|
|
|
13
13
|
const PERMISSION_TIMEOUT_MS = 10 * 60_000;
|
|
14
14
|
/** Spec §4.3: 10-15 s before a vanished controller triggers the unattended policy. */
|
|
15
15
|
const CONTROLLER_GRACE_MS = 12_000;
|
|
16
|
+
/** Bound safe-boundary waiting without turning a hung tool into cancellation. */
|
|
17
|
+
export const AFTER_TOOL_BOUNDARY_TIMEOUT_MS = 120_000;
|
|
18
|
+
const TERMINAL_TOOL_STATUSES = new Set(['completed', 'failed']);
|
|
16
19
|
const SCHEDULED_LOOP_REDACTION = '[scheduled-loop content redacted]';
|
|
17
20
|
const OWNER_COMMENTARY_REDACTION = '[assistant commentary redacted]';
|
|
18
21
|
const scheduledTurn = (turn) => turn?.origin?.kind === 'scheduled-loop';
|
|
@@ -95,9 +98,13 @@ export class AcpSession {
|
|
|
95
98
|
runtimeModel;
|
|
96
99
|
reasoningEffort;
|
|
97
100
|
controllerCount = 0;
|
|
101
|
+
closing = false;
|
|
98
102
|
/** Armed when the last controller detaches; unattended policy applies on fire. */
|
|
99
103
|
controllerGrace;
|
|
100
104
|
cancelEscalation;
|
|
105
|
+
/** ACP-authenticated in-flight calls, including independently reserved permissions. */
|
|
106
|
+
activeToolCalls = new Map();
|
|
107
|
+
toolBoundaryWaiters = new Set();
|
|
101
108
|
activeTurn;
|
|
102
109
|
constructor(options, child, connection) {
|
|
103
110
|
this.options = options;
|
|
@@ -215,6 +222,142 @@ export class AcpSession {
|
|
|
215
222
|
permissionMode: this.options.permissionMode,
|
|
216
223
|
};
|
|
217
224
|
}
|
|
225
|
+
toolCall(toolCallId) {
|
|
226
|
+
const existing = this.activeToolCalls.get(toolCallId);
|
|
227
|
+
if (existing)
|
|
228
|
+
return existing;
|
|
229
|
+
const created = { lifecycle: false, permissions: new Map() };
|
|
230
|
+
this.activeToolCalls.set(toolCallId, created);
|
|
231
|
+
return created;
|
|
232
|
+
}
|
|
233
|
+
reserveTool(toolCallId) {
|
|
234
|
+
if (toolCallId)
|
|
235
|
+
this.toolCall(toolCallId).lifecycle = true;
|
|
236
|
+
}
|
|
237
|
+
reservePermission(toolCallId, permissionId) {
|
|
238
|
+
if (toolCallId)
|
|
239
|
+
this.toolCall(toolCallId).permissions.set(permissionId, 'pending');
|
|
240
|
+
}
|
|
241
|
+
allowPermission(toolCallId, permissionId) {
|
|
242
|
+
if (!toolCallId)
|
|
243
|
+
return;
|
|
244
|
+
const permission = this.activeToolCalls.get(toolCallId)?.permissions;
|
|
245
|
+
if (permission?.has(permissionId))
|
|
246
|
+
permission.set(permissionId, 'allowed');
|
|
247
|
+
}
|
|
248
|
+
releasePermission(toolCallId, permissionId) {
|
|
249
|
+
const call = toolCallId && this.activeToolCalls.get(toolCallId);
|
|
250
|
+
if (!call || !call.permissions.delete(permissionId))
|
|
251
|
+
return;
|
|
252
|
+
this.releaseToolIfIdle(toolCallId, call);
|
|
253
|
+
}
|
|
254
|
+
releaseTool(toolCallId) {
|
|
255
|
+
const call = toolCallId && this.activeToolCalls.get(toolCallId);
|
|
256
|
+
if (!call)
|
|
257
|
+
return;
|
|
258
|
+
call.lifecycle = false;
|
|
259
|
+
// Terminal tool evidence consumes permissions already granted for this
|
|
260
|
+
// call, but never a separate request that is still awaiting a decision.
|
|
261
|
+
for (const [permissionId, state] of call.permissions)
|
|
262
|
+
if (state === 'allowed')
|
|
263
|
+
call.permissions.delete(permissionId);
|
|
264
|
+
this.releaseToolIfIdle(toolCallId, call);
|
|
265
|
+
}
|
|
266
|
+
releaseToolIfIdle(toolCallId, call) {
|
|
267
|
+
if (call.lifecycle || call.permissions.size > 0)
|
|
268
|
+
return;
|
|
269
|
+
if (!this.activeToolCalls.delete(toolCallId) || this.activeToolCalls.size > 0)
|
|
270
|
+
return;
|
|
271
|
+
for (const notify of [...this.toolBoundaryWaiters])
|
|
272
|
+
notify();
|
|
273
|
+
}
|
|
274
|
+
releaseAllTools() {
|
|
275
|
+
if (this.activeToolCalls.size === 0)
|
|
276
|
+
return;
|
|
277
|
+
this.activeToolCalls.clear();
|
|
278
|
+
for (const notify of [...this.toolBoundaryWaiters])
|
|
279
|
+
notify();
|
|
280
|
+
}
|
|
281
|
+
waitForToolBoundary(timeoutMs) {
|
|
282
|
+
if (this.activeToolCalls.size === 0)
|
|
283
|
+
return Promise.resolve(true);
|
|
284
|
+
return new Promise(resolve => {
|
|
285
|
+
let settled = false;
|
|
286
|
+
const finish = (atBoundary) => {
|
|
287
|
+
if (settled)
|
|
288
|
+
return;
|
|
289
|
+
settled = true;
|
|
290
|
+
clearTimeout(timer);
|
|
291
|
+
this.toolBoundaryWaiters.delete(check);
|
|
292
|
+
resolve(atBoundary);
|
|
293
|
+
};
|
|
294
|
+
const check = () => {
|
|
295
|
+
if (this.activeToolCalls.size === 0 || !this.isAlive())
|
|
296
|
+
finish(this.activeToolCalls.size === 0);
|
|
297
|
+
};
|
|
298
|
+
const timer = setTimeout(() => finish(false), Math.max(0, timeoutMs));
|
|
299
|
+
timer.unref?.();
|
|
300
|
+
this.toolBoundaryWaiters.add(check);
|
|
301
|
+
// Close the subscribe/check race without guessing about elapsed time.
|
|
302
|
+
check();
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
recordAfterToolDelivery(state, activeToolCount, waitedMs) {
|
|
306
|
+
this.events.emit('monitor_delivery', {
|
|
307
|
+
status: state, monitorPolicy: 'after_tool', activeToolCount, waitedMs,
|
|
308
|
+
});
|
|
309
|
+
this.conversation.appendSafe({
|
|
310
|
+
kind: 'monitor.delivery', sessionGeneration: this.sessionGeneration,
|
|
311
|
+
acpSessionId: this.sessionId, source: 'fleet_monitor',
|
|
312
|
+
payload: { policy: 'after_tool', state, activeToolCount, waitedMs },
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Monitor-only safe-boundary delivery. Steering is the interruption: this
|
|
317
|
+
* path never calls session/cancel and never resolves a pending permission.
|
|
318
|
+
*/
|
|
319
|
+
async submitPromptAfterTool(text, options = {}) {
|
|
320
|
+
if (this.closing || !this.isAlive())
|
|
321
|
+
return turnResult(false, 'failed', this.lastError ?? 'ACP session is closing');
|
|
322
|
+
const startedAt = Date.now();
|
|
323
|
+
const initialToolCount = this.activeToolCalls.size;
|
|
324
|
+
if (!this.steeringSupported) {
|
|
325
|
+
this.recordAfterToolDelivery('unsupported', initialToolCount, 0);
|
|
326
|
+
const result = await this.submitPrompt(text, { ...options, interrupt: false, steer: false });
|
|
327
|
+
return {
|
|
328
|
+
...result,
|
|
329
|
+
safeBoundary: { state: 'unsupported', waitedMs: 0, activeToolCount: initialToolCount },
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
if (initialToolCount === 0) {
|
|
333
|
+
this.recordAfterToolDelivery('direct', 0, 0);
|
|
334
|
+
const result = await this.steerPrompt(text);
|
|
335
|
+
return { ...result, safeBoundary: { state: 'direct', waitedMs: 0, activeToolCount: 0 } };
|
|
336
|
+
}
|
|
337
|
+
this.recordAfterToolDelivery('deferred', initialToolCount, 0);
|
|
338
|
+
const timeoutMs = this.options.afterToolBoundaryTimeoutMs ?? AFTER_TOOL_BOUNDARY_TIMEOUT_MS;
|
|
339
|
+
const deadline = startedAt + timeoutMs;
|
|
340
|
+
let atBoundary = false;
|
|
341
|
+
// Re-check after every wake: another authenticated tool event may have
|
|
342
|
+
// arrived before this continuation ran. Only an empty tracked set is safe.
|
|
343
|
+
while (this.activeToolCalls.size > 0) {
|
|
344
|
+
const remaining = deadline - Date.now();
|
|
345
|
+
if (remaining <= 0 || !(await this.waitForToolBoundary(remaining)))
|
|
346
|
+
break;
|
|
347
|
+
}
|
|
348
|
+
atBoundary = this.activeToolCalls.size === 0;
|
|
349
|
+
if (this.closing || !this.isAlive())
|
|
350
|
+
return turnResult(false, 'failed', this.lastError ?? 'ACP session closed during after_tool wait');
|
|
351
|
+
const waitedMs = Math.max(0, Date.now() - startedAt);
|
|
352
|
+
const state = atBoundary ? 'after_tool' : 'timeout';
|
|
353
|
+
const remainingToolCount = this.activeToolCalls.size;
|
|
354
|
+
this.recordAfterToolDelivery(state, remainingToolCount, waitedMs);
|
|
355
|
+
const result = await this.steerPrompt(text);
|
|
356
|
+
return {
|
|
357
|
+
...result,
|
|
358
|
+
safeBoundary: { state, waitedMs, activeToolCount: remainingToolCount },
|
|
359
|
+
};
|
|
360
|
+
}
|
|
218
361
|
/**
|
|
219
362
|
* Accept responsibility for a prompt, then return. The turn itself may run
|
|
220
363
|
* for minutes behind other queued turns; making an interactive caller wait
|
|
@@ -365,6 +508,10 @@ export class AcpSession {
|
|
|
365
508
|
clearTimeout(pending.expiry);
|
|
366
509
|
pending.resolve({ outcome: { outcome: 'selected', optionId } });
|
|
367
510
|
const decision = chosen.kind.startsWith('reject') ? 'denied' : 'allowed';
|
|
511
|
+
if (decision === 'allowed')
|
|
512
|
+
this.allowPermission(pending.toolCallId, permissionId);
|
|
513
|
+
else
|
|
514
|
+
this.releasePermission(pending.toolCallId, permissionId);
|
|
368
515
|
this.events.emit('permission', {
|
|
369
516
|
turnId: this.activeTurn?.id,
|
|
370
517
|
origin: this.activeTurn?.origin,
|
|
@@ -381,7 +528,7 @@ export class AcpSession {
|
|
|
381
528
|
promptId: this.activeTurn?.id, turnId: this.activeTurn?.id,
|
|
382
529
|
payload: { decision, decisionSource: 'manual', optionId },
|
|
383
530
|
});
|
|
384
|
-
this.readiness = 'running';
|
|
531
|
+
this.readiness = this.pendingPermissions.size > 0 ? 'awaiting_permission' : 'running';
|
|
385
532
|
return true;
|
|
386
533
|
}
|
|
387
534
|
/**
|
|
@@ -446,11 +593,12 @@ export class AcpSession {
|
|
|
446
593
|
? { outcome: { outcome: 'selected', optionId: rejectOption.optionId } }
|
|
447
594
|
: { outcome: { outcome: 'cancelled' } });
|
|
448
595
|
const settled = decision === 'denied' && !rejectOption ? 'cancelled' : decision;
|
|
596
|
+
this.releasePermission(pending.toolCallId, permissionId);
|
|
449
597
|
this.events.emit('permission', {
|
|
450
598
|
turnId: this.activeTurn?.id,
|
|
451
599
|
origin: this.activeTurn?.origin,
|
|
452
600
|
permissionId,
|
|
453
|
-
toolCallId: pending.
|
|
601
|
+
toolCallId: pending.eventToolCallId,
|
|
454
602
|
status: 'completed',
|
|
455
603
|
decision: settled === 'expired' ? 'cancelled' : settled,
|
|
456
604
|
decisionSource: 'automatic',
|
|
@@ -462,7 +610,7 @@ export class AcpSession {
|
|
|
462
610
|
kind: 'permission.resolved', sessionGeneration: this.sessionGeneration,
|
|
463
611
|
acpSessionId: this.sessionId, permissionId,
|
|
464
612
|
promptId: this.activeTurn?.id, turnId: this.activeTurn?.id,
|
|
465
|
-
toolCallId: pending.
|
|
613
|
+
toolCallId: pending.eventToolCallId,
|
|
466
614
|
payload: {
|
|
467
615
|
decision: settled, decisionSource: 'automatic',
|
|
468
616
|
...(policy ? { policy } : {}), reason,
|
|
@@ -476,6 +624,7 @@ export class AcpSession {
|
|
|
476
624
|
return this.exit;
|
|
477
625
|
}
|
|
478
626
|
async close() {
|
|
627
|
+
this.closing = true;
|
|
479
628
|
if (this.cancelEscalation)
|
|
480
629
|
clearTimeout(this.cancelEscalation);
|
|
481
630
|
this.cancelEscalation = undefined;
|
|
@@ -484,6 +633,7 @@ export class AcpSession {
|
|
|
484
633
|
this.controllerGrace = undefined;
|
|
485
634
|
for (const [permissionId, pending] of [...this.pendingPermissions])
|
|
486
635
|
this.settlePendingAutomatically(permissionId, pending, 'cancelled', undefined, 'the session closed while this request was pending');
|
|
636
|
+
this.releaseAllTools();
|
|
487
637
|
if (this.sessionId && this.capabilities?.sessionCapabilities?.close != null) {
|
|
488
638
|
await this.connection.agent.request(acp.methods.agent.session.close, { sessionId: this.sessionId }).catch(() => undefined);
|
|
489
639
|
}
|
|
@@ -627,6 +777,7 @@ export class AcpSession {
|
|
|
627
777
|
return turnResult(false, 'failed', this.lastError, this.activeTurn?.id === turnId ? this.activeTurn.output : undefined);
|
|
628
778
|
}
|
|
629
779
|
finally {
|
|
780
|
+
this.releaseAllTools();
|
|
630
781
|
if (this.activeTurn?.id === turnId) {
|
|
631
782
|
if (this.cancelEscalation)
|
|
632
783
|
clearTimeout(this.cancelEscalation);
|
|
@@ -667,9 +818,19 @@ export class AcpSession {
|
|
|
667
818
|
}
|
|
668
819
|
return undefined;
|
|
669
820
|
};
|
|
821
|
+
const toolCallId = params.toolCall.toolCallId;
|
|
822
|
+
const permissionId = randomUUID();
|
|
823
|
+
// Permission is part of the tool lifecycle. Reserve before any policy or
|
|
824
|
+
// human decision so a monitor wake cannot slip between request and answer.
|
|
825
|
+
this.reservePermission(toolCallId, permissionId);
|
|
670
826
|
if (this.options.permissions.approval === 'allow' && this.withinAutomaticBoundary(params)) {
|
|
671
827
|
const option = choose(['allow_always', 'allow_once']);
|
|
672
|
-
|
|
828
|
+
const response = this.settleAutomatically(params, option, 'allowed', 'permissions.approval=allow', `the request is inside the ${this.options.permissions.filesystem} boundary`);
|
|
829
|
+
if (option)
|
|
830
|
+
this.allowPermission(toolCallId, permissionId);
|
|
831
|
+
else
|
|
832
|
+
this.releasePermission(toolCallId, permissionId);
|
|
833
|
+
return Promise.resolve(response);
|
|
673
834
|
}
|
|
674
835
|
// A live grace window still counts as attended: the controller may be
|
|
675
836
|
// mid-reconnect, and denying instantly is exactly what the grace prevents.
|
|
@@ -680,11 +841,12 @@ export class AcpSession {
|
|
|
680
841
|
// a decision no human made, so one unattended denial would silently disable
|
|
681
842
|
// the tool for the rest of the session.
|
|
682
843
|
const option = choose(['reject_once', 'reject_always']);
|
|
683
|
-
|
|
844
|
+
const response = this.settleAutomatically(params, option, 'denied', unattended ? 'permissions.unattended=deny' : 'permissions.approval=deny', unattended
|
|
684
845
|
? 'no controller is attached, so the request cannot be shown to anyone'
|
|
685
|
-
: 'the role denies every permission request by policy')
|
|
846
|
+
: 'the role denies every permission request by policy');
|
|
847
|
+
this.releasePermission(toolCallId, permissionId);
|
|
848
|
+
return Promise.resolve(response);
|
|
686
849
|
}
|
|
687
|
-
const permissionId = randomUUID();
|
|
688
850
|
const timeoutMs = this.options.permissionTimeoutMs ?? PERMISSION_TIMEOUT_MS;
|
|
689
851
|
const expiresAt = new Date(Date.now() + timeoutMs).toISOString();
|
|
690
852
|
this.readiness = 'awaiting_permission';
|
|
@@ -723,8 +885,8 @@ export class AcpSession {
|
|
|
723
885
|
return new Promise(resolve => {
|
|
724
886
|
const pending = {
|
|
725
887
|
options: params.options, resolve,
|
|
726
|
-
toolCallId
|
|
727
|
-
|
|
888
|
+
toolCallId,
|
|
889
|
+
eventToolCallId: scheduledTurn(this.activeTurn) ? 'scheduled-loop-tool' : toolCallId,
|
|
728
890
|
};
|
|
729
891
|
pending.expiry = setTimeout(() => {
|
|
730
892
|
this.settlePendingAutomatically(permissionId, pending, 'expired', undefined, `no decision arrived within ${Math.round(timeoutMs / 1000)}s`);
|
|
@@ -832,6 +994,10 @@ export class AcpSession {
|
|
|
832
994
|
title: scheduled ? 'scheduled-loop tool' : update.title,
|
|
833
995
|
status: update.status,
|
|
834
996
|
});
|
|
997
|
+
if (TERMINAL_TOOL_STATUSES.has(update.status ?? ''))
|
|
998
|
+
this.releaseTool(update.toolCallId);
|
|
999
|
+
else
|
|
1000
|
+
this.reserveTool(update.toolCallId);
|
|
835
1001
|
break;
|
|
836
1002
|
case 'tool_call_update':
|
|
837
1003
|
this.events.emit('tool_update', {
|
|
@@ -841,6 +1007,10 @@ export class AcpSession {
|
|
|
841
1007
|
title: scheduled ? 'scheduled-loop tool' : update.title ?? undefined,
|
|
842
1008
|
status: update.status ?? undefined,
|
|
843
1009
|
});
|
|
1010
|
+
if (TERMINAL_TOOL_STATUSES.has(update.status ?? ''))
|
|
1011
|
+
this.releaseTool(update.toolCallId);
|
|
1012
|
+
else if (update.status !== undefined)
|
|
1013
|
+
this.reserveTool(update.toolCallId);
|
|
844
1014
|
break;
|
|
845
1015
|
default:
|
|
846
1016
|
break;
|
|
@@ -864,7 +1034,10 @@ export class AcpSession {
|
|
|
864
1034
|
}
|
|
865
1035
|
/** Normalize every ACP update losslessly into the durable ledger. */
|
|
866
1036
|
recordConversationUpdate(update, scheduled, commentary = false) {
|
|
867
|
-
const normalized = normalizeSessionUpdate(update, scheduled ? {
|
|
1037
|
+
const normalized = normalizeSessionUpdate(update, scheduled ? {
|
|
1038
|
+
redactText: SCHEDULED_LOOP_REDACTION,
|
|
1039
|
+
redactToolCallId: 'scheduled-loop-tool',
|
|
1040
|
+
}
|
|
868
1041
|
: commentary ? { redactText: OWNER_COMMENTARY_REDACTION } : {});
|
|
869
1042
|
this.conversation.appendSafe({
|
|
870
1043
|
kind: normalized.kind,
|
|
@@ -27,6 +27,11 @@ export declare class RoleTurnArbiter implements SessionHandle {
|
|
|
27
27
|
private track;
|
|
28
28
|
queuePrompt(text: string, options?: SubmitPromptOptions): Promise<QueuedPrompt>;
|
|
29
29
|
submitPrompt(text: string, options?: SubmitPromptOptions): Promise<TurnResult>;
|
|
30
|
+
/**
|
|
31
|
+
* Do not hold `exclusive` while ACP waits for a tool boundary: permission
|
|
32
|
+
* answers and explicit interrupts must remain able to pass immediately.
|
|
33
|
+
*/
|
|
34
|
+
submitPromptAfterTool(text: string, options?: SubmitPromptOptions): Promise<TurnResult>;
|
|
30
35
|
tryScheduled(text: string, origin: Extract<PromptOrigin, {
|
|
31
36
|
kind: 'scheduled-loop';
|
|
32
37
|
}>, beforeQueue?: () => void | Promise<void>): Promise<ScheduledAttempt>;
|
package/dist/session/arbiter.js
CHANGED
|
@@ -32,6 +32,14 @@ export class RoleTurnArbiter {
|
|
|
32
32
|
async submitPrompt(text, options = {}) {
|
|
33
33
|
return (await this.queuePrompt(text, options)).completion;
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Do not hold `exclusive` while ACP waits for a tool boundary: permission
|
|
37
|
+
* answers and explicit interrupts must remain able to pass immediately.
|
|
38
|
+
*/
|
|
39
|
+
submitPromptAfterTool(text, options = {}) {
|
|
40
|
+
return this.session.submitPromptAfterTool?.(text, options)
|
|
41
|
+
?? this.session.submitPrompt(text, { ...options, interrupt: false, steer: false });
|
|
42
|
+
}
|
|
35
43
|
async tryScheduled(text, origin, beforeQueue) {
|
|
36
44
|
// Give owner/console/I/O callbacks already ready in this event-loop turn a
|
|
37
45
|
// chance to claim the arbiter first. Scheduled work is best-effort; humans
|
|
@@ -23,6 +23,12 @@ export interface NormalizeOptions {
|
|
|
23
23
|
* digest. Used for scheduled-loop turns whose output must not be retained.
|
|
24
24
|
*/
|
|
25
25
|
redactText?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Replace ACP tool-call IDs in both the normalized event correlation field
|
|
28
|
+
* and payload. The caller may still use the original update for in-memory
|
|
29
|
+
* lifecycle tracking without persisting its private identifier.
|
|
30
|
+
*/
|
|
31
|
+
redactToolCallId?: string;
|
|
26
32
|
}
|
|
27
33
|
export interface NormalizedUpdate {
|
|
28
34
|
kind: ConversationEventKind;
|
|
@@ -203,9 +203,10 @@ function normalizeToolContent(raw, redact) {
|
|
|
203
203
|
}
|
|
204
204
|
});
|
|
205
205
|
}
|
|
206
|
-
function toolUpsert(update, snapshot,
|
|
206
|
+
function toolUpsert(update, snapshot, options) {
|
|
207
|
+
const redact = options.redactText;
|
|
207
208
|
const payload = {
|
|
208
|
-
toolCallId: asString(update.toolCallId) ?? '',
|
|
209
|
+
toolCallId: options.redactToolCallId ?? asString(update.toolCallId) ?? '',
|
|
209
210
|
snapshot,
|
|
210
211
|
};
|
|
211
212
|
if (asString(update.title) !== undefined)
|
|
@@ -271,7 +272,7 @@ export function normalizeSessionUpdate(update, options = {}) {
|
|
|
271
272
|
}
|
|
272
273
|
case 'tool_call':
|
|
273
274
|
case 'tool_call_update': {
|
|
274
|
-
const payload = toolUpsert(raw, raw.sessionUpdate === 'tool_call',
|
|
275
|
+
const payload = toolUpsert(raw, raw.sessionUpdate === 'tool_call', options);
|
|
275
276
|
return withMeta({
|
|
276
277
|
kind: 'tool.upsert', payload,
|
|
277
278
|
...(payload.toolCallId ? { toolCallId: payload.toolCallId } : {}),
|
|
@@ -7,7 +7,7 @@ import type { PromptOrigin, TurnCancellationSource, TurnOutcome } from './types.
|
|
|
7
7
|
* file touches the wire: ACP updates are reduced into these shapes by the
|
|
8
8
|
* normalizer, and the store (phase 1) assigns `seq`/`eventId`/timestamps.
|
|
9
9
|
*/
|
|
10
|
-
export type ConversationEventKind = 'prompt.admitted' | 'prompt.started' | 'prompt.interrupt_requested' | 'message.chunk' | 'message.replace' | 'thought.chunk' | 'thought.replace' | 'plan.replace' | 'tool.upsert' | 'tool.content_chunk' | 'permission.requested' | 'permission.resolved' | 'usage.updated' | 'turn.state' | 'turn.completed' | 'session.state' | 'session.info' | 'capabilities.updated' | 'error'
|
|
10
|
+
export type ConversationEventKind = 'prompt.admitted' | 'prompt.started' | 'prompt.interrupt_requested' | 'message.chunk' | 'message.replace' | 'thought.chunk' | 'thought.replace' | 'plan.replace' | 'tool.upsert' | 'tool.content_chunk' | 'permission.requested' | 'permission.resolved' | 'monitor.delivery' | 'usage.updated' | 'turn.state' | 'turn.completed' | 'session.state' | 'session.info' | 'capabilities.updated' | 'error'
|
|
11
11
|
/** A well-formed ACP update this version cannot represent. Bounded, never a crash. */
|
|
12
12
|
| 'unsupported';
|
|
13
13
|
/** Where a conversation record came from. Typed provenance, never prompt text. */
|
|
@@ -178,6 +178,13 @@ export interface PermissionResolvedPayload {
|
|
|
178
178
|
policy?: string;
|
|
179
179
|
reason?: string;
|
|
180
180
|
}
|
|
181
|
+
/** Body-free monitor evidence. Tool ids, titles, output, and wake text are never stored. */
|
|
182
|
+
export interface MonitorDeliveryPayload {
|
|
183
|
+
policy: 'after_tool';
|
|
184
|
+
state: 'deferred' | 'direct' | 'after_tool' | 'timeout' | 'unsupported';
|
|
185
|
+
activeToolCount: number;
|
|
186
|
+
waitedMs: number;
|
|
187
|
+
}
|
|
181
188
|
export interface TurnStatePayload {
|
|
182
189
|
state: 'queued' | 'running' | 'awaiting_permission' | 'interrupt_requested';
|
|
183
190
|
}
|
|
@@ -201,7 +208,7 @@ export interface BoundedJson {
|
|
|
201
208
|
digest?: string;
|
|
202
209
|
redacted?: true;
|
|
203
210
|
}
|
|
204
|
-
export type ConversationPayload = MessageChunkPayload | ThoughtChunkPayload | PlanReplacePayload | ToolUpsertPayload | UsageUpdatedPayload | SessionStatePayload | SessionInfoPayload | CapabilitiesUpdatedPayload | UnsupportedPayload | PromptAdmittedPayload | PromptStartedPayload | PromptInterruptRequestedPayload | PermissionRequestedPayload | PermissionResolvedPayload | TurnStatePayload | TurnCompletedPayload | SessionLifecyclePayload | ErrorPayload;
|
|
211
|
+
export type ConversationPayload = MessageChunkPayload | ThoughtChunkPayload | PlanReplacePayload | ToolUpsertPayload | UsageUpdatedPayload | SessionStatePayload | SessionInfoPayload | CapabilitiesUpdatedPayload | UnsupportedPayload | PromptAdmittedPayload | PromptStartedPayload | PromptInterruptRequestedPayload | PermissionRequestedPayload | PermissionResolvedPayload | TurnStatePayload | TurnCompletedPayload | MonitorDeliveryPayload | SessionLifecyclePayload | ErrorPayload;
|
|
205
212
|
export interface ConversationEventV1 {
|
|
206
213
|
schemaVersion: 1;
|
|
207
214
|
roleId: string;
|
package/dist/session/types.d.ts
CHANGED
|
@@ -49,6 +49,12 @@ export interface TurnResult {
|
|
|
49
49
|
cancellationSource?: TurnCancellationSource;
|
|
50
50
|
/** Final assistant text captured structurally by a backend, when available. */
|
|
51
51
|
output?: string;
|
|
52
|
+
/** Body-free monitor safe-boundary disposition, when this was an after_tool wake. */
|
|
53
|
+
safeBoundary?: {
|
|
54
|
+
state: 'direct' | 'after_tool' | 'timeout' | 'unsupported';
|
|
55
|
+
waitedMs: number;
|
|
56
|
+
activeToolCount: number;
|
|
57
|
+
};
|
|
52
58
|
}
|
|
53
59
|
/**
|
|
54
60
|
* Why a control operation failed. The distinctions exist because collapsing
|
|
@@ -137,7 +143,7 @@ export interface SessionSnapshot {
|
|
|
137
143
|
nativeMode: string;
|
|
138
144
|
};
|
|
139
145
|
}
|
|
140
|
-
export type SessionEventKind = 'state' | 'agent_text' | 'thought' | 'tool_call' | 'tool_update' | 'permission' | 'turn_stop' | 'error';
|
|
146
|
+
export type SessionEventKind = 'state' | 'agent_text' | 'thought' | 'tool_call' | 'tool_update' | 'permission' | 'monitor_delivery' | 'turn_stop' | 'error';
|
|
141
147
|
/** What a settled permission request resolved to. */
|
|
142
148
|
export type PermissionDecision = 'allowed' | 'denied' | 'cancelled';
|
|
143
149
|
export interface SessionEvent {
|
|
@@ -178,6 +184,10 @@ export interface SessionEvent {
|
|
|
178
184
|
reason?: string;
|
|
179
185
|
/** The option actually selected, when one was. */
|
|
180
186
|
optionId?: string;
|
|
187
|
+
/** Body-free evidence for monitor safe-boundary delivery. */
|
|
188
|
+
monitorPolicy?: 'after_tool';
|
|
189
|
+
activeToolCount?: number;
|
|
190
|
+
waitedMs?: number;
|
|
181
191
|
}
|
|
182
192
|
export interface ConversationHandlePage {
|
|
183
193
|
events: ConversationEventV1[];
|
|
@@ -206,6 +216,8 @@ export interface SessionHandle {
|
|
|
206
216
|
queuePrompt(text: string, options?: SubmitPromptOptions): Promise<QueuedPrompt>;
|
|
207
217
|
/** Queue a prompt and wait for its terminal result. */
|
|
208
218
|
submitPrompt(text: string, options?: SubmitPromptOptions): Promise<TurnResult>;
|
|
219
|
+
/** Monitor-only ACP safe-boundary delivery. Never implies human/control cancellation. */
|
|
220
|
+
submitPromptAfterTool?(text: string, options?: SubmitPromptOptions): Promise<TurnResult>;
|
|
209
221
|
interrupt(source?: TurnCancellationSource): Promise<void>;
|
|
210
222
|
respondPermission(permissionId: string, optionId: string): boolean;
|
|
211
223
|
/** Generation-bound browser decision; stale/settled/invalid all fail closed. */
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{r as le,a as Ee,j as re}from"./index-
|
|
1
|
+
import{r as le,a as Ee,j as re}from"./index-CliHATFt.js";var ge={exports:{}},Se;function ke(){return Se||(Se=1,(function(se,ne){(function(Q,X){se.exports=X()})(globalThis,(()=>(()=>{var Q={4567:function(B,r,o){var l=this&&this.__decorate||function(e,i,a,v){var f,g=arguments.length,c=g<3?i:v===null?v=Object.getOwnPropertyDescriptor(i,a):v;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")c=Reflect.decorate(e,i,a,v);else for(var m=e.length-1;m>=0;m--)(f=e[m])&&(c=(g<3?f(c):g>3?f(i,a,c):f(i,a))||c);return g>3&&c&&Object.defineProperty(i,a,c),c},_=this&&this.__param||function(e,i){return function(a,v){i(a,v,e)}};Object.defineProperty(r,"__esModule",{value:!0}),r.AccessibilityManager=void 0;const n=o(9042),d=o(9924),u=o(844),p=o(4725),h=o(2585),t=o(3656);let s=r.AccessibilityManager=class extends u.Disposable{constructor(e,i,a,v){super(),this._terminal=e,this._coreBrowserService=a,this._renderService=v,this._rowColumns=new WeakMap,this._liveRegionLineCount=0,this._charsToConsume=[],this._charsToAnnounce="",this._accessibilityContainer=this._coreBrowserService.mainDocument.createElement("div"),this._accessibilityContainer.classList.add("xterm-accessibility"),this._rowContainer=this._coreBrowserService.mainDocument.createElement("div"),this._rowContainer.setAttribute("role","list"),this._rowContainer.classList.add("xterm-accessibility-tree"),this._rowElements=[];for(let f=0;f<this._terminal.rows;f++)this._rowElements[f]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[f]);if(this._topBoundaryFocusListener=f=>this._handleBoundaryFocus(f,0),this._bottomBoundaryFocusListener=f=>this._handleBoundaryFocus(f,1),this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions(),this._accessibilityContainer.appendChild(this._rowContainer),this._liveRegion=this._coreBrowserService.mainDocument.createElement("div"),this._liveRegion.classList.add("live-region"),this._liveRegion.setAttribute("aria-live","assertive"),this._accessibilityContainer.appendChild(this._liveRegion),this._liveRegionDebouncer=this.register(new d.TimeBasedDebouncer(this._renderRows.bind(this))),!this._terminal.element)throw new Error("Cannot enable accessibility before Terminal.open");this._terminal.element.insertAdjacentElement("afterbegin",this._accessibilityContainer),this.register(this._terminal.onResize((f=>this._handleResize(f.rows)))),this.register(this._terminal.onRender((f=>this._refreshRows(f.start,f.end)))),this.register(this._terminal.onScroll((()=>this._refreshRows()))),this.register(this._terminal.onA11yChar((f=>this._handleChar(f)))),this.register(this._terminal.onLineFeed((()=>this._handleChar(`
|
|
2
2
|
`)))),this.register(this._terminal.onA11yTab((f=>this._handleTab(f)))),this.register(this._terminal.onKey((f=>this._handleKey(f.key)))),this.register(this._terminal.onBlur((()=>this._clearLiveRegion()))),this.register(this._renderService.onDimensionsChange((()=>this._refreshRowsDimensions()))),this.register((0,t.addDisposableDomListener)(document,"selectionchange",(()=>this._handleSelectionChange()))),this.register(this._coreBrowserService.onDprChange((()=>this._refreshRowsDimensions()))),this._refreshRows(),this.register((0,u.toDisposable)((()=>{this._accessibilityContainer.remove(),this._rowElements.length=0})))}_handleTab(e){for(let i=0;i<e;i++)this._handleChar(" ")}_handleChar(e){this._liveRegionLineCount<21&&(this._charsToConsume.length>0?this._charsToConsume.shift()!==e&&(this._charsToAnnounce+=e):this._charsToAnnounce+=e,e===`
|
|
3
3
|
`&&(this._liveRegionLineCount++,this._liveRegionLineCount===21&&(this._liveRegion.textContent+=n.tooMuchOutput)))}_clearLiveRegion(){this._liveRegion.textContent="",this._liveRegionLineCount=0}_handleKey(e){this._clearLiveRegion(),new RegExp("\\p{Control}","u").test(e)||this._charsToConsume.push(e)}_refreshRows(e,i){this._liveRegionDebouncer.refresh(e,i,this._terminal.rows)}_renderRows(e,i){const a=this._terminal.buffer,v=a.lines.length.toString();for(let f=e;f<=i;f++){const g=a.lines.get(a.ydisp+f),c=[],m=g?.translateToString(!0,void 0,void 0,c)||"",E=(a.ydisp+f+1).toString(),k=this._rowElements[f];k&&(m.length===0?(k.innerText=" ",this._rowColumns.set(k,[0,1])):(k.textContent=m,this._rowColumns.set(k,c)),k.setAttribute("aria-posinset",E),k.setAttribute("aria-setsize",v))}this._announceCharacters()}_announceCharacters(){this._charsToAnnounce.length!==0&&(this._liveRegion.textContent+=this._charsToAnnounce,this._charsToAnnounce="")}_handleBoundaryFocus(e,i){const a=e.target,v=this._rowElements[i===0?1:this._rowElements.length-2];if(a.getAttribute("aria-posinset")===(i===0?"1":`${this._terminal.buffer.lines.length}`)||e.relatedTarget!==v)return;let f,g;if(i===0?(f=a,g=this._rowElements.pop(),this._rowContainer.removeChild(g)):(f=this._rowElements.shift(),g=a,this._rowContainer.removeChild(f)),f.removeEventListener("focus",this._topBoundaryFocusListener),g.removeEventListener("focus",this._bottomBoundaryFocusListener),i===0){const c=this._createAccessibilityTreeNode();this._rowElements.unshift(c),this._rowContainer.insertAdjacentElement("afterbegin",c)}else{const c=this._createAccessibilityTreeNode();this._rowElements.push(c),this._rowContainer.appendChild(c)}this._rowElements[0].addEventListener("focus",this._topBoundaryFocusListener),this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._terminal.scrollLines(i===0?-1:1),this._rowElements[i===0?1:this._rowElements.length-2].focus(),e.preventDefault(),e.stopImmediatePropagation()}_handleSelectionChange(){if(this._rowElements.length===0)return;const e=document.getSelection();if(!e)return;if(e.isCollapsed)return void(this._rowContainer.contains(e.anchorNode)&&this._terminal.clearSelection());if(!e.anchorNode||!e.focusNode)return void console.error("anchorNode and/or focusNode are null");let i={node:e.anchorNode,offset:e.anchorOffset},a={node:e.focusNode,offset:e.focusOffset};if((i.node.compareDocumentPosition(a.node)&Node.DOCUMENT_POSITION_PRECEDING||i.node===a.node&&i.offset>a.offset)&&([i,a]=[a,i]),i.node.compareDocumentPosition(this._rowElements[0])&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_FOLLOWING)&&(i={node:this._rowElements[0].childNodes[0],offset:0}),!this._rowContainer.contains(i.node))return;const v=this._rowElements.slice(-1)[0];if(a.node.compareDocumentPosition(v)&(Node.DOCUMENT_POSITION_CONTAINED_BY|Node.DOCUMENT_POSITION_PRECEDING)&&(a={node:v,offset:v.textContent?.length??0}),!this._rowContainer.contains(a.node))return;const f=({node:m,offset:E})=>{const k=m instanceof Text?m.parentNode:m;let D=parseInt(k?.getAttribute("aria-posinset"),10)-1;if(isNaN(D))return console.warn("row is invalid. Race condition?"),null;const b=this._rowColumns.get(k);if(!b)return console.warn("columns is null. Race condition?"),null;let x=E<b.length?b[E]:b.slice(-1)[0]+1;return x>=this._terminal.cols&&(++D,x=0),{row:D,column:x}},g=f(i),c=f(a);if(g&&c){if(g.row>c.row||g.row===c.row&&g.column>=c.column)throw new Error("invalid range");this._terminal.select(g.column,g.row,(c.row-g.row)*this._terminal.cols-g.column+c.column)}}_handleResize(e){this._rowElements[this._rowElements.length-1].removeEventListener("focus",this._bottomBoundaryFocusListener);for(let i=this._rowContainer.children.length;i<this._terminal.rows;i++)this._rowElements[i]=this._createAccessibilityTreeNode(),this._rowContainer.appendChild(this._rowElements[i]);for(;this._rowElements.length>e;)this._rowContainer.removeChild(this._rowElements.pop());this._rowElements[this._rowElements.length-1].addEventListener("focus",this._bottomBoundaryFocusListener),this._refreshRowsDimensions()}_createAccessibilityTreeNode(){const e=this._coreBrowserService.mainDocument.createElement("div");return e.setAttribute("role","listitem"),e.tabIndex=-1,this._refreshRowDimensions(e),e}_refreshRowsDimensions(){if(this._renderService.dimensions.css.cell.height){this._accessibilityContainer.style.width=`${this._renderService.dimensions.css.canvas.width}px`,this._rowElements.length!==this._terminal.rows&&this._handleResize(this._terminal.rows);for(let e=0;e<this._terminal.rows;e++)this._refreshRowDimensions(this._rowElements[e])}}_refreshRowDimensions(e){e.style.height=`${this._renderService.dimensions.css.cell.height}px`}};r.AccessibilityManager=s=l([_(1,h.IInstantiationService),_(2,p.ICoreBrowserService),_(3,p.IRenderService)],s)},3614:(B,r)=>{function o(d){return d.replace(/\r?\n/g,"\r")}function l(d,u){return u?"\x1B[200~"+d+"\x1B[201~":d}function _(d,u,p,h){d=l(d=o(d),p.decPrivateModes.bracketedPasteMode&&h.rawOptions.ignoreBracketedPasteMode!==!0),p.triggerDataEvent(d,!0),u.value=""}function n(d,u,p){const h=p.getBoundingClientRect(),t=d.clientX-h.left-10,s=d.clientY-h.top-10;u.style.width="20px",u.style.height="20px",u.style.left=`${t}px`,u.style.top=`${s}px`,u.style.zIndex="1000",u.focus()}Object.defineProperty(r,"__esModule",{value:!0}),r.rightClickHandler=r.moveTextAreaUnderMouseCursor=r.paste=r.handlePasteEvent=r.copyHandler=r.bracketTextForPaste=r.prepareTextForTerminal=void 0,r.prepareTextForTerminal=o,r.bracketTextForPaste=l,r.copyHandler=function(d,u){d.clipboardData&&d.clipboardData.setData("text/plain",u.selectionText),d.preventDefault()},r.handlePasteEvent=function(d,u,p,h){d.stopPropagation(),d.clipboardData&&_(d.clipboardData.getData("text/plain"),u,p,h)},r.paste=_,r.moveTextAreaUnderMouseCursor=n,r.rightClickHandler=function(d,u,p,h,t){n(d,u,p),t&&h.rightClickSelect(d),u.value=h.selectionText,u.select()}},7239:(B,r,o)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.ColorContrastCache=void 0;const l=o(1505);r.ColorContrastCache=class{constructor(){this._color=new l.TwoKeyMap,this._css=new l.TwoKeyMap}setCss(_,n,d){this._css.set(_,n,d)}getCss(_,n){return this._css.get(_,n)}setColor(_,n,d){this._color.set(_,n,d)}getColor(_,n){return this._color.get(_,n)}clear(){this._color.clear(),this._css.clear()}}},3656:(B,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.addDisposableDomListener=void 0,r.addDisposableDomListener=function(o,l,_,n){o.addEventListener(l,_,n);let d=!1;return{dispose:()=>{d||(d=!0,o.removeEventListener(l,_,n))}}}},3551:function(B,r,o){var l=this&&this.__decorate||function(s,e,i,a){var v,f=arguments.length,g=f<3?e:a===null?a=Object.getOwnPropertyDescriptor(e,i):a;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")g=Reflect.decorate(s,e,i,a);else for(var c=s.length-1;c>=0;c--)(v=s[c])&&(g=(f<3?v(g):f>3?v(e,i,g):v(e,i))||g);return f>3&&g&&Object.defineProperty(e,i,g),g},_=this&&this.__param||function(s,e){return function(i,a){e(i,a,s)}};Object.defineProperty(r,"__esModule",{value:!0}),r.Linkifier=void 0;const n=o(3656),d=o(8460),u=o(844),p=o(2585),h=o(4725);let t=r.Linkifier=class extends u.Disposable{get currentLink(){return this._currentLink}constructor(s,e,i,a,v){super(),this._element=s,this._mouseService=e,this._renderService=i,this._bufferService=a,this._linkProviderService=v,this._linkCacheDisposables=[],this._isMouseOut=!0,this._wasResized=!1,this._activeLine=-1,this._onShowLinkUnderline=this.register(new d.EventEmitter),this.onShowLinkUnderline=this._onShowLinkUnderline.event,this._onHideLinkUnderline=this.register(new d.EventEmitter),this.onHideLinkUnderline=this._onHideLinkUnderline.event,this.register((0,u.getDisposeArrayDisposable)(this._linkCacheDisposables)),this.register((0,u.toDisposable)((()=>{this._lastMouseEvent=void 0,this._activeProviderReplies?.clear()}))),this.register(this._bufferService.onResize((()=>{this._clearCurrentLink(),this._wasResized=!0}))),this.register((0,n.addDisposableDomListener)(this._element,"mouseleave",(()=>{this._isMouseOut=!0,this._clearCurrentLink()}))),this.register((0,n.addDisposableDomListener)(this._element,"mousemove",this._handleMouseMove.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mousedown",this._handleMouseDown.bind(this))),this.register((0,n.addDisposableDomListener)(this._element,"mouseup",this._handleMouseUp.bind(this)))}_handleMouseMove(s){this._lastMouseEvent=s;const e=this._positionFromMouseEvent(s,this._element,this._mouseService);if(!e)return;this._isMouseOut=!1;const i=s.composedPath();for(let a=0;a<i.length;a++){const v=i[a];if(v.classList.contains("xterm"))break;if(v.classList.contains("xterm-hover"))return}this._lastBufferCell&&e.x===this._lastBufferCell.x&&e.y===this._lastBufferCell.y||(this._handleHover(e),this._lastBufferCell=e)}_handleHover(s){if(this._activeLine!==s.y||this._wasResized)return this._clearCurrentLink(),this._askForLink(s,!1),void(this._wasResized=!1);this._currentLink&&this._linkAtPosition(this._currentLink.link,s)||(this._clearCurrentLink(),this._askForLink(s,!0))}_askForLink(s,e){this._activeProviderReplies&&e||(this._activeProviderReplies?.forEach((a=>{a?.forEach((v=>{v.link.dispose&&v.link.dispose()}))})),this._activeProviderReplies=new Map,this._activeLine=s.y);let i=!1;for(const[a,v]of this._linkProviderService.linkProviders.entries())e?this._activeProviderReplies?.get(a)&&(i=this._checkLinkProviderResult(a,s,i)):v.provideLinks(s.y,(f=>{if(this._isMouseOut)return;const g=f?.map((c=>({link:c})));this._activeProviderReplies?.set(a,g),i=this._checkLinkProviderResult(a,s,i),this._activeProviderReplies?.size===this._linkProviderService.linkProviders.length&&this._removeIntersectingLinks(s.y,this._activeProviderReplies)}))}_removeIntersectingLinks(s,e){const i=new Set;for(let a=0;a<e.size;a++){const v=e.get(a);if(v)for(let f=0;f<v.length;f++){const g=v[f],c=g.link.range.start.y<s?0:g.link.range.start.x,m=g.link.range.end.y>s?this._bufferService.cols:g.link.range.end.x;for(let E=c;E<=m;E++){if(i.has(E)){v.splice(f--,1);break}i.add(E)}}}}_checkLinkProviderResult(s,e,i){if(!this._activeProviderReplies)return i;const a=this._activeProviderReplies.get(s);let v=!1;for(let f=0;f<s;f++)this._activeProviderReplies.has(f)&&!this._activeProviderReplies.get(f)||(v=!0);if(!v&&a){const f=a.find((g=>this._linkAtPosition(g.link,e)));f&&(i=!0,this._handleNewLink(f))}if(this._activeProviderReplies.size===this._linkProviderService.linkProviders.length&&!i)for(let f=0;f<this._activeProviderReplies.size;f++){const g=this._activeProviderReplies.get(f)?.find((c=>this._linkAtPosition(c.link,e)));if(g){i=!0,this._handleNewLink(g);break}}return i}_handleMouseDown(){this._mouseDownLink=this._currentLink}_handleMouseUp(s){if(!this._currentLink)return;const e=this._positionFromMouseEvent(s,this._element,this._mouseService);e&&this._mouseDownLink===this._currentLink&&this._linkAtPosition(this._currentLink.link,e)&&this._currentLink.link.activate(s,this._currentLink.link.text)}_clearCurrentLink(s,e){this._currentLink&&this._lastMouseEvent&&(!s||!e||this._currentLink.link.range.start.y>=s&&this._currentLink.link.range.end.y<=e)&&(this._linkLeave(this._element,this._currentLink.link,this._lastMouseEvent),this._currentLink=void 0,(0,u.disposeArray)(this._linkCacheDisposables))}_handleNewLink(s){if(!this._lastMouseEvent)return;const e=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);e&&this._linkAtPosition(s.link,e)&&(this._currentLink=s,this._currentLink.state={decorations:{underline:s.link.decorations===void 0||s.link.decorations.underline,pointerCursor:s.link.decorations===void 0||s.link.decorations.pointerCursor},isHovered:!0},this._linkHover(this._element,s.link,this._lastMouseEvent),s.link.decorations={},Object.defineProperties(s.link.decorations,{pointerCursor:{get:()=>this._currentLink?.state?.decorations.pointerCursor,set:i=>{this._currentLink?.state&&this._currentLink.state.decorations.pointerCursor!==i&&(this._currentLink.state.decorations.pointerCursor=i,this._currentLink.state.isHovered&&this._element.classList.toggle("xterm-cursor-pointer",i))}},underline:{get:()=>this._currentLink?.state?.decorations.underline,set:i=>{this._currentLink?.state&&this._currentLink?.state?.decorations.underline!==i&&(this._currentLink.state.decorations.underline=i,this._currentLink.state.isHovered&&this._fireUnderlineEvent(s.link,i))}}}),this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange((i=>{if(!this._currentLink)return;const a=i.start===0?0:i.start+1+this._bufferService.buffer.ydisp,v=this._bufferService.buffer.ydisp+1+i.end;if(this._currentLink.link.range.start.y>=a&&this._currentLink.link.range.end.y<=v&&(this._clearCurrentLink(a,v),this._lastMouseEvent)){const f=this._positionFromMouseEvent(this._lastMouseEvent,this._element,this._mouseService);f&&this._askForLink(f,!1)}}))))}_linkHover(s,e,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!0,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(e,!0),this._currentLink.state.decorations.pointerCursor&&s.classList.add("xterm-cursor-pointer")),e.hover&&e.hover(i,e.text)}_fireUnderlineEvent(s,e){const i=s.range,a=this._bufferService.buffer.ydisp,v=this._createLinkUnderlineEvent(i.start.x-1,i.start.y-a-1,i.end.x,i.end.y-a-1,void 0);(e?this._onShowLinkUnderline:this._onHideLinkUnderline).fire(v)}_linkLeave(s,e,i){this._currentLink?.state&&(this._currentLink.state.isHovered=!1,this._currentLink.state.decorations.underline&&this._fireUnderlineEvent(e,!1),this._currentLink.state.decorations.pointerCursor&&s.classList.remove("xterm-cursor-pointer")),e.leave&&e.leave(i,e.text)}_linkAtPosition(s,e){const i=s.range.start.y*this._bufferService.cols+s.range.start.x,a=s.range.end.y*this._bufferService.cols+s.range.end.x,v=e.y*this._bufferService.cols+e.x;return i<=v&&v<=a}_positionFromMouseEvent(s,e,i){const a=i.getCoords(s,e,this._bufferService.cols,this._bufferService.rows);if(a)return{x:a[0],y:a[1]+this._bufferService.buffer.ydisp}}_createLinkUnderlineEvent(s,e,i,a,v){return{x1:s,y1:e,x2:i,y2:a,cols:this._bufferService.cols,fg:v}}};r.Linkifier=t=l([_(1,h.IMouseService),_(2,h.IRenderService),_(3,p.IBufferService),_(4,h.ILinkProviderService)],t)},9042:(B,r)=>{Object.defineProperty(r,"__esModule",{value:!0}),r.tooMuchOutput=r.promptLabel=void 0,r.promptLabel="Terminal input",r.tooMuchOutput="Too much output to announce, navigate to rows manually to read"},3730:function(B,r,o){var l=this&&this.__decorate||function(h,t,s,e){var i,a=arguments.length,v=a<3?t:e===null?e=Object.getOwnPropertyDescriptor(t,s):e;if(typeof Reflect=="object"&&typeof Reflect.decorate=="function")v=Reflect.decorate(h,t,s,e);else for(var f=h.length-1;f>=0;f--)(i=h[f])&&(v=(a<3?i(v):a>3?i(t,s,v):i(t,s))||v);return a>3&&v&&Object.defineProperty(t,s,v),v},_=this&&this.__param||function(h,t){return function(s,e){t(s,e,h)}};Object.defineProperty(r,"__esModule",{value:!0}),r.OscLinkProvider=void 0;const n=o(511),d=o(2585);let u=r.OscLinkProvider=class{constructor(h,t,s){this._bufferService=h,this._optionsService=t,this._oscLinkService=s}provideLinks(h,t){const s=this._bufferService.buffer.lines.get(h-1);if(!s)return void t(void 0);const e=[],i=this._optionsService.rawOptions.linkHandler,a=new n.CellData,v=s.getTrimmedLength();let f=-1,g=-1,c=!1;for(let m=0;m<v;m++)if(g!==-1||s.hasContent(m)){if(s.loadCell(m,a),a.hasExtendedAttrs()&&a.extended.urlId){if(g===-1){g=m,f=a.extended.urlId;continue}c=a.extended.urlId!==f}else g!==-1&&(c=!0);if(c||g!==-1&&m===v-1){const E=this._oscLinkService.getLinkData(f)?.uri;if(E){const k={start:{x:g+1,y:h},end:{x:m+(c||m!==v-1?0:1),y:h}};let D=!1;if(!i?.allowNonHttpProtocols)try{const b=new URL(E);["http:","https:"].includes(b.protocol)||(D=!0)}catch{D=!0}D||e.push({text:E,range:k,activate:(b,x)=>i?i.activate(b,x,k):p(0,x),hover:(b,x)=>i?.hover?.(b,x,k),leave:(b,x)=>i?.leave?.(b,x,k)})}c=!1,a.hasExtendedAttrs()&&a.extended.urlId?(g=m,f=a.extended.urlId):(g=-1,f=-1)}}t(e)}};function p(h,t){if(confirm(`Do you want to navigate to ${t}?
|
|
4
4
|
|