@timurproko/a1 0.2.7-dev.1255 → 0.2.7-dev.1264
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/dist/app/session-shell/prompt-submission.d.ts +1 -1
- package/dist/app/session-shell/prompt-submission.js +9 -9
- package/dist/app/session-shell/resource-labels.d.ts +2 -0
- package/dist/app/session-shell/resource-labels.js +158 -0
- package/dist/app/session-shell/session-prompt-history.d.ts +29 -0
- package/dist/app/session-shell/session-prompt-history.js +80 -0
- package/dist/app/session-shell/session-selectors.d.ts +46 -0
- package/dist/app/session-shell/session-selectors.js +269 -0
- package/dist/app/session-shell/session-shell-root.d.ts +6 -28
- package/dist/app/session-shell/session-shell-root.js +26 -220
- package/dist/app/session-shell/session-shell.d.ts +3 -23
- package/dist/app/session-shell/session-shell.js +54 -365
- package/dist/app/session-shell/session-viewport-controller.d.ts +2 -10
- package/dist/app/session-shell/session-viewport-controller.js +40 -318
- package/dist/app/session-shell/settings-bindings.d.ts +1 -1
- package/dist/app/session-shell/settings-bindings.js +2 -2
- package/dist/app/session-shell/viewport-pointer.d.ts +83 -0
- package/dist/app/session-shell/viewport-pointer.js +361 -0
- package/dist/composition/owned-ui.js +63 -59
- package/dist/contracts/owned-ui/index.d.ts +1 -1
- package/dist/contracts/owned-ui/index.js +1 -1
- package/dist/contracts/owned-ui/validation.d.ts +1 -11
- package/dist/contracts/owned-ui/validation.js +8 -104
- package/dist/contracts/presentation/index.d.ts +1 -1
- package/dist/contracts/presentation/terminal.d.ts +0 -6
- package/dist/features/owned-ui/settings-app.js +13 -208
- package/dist/features/owned-ui/settings-model-dialog.d.ts +41 -0
- package/dist/features/owned-ui/settings-model-dialog.js +194 -0
- package/dist/foundation/release/automatic-update.js +1 -8
- package/dist/foundation/release/dependency-layer.js +3 -3
- package/dist/foundation/release/latest-release.js +1 -1
- package/dist/foundation/release/managed-path.d.ts +10 -0
- package/dist/foundation/release/managed-path.js +26 -0
- package/dist/foundation/release/release-gc.js +6 -8
- package/dist/foundation/release/restart-certification.js +3 -4
- package/dist/foundation/release/update-activation.js +1 -1
- package/dist/foundation/release/update-execution-lease.js +1 -7
- package/dist/foundation/release/update-installer.d.ts +45 -0
- package/dist/foundation/release/update-installer.js +57 -0
- package/dist/foundation/release/update-recovery.js +2 -9
- package/dist/foundation/release/update.d.ts +4 -23
- package/dist/foundation/release/update.js +160 -179
- package/dist/integrations/pi/components/bracketed-paste.d.ts +33 -0
- package/dist/integrations/pi/components/bracketed-paste.js +123 -0
- package/dist/integrations/pi/components/owned-editor-ux.js +46 -140
- package/dist/integrations/pi/engine/adapter.d.ts +1 -8
- package/dist/integrations/pi/engine/adapter.js +6 -49
- package/dist/integrations/pi/engine/host.js +1 -1
- package/dist/integrations/pi/engine/repository-metadata.d.ts +49 -0
- package/dist/integrations/pi/engine/repository-metadata.js +189 -0
- package/dist/integrations/pi/engine/session-runtime.d.ts +6 -12
- package/dist/integrations/pi/engine/session-runtime.js +21 -178
- package/dist/integrations/pi/engine/view-state.d.ts +21 -2
- package/dist/integrations/pi/engine/view-state.js +129 -1
- package/dist/integrations/pi/engine/workflow-runner.d.ts +0 -1
- package/dist/integrations/pi/engine/workflow-runner.js +254 -365
- package/dist/integrations/pi/engine/workflow-share.d.ts +9 -0
- package/dist/integrations/pi/engine/workflow-share.js +168 -0
- package/dist/integrations/pi/engine/workflow-support.d.ts +0 -14
- package/dist/integrations/pi/engine/workflow-support.js +0 -47
- package/dist/integrations/pi/tui-runtime/adapter.d.ts +9 -19
- package/dist/integrations/pi/tui-runtime/adapter.js +35 -144
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +4 -4
- package/dist/integrations/pi/tui-runtime/index.d.ts +0 -1
- package/dist/integrations/pi/tui-runtime/overlay-geometry.d.ts +2 -2
- package/dist/integrations/pi/tui-runtime/presentation-adapter.d.ts +2 -2
- package/dist/ui/components/transcript-viewport-frame.d.ts +120 -0
- package/dist/ui/components/transcript-viewport-frame.js +314 -0
- package/dist/ui/components/transcript-viewport-types.d.ts +147 -0
- package/dist/ui/components/transcript-viewport.d.ts +2 -147
- package/dist/ui/components/transcript-viewport.js +87 -315
- package/package.json +3 -3
- package/dist/integrations/pi/engine/diagnostics-state.d.ts +0 -9
- package/dist/integrations/pi/engine/diagnostics-state.js +0 -34
- package/dist/integrations/pi/engine/usage-view.d.ts +0 -4
- package/dist/integrations/pi/engine/usage-view.js +0 -56
- package/dist/integrations/pi/tui-runtime/contracts.d.ts +0 -22
- /package/dist/{integrations/pi/tui-runtime/contracts.js → ui/components/transcript-viewport-types.js} +0 -0
|
@@ -5,7 +5,8 @@ import type { PiProjectTrustPreflightPrompt } from "./project-trust-preflight.js
|
|
|
5
5
|
import type { PiSessionForkPrompt, PiSessionSelection } from "./session-selection.js";
|
|
6
6
|
import type { OwnedUiDiagnostics } from "../../../contracts/owned-ui/index.js";
|
|
7
7
|
import type { PiSessionResumeMetadata, PiWorkflowHost } from "./workflows.js";
|
|
8
|
-
import
|
|
8
|
+
import type { PiPullRequestProbe } from "./repository-pr.js";
|
|
9
|
+
import { RepositoryMetadataPoller, type PiRepositoryContextReader } from "./repository-metadata.js";
|
|
9
10
|
export interface PiEngineRuntimeFactoryInput {
|
|
10
11
|
readonly cwd: string;
|
|
11
12
|
readonly agentDir: string;
|
|
@@ -20,12 +21,7 @@ export interface PiEngineRuntimeFactoryInput {
|
|
|
20
21
|
}
|
|
21
22
|
export type PiEngineRuntimeFactory = (input: PiEngineRuntimeFactoryInput) => Promise<AgentSessionRuntime>;
|
|
22
23
|
export type PiEnginePackageUpdateProbe = (settingsManager: AgentSessionServices["settingsManager"]) => Promise<readonly string[]>;
|
|
23
|
-
|
|
24
|
-
readonly cwd: string;
|
|
25
|
-
readonly branch: string;
|
|
26
|
-
}
|
|
27
|
-
export type PiRepositoryContextReader = (sessionId: string, sessionFile: string, signal: AbortSignal) => Promise<PiRepositoryContextSelection | null>;
|
|
28
|
-
type PiGitBranchReader = (cwd: string, signal: AbortSignal) => Promise<string | null>;
|
|
24
|
+
export type { PiRepositoryContextReader } from "./repository-metadata.js";
|
|
29
25
|
interface PiEngineRuntimeOptions {
|
|
30
26
|
readonly cwd: string;
|
|
31
27
|
readonly agentDir: string;
|
|
@@ -43,7 +39,7 @@ interface PiEngineRuntimeOptions {
|
|
|
43
39
|
readonly pullRequestRefreshMs?: number;
|
|
44
40
|
readonly repositoryContextPollMs?: number;
|
|
45
41
|
readonly repositoryContextReader?: PiRepositoryContextReader;
|
|
46
|
-
readonly gitBranchReader?:
|
|
42
|
+
readonly gitBranchReader?: (cwd: string, signal: AbortSignal) => Promise<string | null>;
|
|
47
43
|
readonly host: PiWorkflowHost;
|
|
48
44
|
}
|
|
49
45
|
export interface PiEngineRuntimePorts {
|
|
@@ -74,9 +70,8 @@ export declare class PiEngineRuntime {
|
|
|
74
70
|
/** Actual session replacements, excluding delivery-only invalidation of callbacks. */
|
|
75
71
|
get bindingGeneration(): number;
|
|
76
72
|
get cwd(): string;
|
|
77
|
-
|
|
78
|
-
get
|
|
79
|
-
get pullRequest(): PiPullRequestIdentity | null;
|
|
73
|
+
/** The branch and pull request polled for the bound session. */
|
|
74
|
+
get repository(): RepositoryMetadataPoller;
|
|
80
75
|
get sessionCommands(): PiSessionCommandIntegration | undefined;
|
|
81
76
|
get started(): boolean;
|
|
82
77
|
/** Create the runtime and bind its first session; startup failures propagate. */
|
|
@@ -106,4 +101,3 @@ export declare class PiEngineRuntime {
|
|
|
106
101
|
*/
|
|
107
102
|
announceChangelog(): Promise<void>;
|
|
108
103
|
}
|
|
109
|
-
export {};
|
|
@@ -1,17 +1,10 @@
|
|
|
1
|
-
import { execFile } from "node:child_process";
|
|
2
1
|
import { existsSync } from "node:fs";
|
|
3
|
-
import { promisify } from "node:util";
|
|
4
2
|
import { PRODUCT_IDENTITY } from "../../../product-identity.js";
|
|
5
3
|
import { observeCompactionProgress } from "./compaction-progress.js";
|
|
6
4
|
import { createPiRuntimeIntegration } from "./runtime-integration.js";
|
|
7
5
|
import { PiSessionCommandIntegration } from "./session-integration.js";
|
|
8
6
|
import { DefaultPackageManager, VERSION } from "../startup-public.js";
|
|
9
|
-
import {
|
|
10
|
-
const execFileAsync = promisify(execFile);
|
|
11
|
-
const PULL_REQUEST_REFRESH_MS = 60_000;
|
|
12
|
-
const REPOSITORY_CONTEXT_POLL_MS = 5_000;
|
|
13
|
-
const GIT_BRANCH_TIMEOUT_MS = 5_000;
|
|
14
|
-
const GIT_BRANCH_MAX_BUFFER_BYTES = 4 * 1024;
|
|
7
|
+
import { RepositoryMetadataPoller } from "./repository-metadata.js";
|
|
15
8
|
/**
|
|
16
9
|
* The pinned Pi runtime and the session bound to it: creation through the runtime factory, the
|
|
17
10
|
* session generation that stamps and invalidates events, the subscription that forwards session
|
|
@@ -26,11 +19,6 @@ export class PiEngineRuntime {
|
|
|
26
19
|
#ports;
|
|
27
20
|
#runtimeFactory;
|
|
28
21
|
#checkPackageUpdates;
|
|
29
|
-
#pullRequestProbe;
|
|
30
|
-
#pullRequestRefreshMs;
|
|
31
|
-
#repositoryContextPollMs;
|
|
32
|
-
#repositoryContextReader;
|
|
33
|
-
#gitBranchReader;
|
|
34
22
|
#cwd;
|
|
35
23
|
#runtime;
|
|
36
24
|
#session;
|
|
@@ -39,31 +27,27 @@ export class PiEngineRuntime {
|
|
|
39
27
|
#sessionBindingGeneration = 0;
|
|
40
28
|
#sessionCommands;
|
|
41
29
|
#compactionProgress = null;
|
|
42
|
-
#
|
|
43
|
-
#gitBranch = null;
|
|
44
|
-
#pullRequest = null;
|
|
45
|
-
#repositoryRefreshTimer;
|
|
46
|
-
#repositoryRefreshAbort;
|
|
47
|
-
#repositoryRefreshTask;
|
|
48
|
-
#repositoryRefreshPending = false;
|
|
49
|
-
#lastPullRequestProbeAt = null;
|
|
50
|
-
#repositoryRefreshEnabled = false;
|
|
30
|
+
#repository;
|
|
51
31
|
#disposed = false;
|
|
52
32
|
constructor(options, ports) {
|
|
53
33
|
this.#options = options;
|
|
54
34
|
this.#ports = ports;
|
|
55
35
|
this.#cwd = options.cwd;
|
|
56
|
-
this.#repositoryCwd = options.cwd;
|
|
57
36
|
this.#runtimeFactory = options.createRuntime ?? createDefaultPiRuntime;
|
|
58
37
|
this.#checkPackageUpdates = options.checkPackageUpdates
|
|
59
38
|
?? (options.createRuntime
|
|
60
39
|
? async () => []
|
|
61
40
|
: settingsManager => checkDefaultPiPackageUpdates(this.#cwd, options.agentDir, settingsManager));
|
|
62
|
-
this.#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
41
|
+
this.#repository = new RepositoryMetadataPoller(options, {
|
|
42
|
+
bindingGeneration: () => this.#sessionBindingGeneration,
|
|
43
|
+
sessionIdentity: () => {
|
|
44
|
+
const manager = this.#session?.sessionManager;
|
|
45
|
+
return { sessionId: manager?.getSessionId?.(), sessionFile: manager?.getSessionFile?.() };
|
|
46
|
+
},
|
|
47
|
+
fallbackCwd: () => this.#cwd,
|
|
48
|
+
disposed: () => this.#disposed || this.#ports.disposed(),
|
|
49
|
+
changed: () => this.#ports.emitView(),
|
|
50
|
+
});
|
|
67
51
|
}
|
|
68
52
|
get runtime() {
|
|
69
53
|
return this.#runtime;
|
|
@@ -82,14 +66,9 @@ export class PiEngineRuntime {
|
|
|
82
66
|
get cwd() {
|
|
83
67
|
return this.#runtime?.cwd ?? this.#cwd;
|
|
84
68
|
}
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
get gitBranch() {
|
|
89
|
-
return this.#gitBranch;
|
|
90
|
-
}
|
|
91
|
-
get pullRequest() {
|
|
92
|
-
return this.#pullRequest;
|
|
69
|
+
/** The branch and pull request polled for the bound session. */
|
|
70
|
+
get repository() {
|
|
71
|
+
return this.#repository;
|
|
93
72
|
}
|
|
94
73
|
get sessionCommands() {
|
|
95
74
|
return this.#sessionCommands;
|
|
@@ -112,7 +91,7 @@ export class PiEngineRuntime {
|
|
|
112
91
|
});
|
|
113
92
|
this.#runtime = runtime;
|
|
114
93
|
this.#cwd = runtime.cwd ?? this.#cwd;
|
|
115
|
-
this.#
|
|
94
|
+
this.#repository.reset();
|
|
116
95
|
this.#ports.started(runtime);
|
|
117
96
|
runtime.setRebindSession(async (session) => {
|
|
118
97
|
if (this.#ports.rebindBlocked())
|
|
@@ -127,8 +106,7 @@ export class PiEngineRuntime {
|
|
|
127
106
|
this.#ports.diagnostic(diagnostic.type === "error" ? "error" : diagnostic.type === "warning" ? "warning" : "info", code, diagnostic.message, diagnostic.type !== "error");
|
|
128
107
|
}
|
|
129
108
|
this.bindSession(runtime.session);
|
|
130
|
-
this.#
|
|
131
|
-
this.#startRepositoryRefresh();
|
|
109
|
+
this.#repository.start();
|
|
132
110
|
return runtime;
|
|
133
111
|
}
|
|
134
112
|
/**
|
|
@@ -186,10 +164,9 @@ export class PiEngineRuntime {
|
|
|
186
164
|
// Invariant: the subscription is live before the adapter rebuilds its state so the extension
|
|
187
165
|
// rebind that finishes the rebuild cannot emit an event nobody is listening to.
|
|
188
166
|
this.#subscribe();
|
|
189
|
-
this.#
|
|
167
|
+
this.#repository.reset();
|
|
190
168
|
this.#ports.sessionReplaced(session);
|
|
191
|
-
|
|
192
|
-
this.#startRepositoryRefresh();
|
|
169
|
+
this.#repository.refresh();
|
|
193
170
|
}
|
|
194
171
|
/** Stop forwarding the current session's events and open a new generation; overload recovery resumes or abandons it. */
|
|
195
172
|
suspend() {
|
|
@@ -235,127 +212,14 @@ export class PiEngineRuntime {
|
|
|
235
212
|
/** Unsubscribe, stop observing compaction, and dispose the runtime; the session reference is kept for final reads. */
|
|
236
213
|
async dispose() {
|
|
237
214
|
this.#disposed = true;
|
|
238
|
-
|
|
239
|
-
if (this.#repositoryRefreshTimer !== undefined)
|
|
240
|
-
clearTimeout(this.#repositoryRefreshTimer);
|
|
241
|
-
this.#repositoryRefreshTimer = undefined;
|
|
242
|
-
this.#repositoryRefreshPending = false;
|
|
243
|
-
this.#repositoryRefreshAbort?.abort();
|
|
244
|
-
const repositoryRefreshTask = this.#repositoryRefreshTask;
|
|
215
|
+
const repository = this.#repository.dispose();
|
|
245
216
|
this.#unsubscribe?.();
|
|
246
217
|
this.#unsubscribe = undefined;
|
|
247
218
|
this.#compactionProgress?.dispose();
|
|
248
219
|
this.#compactionProgress = null;
|
|
249
|
-
await
|
|
220
|
+
await repository;
|
|
250
221
|
await this.#runtime?.dispose();
|
|
251
222
|
}
|
|
252
|
-
#startRepositoryRefresh() {
|
|
253
|
-
if (!this.#repositoryRefreshEnabled || this.#disposed || this.#ports.disposed())
|
|
254
|
-
return;
|
|
255
|
-
if (this.#repositoryRefreshTask !== undefined) {
|
|
256
|
-
this.#repositoryRefreshPending = true;
|
|
257
|
-
return;
|
|
258
|
-
}
|
|
259
|
-
const task = this.#refreshRepositoryMetadata();
|
|
260
|
-
this.#repositoryRefreshTask = task;
|
|
261
|
-
const settled = () => {
|
|
262
|
-
if (this.#repositoryRefreshTask === task)
|
|
263
|
-
this.#repositoryRefreshTask = undefined;
|
|
264
|
-
if (!this.#repositoryRefreshPending)
|
|
265
|
-
return;
|
|
266
|
-
this.#repositoryRefreshPending = false;
|
|
267
|
-
this.#startRepositoryRefresh();
|
|
268
|
-
};
|
|
269
|
-
void task.then(settled, settled);
|
|
270
|
-
}
|
|
271
|
-
#resetRepositoryRefresh() {
|
|
272
|
-
if (this.#repositoryRefreshTimer !== undefined)
|
|
273
|
-
clearTimeout(this.#repositoryRefreshTimer);
|
|
274
|
-
this.#repositoryRefreshTimer = undefined;
|
|
275
|
-
this.#repositoryRefreshAbort?.abort();
|
|
276
|
-
this.#repositoryCwd = this.#cwd;
|
|
277
|
-
this.#gitBranch = null;
|
|
278
|
-
this.#pullRequest = null;
|
|
279
|
-
this.#lastPullRequestProbeAt = null;
|
|
280
|
-
}
|
|
281
|
-
async #refreshRepositoryMetadata() {
|
|
282
|
-
if (this.#repositoryRefreshAbort !== undefined || this.#disposed || this.#ports.disposed())
|
|
283
|
-
return;
|
|
284
|
-
const controller = new AbortController();
|
|
285
|
-
const generation = this.#sessionBindingGeneration;
|
|
286
|
-
this.#repositoryRefreshAbort = controller;
|
|
287
|
-
let associatedContext = null;
|
|
288
|
-
const manager = this.#session?.sessionManager;
|
|
289
|
-
const sessionId = manager?.getSessionId?.();
|
|
290
|
-
const sessionFile = manager?.getSessionFile?.();
|
|
291
|
-
try {
|
|
292
|
-
if (typeof sessionId === "string" && sessionId.length > 0 && typeof sessionFile === "string" && sessionFile.length > 0) {
|
|
293
|
-
try {
|
|
294
|
-
associatedContext = await this.#repositoryContextReader(sessionId, sessionFile, controller.signal);
|
|
295
|
-
}
|
|
296
|
-
catch {
|
|
297
|
-
associatedContext = null;
|
|
298
|
-
}
|
|
299
|
-
}
|
|
300
|
-
const nextCwd = associatedContext?.cwd ?? this.#cwd;
|
|
301
|
-
let nextBranch = associatedContext?.branch ?? null;
|
|
302
|
-
if (associatedContext === null) {
|
|
303
|
-
try {
|
|
304
|
-
nextBranch = await this.#gitBranchReader(nextCwd, controller.signal);
|
|
305
|
-
}
|
|
306
|
-
catch {
|
|
307
|
-
nextBranch = null;
|
|
308
|
-
}
|
|
309
|
-
}
|
|
310
|
-
const metadataChanged = nextCwd !== this.#repositoryCwd || nextBranch !== this.#gitBranch;
|
|
311
|
-
const remoteDue = metadataChanged || this.#lastPullRequestProbeAt === null
|
|
312
|
-
|| Date.now() - this.#lastPullRequestProbeAt >= this.#pullRequestRefreshMs;
|
|
313
|
-
if (remoteDue) {
|
|
314
|
-
let nextPullRequest = null;
|
|
315
|
-
try {
|
|
316
|
-
nextPullRequest = nextBranch === null
|
|
317
|
-
? null
|
|
318
|
-
: await this.#pullRequestProbe(nextCwd, nextBranch, controller.signal);
|
|
319
|
-
}
|
|
320
|
-
catch {
|
|
321
|
-
nextPullRequest = null;
|
|
322
|
-
}
|
|
323
|
-
if (controller.signal.aborted || generation !== this.#sessionBindingGeneration || this.#disposed || this.#ports.disposed())
|
|
324
|
-
return;
|
|
325
|
-
const changed = nextCwd !== this.#repositoryCwd
|
|
326
|
-
|| nextBranch !== this.#gitBranch
|
|
327
|
-
|| !samePullRequest(this.#pullRequest, nextPullRequest);
|
|
328
|
-
this.#repositoryCwd = nextCwd;
|
|
329
|
-
this.#gitBranch = nextBranch;
|
|
330
|
-
this.#pullRequest = nextPullRequest;
|
|
331
|
-
this.#lastPullRequestProbeAt = Date.now();
|
|
332
|
-
if (changed)
|
|
333
|
-
this.#ports.emitView();
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
catch {
|
|
337
|
-
if (!controller.signal.aborted && generation === this.#sessionBindingGeneration && !this.#disposed && !this.#ports.disposed()) {
|
|
338
|
-
const changed = this.#repositoryCwd !== this.#cwd || this.#gitBranch !== null || this.#pullRequest !== null;
|
|
339
|
-
this.#repositoryCwd = this.#cwd;
|
|
340
|
-
this.#gitBranch = null;
|
|
341
|
-
this.#pullRequest = null;
|
|
342
|
-
this.#lastPullRequestProbeAt = Date.now();
|
|
343
|
-
if (changed)
|
|
344
|
-
this.#ports.emitView();
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
finally {
|
|
348
|
-
if (this.#repositoryRefreshAbort === controller)
|
|
349
|
-
this.#repositoryRefreshAbort = undefined;
|
|
350
|
-
}
|
|
351
|
-
if (controller.signal.aborted || generation !== this.#sessionBindingGeneration || this.#disposed || this.#ports.disposed())
|
|
352
|
-
return;
|
|
353
|
-
this.#repositoryRefreshTimer = setTimeout(() => {
|
|
354
|
-
this.#repositoryRefreshTimer = undefined;
|
|
355
|
-
this.#startRepositoryRefresh();
|
|
356
|
-
}, this.#repositoryContextPollMs);
|
|
357
|
-
this.#repositoryRefreshTimer.unref?.();
|
|
358
|
-
}
|
|
359
223
|
#attachCompactionProgress(session) {
|
|
360
224
|
this.#compactionProgress?.dispose();
|
|
361
225
|
this.#compactionProgress = observeCompactionProgress(session, percent => {
|
|
@@ -419,24 +283,3 @@ async function checkDefaultPiPackageUpdates(cwd, agentDir, settingsManager) {
|
|
|
419
283
|
const updates = await packageManager.checkForAvailableUpdates();
|
|
420
284
|
return updates.map(update => update.displayName);
|
|
421
285
|
}
|
|
422
|
-
function samePullRequest(left, right) {
|
|
423
|
-
return left?.number === right?.number && left?.url === right?.url;
|
|
424
|
-
}
|
|
425
|
-
async function readGitBranch(cwd, signal) {
|
|
426
|
-
if (!existsSync(cwd))
|
|
427
|
-
return null;
|
|
428
|
-
try {
|
|
429
|
-
const { stdout } = await execFileAsync("git", ["branch", "--show-current"], {
|
|
430
|
-
cwd,
|
|
431
|
-
windowsHide: true,
|
|
432
|
-
timeout: GIT_BRANCH_TIMEOUT_MS,
|
|
433
|
-
maxBuffer: GIT_BRANCH_MAX_BUFFER_BYTES,
|
|
434
|
-
signal,
|
|
435
|
-
encoding: "utf8",
|
|
436
|
-
});
|
|
437
|
-
return stdout.trim() || null;
|
|
438
|
-
}
|
|
439
|
-
catch {
|
|
440
|
-
return null;
|
|
441
|
-
}
|
|
442
|
-
}
|
|
@@ -1,5 +1,13 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import type { OwnedUiDiagnostics, OwnedUiEditorState, OwnedUiModelInfo, OwnedUiSessionViewModel, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiUsageView } from "../../../contracts/owned-ui/index.js";
|
|
1
|
+
import type { PiEngineRuntime } from "./session-runtime.js";
|
|
2
|
+
import type { OwnedUiDiagnostics, OwnedUiEditorState, OwnedUiModelInfo, OwnedUiSessionViewModel, OwnedUiStatusView, OwnedUiTerminalSurface, OwnedUiThinkingLevel, OwnedUiTranscriptBlock, OwnedUiUsageView } from "../../../contracts/owned-ui/index.js";
|
|
3
|
+
/** Bounded structured notices; acknowledgements never inspect terminal cells or touch Agent work. */
|
|
4
|
+
declare class EngineDiagnostics {
|
|
5
|
+
#private;
|
|
6
|
+
get values(): readonly OwnedUiDiagnostics[];
|
|
7
|
+
get messages(): readonly string[];
|
|
8
|
+
record(severity: OwnedUiDiagnostics["severity"], code: string, message: string, recoverable: boolean): OwnedUiDiagnostics;
|
|
9
|
+
clearCodes(codes: readonly string[]): boolean;
|
|
10
|
+
}
|
|
3
11
|
/**
|
|
4
12
|
* The engine adapter's own view-model state: lifecycle, editor, status, terminal surface, active
|
|
5
13
|
* model, thinking level, the usage cache, diagnostics, and the view revision. Every change that
|
|
@@ -41,3 +49,14 @@ export declare class EngineViewState {
|
|
|
41
49
|
/** Delivery overload ended the run: ready when it can resume, stopped once disposed, otherwise failed. */
|
|
42
50
|
settleOverload(canResume: boolean, disposed: boolean): void;
|
|
43
51
|
}
|
|
52
|
+
/** What the session view is projected from: the adapter's view state, the bound engine, the transcript and the running commands. */
|
|
53
|
+
export interface PiSessionViewSource {
|
|
54
|
+
readonly sessionId: string;
|
|
55
|
+
readonly state: EngineViewState;
|
|
56
|
+
readonly engine: PiEngineRuntime;
|
|
57
|
+
readonly transcript: readonly OwnedUiTranscriptBlock[];
|
|
58
|
+
readonly activeCommandIds: readonly string[];
|
|
59
|
+
}
|
|
60
|
+
/** The owned UI session view model, copied so a published view never aliases adapter state. */
|
|
61
|
+
export declare function projectSessionView({ sessionId, state, engine, transcript, activeCommandIds }: PiSessionViewSource): OwnedUiSessionViewModel;
|
|
62
|
+
export {};
|
|
@@ -1,4 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { finiteNumber, isRecord, readModel, readThinkingLevel } from "./message-values.js";
|
|
2
|
+
/** Bounded structured notices; acknowledgements never inspect terminal cells or touch Agent work. */
|
|
3
|
+
class EngineDiagnostics {
|
|
4
|
+
#values = [];
|
|
5
|
+
#messages = [];
|
|
6
|
+
#sequence = 0;
|
|
7
|
+
get values() { return this.#values; }
|
|
8
|
+
get messages() { return this.#messages; }
|
|
9
|
+
record(severity, code, message, recoverable) {
|
|
10
|
+
const diagnostic = { sequence: this.#sequence++, code, severity, message, recoverable };
|
|
11
|
+
this.#values.push(diagnostic);
|
|
12
|
+
if (this.#values.length > 100)
|
|
13
|
+
this.#values.shift();
|
|
14
|
+
this.#messages = [...this.#messages, message].slice(-8);
|
|
15
|
+
return diagnostic;
|
|
16
|
+
}
|
|
17
|
+
clearCodes(codes) {
|
|
18
|
+
const selected = new Set(codes);
|
|
19
|
+
return this.#remove(diagnostic => selected.has(diagnostic.code));
|
|
20
|
+
}
|
|
21
|
+
#remove(predicate) {
|
|
22
|
+
const removed = new Set();
|
|
23
|
+
for (let index = this.#values.length - 1; index >= 0; index--) {
|
|
24
|
+
const diagnostic = this.#values[index];
|
|
25
|
+
if (predicate(diagnostic)) {
|
|
26
|
+
removed.add(diagnostic.message);
|
|
27
|
+
this.#values.splice(index, 1);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
if (removed.size === 0)
|
|
31
|
+
return false;
|
|
32
|
+
this.#messages = this.#messages.filter(message => !removed.has(message) || this.#values.some(diagnostic => diagnostic.message === message));
|
|
33
|
+
return true;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
2
36
|
const DEFAULT_SURFACE = {
|
|
3
37
|
columns: 100,
|
|
4
38
|
rows: 32,
|
|
@@ -112,3 +146,97 @@ export class EngineViewState {
|
|
|
112
146
|
this.#revision += 1;
|
|
113
147
|
}
|
|
114
148
|
}
|
|
149
|
+
/** Token, cost, cache, and context usage summed from the session's entries for the status footer. */
|
|
150
|
+
function readUsageView(session, runtime, activeModel) {
|
|
151
|
+
let input = 0;
|
|
152
|
+
let output = 0;
|
|
153
|
+
let cacheRead = 0;
|
|
154
|
+
let cacheWrite = 0;
|
|
155
|
+
let cost = 0;
|
|
156
|
+
let latestCacheHitRate = null;
|
|
157
|
+
let latestPrompt = null;
|
|
158
|
+
const entries = session?.sessionManager?.getEntries?.()
|
|
159
|
+
?? (session?.messages ?? []).map(message => ({ type: "message", message }));
|
|
160
|
+
for (const entry of entries) {
|
|
161
|
+
if (!isRecord(entry))
|
|
162
|
+
continue;
|
|
163
|
+
const message = entry.type === "message" && isRecord(entry.message) ? entry.message : undefined;
|
|
164
|
+
const usage = message !== undefined && isRecord(message.usage)
|
|
165
|
+
? message.usage
|
|
166
|
+
: (entry.type === "usage" || entry.type === "branch_summary" || entry.type === "compaction") && isRecord(entry.usage) ? entry.usage : undefined;
|
|
167
|
+
if (usage === undefined)
|
|
168
|
+
continue;
|
|
169
|
+
input += finiteNumber(usage.input);
|
|
170
|
+
output += finiteNumber(usage.output);
|
|
171
|
+
cacheRead += finiteNumber(usage.cacheRead);
|
|
172
|
+
cacheWrite += finiteNumber(usage.cacheWrite);
|
|
173
|
+
cost += isRecord(usage.cost) ? finiteNumber(usage.cost.total) : 0;
|
|
174
|
+
if (message?.role === "assistant") {
|
|
175
|
+
latestPrompt = {
|
|
176
|
+
input: finiteNumber(usage.input),
|
|
177
|
+
cacheRead: finiteNumber(usage.cacheRead),
|
|
178
|
+
cacheWrite: finiteNumber(usage.cacheWrite),
|
|
179
|
+
};
|
|
180
|
+
const promptTokens = latestPrompt.input + latestPrompt.cacheRead + latestPrompt.cacheWrite;
|
|
181
|
+
latestCacheHitRate = promptTokens > 0 ? (latestPrompt.cacheRead / promptTokens) * 100 : null;
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
const context = session?.getContextUsage?.();
|
|
185
|
+
const providerId = activeModel?.providerId;
|
|
186
|
+
const usingSubscription = providerId === "kimi-coding"
|
|
187
|
+
|| (providerId !== undefined && runtime?.services.modelRuntime.isUsingSubscription?.(providerId) === true);
|
|
188
|
+
return {
|
|
189
|
+
input,
|
|
190
|
+
output,
|
|
191
|
+
cacheRead,
|
|
192
|
+
cacheWrite,
|
|
193
|
+
cost,
|
|
194
|
+
latestCacheHitRate,
|
|
195
|
+
latestPrompt,
|
|
196
|
+
contextAvailable: context !== undefined,
|
|
197
|
+
contextTokens: context?.tokens ?? null,
|
|
198
|
+
contextWindow: context?.contextWindow ?? 0,
|
|
199
|
+
contextPercent: context?.percent ?? null,
|
|
200
|
+
usingSubscription,
|
|
201
|
+
autoCompactEnabled: runtime?.services.settingsManager?.getCompactionEnabled?.() ?? true,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
/** The owned UI session view model, copied so a published view never aliases adapter state. */
|
|
205
|
+
export function projectSessionView({ sessionId, state, engine, transcript, activeCommandIds }) {
|
|
206
|
+
const routed = engine.session?.routedModel;
|
|
207
|
+
const routedModel = routed === undefined ? null : readModel(routed.model);
|
|
208
|
+
return {
|
|
209
|
+
contractVersion: 1,
|
|
210
|
+
sessionId,
|
|
211
|
+
revision: state.revision,
|
|
212
|
+
lifecycle: state.lifecycle,
|
|
213
|
+
transcript,
|
|
214
|
+
editor: { ...state.editor, queuedSubmissions: [...state.editor.queuedSubmissions] },
|
|
215
|
+
status: {
|
|
216
|
+
...state.status,
|
|
217
|
+
diagnostics: [...state.status.diagnostics],
|
|
218
|
+
badges: [...state.status.badges],
|
|
219
|
+
usage: state.usage(() => readUsageView(engine.session, engine.runtime, state.activeModel)),
|
|
220
|
+
footer: {
|
|
221
|
+
branch: engine.repository.branch,
|
|
222
|
+
repositoryPath: engine.repository.cwd,
|
|
223
|
+
pullRequest: engine.repository.pullRequest,
|
|
224
|
+
sessionName: engine.session?.sessionManager?.getSessionName() ?? null,
|
|
225
|
+
availableProviderCount: new Set(engine.runtime?.services.modelRuntime.getAvailableSnapshot?.().map(model => model.provider).filter(provider => provider !== undefined) ?? []).size,
|
|
226
|
+
extensionStatuses: [],
|
|
227
|
+
},
|
|
228
|
+
},
|
|
229
|
+
terminal: { ...state.terminal },
|
|
230
|
+
activeModel: state.activeModel === null ? null : { ...state.activeModel },
|
|
231
|
+
routedModel: routedModel === null ? null : {
|
|
232
|
+
model: routedModel,
|
|
233
|
+
...(routed?.thinkingLevel === undefined ? {} : { thinkingLevel: readThinkingLevel(routed.thinkingLevel) }),
|
|
234
|
+
},
|
|
235
|
+
thinkingLevel: state.thinkingLevel,
|
|
236
|
+
activeCommandIds: [...activeCommandIds],
|
|
237
|
+
dialog: null,
|
|
238
|
+
overlay: null,
|
|
239
|
+
customizations: [],
|
|
240
|
+
diagnostics: state.diagnostics.map(diagnostic => ({ ...diagnostic })),
|
|
241
|
+
};
|
|
242
|
+
}
|
|
@@ -52,7 +52,6 @@ export declare class PiWorkflowRunner {
|
|
|
52
52
|
bindClipboardWriter(writer: (text: string) => Promise<boolean>): () => void;
|
|
53
53
|
/** Workflow and tree copying share the active owner's write fence and delivery acknowledgment. */
|
|
54
54
|
copyWorkflowText(text: string): Promise<boolean>;
|
|
55
|
-
abortBashWorkflow(): void;
|
|
56
55
|
executeBashWorkflow(command: string, excludeFromContext: boolean): Promise<PiBashWorkflowResult>;
|
|
57
56
|
reloadBlockedResult(): PiWorkflowResult | null;
|
|
58
57
|
executeWorkflow(request: PiWorkflowRequest): Promise<PiWorkflowResult>;
|