@timurproko/a1 0.2.7-dev.810 → 0.2.7-dev.828
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 +7 -1
- package/bin/automatic-update.js +7 -0
- package/bin/tab-launch-context.d.ts +1 -0
- package/bin/tab-launch-context.js +3 -3
- package/bin/ui.js +96 -66
- package/dist/app/session-shell/resident-tab-coordinator.d.ts +6 -9
- package/dist/app/session-shell/resident-tab-coordinator.js +9 -52
- package/dist/app/session-shell/session-shell-root.d.ts +14 -8
- package/dist/app/session-shell/session-shell-root.js +9 -5
- package/dist/app/session-shell/session-shell.js +70 -20
- package/dist/app/session-shell/session-viewport-controller.js +6 -4
- package/dist/app/session-shell/shell-host.js +6 -3
- package/dist/app/session-shell/transcript-document.js +1 -1
- package/dist/cli/tabs.d.ts +1 -1
- package/dist/cli/tabs.js +10 -14
- package/dist/composition/owned-settings.d.ts +12 -0
- package/dist/composition/owned-settings.js +36 -0
- package/dist/composition/owned-ui.d.ts +5 -14
- package/dist/composition/owned-ui.js +93 -64
- package/dist/composition/resident-tab-bridge.d.ts +10 -1
- package/dist/composition/resident-tab-bridge.js +21 -0
- package/dist/composition/settings-route-host.d.ts +12 -2
- package/dist/composition/settings-route-host.js +27 -9
- package/dist/composition/settings-search-input.d.ts +9 -0
- package/dist/composition/settings-search-input.js +58 -0
- package/dist/composition/utility-tab.d.ts +28 -0
- package/dist/composition/utility-tab.js +242 -0
- package/dist/contracts/owned-ui/session-backend.d.ts +2 -0
- package/dist/contracts/owned-ui/session-workflows.d.ts +7 -3
- package/dist/contracts/presentation/index.d.ts +11 -0
- package/dist/contracts/presentation/index.js +12 -0
- package/dist/features/launch/development-launch.js +6 -0
- package/dist/features/launch/profile-paths.js +4 -0
- package/dist/features/owned-ui/plus-menu-dialog.d.ts +22 -0
- package/dist/features/owned-ui/plus-menu-dialog.js +76 -0
- package/dist/features/owned-ui/project-trust-dialog.d.ts +1 -1
- package/dist/features/owned-ui/project-trust-dialog.js +6 -8
- package/dist/features/owned-ui/project-trust-prompt.d.ts +1 -0
- package/dist/features/owned-ui/project-trust-prompt.js +7 -3
- package/dist/features/owned-ui/reference-screen-app.d.ts +2 -0
- package/dist/features/owned-ui/reference-screen-app.js +12 -2
- package/dist/features/owned-ui/settings-app.d.ts +10 -3
- package/dist/features/owned-ui/settings-app.js +98 -45
- package/dist/features/owned-ui/settings-search-input.d.ts +29 -0
- package/dist/features/owned-ui/settings-search-input.js +1 -0
- package/dist/features/prompt-history/index.d.ts +1 -1
- package/dist/features/prompt-history/paths.d.ts +2 -1
- package/dist/features/prompt-history/paths.js +10 -2
- package/dist/features/prompt-history/service.d.ts +5 -0
- package/dist/features/prompt-history/service.js +1 -1
- package/dist/features/resident-tab/shortcut-declarations.d.ts +1 -1
- package/dist/features/resident-tab/shortcut-declarations.js +2 -0
- package/dist/foundation/launch-context/index.d.ts +2 -0
- package/dist/foundation/launch-context/index.js +1 -0
- package/dist/foundation/lifecycle/session-repository-context.js +16 -2
- package/dist/foundation/release/automatic-update.d.ts +37 -0
- package/dist/foundation/release/automatic-update.js +265 -0
- package/dist/foundation/release/bootstrap.d.ts +1 -9
- package/dist/foundation/release/bootstrap.js +7 -3
- package/dist/foundation/release/early-accent.d.ts +12 -0
- package/dist/foundation/release/early-accent.js +59 -0
- package/dist/foundation/release/index.d.ts +1 -1
- package/dist/foundation/release/index.js +1 -1
- package/dist/foundation/release/latest-release.d.ts +3 -2
- package/dist/foundation/release/latest-release.js +1 -1
- package/dist/foundation/release/progress-palette.generated.d.ts +137 -3
- package/dist/foundation/release/progress-palette.generated.js +137 -3
- package/dist/foundation/release/release-gc.js +19 -4
- package/dist/foundation/release/update-execution-lease.d.ts +36 -0
- package/dist/foundation/release/update-execution-lease.js +145 -0
- package/dist/foundation/release/update.d.ts +9 -7
- package/dist/foundation/release/update.js +244 -175
- package/dist/foundation/resident-tabs/bridge-client.d.ts +10 -3
- package/dist/foundation/resident-tabs/bridge-client.js +20 -8
- package/dist/foundation/resident-tabs/maintenance.d.ts +2 -6
- package/dist/foundation/resident-tabs/maintenance.js +5 -23
- package/dist/foundation/resident-tabs/progress-observation-schema.d.ts +34 -0
- package/dist/foundation/resident-tabs/progress-observation-schema.js +1 -0
- package/dist/foundation/resident-tabs/progress-observation.d.ts +3 -6
- package/dist/foundation/resident-tabs/progress-observation.js +43 -12
- package/dist/foundation/resident-tabs/release-holds.js +3 -14
- package/dist/foundation/resident-tabs/routes.d.ts +5 -0
- package/dist/foundation/resident-tabs/routes.js +5 -0
- package/dist/foundation/resident-tabs/settings.d.ts +0 -1
- package/dist/foundation/resident-tabs/settings.js +0 -2
- package/dist/integrations/pi/components/editor-interaction.d.ts +2 -0
- package/dist/integrations/pi/components/modal-frame.d.ts +17 -1
- package/dist/integrations/pi/components/modal-frame.js +48 -9
- package/dist/integrations/pi/components/models-dialog.js +4 -52
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +3 -0
- package/dist/integrations/pi/components/owned-editor-ux.js +75 -4
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +57 -37
- package/dist/integrations/pi/components/shell-footer-status.js +19 -3
- package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -1
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +4 -1
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +9 -2
- package/dist/integrations/pi/components/skills-dialog.js +2 -2
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +7 -5
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +15 -8
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.d.ts +3 -3
- package/dist/integrations/pi/components/upstream/components/scoped-models-selector.js +2 -2
- package/dist/integrations/pi/components/upstream/components/session-footer.js +26 -23
- package/dist/integrations/pi/components/upstream/components/session-selector.js +7 -6
- package/dist/integrations/pi/components/upstream/components/thinking-selector.d.ts +7 -6
- package/dist/integrations/pi/components/upstream/components/thinking-selector.js +9 -8
- package/dist/integrations/pi/components/upstream/components/tool-execution.js +6 -4
- package/dist/integrations/pi/components/upstream/components/tree-selector.d.ts +8 -8
- package/dist/integrations/pi/components/upstream/components/tree-selector.js +10 -10
- package/dist/integrations/pi/components/upstream/history/editor-core.js +2 -0
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +2 -0
- package/dist/integrations/pi/components/upstream/theme/theme.js +5 -1
- package/dist/integrations/pi/engine/adapter.js +7 -2
- package/dist/integrations/pi/engine/offline-settings-port.d.ts +23 -0
- package/dist/integrations/pi/engine/offline-settings-port.js +53 -0
- package/dist/integrations/pi/engine/ports.d.ts +1 -1
- package/dist/integrations/pi/engine/ports.js +4 -0
- package/dist/integrations/pi/engine/settings-bridge.d.ts +5 -0
- package/dist/integrations/pi/engine/settings-bridge.js +13 -0
- package/dist/integrations/pi/engine/settings-port.js +1 -14
- package/dist/integrations/pi/engine/workflow-runner.js +9 -2
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/darwin-arm64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-arm64/terminal-host.node +0 -0
- package/dist/native/darwin-x64/manifest.json +1 -1
- package/dist/native/darwin-x64/terminal-host.manifest.json +3 -3
- package/dist/native/darwin-x64/terminal-host.node +0 -0
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/linux-x64/terminal-host.manifest.json +3 -3
- package/dist/native/linux-x64/terminal-host.node +0 -0
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.node +0 -0
- package/dist/native/win32-x64/terminal-host.manifest.json +3 -3
- package/dist/native/win32-x64/terminal-host.node +0 -0
- package/dist/product-identity.d.ts +1 -1
- package/dist/product-identity.js +2 -2
- package/dist/product-identity.json +2 -0
- package/dist/ui/apps/host.d.ts +2 -0
- package/dist/ui/apps/host.js +7 -1
- package/dist/ui/components/dialog-panel.js +35 -30
- package/dist/ui/components/line-input.d.ts +3 -0
- package/dist/ui/components/line-input.js +3 -1
- package/dist/ui/components/prompt-input.d.ts +5 -4
- package/dist/ui/components/prompt-input.js +8 -6
- package/dist/ui/components/spans.js +2 -2
- package/dist/ui/components/submitted-prompt.d.ts +2 -2
- package/dist/ui/components/submitted-prompt.js +3 -3
- package/dist/ui/components/surface.js +4 -2
- package/dist/ui/components/text.d.ts +3 -6
- package/dist/ui/components/text.js +6 -8
- package/dist/ui/components/transcript-viewport.d.ts +1 -1
- package/dist/ui/components/transcript-viewport.js +141 -24
- package/dist/ui/settings/declarations.d.ts +67 -17
- package/dist/ui/settings/declarations.js +47 -15
- package/dist/ui/settings/early-accent.d.ts +81 -0
- package/dist/ui/settings/early-accent.js +50 -0
- package/dist/ui/settings/manager.js +7 -3
- package/dist/ui/settings/migrations.js +22 -0
- package/dist/ui/settings/progress-palette.generated.d.ts +139 -0
- package/dist/ui/settings/progress-palette.generated.js +139 -0
- package/dist/ui/settings/sections.d.ts +4 -0
- package/dist/ui/settings/sections.js +9 -3
- package/docs/architecture/resident-tabs.md +52 -21
- package/docs/architecture/tool-image-presentation.md +2 -1
- package/docs/features/prompt-history.md +41 -20
- package/docs/validation.md +25 -5
- package/package.json +1 -1
|
@@ -15,6 +15,19 @@ const IDENTITY_ROW = (row) => row;
|
|
|
15
15
|
function documentSelectionAnchor(row, source, liveFromBottom) {
|
|
16
16
|
return { kind: "document", row, source, identity: stripAnsi(source).trimEnd(), liveFromBottom };
|
|
17
17
|
}
|
|
18
|
+
function sameSelectionRowAnchor(left, right) {
|
|
19
|
+
if (left.kind !== right.kind)
|
|
20
|
+
return false;
|
|
21
|
+
if (left.kind === "document" && right.kind === "document") {
|
|
22
|
+
return left.row === right.row && left.source === right.source && left.liveFromBottom === right.liveFromBottom;
|
|
23
|
+
}
|
|
24
|
+
if (left.kind === "screen" && right.kind === "screen") {
|
|
25
|
+
return left.row === right.row && left.source === right.source;
|
|
26
|
+
}
|
|
27
|
+
if (left.kind === "transient" && right.kind === "transient")
|
|
28
|
+
return left.fromBottom === right.fromBottom;
|
|
29
|
+
return left.kind === "dock" && right.kind === "dock" && left.fromBottom === right.fromBottom;
|
|
30
|
+
}
|
|
18
31
|
function viewportSelectionAnchor(row, source, selectableDocumentRowCount, documentRowCount) {
|
|
19
32
|
return row < selectableDocumentRowCount
|
|
20
33
|
? documentSelectionAnchor(row, source)
|
|
@@ -140,7 +153,12 @@ export class TranscriptViewport {
|
|
|
140
153
|
this.scrollBy(1, now);
|
|
141
154
|
else if (autoScroll && frameRow <= 1 && this.#scrollTop > 0)
|
|
142
155
|
this.scrollBy(-1, now);
|
|
143
|
-
const
|
|
156
|
+
const pointerLine = clamp(frameRow - 1, 0, this.#selectionRows.length - 1);
|
|
157
|
+
// Invariant: a pinned prompt alias is chrome; an upward drag reaching it keeps the pointer
|
|
158
|
+
// column on the first visible content row.
|
|
159
|
+
const line = pointerLine < this.#firstSelectableRow && pointerLine < selection.anchor.line
|
|
160
|
+
? this.#firstSelectableRow
|
|
161
|
+
: pointerLine;
|
|
144
162
|
const selectionWidth = line < (this.#frame?.hits.viewportHeight ?? 0)
|
|
145
163
|
? this.#contentWidth
|
|
146
164
|
: this.#selectionWidth;
|
|
@@ -151,12 +169,13 @@ export class TranscriptViewport {
|
|
|
151
169
|
? { line, column: targetColumn }
|
|
152
170
|
: textSelectionPointAt(line, targetColumn, this.#selectionRows[line] ?? "");
|
|
153
171
|
const next = extendTextSelection(selection, point);
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
172
|
+
const headAnchor = this.#selectionAnchorAt(line);
|
|
173
|
+
if (headAnchor === undefined || this.#selectionAnchors === undefined) {
|
|
174
|
+
this.clearSelection();
|
|
175
|
+
return true;
|
|
176
|
+
}
|
|
177
|
+
// Invariant: edge auto-scroll changes the document row under a still pointer; that advances the head.
|
|
178
|
+
if (next !== selection || !sameSelectionRowAnchor(this.#selectionAnchors.head, headAnchor)) {
|
|
160
179
|
this.#selection = next;
|
|
161
180
|
this.#selectionAnchors = { ...this.#selectionAnchors, head: headAnchor };
|
|
162
181
|
this.#selectionRevision += 1;
|
|
@@ -184,25 +203,66 @@ export class TranscriptViewport {
|
|
|
184
203
|
return true;
|
|
185
204
|
}
|
|
186
205
|
selectedText() {
|
|
187
|
-
const
|
|
188
|
-
if (
|
|
206
|
+
const visible = this.#visibleSelection();
|
|
207
|
+
if (visible === undefined)
|
|
189
208
|
return null;
|
|
190
|
-
const
|
|
209
|
+
const offscreen = offscreenSelectionRows(this.#selection, this.#selectionAnchors, this.#scrollTop, this.#firstSelectableRow, this.#viewportHeight, this.#documentRows.length);
|
|
210
|
+
// Rationale: edge auto-scroll grows a drag beyond one screen. Paint stays clipped to the
|
|
211
|
+
// frame, while copy reads the selected document rows past either viewport edge and beneath
|
|
212
|
+
// the floating bottom control.
|
|
213
|
+
const selectionRows = [];
|
|
214
|
+
const rowAnchors = [];
|
|
215
|
+
const controlLine = (this.#frame?.hits.bottom?.row ?? 0) - 1;
|
|
216
|
+
const pushDocumentRow = (row) => {
|
|
217
|
+
const source = this.#documentRows[row] ?? "";
|
|
218
|
+
selectionRows.push(truncateToWidth(source, this.#contentWidth));
|
|
219
|
+
rowAnchors.push(documentSelectionAnchor(row, source));
|
|
220
|
+
};
|
|
221
|
+
const pushBelow = () => {
|
|
222
|
+
for (let row = offscreen.below?.from ?? 0; row <= (offscreen.below?.to ?? -1); row += 1)
|
|
223
|
+
pushDocumentRow(row);
|
|
224
|
+
};
|
|
225
|
+
for (let row = offscreen.above?.from ?? 0; row <= (offscreen.above?.to ?? -1); row += 1)
|
|
226
|
+
pushDocumentRow(row);
|
|
227
|
+
if (offscreen.belowFirst)
|
|
228
|
+
pushBelow();
|
|
229
|
+
for (let line = visible.start.line; line <= visible.end.line; line += 1) {
|
|
191
230
|
const anchor = this.#selectionRowAnchors[line];
|
|
231
|
+
if (line === controlLine && anchor?.kind === "document")
|
|
232
|
+
pushDocumentRow(anchor.row);
|
|
233
|
+
else {
|
|
234
|
+
selectionRows.push(this.#selectionRows[line] ?? "");
|
|
235
|
+
rowAnchors.push(anchor);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
if (!offscreen.belowFirst)
|
|
239
|
+
pushBelow();
|
|
240
|
+
const offscreenStart = offscreen.above !== undefined || offscreen.belowFirst === true;
|
|
241
|
+
const offscreenEnd = offscreen.below !== undefined && !offscreen.belowFirst;
|
|
242
|
+
const selection = {
|
|
243
|
+
...visible,
|
|
244
|
+
start: { line: 0, column: offscreenStart ? offscreen.startColumn ?? 0 : visible.start.column },
|
|
245
|
+
end: {
|
|
246
|
+
line: selectionRows.length - 1,
|
|
247
|
+
column: offscreenEnd ? offscreen.endColumn ?? Number.MAX_SAFE_INTEGER : visible.end.column,
|
|
248
|
+
},
|
|
249
|
+
};
|
|
250
|
+
const copiedLines = Array.from({ length: Math.max(0, selection.end.line - selection.start.line + 1) }, (_value, index) => selection.start.line + index).filter(line => {
|
|
251
|
+
const anchor = rowAnchors[line];
|
|
192
252
|
return anchor?.kind === "document" && anchor.row < this.#selectableDocumentRowCount
|
|
193
253
|
|| anchor?.kind === "dock" && this.#copyableDockRows.has(anchor.fromBottom);
|
|
194
254
|
});
|
|
195
255
|
if (copiedLines.length === 0)
|
|
196
256
|
return null;
|
|
197
|
-
const transcriptLines = copiedLines.filter(line =>
|
|
257
|
+
const transcriptLines = copiedLines.filter(line => rowAnchors[line]?.kind === "document");
|
|
198
258
|
const prompt = transcriptLines.length === 0 ? undefined : this.#promptAnchors.find(candidate => transcriptLines.every(line => {
|
|
199
|
-
const anchor =
|
|
259
|
+
const anchor = rowAnchors[line];
|
|
200
260
|
return anchor?.kind === "document" && anchor.row >= candidate.firstRow && anchor.row <= candidate.lastRow;
|
|
201
261
|
}));
|
|
202
262
|
const included = new Set(copiedLines);
|
|
203
|
-
const text = textSelectionText(selection,
|
|
204
|
-
const row =
|
|
205
|
-
const anchor =
|
|
263
|
+
const text = textSelectionText(selection, selectionRows, line => {
|
|
264
|
+
const row = selectionRows[line] ?? "";
|
|
265
|
+
const anchor = rowAnchors[line];
|
|
206
266
|
const dock = anchor?.kind === "dock" ? this.#copyableDockRows.get(anchor.fromBottom) : undefined;
|
|
207
267
|
if (prompt !== undefined && anchor?.kind === "document") {
|
|
208
268
|
const first = anchor.row === prompt.firstRow;
|
|
@@ -211,11 +271,12 @@ export class TranscriptViewport {
|
|
|
211
271
|
: row;
|
|
212
272
|
return selectionCopyLineContent(copyRow, first ? "first" : "continuation");
|
|
213
273
|
}
|
|
214
|
-
|
|
274
|
+
// Invariant: the dock editor has no prefix; transcript prompts still carry chrome.
|
|
275
|
+
return dock?.prompt !== undefined ? usefulTextLineContent(row, 1) : usefulTextLineContent(row);
|
|
215
276
|
}, line => included.has(line));
|
|
216
277
|
return text.length === 0 ? null : text;
|
|
217
278
|
}
|
|
218
|
-
/** Captures
|
|
279
|
+
/** Captures selected text, including document rows of a visible selection scrolled off-screen. */
|
|
219
280
|
captureSelectedText() {
|
|
220
281
|
if (!this.#copyableSelection)
|
|
221
282
|
return null;
|
|
@@ -470,7 +531,7 @@ export class TranscriptViewport {
|
|
|
470
531
|
const bottomHovered = pointer !== undefined && pointer.row === bottomHit.row
|
|
471
532
|
&& pointer.column >= bottomHit.columnStart && pointer.column <= bottomHit.columnEnd;
|
|
472
533
|
control = { row, left, text: `${CONTROL_STYLE_RESET}${theme.bottomControl(label, bottomHovered)}` };
|
|
473
|
-
// Invariant: the control floats above selection;
|
|
534
|
+
// Invariant: the control floats above selection; copy restores the text beneath it.
|
|
474
535
|
selectionRows[row] = overlaySpan(padRowPreservingBackground(selectionRows[row] ?? "", width), left, left + labelWidth, " ".repeat(labelWidth));
|
|
475
536
|
}
|
|
476
537
|
}
|
|
@@ -701,7 +762,7 @@ export class TranscriptViewport {
|
|
|
701
762
|
const anchors = this.#selectionAnchors;
|
|
702
763
|
if (selection === undefined || anchors === undefined)
|
|
703
764
|
return;
|
|
704
|
-
const project = (anchor) => {
|
|
765
|
+
const project = (anchor, moving) => {
|
|
705
766
|
if (anchor.kind === "dock") {
|
|
706
767
|
const dockIndex = dockRows.length - anchor.fromBottom - 1;
|
|
707
768
|
return dockIndex < 0 || dockIndex >= dockRows.length
|
|
@@ -743,7 +804,7 @@ export class TranscriptViewport {
|
|
|
743
804
|
// Concurrency: a streaming chunk may replace or reflow the pointer's current live-tail
|
|
744
805
|
// row before the next motion report. During the held gesture only, retain its distance
|
|
745
806
|
// from the persistent tail; release restores identity-only projection.
|
|
746
|
-
if (selection.selecting && anchor.liveFromBottom !== undefined && this.#liveTailStartRow !== undefined) {
|
|
807
|
+
if (selection.selecting && moving && anchor.liveFromBottom !== undefined && this.#liveTailStartRow !== undefined) {
|
|
747
808
|
const documentRow = this.#selectableDocumentRowCount - anchor.liveFromBottom - 1;
|
|
748
809
|
if (documentRow >= this.#liveTailStartRow && documentRow < this.#selectableDocumentRowCount) {
|
|
749
810
|
const visible = this.#selectionRowAnchors.findIndex(candidate => candidate?.kind === "document" && candidate.row === documentRow);
|
|
@@ -755,10 +816,18 @@ export class TranscriptViewport {
|
|
|
755
816
|
}
|
|
756
817
|
}
|
|
757
818
|
}
|
|
819
|
+
// Concurrency: streaming may restyle a held endpoint's row; it keeps its document index.
|
|
820
|
+
// Following the tail would drag the press row toward the newest output.
|
|
821
|
+
if (selection.selecting && anchor.row >= 0 && anchor.row < documentRows.length) {
|
|
822
|
+
return {
|
|
823
|
+
line: anchor.row - this.#scrollTop,
|
|
824
|
+
anchor: documentSelectionAnchor(anchor.row, documentRows[anchor.row] ?? "", anchor.liveFromBottom),
|
|
825
|
+
};
|
|
826
|
+
}
|
|
758
827
|
return undefined;
|
|
759
828
|
};
|
|
760
|
-
const projectedAnchor = project(anchors.anchor);
|
|
761
|
-
const projectedHead = project(anchors.head);
|
|
829
|
+
const projectedAnchor = project(anchors.anchor, false);
|
|
830
|
+
const projectedHead = project(anchors.head, true);
|
|
762
831
|
if (projectedAnchor === undefined || projectedHead === undefined) {
|
|
763
832
|
this.clearSelection();
|
|
764
833
|
return;
|
|
@@ -778,11 +847,59 @@ export class TranscriptViewport {
|
|
|
778
847
|
// Invariant: mixed viewport/dock ranges project across the same complete frame regardless
|
|
779
848
|
// of origin. Document-only ranges remain clipped to the scrollable viewport when off-screen.
|
|
780
849
|
const rows = crossesDock ? this.#selectionRows.length : this.#viewportHeight;
|
|
781
|
-
|
|
850
|
+
const ordered = orderedTextSelection(dockOrderedSelection(this.#selection, anchors, this.#viewportHeight));
|
|
851
|
+
return visibleTextSelection(ordered, rows, this.#firstSelectableRow);
|
|
782
852
|
}
|
|
783
853
|
#updateCopyableSelection() {
|
|
784
|
-
|
|
854
|
+
// Performance: off-screen rows count as copyable by range alone; capture trims whitespace later.
|
|
855
|
+
const offscreen = offscreenSelectionRows(this.#selection, this.#selectionAnchors, this.#scrollTop, this.#firstSelectableRow, this.#viewportHeight, this.#documentRows.length);
|
|
856
|
+
const selectable = [offscreen.above, offscreen.below]
|
|
857
|
+
.some(range => range !== undefined && range.from < this.#selectableDocumentRowCount);
|
|
858
|
+
this.#copyableSelection = selectable && this.#visibleSelection() !== undefined || this.selectedText() !== null;
|
|
859
|
+
}
|
|
860
|
+
}
|
|
861
|
+
/**
|
|
862
|
+
* Invariant: dock rows follow the whole transcript, so a document endpoint scrolled below the
|
|
863
|
+
* viewport orders before every dock row instead of at its numeric frame line among them.
|
|
864
|
+
*/
|
|
865
|
+
function dockOrderedSelection(selection, anchors, viewportHeight) {
|
|
866
|
+
if (selection === undefined || anchors === undefined || anchors.anchor.kind !== "dock" && anchors.head.kind !== "dock") {
|
|
867
|
+
return selection;
|
|
785
868
|
}
|
|
869
|
+
const place = (point, kind) => kind === "document" && point.line >= viewportHeight ? { line: viewportHeight, column: 1, from: 0, to: 0 } : point;
|
|
870
|
+
return { ...selection, anchor: place(selection.anchor, anchors.anchor.kind), head: place(selection.head, anchors.head.kind) };
|
|
871
|
+
}
|
|
872
|
+
/** Document rows of a selection whose endpoints lie beyond the visible viewport edges. */
|
|
873
|
+
function offscreenSelectionRows(selection, anchors, scrollTop, firstSelectableRow, viewportHeight, documentRowCount) {
|
|
874
|
+
const ordered = orderedTextSelection(dockOrderedSelection(selection, anchors, viewportHeight));
|
|
875
|
+
if (selection === undefined || ordered === undefined || anchors === undefined)
|
|
876
|
+
return {};
|
|
877
|
+
const placed = dockOrderedSelection(selection, anchors, viewportHeight);
|
|
878
|
+
const anchorFirst = placed.anchor.line < placed.head.line
|
|
879
|
+
|| placed.anchor.line === placed.head.line && placed.anchor.column <= placed.head.column;
|
|
880
|
+
const top = anchorFirst ? anchors.anchor : anchors.head;
|
|
881
|
+
const bottom = anchorFirst ? anchors.head : anchors.anchor;
|
|
882
|
+
const topPoint = anchorFirst ? selection.anchor : selection.head;
|
|
883
|
+
const bottomPoint = anchorFirst ? selection.head : selection.anchor;
|
|
884
|
+
const firstVisibleRow = scrollTop + firstSelectableRow;
|
|
885
|
+
const pastVisibleRow = scrollTop + viewportHeight;
|
|
886
|
+
const columns = {
|
|
887
|
+
startColumn: selection.fullRow ? 0 : topPoint.from ?? Math.max(0, topPoint.column - 1),
|
|
888
|
+
endColumn: selection.fullRow ? Number.MAX_SAFE_INTEGER : bottomPoint.to ?? bottomPoint.column,
|
|
889
|
+
};
|
|
890
|
+
if (top.kind === "document" && bottom.kind === "dock" && top.row >= pastVisibleRow) {
|
|
891
|
+
return { ...columns, below: { from: top.row, to: documentRowCount - 1 }, belowFirst: true };
|
|
892
|
+
}
|
|
893
|
+
return {
|
|
894
|
+
...columns,
|
|
895
|
+
...(top.kind === "document" && top.row < firstVisibleRow && ordered.start.line < firstSelectableRow
|
|
896
|
+
? { above: { from: top.row, to: firstVisibleRow - 1 } }
|
|
897
|
+
: {}),
|
|
898
|
+
...(top.kind === "document" && bottom.kind === "document" && bottom.row >= pastVisibleRow
|
|
899
|
+
&& ordered.end.line >= viewportHeight
|
|
900
|
+
? { below: { from: pastVisibleRow, to: bottom.row } }
|
|
901
|
+
: {}),
|
|
902
|
+
};
|
|
786
903
|
}
|
|
787
904
|
function visibleTextSelection(selection, rowCount, firstRow) {
|
|
788
905
|
if (selection === undefined || rowCount <= firstRow || selection.end.line < firstRow || selection.start.line >= rowCount)
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
export declare const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export declare const OWNED_UI_SETTINGS_VERSION = 19;
|
|
2
2
|
export type OwnedUiSettingValue = string | number | boolean;
|
|
3
3
|
export type OwnedUiSettingApplication = "live" | "restart";
|
|
4
4
|
export interface OwnedUiSettingDeclaration {
|
|
5
5
|
readonly id: string;
|
|
6
|
-
/** Optional presentation label; the id remains the persistence key. */
|
|
7
6
|
readonly label?: string;
|
|
8
|
-
/** Optional settings-screen group for related owned controls. */
|
|
9
7
|
readonly section?: {
|
|
10
8
|
readonly id: string;
|
|
11
9
|
readonly title: string;
|
|
@@ -14,23 +12,28 @@ export interface OwnedUiSettingDeclaration {
|
|
|
14
12
|
readonly application: OwnedUiSettingApplication;
|
|
15
13
|
readonly defaultValue: OwnedUiSettingValue;
|
|
16
14
|
readonly allowedValues: readonly OwnedUiSettingValue[];
|
|
15
|
+
/**
|
|
16
|
+
* Parts of a structured setting, edited through their own dialog: the value is the comma-separated
|
|
17
|
+
* keys of the enabled parts in this order.
|
|
18
|
+
*/
|
|
19
|
+
readonly flags?: readonly {
|
|
20
|
+
readonly key: string;
|
|
21
|
+
readonly label: string;
|
|
22
|
+
readonly description: string;
|
|
23
|
+
}[];
|
|
17
24
|
}
|
|
18
|
-
/**
|
|
19
|
-
* Every A1 setting, keyed by its id. The table is the one declaration: ids, defaults, and allowed
|
|
20
|
-
* values are read from it, and `OwnedSettingValueOf` derives each getter's type from it.
|
|
21
|
-
*/
|
|
22
25
|
export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
23
26
|
readonly updateCheck: Readonly<{
|
|
24
27
|
id: "updateCheck";
|
|
25
|
-
label: "Update
|
|
28
|
+
label: "Update";
|
|
26
29
|
section: Readonly<{
|
|
27
30
|
id: "generic";
|
|
28
31
|
title: "Generic";
|
|
29
32
|
}>;
|
|
30
|
-
description: "
|
|
33
|
+
description: "Auto installs verified channel updates silently, Notify shows the current update notice, and No leaves updates manual. Checks use the public npm registry; applies on next start.";
|
|
31
34
|
application: "restart";
|
|
32
|
-
defaultValue:
|
|
33
|
-
allowedValues: readonly [
|
|
35
|
+
defaultValue: "auto";
|
|
36
|
+
allowedValues: readonly ["auto", "notify", "no"];
|
|
34
37
|
}>;
|
|
35
38
|
readonly timeFormat: Readonly<{
|
|
36
39
|
id: "timeFormat";
|
|
@@ -53,8 +56,8 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
53
56
|
}>;
|
|
54
57
|
description: "Color used by highlighted interface controls, list markers, and tonal interface surfaces.";
|
|
55
58
|
application: "live";
|
|
56
|
-
defaultValue: "
|
|
57
|
-
allowedValues: readonly ["
|
|
59
|
+
defaultValue: "blue";
|
|
60
|
+
allowedValues: readonly ["blue", "purple", "cyan", "green", "orange", "pink"];
|
|
58
61
|
}>;
|
|
59
62
|
readonly backgroundStyle: Readonly<{
|
|
60
63
|
id: "backgroundStyle";
|
|
@@ -123,11 +126,23 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
123
126
|
id: "history";
|
|
124
127
|
title: "History";
|
|
125
128
|
}>;
|
|
126
|
-
description: "Retain reusable prompts
|
|
129
|
+
description: "Retain reusable prompts after restart. Applies on next start; disabling does not erase saved history or stop existing instances.";
|
|
127
130
|
application: "restart";
|
|
128
131
|
defaultValue: true;
|
|
129
132
|
allowedValues: readonly [true, false];
|
|
130
133
|
}>;
|
|
134
|
+
readonly promptHistoryScope: Readonly<{
|
|
135
|
+
id: "promptHistoryScope";
|
|
136
|
+
label: "History scope";
|
|
137
|
+
section: Readonly<{
|
|
138
|
+
id: "history";
|
|
139
|
+
title: "History";
|
|
140
|
+
}>;
|
|
141
|
+
description: "Unique shows each agent session's history; Shared shows the profile-wide history. Switches running agents without moving or erasing saved prompts.";
|
|
142
|
+
application: "live";
|
|
143
|
+
defaultValue: "unique";
|
|
144
|
+
allowedValues: readonly ["unique", "shared"];
|
|
145
|
+
}>;
|
|
131
146
|
readonly promptHistoryMaxItems: Readonly<{
|
|
132
147
|
id: "promptHistoryMaxItems";
|
|
133
148
|
label: "History limit";
|
|
@@ -176,12 +191,49 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
176
191
|
defaultValue: 8;
|
|
177
192
|
allowedValues: readonly [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16];
|
|
178
193
|
}>;
|
|
194
|
+
readonly tabsPosition: Readonly<{
|
|
195
|
+
id: "tabsPosition";
|
|
196
|
+
label: "Position";
|
|
197
|
+
section: Readonly<{
|
|
198
|
+
id: "tabs";
|
|
199
|
+
title: "Tab Bar";
|
|
200
|
+
}>;
|
|
201
|
+
description: "Place the resident tab bar at the top or bottom of the terminal.";
|
|
202
|
+
application: "live";
|
|
203
|
+
defaultValue: "top";
|
|
204
|
+
allowedValues: readonly ["top", "bottom"];
|
|
205
|
+
}>;
|
|
206
|
+
readonly tabBarPlusMenu: Readonly<{
|
|
207
|
+
id: "tabBarPlusMenu";
|
|
208
|
+
label: "Plus menu";
|
|
209
|
+
section: Readonly<{
|
|
210
|
+
id: "tabs";
|
|
211
|
+
title: "Tab Bar";
|
|
212
|
+
}>;
|
|
213
|
+
description: "The tabs + offers. With only Agent, + adds an Agent at once; with more, it opens a menu; with none, + is hidden.";
|
|
214
|
+
application: "live";
|
|
215
|
+
defaultValue: "agent";
|
|
216
|
+
allowedValues: readonly ["", "agent", "settings", "changelog", "agent,settings", "agent,changelog", "settings,changelog", "agent,settings,changelog"];
|
|
217
|
+
flags: readonly (Readonly<{
|
|
218
|
+
key: "agent";
|
|
219
|
+
label: "Agent";
|
|
220
|
+
description: "Add a new Agent tab every time.";
|
|
221
|
+
}> | Readonly<{
|
|
222
|
+
key: "settings";
|
|
223
|
+
label: "Settings";
|
|
224
|
+
description: "Show the one Settings tab.";
|
|
225
|
+
}> | Readonly<{
|
|
226
|
+
key: "changelog";
|
|
227
|
+
label: "Changelog";
|
|
228
|
+
description: "Show the one Changelog tab.";
|
|
229
|
+
}>)[];
|
|
230
|
+
}>;
|
|
179
231
|
readonly tabsAutoName: Readonly<{
|
|
180
232
|
id: "tabsAutoName";
|
|
181
233
|
label: "Auto name";
|
|
182
234
|
section: Readonly<{
|
|
183
235
|
id: "tabs";
|
|
184
|
-
title: "
|
|
236
|
+
title: "Tab Bar";
|
|
185
237
|
}>;
|
|
186
238
|
description: "Automatically name a new tab from its first completed turn with the tab's current model.";
|
|
187
239
|
application: "live";
|
|
@@ -190,9 +242,7 @@ export declare const OWNED_SETTING_DECLARATIONS: Readonly<{
|
|
|
190
242
|
}>;
|
|
191
243
|
}>;
|
|
192
244
|
export type OwnedSettingId = keyof typeof OWNED_SETTING_DECLARATIONS;
|
|
193
|
-
/** The value type a setting's declaration allows: a literal union for a choice, `number` for a stepped range. */
|
|
194
245
|
export type OwnedSettingValueOf<Id extends OwnedSettingId> = (typeof OWNED_SETTING_DECLARATIONS)[Id]["allowedValues"][number];
|
|
195
|
-
/** The declarations in declaration order, for resolution, persistence, and the settings screen. */
|
|
196
246
|
export declare const OWNED_UI_SETTING_DECLARATIONS: readonly OwnedUiSettingDeclaration[];
|
|
197
247
|
export declare function isOwnedSettingId(id: string): id is OwnedSettingId;
|
|
198
248
|
export declare function assertOwnedUiSettingDeclarations(declarations: readonly OwnedUiSettingDeclaration[]): void;
|
|
@@ -1,28 +1,33 @@
|
|
|
1
|
-
export const OWNED_UI_SETTINGS_VERSION =
|
|
1
|
+
export const OWNED_UI_SETTINGS_VERSION = 19;
|
|
2
2
|
const UI_ACCENT_COLOR_CHOICES = Object.freeze([
|
|
3
|
-
"
|
|
3
|
+
"blue", "purple", "cyan", "green", "orange", "pink",
|
|
4
4
|
]);
|
|
5
5
|
const MAX_ID_LENGTH = 64;
|
|
6
6
|
const ID_PATTERN = /^[a-z][a-z0-9]*(?:[A-Z][a-z0-9]*)*$/;
|
|
7
|
-
/** Declared first so the settings screen opens on it; sections follow first-declaration order. */
|
|
8
7
|
const GENERIC_SECTION = Object.freeze({ id: "generic", title: "Generic" });
|
|
9
8
|
const APPEARANCE_SECTION = Object.freeze({ id: "appearance", title: "Appearance" });
|
|
10
9
|
const SCROLL_SECTION = Object.freeze({ id: "scroll", title: "Scroll" });
|
|
11
10
|
const AGENT_SECTION = Object.freeze({ id: "agent", title: "Agent" });
|
|
12
|
-
const TABS_SECTION = Object.freeze({ id: "tabs", title: "
|
|
13
|
-
/**
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
const TABS_SECTION = Object.freeze({ id: "tabs", title: "Tab Bar" });
|
|
12
|
+
/** The tab kinds the strip's `+` can offer, in the order it shows them. */
|
|
13
|
+
const PLUS_MENU_KINDS = Object.freeze([
|
|
14
|
+
Object.freeze({ key: "agent", label: "Agent", description: "Add a new Agent tab every time." }),
|
|
15
|
+
Object.freeze({ key: "settings", label: "Settings", description: "Show the one Settings tab." }),
|
|
16
|
+
Object.freeze({ key: "changelog", label: "Changelog", description: "Show the one Changelog tab." }),
|
|
17
|
+
]);
|
|
18
|
+
/** Every enabled subset of the plus-menu kinds, each in kind order. */
|
|
19
|
+
const PLUS_MENU_VALUES = Object.freeze([
|
|
20
|
+
"", "agent", "settings", "changelog", "agent,settings", "agent,changelog", "settings,changelog", "agent,settings,changelog",
|
|
21
|
+
]);
|
|
17
22
|
export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
18
23
|
updateCheck: Object.freeze({
|
|
19
24
|
id: "updateCheck",
|
|
20
|
-
label: "Update
|
|
25
|
+
label: "Update",
|
|
21
26
|
section: GENERIC_SECTION,
|
|
22
|
-
description: "
|
|
27
|
+
description: "Auto installs verified channel updates silently, Notify shows the current update notice, and No leaves updates manual. Checks use the public npm registry; applies on next start.",
|
|
23
28
|
application: "restart",
|
|
24
|
-
defaultValue:
|
|
25
|
-
allowedValues: Object.freeze([
|
|
29
|
+
defaultValue: "auto",
|
|
30
|
+
allowedValues: Object.freeze(["auto", "notify", "no"]),
|
|
26
31
|
}),
|
|
27
32
|
timeFormat: Object.freeze({
|
|
28
33
|
id: "timeFormat",
|
|
@@ -41,7 +46,7 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
41
46
|
section: APPEARANCE_SECTION,
|
|
42
47
|
description: "Color used by highlighted interface controls, list markers, and tonal interface surfaces.",
|
|
43
48
|
application: "live",
|
|
44
|
-
defaultValue: "
|
|
49
|
+
defaultValue: "blue",
|
|
45
50
|
allowedValues: UI_ACCENT_COLOR_CHOICES,
|
|
46
51
|
}),
|
|
47
52
|
backgroundStyle: Object.freeze({
|
|
@@ -95,11 +100,20 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
95
100
|
id: "promptHistoryEnabled",
|
|
96
101
|
label: "Persistent history",
|
|
97
102
|
section: Object.freeze({ id: "history", title: "History" }),
|
|
98
|
-
description: "Retain reusable prompts
|
|
103
|
+
description: "Retain reusable prompts after restart. Applies on next start; disabling does not erase saved history or stop existing instances.",
|
|
99
104
|
application: "restart",
|
|
100
105
|
defaultValue: true,
|
|
101
106
|
allowedValues: Object.freeze([true, false]),
|
|
102
107
|
}),
|
|
108
|
+
promptHistoryScope: Object.freeze({
|
|
109
|
+
id: "promptHistoryScope",
|
|
110
|
+
label: "History scope",
|
|
111
|
+
section: Object.freeze({ id: "history", title: "History" }),
|
|
112
|
+
description: "Unique shows each agent session's history; Shared shows the profile-wide history. Switches running agents without moving or erasing saved prompts.",
|
|
113
|
+
application: "live",
|
|
114
|
+
defaultValue: "unique",
|
|
115
|
+
allowedValues: Object.freeze(["unique", "shared"]),
|
|
116
|
+
}),
|
|
103
117
|
promptHistoryMaxItems: Object.freeze({
|
|
104
118
|
id: "promptHistoryMaxItems",
|
|
105
119
|
label: "History limit",
|
|
@@ -136,6 +150,25 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
136
150
|
defaultValue: 8,
|
|
137
151
|
allowedValues: Object.freeze([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]),
|
|
138
152
|
}),
|
|
153
|
+
tabsPosition: Object.freeze({
|
|
154
|
+
id: "tabsPosition",
|
|
155
|
+
label: "Position",
|
|
156
|
+
section: TABS_SECTION,
|
|
157
|
+
description: "Place the resident tab bar at the top or bottom of the terminal.",
|
|
158
|
+
application: "live",
|
|
159
|
+
defaultValue: "top",
|
|
160
|
+
allowedValues: Object.freeze(["top", "bottom"]),
|
|
161
|
+
}),
|
|
162
|
+
tabBarPlusMenu: Object.freeze({
|
|
163
|
+
id: "tabBarPlusMenu",
|
|
164
|
+
label: "Plus menu",
|
|
165
|
+
section: TABS_SECTION,
|
|
166
|
+
description: "The tabs + offers. With only Agent, + adds an Agent at once; with more, it opens a menu; with none, + is hidden.",
|
|
167
|
+
application: "live",
|
|
168
|
+
defaultValue: "agent",
|
|
169
|
+
allowedValues: PLUS_MENU_VALUES,
|
|
170
|
+
flags: PLUS_MENU_KINDS,
|
|
171
|
+
}),
|
|
139
172
|
tabsAutoName: Object.freeze({
|
|
140
173
|
id: "tabsAutoName",
|
|
141
174
|
label: "Auto name",
|
|
@@ -146,7 +179,6 @@ export const OWNED_SETTING_DECLARATIONS = Object.freeze({
|
|
|
146
179
|
allowedValues: Object.freeze([true, false]),
|
|
147
180
|
}),
|
|
148
181
|
});
|
|
149
|
-
/** The declarations in declaration order, for resolution, persistence, and the settings screen. */
|
|
150
182
|
export const OWNED_UI_SETTING_DECLARATIONS = Object.freeze(Object.values(OWNED_SETTING_DECLARATIONS));
|
|
151
183
|
export function isOwnedSettingId(id) {
|
|
152
184
|
return Object.hasOwn(OWNED_SETTING_DECLARATIONS, id);
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import type { UiAccentColor } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
type Appearance = "dark" | "light";
|
|
3
|
+
type ColorMode = "truecolor" | "256color";
|
|
4
|
+
/** Global settings only: project resources must remain unavailable until trust is resolved. */
|
|
5
|
+
export declare function readPreTrustAccent(environment?: NodeJS.ProcessEnv): UiAccentColor;
|
|
6
|
+
export declare function preTrustPalette(color: UiAccentColor, appearance: Appearance, mode: ColorMode): {
|
|
7
|
+
accent: string;
|
|
8
|
+
border: string;
|
|
9
|
+
} | {
|
|
10
|
+
accent: string;
|
|
11
|
+
border: string;
|
|
12
|
+
} | {
|
|
13
|
+
accent: string;
|
|
14
|
+
border: string;
|
|
15
|
+
} | {
|
|
16
|
+
accent: string;
|
|
17
|
+
border: string;
|
|
18
|
+
} | {
|
|
19
|
+
accent: string;
|
|
20
|
+
border: string;
|
|
21
|
+
} | {
|
|
22
|
+
accent: string;
|
|
23
|
+
border: string;
|
|
24
|
+
} | {
|
|
25
|
+
accent: string;
|
|
26
|
+
border: string;
|
|
27
|
+
} | {
|
|
28
|
+
accent: string;
|
|
29
|
+
border: string;
|
|
30
|
+
} | {
|
|
31
|
+
accent: string;
|
|
32
|
+
border: string;
|
|
33
|
+
} | {
|
|
34
|
+
accent: string;
|
|
35
|
+
border: string;
|
|
36
|
+
} | {
|
|
37
|
+
accent: string;
|
|
38
|
+
border: string;
|
|
39
|
+
} | {
|
|
40
|
+
accent: string;
|
|
41
|
+
border: string;
|
|
42
|
+
} | {
|
|
43
|
+
accent: string;
|
|
44
|
+
border: string;
|
|
45
|
+
} | {
|
|
46
|
+
accent: string;
|
|
47
|
+
border: string;
|
|
48
|
+
} | {
|
|
49
|
+
accent: string;
|
|
50
|
+
border: string;
|
|
51
|
+
} | {
|
|
52
|
+
accent: string;
|
|
53
|
+
border: string;
|
|
54
|
+
} | {
|
|
55
|
+
accent: string;
|
|
56
|
+
border: string;
|
|
57
|
+
} | {
|
|
58
|
+
accent: string;
|
|
59
|
+
border: string;
|
|
60
|
+
} | {
|
|
61
|
+
accent: string;
|
|
62
|
+
border: string;
|
|
63
|
+
} | {
|
|
64
|
+
accent: string;
|
|
65
|
+
border: string;
|
|
66
|
+
} | {
|
|
67
|
+
accent: string;
|
|
68
|
+
border: string;
|
|
69
|
+
} | {
|
|
70
|
+
accent: string;
|
|
71
|
+
border: string;
|
|
72
|
+
} | {
|
|
73
|
+
accent: string;
|
|
74
|
+
border: string;
|
|
75
|
+
} | {
|
|
76
|
+
accent: string;
|
|
77
|
+
border: string;
|
|
78
|
+
};
|
|
79
|
+
export declare function preTrustTerminalAppearance(environment?: NodeJS.ProcessEnv): Appearance;
|
|
80
|
+
export declare function preTrustTerminalColorMode(environment?: NodeJS.ProcessEnv): ColorMode;
|
|
81
|
+
export {};
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { readFileSync, statSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { isAbsolute, join } from "node:path";
|
|
4
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
|
+
import { SHARED_PROGRESS_PALETTE } from "./progress-palette.generated.js";
|
|
6
|
+
/** Global settings only: project resources must remain unavailable until trust is resolved. */
|
|
7
|
+
export function readPreTrustAccent(environment = process.env) {
|
|
8
|
+
try {
|
|
9
|
+
const home = environment[PRODUCT_IDENTITY.environment.profileHome] ?? homedir();
|
|
10
|
+
if (!isAbsolute(home) || home.includes("\0"))
|
|
11
|
+
return "blue";
|
|
12
|
+
const file = join(home, PRODUCT_IDENTITY.state.piAgentProfile, "settings.json");
|
|
13
|
+
if (statSync(file).size > 256 * 1024)
|
|
14
|
+
return "blue";
|
|
15
|
+
const raw = readFileSync(file, "utf8");
|
|
16
|
+
if (Buffer.byteLength(raw, "utf8") > 256 * 1024)
|
|
17
|
+
return "blue";
|
|
18
|
+
const root = JSON.parse(raw.replace(/^\uFEFF/u, ""));
|
|
19
|
+
if (root === null || typeof root !== "object" || Array.isArray(root))
|
|
20
|
+
return "blue";
|
|
21
|
+
const namespace = root[PRODUCT_IDENTITY.commandName];
|
|
22
|
+
if (namespace === null || typeof namespace !== "object" || Array.isArray(namespace))
|
|
23
|
+
return "blue";
|
|
24
|
+
const value = namespace.accentColor;
|
|
25
|
+
if (value === "default")
|
|
26
|
+
return "purple";
|
|
27
|
+
return typeof value === "string" && Object.hasOwn(SHARED_PROGRESS_PALETTE, value) ? value : "blue";
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return "blue";
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
export function preTrustPalette(color, appearance, mode) {
|
|
34
|
+
return SHARED_PROGRESS_PALETTE[color][appearance][mode];
|
|
35
|
+
}
|
|
36
|
+
export function preTrustTerminalAppearance(environment = process.env) {
|
|
37
|
+
const index = Number.parseInt((environment.COLORFGBG ?? "").split(";").at(-1) ?? "", 10);
|
|
38
|
+
return Number.isInteger(index) && (index === 7 || index === 15 || index >= 231) ? "light" : "dark";
|
|
39
|
+
}
|
|
40
|
+
export function preTrustTerminalColorMode(environment = process.env) {
|
|
41
|
+
if (environment.PI_TRUE_COLOR === "1")
|
|
42
|
+
return "truecolor";
|
|
43
|
+
if (environment.PI_TRUE_COLOR === "0")
|
|
44
|
+
return "256color";
|
|
45
|
+
const program = (environment.TERM_PROGRAM ?? "").toLowerCase();
|
|
46
|
+
const known = ["kitty", "ghostty", "wezterm", "rex", "warpterminal", "iterm.app", "alacritty", "vscode", "zed"];
|
|
47
|
+
return /^(truecolor|24bit)$/iu.test(environment.COLORTERM ?? "") || (environment.TERM ?? "").endsWith("-direct")
|
|
48
|
+
|| process.platform === "win32" || environment.WT_SESSION !== undefined || known.includes(program)
|
|
49
|
+
? "truecolor" : "256color";
|
|
50
|
+
}
|
|
@@ -188,9 +188,13 @@ export class OwnedSettingsManager {
|
|
|
188
188
|
return () => this.#listeners.delete(listener);
|
|
189
189
|
}
|
|
190
190
|
async changeStructured(backend, id, value) {
|
|
191
|
-
if (backend
|
|
192
|
-
return
|
|
193
|
-
|
|
191
|
+
if (backend === "agent")
|
|
192
|
+
return await this.#changeAgentValue(id, value);
|
|
193
|
+
// Invariant: a flagged A1 setting stores its enabled parts as one value, in declaration order.
|
|
194
|
+
const flags = findOwnedUiSettingsEntry(this.sections(), id, "a1")?.flags ?? [];
|
|
195
|
+
if (flags.length === 0)
|
|
196
|
+
return failed(`${id} holds no structured value`);
|
|
197
|
+
return await this.change("a1", id, flags.filter(flag => value[flag.key] === true).map(flag => flag.key).join(","));
|
|
194
198
|
}
|
|
195
199
|
async change(backend, id, value) {
|
|
196
200
|
const entry = findOwnedUiSettingsEntry(this.sections(), id, backend);
|