@ours.network/fleet 0.17.9 → 0.17.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 +38 -3
- package/dist/briefing.js +4 -2
- package/dist/build-info.json +4 -4
- package/dist/config.d.ts +6 -3
- package/dist/config.js +28 -14
- package/dist/docs.d.ts +1 -1
- package/dist/docs.js +32 -4
- package/dist/model-env.d.ts +71 -0
- package/dist/model-env.js +106 -0
- package/dist/runner.d.ts +9 -0
- package/dist/runner.js +27 -3
- package/dist/session/acp.d.ts +3 -0
- package/dist/session/acp.js +29 -2
- package/dist/session/conversation-normalizer.d.ts +6 -0
- package/dist/session/conversation-normalizer.js +153 -10
- package/dist/session/conversation-types.d.ts +23 -4
- package/dist/spawn.js +28 -16
- package/dist/web-app/assets/{TerminalView-BAVk1Bot.js → TerminalView-C_G1ID2P.js} +1 -1
- package/dist/web-app/assets/{index-C3S-xFRU.js → index-BCBK78hw.js} +5 -5
- package/dist/web-app/index.html +1 -1
- package/dist/worklog.d.ts +7 -1
- package/dist/worklog.js +191 -39
- package/package.json +1 -1
package/dist/runner.d.ts
CHANGED
|
@@ -35,6 +35,15 @@ export interface RunnerDeps {
|
|
|
35
35
|
}
|
|
36
36
|
/** Environment injected only into the managed harness process. */
|
|
37
37
|
export declare function managedFleetProxyEnv(role: ResolvedRole, stateDir: string): Record<string, string>;
|
|
38
|
+
/**
|
|
39
|
+
* The environment a managed harness child actually receives, checked at the one
|
|
40
|
+
* point where it is composed. `role.env` deliberately wins over harness prep,
|
|
41
|
+
* which is exactly how a stale fleet-wide model pin used to outrank the model
|
|
42
|
+
* the role was spawned with — so the model pin is verified here rather than
|
|
43
|
+
* trusted, and a disagreement stops the launch instead of being reported as a
|
|
44
|
+
* success (see src/model-env.ts).
|
|
45
|
+
*/
|
|
46
|
+
export declare function harnessChildEnv(role: ResolvedRole, launchEnv: Record<string, string> | undefined, stateDir: string): Record<string, string>;
|
|
38
47
|
/**
|
|
39
48
|
* Record who owns wake delivery for this run. Returning true means a fleet
|
|
40
49
|
* monitor is taking ownership back from a native harness and must start at the
|
package/dist/runner.js
CHANGED
|
@@ -24,6 +24,7 @@ import { RoleTurnArbiter } from './session/arbiter.js';
|
|
|
24
24
|
import { ScheduledLoopManager, } from './loops/manager.js';
|
|
25
25
|
import { FLEET_PROXY_CALLER_ENV, FLEET_PROXY_STATE_DIR_ENV, inheritCallerSpawnDefaults, } from './fleet-proxy.js';
|
|
26
26
|
import { effectivePermissionMode } from './permissions.js';
|
|
27
|
+
import { assertModelPinReachesChild, effectiveRoleModel, repinModelEnv } from './model-env.js';
|
|
27
28
|
import { archiveTempState, markTempSupervisorActive, requestedTempStopReason, } from './temp-lifecycle.js';
|
|
28
29
|
const defaultDeps = () => ({
|
|
29
30
|
tmux: new Tmux(),
|
|
@@ -72,6 +73,19 @@ export function managedFleetProxyEnv(role, stateDir) {
|
|
|
72
73
|
[FLEET_PROXY_CALLER_ENV]: role.name,
|
|
73
74
|
};
|
|
74
75
|
}
|
|
76
|
+
/**
|
|
77
|
+
* The environment a managed harness child actually receives, checked at the one
|
|
78
|
+
* point where it is composed. `role.env` deliberately wins over harness prep,
|
|
79
|
+
* which is exactly how a stale fleet-wide model pin used to outrank the model
|
|
80
|
+
* the role was spawned with — so the model pin is verified here rather than
|
|
81
|
+
* trusted, and a disagreement stops the launch instead of being reported as a
|
|
82
|
+
* success (see src/model-env.ts).
|
|
83
|
+
*/
|
|
84
|
+
export function harnessChildEnv(role, launchEnv, stateDir) {
|
|
85
|
+
const env = { ...(launchEnv ?? {}), ...managedFleetProxyEnv(role, stateDir) };
|
|
86
|
+
assertModelPinReachesChild(role, env);
|
|
87
|
+
return env;
|
|
88
|
+
}
|
|
75
89
|
/**
|
|
76
90
|
* Execute a typed proxy request in the caller's supervisor. Dynamic imports
|
|
77
91
|
* avoid a runner↔spawn initialization cycle (spawn imports runner constants).
|
|
@@ -109,7 +123,9 @@ async function executeManagedSpawn(caller, configPath, requested, log) {
|
|
|
109
123
|
statePath,
|
|
110
124
|
harness: preview.harness,
|
|
111
125
|
session: preview.session,
|
|
112
|
-
|
|
126
|
+
// Read back from the resolved environment, not from the request: the banner
|
|
127
|
+
// must name the model the child will run, not the one that was asked for.
|
|
128
|
+
...(effectiveRoleModel(preview) ? { model: effectiveRoleModel(preview) } : {}),
|
|
113
129
|
monitor: { mode: preview.monitor.mode, interrupt: preview.monitor.interrupt },
|
|
114
130
|
permissionMode: effectivePermissionMode(preview),
|
|
115
131
|
inherited,
|
|
@@ -117,6 +133,7 @@ async function executeManagedSpawn(caller, configPath, requested, log) {
|
|
|
117
133
|
};
|
|
118
134
|
log(`[${caller.name}] managed fleet proxy spawned ${result.lifetime} role ${result.role} `
|
|
119
135
|
+ `harness=${result.harness} session=${result.session} `
|
|
136
|
+
+ `model=${result.model ?? '(harness default)'} `
|
|
120
137
|
+ `permission=${result.permissionMode.fleetMode} `
|
|
121
138
|
+ `native=${result.permissionMode.nativeMode}`);
|
|
122
139
|
return result;
|
|
@@ -458,11 +475,18 @@ export async function runOnce(name, opts = {}, partialDeps = {}) {
|
|
|
458
475
|
const effectiveModel = effectiveModelForRole(dir, role);
|
|
459
476
|
if (effectiveModel !== role.model) {
|
|
460
477
|
deps.log(`[${name}] model recovery drift: declared=${role.model ?? '(none)'} effective=${effectiveModel}`);
|
|
461
|
-
|
|
478
|
+
// The env pin has to move with it. A down-shift that changed only
|
|
479
|
+
// `role.model` was reported as a model change while the child kept running
|
|
480
|
+
// the model that had just failed, because the pin is what the harness reads.
|
|
481
|
+
role = { ...role, model: effectiveModel, env: repinModelEnv(role, effectiveModel) };
|
|
462
482
|
}
|
|
463
483
|
if (modelRecoveryHeld(dir))
|
|
464
484
|
throw new Error(`[${name}] model chain exhausted — held down until config changes or recovery reset`);
|
|
465
485
|
const adapter = getAdapter(role.harness);
|
|
486
|
+
// Say the running model out loud, once, from the resolved environment. The
|
|
487
|
+
// spawn banner is a claim made before the process exists; this is the log line
|
|
488
|
+
// that can be checked against the session afterwards.
|
|
489
|
+
deps.log(`[${name}] model: ${effectiveRoleModel(role) ?? '(harness default)'}`);
|
|
466
490
|
mkdirSync(dir, { recursive: true });
|
|
467
491
|
const rotation = rotateWorklog(join(dir, 'WORKLOG.md'), role.worklog);
|
|
468
492
|
if (rotation.deferred)
|
|
@@ -603,7 +627,7 @@ export async function runOnce(name, opts = {}, partialDeps = {}) {
|
|
|
603
627
|
name,
|
|
604
628
|
argv: wrappedArgv,
|
|
605
629
|
cwd: runCwd,
|
|
606
|
-
env:
|
|
630
|
+
env: harnessChildEnv(role, launch.env, dir),
|
|
607
631
|
stateDir: dir,
|
|
608
632
|
mode,
|
|
609
633
|
permissions: perms,
|
package/dist/session/acp.d.ts
CHANGED
|
@@ -83,6 +83,8 @@ export declare class AcpSession implements SessionHandle {
|
|
|
83
83
|
private readonly child;
|
|
84
84
|
private readonly events;
|
|
85
85
|
private readonly conversation;
|
|
86
|
+
/** Cursor before this runner generation began; older durable events stay off the live console. */
|
|
87
|
+
private readonly conversationStartCursor?;
|
|
86
88
|
/** New on every runner start; permission/turn IDs from prior generations are stale. */
|
|
87
89
|
private readonly sessionGeneration;
|
|
88
90
|
/** True while `session/load` replays history as ordinary updates. */
|
|
@@ -300,5 +302,6 @@ export declare class AcpSession implements SessionHandle {
|
|
|
300
302
|
}): ConversationHandlePage;
|
|
301
303
|
conversationSnapshot(): ConversationSnapshot;
|
|
302
304
|
subscribeConversation(listener: Parameters<ConversationEventStore['subscribe']>[0]): () => void;
|
|
305
|
+
private isCurrentConversationEvent;
|
|
303
306
|
private fail;
|
|
304
307
|
}
|
package/dist/session/acp.js
CHANGED
|
@@ -208,6 +208,8 @@ export class AcpSession {
|
|
|
208
208
|
child;
|
|
209
209
|
events;
|
|
210
210
|
conversation;
|
|
211
|
+
/** Cursor before this runner generation began; older durable events stay off the live console. */
|
|
212
|
+
conversationStartCursor;
|
|
211
213
|
/** New on every runner start; permission/turn IDs from prior generations are stale. */
|
|
212
214
|
sessionGeneration = randomUUID();
|
|
213
215
|
/** True while `session/load` replays history as ordinary updates. */
|
|
@@ -265,6 +267,7 @@ export class AcpSession {
|
|
|
265
267
|
this.conversation = new ConversationEventStore(join(options.stateDir, '.conversation'), {
|
|
266
268
|
roleId: options.name, log: line => options.log(`[${options.name}] ${line}`),
|
|
267
269
|
});
|
|
270
|
+
this.conversationStartCursor = this.conversation.lastCursor();
|
|
268
271
|
this.sessionFile = join(options.stateDir, '.acp-session-id');
|
|
269
272
|
this.terminated = new Promise((_resolve, reject) => { this.terminate = reject; });
|
|
270
273
|
// Nothing awaits this promise until a request races it; an unobserved
|
|
@@ -1464,7 +1467,25 @@ export class AcpSession {
|
|
|
1464
1467
|
}
|
|
1465
1468
|
// ── conversation ledger access (SessionHandle) ─────────────────────────────
|
|
1466
1469
|
conversationPage(request = {}) {
|
|
1467
|
-
|
|
1470
|
+
const floor = Number(this.conversationStartCursor ?? 0);
|
|
1471
|
+
const requested = Number(request.after ?? 0);
|
|
1472
|
+
let after = String(Math.max(Number.isSafeInteger(floor) ? floor : 0, Number.isSafeInteger(requested) ? requested : 0));
|
|
1473
|
+
const limit = Math.min(Math.max(request.limit ?? 200, 1), 1_000);
|
|
1474
|
+
let page = this.conversation.page({ after, limit });
|
|
1475
|
+
let visible = page.events.filter(event => this.isCurrentConversationEvent(event));
|
|
1476
|
+
// A resumed adapter may replay a page made entirely of prior session/load
|
|
1477
|
+
// history. Advance over it without exposing it or making the browser stop
|
|
1478
|
+
// before later current-session records.
|
|
1479
|
+
while (!visible.length && page.hasMore && page.nextCursor && page.nextCursor !== after) {
|
|
1480
|
+
after = page.nextCursor;
|
|
1481
|
+
page = this.conversation.page({ after, limit });
|
|
1482
|
+
visible = page.events.filter(event => this.isCurrentConversationEvent(event));
|
|
1483
|
+
}
|
|
1484
|
+
return {
|
|
1485
|
+
...page,
|
|
1486
|
+
events: visible,
|
|
1487
|
+
snapshot: this.conversationSnapshot(),
|
|
1488
|
+
};
|
|
1468
1489
|
}
|
|
1469
1490
|
conversationSnapshot() {
|
|
1470
1491
|
return {
|
|
@@ -1476,7 +1497,13 @@ export class AcpSession {
|
|
|
1476
1497
|
};
|
|
1477
1498
|
}
|
|
1478
1499
|
subscribeConversation(listener) {
|
|
1479
|
-
return this.conversation.subscribe(
|
|
1500
|
+
return this.conversation.subscribe(event => {
|
|
1501
|
+
if (this.isCurrentConversationEvent(event))
|
|
1502
|
+
listener(event);
|
|
1503
|
+
});
|
|
1504
|
+
}
|
|
1505
|
+
isCurrentConversationEvent(event) {
|
|
1506
|
+
return event.sessionGeneration === this.sessionGeneration && event.source !== 'agent_replay';
|
|
1480
1507
|
}
|
|
1481
1508
|
fail(error) {
|
|
1482
1509
|
this.lastError = error?.message ?? String(error);
|
|
@@ -11,6 +11,12 @@ import type { AdapterMeta, ConversationEventKind, ConversationPayload } from './
|
|
|
11
11
|
*/
|
|
12
12
|
/** Cap for any single normalized text payload (spec §5.3). */
|
|
13
13
|
export declare const MAX_TEXT_BYTES: number;
|
|
14
|
+
/** Cap for each retained side of an oversized snapshot-style file diff. */
|
|
15
|
+
export declare const MAX_DIFF_TEXT_BYTES: number;
|
|
16
|
+
/** Cap for attacker-controlled filesystem paths while retaining their useful basename tail. */
|
|
17
|
+
export declare const MAX_PATH_BYTES: number;
|
|
18
|
+
/** Hard cap for the complete normalized update before the durable event envelope is added. */
|
|
19
|
+
export declare const MAX_NORMALIZED_UPDATE_BYTES: number;
|
|
14
20
|
/** Cap for one adapter `_meta` namespace value. */
|
|
15
21
|
export declare const MAX_META_BYTES: number;
|
|
16
22
|
/** Cap for serialized raw tool input/output retained as structured JSON. */
|
|
@@ -10,6 +10,12 @@ import { createHash } from 'node:crypto';
|
|
|
10
10
|
*/
|
|
11
11
|
/** Cap for any single normalized text payload (spec §5.3). */
|
|
12
12
|
export const MAX_TEXT_BYTES = 256 * 1024;
|
|
13
|
+
/** Cap for each retained side of an oversized snapshot-style file diff. */
|
|
14
|
+
export const MAX_DIFF_TEXT_BYTES = 64 * 1024;
|
|
15
|
+
/** Cap for attacker-controlled filesystem paths while retaining their useful basename tail. */
|
|
16
|
+
export const MAX_PATH_BYTES = 4 * 1024;
|
|
17
|
+
/** Hard cap for the complete normalized update before the durable event envelope is added. */
|
|
18
|
+
export const MAX_NORMALIZED_UPDATE_BYTES = 320 * 1024;
|
|
13
19
|
/** Cap for one adapter `_meta` namespace value. */
|
|
14
20
|
export const MAX_META_BYTES = 16 * 1024;
|
|
15
21
|
/** Cap for serialized raw tool input/output retained as structured JSON. */
|
|
@@ -27,6 +33,28 @@ function truncateUtf8(text, maxBytes) {
|
|
|
27
33
|
const buffer = Buffer.from(text).subarray(0, maxBytes);
|
|
28
34
|
return buffer.toString('utf8').replace(/�+$/u, '');
|
|
29
35
|
}
|
|
36
|
+
/** Keep a UTF-8-safe suffix. Paths and identifiers have no line semantics. */
|
|
37
|
+
function truncateUtf8Tail(text, maxBytes) {
|
|
38
|
+
const buffer = Buffer.from(text);
|
|
39
|
+
let start = Math.max(0, buffer.length - maxBytes);
|
|
40
|
+
while (start < buffer.length && (buffer[start] & 0xc0) === 0x80)
|
|
41
|
+
start++;
|
|
42
|
+
return { text: buffer.subarray(start).toString('utf8'), omittedPrefixBytes: start };
|
|
43
|
+
}
|
|
44
|
+
function boundedPath(raw) {
|
|
45
|
+
const path = asString(raw) ?? '';
|
|
46
|
+
const pathBytes = Buffer.byteLength(path);
|
|
47
|
+
if (pathBytes <= MAX_PATH_BYTES)
|
|
48
|
+
return { path };
|
|
49
|
+
const retained = truncateUtf8Tail(path, MAX_PATH_BYTES);
|
|
50
|
+
return {
|
|
51
|
+
path: retained.text,
|
|
52
|
+
pathBytes,
|
|
53
|
+
pathTruncated: true,
|
|
54
|
+
pathDigest: digest24(path),
|
|
55
|
+
pathOmittedPrefixBytes: retained.omittedPrefixBytes,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
30
58
|
function cappedText(raw, redact) {
|
|
31
59
|
const text = asString(raw) ?? '';
|
|
32
60
|
const bytes = Buffer.byteLength(text);
|
|
@@ -39,6 +67,95 @@ function cappedText(raw, redact) {
|
|
|
39
67
|
truncated: true, digest: digest24(text),
|
|
40
68
|
};
|
|
41
69
|
}
|
|
70
|
+
/** Keep the newest UTF-8 tail, aligning to a whole line whenever one fits. */
|
|
71
|
+
function cappedTextTail(text, maxBytes) {
|
|
72
|
+
const buffer = Buffer.from(text);
|
|
73
|
+
const bytes = buffer.length;
|
|
74
|
+
if (bytes <= maxBytes)
|
|
75
|
+
return { text, bytes };
|
|
76
|
+
let start = bytes - maxBytes;
|
|
77
|
+
while (start < bytes && (buffer[start] & 0xc0) === 0x80)
|
|
78
|
+
start++;
|
|
79
|
+
let startsMidLine = start > 0 && buffer[start - 1] !== 0x0a;
|
|
80
|
+
if (startsMidLine) {
|
|
81
|
+
const newline = buffer.indexOf(0x0a, start);
|
|
82
|
+
if (newline >= 0 && newline + 1 < bytes) {
|
|
83
|
+
start = newline + 1;
|
|
84
|
+
startsMidLine = false;
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
text: buffer.subarray(start).toString('utf8'), bytes,
|
|
89
|
+
truncated: true, digest: digest24(text), omittedPrefixBytes: start,
|
|
90
|
+
...(startsMidLine ? { startsMidLine: true } : {}),
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
/** Common unchanged edges in UTF-16 indices, adjusted away from split surrogates. */
|
|
94
|
+
function commonEdges(oldText, newText) {
|
|
95
|
+
const limit = Math.min(oldText.length, newText.length);
|
|
96
|
+
let prefix = 0;
|
|
97
|
+
while (prefix < limit && oldText.charCodeAt(prefix) === newText.charCodeAt(prefix))
|
|
98
|
+
prefix++;
|
|
99
|
+
if (prefix > 0 && prefix < limit
|
|
100
|
+
&& oldText.charCodeAt(prefix) >= 0xdc00 && oldText.charCodeAt(prefix) <= 0xdfff)
|
|
101
|
+
prefix--;
|
|
102
|
+
let oldEnd = oldText.length;
|
|
103
|
+
let newEnd = newText.length;
|
|
104
|
+
while (oldEnd > prefix && newEnd > prefix
|
|
105
|
+
&& oldText.charCodeAt(oldEnd - 1) === newText.charCodeAt(newEnd - 1)) {
|
|
106
|
+
oldEnd--;
|
|
107
|
+
newEnd--;
|
|
108
|
+
}
|
|
109
|
+
// A suffix must never begin at the low half of a surrogate pair.
|
|
110
|
+
if (oldEnd < oldText.length && oldText.charCodeAt(oldEnd) >= 0xdc00
|
|
111
|
+
&& oldText.charCodeAt(oldEnd) <= 0xdfff) {
|
|
112
|
+
oldEnd++;
|
|
113
|
+
newEnd++;
|
|
114
|
+
}
|
|
115
|
+
return { prefix, suffix: oldText.length - oldEnd };
|
|
116
|
+
}
|
|
117
|
+
function normalizedDiff(item, redact) {
|
|
118
|
+
const path = boundedPath(item.path);
|
|
119
|
+
const oldText = asString(item.oldText);
|
|
120
|
+
const newText = asString(item.newText) ?? '';
|
|
121
|
+
// Preserve the established small-diff contract exactly. Redacted turns also
|
|
122
|
+
// retain their established placeholder shape and never derive private text.
|
|
123
|
+
if (redact !== undefined || oldText === undefined
|
|
124
|
+
|| (Buffer.byteLength(oldText) <= MAX_TEXT_BYTES
|
|
125
|
+
&& Buffer.byteLength(newText) <= MAX_TEXT_BYTES)) {
|
|
126
|
+
return {
|
|
127
|
+
type: 'diff', ...path,
|
|
128
|
+
newText: cappedText(newText, redact),
|
|
129
|
+
...(oldText !== undefined ? { oldText: cappedText(oldText, redact) } : {}),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
// ACP adapters may describe an append by sending two complete file snapshots.
|
|
133
|
+
// Persist only the changed region: otherwise a multi-megabyte historical file
|
|
134
|
+
// contributes its prefix twice while the current append disappears past the cap.
|
|
135
|
+
const { prefix, suffix } = commonEdges(oldText, newText);
|
|
136
|
+
const oldEnd = oldText.length - suffix;
|
|
137
|
+
const newEnd = newText.length - suffix;
|
|
138
|
+
const oldDelta = oldText.slice(prefix, oldEnd);
|
|
139
|
+
const newDelta = newText.slice(prefix, newEnd);
|
|
140
|
+
const beforeBytes = Buffer.byteLength(oldText);
|
|
141
|
+
const afterBytes = Buffer.byteLength(newText);
|
|
142
|
+
const commonPrefixBytes = Buffer.byteLength(oldText.slice(0, prefix));
|
|
143
|
+
const commonSuffixBytes = Buffer.byteLength(oldText.slice(oldEnd));
|
|
144
|
+
const operation = oldDelta.length === 0 && newDelta.length === 0
|
|
145
|
+
? 'noop'
|
|
146
|
+
: oldDelta.length === 0 && prefix === oldText.length
|
|
147
|
+
? 'append'
|
|
148
|
+
: newDelta.length === 0
|
|
149
|
+
? 'delete'
|
|
150
|
+
: prefix === 0 && suffix === 0 ? 'replace' : 'edit';
|
|
151
|
+
return {
|
|
152
|
+
type: 'diff', ...path, operation, beforeBytes, afterBytes,
|
|
153
|
+
commonPrefixBytes, commonSuffixBytes, bounded: true,
|
|
154
|
+
newText: cappedTextTail(newDelta, MAX_DIFF_TEXT_BYTES),
|
|
155
|
+
...(oldDelta.length > 0
|
|
156
|
+
? { oldText: cappedTextTail(oldDelta, MAX_DIFF_TEXT_BYTES) } : {}),
|
|
157
|
+
};
|
|
158
|
+
}
|
|
42
159
|
function normalizedText(raw, redact) {
|
|
43
160
|
const text = asString(raw) ?? '';
|
|
44
161
|
const bytes = Buffer.byteLength(text);
|
|
@@ -189,12 +306,7 @@ function normalizeToolContent(raw, redact) {
|
|
|
189
306
|
return raw.filter(isRecord).map((item) => {
|
|
190
307
|
switch (item.type) {
|
|
191
308
|
case 'diff':
|
|
192
|
-
return
|
|
193
|
-
type: 'diff',
|
|
194
|
-
path: asString(item.path) ?? '',
|
|
195
|
-
newText: cappedText(item.newText, redact),
|
|
196
|
-
...(item.oldText != null ? { oldText: cappedText(item.oldText, redact) } : {}),
|
|
197
|
-
};
|
|
309
|
+
return normalizedDiff(item, redact);
|
|
198
310
|
case 'terminal':
|
|
199
311
|
return { type: 'terminal', terminalId: asString(item.terminalId) ?? '' };
|
|
200
312
|
case 'content':
|
|
@@ -220,7 +332,7 @@ function toolUpsert(update, snapshot, options) {
|
|
|
220
332
|
payload.content = content;
|
|
221
333
|
if (Array.isArray(update.locations)) {
|
|
222
334
|
payload.locations = update.locations.filter(isRecord).map(location => ({
|
|
223
|
-
|
|
335
|
+
...boundedPath(location.path),
|
|
224
336
|
...(asFiniteNumber(location.line) !== undefined ? { line: asFiniteNumber(location.line) } : {}),
|
|
225
337
|
}));
|
|
226
338
|
}
|
|
@@ -240,18 +352,49 @@ function unsupported(update) {
|
|
|
240
352
|
}
|
|
241
353
|
const kind = isRecord(update) ? asString(update.sessionUpdate) : undefined;
|
|
242
354
|
return {
|
|
243
|
-
sessionUpdate: kind ?? 'unknown',
|
|
355
|
+
sessionUpdate: truncateUtf8(kind ?? 'unknown', 256),
|
|
244
356
|
bytes: Buffer.byteLength(serialized),
|
|
245
357
|
preview: serialized.slice(0, MAX_UNSUPPORTED_PREVIEW_CHARS),
|
|
358
|
+
...(Buffer.byteLength(serialized) > Buffer.byteLength(serialized.slice(0, MAX_UNSUPPORTED_PREVIEW_CHARS))
|
|
359
|
+
? { digest: digest24(serialized) } : {}),
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
function capNormalizedUpdate(result, sessionUpdate) {
|
|
363
|
+
let serialized;
|
|
364
|
+
try {
|
|
365
|
+
serialized = JSON.stringify(result);
|
|
366
|
+
}
|
|
367
|
+
catch {
|
|
368
|
+
return {
|
|
369
|
+
kind: 'unsupported',
|
|
370
|
+
payload: {
|
|
371
|
+
sessionUpdate: truncateUtf8(sessionUpdate, 256),
|
|
372
|
+
bytes: 0,
|
|
373
|
+
preview: '[normalized update was not serializable]',
|
|
374
|
+
},
|
|
375
|
+
};
|
|
376
|
+
}
|
|
377
|
+
const bytes = Buffer.byteLength(serialized);
|
|
378
|
+
if (bytes <= MAX_NORMALIZED_UPDATE_BYTES)
|
|
379
|
+
return result;
|
|
380
|
+
return {
|
|
381
|
+
kind: 'unsupported',
|
|
382
|
+
payload: {
|
|
383
|
+
sessionUpdate: truncateUtf8(sessionUpdate, 256),
|
|
384
|
+
bytes,
|
|
385
|
+
digest: digest24(serialized),
|
|
386
|
+
preview: `[normalized update exceeded ${MAX_NORMALIZED_UPDATE_BYTES}-byte durable-event cap]`,
|
|
387
|
+
},
|
|
246
388
|
};
|
|
247
389
|
}
|
|
248
390
|
export function normalizeSessionUpdate(update, options = {}) {
|
|
249
391
|
const redact = options.redactText;
|
|
250
392
|
const raw = update;
|
|
251
393
|
if (!isRecord(raw) || typeof raw.sessionUpdate !== 'string')
|
|
252
|
-
return { kind: 'unsupported', payload: unsupported(raw) };
|
|
394
|
+
return capNormalizedUpdate({ kind: 'unsupported', payload: unsupported(raw) }, 'unknown');
|
|
395
|
+
const sessionUpdate = raw.sessionUpdate;
|
|
253
396
|
const adapterMeta = quarantineMeta(raw._meta);
|
|
254
|
-
const withMeta = (result) => adapterMeta ? { ...result, adapterMeta } : result;
|
|
397
|
+
const withMeta = (result) => capNormalizedUpdate(adapterMeta ? { ...result, adapterMeta } : result, sessionUpdate);
|
|
255
398
|
switch (raw.sessionUpdate) {
|
|
256
399
|
case 'user_message_chunk':
|
|
257
400
|
case 'agent_message_chunk': {
|
|
@@ -48,15 +48,33 @@ export interface CappedText {
|
|
|
48
48
|
bytes: number;
|
|
49
49
|
truncated?: true;
|
|
50
50
|
digest?: string;
|
|
51
|
+
/** Bytes omitted from the front when the retained fragment is a tail. */
|
|
52
|
+
omittedPrefixBytes?: number;
|
|
53
|
+
/** The retained tail starts inside one logical line because that line alone exceeded the cap. */
|
|
54
|
+
startsMidLine?: true;
|
|
55
|
+
}
|
|
56
|
+
/** A path kept as a UTF-8-safe tail, with additive provenance only when capped. */
|
|
57
|
+
export interface BoundedPath {
|
|
58
|
+
path: string;
|
|
59
|
+
pathBytes?: number;
|
|
60
|
+
pathTruncated?: true;
|
|
61
|
+
pathDigest?: string;
|
|
62
|
+
pathOmittedPrefixBytes?: number;
|
|
51
63
|
}
|
|
52
64
|
export type NormalizedToolContent = {
|
|
53
65
|
type: 'content';
|
|
54
66
|
content: NormalizedContentBlock;
|
|
55
|
-
} | {
|
|
67
|
+
} | BoundedPath & {
|
|
56
68
|
type: 'diff';
|
|
57
|
-
path: string;
|
|
58
69
|
newText: CappedText;
|
|
59
70
|
oldText?: CappedText;
|
|
71
|
+
/** Additive provenance for oversized snapshot diffs reduced to their changed region. */
|
|
72
|
+
operation?: 'append' | 'edit' | 'delete' | 'noop' | 'replace';
|
|
73
|
+
beforeBytes?: number;
|
|
74
|
+
afterBytes?: number;
|
|
75
|
+
commonPrefixBytes?: number;
|
|
76
|
+
commonSuffixBytes?: number;
|
|
77
|
+
bounded?: true;
|
|
60
78
|
}
|
|
61
79
|
/** A tool-owned display terminal reference — never a PTY attachment. */
|
|
62
80
|
| {
|
|
@@ -105,8 +123,7 @@ export interface ToolUpsertPayload {
|
|
|
105
123
|
kind?: string;
|
|
106
124
|
status?: string;
|
|
107
125
|
content?: NormalizedToolContent[];
|
|
108
|
-
locations?: Array<{
|
|
109
|
-
path: string;
|
|
126
|
+
locations?: Array<BoundedPath & {
|
|
110
127
|
line?: number;
|
|
111
128
|
}>;
|
|
112
129
|
rawInput?: BoundedJson;
|
|
@@ -140,6 +157,8 @@ export interface UnsupportedPayload {
|
|
|
140
157
|
/** The wire discriminant (or 'unknown' when even that was absent). */
|
|
141
158
|
sessionUpdate: string;
|
|
142
159
|
bytes: number;
|
|
160
|
+
/** Digest of the omitted original/normalized representation when it was bounded. */
|
|
161
|
+
digest?: string;
|
|
143
162
|
/** Sanitized JSON preview, capped; enough to diagnose, never to exhaust. */
|
|
144
163
|
preview?: string;
|
|
145
164
|
}
|
package/dist/spawn.js
CHANGED
|
@@ -5,6 +5,7 @@ import { parse, stringify } from 'yaml';
|
|
|
5
5
|
import { agentDir, fleetDDir } from './paths.js';
|
|
6
6
|
import { validateIsolationConfig } from './isolation/policy.js';
|
|
7
7
|
import { loadConfig, resolveAuthProxy, resolveModelChain, resolveMonitorConfig, resolveOwnerChannelConfig, resolvePermissions, resolveRoleModel, resolveWorklogPolicy, validateMonitorConfig, } from './config.js';
|
|
8
|
+
import { resolveRoleModelEnv } from './model-env.js';
|
|
8
9
|
import { applyRole, up } from './ops.js';
|
|
9
10
|
import { START_STAGGER_FILE } from './runner.js';
|
|
10
11
|
import { buildProvenance, daemonIdentityProvisioner, ensureIdentity, provenanceOf, withCreationTransaction, writeProvenance, writeRoleFile, } from './creation.js';
|
|
@@ -191,7 +192,17 @@ export function spawnDryRun(o) {
|
|
|
191
192
|
const harness = raw.harness ?? cfg.defaults.harness ?? 'claude-code';
|
|
192
193
|
const defaultHarness = cfg.defaults.harness ?? 'claude-code';
|
|
193
194
|
const inheritsModelDefaults = harness === defaultHarness && raw.model !== null;
|
|
194
|
-
const
|
|
195
|
+
const authProxy = resolveAuthProxy(cfg.defaults.auth_proxy, raw.auth_proxy);
|
|
196
|
+
// One resolution for the environment and the model it pins (src/model-env.ts).
|
|
197
|
+
const modelEnv = resolveRoleModelEnv({
|
|
198
|
+
harness,
|
|
199
|
+
model: resolveRoleModel(raw.model, raw.harness, cfg.defaults),
|
|
200
|
+
modelWasExplicit: raw.model !== undefined,
|
|
201
|
+
defaultsEnv: (cfg.defaults.env ?? {}),
|
|
202
|
+
roleEnv: raw.env,
|
|
203
|
+
...(authProxy ? { authProxyBaseUrl: authProxy.base_url } : {}),
|
|
204
|
+
});
|
|
205
|
+
const model = modelEnv.model;
|
|
195
206
|
const session = raw.session ?? cfg.defaults.session ?? 'tmux';
|
|
196
207
|
const resolvedRole = {
|
|
197
208
|
...raw,
|
|
@@ -212,15 +223,9 @@ export function spawnDryRun(o) {
|
|
|
212
223
|
monitor: resolveMonitorConfig(cfg.defaults.monitor, raw.monitor),
|
|
213
224
|
owner_channel: resolveOwnerChannelConfig(cfg.defaults.owner_channel, raw.owner_channel, session),
|
|
214
225
|
worklog: resolveWorklogPolicy(cfg.defaults.worklog, raw.worklog),
|
|
215
|
-
auth_proxy:
|
|
216
|
-
};
|
|
217
|
-
resolvedRole.env = {
|
|
218
|
-
...(cfg.defaults.env ?? {}),
|
|
219
|
-
...(raw.env ?? {}),
|
|
220
|
-
...(resolvedRole.auth_proxy
|
|
221
|
-
? { ANTHROPIC_BASE_URL: resolvedRole.auth_proxy.base_url }
|
|
222
|
-
: {}),
|
|
226
|
+
auth_proxy: authProxy,
|
|
223
227
|
};
|
|
228
|
+
resolvedRole.env = modelEnv.env;
|
|
224
229
|
const adapter = getAdapter(resolvedRole.harness);
|
|
225
230
|
if (resolvedRole.auth_proxy && resolvedRole.harness !== 'claude-code')
|
|
226
231
|
throw new Error('auth_proxy is supported only by claude-code');
|
|
@@ -403,7 +408,18 @@ async function spawnTempInner(o, binPath, launch, tx, guarantee, onStage) {
|
|
|
403
408
|
};
|
|
404
409
|
const harness = o.harness ?? defaultHarness ?? 'claude-code';
|
|
405
410
|
const inheritsModelDefaults = harness === (defaultHarness ?? 'claude-code') && o.model !== null;
|
|
406
|
-
const
|
|
411
|
+
const tempAuthProxy = resolveAuthProxy(cfg.defaults.auth_proxy, fromOpts.auth_proxy);
|
|
412
|
+
// An explicitly requested --model must reach the child, not just the banner
|
|
413
|
+
// (src/model-env.ts).
|
|
414
|
+
const modelEnv = resolveRoleModelEnv({
|
|
415
|
+
harness,
|
|
416
|
+
model: resolveRoleModel(o.model, o.harness, cfg.defaults),
|
|
417
|
+
modelWasExplicit: o.model !== undefined,
|
|
418
|
+
defaultsEnv: (cfg.defaults.env ?? {}),
|
|
419
|
+
roleEnv: fromOpts.env,
|
|
420
|
+
...(tempAuthProxy ? { authProxyBaseUrl: tempAuthProxy.base_url } : {}),
|
|
421
|
+
});
|
|
422
|
+
const model = modelEnv.model;
|
|
407
423
|
const session = o.session ?? cfg.defaults.session ?? 'tmux';
|
|
408
424
|
const role = {
|
|
409
425
|
...fromOpts, // includes `isolation` when --isolation-file was given
|
|
@@ -422,14 +438,10 @@ async function spawnTempInner(o, binPath, launch, tx, guarantee, onStage) {
|
|
|
422
438
|
monitor: resolveMonitorConfig(cfg.defaults.monitor, fromOpts.monitor),
|
|
423
439
|
owner_channel: resolveOwnerChannelConfig(cfg.defaults.owner_channel, fromOpts.owner_channel, session),
|
|
424
440
|
worklog: resolveWorklogPolicy(cfg.defaults.worklog, fromOpts.worklog),
|
|
425
|
-
auth_proxy:
|
|
441
|
+
auth_proxy: tempAuthProxy,
|
|
426
442
|
sourceFile: '(temp)',
|
|
427
443
|
};
|
|
428
|
-
role.env =
|
|
429
|
-
...(cfg.defaults.env ?? {}),
|
|
430
|
-
...(fromOpts.env ?? {}),
|
|
431
|
-
...(role.auth_proxy ? { ANTHROPIC_BASE_URL: role.auth_proxy.base_url } : {}),
|
|
432
|
-
};
|
|
444
|
+
role.env = modelEnv.env;
|
|
433
445
|
if (role.auth_proxy && role.harness !== 'claude-code')
|
|
434
446
|
throw new Error('auth_proxy is supported only by claude-code');
|
|
435
447
|
onStage?.('writing_role');
|
|
@@ -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-BCBK78hw.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
|
|