@timurproko/a1 0.2.7-dev.810 → 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/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 +9 -3
- 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/transcript-document.js +1 -1
- package/dist/composition/owned-ui.d.ts +3 -11
- package/dist/composition/owned-ui.js +93 -43
- 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 +9 -3
- package/dist/foundation/resident-tabs/bridge-client.js +14 -7
- 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/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 +5 -4
- package/dist/ui/components/prompt-input.js +8 -6
- 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/transcript-viewport.d.ts +1 -1
- package/dist/ui/components/transcript-viewport.js +141 -24
- package/dist/ui/settings/declarations.d.ts +65 -15
- package/dist/ui/settings/declarations.js +45 -13
- package/dist/ui/settings/manager.js +7 -3
- package/dist/ui/settings/migrations.js +22 -0
- package/dist/ui/settings/sections.d.ts +4 -0
- package/dist/ui/settings/sections.js +9 -3
- package/docs/architecture/resident-tabs.md +39 -11
- 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" }),
|
|
@@ -1,18 +1,15 @@
|
|
|
1
1
|
import type { OwnedUiEvent, PromptHistoryImageSidecarPort } from "../../contracts/owned-ui/index.js";
|
|
2
2
|
import type { SessionConcern } from "./session-concern.js";
|
|
3
3
|
import type { OwnedUiShellEngineOptions, OwnedUiSessionShellRoot } from "./session-shell-root.js";
|
|
4
|
-
import type { OwnedUiPresenterTerminal } from "./shell-host.js";
|
|
5
4
|
export type ResidentTabOptions = NonNullable<OwnedUiShellEngineOptions["residentTab"]>;
|
|
6
5
|
export interface ResidentTabCoordinatorPorts {
|
|
7
6
|
readonly root: Pick<OwnedUiSessionShellRoot, "appendWorkflowStatus" | "rehydrateHistoryText" | "editor">;
|
|
8
|
-
readonly terminal: Pick<OwnedUiPresenterTerminal, "requestRender">;
|
|
9
|
-
readonly disposed: () => boolean;
|
|
10
7
|
}
|
|
11
8
|
/**
|
|
12
|
-
* The session presenter's side of a resident tab: recovered input, the
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
9
|
+
* The session presenter's side of a resident tab: recovered input, the idle status it reports to
|
|
10
|
+
* the strip, prompt admission and correlation through the recovery journal, draft checkpoints,
|
|
11
|
+
* detach on quit, and the graceful stop when the presenter is released. Outside a resident tab
|
|
12
|
+
* every operation is a no-op.
|
|
16
13
|
*/
|
|
17
14
|
export declare class ResidentTabCoordinator implements SessionConcern {
|
|
18
15
|
#private;
|
|
@@ -23,8 +20,8 @@ export declare class ResidentTabCoordinator implements SessionConcern {
|
|
|
23
20
|
closeOwnedRoute(route: string): void;
|
|
24
21
|
/** Puts the prompts and draft a previous tab process left unfinished back into the editor. */
|
|
25
22
|
restoreInput(imageSidecar?: PromptHistoryImageSidecarPort): void;
|
|
26
|
-
/**
|
|
27
|
-
|
|
23
|
+
/** Reports idle to the strip whenever the session leaves its busy lifecycle. */
|
|
24
|
+
observeLifecycle(event: OwnedUiEvent): void;
|
|
28
25
|
/** Journals a prompt before it is sent; undefined outside a resident tab. Rejects when the journal cannot sync. */
|
|
29
26
|
admit(input: Parameters<NonNullable<ResidentTabOptions["admit"]>>[0]): Promise<{
|
|
30
27
|
readonly id: string;
|
|
@@ -1,18 +1,12 @@
|
|
|
1
|
-
const PROGRESS_EVENTS = new Set([
|
|
2
|
-
"transcript-block", "session-view", "assistant-message-completed", "agent-run-started",
|
|
3
|
-
]);
|
|
4
1
|
/**
|
|
5
|
-
* The session presenter's side of a resident tab: recovered input, the
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
2
|
+
* The session presenter's side of a resident tab: recovered input, the idle status it reports to
|
|
3
|
+
* the strip, prompt admission and correlation through the recovery journal, draft checkpoints,
|
|
4
|
+
* detach on quit, and the graceful stop when the presenter is released. Outside a resident tab
|
|
5
|
+
* every operation is a no-op.
|
|
9
6
|
*/
|
|
10
7
|
export class ResidentTabCoordinator {
|
|
11
8
|
#options;
|
|
12
9
|
#ports;
|
|
13
|
-
#progressTimer;
|
|
14
|
-
#working = false;
|
|
15
|
-
#stalled = false;
|
|
16
10
|
constructor(options, ports) {
|
|
17
11
|
this.#options = options;
|
|
18
12
|
this.#ports = ports;
|
|
@@ -51,40 +45,10 @@ export class ResidentTabCoordinator {
|
|
|
51
45
|
root.appendWorkflowStatus("Recovered the editor draft from the previous tab process.");
|
|
52
46
|
}
|
|
53
47
|
}
|
|
54
|
-
/**
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
if (resident === undefined || seconds === undefined)
|
|
59
|
-
return;
|
|
60
|
-
if (event.type === "session-lifecycle") {
|
|
61
|
-
this.#working = event.lifecycle === "busy";
|
|
62
|
-
if (!this.#working) {
|
|
63
|
-
this.#clearTimer();
|
|
64
|
-
this.#stalled = false;
|
|
65
|
-
resident.reportStatus?.("idle");
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
else if (!this.#working || !PROGRESS_EVENTS.has(event.type)) {
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
if (this.#stalled) {
|
|
73
|
-
this.#stalled = false;
|
|
74
|
-
resident.reportStatus?.("working");
|
|
75
|
-
}
|
|
76
|
-
this.#clearTimer();
|
|
77
|
-
this.#progressTimer = setTimeout(() => {
|
|
78
|
-
this.#progressTimer = undefined;
|
|
79
|
-
if (this.#ports.disposed() || !this.#working)
|
|
80
|
-
return;
|
|
81
|
-
this.#stalled = true;
|
|
82
|
-
resident.reportStatus?.("stalled");
|
|
83
|
-
const minutes = Math.max(1, Math.round(seconds / 60));
|
|
84
|
-
this.#ports.root.appendWorkflowStatus(`No progress for ${minutes} min — Esc interrupts · use the tab restart action to restart`);
|
|
85
|
-
this.#ports.terminal.requestRender();
|
|
86
|
-
}, seconds * 1_000);
|
|
87
|
-
this.#progressTimer.unref?.();
|
|
48
|
+
/** Reports idle to the strip whenever the session leaves its busy lifecycle. */
|
|
49
|
+
observeLifecycle(event) {
|
|
50
|
+
if (event.type === "session-lifecycle" && event.lifecycle !== "busy")
|
|
51
|
+
this.#options?.reportStatus?.("idle");
|
|
88
52
|
}
|
|
89
53
|
/** Journals a prompt before it is sent; undefined outside a resident tab. Rejects when the journal cannot sync. */
|
|
90
54
|
admit(input) {
|
|
@@ -109,12 +73,5 @@ export class ResidentTabCoordinator {
|
|
|
109
73
|
gracefulStop(sessionFile) {
|
|
110
74
|
return this.#options?.gracefulStop?.(sessionFile) ?? Promise.resolve();
|
|
111
75
|
}
|
|
112
|
-
dispose() {
|
|
113
|
-
this.#clearTimer();
|
|
114
|
-
}
|
|
115
|
-
#clearTimer() {
|
|
116
|
-
if (this.#progressTimer !== undefined)
|
|
117
|
-
clearTimeout(this.#progressTimer);
|
|
118
|
-
this.#progressTimer = undefined;
|
|
119
|
-
}
|
|
76
|
+
dispose() { }
|
|
120
77
|
}
|
|
@@ -47,8 +47,7 @@ export interface OwnedUiShellEngineOptions {
|
|
|
47
47
|
readonly residentTab?: {
|
|
48
48
|
requestDetach(): Promise<boolean>;
|
|
49
49
|
closeOwnedRoute?(route: string): void;
|
|
50
|
-
reportStatus?(status: "working" | "idle"
|
|
51
|
-
readonly stallNoticeSeconds?: number;
|
|
50
|
+
reportStatus?(status: "working" | "idle"): void;
|
|
52
51
|
admit?(input: {
|
|
53
52
|
readonly sessionId: string;
|
|
54
53
|
readonly sessionFile: string | null;
|
|
@@ -117,6 +116,13 @@ export interface OwnedUiShellPresentationOptions {
|
|
|
117
116
|
/** Persistent prompt history: its store, its bound, the editor that recalls it, and the image sidecar. */
|
|
118
117
|
export interface OwnedUiShellHistoryOptions {
|
|
119
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;
|
|
120
126
|
readonly limit: number;
|
|
121
127
|
readonly editor: import("../../integrations/pi/components/index.js").HistoryEditorConstructor;
|
|
122
128
|
/** Optional per-profile filesystem sidecar for image chip payloads. When present, submit
|
|
@@ -192,7 +198,7 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
192
198
|
readonly requestHyperlinkCleanup?: (rows?: readonly number[]) => void;
|
|
193
199
|
readonly enableDockInputReuse?: boolean;
|
|
194
200
|
readonly persistentHistory?: boolean;
|
|
195
|
-
readonly
|
|
201
|
+
readonly hideUtilityTabCommands?: boolean;
|
|
196
202
|
readonly historyEditor?: import("../../integrations/pi/components/index.js").HistoryEditorConstructor;
|
|
197
203
|
readonly onSubmit: (text: string) => void;
|
|
198
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()); },
|
|
@@ -251,7 +257,7 @@ export class OwnedUiSessionPresenter {
|
|
|
251
257
|
// Invariant: the presenter owns its root (theme subscription and helper clients) and disposes it once the
|
|
252
258
|
// terminal no longer renders it.
|
|
253
259
|
constructed.push(() => this.root.dispose());
|
|
254
|
-
this.#resident = new ResidentTabCoordinator(options.engine.residentTab, { root: this.root
|
|
260
|
+
this.#resident = new ResidentTabCoordinator(options.engine.residentTab, { root: this.root });
|
|
255
261
|
constructed.push(() => this.#resident.dispose());
|
|
256
262
|
const startupRoute = options.engine.startupRoute;
|
|
257
263
|
this.#dialogs = new SessionDialogCoordinator({
|
|
@@ -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
|
}
|
|
@@ -366,7 +372,7 @@ export class OwnedUiSessionPresenter {
|
|
|
366
372
|
this.#stop.settleAfter(() => this.dispose());
|
|
367
373
|
return;
|
|
368
374
|
}
|
|
369
|
-
this.#resident.
|
|
375
|
+
this.#resident.observeLifecycle(event);
|
|
370
376
|
// Performance: a streamed chunk names one block, and touching only that block is what keeps the
|
|
371
377
|
// cost of a chunk the same in a long session as in a new one. Everything else
|
|
372
378
|
// resynchronizes the view, which is cheap next to re-reading the transcript.
|
|
@@ -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))
|
|
@@ -322,8 +322,8 @@ export class SessionViewportController {
|
|
|
322
322
|
this.#requestRender();
|
|
323
323
|
}
|
|
324
324
|
}
|
|
325
|
-
const previousPrompt =
|
|
326
|
-
if (editorActive && allowWheel && (previousPrompt ||
|
|
325
|
+
const previousPrompt = PROMPT_UP_INPUTS.has(data) || this.#editor.matchesTerminalKey(data, "alt+home");
|
|
326
|
+
if (editorActive && allowWheel && (previousPrompt || PROMPT_DOWN_INPUTS.has(data))) {
|
|
327
327
|
const scrolled = previousPrompt
|
|
328
328
|
? this.#viewport.scrollToPreviousPrompt(now)
|
|
329
329
|
: this.#viewport.scrollToNextPrompt(now);
|
|
@@ -670,5 +670,7 @@ export class SessionViewportController {
|
|
|
670
670
|
}
|
|
671
671
|
const SELECTION_AUTO_SCROLL_INTERVAL_MS = 30;
|
|
672
672
|
const EDITOR_LINK_DELETION_INPUTS = new Set(["\b", "\u007f", "\u001b[3~"]);
|
|
673
|
-
|
|
674
|
-
|
|
673
|
+
// Platform: Windows Terminal may consume Shift+Arrow for native selection. Ctrl+Arrow matches
|
|
674
|
+
// solo A1's Windows binding while retaining Shift+Arrow whenever the terminal delivers it.
|
|
675
|
+
const PROMPT_UP_INPUTS = new Set(["\u001b[1;2A", "\u001b[1;5A"]);
|
|
676
|
+
const PROMPT_DOWN_INPUTS = new Set(["\u001b[1;2B", "\u001b[1;5B"]);
|
|
@@ -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 {
|