@timurproko/a1 0.2.7-dev.820 → 0.2.7-dev.831
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/ui.js +1 -0
- package/dist/app/session-shell/session-shell-root.d.ts +8 -1
- package/dist/app/session-shell/session-shell.js +68 -18
- package/dist/app/session-shell/transcript-document.js +1 -1
- package/dist/composition/owned-ui.d.ts +3 -11
- package/dist/composition/owned-ui.js +93 -42
- 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/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/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/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/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/update-execution-lease.d.ts +36 -0
- package/dist/foundation/release/update-execution-lease.js +145 -0
- package/dist/foundation/release/update.d.ts +8 -6
- package/dist/foundation/release/update.js +232 -167
- package/dist/foundation/resident-tabs/bridge-client.d.ts +8 -2
- package/dist/foundation/resident-tabs/bridge-client.js +13 -6
- package/dist/foundation/resident-tabs/routes.d.ts +5 -0
- package/dist/foundation/resident-tabs/routes.js +5 -0
- 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/engine/adapter.js +7 -2
- package/dist/integrations/pi/engine/ports.d.ts +1 -1
- package/dist/integrations/pi/engine/ports.js +4 -0
- 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 +1 -1
- package/dist/product-identity.json +1 -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 +3 -2
- package/dist/ui/components/prompt-input.js +6 -4
- package/dist/ui/components/surface.js +4 -2
- package/dist/ui/settings/declarations.d.ts +54 -8
- package/dist/ui/settings/declarations.js +36 -7
- package/dist/ui/settings/manager.js +7 -3
- package/dist/ui/settings/migrations.js +15 -0
- package/dist/ui/settings/sections.d.ts +4 -0
- package/dist/ui/settings/sections.js +9 -3
- package/docs/architecture/resident-tabs.md +35 -7
- package/docs/architecture/tool-image-presentation.md +2 -1
- package/docs/features/prompt-history.md +41 -20
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -145,7 +145,13 @@ Stuck on `0.2.2` and `a1 update` fails? Run the installer once, then use `a1 upd
|
|
|
145
145
|
npm x -y -- @timurproko/a1-install
|
|
146
146
|
```
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
The **Update** setting controls the at-most-daily startup check:
|
|
149
|
+
|
|
150
|
+
- **Auto** (default) silently installs a verified update for the running channel, then shows `Update installed · Restart to update`.
|
|
151
|
+
- **Notify** keeps the `Update Available` notice and leaves installation manual.
|
|
152
|
+
- **No** performs no startup update check; updates remain available through the commands above.
|
|
153
|
+
|
|
154
|
+
`A1_SKIP_VERSION_CHECK=1` also disables the startup check. Manual stable, development, and exact-version update commands remain available in every mode.
|
|
149
155
|
|
|
150
156
|
<p align="center"><picture><source media="(prefers-color-scheme: dark)" srcset="docs/assets/readme/separator-dark.svg"><img src="docs/assets/readme/separator.svg" alt="" width="280"></picture></p>
|
|
151
157
|
|
package/bin/ui.js
CHANGED
|
@@ -78,6 +78,7 @@ Promise.resolve().then(async () => {
|
|
|
78
78
|
cwd: process.cwd(),
|
|
79
79
|
profileId,
|
|
80
80
|
ownedSurfaces,
|
|
81
|
+
notificationVersion: launchContext.updateVersion,
|
|
81
82
|
...(hidesTabSettings(launchContext) ? { hideTabSettings: true } : {}),
|
|
82
83
|
...(processInspector === null ? {} : { inspectProcess: pid => processInspector.observe(pid) }),
|
|
83
84
|
projectTrustPrompt: createConsoleProjectTrustPrompt({ presentation: profile === "a1" ? "bare" : "comparison" }),
|
|
@@ -116,6 +116,13 @@ export interface OwnedUiShellPresentationOptions {
|
|
|
116
116
|
/** Persistent prompt history: its store, its bound, the editor that recalls it, and the image sidecar. */
|
|
117
117
|
export interface OwnedUiShellHistoryOptions {
|
|
118
118
|
readonly store: import("../../contracts/owned-ui/index.js").PromptHistoryPort;
|
|
119
|
+
/** When present, session replacement selects a new store and sidecar, not the old session's recall. */
|
|
120
|
+
readonly sessionId?: string;
|
|
121
|
+
readonly scope?: "unique" | "shared";
|
|
122
|
+
readonly forSession?: (sessionId: string) => Pick<OwnedUiShellHistoryOptions, "store" | "imageSidecar">;
|
|
123
|
+
/** A live scope change selects the matching store for this session without copying records. */
|
|
124
|
+
readonly forScope?: (scope: "unique" | "shared", sessionId: string | null) => Pick<OwnedUiShellHistoryOptions, "store" | "imageSidecar"> | null;
|
|
125
|
+
readonly onScopeChange?: (listener: (scope: "unique" | "shared") => void) => () => void;
|
|
119
126
|
readonly limit: number;
|
|
120
127
|
readonly editor: import("../../integrations/pi/components/index.js").HistoryEditorConstructor;
|
|
121
128
|
/** Optional per-profile filesystem sidecar for image chip payloads. When present, submit
|
|
@@ -191,7 +198,7 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
191
198
|
readonly requestHyperlinkCleanup?: (rows?: readonly number[]) => void;
|
|
192
199
|
readonly enableDockInputReuse?: boolean;
|
|
193
200
|
readonly persistentHistory?: boolean;
|
|
194
|
-
readonly
|
|
201
|
+
readonly hideUtilityTabCommands?: boolean;
|
|
195
202
|
readonly historyEditor?: import("../../integrations/pi/components/index.js").HistoryEditorConstructor;
|
|
196
203
|
readonly onSubmit: (text: string) => void;
|
|
197
204
|
readonly onPasteRejected?: (error: unknown) => void;
|
|
@@ -27,6 +27,12 @@ import { writeSystemClipboardText, } from "./system-clipboard.js";
|
|
|
27
27
|
import { OwnedUiSessionShellRoot, shellResourceEntries, } from "./session-shell-root.js";
|
|
28
28
|
// Invariant: a disposed shell leaves the engine a host that holds no reference back to it.
|
|
29
29
|
const DETACHED_WORKFLOW_INTERACTION = { prompt: async () => null, notify() { } };
|
|
30
|
+
/** Resident Agents refuse the commands their tab bar serves instead, naming where they live. */
|
|
31
|
+
const RESIDENT_UTILITY_TAB_REFUSALS = Object.freeze({
|
|
32
|
+
settings: "Settings is available from the global Settings tab.",
|
|
33
|
+
changelog: "The changelog opens as its own tab from the command palette (Alt+/).",
|
|
34
|
+
name: "Rename the session by renaming its tab (F2).",
|
|
35
|
+
});
|
|
30
36
|
export { OwnedUiSessionShellRoot, } from "./session-shell-root.js";
|
|
31
37
|
export { OwnedUiTerminalHost, sessionTerminalHostOptions } from "./shell-host.js";
|
|
32
38
|
export { formatSessionResumeCommand, quoteCommandArgument } from "./session-lifecycle.js";
|
|
@@ -55,7 +61,7 @@ export class OwnedUiSessionPresenter {
|
|
|
55
61
|
#unsubscribeSkills;
|
|
56
62
|
#installedCommandSignature = "";
|
|
57
63
|
#promptHistory = null;
|
|
58
|
-
#
|
|
64
|
+
#historyBinding;
|
|
59
65
|
#extensionBridge;
|
|
60
66
|
#stop = new SessionStopLatch();
|
|
61
67
|
#dialogs;
|
|
@@ -169,7 +175,7 @@ export class OwnedUiSessionPresenter {
|
|
|
169
175
|
}),
|
|
170
176
|
enableDockInputReuse: inputPresentation?.viewportReuse !== false,
|
|
171
177
|
footerSessionName: options.engine.residentTab === undefined,
|
|
172
|
-
|
|
178
|
+
hideUtilityTabCommands: options.engine.residentTab !== undefined,
|
|
173
179
|
persistentHistory: this.#customViewport && promptHistory !== undefined,
|
|
174
180
|
...(promptHistory === undefined ? {} : { historyEditor: promptHistory.editor }),
|
|
175
181
|
onSubmit: text => { void this.submit(text).catch(() => this.#submission.reportError()); },
|
|
@@ -316,9 +322,10 @@ export class OwnedUiSessionPresenter {
|
|
|
316
322
|
});
|
|
317
323
|
};
|
|
318
324
|
applyViewportSettings();
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
325
|
+
const unsubscribeViewport = this.#customViewport && viewportSettings ? viewportSettings.onChange(settings => this.root.setViewportConfig(settings)) : () => { };
|
|
326
|
+
const unsubscribeHistoryScope = this.#customViewport && promptHistory?.onScopeChange?.(scope => this.#rebindTranscript(scope));
|
|
327
|
+
this.#unsubscribeSettings = () => { unsubscribeViewport(); if (unsubscribeHistoryScope)
|
|
328
|
+
unsubscribeHistoryScope(); };
|
|
322
329
|
constructed.push(this.#unsubscribeSettings);
|
|
323
330
|
this.#unbindSessionSettings = bindSessionSettings(this.backend.settings, initialPiSettings, {
|
|
324
331
|
terminal: this.#terminal,
|
|
@@ -331,8 +338,7 @@ export class OwnedUiSessionPresenter {
|
|
|
331
338
|
}, { customViewport: this.#customViewport });
|
|
332
339
|
constructed.push(this.#unbindSessionSettings);
|
|
333
340
|
if (this.#customViewport && promptHistory !== undefined) {
|
|
334
|
-
this.#
|
|
335
|
-
const sidecar = this.#promptHistoryImageSidecar;
|
|
341
|
+
this.#historyBinding = { options: promptHistory, scope: promptHistory.scope ?? "unique", sessionId: promptHistory.sessionId, imageSidecar: promptHistory.imageSidecar };
|
|
336
342
|
this.#promptHistory = new PromptHistoryController({
|
|
337
343
|
editor: this.root.editor,
|
|
338
344
|
store: promptHistory.store,
|
|
@@ -340,7 +346,7 @@ export class OwnedUiSessionPresenter {
|
|
|
340
346
|
fallback: this.view().transcript.flatMap(block => block.kind === "user" ? [block.text] : []),
|
|
341
347
|
active: () => this.root.usesDefaultInputSurface(),
|
|
342
348
|
render: () => this.#terminal.requestRender(),
|
|
343
|
-
rehydrate: value => this.root.rehydrateHistoryText(value, id =>
|
|
349
|
+
rehydrate: value => this.root.rehydrateHistoryText(value, id => this.#historyBinding?.imageSidecar?.readAttachment(id) ?? null),
|
|
344
350
|
});
|
|
345
351
|
constructed.push(() => { void this.#promptHistory?.close().catch(() => false); });
|
|
346
352
|
}
|
|
@@ -1154,7 +1160,7 @@ export class OwnedUiSessionPresenter {
|
|
|
1154
1160
|
residentTab: this.#resident,
|
|
1155
1161
|
cwd,
|
|
1156
1162
|
promptHistory: () => this.#promptHistory,
|
|
1157
|
-
imageSidecar: () => this.#
|
|
1163
|
+
imageSidecar: () => this.#historyBinding?.imageSidecar,
|
|
1158
1164
|
disposed: () => this.#disposed,
|
|
1159
1165
|
correlation: prefix => this.#correlation(prefix),
|
|
1160
1166
|
lifecycle: () => this.view().lifecycle,
|
|
@@ -1183,13 +1189,57 @@ export class OwnedUiSessionPresenter {
|
|
|
1183
1189
|
this.#resident,
|
|
1184
1190
|
]);
|
|
1185
1191
|
}
|
|
1186
|
-
// Invariant: delivery recovery
|
|
1187
|
-
#rebindTranscript() {
|
|
1188
|
-
|
|
1192
|
+
// Invariant: delivery recovery does not replace a store; conversation or live scope changes can.
|
|
1193
|
+
#rebindTranscript(scope) {
|
|
1194
|
+
const replaced = this.#sessionBindingGeneration !== this.backend.identity.sessionBindingGeneration;
|
|
1195
|
+
if (!replaced && scope === undefined)
|
|
1189
1196
|
return;
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1197
|
+
if (replaced) {
|
|
1198
|
+
this.#sessionBindingGeneration = this.backend.identity.sessionBindingGeneration;
|
|
1199
|
+
this.root.resetTranscript();
|
|
1200
|
+
}
|
|
1201
|
+
const binding = this.#historyBinding;
|
|
1202
|
+
if (binding?.options.forSession !== undefined || binding?.options.forScope !== undefined) {
|
|
1203
|
+
const sessionId = this.backend.identity.currentHistorySessionId();
|
|
1204
|
+
const selectedScope = scope ?? binding.scope;
|
|
1205
|
+
if (selectedScope !== binding.scope || sessionId !== binding.sessionId) {
|
|
1206
|
+
if (!replaced)
|
|
1207
|
+
this.root.editor.recall?.restoreDraft?.();
|
|
1208
|
+
const previous = this.#promptHistory;
|
|
1209
|
+
this.#promptHistory = null;
|
|
1210
|
+
binding.imageSidecar = undefined;
|
|
1211
|
+
binding.scope = selectedScope;
|
|
1212
|
+
binding.sessionId = sessionId ?? undefined;
|
|
1213
|
+
void previous?.close().catch(() => false);
|
|
1214
|
+
const destination = binding.options.forScope !== undefined
|
|
1215
|
+
? binding.options.forScope(selectedScope, sessionId)
|
|
1216
|
+
: sessionId === null ? null : binding.options.forSession(sessionId);
|
|
1217
|
+
if (destination !== null) {
|
|
1218
|
+
binding.imageSidecar = destination.imageSidecar;
|
|
1219
|
+
const controller = new PromptHistoryController({
|
|
1220
|
+
editor: this.root.editor,
|
|
1221
|
+
store: destination.store,
|
|
1222
|
+
limit: binding.options.limit,
|
|
1223
|
+
fallback: replaced ? this.view().transcript.flatMap(block => block.kind === "user" ? [block.text] : []) : [],
|
|
1224
|
+
active: () => this.root.usesDefaultInputSurface(),
|
|
1225
|
+
render: () => this.#terminal.requestRender(),
|
|
1226
|
+
rehydrate: value => this.root.rehydrateHistoryText(value, id => this.#historyBinding?.imageSidecar?.readAttachment(id) ?? null),
|
|
1227
|
+
});
|
|
1228
|
+
this.#promptHistory = controller;
|
|
1229
|
+
if (this.#started)
|
|
1230
|
+
controller.start();
|
|
1231
|
+
}
|
|
1232
|
+
else {
|
|
1233
|
+
// Security: missing identity must not reopen Shared or retain another session's recall.
|
|
1234
|
+
const fallback = replaced ? this.view().transcript.flatMap(block => block.kind === "user" ? [block.text] : []).reverse() : [];
|
|
1235
|
+
this.root.editor.recall?.reset();
|
|
1236
|
+
this.root.editor.recall?.replace(fallback);
|
|
1237
|
+
}
|
|
1238
|
+
return;
|
|
1239
|
+
}
|
|
1240
|
+
}
|
|
1241
|
+
if (replaced)
|
|
1242
|
+
this.#promptHistory?.reset(this.view().transcript.flatMap(block => block.kind === "user" ? [block.text] : []));
|
|
1193
1243
|
}
|
|
1194
1244
|
#syncTerminalProgress(view) {
|
|
1195
1245
|
if (!this.#terminal.running)
|
|
@@ -1254,9 +1304,9 @@ export class OwnedUiSessionPresenter {
|
|
|
1254
1304
|
const separator = body.search(/\s/);
|
|
1255
1305
|
const name = separator < 0 ? body : body.slice(0, separator);
|
|
1256
1306
|
const argument = separator < 0 ? "" : body.slice(separator + 1).trimStart();
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1307
|
+
const utilityTab = this.#resident.active ? RESIDENT_UTILITY_TAB_REFUSALS[name] : undefined;
|
|
1308
|
+
if (utilityTab !== undefined)
|
|
1309
|
+
return rejected(utilityTab);
|
|
1260
1310
|
if (this.#dialogs.claimsRoute(name))
|
|
1261
1311
|
return this.#dialogs.openRoute(name);
|
|
1262
1312
|
if (this.#isWorkflowRoute(name))
|
|
@@ -260,7 +260,7 @@ export class TranscriptDocument {
|
|
|
260
260
|
: createPiShellChangelog(diagnostic.message).render(width)));
|
|
261
261
|
rows.push(...diagnostics
|
|
262
262
|
.filter(diagnostic => diagnostic.code !== "engine-startup" && diagnostic.code !== "project-trust"
|
|
263
|
-
&& diagnostic.code !== "release-update"
|
|
263
|
+
&& diagnostic.code !== "release-update" && diagnostic.code !== "release-update-installed"
|
|
264
264
|
&& diagnostic.code !== "package-updates" && diagnostic.code !== "changelog-collapsed"
|
|
265
265
|
&& diagnostic.code !== "changelog-expanded")
|
|
266
266
|
.slice(-3)
|
|
@@ -20,17 +20,11 @@ export interface OwnedUiCompositionOptions {
|
|
|
20
20
|
readonly sessionPath?: string;
|
|
21
21
|
readonly sessionSelection?: SessionSelection;
|
|
22
22
|
readonly sessionForkPrompt?: PiSessionForkPrompt;
|
|
23
|
-
/**
|
|
24
|
-
* A1 profile whose settings this session reads and writes. Omitted keeps the
|
|
25
|
-
* session settings-free, which is what the pinned comparison paths use.
|
|
26
|
-
*/
|
|
23
|
+
/** A1 settings profile; comparison paths omit it. */
|
|
27
24
|
readonly profileId?: string;
|
|
28
25
|
/** Hide resident-only tab controls for the explicit direct single-agent launch. */
|
|
29
26
|
readonly hideTabSettings?: boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Whether A1's product-specific surfaces are reachable. Comparison profiles
|
|
32
|
-
* use the same composition with those surfaces withheld.
|
|
33
|
-
*/
|
|
27
|
+
/** `off` withholds A1-specific surfaces from comparison profiles. */
|
|
34
28
|
readonly ownedSurfaces?: "on" | "off";
|
|
35
29
|
readonly projectTrustPrompt?: PiProjectTrustPreflightPrompt;
|
|
36
30
|
/** Explicit local diagnostic destination; ignored by comparison/settings-free compositions. */
|
|
@@ -39,18 +33,16 @@ export interface OwnedUiCompositionOptions {
|
|
|
39
33
|
readonly clipboardDiagnosticsPath?: string;
|
|
40
34
|
/** Deterministic release-note seams for composition tests. */
|
|
41
35
|
readonly packageVersion?: string;
|
|
36
|
+
readonly notificationVersion?: string | undefined;
|
|
42
37
|
readonly releaseNotes?: ReleaseNoteCatalog;
|
|
43
38
|
/** Startup release-availability seam; defaults to the throttled registry check. */
|
|
44
39
|
readonly checkForNewerRelease?: (options: StartupReleaseCheckOptions) => Promise<AvailableRelease | null>;
|
|
45
|
-
/** Exact native process inspection injected by the shipped entry; absent SDK seams do not publish claims. */
|
|
46
40
|
readonly inspectProcess?: (pid: number) => Promise<NativeProcessIdentity | null>;
|
|
47
|
-
/** Private credentials were consumed by the entry before composition or extensions loaded. */
|
|
48
41
|
readonly tab?: {
|
|
49
42
|
readonly bridge: TabBridgeClient;
|
|
50
43
|
readonly dataDir: string;
|
|
51
44
|
readonly incarnation: number;
|
|
52
45
|
};
|
|
53
|
-
/** One prompt-adjacent notice explaining why a resident launch fell back. */
|
|
54
46
|
readonly residentFallbackNotice?: string;
|
|
55
47
|
}
|
|
56
48
|
export interface OwnedUiComposition {
|
|
@@ -6,11 +6,13 @@ import { PromptImageSidecar } from "../features/prompt-history/image-sidecar.js"
|
|
|
6
6
|
import { resolvePromptHistoryPath } from "../features/prompt-history/paths.js";
|
|
7
7
|
import { resolveLaunchProfilePaths, resolvePromptHistoryDataDir } from "../features/launch/profile-paths.js";
|
|
8
8
|
import { resolveProductPaths } from "../foundation/lifecycle/paths.js";
|
|
9
|
+
import { MAX_CLIPBOARD_TEXT_BYTES } from "../contracts/owned-ui/index.js";
|
|
9
10
|
import { applyConfiguredPiTheme, getAvailablePiThemes, setPiAccentColor, setPiPackageBorderProjectionEnabled } from "../integrations/pi/components/upstream/theme/theme.js";
|
|
10
11
|
import { createPiEngineHost } from "../integrations/pi/engine/host.js";
|
|
11
12
|
import { createPiSessionPresenters } from "../integrations/pi/session-presenters/index.js";
|
|
12
13
|
import { ClipboardDiagnosticCapture } from "../app/session-shell/clipboard-diagnostics.js";
|
|
13
14
|
import { createOwnedUiClipboardServices } from "../app/session-shell/clipboard-services.js";
|
|
15
|
+
import { writeSystemClipboardText } from "../app/session-shell/system-clipboard.js";
|
|
14
16
|
import { createPiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
|
|
15
17
|
import { OwnedUiSessionPresenter, OwnedUiTerminalHost, sessionTerminalHostOptions, } from "../app/session-shell/session-shell.js";
|
|
16
18
|
import { OwnedSettingsManager } from "../ui/settings/manager.js";
|
|
@@ -19,7 +21,7 @@ import { createOwnedRouteHost } from "./settings-route-host.js";
|
|
|
19
21
|
import { renderPiShellChangelogLines } from "../integrations/pi/components/shell-presenters-info.js";
|
|
20
22
|
import { nativeHyperlinkStyle } from "../ui/components/spans.js";
|
|
21
23
|
import { ResidentTabRecovery } from "../foundation/resident-tabs/recovery.js";
|
|
22
|
-
import { bindResidentTabBridge, correlateResidentTabSubmission, currentBackendSessionFile, residentTabKeybindings } from "./resident-tab-bridge.js";
|
|
24
|
+
import { bindResidentTabBridge, closeResidentUtilityRoute, correlateResidentTabSubmission, currentBackendSessionFile, residentRouteHostOptions, residentTabKeybindings } from "./resident-tab-bridge.js";
|
|
23
25
|
import { SessionRuntimeRegistry } from "./session-runtime-registry.js";
|
|
24
26
|
import { readPackageVersion, StartupReleaseNote } from "./startup-route.js";
|
|
25
27
|
export { bindResidentTabBridge, correlateResidentTabSubmission } from "./resident-tab-bridge.js";
|
|
@@ -50,7 +52,7 @@ export async function composeOwnedUi(options = {}) {
|
|
|
50
52
|
namespace: PRODUCT_IDENTITY.commandName,
|
|
51
53
|
legacyConfigDir: productPaths.configDir,
|
|
52
54
|
agentProvider: () => backend.settingsPort(),
|
|
53
|
-
...(options.hideTabSettings ? { hiddenOwnedSettingIds: ["tabsAutoName", "tabsPosition"] } : {}),
|
|
55
|
+
...(options.hideTabSettings ? { hiddenOwnedSettingIds: ["tabsAutoName", "tabsPosition", "tabBarPlusMenu"] } : {}),
|
|
54
56
|
hiddenAgentSettingIds: ["fullscreenWheelScrollLines"],
|
|
55
57
|
agentSettingLabelOverrides: { fullscreenCopyOnSelect: "Copy on select" },
|
|
56
58
|
});
|
|
@@ -130,12 +132,15 @@ export async function composeOwnedUi(options = {}) {
|
|
|
130
132
|
host.setAccentColor(accent);
|
|
131
133
|
tabBridge?.accent(accent);
|
|
132
134
|
});
|
|
133
|
-
// Rationale:
|
|
134
|
-
// change saved in
|
|
135
|
-
const unwatchSharedSettings = settings === null || !ownedSurfaces
|
|
135
|
+
// Rationale: resident tabs and separate solo agents share a settings document; a live scope
|
|
136
|
+
// change saved in either reaches the others only by rereading that document.
|
|
137
|
+
const unwatchSharedSettings = settings === null || !ownedSurfaces
|
|
136
138
|
? () => { }
|
|
137
139
|
: watchSharedSettings(settings);
|
|
138
140
|
const unsubscribeAccent = () => { unwatchSharedSettings(); unsubscribeAccentChange(); };
|
|
141
|
+
// Invariant: the Settings search and agent prompt borrow the same resolved Pi keybindings.
|
|
142
|
+
const keybindingsHost = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
|
|
143
|
+
const keybindings = residentTabKeybindings(tabBridge, backend.identity.agentDir, keybindingsHost);
|
|
139
144
|
// Rationale: Routes open only after shell construction.
|
|
140
145
|
const references = {
|
|
141
146
|
changelog: async (input) => {
|
|
@@ -151,9 +156,8 @@ export async function composeOwnedUi(options = {}) {
|
|
|
151
156
|
},
|
|
152
157
|
session: () => import("./session-info-reference.js").then(m => m.loadSessionInfoReference(backend)),
|
|
153
158
|
};
|
|
154
|
-
const routeHost = settings === null || !ownedSurfaces ? null
|
|
155
|
-
|
|
156
|
-
});
|
|
159
|
+
const routeHost = settings === null || !ownedSurfaces ? null
|
|
160
|
+
: createOwnedRouteHost(settings, references, settingsRouteOptions(tabBridge, keybindings, backend.identity.agentDir, cwd));
|
|
157
161
|
const viewportSettings = settings === null || !ownedSurfaces ? null : {
|
|
158
162
|
snapshot: () => viewportSettingsSnapshot(settings),
|
|
159
163
|
onChange: listener => settings.onChange(() => listener(viewportSettingsSnapshot(settings))),
|
|
@@ -181,26 +185,11 @@ export async function composeOwnedUi(options = {}) {
|
|
|
181
185
|
// Rationale: one listener covers both the A1 presentation choice and the engine skill-command toggle.
|
|
182
186
|
onChange: (listener) => settings.onChange(() => listener()),
|
|
183
187
|
};
|
|
184
|
-
const
|
|
185
|
-
const historyProfileLocation = settings === null || !ownedSurfaces || !settings.value("promptHistoryEnabled")
|
|
186
|
-
? null
|
|
187
|
-
: resolvePromptHistoryPath(resolvePromptHistoryDataDir(), backend.identity.agentDir);
|
|
188
|
-
const promptHistory = historyProfileLocation === null ? null : {
|
|
189
|
-
limit: typeof historyLimit === "number" ? historyLimit : 100,
|
|
190
|
-
store: new PromptHistoryService({
|
|
191
|
-
dataDir: resolvePromptHistoryDataDir(),
|
|
192
|
-
profileRoot: backend.identity.agentDir,
|
|
193
|
-
limit: typeof historyLimit === "number" ? historyLimit : 100,
|
|
194
|
-
}),
|
|
195
|
-
imageSidecar: new PromptImageSidecar(historyProfileLocation.imagesDir),
|
|
196
|
-
};
|
|
188
|
+
const promptHistory = createPromptHistoryConfiguration(settings, backend, ownedSurfaces);
|
|
197
189
|
const clipboardDestination = options.clipboardDiagnosticsPath ?? process.env[PRODUCT_IDENTITY.environment.clipboardDiagnostics];
|
|
198
190
|
const clipboardDiagnostics = settings !== null && ownedSurfaces && clipboardDestination?.trim()
|
|
199
191
|
? new ClipboardDiagnosticCapture(clipboardDestination) : null;
|
|
200
|
-
// Invariant: process-wide services are created once here and borrowed by every session shell.
|
|
201
|
-
// keybinding registry is applied before any presenter is built, so none of them reads Pi's defaults.
|
|
202
|
-
const keybindingsHost = createPiKeybindingsHost({ profile: ownedSurfaces ? "a1" : "pi", agentDir: backend.identity.agentDir });
|
|
203
|
-
const keybindings = residentTabKeybindings(tabBridge, backend.identity.agentDir, keybindingsHost);
|
|
192
|
+
// Invariant: process-wide services are created once here and borrowed by every session shell.
|
|
204
193
|
const clipboardServices = ownedSurfaces ? createOwnedUiClipboardServices() : null;
|
|
205
194
|
let createdTerminalHost;
|
|
206
195
|
let terminalHost;
|
|
@@ -216,10 +205,7 @@ export async function composeOwnedUi(options = {}) {
|
|
|
216
205
|
...(ownedSurfaces ? { sessionLayout: "custom-viewport" } : {}),
|
|
217
206
|
...(tabBridge === null || tabRecovery === null ? {} : { residentTab: {
|
|
218
207
|
requestDetach: () => tabBridge.requestDetach(),
|
|
219
|
-
closeOwnedRoute: route =>
|
|
220
|
-
if (tabBridge.tabId.startsWith("settings-") && route === "settings")
|
|
221
|
-
void tabBridge.requestClose();
|
|
222
|
-
},
|
|
208
|
+
closeOwnedRoute: route => closeResidentUtilityRoute(tabBridge, route),
|
|
223
209
|
reportStatus: status => tabBridge.status(status),
|
|
224
210
|
admit: input => tabRecovery.admit({ ...input, incarnation: options.tab.incarnation }),
|
|
225
211
|
dispatched: () => tabRecovery.dispatched(),
|
|
@@ -290,18 +276,13 @@ export async function composeOwnedUi(options = {}) {
|
|
|
290
276
|
// Rationale: pinned Pi's version check is unreachable because the owned shell never runs its
|
|
291
277
|
// InteractiveMode, so A1 checks its own channel. The result is never awaited on the startup path;
|
|
292
278
|
// settings are read here because the runner resolves them only just before start.
|
|
293
|
-
const
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
...(settings === null || !ownedSurfaces ? {} : { settingEnabled: settings.value("updateCheck") }),
|
|
301
|
-
});
|
|
302
|
-
if (release !== null)
|
|
303
|
-
backend.extensions.announceReleaseUpdate(release);
|
|
304
|
-
};
|
|
279
|
+
const releaseUpdates = createStartupReleaseUpdateObservation({
|
|
280
|
+
backend,
|
|
281
|
+
configDir: productPaths.configDir,
|
|
282
|
+
mode: settings === null || !ownedSurfaces ? "auto" : settings.value("updateCheck"),
|
|
283
|
+
packageVersion: releaseNote.packageVersion, notificationVersion: options.notificationVersion,
|
|
284
|
+
checkForNewerRelease: options.checkForNewerRelease,
|
|
285
|
+
});
|
|
305
286
|
const exitNoticePath = process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
|
|
306
287
|
// Security: tools the agent runs must never see, or rewrite, this instance's notice.
|
|
307
288
|
delete process.env[PRODUCT_IDENTITY.environment.exitNoticePath];
|
|
@@ -314,11 +295,12 @@ export async function composeOwnedUi(options = {}) {
|
|
|
314
295
|
exitNotice = import("../app/session-shell/exit-notice.js")
|
|
315
296
|
.then(module => module.armExitNotice(backend, exitNoticePath), () => null);
|
|
316
297
|
presenter.start();
|
|
317
|
-
|
|
298
|
+
releaseUpdates.start();
|
|
318
299
|
},
|
|
319
300
|
flush: () => backend.session.flushEvents(),
|
|
320
301
|
waitUntilStopped: () => presenter.waitUntilStopped(),
|
|
321
302
|
dispose: async () => {
|
|
303
|
+
releaseUpdates.stop();
|
|
322
304
|
try {
|
|
323
305
|
await terminalHost.dispose();
|
|
324
306
|
// Invariant: cleared only once the terminal is restored; a failed dispose leaves it armed.
|
|
@@ -343,6 +325,63 @@ export async function composeOwnedUi(options = {}) {
|
|
|
343
325
|
};
|
|
344
326
|
return { application, settings };
|
|
345
327
|
}
|
|
328
|
+
function createPromptHistoryConfiguration(settings, backend, ownedSurfaces) {
|
|
329
|
+
const limit = settings?.value("promptHistoryMaxItems") ?? 100;
|
|
330
|
+
const scope = settings?.value("promptHistoryScope") ?? "unique";
|
|
331
|
+
const enabled = settings !== null && ownedSurfaces && settings.value("promptHistoryEnabled");
|
|
332
|
+
const sessionId = enabled ? backend.identity.currentHistorySessionId() : null;
|
|
333
|
+
if (settings === null || !enabled || (scope === "unique" && sessionId === null))
|
|
334
|
+
return null;
|
|
335
|
+
const dataDir = resolvePromptHistoryDataDir();
|
|
336
|
+
const forScope = (selected, id) => {
|
|
337
|
+
if (selected === "unique" && id === null)
|
|
338
|
+
return null;
|
|
339
|
+
const location = resolvePromptHistoryPath(dataDir, backend.identity.agentDir, process.platform, selected, id ?? "");
|
|
340
|
+
return {
|
|
341
|
+
store: new PromptHistoryService({ dataDir, profileRoot: backend.identity.agentDir, limit, scope: selected, sessionId: id ?? "" }),
|
|
342
|
+
imageSidecar: new PromptImageSidecar(location.imagesDir),
|
|
343
|
+
};
|
|
344
|
+
};
|
|
345
|
+
return {
|
|
346
|
+
limit, scope,
|
|
347
|
+
...(sessionId === null ? {} : { sessionId }),
|
|
348
|
+
forScope,
|
|
349
|
+
onScopeChange: (listener) => settings.onChange(() => listener(settings.value("promptHistoryScope"))),
|
|
350
|
+
...forScope(scope, sessionId),
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
function createStartupReleaseUpdateObservation(input) {
|
|
354
|
+
const controller = new AbortController();
|
|
355
|
+
const observe = async () => {
|
|
356
|
+
const check = input.checkForNewerRelease
|
|
357
|
+
?? (await import("../foundation/release/latest-release.js")).checkForNewerRelease;
|
|
358
|
+
const runningVersion = input.packageVersion ?? await readPackageVersion();
|
|
359
|
+
const discoveryVersion = input.mode === "notify" ? input.notificationVersion ?? runningVersion : runningVersion;
|
|
360
|
+
const release = await check({
|
|
361
|
+
runningVersion: discoveryVersion,
|
|
362
|
+
configDir: input.configDir,
|
|
363
|
+
interactive: process.stdout.isTTY === true,
|
|
364
|
+
settingMode: input.mode,
|
|
365
|
+
});
|
|
366
|
+
if (release === null || controller.signal.aborted)
|
|
367
|
+
return;
|
|
368
|
+
if (input.mode === "notify") {
|
|
369
|
+
input.backend.extensions.announceReleaseUpdate(release);
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
if (input.mode === "auto") {
|
|
373
|
+
const installed = await import("../foundation/release/automatic-update.js")
|
|
374
|
+
.then(module => module.requestAutomaticUpdate({ release, runningVersion, signal: controller.signal }));
|
|
375
|
+
if (installed !== null && !controller.signal.aborted) {
|
|
376
|
+
input.backend.extensions.announceReleaseUpdate({ status: "installed", version: installed });
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
return {
|
|
381
|
+
start() { void observe().catch(() => undefined); },
|
|
382
|
+
stop() { controller.abort(); },
|
|
383
|
+
};
|
|
384
|
+
}
|
|
346
385
|
const SHARED_SETTINGS_POLL_MS = 250;
|
|
347
386
|
/** Rereads the shared settings document whenever its stat changes; returns the stop. */
|
|
348
387
|
export function watchSharedSettings(settings) {
|
|
@@ -358,6 +397,18 @@ export function watchSharedSettings(settings) {
|
|
|
358
397
|
watchFile(file, { interval: SHARED_SETTINGS_POLL_MS, persistent: false }, listener);
|
|
359
398
|
return () => unwatchFile(file, listener);
|
|
360
399
|
}
|
|
400
|
+
function settingsRouteOptions(tabBridge, keybindings, agentDir, cwd) {
|
|
401
|
+
return {
|
|
402
|
+
...residentRouteHostOptions(tabBridge),
|
|
403
|
+
keybindings,
|
|
404
|
+
agentDir,
|
|
405
|
+
cwd,
|
|
406
|
+
copyText: text => {
|
|
407
|
+
if (Buffer.byteLength(text) <= MAX_CLIPBOARD_TEXT_BYTES)
|
|
408
|
+
void writeSystemClipboardText(text).catch(() => { });
|
|
409
|
+
},
|
|
410
|
+
};
|
|
411
|
+
}
|
|
361
412
|
function quitOutroSettingsSnapshot(settings) {
|
|
362
413
|
return {
|
|
363
414
|
enabled: settings.value("quitAnimation"),
|
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
import type { TabBridgeClient } from "../foundation/resident-tabs/bridge-client.js";
|
|
2
|
+
import { type ResidentTabRoute } from "../foundation/resident-tabs/routes.js";
|
|
2
3
|
import type { ResidentTabRecovery } from "../foundation/resident-tabs/recovery.js";
|
|
3
4
|
import type { PiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
|
|
4
5
|
import type { ComposedSessionBackend } from "./session-backend.js";
|
|
6
|
+
import type { OwnedRouteHostOptions } from "./settings-route-host.js";
|
|
5
7
|
/**
|
|
6
8
|
* The keybindings the shells borrow. Inside a resident tab the host dispatches and labels the tab
|
|
7
9
|
* shortcuts this child projects from its effective declarations, so the projection is published now
|
|
8
10
|
* and again after every customization reload.
|
|
9
11
|
*/
|
|
10
12
|
export declare function residentTabKeybindings(tabBridge: TabBridgeClient | null, agentDir: string, keybindingsHost: PiKeybindingsHost): PiKeybindingsHost;
|
|
13
|
+
/**
|
|
14
|
+
* How owned screens are presented in a resident tab: a Settings or Changelog tab's screen is the tab, and the Plus menu entry opens
|
|
15
|
+
* the tab bar's own Plus Menu dialog while this tab's controlling client can show it.
|
|
16
|
+
*/
|
|
17
|
+
export declare function residentRouteHostOptions(tabBridge: TabBridgeClient | null): OwnedRouteHostOptions;
|
|
18
|
+
/** Closes a utility tab when its own screen closes. Invariant: a utility tab's screen is the tab. */
|
|
19
|
+
export declare function closeResidentUtilityRoute(tabBridge: Pick<TabBridgeClient, "tabId" | "requestClose">, route: string): void;
|
|
11
20
|
export declare function bindResidentTabBridge(tabBridge: TabBridgeClient, backend: Pick<ComposedSessionBackend, "identity" | "session" | "workflows" | "generateResidentTabName">, recovery?: Pick<ResidentTabRecovery, "settled"> | null, options?: {
|
|
12
21
|
readonly autoName?: boolean;
|
|
13
|
-
readonly openRoute?: (route:
|
|
22
|
+
readonly openRoute?: (route: ResidentTabRoute) => void;
|
|
14
23
|
}): Promise<() => void>;
|
|
15
24
|
export declare function correlateResidentTabSubmission(recovery: Pick<ResidentTabRecovery, "correlated" | "settled">, backend: Pick<ComposedSessionBackend, "identity" | "session">, submissionId: string, entryId: string): Promise<void>;
|
|
16
25
|
export declare function currentBackendSessionFile(backend: Pick<ComposedSessionBackend, "identity">): string | null;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { residentUtilityRoute } from "../foundation/resident-tabs/routes.js";
|
|
1
2
|
import { deriveResidentTabStatus } from "../features/resident-tab/status-deriver.js";
|
|
2
3
|
import { projectResidentTabShortcuts } from "../features/resident-tab/shortcut-projection.js";
|
|
3
4
|
import { readShortcutBindingsFile } from "../features/resident-tab/shortcut-bindings-file.js";
|
|
@@ -16,6 +17,26 @@ export function residentTabKeybindings(tabBridge, agentDir, keybindingsHost) {
|
|
|
16
17
|
publish();
|
|
17
18
|
return { ...keybindingsHost, reload: () => { keybindingsHost.reload(); publish(); } };
|
|
18
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* How owned screens are presented in a resident tab: a Settings or Changelog tab's screen is the tab, and the Plus menu entry opens
|
|
22
|
+
* the tab bar's own Plus Menu dialog while this tab's controlling client can show it.
|
|
23
|
+
*/
|
|
24
|
+
export function residentRouteHostOptions(tabBridge) {
|
|
25
|
+
return {
|
|
26
|
+
...(tabBridge === null ? {} : { tabRoute: residentUtilityRoute(tabBridge.tabId) }),
|
|
27
|
+
configurePlusMenu: () => {
|
|
28
|
+
if (tabBridge === null || !tabBridge.available || tabBridge.captureAttachment() === null)
|
|
29
|
+
return false;
|
|
30
|
+
void tabBridge.requestAction("configure-plus");
|
|
31
|
+
return true;
|
|
32
|
+
},
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** Closes a utility tab when its own screen closes. Invariant: a utility tab's screen is the tab. */
|
|
36
|
+
export function closeResidentUtilityRoute(tabBridge, route) {
|
|
37
|
+
if (residentUtilityRoute(tabBridge.tabId) === route)
|
|
38
|
+
void tabBridge.requestClose();
|
|
39
|
+
}
|
|
19
40
|
export async function bindResidentTabBridge(tabBridge, backend, recovery = null, options = {}) {
|
|
20
41
|
await tabBridge.start().catch(() => false);
|
|
21
42
|
tabBridge.status("starting");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { ReferenceDocumentProvider } from "../features/owned-ui/reference-screen-app.js";
|
|
2
2
|
import type { OwnedSettingsManager } from "../ui/settings/manager.js";
|
|
3
3
|
import type { UiRouteHost, UiRouteInput } from "../ui/apps/contracts.js";
|
|
4
|
+
import type { PiKeybindingsHost } from "../integrations/pi/components/shell-shared-facade.js";
|
|
4
5
|
/** Styled document rows for one content width. */
|
|
5
6
|
export type OwnedReferenceRows = NonNullable<ReferenceDocumentProvider["rows"]>;
|
|
6
7
|
/** Documents supplied by composition so the route host never reads shell data itself. */
|
|
@@ -11,8 +12,17 @@ export interface OwnedReferenceProviders {
|
|
|
11
12
|
}
|
|
12
13
|
/** How the settings route is presented. */
|
|
13
14
|
export interface OwnedRouteHostOptions {
|
|
14
|
-
/**
|
|
15
|
-
|
|
15
|
+
/**
|
|
16
|
+
* The route whose screen is this resident utility tab. That screen is the tab, so it offers no
|
|
17
|
+
* screen-level close: neither Esc nor one Ctrl+C dismisses it, and it shows no close hint.
|
|
18
|
+
*/
|
|
19
|
+
readonly tabRoute?: string | null;
|
|
20
|
+
/** Opens the tab bar's own Plus Menu dialog; false when no tab bar can show it. */
|
|
21
|
+
readonly configurePlusMenu?: () => boolean;
|
|
22
|
+
readonly keybindings?: PiKeybindingsHost;
|
|
23
|
+
readonly agentDir?: string;
|
|
24
|
+
readonly cwd?: string;
|
|
25
|
+
readonly copyText?: (text: string) => void;
|
|
16
26
|
}
|
|
17
27
|
/** Declares settings and lazy document routes. */
|
|
18
28
|
export declare function createOwnedRouteHost(settings: OwnedSettingsManager, references?: OwnedReferenceProviders, options?: OwnedRouteHostOptions): UiRouteHost;
|