@timurproko/a1 0.1.8-dev.290 → 0.1.8-dev.322
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 +21 -0
- package/bin/guardian.js +4 -3
- package/bin/ui.js +4 -2
- package/bin/update-recovery.js +3 -1
- package/dist/composition/owned-ui.js +13 -1
- package/dist/contracts/owned-ui/index.d.ts +1 -0
- package/dist/contracts/owned-ui/index.js +1 -0
- package/dist/contracts/owned-ui/prompt-history.d.ts +37 -0
- package/dist/contracts/owned-ui/prompt-history.js +23 -0
- package/dist/features/launch/profile-paths.d.ts +2 -0
- package/dist/features/launch/profile-paths.js +11 -0
- package/dist/features/prompt-history/index.d.ts +2 -0
- package/dist/features/prompt-history/index.js +2 -0
- package/dist/features/prompt-history/paths.d.ts +4 -0
- package/dist/features/prompt-history/paths.js +16 -0
- package/dist/features/prompt-history/service.d.ts +24 -0
- package/dist/features/prompt-history/service.js +260 -0
- package/dist/features/prompt-history/store.d.ts +15 -0
- package/dist/features/prompt-history/store.js +166 -0
- package/dist/features/prompt-history/worker.d.ts +9 -0
- package/dist/features/prompt-history/worker.js +42 -0
- package/dist/foundation/launch-context/index.d.ts +29 -0
- package/dist/foundation/launch-context/index.js +83 -0
- package/dist/foundation/launch-guardian/main.js +4 -3
- package/dist/foundation/release/bootstrap.d.ts +1 -1
- package/dist/foundation/release/bootstrap.js +18 -12
- package/dist/foundation/release/cohort-state.d.ts +1 -0
- package/dist/foundation/release/cohort-state.js +4 -0
- package/dist/foundation/release/release-gc.js +2 -2
- package/dist/foundation/release/release-store.js +10 -3
- package/dist/foundation/release/release.d.ts +3 -1
- package/dist/foundation/release/release.js +7 -3
- package/dist/foundation/release/restart-certification.d.ts +1 -0
- package/dist/foundation/release/restart-certification.js +5 -0
- package/dist/foundation/release/update-recovery.d.ts +2 -0
- package/dist/foundation/release/update-recovery.js +4 -0
- package/dist/foundation/release/update.js +5 -0
- package/dist/foundation/release/warmup.d.ts +1 -1
- package/dist/foundation/release/warmup.js +5 -4
- package/dist/foundation/startup/startup-runtime.js +13 -11
- package/dist/foundation/supervision/main.js +8 -7
- package/dist/integrations/pi/components/editor-interaction.d.ts +38 -0
- package/dist/integrations/pi/components/editor-interaction.js +1 -0
- package/dist/integrations/pi/components/history-editor-loader.d.ts +5 -0
- package/dist/integrations/pi/components/history-editor-loader.js +5 -0
- package/dist/integrations/pi/components/index.d.ts +1 -0
- package/dist/integrations/pi/components/index.js +1 -0
- package/dist/integrations/pi/components/owned-editor-ux.d.ts +2 -1
- package/dist/integrations/pi/components/owned-editor-ux.js +95 -22
- package/dist/integrations/pi/components/shell-editor-autocomplete.js +12 -1
- package/dist/integrations/pi/components/shell-presenters-info.d.ts +9 -2
- package/dist/integrations/pi/components/shell-presenters-info.js +35 -4
- package/dist/integrations/pi/components/shell-selectors-dialogs.d.ts +3 -2
- package/dist/integrations/pi/components/shell-selectors-dialogs.js +8 -5
- package/dist/integrations/pi/components/shell-shared-facade.d.ts +15 -2
- package/dist/integrations/pi/components/upstream/assets/earendil-image.json +12 -0
- package/dist/integrations/pi/components/upstream/components/earendil-announcement.js +25 -2
- package/dist/integrations/pi/components/upstream/components/owned-editor.d.ts +13 -9
- package/dist/integrations/pi/components/upstream/components/owned-editor.js +137 -133
- package/dist/integrations/pi/components/upstream/history/editor-core.d.ts +280 -0
- package/dist/integrations/pi/components/upstream/history/editor-core.js +2062 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.d.ts +32 -0
- package/dist/integrations/pi/components/upstream/history/kill-ring.js +48 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.d.ts +1 -0
- package/dist/integrations/pi/components/upstream/history/printable-key.js +40 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.d.ts +14 -0
- package/dist/integrations/pi/components/upstream/history/text-helpers.js +28 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.d.ts +22 -0
- package/dist/integrations/pi/components/upstream/history/undo-stack.js +36 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.d.ts +24 -0
- package/dist/integrations/pi/components/upstream/history/word-navigation.js +100 -0
- package/dist/integrations/pi/engine/adapter.d.ts +13 -1
- package/dist/integrations/pi/engine/adapter.js +86 -25
- package/dist/integrations/pi/engine/changelog.d.ts +2 -0
- package/dist/integrations/pi/engine/changelog.js +63 -0
- package/dist/integrations/pi/engine/resources/changelog.json +12 -0
- package/dist/integrations/pi/engine/workflow-controllers.d.ts +1 -1
- package/dist/integrations/pi/engine/workflows.d.ts +1 -1
- package/dist/integrations/pi/session-ui/prompt-chips.d.ts +4 -1
- package/dist/integrations/pi/session-ui/prompt-chips.js +40 -13
- package/dist/integrations/pi/session-ui/prompt-history-controller.d.ts +30 -0
- package/dist/integrations/pi/session-ui/prompt-history-controller.js +147 -0
- package/dist/integrations/pi/session-ui/session-shell-root.d.ts +33 -0
- package/dist/integrations/pi/session-ui/session-shell-root.js +68 -74
- package/dist/integrations/pi/session-ui/session-shell.d.ts +1 -1
- package/dist/integrations/pi/session-ui/session-shell.js +98 -12
- package/dist/integrations/pi/session-ui/session-viewport-controller.d.ts +5 -0
- package/dist/integrations/pi/session-ui/session-viewport-controller.js +21 -15
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.d.ts +7 -0
- package/dist/integrations/pi/tui-runtime/damage-aware-terminal.js +7 -6
- 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/product-identity.d.ts +2 -2
- package/dist/product-identity.js +3 -36
- package/dist/product-identity.json +1 -22
- package/dist/ui/components/transcript-viewport.d.ts +8 -0
- package/dist/ui/components/transcript-viewport.js +23 -2
- package/dist/ui/components/visible-hyperlinks.d.ts +7 -0
- package/dist/ui/components/visible-hyperlinks.js +1 -0
- package/dist/ui/settings/declarations.js +19 -0
- package/dist/ui/settings/sections.js +11 -1
- package/dist/ui/settings/session.js +13 -4
- package/docs/architecture/boundaries.md +2 -0
- package/docs/architecture/history-editor-provenance.md +96 -0
- package/docs/architecture/internal-naming.md +89 -0
- package/docs/architecture/project-structure.md +1 -0
- package/docs/architecture/resource-and-data-policy.md +27 -1
- package/docs/architecture/toolchain.md +15 -1
- package/docs/features/prompt-history.md +149 -0
- package/package.json +8 -3
|
@@ -2,6 +2,7 @@ import { createHash } from "node:crypto";
|
|
|
2
2
|
import { lstat, readFile, realpath, stat } from "node:fs/promises";
|
|
3
3
|
import { basename, isAbsolute, relative, resolve, sep } from "node:path";
|
|
4
4
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
5
|
+
import { assertCurrentLaunchContract } from "../launch-context/index.js";
|
|
5
6
|
import { DEPENDENCY_LAYER_MANIFEST, dependencyLayerCertificationPath } from "./dependency-layer.js";
|
|
6
7
|
import { immutablePlatformPolicy } from "./immutable-platform.js";
|
|
7
8
|
import { PRODUCT_PACKAGE_NAME } from "./release.js";
|
|
@@ -11,6 +12,7 @@ const RESTART_SEAL_VERSION = 1;
|
|
|
11
12
|
const REQUIRED_LAUNCH_ENTRIES = ["bin/supervisor.js", "bin/guardian.js"];
|
|
12
13
|
/** Build compact restart authority after complete content verification established read-only payload files. */
|
|
13
14
|
export async function createRestartSeal(release, dataDir) {
|
|
15
|
+
assertCurrentLaunchContract(release);
|
|
14
16
|
const policy = immutablePlatformPolicy();
|
|
15
17
|
if (policy === null)
|
|
16
18
|
return null;
|
|
@@ -45,6 +47,7 @@ export async function createRestartSeal(release, dataDir) {
|
|
|
45
47
|
}));
|
|
46
48
|
const core = {
|
|
47
49
|
version: RESTART_SEAL_VERSION,
|
|
50
|
+
launchContract: release.launchContract,
|
|
48
51
|
platform: process.platform,
|
|
49
52
|
platformPolicy: policy,
|
|
50
53
|
releaseId: release.releaseId,
|
|
@@ -81,6 +84,7 @@ export async function readRestartCertifiedRelease(record, dataDir, onEvent) {
|
|
|
81
84
|
throw new Error("restart certification differs from the approved release record");
|
|
82
85
|
}
|
|
83
86
|
const seal = normalizeRestartSeal(certification.restartSeal);
|
|
87
|
+
assertCurrentLaunchContract(seal);
|
|
84
88
|
if (seal.platform !== process.platform || seal.platformPolicy !== immutablePlatformPolicy()) {
|
|
85
89
|
throw new Error("restart certification platform immutability evidence is unsupported");
|
|
86
90
|
}
|
|
@@ -129,6 +133,7 @@ export async function readRestartCertifiedRelease(record, dataDir, onEvent) {
|
|
|
129
133
|
}
|
|
130
134
|
return {
|
|
131
135
|
packageName: PRODUCT_PACKAGE_NAME,
|
|
136
|
+
launchContract: seal.launchContract,
|
|
132
137
|
packageVersion: seal.packageVersion,
|
|
133
138
|
contentDigest: seal.contentDigest,
|
|
134
139
|
releaseId: seal.releaseId,
|
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { PRIVATE_LAUNCH_CONTRACT } from "../launch-context/index.js";
|
|
1
2
|
import type { UpdateTransaction, UpdateRecoveryState } from "./update-transaction.js";
|
|
2
3
|
export declare const UPDATE_RECOVERY_SCHEMA: "a1-update-recovery-v1";
|
|
3
4
|
export interface UpdateRecoveryCapsule {
|
|
4
5
|
readonly schema: typeof UPDATE_RECOVERY_SCHEMA;
|
|
6
|
+
readonly launchContract: typeof PRIVATE_LAUNCH_CONTRACT;
|
|
5
7
|
readonly transactionId: string;
|
|
6
8
|
readonly packageName: string;
|
|
7
9
|
readonly targetVersion: string;
|
|
@@ -5,6 +5,7 @@ import { dirname, isAbsolute, relative, resolve, sep } from "node:path";
|
|
|
5
5
|
import { fileURLToPath } from "node:url";
|
|
6
6
|
import { PRODUCT_IDENTITY, PRODUCT_TEXT } from "../../product-identity.js";
|
|
7
7
|
import { processIsAlive } from "./process-cleanup.js";
|
|
8
|
+
import { PRIVATE_LAUNCH_CONTRACT, assertCurrentLaunchContract } from "../launch-context/index.js";
|
|
8
9
|
export const UPDATE_RECOVERY_SCHEMA = "a1-update-recovery-v1";
|
|
9
10
|
const WORKER_TIMEOUT_MS = 15 * 60 * 1_000;
|
|
10
11
|
const POLL_MS = 50;
|
|
@@ -18,6 +19,7 @@ export function updateLauncherPaths(globalRoot, platform = process.platform) {
|
|
|
18
19
|
/** Validate transaction-scoped recovery authority without trusting npm temporary names. */
|
|
19
20
|
export async function readUpdateRecoveryCapsule(manifestPath, platform = process.platform) {
|
|
20
21
|
const capsule = JSON.parse(await readFile(manifestPath, "utf8"));
|
|
22
|
+
assertCurrentLaunchContract(capsule);
|
|
21
23
|
if (capsule.schema !== UPDATE_RECOVERY_SCHEMA || !/^[0-9a-f-]{36}$/i.test(capsule.transactionId) || typeof capsule.targetVersion !== "string"
|
|
22
24
|
|| capsule.packageName !== PRODUCT_TEXT.packageName || typeof capsule.packageRoot !== "string" || typeof capsule.globalRoot !== "string"
|
|
23
25
|
|| typeof capsule.launcherRoot !== "string" || !Array.isArray(capsule.launchers) || typeof capsule.priorReleaseId !== "string"
|
|
@@ -59,6 +61,7 @@ export async function readUpdateRecoveryCapsule(manifestPath, platform = process
|
|
|
59
61
|
if (priorReleaseRoot.split(sep).at(-1) !== capsule.priorReleaseId)
|
|
60
62
|
throw new Error("recovery prior release identity is invalid");
|
|
61
63
|
const priorManifest = JSON.parse(await readFile(resolve(priorReleaseRoot, capsule.releaseManifestName), "utf8"));
|
|
64
|
+
assertCurrentLaunchContract(priorManifest);
|
|
62
65
|
if (priorManifest.releaseId !== capsule.priorReleaseId || priorManifest.contentDigest !== capsule.priorContentDigest) {
|
|
63
66
|
throw new Error("recovery prior release manifest differs from the capsule");
|
|
64
67
|
}
|
|
@@ -95,6 +98,7 @@ export async function prepareUpdateRecoveryCapsule(options) {
|
|
|
95
98
|
const npmCli = await resolveNpmCli(canonicalGlobal, options.environment ?? process.env);
|
|
96
99
|
const capsule = {
|
|
97
100
|
schema: UPDATE_RECOVERY_SCHEMA,
|
|
101
|
+
launchContract: PRIVATE_LAUNCH_CONTRACT,
|
|
98
102
|
transactionId: options.transaction.transactionId,
|
|
99
103
|
packageName: PRODUCT_TEXT.packageName,
|
|
100
104
|
targetVersion: options.transaction.targetVersion,
|
|
@@ -13,6 +13,7 @@ import { cleanupVerifiedOwner, processIsAlive } from "./process-cleanup.js";
|
|
|
13
13
|
import { materializeRelease, readMaterializedRelease } from "./release-store.js";
|
|
14
14
|
import { scheduleReleaseCleanup } from "./release-gc.js";
|
|
15
15
|
import { warmMaterializedRelease } from "./warmup.js";
|
|
16
|
+
import { assertCurrentLaunchContract } from "../launch-context/index.js";
|
|
16
17
|
import { UpdateTransactionStore } from "./update-transaction.js";
|
|
17
18
|
import { removeUpdateRecoveryCapsule, runProtectedPackageReplacement } from "./update-recovery.js";
|
|
18
19
|
export const PRODUCT_PACKAGE = PRODUCT_TEXT.packageName;
|
|
@@ -77,6 +78,8 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
77
78
|
async targetIsActive(targetVersion) {
|
|
78
79
|
const state = await stateStore.read();
|
|
79
80
|
const activeId = state.references.active;
|
|
81
|
+
if (activeId)
|
|
82
|
+
assertCurrentLaunchContract(state.releases[activeId] ?? {});
|
|
80
83
|
if (!activeId || state.releases[activeId]?.packageVersion !== targetVersion)
|
|
81
84
|
return false;
|
|
82
85
|
const endpoint = await readActiveEndpoint(paths, activeId, environment);
|
|
@@ -85,6 +88,8 @@ export function createUpdateLifecycleCoordinator(environment = process.env, file
|
|
|
85
88
|
async shutdownVerifiedOwners(targetVersion) {
|
|
86
89
|
const state = await stateStore.read();
|
|
87
90
|
const activeId = state.references.active;
|
|
91
|
+
if (activeId)
|
|
92
|
+
assertCurrentLaunchContract(state.releases[activeId] ?? {});
|
|
88
93
|
const priorActiveVersion = activeId ? state.releases[activeId]?.packageVersion ?? null : null;
|
|
89
94
|
const owner = await readActiveEndpoint(paths, activeId, environment);
|
|
90
95
|
if (!owner)
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import type
|
|
1
|
+
import { type MaterializedRelease } from "./release-store.js";
|
|
2
2
|
/** Import the exact immutable startup graph in a terminal-free bounded child process. */
|
|
3
3
|
export declare function warmMaterializedRelease(release: MaterializedRelease, environment: NodeJS.ProcessEnv, timeoutMs?: number): Promise<void>;
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import { spawn } from "node:child_process";
|
|
2
|
-
import {
|
|
2
|
+
import { resolveReleaseEntryPoint } from "./release-store.js";
|
|
3
3
|
import { releaseEnvironment } from "./bootstrap.js";
|
|
4
|
-
import {
|
|
4
|
+
import { PRIVATE_ENVIRONMENT, assertCurrentLaunchContract } from "../launch-context/index.js";
|
|
5
5
|
/** Import the exact immutable startup graph in a terminal-free bounded child process. */
|
|
6
6
|
export async function warmMaterializedRelease(release, environment, timeoutMs = 30_000) {
|
|
7
|
-
|
|
7
|
+
assertCurrentLaunchContract(release);
|
|
8
|
+
const entry = await resolveReleaseEntryPoint(release, "bin/warmup.js");
|
|
8
9
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
9
10
|
const child = spawn(process.execPath, [entry], {
|
|
10
|
-
env: { ...releaseEnvironment(environment, release), [
|
|
11
|
+
env: { ...releaseEnvironment(environment, release), [PRIVATE_ENVIRONMENT.immutableWarmup]: "1" },
|
|
11
12
|
stdio: "ignore",
|
|
12
13
|
windowsHide: true,
|
|
13
14
|
});
|
|
@@ -5,18 +5,20 @@ import { dirname, resolve } from "node:path";
|
|
|
5
5
|
import { homedir, platform } from "node:os";
|
|
6
6
|
import { performance } from "node:perf_hooks";
|
|
7
7
|
import { PRODUCT_IDENTITY } from "../../product-identity.js";
|
|
8
|
+
import { readLaunchContext } from "../launch-context/index.js";
|
|
8
9
|
/** Initialize opt-in startup tracing from a caller-provided evidence path. */
|
|
9
10
|
export function initializeStartupTrace(environment, profileId, startedAtMs = performance.timeOrigin + performance.now()) {
|
|
10
11
|
const configured = environment[PRODUCT_IDENTITY.environment.startupTrace];
|
|
11
12
|
if (!configured || parseContext(configured) !== null)
|
|
12
13
|
return;
|
|
14
|
+
const launch = readLaunchContext(environment);
|
|
13
15
|
const context = {
|
|
14
16
|
path: resolve(configured),
|
|
15
17
|
traceId: randomUUID(),
|
|
16
18
|
startedAtMs,
|
|
17
19
|
profileId,
|
|
18
|
-
releaseId:
|
|
19
|
-
dependencyLayerIds: parseLayerIds(
|
|
20
|
+
releaseId: launch.releaseId ?? null,
|
|
21
|
+
dependencyLayerIds: parseLayerIds(launch.releaseLayers),
|
|
20
22
|
};
|
|
21
23
|
environment[PRODUCT_IDENTITY.environment.startupTrace] = JSON.stringify(context);
|
|
22
24
|
}
|
|
@@ -25,17 +27,18 @@ export async function markStartupPhase(environment, phase) {
|
|
|
25
27
|
const context = parseContext(environment[PRODUCT_IDENTITY.environment.startupTrace]);
|
|
26
28
|
if (context === null)
|
|
27
29
|
return;
|
|
30
|
+
const elapsedMs = Math.max(0, performance.timeOrigin + performance.now() - context.startedAtMs);
|
|
31
|
+
const launch = readLaunchContext(environment);
|
|
32
|
+
const dependencyLayerIds = parseLayerIds(launch.releaseLayers);
|
|
28
33
|
const event = {
|
|
29
34
|
schema: PRODUCT_IDENTITY.evidence.startupTraceSchema,
|
|
30
35
|
traceId: context.traceId,
|
|
31
36
|
phase,
|
|
32
|
-
elapsedMs
|
|
37
|
+
elapsedMs,
|
|
33
38
|
processId: process.pid,
|
|
34
39
|
profileId: context.profileId,
|
|
35
|
-
releaseId:
|
|
36
|
-
dependencyLayerIds:
|
|
37
|
-
? parseLayerIds(environment[PRODUCT_IDENTITY.environment.releaseLayers])
|
|
38
|
-
: context.dependencyLayerIds,
|
|
40
|
+
releaseId: launch.releaseId ?? context.releaseId,
|
|
41
|
+
dependencyLayerIds: dependencyLayerIds.length > 0 ? dependencyLayerIds : context.dependencyLayerIds,
|
|
39
42
|
nodeVersion: process.version,
|
|
40
43
|
fileReadOperations: process.resourceUsage().fsRead,
|
|
41
44
|
};
|
|
@@ -43,9 +46,7 @@ export async function markStartupPhase(environment, phase) {
|
|
|
43
46
|
await appendFile(context.path, `${JSON.stringify(event)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
44
47
|
}
|
|
45
48
|
export function assertImmutableWarmupEnvironment(environment) {
|
|
46
|
-
|
|
47
|
-
throw new Error("warmup entry is private to verified update activation");
|
|
48
|
-
}
|
|
49
|
+
readLaunchContext(environment, "warmup");
|
|
49
50
|
}
|
|
50
51
|
/** Enable the compile cache directly from launch environment without loading profile services. */
|
|
51
52
|
export function enableEnvironmentCompileCache(environment) {
|
|
@@ -54,7 +55,8 @@ export function enableEnvironmentCompileCache(environment) {
|
|
|
54
55
|
?? (platform() === "win32"
|
|
55
56
|
? resolve(environment.LOCALAPPDATA ?? home, PRODUCT_IDENTITY.state.windowsControlDirectory)
|
|
56
57
|
: resolve(environment.XDG_DATA_HOME ?? resolve(home, ".local", "share"), PRODUCT_IDENTITY.state.unixControlDirectory)));
|
|
57
|
-
|
|
58
|
+
const launch = readLaunchContext(environment);
|
|
59
|
+
return enableStartupCompileCache(dataDir, launch.releaseId ?? null, parseLayerIds(launch.releaseLayers));
|
|
58
60
|
}
|
|
59
61
|
/** Enable Node's supported persistent compile cache in an immutable-identity namespace. */
|
|
60
62
|
export function enableStartupCompileCache(dataDir, releaseId, dependencyLayerIds) {
|
|
@@ -6,16 +6,18 @@ import { publishSupervisorStartupResult, supervisorStartupFailure, supervisorSta
|
|
|
6
6
|
import { ControlStore } from "../storage/index.js";
|
|
7
7
|
import { resolveCohortEndpoint, resolveProductPaths } from "./paths.js";
|
|
8
8
|
import { SupervisorServer } from "./server.js";
|
|
9
|
-
import {
|
|
9
|
+
import { PRODUCT_TEXT } from "../../product-identity.js";
|
|
10
|
+
import { readLaunchContext } from "../launch-context/index.js";
|
|
10
11
|
export async function runSupervisor(arguments_ = []) {
|
|
11
12
|
const productPaths = resolveProductPaths();
|
|
12
13
|
mkdirSync(productPaths.runtimeDir, { recursive: true, mode: 0o700 });
|
|
13
14
|
mkdirSync(productPaths.endpointsDir, { recursive: true, mode: 0o700 });
|
|
14
15
|
let paths = productPaths;
|
|
15
16
|
const log = (message) => appendFileSync(paths.supervisorLogPath, `${new Date().toISOString()} ${message}\n`);
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
const
|
|
17
|
+
const context = readLaunchContext(process.env, "release");
|
|
18
|
+
const releaseRoot = context.releaseRoot;
|
|
19
|
+
const releaseId = context.releaseId;
|
|
20
|
+
const contentDigest = context.releaseDigest;
|
|
19
21
|
const attemptId = startupAttempt(arguments_);
|
|
20
22
|
const resultPath = attemptId ? supervisorStartupResultPath(productPaths.runtimeDir, attemptId) : null;
|
|
21
23
|
let stage = "release-environment";
|
|
@@ -24,9 +26,8 @@ export async function runSupervisor(arguments_ = []) {
|
|
|
24
26
|
if (!releaseRoot || !releaseId || !contentDigest)
|
|
25
27
|
throw new Error(PRODUCT_TEXT.diagnostic("supervisor must be launched from a verified immutable release"));
|
|
26
28
|
stage = "release-certification";
|
|
27
|
-
const release = await readCertifiedReleaseManifest({ releaseRoot, releaseId, contentDigest }, resolve(paths.dataDir, "releases")
|
|
28
|
-
//
|
|
29
|
-
// existed, even when its layer certification has already been upgraded by a retry.
|
|
29
|
+
const release = await readCertifiedReleaseManifest({ releaseRoot, releaseId, contentDigest }, resolve(paths.dataDir, "releases"));
|
|
30
|
+
// Invariant: readiness follows current-contract certification, never an old-updater upgrade path.
|
|
30
31
|
await recordParentCertifiedRelease(release, paths.dataDir);
|
|
31
32
|
stage = "immutable-root";
|
|
32
33
|
await assertImmutableExecutionRoot(release, paths.dataDir);
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import type { Editor } from "#pi-tui";
|
|
2
|
+
export interface EditorInteractionState {
|
|
3
|
+
lines: string[];
|
|
4
|
+
cursorLine: number;
|
|
5
|
+
cursorCol: number;
|
|
6
|
+
}
|
|
7
|
+
export interface EditorInteractionPort {
|
|
8
|
+
snapshot(): EditorInteractionState;
|
|
9
|
+
setCursor(line: number, col: number): void;
|
|
10
|
+
replaceLines(lines: readonly string[]): void;
|
|
11
|
+
updateUndoStates(update: (state: EditorInteractionState) => void): void;
|
|
12
|
+
scrollOffset(): number;
|
|
13
|
+
visualLines(width: number): Array<{
|
|
14
|
+
logicalLine: number;
|
|
15
|
+
startCol: number;
|
|
16
|
+
length: number;
|
|
17
|
+
}>;
|
|
18
|
+
setSegmentTransform(transform: (text: string, mode: "word" | "grapheme", segments: Iterable<Intl.SegmentData>) => Iterable<Intl.SegmentData>): void;
|
|
19
|
+
}
|
|
20
|
+
export interface EditorRecallPort {
|
|
21
|
+
replace(entries: readonly string[]): void;
|
|
22
|
+
position(): {
|
|
23
|
+
readonly index: number;
|
|
24
|
+
readonly total: number;
|
|
25
|
+
};
|
|
26
|
+
observe(listener: () => void): () => void;
|
|
27
|
+
reset(): void;
|
|
28
|
+
}
|
|
29
|
+
export interface EditorSurface extends Pick<Editor, Exclude<keyof Editor, "setText" | "render" | "handleInput">> {
|
|
30
|
+
setText(text: string): void;
|
|
31
|
+
render(width: number): string[];
|
|
32
|
+
handleInput(data: string): void;
|
|
33
|
+
readonly interaction?: EditorInteractionPort;
|
|
34
|
+
readonly recall?: EditorRecallPort;
|
|
35
|
+
}
|
|
36
|
+
export type SelectionEditor = Pick<Editor, "getText" | "getCursor" | "setText" | "insertTextAtCursor" | "invalidate" | "onChange" | "getPaddingX" | "isShowingAutocomplete"> & {
|
|
37
|
+
readonly interaction?: EditorInteractionPort;
|
|
38
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type ShellEditorInstance, type OwnedEditorOptions } from "./upstream/components/owned-editor.js";
|
|
2
|
+
import type { EditorTheme, TUI } from "#pi-tui";
|
|
3
|
+
import type { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
|
|
4
|
+
export type HistoryEditorConstructor = new (tui: TUI, theme: EditorTheme, keybindings: KeybindingsManager, options?: OwnedEditorOptions) => ShellEditorInstance;
|
|
5
|
+
export declare function loadHistoryEditor(): Promise<HistoryEditorConstructor>;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { SelectionEditor as Editor } from "./editor-interaction.js";
|
|
2
2
|
import type { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
|
|
3
3
|
import type { PiShellClipboardContent, PiShellEditorTextRange } from "./shell-shared-facade.js";
|
|
4
4
|
/**
|
|
@@ -52,6 +52,7 @@ export interface PromptSelectionUxOptions {
|
|
|
52
52
|
};
|
|
53
53
|
readonly transformPastedContent: (content: PiShellClipboardContent) => string;
|
|
54
54
|
readonly atomicRanges: (line: string) => readonly PiShellEditorTextRange[];
|
|
55
|
+
readonly hiddenRanges?: (line: string) => readonly PiShellEditorTextRange[];
|
|
55
56
|
readonly expandCopiedText: (text: string) => string;
|
|
56
57
|
readonly paintSelection: (line: string, from: number, to: number, atomic: boolean) => string;
|
|
57
58
|
readonly decorateRow: (row: string, width: number) => string;
|
|
@@ -202,6 +202,47 @@ class PromptSelectionInterceptor {
|
|
|
202
202
|
this.#redoStack = [];
|
|
203
203
|
}
|
|
204
204
|
render(width, next) {
|
|
205
|
+
const state = editorState(this.editor);
|
|
206
|
+
const hidden = state.lines.map(line => this.options.hiddenRanges?.(line) ?? []);
|
|
207
|
+
if (!hidden.some(ranges => ranges.length > 0))
|
|
208
|
+
return this.#renderVisible(width, next);
|
|
209
|
+
const original = { ...state, lines: [...state.lines] };
|
|
210
|
+
const selection = this.#selection;
|
|
211
|
+
const project = (position) => ({
|
|
212
|
+
line: position.line,
|
|
213
|
+
col: hideColumn(position.col, hidden[position.line] ?? []),
|
|
214
|
+
});
|
|
215
|
+
const lines = state.lines.map((line, index) => {
|
|
216
|
+
for (const range of [...(hidden[index] ?? [])].reverse())
|
|
217
|
+
line = line.slice(0, range.start) + line.slice(range.end);
|
|
218
|
+
return line;
|
|
219
|
+
});
|
|
220
|
+
// Rationale: project pending clipboard identities out before layout, not after painting.
|
|
221
|
+
// Keep the semantic draft/undo/submission markers intact and restore them even if rendering throws.
|
|
222
|
+
try {
|
|
223
|
+
this.#setRenderState(lines, project({ line: original.cursorLine, col: original.cursorCol }));
|
|
224
|
+
if (selection !== undefined)
|
|
225
|
+
this.#selection = { anchor: project(selection.anchor), head: project(selection.head) };
|
|
226
|
+
const rows = this.#renderVisible(width, next);
|
|
227
|
+
if (this.#geometry !== undefined) {
|
|
228
|
+
this.#geometry.hiddenRanges = hidden;
|
|
229
|
+
this.#geometry.lines = lines;
|
|
230
|
+
}
|
|
231
|
+
return rows;
|
|
232
|
+
}
|
|
233
|
+
finally {
|
|
234
|
+
this.#setRenderState(original.lines, { line: original.cursorLine, col: original.cursorCol });
|
|
235
|
+
this.#selection = selection;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
#setRenderState(lines, cursor) {
|
|
239
|
+
if (this.editor.interaction !== undefined)
|
|
240
|
+
this.editor.interaction.replaceLines(lines);
|
|
241
|
+
else
|
|
242
|
+
editorState(this.editor).lines = lines;
|
|
243
|
+
this.#setCursor(cursor);
|
|
244
|
+
}
|
|
245
|
+
#renderVisible(width, next) {
|
|
205
246
|
const rows = next().map(row => row.replaceAll(ATOMIC_SPACE_SENTINEL, " "));
|
|
206
247
|
const maxPadding = Math.max(0, Math.floor((width - 1) / 2));
|
|
207
248
|
const padding = Math.min(this.editor.getPaddingX(), maxPadding);
|
|
@@ -211,10 +252,10 @@ class PromptSelectionInterceptor {
|
|
|
211
252
|
const layoutWidth = Math.max(1, contentWidth - (padding ? 0 : 1));
|
|
212
253
|
const visualLines = editorVisualLineMap(this.editor, layoutWidth)
|
|
213
254
|
?? buildVisualLineMap(editorState(this.editor).lines, layoutWidth);
|
|
214
|
-
const scrollOffset = numericProperty(this.editor, "scrollOffset");
|
|
255
|
+
const scrollOffset = this.editor.interaction?.scrollOffset() ?? numericProperty(this.editor, "scrollOffset");
|
|
215
256
|
const maxVisibleLines = Math.max(5, Math.floor(this.options.getRows() * 0.3));
|
|
216
257
|
const textRows = Math.max(0, Math.min(visualLines.length - scrollOffset, maxVisibleLines, rows.length - 2));
|
|
217
|
-
this.#geometry = { width, padding, layoutWidth, visualLines, scrollOffset, textRows };
|
|
258
|
+
this.#geometry = { width, padding, layoutWidth, visualLines, scrollOffset, textRows, hiddenRanges: [] };
|
|
218
259
|
if (this.#atomicFocus() !== undefined) {
|
|
219
260
|
for (let row = 0; row < rows.length; row += 1) {
|
|
220
261
|
rows[row] = (rows[row] ?? "").replaceAll(CURSOR_MARKER, "");
|
|
@@ -344,12 +385,12 @@ class PromptSelectionInterceptor {
|
|
|
344
385
|
const visual = geometry.visualLines[geometry.scrollOffset + textRow];
|
|
345
386
|
if (visual === undefined)
|
|
346
387
|
return undefined;
|
|
347
|
-
const line = editorState(this.editor).lines[visual.logicalLine] ?? "";
|
|
388
|
+
const line = (geometry.lines ?? editorState(this.editor).lines)[visual.logicalLine] ?? "";
|
|
348
389
|
const segment = line.slice(visual.startCol, visual.startCol + visual.length);
|
|
349
390
|
const displayColumn = Math.max(0, column - 1 - geometry.padding - (this.options.promptPrefixWidth ?? 0));
|
|
350
391
|
return {
|
|
351
392
|
line: visual.logicalLine,
|
|
352
|
-
col: visual.startCol + indexAtDisplayWidth(segment, displayColumn),
|
|
393
|
+
col: restoreColumn(visual.startCol + indexAtDisplayWidth(segment, displayColumn), geometry.hiddenRanges[visual.logicalLine] ?? []),
|
|
353
394
|
};
|
|
354
395
|
}
|
|
355
396
|
#selectWord(position) {
|
|
@@ -464,15 +505,21 @@ class PromptSelectionInterceptor {
|
|
|
464
505
|
const selection = this.#selection === undefined ? undefined : { anchor: remap(this.#selection.anchor), head: remap(this.#selection.head) };
|
|
465
506
|
const next = current.slice(0, from) + text + current.slice(to);
|
|
466
507
|
// Compatibility: completing a paste updates its provisional undo snapshots, not the user's undo history.
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
508
|
+
if (this.editor.interaction !== undefined) {
|
|
509
|
+
this.editor.interaction.replaceLines(next.split("\n"));
|
|
510
|
+
this.editor.interaction.updateUndoStates(state => replaceSnapshotMarker(state, marker, text));
|
|
511
|
+
}
|
|
512
|
+
else {
|
|
513
|
+
editorState(this.editor).lines = next.split("\n");
|
|
514
|
+
const undo = Reflect.get(this.editor, "undoStack");
|
|
515
|
+
const snapshots = typeof undo === "object" && undo !== null ? Reflect.get(undo, "stack") : undefined;
|
|
516
|
+
if (Array.isArray(snapshots))
|
|
517
|
+
for (const snapshot of snapshots) {
|
|
518
|
+
const state = typeof snapshot === "object" && snapshot !== null ? Reflect.get(snapshot, "state") : undefined;
|
|
519
|
+
if (isEditorState(state))
|
|
520
|
+
replaceSnapshotMarker(state, marker, text);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
476
523
|
for (const snapshot of this.#redoStack) {
|
|
477
524
|
const state = { lines: snapshot.text.split("\n"), cursorLine: snapshot.cursor.line, cursorCol: snapshot.cursor.col };
|
|
478
525
|
replaceSnapshotMarker(state, marker, text);
|
|
@@ -602,6 +649,10 @@ class PromptSelectionInterceptor {
|
|
|
602
649
|
return this.editor.getCursor();
|
|
603
650
|
}
|
|
604
651
|
#setCursor(position) {
|
|
652
|
+
if (this.editor.interaction !== undefined) {
|
|
653
|
+
this.editor.interaction.setCursor(position.line, position.col);
|
|
654
|
+
return;
|
|
655
|
+
}
|
|
605
656
|
const state = editorState(this.editor);
|
|
606
657
|
const line = clamp(position.line, 0, Math.max(0, state.lines.length - 1));
|
|
607
658
|
state.cursorLine = line;
|
|
@@ -615,6 +666,7 @@ class PromptSelectionInterceptor {
|
|
|
615
666
|
: state.cursorCol >= range.start && state.cursorCol < range.end);
|
|
616
667
|
if (atomic !== undefined) {
|
|
617
668
|
state.cursorCol = delta < 0 ? atomic.start : atomic.end;
|
|
669
|
+
this.editor.interaction?.setCursor(state.cursorLine, state.cursorCol);
|
|
618
670
|
return;
|
|
619
671
|
}
|
|
620
672
|
if (delta < 0) {
|
|
@@ -626,6 +678,7 @@ class PromptSelectionInterceptor {
|
|
|
626
678
|
state.cursorLine -= 1;
|
|
627
679
|
state.cursorCol = (state.lines[state.cursorLine] ?? "").length;
|
|
628
680
|
}
|
|
681
|
+
this.editor.interaction?.setCursor(state.cursorLine, state.cursorCol);
|
|
629
682
|
return;
|
|
630
683
|
}
|
|
631
684
|
if (state.cursorCol < line.length) {
|
|
@@ -635,6 +688,7 @@ class PromptSelectionInterceptor {
|
|
|
635
688
|
state.cursorLine += 1;
|
|
636
689
|
state.cursorCol = 0;
|
|
637
690
|
}
|
|
691
|
+
this.editor.interaction?.setCursor(state.cursorLine, state.cursorCol);
|
|
638
692
|
}
|
|
639
693
|
#atomicRangeAt(position) {
|
|
640
694
|
const line = editorState(this.editor).lines[position.line] ?? "";
|
|
@@ -674,14 +728,8 @@ class PromptSelectionInterceptor {
|
|
|
674
728
|
}
|
|
675
729
|
}
|
|
676
730
|
function installAtomicSegmentation(editor, rangesForText, wordDirection) {
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
const originalValue = Reflect.get(editor, "segment");
|
|
680
|
-
if (typeof originalValue !== "function")
|
|
681
|
-
return;
|
|
682
|
-
const original = originalValue.bind(editor);
|
|
683
|
-
Reflect.set(editor, "segment", (text, mode) => {
|
|
684
|
-
const segments = [...original(text, mode)].filter(isEditorSegment);
|
|
731
|
+
const transform = (text, mode, values) => {
|
|
732
|
+
const segments = [...values].filter(isEditorSegment);
|
|
685
733
|
const ranges = rangesForText(text).map(range => ({ ...range, wordLike: false }));
|
|
686
734
|
if (mode === "word") {
|
|
687
735
|
for (const range of contextualPathRanges(editor, text, wordDirection())) {
|
|
@@ -713,7 +761,18 @@ function installAtomicSegmentation(editor, rangesForText, wordDirection) {
|
|
|
713
761
|
merged.push(segment);
|
|
714
762
|
}
|
|
715
763
|
return merged;
|
|
716
|
-
}
|
|
764
|
+
};
|
|
765
|
+
if (editor.interaction !== undefined) {
|
|
766
|
+
editor.interaction.setSegmentTransform(transform);
|
|
767
|
+
return;
|
|
768
|
+
}
|
|
769
|
+
if (Reflect.get(editor, ATOMIC_SEGMENTATION) === true)
|
|
770
|
+
return;
|
|
771
|
+
const originalValue = Reflect.get(editor, "segment");
|
|
772
|
+
if (typeof originalValue !== "function")
|
|
773
|
+
return;
|
|
774
|
+
const original = originalValue.bind(editor);
|
|
775
|
+
Reflect.set(editor, "segment", (text, mode) => transform(text, mode, original(text, mode)));
|
|
717
776
|
Reflect.set(editor, ATOMIC_SEGMENTATION, true);
|
|
718
777
|
}
|
|
719
778
|
function contextualPathRanges(editor, text, direction) {
|
|
@@ -786,7 +845,19 @@ function samePosition(left, right) {
|
|
|
786
845
|
function sameSnapshot(left, right) {
|
|
787
846
|
return left.text === right.text && samePosition(left.cursor, right.cursor);
|
|
788
847
|
}
|
|
848
|
+
function hideColumn(column, ranges) {
|
|
849
|
+
return column - ranges.reduce((removed, range) => removed + Math.max(0, Math.min(column, range.end) - range.start), 0);
|
|
850
|
+
}
|
|
851
|
+
function restoreColumn(column, ranges) {
|
|
852
|
+
let restored = column;
|
|
853
|
+
for (const range of ranges)
|
|
854
|
+
if (restored >= range.start)
|
|
855
|
+
restored += range.end - range.start;
|
|
856
|
+
return restored;
|
|
857
|
+
}
|
|
789
858
|
function editorState(editor) {
|
|
859
|
+
if (editor.interaction !== undefined)
|
|
860
|
+
return editor.interaction.snapshot();
|
|
790
861
|
const value = Object.getOwnPropertyDescriptor(editor, "state")?.value;
|
|
791
862
|
if (!isEditorState(value))
|
|
792
863
|
throw new Error("Pi editor state is unavailable");
|
|
@@ -806,6 +877,8 @@ function numericProperty(target, key) {
|
|
|
806
877
|
return typeof value === "number" ? value : 0;
|
|
807
878
|
}
|
|
808
879
|
function editorVisualLineMap(editor, width) {
|
|
880
|
+
if (editor.interaction !== undefined)
|
|
881
|
+
return editor.interaction.visualLines(width);
|
|
809
882
|
const builder = Reflect.get(editor, "buildVisualLineMap");
|
|
810
883
|
if (typeof builder !== "function")
|
|
811
884
|
return undefined;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { getSelectListTheme } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { CombinedAutocompleteProvider, matchesKey, setKeybindings, } from "#pi-tui";
|
|
3
|
+
import { PROMPT_HISTORY_EDITOR_REPLACEMENT } from "../../../contracts/owned-ui/index.js";
|
|
3
4
|
import { KeybindingsManager } from "./upstream/adjacent/core/keybindings.js";
|
|
4
5
|
import { OwnedEditor } from "./upstream/components/owned-editor.js";
|
|
5
6
|
import { OwnedEditorUxInterception, createPromptSelectionInterceptor, } from "./owned-editor-ux.js";
|
|
@@ -36,12 +37,18 @@ export function createPiShellEditor(options) {
|
|
|
36
37
|
? KeybindingsManager.createForOwnedInput(options.agentDir)
|
|
37
38
|
: KeybindingsManager.create(options.agentDir);
|
|
38
39
|
setKeybindings(keybindings);
|
|
39
|
-
|
|
40
|
+
if (options.persistentHistory === true && options.keybindingProfile === "a1" && options.historyEditor === undefined) {
|
|
41
|
+
throw new Error("Persistent history requires the loaded owned editor");
|
|
42
|
+
}
|
|
43
|
+
const EditorClass = options.keybindingProfile === "a1" && options.persistentHistory === true ? options.historyEditor : OwnedEditor;
|
|
44
|
+
const editor = new EditorClass(tui, {
|
|
40
45
|
borderColor: (value) => piTheme().fg("borderMuted", value),
|
|
41
46
|
selectList: getSelectListTheme(),
|
|
42
47
|
}, keybindings, {
|
|
43
48
|
paddingX: PINNED_PI_LAYOUT.editorPaddingX,
|
|
44
49
|
autocompleteMaxVisible: PINNED_PI_LAYOUT.autocompleteMaxVisible,
|
|
50
|
+
persistentHistory: options.persistentHistory === true,
|
|
51
|
+
styleHistoryLabel: text => piTheme().fg("dim", text),
|
|
45
52
|
...(options.keybindingProfile === "a1" && options.promptPresentation !== undefined ? {
|
|
46
53
|
promptPrefix: options.promptPresentation.prefix,
|
|
47
54
|
styleSuggestion: options.promptPresentation.styleSuggestion,
|
|
@@ -57,6 +64,7 @@ export function createPiShellEditor(options) {
|
|
|
57
64
|
...(options.beginClipboardPaste === undefined ? {} : { beginClipboardPaste: options.beginClipboardPaste }),
|
|
58
65
|
transformPastedContent: options.transformPastedContent ?? (content => content.kind === "text" ? content.text : ""),
|
|
59
66
|
atomicRanges: options.editorAtomicRanges ?? (() => []),
|
|
67
|
+
hiddenRanges: options.editorHiddenRanges ?? (() => []),
|
|
60
68
|
expandCopiedText: options.expandCopiedEditorText ?? (text => text),
|
|
61
69
|
paintSelection: options.paintEditorSelection ?? (line => line),
|
|
62
70
|
decorateRow: options.decorateEditorRow ?? (row => row),
|
|
@@ -142,6 +150,8 @@ export function createPiShellEditor(options) {
|
|
|
142
150
|
return {
|
|
143
151
|
render: width => editorUx?.render(width) ?? editor.render(width),
|
|
144
152
|
activateKeybindings: () => setKeybindings(keybindings),
|
|
153
|
+
keybindingConfig: () => keybindings.getEffectiveConfig(),
|
|
154
|
+
reloadKeybindings: () => { keybindings.reload(); setKeybindings(keybindings); },
|
|
145
155
|
matchesTerminalKey: (data, key) => matchesKey(data, key),
|
|
146
156
|
handleInput: data => {
|
|
147
157
|
if (editorUx === undefined)
|
|
@@ -163,6 +173,7 @@ export function createPiShellEditor(options) {
|
|
|
163
173
|
editor.insertTextAtCursor(text);
|
|
164
174
|
},
|
|
165
175
|
addToHistory: text => editor.addToHistory(text),
|
|
176
|
+
...(editor.recall === undefined ? {} : { recall: editor.recall, historyReplacement: PROMPT_HISTORY_EDITOR_REPLACEMENT }),
|
|
166
177
|
setSubmitEnabled: enabled => {
|
|
167
178
|
editor.disableSubmit = !enabled;
|
|
168
179
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { type
|
|
1
|
+
import { type KeybindingsConfig } from "#pi-tui";
|
|
2
|
+
import { type PiShellComponentPort, type PiShellExtensionRendererResolver } from "./shell-shared-facade.js";
|
|
2
3
|
export interface PiShellSessionInfoPresentation {
|
|
3
4
|
readonly sessionName?: string;
|
|
4
5
|
readonly stats: {
|
|
@@ -30,7 +31,13 @@ export interface PiShellSessionInfoPresentation {
|
|
|
30
31
|
}[];
|
|
31
32
|
}
|
|
32
33
|
export declare function renderPiShellStatusText(message: string, width: number, outputPad?: 0 | 1): readonly string[];
|
|
34
|
+
export interface PiShellCommandMessagePresentation {
|
|
35
|
+
readonly kind: "error" | "warning" | "accent" | "new" | "name" | "debug";
|
|
36
|
+
readonly message: string;
|
|
37
|
+
readonly detail?: string;
|
|
38
|
+
}
|
|
39
|
+
export declare function renderPiShellCommandMessage(presentation: PiShellCommandMessagePresentation, width: number, outputPad?: 0 | 1): readonly string[];
|
|
33
40
|
export declare function createPiShellSessionInfo(presentation: PiShellSessionInfoPresentation): PiShellComponentPort;
|
|
34
41
|
export declare function createPiShellCollapsedChangelog(): PiShellComponentPort;
|
|
35
42
|
export declare function createPiShellChangelog(markdown: string): PiShellComponentPort;
|
|
36
|
-
export declare function createPiShellHotkeys(): PiShellComponentPort;
|
|
43
|
+
export declare function createPiShellHotkeys(bindings?: KeybindingsConfig, getShortcuts?: NonNullable<PiShellExtensionRendererResolver["getShortcuts"]>, profile?: "pi" | "a1"): PiShellComponentPort;
|