@timurproko/a1 0.2.6-dev.727 → 0.2.6-dev.734
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/clipboard-services.d.ts +19 -0
- package/dist/app/session-shell/clipboard-services.js +7 -0
- package/dist/app/session-shell/exit-notice.d.ts +9 -5
- package/dist/app/session-shell/exit-notice.js +5 -5
- package/dist/app/session-shell/index.d.ts +3 -1
- package/dist/app/session-shell/index.js +1 -0
- package/dist/app/session-shell/paste-preparation-client.d.ts +3 -0
- package/dist/app/session-shell/paste-preparation-client.js +5 -2
- package/dist/app/session-shell/path-chip-presentation.d.ts +10 -3
- package/dist/app/session-shell/path-chip-presentation.js +48 -6
- package/dist/app/session-shell/prompt-chips.js +30 -4
- package/dist/app/session-shell/quit-outro.d.ts +3 -1
- package/dist/app/session-shell/quit-outro.js +23 -8
- package/dist/app/session-shell/response-copy-transport.d.ts +6 -1
- package/dist/app/session-shell/response-copy-transport.js +8 -2
- package/dist/app/session-shell/session-shell-root.d.ts +20 -10
- package/dist/app/session-shell/session-shell-root.js +6 -6
- package/dist/app/session-shell/session-shell.d.ts +19 -21
- package/dist/app/session-shell/session-shell.js +656 -860
- package/dist/composition/owned-ui.d.ts +20 -2
- package/dist/composition/owned-ui.js +66 -35
- package/dist/composition/session-info-reference.d.ts +2 -2
- package/dist/composition/session-info-reference.js +2 -2
- package/dist/contracts/agent-engine/capability-ports.d.ts +1 -85
- package/dist/contracts/agent-engine/capability-ports.js +1 -35
- package/dist/contracts/agent-engine/index.d.ts +1 -7
- package/dist/contracts/agent-engine/index.js +0 -4
- package/dist/contracts/owned-ui/index.d.ts +5 -1
- package/dist/contracts/owned-ui/index.js +1 -0
- package/dist/contracts/owned-ui/model.d.ts +6 -0
- package/dist/contracts/owned-ui/session-backend.d.ts +119 -0
- package/dist/contracts/owned-ui/session-presenters.d.ts +55 -0
- package/dist/contracts/owned-ui/session-presenters.js +1 -0
- package/dist/contracts/owned-ui/session-workflows.d.ts +342 -0
- package/dist/contracts/owned-ui/session-workflows.js +30 -0
- package/dist/features/owned-ui/settings-app.js +35 -15
- package/dist/foundation/release/bootstrap.js +1 -2
- package/dist/foundation/release/release-gc.js +1 -1
- package/dist/foundation/release/update.js +0 -4
- package/dist/foundation/storage/control-store.js +0 -12
- package/dist/integrations/pi/components/components.js +0 -16
- package/dist/integrations/pi/components/index.d.ts +3 -3
- package/dist/integrations/pi/components/index.js +2 -2
- package/dist/integrations/pi/components/models-dialog.js +1 -30
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +11 -9
- package/dist/integrations/pi/components/shell-extension-ui.d.ts +3 -3
- package/dist/integrations/pi/components/shell-extension-ui.js +6 -2
- package/dist/integrations/pi/components/shell-presenters-transcript.js +4 -4
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +21 -1
- package/dist/integrations/pi/components/shell-shared-facade.js +18 -2
- package/dist/integrations/pi/components/upstream/theme/theme.d.ts +5 -1
- package/dist/integrations/pi/components/upstream/theme/theme.js +20 -2
- package/dist/integrations/pi/engine/adapter.d.ts +44 -24
- package/dist/integrations/pi/engine/adapter.js +130 -22
- package/dist/integrations/pi/engine/command-dispatch.d.ts +2 -5
- package/dist/integrations/pi/engine/extension-ui-binding.d.ts +2 -11
- package/dist/integrations/pi/engine/host-ports.d.ts +20 -0
- package/dist/integrations/pi/engine/host-ports.js +13 -0
- package/dist/integrations/pi/engine/host.d.ts +70 -0
- package/dist/integrations/pi/engine/host.js +147 -0
- package/dist/integrations/pi/engine/index.d.ts +8 -4
- package/dist/integrations/pi/engine/index.js +3 -1
- package/dist/integrations/pi/engine/resource-catalog.d.ts +4 -23
- package/dist/integrations/pi/engine/runtime-integration.d.ts +8 -2
- package/dist/integrations/pi/engine/runtime-integration.js +12 -7
- package/dist/integrations/pi/engine/session-integration.d.ts +3 -8
- package/dist/integrations/pi/engine/session-integration.js +0 -49
- package/dist/integrations/pi/engine/session-runtime.d.ts +18 -3
- package/dist/integrations/pi/engine/session-runtime.js +18 -7
- package/dist/integrations/pi/engine/settings-bridge.d.ts +2 -2
- package/dist/integrations/pi/engine/settings-bridge.js +0 -2
- package/dist/integrations/pi/engine/settings-port.d.ts +2 -0
- package/dist/integrations/pi/engine/settings-port.js +3 -5
- package/dist/integrations/pi/engine/workflows.d.ts +33 -260
- package/dist/integrations/pi/engine/workflows.js +6 -28
- package/dist/integrations/pi/session-presenters/index.d.ts +2 -0
- package/dist/integrations/pi/session-presenters/index.js +1 -0
- package/dist/integrations/pi/session-presenters/presenters.d.ts +16 -0
- package/dist/integrations/pi/session-presenters/presenters.js +341 -0
- package/dist/integrations/pi/tui-runtime/adapter.js +0 -2
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +7 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +66 -1
- package/dist/integrations/pi/tui-runtime/index.d.ts +1 -1
- package/dist/integrations/pi/tui-runtime/index.js +1 -1
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/ui/settings/declarations.d.ts +13 -1
- package/dist/ui/settings/declarations.js +12 -1
- package/dist/ui/settings/migrations.js +7 -0
- package/docs/architecture/boundaries.md +9 -1
- package/docs/architecture/project-structure.md +3 -2
- package/package.json +1 -1
- package/dist/contracts/agent-engine/model.d.ts +0 -78
- package/dist/contracts/agent-engine/model.js +0 -1
- package/dist/contracts/agent-engine/ports.d.ts +0 -18
- package/dist/contracts/agent-engine/serialization.d.ts +0 -7
- package/dist/contracts/agent-engine/serialization.js +0 -58
- package/dist/contracts/agent-engine/validation.d.ts +0 -5
- package/dist/contracts/agent-engine/validation.js +0 -128
- package/dist/integrations/pi/components/upstream/theme/system-theme.d.ts +0 -61
- package/dist/integrations/pi/components/upstream/theme/system-theme.js +0 -709
- /package/dist/contracts/{agent-engine/ports.js → owned-ui/session-backend.js} +0 -0
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { HelperPool } from "./helper-pool.js";
|
|
2
|
+
/**
|
|
3
|
+
* Process-wide clipboard helper spares. Composition creates one and every session shell borrows it, so N
|
|
4
|
+
* sessions keep at most one spare paste helper and one spare copy helper instead of 2N. Shells warm the
|
|
5
|
+
* pools after their first frame; only the creator disposes them.
|
|
6
|
+
*/
|
|
7
|
+
export interface OwnedUiClipboardServices {
|
|
8
|
+
readonly paste: HelperPool;
|
|
9
|
+
readonly copy: HelperPool;
|
|
10
|
+
dispose(): void;
|
|
11
|
+
}
|
|
12
|
+
export interface OwnedUiClipboardServicesOptions {
|
|
13
|
+
/** Package/fault-test seams for the forked helpers' entries. */
|
|
14
|
+
readonly pasteHelper?: URL;
|
|
15
|
+
readonly copyHelper?: URL;
|
|
16
|
+
/** Idle bound for both spares; production keeps the default. */
|
|
17
|
+
readonly spareIdleMs?: number;
|
|
18
|
+
}
|
|
19
|
+
export declare function createOwnedUiClipboardServices(options?: OwnedUiClipboardServicesOptions): OwnedUiClipboardServices;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { createPasteHelperPool } from "./paste-executor.js";
|
|
2
|
+
import { createCopyHelperPool } from "./response-copy-transport.js";
|
|
3
|
+
export function createOwnedUiClipboardServices(options = {}) {
|
|
4
|
+
const paste = createPasteHelperPool(options.pasteHelper, options.spareIdleMs);
|
|
5
|
+
const copy = createCopyHelperPool(options.copyHelper, options.spareIdleMs);
|
|
6
|
+
return { paste, copy, dispose: () => { paste.dispose(); copy.dispose(); } };
|
|
7
|
+
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { type SessionResumeCommandMetadata } from "./session-shell.js";
|
|
2
2
|
export interface ExitNoticeSource {
|
|
3
|
-
readonly
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
3
|
+
readonly identity: {
|
|
4
|
+
readonly sessionGeneration: number;
|
|
5
|
+
currentSessionResumeMetadata(): SessionResumeCommandMetadata | null;
|
|
6
|
+
};
|
|
7
|
+
readonly session: {
|
|
8
|
+
onEvent(listener: (event: {
|
|
9
|
+
readonly type: string;
|
|
10
|
+
}) => void): () => void;
|
|
11
|
+
};
|
|
8
12
|
}
|
|
9
13
|
export interface ArmedExitNotice {
|
|
10
14
|
clear(): void;
|
|
@@ -17,12 +17,12 @@ export function uncleanExitNoticeLines(resume) {
|
|
|
17
17
|
export function armExitNotice(source, path) {
|
|
18
18
|
let current = null;
|
|
19
19
|
let cleared = false;
|
|
20
|
-
let generation = source.sessionGeneration;
|
|
20
|
+
let generation = source.identity.sessionGeneration;
|
|
21
21
|
const write = () => {
|
|
22
22
|
if (cleared)
|
|
23
23
|
return;
|
|
24
24
|
// Protocol: plain text only; the guardian strips control characters, so styling would be lost.
|
|
25
|
-
const text = `${uncleanExitNoticeLines(source.currentSessionResumeMetadata()).join("\n")}\n`;
|
|
25
|
+
const text = `${uncleanExitNoticeLines(source.identity.currentSessionResumeMetadata()).join("\n")}\n`;
|
|
26
26
|
if (text === current)
|
|
27
27
|
return;
|
|
28
28
|
try {
|
|
@@ -35,13 +35,13 @@ export function armExitNotice(source, path) {
|
|
|
35
35
|
catch { }
|
|
36
36
|
};
|
|
37
37
|
write();
|
|
38
|
-
const unsubscribe = source.onEvent(event => {
|
|
38
|
+
const unsubscribe = source.session.onEvent(event => {
|
|
39
39
|
// Rationale: a session is persisted by its first response and replaced by /new or /resume;
|
|
40
40
|
// these events cover both without touching the per-chunk stream.
|
|
41
|
-
const replaced = source.sessionGeneration !== generation;
|
|
41
|
+
const replaced = source.identity.sessionGeneration !== generation;
|
|
42
42
|
if (!replaced && event.type !== "session-lifecycle" && event.type !== "assistant-message-completed")
|
|
43
43
|
return;
|
|
44
|
-
generation = source.sessionGeneration;
|
|
44
|
+
generation = source.identity.sessionGeneration;
|
|
45
45
|
write();
|
|
46
46
|
});
|
|
47
47
|
return {
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
export { ClipboardDiagnosticCapture } from "./clipboard-diagnostics.js";
|
|
2
|
+
export { createOwnedUiClipboardServices } from "./clipboard-services.js";
|
|
3
|
+
export type { OwnedUiClipboardServices, OwnedUiClipboardServicesOptions } from "./clipboard-services.js";
|
|
2
4
|
export { ContextualPromptSuggestionController, samePromptSuggestionIdentity } from "./prompt-suggestion-controller.js";
|
|
3
5
|
export type { ContextualPromptSuggestionControllerOptions, ContextualPromptSuggestionSurface } from "./prompt-suggestion-controller.js";
|
|
4
6
|
export { OwnedUiSessionShell, OwnedUiSessionShellRoot, formatSessionResumeCommand, quoteCommandArgument } from "./session-shell.js";
|
|
5
|
-
export type { OwnedUiSessionShellOptions, OwnedUiShellDiagnosticOptions, OwnedUiShellEngineOptions, OwnedUiShellHistoryOptions, OwnedUiShellPresentationOptions, OwnedUiShellPromptImagesOptions, OwnedUiShellSkillsOptions, OwnedUiShellSuggestionOptions, SessionResumeCommandMetadata, } from "./session-shell.js";
|
|
7
|
+
export type { OwnedUiSessionShellOptions, OwnedUiShellDiagnosticOptions, OwnedUiShellEngineOptions, OwnedUiShellHistoryOptions, OwnedUiShellPresentationOptions, OwnedUiShellPromptImagesOptions, OwnedUiShellSharedServices, OwnedUiShellSkillsOptions, OwnedUiShellSuggestionOptions, SessionResumeCommandMetadata, } from "./session-shell.js";
|
|
6
8
|
export { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer } from "./stream-presentation-coalescer.js";
|
|
7
9
|
export type { StreamPresentationScheduler } from "./stream-presentation-coalescer.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { ClipboardDiagnosticCapture } from "./clipboard-diagnostics.js";
|
|
2
|
+
export { createOwnedUiClipboardServices } from "./clipboard-services.js";
|
|
2
3
|
export { ContextualPromptSuggestionController, samePromptSuggestionIdentity } from "./prompt-suggestion-controller.js";
|
|
3
4
|
export { OwnedUiSessionShell, OwnedUiSessionShellRoot, formatSessionResumeCommand, quoteCommandArgument } from "./session-shell.js";
|
|
4
5
|
export { STREAM_PRESENTATION_INTERVAL_MS, StreamPresentationCoalescer } from "./stream-presentation-coalescer.js";
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { startPasteExecutor } from "./paste-executor.js";
|
|
2
|
+
import type { HelperPool } from "./helper-pool.js";
|
|
2
3
|
import { type PasteEvent, type PasteSource, type PreparedPaste } from "./paste-protocol.js";
|
|
3
4
|
export interface PreparedPasteJob<T> {
|
|
4
5
|
readonly result: Promise<T>;
|
|
@@ -16,6 +17,8 @@ export interface PastePreparationClientOptions {
|
|
|
16
17
|
readonly helper?: URL;
|
|
17
18
|
/** Idle bound for the spare helper; production keeps the default. */
|
|
18
19
|
readonly spareIdleMs?: number;
|
|
20
|
+
/** Process-wide spare pool shared across sessions; the client warms it but never disposes it. */
|
|
21
|
+
readonly pool?: HelperPool;
|
|
19
22
|
}
|
|
20
23
|
/** Keeps eight distinct paste transactions alive through insertion; canceled executors retain capacity until fenced. */
|
|
21
24
|
export declare class PastePreparationClient {
|
|
@@ -8,13 +8,15 @@ export class PastePreparationClient {
|
|
|
8
8
|
#execute;
|
|
9
9
|
#helper;
|
|
10
10
|
#pool;
|
|
11
|
+
#ownsPool;
|
|
11
12
|
#sequence = 0;
|
|
12
13
|
#disposed = false;
|
|
13
14
|
constructor(options = {}) {
|
|
14
15
|
this.#onEvent = options.onEvent;
|
|
15
16
|
this.#execute = options.execute ?? startPasteExecutor;
|
|
16
17
|
this.#helper = options.helper;
|
|
17
|
-
this.#pool = options.execute === undefined ? createPasteHelperPool(options.helper, options.spareIdleMs) : undefined;
|
|
18
|
+
this.#pool = options.execute === undefined ? options.pool ?? createPasteHelperPool(options.helper, options.spareIdleMs) : undefined;
|
|
19
|
+
this.#ownsPool = options.pool === undefined;
|
|
18
20
|
}
|
|
19
21
|
/** Forks the spare helper now so the first paste takes a live child; later pastes rewarm it themselves. */
|
|
20
22
|
warm() { this.#pool?.warm(); }
|
|
@@ -160,7 +162,8 @@ export class PastePreparationClient {
|
|
|
160
162
|
async dispose() {
|
|
161
163
|
this.#disposed = true;
|
|
162
164
|
this.reset();
|
|
163
|
-
this.#
|
|
165
|
+
if (this.#ownsPool)
|
|
166
|
+
this.#pool?.dispose();
|
|
164
167
|
let timer;
|
|
165
168
|
await Promise.race([Promise.all([...this.#active].map(active => active.stopped)),
|
|
166
169
|
new Promise(resolve => { timer = setTimeout(resolve, PASTE_STOP_MS); timer.unref(); })]);
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import type { ClipboardPath, PreparedPasteText } from "./paste-types.js";
|
|
2
2
|
export declare const PATH_CHIP_PRESENTATION_UNITS = 4096;
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
/** Normalizes a path for host-filesystem identity comparisons. */
|
|
4
|
+
export declare function normalizedPathIdentity(fullPath: string): string;
|
|
5
|
+
/** Yields labels from the basename through the normalized rooted path, shortest first. */
|
|
6
|
+
export declare function pathChipLabelCandidates(fullPath: string): Iterable<string>;
|
|
7
|
+
/** Formats one path label with the established folder/file/image-file icon. */
|
|
8
|
+
export declare function pathChipTag(item: ClipboardPath, label?: string): string;
|
|
9
|
+
/** Yields complete deterministic tags lazily for path collision adoption. */
|
|
10
|
+
export declare function pathChipTagCandidates(item: ClipboardPath): Iterable<string>;
|
|
11
|
+
/** Returns the conservative UTF-16 presentation cost for one path occurrence. */
|
|
12
|
+
export declare function pathChipPresentationUnits(item: ClipboardPath): number;
|
|
6
13
|
/** Run in the isolated preparer: compact before path arrays become an oversized editor presentation. */
|
|
7
14
|
export declare function preparePathPresentation(paths: readonly ClipboardPath[]): PreparedPasteText;
|
|
@@ -1,19 +1,52 @@
|
|
|
1
1
|
import path from "node:path";
|
|
2
2
|
export const PATH_CHIP_PRESENTATION_UNITS = 4096;
|
|
3
|
-
// Invariant: a collision suffix containing any safe-integer index fits this per-occurrence reserve.
|
|
4
|
-
export const PATH_CHIP_SUFFIX_UNITS = 20;
|
|
5
3
|
const IMAGE_EXTENSION = /\.(?:jpe?g|png|webp|gif|bmp|tiff?)$/iu;
|
|
6
|
-
/**
|
|
7
|
-
export function
|
|
8
|
-
const
|
|
4
|
+
/** Normalizes a path for host-filesystem identity comparisons. */
|
|
5
|
+
export function normalizedPathIdentity(fullPath) {
|
|
6
|
+
const normalized = path.normalize(fullPath.trim());
|
|
7
|
+
return process.platform === "win32" ? normalized.toLowerCase() : normalized;
|
|
8
|
+
}
|
|
9
|
+
/** Yields labels from the basename through the normalized rooted path, shortest first. */
|
|
10
|
+
export function* pathChipLabelCandidates(fullPath) {
|
|
11
|
+
const normalized = path.normalize(fullPath.trim());
|
|
12
|
+
const parsed = path.parse(normalized);
|
|
13
|
+
const relative = normalized.slice(parsed.root.length);
|
|
14
|
+
const segments = relative.split(path.sep).filter(segment => segment.length > 0);
|
|
15
|
+
let previous = "";
|
|
16
|
+
for (let depth = 1; depth <= segments.length; depth++) {
|
|
17
|
+
previous = segments.slice(-depth).join("/");
|
|
18
|
+
yield previous;
|
|
19
|
+
}
|
|
20
|
+
const rooted = displayPath(normalized);
|
|
21
|
+
if (segments.length === 0) {
|
|
22
|
+
const root = displayPath(parsed.root).replace(/\/$/u, "");
|
|
23
|
+
if (root.length > 0) {
|
|
24
|
+
previous = root;
|
|
25
|
+
yield root;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
if (rooted.length > 0 && rooted !== previous)
|
|
29
|
+
yield rooted;
|
|
30
|
+
}
|
|
31
|
+
/** Formats one path label with the established folder/file/image-file icon. */
|
|
32
|
+
export function pathChipTag(item, label = basePathLabel(item.fullPath)) {
|
|
9
33
|
const icon = item.kind === "folder" ? "📁" : IMAGE_EXTENSION.test(item.fullPath) ? "🖼 " : "📄";
|
|
10
34
|
return `[${icon} ${label}]`;
|
|
11
35
|
}
|
|
36
|
+
/** Yields complete deterministic tags lazily for path collision adoption. */
|
|
37
|
+
export function* pathChipTagCandidates(item) {
|
|
38
|
+
for (const label of pathChipLabelCandidates(item.fullPath))
|
|
39
|
+
yield pathChipTag(item, label);
|
|
40
|
+
}
|
|
41
|
+
/** Returns the conservative UTF-16 presentation cost for one path occurrence. */
|
|
42
|
+
export function pathChipPresentationUnits(item) {
|
|
43
|
+
return pathChipTag(item, displayPath(path.normalize(item.fullPath.trim()))).length;
|
|
44
|
+
}
|
|
12
45
|
/** Run in the isolated preparer: compact before path arrays become an oversized editor presentation. */
|
|
13
46
|
export function preparePathPresentation(paths) {
|
|
14
47
|
let units = 0;
|
|
15
48
|
for (const item of paths) {
|
|
16
|
-
units +=
|
|
49
|
+
units += pathChipPresentationUnits(item);
|
|
17
50
|
if (units > PATH_CHIP_PRESENTATION_UNITS) {
|
|
18
51
|
// Compatibility: individual adjacent chips expand without inserted separators or text re-normalization.
|
|
19
52
|
const text = paths.map(value => value.fullPath).join("");
|
|
@@ -22,3 +55,12 @@ export function preparePathPresentation(paths) {
|
|
|
22
55
|
}
|
|
23
56
|
return { kind: "paths", paths };
|
|
24
57
|
}
|
|
58
|
+
function basePathLabel(fullPath) {
|
|
59
|
+
const normalized = path.normalize(fullPath.trim());
|
|
60
|
+
return path.basename(normalized)
|
|
61
|
+
|| displayPath(path.parse(normalized).root).replace(/\/$/u, "")
|
|
62
|
+
|| displayPath(normalized);
|
|
63
|
+
}
|
|
64
|
+
function displayPath(value) {
|
|
65
|
+
return path.sep === "\\" ? value.replaceAll("\\", "/") : value;
|
|
66
|
+
}
|
|
@@ -1,10 +1,9 @@
|
|
|
1
1
|
import { randomBytes } from "node:crypto";
|
|
2
|
-
import path from "node:path";
|
|
3
2
|
import { canonicalizeClipboardImage } from "./clipboard-image.js";
|
|
4
3
|
import { assertImageEncodedSize, assertPromptImages, canonicalPromptChipMatches, DEFAULT_PROMPT_IMAGE_LIMIT, ImageAttachmentError, replaceCanonicalPromptChips, } from "../../contracts/owned-ui/index.js";
|
|
5
4
|
import { ImagePreparationClient } from "./image-preparation-client.js";
|
|
6
5
|
import { preparePasteText } from "./paste-text-preparation.js";
|
|
7
|
-
import {
|
|
6
|
+
import { normalizedPathIdentity, pathChipTagCandidates } from "./path-chip-presentation.js";
|
|
8
7
|
import { PastePreparationClient } from "./paste-preparation-client.js";
|
|
9
8
|
const URL_SUBSTRING_PATTERN = /https?:\/\/[^\s\u0000-\u001f\u007f\]]+/giu;
|
|
10
9
|
const IMAGE_CHIP_IDENTIFIER_PATTERN = /^\[📷 screenshot-([a-f0-9]+)(?:-resized)?\]$/u;
|
|
@@ -23,6 +22,7 @@ function referencesPasteMarker(text, entry) {
|
|
|
23
22
|
/** Owns semantic chips and bounded pending paste references; cancels background work on reset or disposal. */
|
|
24
23
|
export class PromptChipStore {
|
|
25
24
|
#chips = new Map();
|
|
25
|
+
#pathTags = new Map();
|
|
26
26
|
// Invariant: clearing the editor never recycles a recoverable text chip's identity.
|
|
27
27
|
#textCounter = 0;
|
|
28
28
|
#pending = new Map();
|
|
@@ -199,6 +199,7 @@ export class PromptChipStore {
|
|
|
199
199
|
async dispose() {
|
|
200
200
|
await Promise.all([this.#preparation.dispose(), this.#isolated?.dispose(), ...this.#stopping]);
|
|
201
201
|
this.#chips.clear();
|
|
202
|
+
this.#pathTags.clear();
|
|
202
203
|
this.#pending.clear();
|
|
203
204
|
this.#countRejectedImages.clear();
|
|
204
205
|
this.#provisionalOwners.clear();
|
|
@@ -269,7 +270,26 @@ export class PromptChipStore {
|
|
|
269
270
|
this.#claimChip(tag, owner, true);
|
|
270
271
|
return tag;
|
|
271
272
|
}
|
|
272
|
-
return paste.paths.map(item => this.#
|
|
273
|
+
return paste.paths.map(item => this.#recordPath(item, owner)).join("");
|
|
274
|
+
}
|
|
275
|
+
#recordPath(item, owner) {
|
|
276
|
+
const key = pathChipKey(item);
|
|
277
|
+
const establishedTag = this.#pathTags.get(key);
|
|
278
|
+
if (establishedTag !== undefined && this.#chips.has(establishedTag)) {
|
|
279
|
+
this.#claimChip(establishedTag, owner, false);
|
|
280
|
+
return establishedTag;
|
|
281
|
+
}
|
|
282
|
+
for (const tag of pathChipTagCandidates(item)) {
|
|
283
|
+
const chip = { kind: item.kind, tag, path: item.fullPath };
|
|
284
|
+
const existing = this.#chips.get(tag);
|
|
285
|
+
if (existing !== undefined && !sameChipValue(existing, chip))
|
|
286
|
+
continue;
|
|
287
|
+
this.#chips.set(tag, chip);
|
|
288
|
+
this.#pathTags.set(key, tag);
|
|
289
|
+
this.#claimChip(tag, owner, existing === undefined);
|
|
290
|
+
return tag;
|
|
291
|
+
}
|
|
292
|
+
throw new Error("Path chip labels could not distinguish normalized paths");
|
|
273
293
|
}
|
|
274
294
|
/** Hide provisional clipboard identities until the read identifies an actual image. */
|
|
275
295
|
hiddenRanges(line) {
|
|
@@ -501,7 +521,10 @@ export class PromptChipStore {
|
|
|
501
521
|
owners.delete(owner);
|
|
502
522
|
if (owners.size === 0) {
|
|
503
523
|
this.#provisionalOwners.delete(tag);
|
|
524
|
+
const chip = this.#chips.get(tag);
|
|
504
525
|
this.#chips.delete(tag);
|
|
526
|
+
if (chip?.kind === "file" || chip?.kind === "folder")
|
|
527
|
+
this.#pathTags.delete(pathChipKey(chip));
|
|
505
528
|
}
|
|
506
529
|
}
|
|
507
530
|
}
|
|
@@ -522,13 +545,16 @@ export class PromptChipStore {
|
|
|
522
545
|
return uniqueTag;
|
|
523
546
|
}
|
|
524
547
|
}
|
|
548
|
+
function pathChipKey(item) {
|
|
549
|
+
return `${item.kind}\0${normalizedPathIdentity("fullPath" in item ? item.fullPath : item.path)}`;
|
|
550
|
+
}
|
|
525
551
|
function sameChipValue(left, right) {
|
|
526
552
|
if (left.kind !== right.kind)
|
|
527
553
|
return false;
|
|
528
554
|
if (left.kind === "url" && right.kind === "url")
|
|
529
555
|
return left.url === right.url;
|
|
530
556
|
if ((left.kind === "file" || left.kind === "folder") && (right.kind === "file" || right.kind === "folder")) {
|
|
531
|
-
return
|
|
557
|
+
return normalizedPathIdentity(left.path) === normalizedPathIdentity(right.path);
|
|
532
558
|
}
|
|
533
559
|
if (left.kind === "image" && right.kind === "image")
|
|
534
560
|
return left.image.data === right.image.data;
|
|
@@ -15,6 +15,8 @@ export interface QuitOutroPlayback {
|
|
|
15
15
|
sleep?(ms: number): Promise<void>;
|
|
16
16
|
/** Plan seed; defaults to a time- and geometry-derived value. */
|
|
17
17
|
readonly seed?: number;
|
|
18
|
+
/** Active bare-A1 canvas; omitted preserves transparent playback bytes. */
|
|
19
|
+
readonly canvasBackgroundAnsi?: string;
|
|
18
20
|
}
|
|
19
21
|
export declare const QUIT_OUTRO_MIN_MS = 300;
|
|
20
22
|
export declare const QUIT_OUTRO_MAX_MS = 2000;
|
|
@@ -29,7 +31,7 @@ export declare function clampQuitOutroDuration(durationMs: number): number;
|
|
|
29
31
|
*/
|
|
30
32
|
export declare function captureQuitOutroFrame(presented: readonly string[], columns: number, rows: number): QuitOutroFrame | null;
|
|
31
33
|
/** The clear-and-repaint block that seeds the animation surface with the captured frame. */
|
|
32
|
-
export declare function createQuitOutroSurfaceFrame(frame: QuitOutroFrame): string;
|
|
34
|
+
export declare function createQuitOutroSurfaceFrame(frame: QuitOutroFrame, canvasBackgroundAnsi?: string): string;
|
|
33
35
|
/**
|
|
34
36
|
* Plays the effect over the frame. Resolves true when the plan was played to
|
|
35
37
|
* completion or abandoned at its guard, false when there was nothing to play.
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
* terminal cannot delay restoration past the configured clamp.
|
|
7
7
|
*/
|
|
8
8
|
import { displayWidth, truncateToWidth } from "../../ui/components/index.js";
|
|
9
|
+
import { rebaseTerminalDefaultBackground } from "../../integrations/pi/tui-runtime/index.js";
|
|
9
10
|
import { createQuitOutroPlan } from "./quit-outro-effects.js";
|
|
10
11
|
export const QUIT_OUTRO_MIN_MS = 300;
|
|
11
12
|
export const QUIT_OUTRO_MAX_MS = 2000;
|
|
@@ -44,14 +45,25 @@ export function captureQuitOutroFrame(presented, columns, rows) {
|
|
|
44
45
|
return { lines, columns: width, rows: height, rowWidths };
|
|
45
46
|
}
|
|
46
47
|
/** The clear-and-repaint block that seeds the animation surface with the captured frame. */
|
|
47
|
-
export function createQuitOutroSurfaceFrame(frame) {
|
|
48
|
-
|
|
48
|
+
export function createQuitOutroSurfaceFrame(frame, canvasBackgroundAnsi) {
|
|
49
|
+
if (canvasBackgroundAnsi === undefined) {
|
|
50
|
+
let output = `${SYNC_BEGIN}${HIDE_CURSOR}${CLEAR_SCREEN}${HOME}${RESET}`;
|
|
51
|
+
for (let row = 0; row < frame.rows; row++) {
|
|
52
|
+
const line = frame.lines[row] ?? "";
|
|
53
|
+
if (frame.rowWidths[row] > 0)
|
|
54
|
+
output += `${cursorAt(row, 0)}${line}${RESET}`;
|
|
55
|
+
}
|
|
56
|
+
return `${output}${SYNC_END}`;
|
|
57
|
+
}
|
|
58
|
+
let output = `${SYNC_BEGIN}${HIDE_CURSOR}${RESET}${canvasBackgroundAnsi}${CLEAR_SCREEN}${HOME}`;
|
|
49
59
|
for (let row = 0; row < frame.rows; row++) {
|
|
50
60
|
const line = frame.lines[row] ?? "";
|
|
51
|
-
if (frame.rowWidths[row] > 0)
|
|
52
|
-
output += `${cursorAt(row, 0)}${
|
|
61
|
+
if (frame.rowWidths[row] > 0) {
|
|
62
|
+
output += `${cursorAt(row, 0)}${canvasBackgroundAnsi}`
|
|
63
|
+
+ `${rebaseTerminalDefaultBackground(line, canvasBackgroundAnsi)}${RESET}${canvasBackgroundAnsi}`;
|
|
64
|
+
}
|
|
53
65
|
}
|
|
54
|
-
return `${output}${SYNC_END}`;
|
|
66
|
+
return `${output}${RESET}${SYNC_END}`;
|
|
55
67
|
}
|
|
56
68
|
/**
|
|
57
69
|
* Plays the effect over the frame. Resolves true when the plan was played to
|
|
@@ -69,20 +81,23 @@ export async function playQuitOutro(frame, effect, durationMs, playback) {
|
|
|
69
81
|
let sparkleIndex = 0;
|
|
70
82
|
let clearIndex = 0;
|
|
71
83
|
let ticks = 0;
|
|
72
|
-
playback.
|
|
84
|
+
const canvas = playback.canvasBackgroundAnsi;
|
|
85
|
+
playback.write(createQuitOutroSurfaceFrame(frame, canvas));
|
|
73
86
|
const startedAt = now();
|
|
74
87
|
for (;;) {
|
|
75
88
|
ticks += 1;
|
|
76
89
|
const elapsed = now() - startedAt;
|
|
77
90
|
const progress = Math.min(1, elapsed / duration);
|
|
78
|
-
let output = `${SYNC_BEGIN}${RESET}`;
|
|
91
|
+
let output = canvas === undefined ? `${SYNC_BEGIN}${RESET}` : `${SYNC_BEGIN}${RESET}${canvas}`;
|
|
79
92
|
while (sparkleIndex < plan.sparkles.length && plan.sparkles[sparkleIndex].start <= progress) {
|
|
80
93
|
const cell = plan.sparkles[sparkleIndex++];
|
|
81
94
|
output += `${cursorAt(cell.row, cell.col)}${cell.color}${cell.glyph}`;
|
|
82
95
|
}
|
|
83
96
|
while (clearIndex < plan.clears.length && plan.clears[clearIndex].end <= progress) {
|
|
84
97
|
const cell = plan.clears[clearIndex++];
|
|
85
|
-
output +=
|
|
98
|
+
output += canvas === undefined
|
|
99
|
+
? `${cursorAt(cell.row, cell.col)}${RESET} `
|
|
100
|
+
: `${cursorAt(cell.row, cell.col)}${RESET}${canvas} `;
|
|
86
101
|
}
|
|
87
102
|
const finished = clearIndex >= plan.clears.length || progress >= 1
|
|
88
103
|
|| elapsed > duration + QUIT_OUTRO_GUARD_MS || ticks >= QUIT_OUTRO_MAX_TICKS;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { HelperPool } from "./helper-pool.js";
|
|
1
2
|
import type { SelectionCopySnapshot } from "../../ui/components/selection-copy.js";
|
|
2
3
|
import { type CopyResult } from "./response-copy-protocol.js";
|
|
3
4
|
export interface ResponseCopyJob {
|
|
@@ -8,7 +9,7 @@ export interface ResponseCopyJob {
|
|
|
8
9
|
}
|
|
9
10
|
export type CopyPhaseObserver = (phase: "extracted" | "encoded" | "submitting", bytes: number, transport: "native" | "terminal" | "injected") => void;
|
|
10
11
|
export type ResponseCopyExecutor = (snapshot: SelectionCopySnapshot, phase: CopyPhaseObserver) => ResponseCopyJob;
|
|
11
|
-
/** The production executor also
|
|
12
|
+
/** The production executor also holds a spare helper; the owner warms it at start and disposes it at shutdown unless the pool is shared. */
|
|
12
13
|
export interface OwnedResponseCopyExecutor extends ResponseCopyExecutor {
|
|
13
14
|
warm(): void;
|
|
14
15
|
dispose(): void;
|
|
@@ -36,4 +37,8 @@ export declare function createResponseCopyExecutor(options?: {
|
|
|
36
37
|
readonly helper?: URL;
|
|
37
38
|
/** Idle bound for the spare helper; production keeps the default. */
|
|
38
39
|
readonly spareIdleMs?: number;
|
|
40
|
+
/** Process-wide spare pool shared across sessions; the executor warms it but never disposes it. */
|
|
41
|
+
readonly pool?: HelperPool;
|
|
39
42
|
}): OwnedResponseCopyExecutor;
|
|
43
|
+
/** A spare-of-one pool of copy helpers; `createResponseCopyExecutor` takes its child and warms the next one after each copy. */
|
|
44
|
+
export declare function createCopyHelperPool(helper?: URL, idleMs?: number): HelperPool;
|
|
@@ -23,7 +23,8 @@ export function hasAsyncClipboardOutput(platform = process.platform, stdout = pr
|
|
|
23
23
|
}
|
|
24
24
|
/** Isolates preparation and native clipboard access; only the owner may submit terminal controls. */
|
|
25
25
|
export function createResponseCopyExecutor(options = {}) {
|
|
26
|
-
const pool =
|
|
26
|
+
const pool = options.pool ?? createCopyHelperPool(options.helper, options.spareIdleMs);
|
|
27
|
+
const ownsPool = options.pool === undefined;
|
|
27
28
|
const execute = (snapshot, phase) => {
|
|
28
29
|
const controller = new AbortController();
|
|
29
30
|
let active;
|
|
@@ -70,10 +71,15 @@ export function createResponseCopyExecutor(options = {}) {
|
|
|
70
71
|
// Rationale: `Object.assign` would copy the getter's value once; the accessor must read the pool each time.
|
|
71
72
|
return Object.defineProperties(execute, {
|
|
72
73
|
warm: { value: () => pool.warm() },
|
|
73
|
-
dispose: { value: () =>
|
|
74
|
+
dispose: { value: () => { if (ownsPool)
|
|
75
|
+
pool.dispose(); } },
|
|
74
76
|
warmed: { get: () => pool.warmed },
|
|
75
77
|
});
|
|
76
78
|
}
|
|
79
|
+
/** A spare-of-one pool of copy helpers; `createResponseCopyExecutor` takes its child and warms the next one after each copy. */
|
|
80
|
+
export function createCopyHelperPool(helper, idleMs) {
|
|
81
|
+
return new HelperPool({ fork: () => forkCopyHelper(helper), stop: stopCopyHelper, ...(idleMs === undefined ? {} : { idleMs }) });
|
|
82
|
+
}
|
|
77
83
|
/** Forks one copy helper: bounded IPC only, no clipboard payload in argv or temp files, no inherited terminal descriptors. */
|
|
78
84
|
function forkCopyHelper(helper) {
|
|
79
85
|
const source = new URL(import.meta.url).pathname.endsWith(".ts");
|
|
@@ -1,23 +1,21 @@
|
|
|
1
1
|
import { ImageAttachmentError } from "../../contracts/owned-ui/index.js";
|
|
2
|
-
import type { OwnedUiPromptSuggestionGeneratorPort, OwnedUiSessionViewModel, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, OwnedUiQuitOutroSettingsPort, SuggestionDecision, SuggestionDiagnosticObserver } from "../../contracts/owned-ui/index.js";
|
|
2
|
+
import type { OwnedUiBackgroundSettingsPort, OwnedUiPromptSuggestionGeneratorPort, OwnedUiSessionBackend, OwnedUiSessionPresenters, OwnedUiSessionViewModel, OwnedUiTranscriptRendererPort, OwnedUiWorkflowMessage, OwnedUiWorkflowResult, OwnedUiViewportSettings, OwnedUiViewportSettingsPort, OwnedUiQuitOutroSettingsPort, SuggestionDecision, SuggestionDiagnosticObserver } from "../../contracts/owned-ui/index.js";
|
|
3
3
|
import type { PiTuiPointerSurface } from "../../integrations/pi/tui-runtime/contracts.js";
|
|
4
4
|
import type { UiRouteHost, UiRouteInput } from "../../ui/apps/contracts.js";
|
|
5
5
|
import type { TranscriptViewportFrame, TranscriptViewportFrameDescriptor } from "../../ui/components/transcript-viewport.js";
|
|
6
|
-
import type { PiEngineAdapter } from "../../integrations/pi/engine/adapter.js";
|
|
7
|
-
import type { PiWorkflowMessage, PiWorkflowResult } from "../../integrations/pi/engine/workflows.js";
|
|
8
6
|
import type { PiShellLazySelectorLoader } from "../../integrations/pi/components/lazy-selectors.js";
|
|
9
7
|
import { type PiShellHotkeysPresentation } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
10
|
-
import { type PiShellClipboardContent, type PiShellComponentPort, type
|
|
8
|
+
import { type PiShellClipboardContent, type PiShellComponentPort, type PiKeybindingsHost, type PiShellEditorPort, type PiShellHeaderOptions, type PiShellHeaderPort, type PiShellImageAssetResolver, type PiShellLoadedResourcesPort, type PiShellResourceEntry, type PiShellTranscriptComponentPort } from "../../integrations/pi/components/shell-shared-facade.js";
|
|
11
9
|
import { type PiTuiInputCoordinationScheduler, type PiTuiInputSurfaceKind } from "../../integrations/pi/tui-runtime/input-presentation-coordinator.js";
|
|
12
10
|
import type { PiTuiComponentPort, PiTuiInputDiagnosticsEvent, PiTuiLayoutNode, PiTuiTerminalPort } from "../../integrations/pi/tui-runtime/contracts.js";
|
|
13
11
|
import { type PreparedPrompt } from "./prompt-chips.js";
|
|
14
12
|
import type { PastePreparationClientOptions } from "./paste-preparation-client.js";
|
|
13
|
+
import type { OwnedUiClipboardServices } from "./clipboard-services.js";
|
|
15
14
|
import { type SessionViewportInputResult } from "./session-viewport-controller.js";
|
|
16
15
|
import type { ResponseCopyExecutor } from "./response-copy-transport.js";
|
|
17
16
|
import type { ResponseCopyEvent } from "./response-copy-protocol.js";
|
|
18
17
|
import type { PasteEvent, PasteSource } from "./paste-protocol.js";
|
|
19
18
|
import type { StreamPresentationScheduler } from "./stream-presentation-coalescer.js";
|
|
20
|
-
export type OwnedUiBackendPort = PiEngineAdapter;
|
|
21
19
|
export type OwnedUiTerminalPort = PiTuiTerminalPort;
|
|
22
20
|
type OwnedUiStartupOptions = PiShellHeaderOptions;
|
|
23
21
|
export interface OwnedUiClipboardPort {
|
|
@@ -30,7 +28,7 @@ export interface OwnedUiClipboardPort {
|
|
|
30
28
|
}
|
|
31
29
|
/** The engine session the shell presents and the composition's decisions about it. */
|
|
32
30
|
export interface OwnedUiShellEngineOptions {
|
|
33
|
-
readonly backend:
|
|
31
|
+
readonly backend: OwnedUiSessionBackend;
|
|
34
32
|
readonly cwd: string;
|
|
35
33
|
/**
|
|
36
34
|
* Declared A1-owned routes. A route this host claims resolves to its app;
|
|
@@ -52,6 +50,8 @@ export interface OwnedUiShellPresentationOptions {
|
|
|
52
50
|
readonly startup?: OwnedUiStartupOptions;
|
|
53
51
|
/** Live profile-local settings, supplied only to the bare-A1 composition. */
|
|
54
52
|
readonly viewportSettings?: OwnedUiViewportSettingsPort;
|
|
53
|
+
/** Live fullscreen canvas choice, supplied only to the bare-A1 composition. */
|
|
54
|
+
readonly backgroundSettings?: OwnedUiBackgroundSettingsPort;
|
|
55
55
|
/** Deterministic scheduling seam for presentation-cadence tests. */
|
|
56
56
|
readonly stream?: {
|
|
57
57
|
readonly intervalMs?: number;
|
|
@@ -130,9 +130,17 @@ export interface OwnedUiShellSkillsOptions {
|
|
|
130
130
|
readonly presentation: () => "collapse" | "expand";
|
|
131
131
|
readonly onChange: (listener: () => void) => () => void;
|
|
132
132
|
}
|
|
133
|
+
/** Process-wide services composition creates once and every session shell borrows; absent, a shell keeps private ones. */
|
|
134
|
+
export interface OwnedUiShellSharedServices {
|
|
135
|
+
readonly clipboard?: OwnedUiClipboardServices;
|
|
136
|
+
/** Must match the shell's layout: the owned-input profile for the custom viewport, Pi's otherwise. */
|
|
137
|
+
readonly keybindings?: PiKeybindingsHost;
|
|
138
|
+
}
|
|
133
139
|
/** What composes an owned session shell, grouped by the collaborator that provides each part. */
|
|
134
140
|
export interface OwnedUiSessionShellOptions {
|
|
135
141
|
readonly engine: OwnedUiShellEngineOptions;
|
|
142
|
+
/** Opens the selectors and resolves the transcript renderers whose inputs are engine objects. */
|
|
143
|
+
readonly presenters: OwnedUiSessionPresenters;
|
|
136
144
|
readonly presentation?: OwnedUiShellPresentationOptions;
|
|
137
145
|
readonly history?: OwnedUiShellHistoryOptions;
|
|
138
146
|
readonly suggestions?: OwnedUiShellSuggestionOptions;
|
|
@@ -141,6 +149,7 @@ export interface OwnedUiSessionShellOptions {
|
|
|
141
149
|
/** Supplied only to the bare-A1 composition; absent keeps the pinned per-skill command list. */
|
|
142
150
|
readonly skills?: OwnedUiShellSkillsOptions;
|
|
143
151
|
readonly diagnostics?: OwnedUiShellDiagnosticOptions;
|
|
152
|
+
readonly shared?: OwnedUiShellSharedServices;
|
|
144
153
|
}
|
|
145
154
|
/** Composes backend session state into the owned transcript, viewport, editor, and dock presentation. */
|
|
146
155
|
export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
@@ -178,9 +187,10 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
178
187
|
readonly captureClipboardPaste?: () => PasteSource;
|
|
179
188
|
readonly pasteDiagnostics?: (event: PasteEvent) => void;
|
|
180
189
|
readonly pastePreparation?: Omit<PastePreparationClientOptions, "onEvent">;
|
|
190
|
+
readonly keybindings?: PiKeybindingsHost;
|
|
181
191
|
readonly promptImageLimit?: () => number;
|
|
182
192
|
readonly skillsPresentation?: () => "collapse" | "expand";
|
|
183
|
-
}, startup?: PiShellHeaderOptions, agentDir?: string, extensionRenderers?:
|
|
193
|
+
}, startup?: PiShellHeaderOptions, agentDir?: string, extensionRenderers?: OwnedUiTranscriptRendererPort, sessionLayout?: "pinned" | "custom-viewport", imageAssets?: PiShellImageAssetResolver);
|
|
184
194
|
setEditorPaddingX(padding: number): void;
|
|
185
195
|
setAutocompleteMaxVisible(maxVisible: number): void;
|
|
186
196
|
setOutputPad(padding: 0 | 1): void;
|
|
@@ -266,8 +276,8 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
266
276
|
transcriptComponent(id: string): PiShellTranscriptComponentPort | undefined;
|
|
267
277
|
exitTranscript(width: number): string;
|
|
268
278
|
appendWorkflowStatus(message: string): void;
|
|
269
|
-
appendWorkflowMessage(message:
|
|
270
|
-
appendWorkflowResult(result:
|
|
279
|
+
appendWorkflowMessage(message: OwnedUiWorkflowMessage, errorCode?: ImageAttachmentError["code"]): void;
|
|
280
|
+
appendWorkflowResult(result: OwnedUiWorkflowResult, errorCode?: ImageAttachmentError["code"]): void;
|
|
271
281
|
toggleThinkingVisibility(): void;
|
|
272
282
|
get toolsExpanded(): boolean;
|
|
273
283
|
setToolsExpanded(expanded: boolean): void;
|
|
@@ -296,5 +306,5 @@ export declare class OwnedUiSessionShellRoot implements PiTuiComponentPort {
|
|
|
296
306
|
setFocused(focused: boolean): void;
|
|
297
307
|
dispose(): void;
|
|
298
308
|
}
|
|
299
|
-
export declare function shellResourceEntries(backend:
|
|
309
|
+
export declare function shellResourceEntries(backend: OwnedUiSessionBackend): readonly PiShellResourceEntry[];
|
|
300
310
|
export {};
|
|
@@ -5,11 +5,9 @@ import { composeSubmittedPromptRows, formatSubmittedPromptTime, submittedPromptL
|
|
|
5
5
|
import { backgroundSgrSpan, heldNativeHyperlinkStyle, hyperlinkSgrSpan, nativeHyperlinkStyle, overlaySpan, } from "../../ui/components/spans.js";
|
|
6
6
|
import { progressStatusFrame, progressStatusText } from "../../ui/components/progress-status.js";
|
|
7
7
|
import { displayWidth, faint, stripAnsi } from "../../ui/components/text.js";
|
|
8
|
-
import { PINNED_PI_HIDDEN_COMMAND_NAMES, PINNED_PI_WORKFLOW_COMMAND_NAMES } from "../../integrations/pi/engine/workflows.js";
|
|
9
|
-
import { createPiExtensionUiBridge } from "../../integrations/pi/components/shell-extension-ui.js";
|
|
10
8
|
import { createPiShellEditor } from "../../integrations/pi/components/shell-editor-autocomplete.js";
|
|
11
9
|
import { createPiQueuedInputStatus, createPiShellFooter, createPiShellHeader, createPiShellLoadedResources, createPiShellStatus, } from "../../integrations/pi/components/shell-footer-status.js";
|
|
12
|
-
import { createPiShellArmin,
|
|
10
|
+
import { createPiShellArmin, createPiShellEarendilAnnouncement, } from "../../integrations/pi/components/shell-selectors-dialogs.js";
|
|
13
11
|
import { createPiShellChangelog, createPiShellCollapsedChangelog, createPiShellHotkeys, createPiShellSessionInfo, renderPiShellCommandMessage, renderPiShellPackageUpdateNotice, renderPiShellReleaseUpdateBanner, renderPiShellReleaseUpdateNotice, renderPiShellStatusText, } from "../../integrations/pi/components/shell-presenters-info.js";
|
|
14
12
|
import { createPiShellTranscriptComponent, isPiPromptStyleCompaction, paintPiSubmittedPromptTimestamp, renderPiShellStartupDiagnostic, renderPiShellTranscriptBlock, } from "../../integrations/pi/components/shell-presenters-transcript.js";
|
|
15
13
|
import { onPiThemeChange, PINNED_PI_LAYOUT, piTheme } from "../../integrations/pi/components/upstream/theme/theme.js";
|
|
@@ -88,6 +86,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
88
86
|
constructor(view, cwd, handlers, startup = {}, agentDir, extensionRenderers = {
|
|
89
87
|
getMessageRenderer: () => undefined,
|
|
90
88
|
getToolRenderers: () => undefined,
|
|
89
|
+
getShortcuts: () => [],
|
|
91
90
|
}, sessionLayout = "pinned", imageAssets) {
|
|
92
91
|
this.#view = view;
|
|
93
92
|
this.#customViewport = sessionLayout === "custom-viewport";
|
|
@@ -124,6 +123,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
124
123
|
this.editor = createPiShellEditor({
|
|
125
124
|
...handlers,
|
|
126
125
|
keybindingProfile: this.#customViewport ? "a1" : "pi",
|
|
126
|
+
...(handlers.keybindings === undefined ? {} : { keybindings: handlers.keybindings }),
|
|
127
127
|
paintEditorSelection: (line, from, to, atomic) => backgroundSgrSpan(line, from, to, atomic ? "\u001b[7m" : "\u001b[27m\u001b[48;2;38;79;120m", atomic ? "\u001b[27m" : "\u001b[49m", piShellVisibleWidth),
|
|
128
128
|
transformPastedContent: content => {
|
|
129
129
|
try {
|
|
@@ -1071,7 +1071,7 @@ export class OwnedUiSessionShellRoot {
|
|
|
1071
1071
|
hotkeysPresentation() {
|
|
1072
1072
|
return {
|
|
1073
1073
|
bindings: this.editor.keybindingConfig(),
|
|
1074
|
-
getShortcuts: bindings => this.#extensionRenderers.getShortcuts
|
|
1074
|
+
getShortcuts: bindings => this.#extensionRenderers.getShortcuts(bindings),
|
|
1075
1075
|
profile: this.#customViewport ? "a1" : "pi",
|
|
1076
1076
|
};
|
|
1077
1077
|
}
|
|
@@ -1381,7 +1381,7 @@ function layoutPort(render, invalidate, handleInput) {
|
|
|
1381
1381
|
};
|
|
1382
1382
|
}
|
|
1383
1383
|
export function shellResourceEntries(backend) {
|
|
1384
|
-
const resources = backend.nonVisualResources().map(resource => ({
|
|
1384
|
+
const resources = backend.extensions.nonVisualResources().map(resource => ({
|
|
1385
1385
|
section: resource.kind === "skill"
|
|
1386
1386
|
? "Skills"
|
|
1387
1387
|
: resource.kind === "prompt-template"
|
|
@@ -1397,7 +1397,7 @@ export function shellResourceEntries(backend) {
|
|
|
1397
1397
|
sourcePath: resource.sourcePath,
|
|
1398
1398
|
diagnostic: resource.diagnostic,
|
|
1399
1399
|
}));
|
|
1400
|
-
const extensions = backend.extensionResources().filter(extension => !extension.hidden);
|
|
1400
|
+
const extensions = backend.extensions.extensionResources().filter(extension => !extension.hidden);
|
|
1401
1401
|
const loadedExtensions = extensions.filter(extension => extension.diagnostic === null);
|
|
1402
1402
|
const extensionLabels = compactExtensionLabels(loadedExtensions);
|
|
1403
1403
|
for (const extension of extensions) {
|