@timurproko/a1 0.2.7-dev.1264 → 0.2.7-dev.1265
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.
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { SessionTerminalPresentation } from "./session-terminal-presentation.js";
|
|
1
2
|
import { ShellClipboard } from "./shell-clipboard.js";
|
|
2
3
|
import { SessionPromptHistory } from "./session-prompt-history.js";
|
|
3
4
|
import { shellResourceEntries } from "./resource-labels.js";
|
|
@@ -64,7 +65,11 @@ export class OwnedUiSessionPresenter {
|
|
|
64
65
|
#inputCoordination;
|
|
65
66
|
#unbindShellSettings;
|
|
66
67
|
#unbindSessionSettings;
|
|
67
|
-
#
|
|
68
|
+
#terminalPresentation = new SessionTerminalPresentation({
|
|
69
|
+
terminal: () => this.#terminal,
|
|
70
|
+
programStatus: () => this.#programStatus,
|
|
71
|
+
titleEnabled: () => this.#customViewport && this.#started && !this.#disposed,
|
|
72
|
+
});
|
|
68
73
|
#programStatus;
|
|
69
74
|
#fullscreenExitOutput = "transcript";
|
|
70
75
|
#lastClearTime = 0;
|
|
@@ -186,7 +191,7 @@ export class OwnedUiSessionPresenter {
|
|
|
186
191
|
this.#programStatus = options.presenters.components.chrome.programStatusReporter(status => this.#terminal.setProgramStatus(status), () => this.view().status.footer?.sessionName ?? undefined);
|
|
187
192
|
this.#login = new LoginInteraction({
|
|
188
193
|
terminal: this.#terminal, root: this.root, programStatus: this.#programStatus, dialogs: options.presenters.components.dialogs,
|
|
189
|
-
syncProgress: () => this.#
|
|
194
|
+
syncProgress: () => this.#terminalPresentation.syncProgress(this.view()),
|
|
190
195
|
});
|
|
191
196
|
this.#submission = this.#createSubmission(cwd);
|
|
192
197
|
this.#reloadPresentation = reloadPresentation;
|
|
@@ -216,9 +221,9 @@ export class OwnedUiSessionPresenter {
|
|
|
216
221
|
terminal: this.#terminal,
|
|
217
222
|
root: this.root,
|
|
218
223
|
setTerminalProgress: enabled => {
|
|
219
|
-
this.#
|
|
224
|
+
this.#terminalPresentation.progressEnabled = enabled;
|
|
220
225
|
if (this.#terminal.running)
|
|
221
|
-
this.#
|
|
226
|
+
this.#terminalPresentation.syncProgress(this.view());
|
|
222
227
|
},
|
|
223
228
|
}, { customViewport: this.#customViewport });
|
|
224
229
|
constructed.push(this.#unbindSessionSettings);
|
|
@@ -291,7 +296,9 @@ export class OwnedUiSessionPresenter {
|
|
|
291
296
|
return this.#layoutParts[part];
|
|
292
297
|
}
|
|
293
298
|
activated() {
|
|
294
|
-
this
|
|
299
|
+
const view = this.view();
|
|
300
|
+
this.#terminalPresentation.syncProgress(view);
|
|
301
|
+
this.#terminalPresentation.syncTitle(view, true);
|
|
295
302
|
}
|
|
296
303
|
handleViewportInput(data) {
|
|
297
304
|
if (!this.#inputCoordination)
|
|
@@ -360,7 +367,7 @@ export class OwnedUiSessionPresenter {
|
|
|
360
367
|
const view = event.type === "transcript-block" && this.#sessionGeneration === this.backend.identity.sessionGeneration
|
|
361
368
|
? this.#syncBlock(event.block)
|
|
362
369
|
: semanticOnly ? this.view() : this.#syncView();
|
|
363
|
-
this.#
|
|
370
|
+
this.#terminalPresentation.syncProgress(view);
|
|
364
371
|
this.#promptSuggestions?.noteView(view, this.backend.identity.sessionGeneration !== this.#sessionGeneration);
|
|
365
372
|
if (event.type === "status" && /^(Retrying|Compacting)/.test(event.status.workingMessage ?? "")) {
|
|
366
373
|
this.#promptSuggestions?.invalidate();
|
|
@@ -385,8 +392,9 @@ export class OwnedUiSessionPresenter {
|
|
|
385
392
|
return;
|
|
386
393
|
this.#started = true;
|
|
387
394
|
this.#terminal.start();
|
|
395
|
+
this.#terminalPresentation.syncTitle(this.view());
|
|
388
396
|
this.#history?.start();
|
|
389
|
-
this.#
|
|
397
|
+
this.#terminalPresentation.syncProgress(this.view());
|
|
390
398
|
void this.backend.extensions.bindExtensionUi(this.#extensionBridge.context, () => { void this.shutdown(); });
|
|
391
399
|
this.#syncView();
|
|
392
400
|
// Performance: the spare clipboard helpers fork after the first frame is out, so startup never waits on them.
|
|
@@ -822,28 +830,13 @@ export class OwnedUiSessionPresenter {
|
|
|
822
830
|
}
|
|
823
831
|
this.#history?.rebind(replaced, scope);
|
|
824
832
|
}
|
|
825
|
-
#syncTerminalProgress(view) {
|
|
826
|
-
if (!this.#terminal.running)
|
|
827
|
-
return;
|
|
828
|
-
this.#terminal.setTerminalProgress(this.#terminalProgressEnabled && view.lifecycle === "busy");
|
|
829
|
-
if (view.lifecycle === "stopped" || view.lifecycle === "stopping") {
|
|
830
|
-
this.#programStatus.clear();
|
|
831
|
-
return;
|
|
832
|
-
}
|
|
833
|
-
this.#programStatus.setBlocked("dialog", view.dialog === null ? undefined : {
|
|
834
|
-
kind: "question",
|
|
835
|
-
message: view.dialog.title,
|
|
836
|
-
});
|
|
837
|
-
if (view.lifecycle === "failed")
|
|
838
|
-
this.#programStatus.setErrorMessage(view.status.diagnostics.at(-1));
|
|
839
|
-
this.#programStatus.report();
|
|
840
|
-
}
|
|
841
833
|
#syncView() {
|
|
842
834
|
this.#streamPresentation.noteImmediatePresentation();
|
|
843
835
|
const view = this.view();
|
|
844
836
|
if (this.backend.identity.sessionGeneration !== this.#sessionGeneration)
|
|
845
837
|
this.#concerns.replaceSession();
|
|
846
838
|
this.root.update(view);
|
|
839
|
+
this.#terminalPresentation.syncTitle(view);
|
|
847
840
|
this.#dialogs.syncBackend(view.dialog);
|
|
848
841
|
this.#presentStartupTrustWarning(view);
|
|
849
842
|
this.#terminal.requestRender();
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { OwnedUiSessionViewModel, OwnedUiShellProgramStatusReporter } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { OwnedUiPresenterTerminal } from "./shell-host.js";
|
|
3
|
+
interface SessionTerminalPresentationPorts {
|
|
4
|
+
terminal(): OwnedUiPresenterTerminal;
|
|
5
|
+
programStatus(): OwnedUiShellProgramStatusReporter;
|
|
6
|
+
titleEnabled(): boolean;
|
|
7
|
+
}
|
|
8
|
+
/** Session-derived terminal state, published only through the presenter's guarded handle. */
|
|
9
|
+
export declare class SessionTerminalPresentation {
|
|
10
|
+
#private;
|
|
11
|
+
progressEnabled: boolean;
|
|
12
|
+
constructor(ports: SessionTerminalPresentationPorts);
|
|
13
|
+
syncTitle(view: OwnedUiSessionViewModel, force?: boolean): void;
|
|
14
|
+
syncProgress(view: OwnedUiSessionViewModel): void;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
2
|
+
/** Session-derived terminal state, published only through the presenter's guarded handle. */
|
|
3
|
+
export class SessionTerminalPresentation {
|
|
4
|
+
#ports;
|
|
5
|
+
progressEnabled = false;
|
|
6
|
+
// Invariant: extension titles never change this memo, so unrelated views leave them alone.
|
|
7
|
+
#lastCoreTitle;
|
|
8
|
+
constructor(ports) { this.#ports = ports; }
|
|
9
|
+
syncTitle(view, force = false) {
|
|
10
|
+
const terminal = this.#ports.terminal();
|
|
11
|
+
if (!this.#ports.titleEnabled() || !terminal.running || !terminal.attached)
|
|
12
|
+
return;
|
|
13
|
+
const title = view.status.footer?.sessionName?.replace(/[\u0000-\u001f\u007f-\u009f\u2028\u2029]+/gu, " ").trim()
|
|
14
|
+
|| PRODUCT_IDENTITY.displayName;
|
|
15
|
+
if (!force && title === this.#lastCoreTitle)
|
|
16
|
+
return;
|
|
17
|
+
terminal.setTitle(title);
|
|
18
|
+
this.#lastCoreTitle = title;
|
|
19
|
+
}
|
|
20
|
+
syncProgress(view) {
|
|
21
|
+
const terminal = this.#ports.terminal();
|
|
22
|
+
if (!terminal.running)
|
|
23
|
+
return;
|
|
24
|
+
const status = this.#ports.programStatus();
|
|
25
|
+
terminal.setTerminalProgress(this.progressEnabled && view.lifecycle === "busy");
|
|
26
|
+
if (view.lifecycle === "stopped" || view.lifecycle === "stopping") {
|
|
27
|
+
status.clear();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
status.setBlocked("dialog", view.dialog === null ? undefined : { kind: "question", message: view.dialog.title });
|
|
31
|
+
if (view.lifecycle === "failed")
|
|
32
|
+
status.setErrorMessage(view.status.diagnostics.at(-1));
|
|
33
|
+
status.report();
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -65,6 +65,11 @@ export class PiSessionEvents {
|
|
|
65
65
|
/** Apply one pinned Pi session event; image assets no block references any more are released afterwards. */
|
|
66
66
|
handle(event) {
|
|
67
67
|
try {
|
|
68
|
+
if (!isRecord(event) || typeof event.type !== "string")
|
|
69
|
+
return;
|
|
70
|
+
// Invariant: usage moves at message and lifecycle boundaries, not with stream chunks.
|
|
71
|
+
if (event.type !== "message_update" && event.type !== "tool_execution_update")
|
|
72
|
+
this.#ports.usageInvalidated();
|
|
68
73
|
this.#applyPiEvent(event);
|
|
69
74
|
}
|
|
70
75
|
finally {
|
|
@@ -72,12 +77,6 @@ export class PiSessionEvents {
|
|
|
72
77
|
}
|
|
73
78
|
}
|
|
74
79
|
#applyPiEvent(event) {
|
|
75
|
-
if (!isRecord(event) || typeof event.type !== "string")
|
|
76
|
-
return;
|
|
77
|
-
// Invariant: usage moves at message and lifecycle boundaries, not with stream chunks, so the
|
|
78
|
-
// two streaming event kinds keep the memo and everything else drops it.
|
|
79
|
-
if (event.type !== "message_update" && event.type !== "tool_execution_update")
|
|
80
|
-
this.#ports.usageInvalidated();
|
|
81
80
|
switch (event.type) {
|
|
82
81
|
case "agent_start":
|
|
83
82
|
this.#agentRunActive = true;
|
|
@@ -221,6 +220,9 @@ export class PiSessionEvents {
|
|
|
221
220
|
if (event.reason === "manual")
|
|
222
221
|
this.#ports.deliverQueuedAfterCompaction();
|
|
223
222
|
return;
|
|
223
|
+
case "session_info_changed":
|
|
224
|
+
this.#ports.emitView();
|
|
225
|
+
return;
|
|
224
226
|
case "thinking_level_changed":
|
|
225
227
|
this.#ports.thinkingLevelChanged(readThinkingLevel(event.level));
|
|
226
228
|
return;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@timurproko/a1",
|
|
3
|
-
"version": "0.2.7-dev.
|
|
3
|
+
"version": "0.2.7-dev.1265",
|
|
4
4
|
"description": "Standalone single-agent terminal UI on pinned Pi",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"privateLaunchContract": "neutral-launch-v1",
|
|
@@ -113,7 +113,7 @@
|
|
|
113
113
|
"@mariozechner/clipboard": "^0.3.9"
|
|
114
114
|
},
|
|
115
115
|
"publication": {
|
|
116
|
-
"source": "
|
|
117
|
-
"pullRequest":
|
|
116
|
+
"source": "747f0f74face4482a28c0a8f1df3ea088ee6df50",
|
|
117
|
+
"pullRequest": 892
|
|
118
118
|
}
|
|
119
119
|
}
|