@timurproko/a1 0.1.1-dev.6 → 0.1.1-dev.7
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 +32 -9
- package/bin/a1-guardian.js +22 -0
- package/bin/a1-ui.js +7 -4
- package/dist/native/darwin-arm64/a1-process-guardian +0 -0
- package/dist/native/darwin-arm64/manifest.json +20 -0
- package/dist/native/linux-x64/a1-process-guardian +0 -0
- package/dist/native/linux-x64/manifest.json +20 -0
- package/dist/native/win32-x64/a1-process-guardian.exe +0 -0
- package/dist/native/win32-x64/manifest.json +20 -0
- package/dist/src/composition/index.d.ts +26 -0
- package/dist/src/composition/index.js +88 -2
- package/dist/src/features/launch/runtime-selection.d.ts +2 -1
- package/dist/src/features/launch/runtime-selection.js +2 -2
- package/dist/src/features/owned-ui/index.d.ts +1 -0
- package/dist/src/features/owned-ui/index.js +1 -0
- package/dist/src/features/owned-ui/run.d.ts +6 -0
- package/dist/src/features/owned-ui/run.js +3 -1
- package/dist/src/features/owned-ui/settings-app.d.ts +22 -0
- package/dist/src/features/owned-ui/settings-app.js +631 -0
- package/dist/src/foundation/agent-engine-contracts/domain.d.ts +26 -0
- package/dist/src/foundation/launch-guardian/index.d.ts +1 -0
- package/dist/src/foundation/launch-guardian/index.js +1 -0
- package/dist/src/foundation/launch-guardian/main.d.ts +31 -0
- package/dist/src/foundation/launch-guardian/main.js +165 -0
- package/dist/src/foundation/lifecycle/commands.d.ts +40 -0
- package/dist/src/foundation/lifecycle/commands.js +1 -0
- package/dist/src/foundation/lifecycle/index.d.ts +2 -0
- package/dist/src/foundation/lifecycle/index.js +2 -0
- package/dist/src/foundation/lifecycle/launch-instance.d.ts +46 -0
- package/dist/src/foundation/lifecycle/launch-instance.js +134 -0
- package/dist/src/foundation/lifecycle/model.d.ts +6 -42
- package/dist/src/foundation/owned-ui-settings/declarations.d.ts +13 -0
- package/dist/src/foundation/owned-ui-settings/declarations.js +39 -0
- package/dist/src/foundation/owned-ui-settings/index.d.ts +6 -0
- package/dist/src/foundation/owned-ui-settings/index.js +6 -0
- package/dist/src/foundation/owned-ui-settings/migrations.d.ts +13 -0
- package/dist/src/foundation/owned-ui-settings/migrations.js +28 -0
- package/dist/src/foundation/owned-ui-settings/resolution.d.ts +45 -0
- package/dist/src/foundation/owned-ui-settings/resolution.js +147 -0
- package/dist/src/foundation/owned-ui-settings/sections.d.ts +70 -0
- package/dist/src/foundation/owned-ui-settings/sections.js +93 -0
- package/dist/src/foundation/owned-ui-settings/session.d.ts +44 -0
- package/dist/src/foundation/owned-ui-settings/session.js +145 -0
- package/dist/src/foundation/owned-ui-settings/store.d.ts +28 -0
- package/dist/src/foundation/owned-ui-settings/store.js +90 -0
- package/dist/src/foundation/pi-component-adapter/index.d.ts +1 -0
- package/dist/src/foundation/pi-component-adapter/index.js +1 -0
- package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.d.ts +9 -1
- package/dist/src/foundation/pi-component-adapter/shell-selectors-dialogs.js +10 -8
- package/dist/src/foundation/pi-engine-adapter/adapter.d.ts +12 -3
- package/dist/src/foundation/pi-engine-adapter/adapter.js +73 -7
- package/dist/src/foundation/pi-engine-adapter/pi-settings-metadata.json +374 -0
- package/dist/src/foundation/pi-engine-adapter/public-main-entry.js +10 -1
- package/dist/src/foundation/pi-engine-adapter/settings-integration.d.ts +42 -2
- package/dist/src/foundation/pi-engine-adapter/settings-integration.js +185 -24
- package/dist/src/foundation/pi-engine-adapter/workflows.d.ts +9 -0
- package/dist/src/foundation/pi-owned-ui-integration/index.d.ts +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/index.js +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/route-host.d.ts +29 -0
- package/dist/src/foundation/pi-owned-ui-integration/route-host.js +1 -0
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.d.ts +6 -0
- package/dist/src/foundation/pi-owned-ui-integration/session-shell.js +71 -1
- package/dist/src/foundation/pi-tui-runtime-adapter/adapter.d.ts +6 -0
- package/dist/src/foundation/pi-tui-runtime-adapter/adapter.js +9 -0
- package/dist/src/foundation/process-containment/artifact.d.ts +1 -0
- package/dist/src/foundation/process-containment/artifact.js +34 -0
- package/dist/src/foundation/process-containment/contracts.d.ts +31 -0
- package/dist/src/foundation/process-containment/contracts.js +35 -0
- package/dist/src/foundation/process-containment/index.d.ts +5 -0
- package/dist/src/foundation/process-containment/index.js +5 -0
- package/dist/src/foundation/process-containment/linux-process-inspector.d.ts +6 -0
- package/dist/src/foundation/process-containment/linux-process-inspector.js +26 -0
- package/dist/src/foundation/process-containment/native-guardian-containment.d.ts +16 -0
- package/dist/src/foundation/process-containment/native-guardian-containment.js +139 -0
- package/dist/src/foundation/process-containment/windows-process-inspector.d.ts +17 -0
- package/dist/src/foundation/process-containment/windows-process-inspector.js +53 -0
- package/dist/src/foundation/protocol/client.d.ts +2 -1
- package/dist/src/foundation/protocol/client.js +3 -0
- package/dist/src/foundation/protocol/messages.d.ts +5 -5
- package/dist/src/foundation/protocol/messages.js +1 -1
- package/dist/src/foundation/release/bootstrap.js +29 -10
- package/dist/src/foundation/release/cohort-selection.js +3 -3
- package/dist/src/foundation/release/cohort-state.d.ts +3 -2
- package/dist/src/foundation/release/process-cleanup.d.ts +1 -1
- package/dist/src/foundation/release/process-cleanup.js +2 -2
- package/dist/src/foundation/release/update.js +2 -2
- package/dist/src/foundation/storage/control-store.d.ts +8 -7
- package/dist/src/foundation/storage/control-store.js +105 -55
- package/dist/src/foundation/supervision/server.d.ts +4 -2
- package/dist/src/foundation/supervision/server.js +254 -87
- package/dist/src/foundation/transparent-terminal/command-resolution.js +6 -3
- package/dist/src/foundation/transparent-terminal/foreground-broker.d.ts +5 -13
- package/dist/src/foundation/transparent-terminal/foreground-broker.js +11 -68
- package/dist/src/foundation/transparent-terminal/main.js +1 -8
- package/dist/src/foundation/ui-apps/contracts.d.ts +42 -0
- package/dist/src/foundation/ui-apps/contracts.js +12 -0
- package/dist/src/foundation/ui-apps/host.d.ts +42 -0
- package/dist/src/foundation/ui-apps/host.js +152 -0
- package/dist/src/foundation/ui-apps/index.d.ts +3 -0
- package/dist/src/foundation/ui-apps/index.js +3 -0
- package/dist/src/foundation/ui-apps/registry.d.ts +11 -0
- package/dist/src/foundation/ui-apps/registry.js +32 -0
- package/dist/src/foundation/ui-components/dialog-panel.d.ts +36 -0
- package/dist/src/foundation/ui-components/dialog-panel.js +47 -0
- package/dist/src/foundation/ui-components/frame.d.ts +21 -0
- package/dist/src/foundation/ui-components/frame.js +54 -0
- package/dist/src/foundation/ui-components/index.d.ts +18 -0
- package/dist/src/foundation/ui-components/index.js +18 -0
- package/dist/src/foundation/ui-components/label.d.ts +8 -0
- package/dist/src/foundation/ui-components/label.js +36 -0
- package/dist/src/foundation/ui-components/line-input.d.ts +74 -0
- package/dist/src/foundation/ui-components/line-input.js +245 -0
- package/dist/src/foundation/ui-components/list-block.d.ts +66 -0
- package/dist/src/foundation/ui-components/list-block.js +176 -0
- package/dist/src/foundation/ui-components/list-view.d.ts +66 -0
- package/dist/src/foundation/ui-components/list-view.js +76 -0
- package/dist/src/foundation/ui-components/mouse.d.ts +15 -0
- package/dist/src/foundation/ui-components/mouse.js +46 -0
- package/dist/src/foundation/ui-components/pane.d.ts +33 -0
- package/dist/src/foundation/ui-components/pane.js +7 -0
- package/dist/src/foundation/ui-components/revision.d.ts +35 -0
- package/dist/src/foundation/ui-components/revision.js +79 -0
- package/dist/src/foundation/ui-components/scrollbar.d.ts +62 -0
- package/dist/src/foundation/ui-components/scrollbar.js +102 -0
- package/dist/src/foundation/ui-components/shortcuts.d.ts +57 -0
- package/dist/src/foundation/ui-components/shortcuts.js +81 -0
- package/dist/src/foundation/ui-components/spans.d.ts +7 -0
- package/dist/src/foundation/ui-components/spans.js +59 -0
- package/dist/src/foundation/ui-components/status-line.d.ts +16 -0
- package/dist/src/foundation/ui-components/status-line.js +14 -0
- package/dist/src/foundation/ui-components/stepper.d.ts +24 -0
- package/dist/src/foundation/ui-components/stepper.js +33 -0
- package/dist/src/foundation/ui-components/surface.d.ts +20 -0
- package/dist/src/foundation/ui-components/surface.js +38 -0
- package/dist/src/foundation/ui-components/text.d.ts +24 -0
- package/dist/src/foundation/ui-components/text.js +123 -0
- package/dist/src/foundation/ui-components/theme.d.ts +17 -0
- package/dist/src/foundation/ui-components/theme.js +12 -0
- package/dist/src/foundation/ui-components/value-menu.d.ts +41 -0
- package/dist/src/foundation/ui-components/value-menu.js +33 -0
- package/dist/src/product-identity.d.ts +2 -2
- package/dist/src/product-identity.js +2 -1
- package/dist/src/product-identity.json +3 -0
- package/docs/architecture/boundaries.md +31 -13
- package/docs/architecture/process-guardian-provenance.md +26 -0
- package/docs/architecture/toolchain.md +6 -0
- package/docs/architecture/ui-reference-provenance.md +50 -0
- package/docs/ci-release-runbook.md +38 -42
- package/docs/features/launch-profiles.md +7 -1
- package/docs/manual-launch-instance-acceptance.md +66 -0
- package/package.json +11 -12
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import { OWNED_UI_SETTINGS_VERSION, findOwnedUiSettingDeclaration, } from "./declarations.js";
|
|
2
|
+
import { migrationsFrom } from "./migrations.js";
|
|
3
|
+
export function parseOwnedUiSettingsDocument(raw) {
|
|
4
|
+
let parsed;
|
|
5
|
+
try {
|
|
6
|
+
parsed = JSON.parse(raw);
|
|
7
|
+
}
|
|
8
|
+
catch {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed))
|
|
12
|
+
return null;
|
|
13
|
+
const candidate = parsed;
|
|
14
|
+
const version = candidate["version"];
|
|
15
|
+
if (typeof version !== "number" || !Number.isInteger(version) || version < 1)
|
|
16
|
+
return null;
|
|
17
|
+
const values = candidate["values"];
|
|
18
|
+
if (typeof values !== "object" || values === null || Array.isArray(values))
|
|
19
|
+
return null;
|
|
20
|
+
return { version, values: values };
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Pure resolution: declarations plus a parsed document produce a complete value
|
|
24
|
+
* set, the keys to preserve, and every notice worth reporting. Never throws.
|
|
25
|
+
*/
|
|
26
|
+
export function resolveOwnedUiSettings(input) {
|
|
27
|
+
const currentVersion = input.currentVersion ?? OWNED_UI_SETTINGS_VERSION;
|
|
28
|
+
const notices = [];
|
|
29
|
+
if (input.unreadableDetail !== undefined) {
|
|
30
|
+
notices.push({ code: "document-unreadable", settingId: null, detail: input.unreadableDetail });
|
|
31
|
+
}
|
|
32
|
+
if (input.document === null) {
|
|
33
|
+
return {
|
|
34
|
+
version: currentVersion,
|
|
35
|
+
settings: defaultsFor(input.declarations),
|
|
36
|
+
preserved: Object.freeze({}),
|
|
37
|
+
notices: Object.freeze(notices),
|
|
38
|
+
migrated: false,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
if (input.document.version > currentVersion) {
|
|
42
|
+
notices.push({
|
|
43
|
+
code: "version-newer-than-supported",
|
|
44
|
+
settingId: null,
|
|
45
|
+
detail: `stored version ${input.document.version} is newer than supported version ${currentVersion}`,
|
|
46
|
+
});
|
|
47
|
+
return {
|
|
48
|
+
version: currentVersion,
|
|
49
|
+
settings: defaultsFor(input.declarations),
|
|
50
|
+
preserved: Object.freeze({ ...input.document.values }),
|
|
51
|
+
notices: Object.freeze(notices),
|
|
52
|
+
migrated: false,
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
const pending = migrationsFrom(input.migrations, input.document.version);
|
|
56
|
+
const expected = currentVersion - input.document.version;
|
|
57
|
+
if (pending.length !== expected) {
|
|
58
|
+
notices.push({
|
|
59
|
+
code: "migration-unavailable",
|
|
60
|
+
settingId: null,
|
|
61
|
+
detail: `no declared migration path from stored version ${input.document.version} to ${currentVersion}`,
|
|
62
|
+
});
|
|
63
|
+
return {
|
|
64
|
+
version: currentVersion,
|
|
65
|
+
settings: defaultsFor(input.declarations),
|
|
66
|
+
preserved: Object.freeze({ ...input.document.values }),
|
|
67
|
+
notices: Object.freeze(notices),
|
|
68
|
+
migrated: false,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
let values = { ...input.document.values };
|
|
72
|
+
for (const migration of pending) {
|
|
73
|
+
try {
|
|
74
|
+
values = { ...migration.migrate(Object.freeze({ ...values })) };
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
notices.push({
|
|
78
|
+
code: "migration-unavailable",
|
|
79
|
+
settingId: null,
|
|
80
|
+
detail: `migration to version ${migration.to} failed: ${describe(error)}`,
|
|
81
|
+
});
|
|
82
|
+
return {
|
|
83
|
+
version: currentVersion,
|
|
84
|
+
settings: defaultsFor(input.declarations),
|
|
85
|
+
preserved: Object.freeze({ ...input.document.values }),
|
|
86
|
+
notices: Object.freeze(notices),
|
|
87
|
+
migrated: false,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
const settings = [];
|
|
92
|
+
for (const declaration of input.declarations) {
|
|
93
|
+
if (!Object.hasOwn(values, declaration.id)) {
|
|
94
|
+
settings.push({ declaration, value: declaration.defaultValue, source: "default" });
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
const stored = values[declaration.id];
|
|
98
|
+
if (isAllowed(declaration, stored)) {
|
|
99
|
+
settings.push({ declaration, value: stored, source: "stored" });
|
|
100
|
+
continue;
|
|
101
|
+
}
|
|
102
|
+
notices.push({
|
|
103
|
+
code: "value-rejected",
|
|
104
|
+
settingId: declaration.id,
|
|
105
|
+
detail: `stored value ${JSON.stringify(stored) ?? "undefined"} is not an allowed value`,
|
|
106
|
+
});
|
|
107
|
+
settings.push({ declaration, value: declaration.defaultValue, source: "default" });
|
|
108
|
+
}
|
|
109
|
+
const preserved = {};
|
|
110
|
+
for (const [key, value] of Object.entries(values)) {
|
|
111
|
+
if (findOwnedUiSettingDeclaration(input.declarations, key) === null)
|
|
112
|
+
preserved[key] = value;
|
|
113
|
+
}
|
|
114
|
+
return {
|
|
115
|
+
version: currentVersion,
|
|
116
|
+
settings: Object.freeze(settings),
|
|
117
|
+
preserved: Object.freeze(preserved),
|
|
118
|
+
notices: Object.freeze(notices),
|
|
119
|
+
migrated: pending.length > 0,
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
export function settingValue(resolution, id) {
|
|
123
|
+
return resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
124
|
+
}
|
|
125
|
+
export function documentFrom(resolution) {
|
|
126
|
+
const values = { ...resolution.preserved };
|
|
127
|
+
for (const setting of resolution.settings) {
|
|
128
|
+
if (setting.source === "stored")
|
|
129
|
+
values[setting.declaration.id] = setting.value;
|
|
130
|
+
}
|
|
131
|
+
return { version: resolution.version, values };
|
|
132
|
+
}
|
|
133
|
+
function defaultsFor(declarations) {
|
|
134
|
+
return Object.freeze(declarations.map(declaration => ({
|
|
135
|
+
declaration,
|
|
136
|
+
value: declaration.defaultValue,
|
|
137
|
+
source: "default",
|
|
138
|
+
})));
|
|
139
|
+
}
|
|
140
|
+
function isAllowed(declaration, value) {
|
|
141
|
+
if (typeof value !== "string" && typeof value !== "number" && typeof value !== "boolean")
|
|
142
|
+
return false;
|
|
143
|
+
return declaration.allowedValues.includes(value);
|
|
144
|
+
}
|
|
145
|
+
function describe(error) {
|
|
146
|
+
return error instanceof Error ? error.message : String(error);
|
|
147
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { OwnedUiSettingValue } from "./declarations.js";
|
|
2
|
+
import type { OwnedUiSettingsResolution } from "./resolution.js";
|
|
3
|
+
export type OwnedUiSettingsBackend = "a1" | "agent";
|
|
4
|
+
export interface OwnedUiSettingsEntry {
|
|
5
|
+
readonly id: string;
|
|
6
|
+
/** Label to show, when its source provides one. Falls back to the id. */
|
|
7
|
+
readonly label: string | null;
|
|
8
|
+
readonly backend: OwnedUiSettingsBackend;
|
|
9
|
+
readonly description: string | null;
|
|
10
|
+
/** Present when the value is a scalar the surface can offer as a choice. */
|
|
11
|
+
readonly value: OwnedUiSettingValue | null;
|
|
12
|
+
/** Raw value as reported by its backend, for entries the surface can only display. */
|
|
13
|
+
readonly rawValue: unknown;
|
|
14
|
+
readonly editable: boolean;
|
|
15
|
+
readonly choices: readonly OwnedUiSettingValue[] | null;
|
|
16
|
+
/** True when the value is a structured object edited through its own surface. */
|
|
17
|
+
readonly structured: boolean;
|
|
18
|
+
/** Limits a numeric setting accepts, when the engine states them. */
|
|
19
|
+
readonly minimum: number | null;
|
|
20
|
+
readonly maximum: number | null;
|
|
21
|
+
/** Flags that surface offers, declared by the source rather than by the value. */
|
|
22
|
+
readonly flags: readonly {
|
|
23
|
+
readonly key: string;
|
|
24
|
+
readonly label: string;
|
|
25
|
+
readonly description: string;
|
|
26
|
+
readonly fallback: boolean;
|
|
27
|
+
}[];
|
|
28
|
+
readonly origin: "default" | "stored" | "engine";
|
|
29
|
+
readonly application: "live" | "restart" | "engine";
|
|
30
|
+
}
|
|
31
|
+
export interface OwnedUiSettingsSection {
|
|
32
|
+
readonly id: string;
|
|
33
|
+
readonly title: string;
|
|
34
|
+
readonly entries: readonly OwnedUiSettingsEntry[];
|
|
35
|
+
/** Set when the section could not be built; entries is then empty. */
|
|
36
|
+
readonly unavailableReason: string | null;
|
|
37
|
+
/** Set when the section is present but nothing in it can be changed here. */
|
|
38
|
+
readonly readOnlyReason: string | null;
|
|
39
|
+
}
|
|
40
|
+
export interface AgentSettingsSnapshot {
|
|
41
|
+
readonly descriptors: readonly {
|
|
42
|
+
readonly key: string;
|
|
43
|
+
readonly valueType: "boolean" | "number" | "string" | "enum" | "json";
|
|
44
|
+
readonly writable: boolean;
|
|
45
|
+
readonly choices?: readonly unknown[];
|
|
46
|
+
readonly label?: string;
|
|
47
|
+
readonly description?: string;
|
|
48
|
+
readonly minimum?: number;
|
|
49
|
+
readonly maximum?: number;
|
|
50
|
+
readonly flags?: readonly {
|
|
51
|
+
readonly key: string;
|
|
52
|
+
readonly label: string;
|
|
53
|
+
readonly description: string;
|
|
54
|
+
readonly fallback: boolean;
|
|
55
|
+
}[];
|
|
56
|
+
}[];
|
|
57
|
+
readonly values: Readonly<Record<string, unknown>>;
|
|
58
|
+
/** Whether the engine advertises settings write capability at all. */
|
|
59
|
+
readonly writeAdvertised: boolean;
|
|
60
|
+
/** Set when the engine could not report its settings. */
|
|
61
|
+
readonly failure: string | null;
|
|
62
|
+
}
|
|
63
|
+
export interface BuildOwnedUiSettingsSectionsInput {
|
|
64
|
+
readonly resolution: OwnedUiSettingsResolution;
|
|
65
|
+
/** Null when no engine is attached, which is not a failure. */
|
|
66
|
+
readonly agent: AgentSettingsSnapshot | null;
|
|
67
|
+
}
|
|
68
|
+
export declare const AGENT_SECTION_ID = "agent";
|
|
69
|
+
export declare function buildOwnedUiSettingsSections(input: BuildOwnedUiSettingsSectionsInput): readonly OwnedUiSettingsSection[];
|
|
70
|
+
export declare function findOwnedUiSettingsEntry(sections: readonly OwnedUiSettingsSection[], id: string, backend: OwnedUiSettingsBackend): OwnedUiSettingsEntry | null;
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export const AGENT_SECTION_ID = "agent";
|
|
2
|
+
const BOOLEAN_CHOICES = Object.freeze([true, false]);
|
|
3
|
+
export function buildOwnedUiSettingsSections(input) {
|
|
4
|
+
const ownedSection = {
|
|
5
|
+
id: "a1",
|
|
6
|
+
title: "A1",
|
|
7
|
+
entries: Object.freeze(input.resolution.settings.map(setting => ({
|
|
8
|
+
id: setting.declaration.id,
|
|
9
|
+
label: null,
|
|
10
|
+
backend: "a1",
|
|
11
|
+
description: setting.declaration.description,
|
|
12
|
+
value: setting.value,
|
|
13
|
+
rawValue: setting.value,
|
|
14
|
+
editable: true,
|
|
15
|
+
structured: false,
|
|
16
|
+
minimum: null,
|
|
17
|
+
maximum: null,
|
|
18
|
+
flags: [],
|
|
19
|
+
choices: setting.declaration.allowedValues,
|
|
20
|
+
origin: setting.source,
|
|
21
|
+
application: setting.declaration.application,
|
|
22
|
+
}))),
|
|
23
|
+
unavailableReason: null,
|
|
24
|
+
readOnlyReason: null,
|
|
25
|
+
};
|
|
26
|
+
return Object.freeze([ownedSection, agentSection(input.agent)]);
|
|
27
|
+
}
|
|
28
|
+
export function findOwnedUiSettingsEntry(sections, id, backend) {
|
|
29
|
+
for (const section of sections) {
|
|
30
|
+
const entry = section.entries.find(candidate => candidate.id === id && candidate.backend === backend);
|
|
31
|
+
if (entry)
|
|
32
|
+
return entry;
|
|
33
|
+
}
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
function agentSection(snapshot) {
|
|
37
|
+
if (snapshot === null) {
|
|
38
|
+
return frozenSection("Agent settings are unavailable because no agent engine is attached", null, []);
|
|
39
|
+
}
|
|
40
|
+
if (snapshot.failure !== null) {
|
|
41
|
+
return frozenSection(`Agent settings are unavailable: ${snapshot.failure}`, null, []);
|
|
42
|
+
}
|
|
43
|
+
if (snapshot.descriptors.length === 0) {
|
|
44
|
+
return frozenSection("The agent engine reported no settings", null, []);
|
|
45
|
+
}
|
|
46
|
+
const entries = snapshot.descriptors.map(descriptor => {
|
|
47
|
+
const raw = Object.hasOwn(snapshot.values, descriptor.key) ? snapshot.values[descriptor.key] : null;
|
|
48
|
+
return {
|
|
49
|
+
id: descriptor.key,
|
|
50
|
+
label: descriptor.label ?? null,
|
|
51
|
+
backend: "agent",
|
|
52
|
+
description: descriptor.description ?? null,
|
|
53
|
+
value: scalar(raw),
|
|
54
|
+
rawValue: raw,
|
|
55
|
+
// A structured value is editable through its own surface rather than a
|
|
56
|
+
// value menu, so it stays reachable instead of being reported as fixed.
|
|
57
|
+
editable: snapshot.writeAdvertised && descriptor.writable,
|
|
58
|
+
structured: descriptor.valueType === "json",
|
|
59
|
+
minimum: descriptor.minimum ?? null,
|
|
60
|
+
maximum: descriptor.maximum ?? null,
|
|
61
|
+
flags: descriptor.flags ?? [],
|
|
62
|
+
// A boolean is a two-value choice even when the engine names no choices,
|
|
63
|
+
// so it opens the same menu as any other enumerated setting.
|
|
64
|
+
choices: descriptor.valueType === "boolean" ? BOOLEAN_CHOICES : choicesOf(descriptor.choices),
|
|
65
|
+
origin: "engine",
|
|
66
|
+
application: "engine",
|
|
67
|
+
};
|
|
68
|
+
});
|
|
69
|
+
const readOnlyReason = snapshot.writeAdvertised
|
|
70
|
+
? (entries.some(entry => entry.editable)
|
|
71
|
+
? null
|
|
72
|
+
: "The agent engine reports no writable settings")
|
|
73
|
+
: "The agent engine does not support changing settings from this surface";
|
|
74
|
+
return {
|
|
75
|
+
id: AGENT_SECTION_ID,
|
|
76
|
+
title: "Agent",
|
|
77
|
+
entries: Object.freeze(entries),
|
|
78
|
+
unavailableReason: null,
|
|
79
|
+
readOnlyReason,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
function frozenSection(unavailableReason, readOnlyReason, entries) {
|
|
83
|
+
return { id: AGENT_SECTION_ID, title: "Agent", entries: Object.freeze(entries), unavailableReason, readOnlyReason };
|
|
84
|
+
}
|
|
85
|
+
function scalar(value) {
|
|
86
|
+
return typeof value === "string" || typeof value === "number" || typeof value === "boolean" ? value : null;
|
|
87
|
+
}
|
|
88
|
+
function choicesOf(choices) {
|
|
89
|
+
if (choices === undefined)
|
|
90
|
+
return null;
|
|
91
|
+
const scalars = choices.map(scalar).filter((choice) => choice !== null);
|
|
92
|
+
return scalars.length === choices.length ? Object.freeze(scalars) : null;
|
|
93
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { AgentSettingsPort } from "../agent-engine-contracts/index.js";
|
|
2
|
+
import type { OwnedUiSettingValue } from "./declarations.js";
|
|
3
|
+
import type { OwnedUiSettingsResolution } from "./resolution.js";
|
|
4
|
+
import { type OwnedUiSettingsBackend, type OwnedUiSettingsSection } from "./sections.js";
|
|
5
|
+
import type { OwnedUiSettingsStore } from "./store.js";
|
|
6
|
+
export interface OwnedUiSettingsChangeOutcome {
|
|
7
|
+
readonly applied: boolean;
|
|
8
|
+
/** True when the value is stored but only takes effect on the next start. */
|
|
9
|
+
readonly pendingRestart: boolean;
|
|
10
|
+
/** Present when the change could not be persisted; the surface must not show it as saved. */
|
|
11
|
+
readonly failure: string | null;
|
|
12
|
+
}
|
|
13
|
+
export interface OwnedUiSettingsSessionOptions {
|
|
14
|
+
readonly store: OwnedUiSettingsStore;
|
|
15
|
+
/** Null when no engine is attached; the Agent section then reports itself unavailable. */
|
|
16
|
+
readonly agent?: AgentSettingsPort | null;
|
|
17
|
+
/**
|
|
18
|
+
* Resolves the port at load time instead of construction time, for an engine
|
|
19
|
+
* whose runtime is not up yet. Takes precedence over `agent`.
|
|
20
|
+
*/
|
|
21
|
+
readonly agentProvider?: () => AgentSettingsPort | null;
|
|
22
|
+
}
|
|
23
|
+
export type OwnedUiSettingsListener = (session: OwnedUiSettingsSession) => void;
|
|
24
|
+
/**
|
|
25
|
+
* Holds the resolved settings for one owned UI session and routes every accepted
|
|
26
|
+
* change to the backend that owns it: A1 settings to the A1 document, agent
|
|
27
|
+
* settings to the engine settings port. Neither backend ever sees the other's value.
|
|
28
|
+
*/
|
|
29
|
+
export declare class OwnedUiSettingsSession {
|
|
30
|
+
#private;
|
|
31
|
+
constructor(options: OwnedUiSettingsSessionOptions);
|
|
32
|
+
get resolution(): OwnedUiSettingsResolution;
|
|
33
|
+
/** Reads the engine's settings so the Agent section can be built. Never throws. */
|
|
34
|
+
load(): Promise<void>;
|
|
35
|
+
sections(): readonly OwnedUiSettingsSection[];
|
|
36
|
+
/** Resolved value of an A1 setting, or null when it is not declared. */
|
|
37
|
+
value(id: string): OwnedUiSettingValue | null;
|
|
38
|
+
/** Value stored this session but not yet in effect, for a restart-required setting. */
|
|
39
|
+
pendingValue(id: string): OwnedUiSettingValue | null;
|
|
40
|
+
onChange(listener: OwnedUiSettingsListener): () => void;
|
|
41
|
+
/** Writes a structured value, which only an engine-backed setting can hold. */
|
|
42
|
+
changeStructured(backend: OwnedUiSettingsBackend, id: string, value: Readonly<Record<string, unknown>>): Promise<OwnedUiSettingsChangeOutcome>;
|
|
43
|
+
change(backend: OwnedUiSettingsBackend, id: string, value: OwnedUiSettingValue): Promise<OwnedUiSettingsChangeOutcome>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import { buildOwnedUiSettingsSections, findOwnedUiSettingsEntry, } from "./sections.js";
|
|
2
|
+
/**
|
|
3
|
+
* Holds the resolved settings for one owned UI session and routes every accepted
|
|
4
|
+
* change to the backend that owns it: A1 settings to the A1 document, agent
|
|
5
|
+
* settings to the engine settings port. Neither backend ever sees the other's value.
|
|
6
|
+
*/
|
|
7
|
+
export class OwnedUiSettingsSession {
|
|
8
|
+
#store;
|
|
9
|
+
#agent;
|
|
10
|
+
#agentProvider;
|
|
11
|
+
#listeners = new Set();
|
|
12
|
+
#resolution;
|
|
13
|
+
#agentSnapshot = null;
|
|
14
|
+
#pending = new Map();
|
|
15
|
+
constructor(options) {
|
|
16
|
+
this.#store = options.store;
|
|
17
|
+
this.#agent = options.agent ?? null;
|
|
18
|
+
this.#agentProvider = options.agentProvider ?? null;
|
|
19
|
+
this.#resolution = options.store.read();
|
|
20
|
+
}
|
|
21
|
+
get resolution() {
|
|
22
|
+
return this.#resolution;
|
|
23
|
+
}
|
|
24
|
+
/** Reads the engine's settings so the Agent section can be built. Never throws. */
|
|
25
|
+
async load() {
|
|
26
|
+
this.#resolution = this.#store.read();
|
|
27
|
+
const agent = this.#agentProvider === null ? this.#agent : this.#agentProvider();
|
|
28
|
+
this.#agentSnapshot = agent === null ? null : await snapshotOf(agent);
|
|
29
|
+
this.#notify();
|
|
30
|
+
}
|
|
31
|
+
sections() {
|
|
32
|
+
return buildOwnedUiSettingsSections({ resolution: this.#resolution, agent: this.#agentSnapshot });
|
|
33
|
+
}
|
|
34
|
+
/** Resolved value of an A1 setting, or null when it is not declared. */
|
|
35
|
+
value(id) {
|
|
36
|
+
return this.#resolution.settings.find(setting => setting.declaration.id === id)?.value ?? null;
|
|
37
|
+
}
|
|
38
|
+
/** Value stored this session but not yet in effect, for a restart-required setting. */
|
|
39
|
+
pendingValue(id) {
|
|
40
|
+
return this.#pending.get(id) ?? null;
|
|
41
|
+
}
|
|
42
|
+
onChange(listener) {
|
|
43
|
+
this.#listeners.add(listener);
|
|
44
|
+
return () => this.#listeners.delete(listener);
|
|
45
|
+
}
|
|
46
|
+
/** Writes a structured value, which only an engine-backed setting can hold. */
|
|
47
|
+
async changeStructured(backend, id, value) {
|
|
48
|
+
if (backend !== "agent")
|
|
49
|
+
return failed("only an agent setting holds a structured value");
|
|
50
|
+
const agent = this.#agentProvider === null ? this.#agent : this.#agentProvider();
|
|
51
|
+
if (agent === null)
|
|
52
|
+
return failed("no agent engine is attached");
|
|
53
|
+
if (!agent.capabilities.write || !agent.writeSetting) {
|
|
54
|
+
return failed("the agent engine does not support changing settings from this surface");
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await agent.writeSetting(id, value);
|
|
58
|
+
if (agent.capabilities.flush && agent.flush)
|
|
59
|
+
await agent.flush();
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
return failed(`${id} could not be written to the agent engine: ${describe(error)}`);
|
|
63
|
+
}
|
|
64
|
+
this.#agentSnapshot = await snapshotOf(agent);
|
|
65
|
+
this.#notify();
|
|
66
|
+
return { applied: true, pendingRestart: false, failure: null };
|
|
67
|
+
}
|
|
68
|
+
async change(backend, id, value) {
|
|
69
|
+
const entry = findOwnedUiSettingsEntry(this.sections(), id, backend);
|
|
70
|
+
if (entry === null)
|
|
71
|
+
return failed(`unknown ${backend} setting: ${id}`);
|
|
72
|
+
if (!entry.editable)
|
|
73
|
+
return failed(`${id} is not editable from this surface`);
|
|
74
|
+
return backend === "a1" ? this.#changeOwned(id, value) : await this.#changeAgent(id, value);
|
|
75
|
+
}
|
|
76
|
+
#changeOwned(id, value) {
|
|
77
|
+
const outcome = this.#store.write(this.#resolution, id, value);
|
|
78
|
+
if (!outcome.stored)
|
|
79
|
+
return failed(outcome.failure ?? `${id} could not be stored`);
|
|
80
|
+
const previous = this.#resolution;
|
|
81
|
+
this.#resolution = this.#store.read();
|
|
82
|
+
const declaration = previous.settings.find(setting => setting.declaration.id === id)?.declaration;
|
|
83
|
+
if (declaration?.application === "restart") {
|
|
84
|
+
this.#pending.set(id, value);
|
|
85
|
+
this.#resolution = previous;
|
|
86
|
+
this.#notify();
|
|
87
|
+
return { applied: false, pendingRestart: true, failure: null };
|
|
88
|
+
}
|
|
89
|
+
this.#pending.delete(id);
|
|
90
|
+
this.#notify();
|
|
91
|
+
return { applied: true, pendingRestart: false, failure: null };
|
|
92
|
+
}
|
|
93
|
+
async #changeAgent(id, value) {
|
|
94
|
+
const agent = this.#agentProvider === null ? this.#agent : this.#agentProvider();
|
|
95
|
+
if (agent === null)
|
|
96
|
+
return failed("no agent engine is attached");
|
|
97
|
+
if (!agent.capabilities.write || !agent.writeSetting) {
|
|
98
|
+
return failed("the agent engine does not support changing settings from this surface");
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
await agent.writeSetting(id, value);
|
|
102
|
+
if (agent.capabilities.flush && agent.flush)
|
|
103
|
+
await agent.flush();
|
|
104
|
+
}
|
|
105
|
+
catch (error) {
|
|
106
|
+
return failed(`${id} could not be written to the agent engine: ${describe(error)}`);
|
|
107
|
+
}
|
|
108
|
+
this.#agentSnapshot = await snapshotOf(agent);
|
|
109
|
+
this.#notify();
|
|
110
|
+
return { applied: true, pendingRestart: false, failure: null };
|
|
111
|
+
}
|
|
112
|
+
#notify() {
|
|
113
|
+
for (const listener of this.#listeners)
|
|
114
|
+
listener(this);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
async function snapshotOf(agent) {
|
|
118
|
+
try {
|
|
119
|
+
const descriptors = await agent.listSettings();
|
|
120
|
+
const values = {};
|
|
121
|
+
for (const descriptor of descriptors) {
|
|
122
|
+
try {
|
|
123
|
+
values[descriptor.key] = await agent.readSetting(descriptor.key) ?? null;
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
values[descriptor.key] = null;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
return {
|
|
130
|
+
descriptors,
|
|
131
|
+
values,
|
|
132
|
+
writeAdvertised: agent.capabilities.write && typeof agent.writeSetting === "function",
|
|
133
|
+
failure: null,
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
catch (error) {
|
|
137
|
+
return { descriptors: [], values: {}, writeAdvertised: false, failure: describe(error) };
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function failed(failure) {
|
|
141
|
+
return { applied: false, pendingRestart: false, failure };
|
|
142
|
+
}
|
|
143
|
+
function describe(error) {
|
|
144
|
+
return error instanceof Error ? error.message : String(error);
|
|
145
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type OwnedUiSettingDeclaration, type OwnedUiSettingValue } from "./declarations.js";
|
|
2
|
+
import { type OwnedUiSettingsMigration } from "./migrations.js";
|
|
3
|
+
import { type OwnedUiSettingsResolution } from "./resolution.js";
|
|
4
|
+
export interface OwnedUiSettingsStoreOptions {
|
|
5
|
+
/** A1 configuration root. Settings live under `<configDir>/settings/`. */
|
|
6
|
+
readonly configDir: string;
|
|
7
|
+
readonly profileId: string;
|
|
8
|
+
readonly declarations?: readonly OwnedUiSettingDeclaration[];
|
|
9
|
+
readonly migrations?: readonly OwnedUiSettingsMigration[];
|
|
10
|
+
}
|
|
11
|
+
export interface OwnedUiSettingsWriteOutcome {
|
|
12
|
+
readonly stored: boolean;
|
|
13
|
+
/** Present when the write failed; the caller must not report the change as saved. */
|
|
14
|
+
readonly failure: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare class OwnedUiSettingsStore {
|
|
17
|
+
#private;
|
|
18
|
+
constructor(options: OwnedUiSettingsStoreOptions);
|
|
19
|
+
get file(): string;
|
|
20
|
+
/** Reads and resolves. Never throws: every failure becomes a notice. */
|
|
21
|
+
read(): OwnedUiSettingsResolution;
|
|
22
|
+
/**
|
|
23
|
+
* Writes the resolved form with `id` set to `value`, preserving undeclared keys.
|
|
24
|
+
* Atomic: a temporary sibling is renamed over the target, so an interrupted
|
|
25
|
+
* write leaves either the complete previous document or the complete new one.
|
|
26
|
+
*/
|
|
27
|
+
write(resolution: OwnedUiSettingsResolution, id: string, value: OwnedUiSettingValue): OwnedUiSettingsWriteOutcome;
|
|
28
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { OWNED_UI_SETTINGS_VERSION, OWNED_UI_SETTING_DECLARATIONS, } from "./declarations.js";
|
|
4
|
+
import { OWNED_UI_SETTINGS_MIGRATIONS } from "./migrations.js";
|
|
5
|
+
import { documentFrom, parseOwnedUiSettingsDocument, resolveOwnedUiSettings, } from "./resolution.js";
|
|
6
|
+
const PROFILE_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;
|
|
7
|
+
const MAX_DOCUMENT_BYTES = 256 * 1024;
|
|
8
|
+
export class OwnedUiSettingsStore {
|
|
9
|
+
#file;
|
|
10
|
+
#declarations;
|
|
11
|
+
#migrations;
|
|
12
|
+
constructor(options) {
|
|
13
|
+
if (!PROFILE_ID_PATTERN.test(options.profileId)) {
|
|
14
|
+
throw new Error(`owned UI settings profile id is not a bounded slug: ${options.profileId}`);
|
|
15
|
+
}
|
|
16
|
+
this.#file = path.join(path.resolve(options.configDir), "settings", `${options.profileId}.json`);
|
|
17
|
+
this.#declarations = options.declarations ?? OWNED_UI_SETTING_DECLARATIONS;
|
|
18
|
+
this.#migrations = options.migrations ?? OWNED_UI_SETTINGS_MIGRATIONS;
|
|
19
|
+
}
|
|
20
|
+
get file() {
|
|
21
|
+
return this.#file;
|
|
22
|
+
}
|
|
23
|
+
/** Reads and resolves. Never throws: every failure becomes a notice. */
|
|
24
|
+
read() {
|
|
25
|
+
let raw = null;
|
|
26
|
+
let unreadable = null;
|
|
27
|
+
try {
|
|
28
|
+
raw = readFileSync(this.#file, "utf8");
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
if (!isMissing(error))
|
|
32
|
+
unreadable = `${this.#file} could not be read: ${describe(error)}`;
|
|
33
|
+
}
|
|
34
|
+
if (raw !== null && Buffer.byteLength(raw, "utf8") > MAX_DOCUMENT_BYTES) {
|
|
35
|
+
unreadable = `${this.#file} exceeds the ${MAX_DOCUMENT_BYTES}-byte settings limit and was ignored`;
|
|
36
|
+
raw = null;
|
|
37
|
+
}
|
|
38
|
+
const document = raw === null ? null : parseOwnedUiSettingsDocument(raw);
|
|
39
|
+
if (raw !== null && document === null && unreadable === null) {
|
|
40
|
+
unreadable = `${this.#file} is not a valid settings document and was ignored`;
|
|
41
|
+
}
|
|
42
|
+
return resolveOwnedUiSettings({
|
|
43
|
+
declarations: this.#declarations,
|
|
44
|
+
migrations: this.#migrations,
|
|
45
|
+
document,
|
|
46
|
+
...(unreadable === null ? {} : { unreadableDetail: unreadable }),
|
|
47
|
+
currentVersion: OWNED_UI_SETTINGS_VERSION,
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Writes the resolved form with `id` set to `value`, preserving undeclared keys.
|
|
52
|
+
* Atomic: a temporary sibling is renamed over the target, so an interrupted
|
|
53
|
+
* write leaves either the complete previous document or the complete new one.
|
|
54
|
+
*/
|
|
55
|
+
write(resolution, id, value) {
|
|
56
|
+
const declaration = this.#declarations.find(candidate => candidate.id === id);
|
|
57
|
+
if (!declaration)
|
|
58
|
+
return { stored: false, failure: `unknown owned UI setting: ${id}` };
|
|
59
|
+
if (!declaration.allowedValues.includes(value)) {
|
|
60
|
+
return { stored: false, failure: `value ${JSON.stringify(value)} is not allowed for ${id}` };
|
|
61
|
+
}
|
|
62
|
+
const current = documentFrom(resolution);
|
|
63
|
+
const next = {
|
|
64
|
+
version: OWNED_UI_SETTINGS_VERSION,
|
|
65
|
+
values: { ...current.values, [id]: value },
|
|
66
|
+
};
|
|
67
|
+
const temporary = `${this.#file}.${process.pid}.tmp`;
|
|
68
|
+
try {
|
|
69
|
+
mkdirSync(path.dirname(this.#file), { recursive: true, mode: 0o700 });
|
|
70
|
+
writeFileSync(temporary, `${JSON.stringify(next, null, 2)}\n`, { encoding: "utf8", mode: 0o600 });
|
|
71
|
+
renameSync(temporary, this.#file);
|
|
72
|
+
return { stored: true, failure: null };
|
|
73
|
+
}
|
|
74
|
+
catch (error) {
|
|
75
|
+
try {
|
|
76
|
+
rmSync(temporary, { force: true });
|
|
77
|
+
}
|
|
78
|
+
catch {
|
|
79
|
+
// A leftover temporary file is inert: read() only ever opens the target path.
|
|
80
|
+
}
|
|
81
|
+
return { stored: false, failure: `${this.#file} could not be written: ${describe(error)}` };
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function isMissing(error) {
|
|
86
|
+
return typeof error === "object" && error !== null && error.code === "ENOENT";
|
|
87
|
+
}
|
|
88
|
+
function describe(error) {
|
|
89
|
+
return error instanceof Error ? error.message : String(error);
|
|
90
|
+
}
|
|
@@ -3,6 +3,7 @@ export * from "./conformance.js";
|
|
|
3
3
|
export * from "./shell-components.js";
|
|
4
4
|
export * from "./theme.js";
|
|
5
5
|
export * from "./upstream/theme/theme-controller.js";
|
|
6
|
+
export { getAvailablePiThemes } from "./upstream/theme/theme.js";
|
|
6
7
|
export * from "./upstream/components/countdown-timer.js";
|
|
7
8
|
export * from "./upstream/components/extension-editor.js";
|
|
8
9
|
export * from "./upstream/components/session-selector.js";
|
|
@@ -3,6 +3,7 @@ export * from "./conformance.js";
|
|
|
3
3
|
export * from "./shell-components.js";
|
|
4
4
|
export * from "./theme.js";
|
|
5
5
|
export * from "./upstream/theme/theme-controller.js";
|
|
6
|
+
export { getAvailablePiThemes } from "./upstream/theme/theme.js";
|
|
6
7
|
export * from "./upstream/components/countdown-timer.js";
|
|
7
8
|
export * from "./upstream/components/extension-editor.js";
|
|
8
9
|
export * from "./upstream/components/session-selector.js";
|
|
@@ -93,7 +93,15 @@ export declare function createPiShellDaxnuts(runtime: Pick<PiShellEditorOptions,
|
|
|
93
93
|
export declare function createPiShellEarendilAnnouncement(): PiShellComponentPort;
|
|
94
94
|
export declare function createPiShellOperationLoader(runtime: Pick<PiShellEditorOptions, "getColumns" | "getRows" | "requestRender">, message: string): PiShellComponentPort;
|
|
95
95
|
export declare function createPiShellReloadBox(): PiShellComponentPort;
|
|
96
|
-
export
|
|
96
|
+
export interface PiShellAuthProviderOption extends PiShellSelectorOption {
|
|
97
|
+
readonly providerId: string;
|
|
98
|
+
readonly authType: "oauth" | "api_key";
|
|
99
|
+
readonly status?: {
|
|
100
|
+
readonly type: "oauth" | "api_key";
|
|
101
|
+
readonly source?: string;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
export declare function createPiShellAuthProviderSelector(mode: "login" | "logout", providers: readonly PiShellAuthProviderOption[], onSelect: (id: string) => void, onCancel: () => void): PiShellComponentPort;
|
|
97
105
|
export declare function createPiShellExtensionSelector(title: string, options: readonly string[], onSelect: (value: string) => void, onCancel: () => void): PiShellComponentPort;
|
|
98
106
|
export declare function createPiShellThinkingSelector(currentLevel: "off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max", availableLevels: readonly ("off" | "minimal" | "low" | "medium" | "high" | "xhigh" | "max")[], onSelect: (level: string) => void, onCancel: () => void): PiShellComponentPort;
|
|
99
107
|
export declare function createPiShellThemeSelector(currentTheme: string, onSelect: (theme: string) => void, onCancel: () => void, onPreview: (theme: string) => void): PiShellComponentPort;
|