@timurproko/a1 0.1.1-dev.1 → 0.1.1-dev.11
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 +8 -43
- package/bin/guardian.js +22 -0
- package/bin/{a1-ui.js → ui.js} +4 -8
- package/dist/native/darwin-arm64/manifest.json +20 -0
- package/dist/native/darwin-arm64/process-guardian +0 -0
- package/dist/native/linux-x64/manifest.json +20 -0
- package/dist/native/linux-x64/process-guardian +0 -0
- package/dist/native/win32-x64/manifest.json +20 -0
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/src/composition/index.d.ts +26 -0
- package/dist/src/composition/index.js +94 -2
- package/dist/src/features/launch/initialize-profile.js +23 -2
- package/dist/src/features/launch/profiles.d.ts +1 -1
- package/dist/src/features/launch/profiles.js +2 -2
- package/dist/src/features/launch/runtime-selection.d.ts +13 -8
- package/dist/src/features/launch/runtime-selection.js +6 -6
- 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 +633 -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-component-adapter/upstream/theme/theme.d.ts +8 -0
- package/dist/src/foundation/pi-component-adapter/upstream/theme/theme.js +12 -0
- package/dist/src/foundation/pi-engine-adapter/adapter.d.ts +17 -3
- package/dist/src/foundation/pi-engine-adapter/adapter.js +80 -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 +40 -2
- package/dist/src/foundation/pi-engine-adapter/settings-integration.js +172 -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.d.ts +2 -2
- package/dist/src/foundation/release/bootstrap.js +69 -18
- 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/concurrency.d.ts +1 -0
- package/dist/src/foundation/release/concurrency.js +17 -0
- 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/release-store.d.ts +35 -2
- package/dist/src/foundation/release/release-store.js +90 -31
- package/dist/src/foundation/release/release.d.ts +15 -0
- package/dist/src/foundation/release/release.js +65 -36
- package/dist/src/foundation/release/update.d.ts +19 -2
- package/dist/src/foundation/release/update.js +132 -16
- 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/main.js +6 -5
- package/dist/src/foundation/supervision/server.d.ts +4 -2
- package/dist/src/foundation/supervision/server.js +254 -87
- 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 +23 -0
- package/dist/src/foundation/ui-components/theme.js +13 -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 +8 -5
- package/docs/architecture/boundaries.md +31 -13
- package/docs/architecture/process-guardian-provenance.md +26 -0
- package/docs/architecture/toolchain.md +9 -3
- package/docs/architecture/ui-reference-provenance.md +50 -0
- package/docs/ci-release-runbook.md +67 -0
- package/docs/features/launch-profiles.md +7 -1
- package/docs/manual-launch-instance-acceptance.md +66 -0
- package/docs/manual-terminal-colour-check.md +55 -0
- package/package.json +20 -14
- package/dist/src/composition/transparent-runtime.d.ts +0 -6
- package/dist/src/composition/transparent-runtime.js +0 -19
- package/dist/src/foundation/transparent-terminal/command-resolution.d.ts +0 -13
- package/dist/src/foundation/transparent-terminal/command-resolution.js +0 -69
- package/dist/src/foundation/transparent-terminal/foreground-broker.d.ts +0 -32
- package/dist/src/foundation/transparent-terminal/foreground-broker.js +0 -87
- package/dist/src/foundation/transparent-terminal/index.d.ts +0 -4
- package/dist/src/foundation/transparent-terminal/index.js +0 -4
- package/dist/src/foundation/transparent-terminal/main.d.ts +0 -9
- package/dist/src/foundation/transparent-terminal/main.js +0 -94
- package/dist/src/foundation/transparent-terminal/native-launcher.d.ts +0 -25
- package/dist/src/foundation/transparent-terminal/native-launcher.js +0 -146
- /package/bin/{a1.js → cli.js} +0 -0
- /package/bin/{a1-supervisor.js → supervisor.js} +0 -0
package/README.md
CHANGED
|
@@ -1,20 +1,11 @@
|
|
|
1
1
|
# A1
|
|
2
2
|
|
|
3
|
-
A1 is a terminal-native agent launcher for Windows, Linux, and macOS. Bare `a1` runs the A1-owned Pi-compatible UI, while explicit fallback profiles can launch untouched Pi directly. A1 also manages release selection, process ownership, and updates.
|
|
4
|
-
|
|
5
3
|
## Install
|
|
6
4
|
|
|
7
|
-
Requirements:
|
|
8
|
-
|
|
9
|
-
- Node.js 22.19 through 24.x
|
|
10
|
-
- npm 11
|
|
11
|
-
|
|
12
5
|
```sh
|
|
13
6
|
npm install --global @timurproko/a1@latest
|
|
14
7
|
```
|
|
15
8
|
|
|
16
|
-
The package installs only the `a1` command.
|
|
17
|
-
|
|
18
9
|
## Commands
|
|
19
10
|
|
|
20
11
|
```sh
|
|
@@ -26,45 +17,19 @@ a1 update # update to npm latest
|
|
|
26
17
|
a1 update:next # update to npm next
|
|
27
18
|
```
|
|
28
19
|
|
|
29
|
-
Bare `a1` owns its Pi-compatible TUI composition and uses the public Pi engine, components, and terminal APIs. It does not insert a PTY or terminal-byte relay. Default visuals and workflows track the pinned vanilla Pi baseline; A1-specific visual customization and structured tabs remain disabled.
|
|
30
|
-
|
|
31
|
-
`a1 pi` is the untouched upstream fallback and comparison oracle. Use it to distinguish A1-owned UI problems from upstream Pi, profile, provider, or terminal problems. The `a1 ui` subcommand was removed and is not a compatibility alias; run bare `a1` for the owned UI.
|
|
32
|
-
|
|
33
|
-
`a1 sandbox` is unchanged: it launches vanilla Pi with isolated Pi configuration and resources. “Sandbox” does not mean operating-system, filesystem, process, network, or credential security isolation. See [`docs/features/launch-profiles.md`](docs/features/launch-profiles.md) for first-run directories, independent `/login`, trust behavior, extension placement, and recovery.
|
|
34
|
-
|
|
35
20
|
## Develop
|
|
36
21
|
|
|
37
22
|
```sh
|
|
38
|
-
npm ci
|
|
39
|
-
npm run build
|
|
40
|
-
npm start
|
|
23
|
+
npm ci # install exact locked dependencies
|
|
24
|
+
npm run build # compile TypeScript and the process guardian into dist
|
|
25
|
+
npm start # build and launch an isolated development instance
|
|
26
|
+
npm run test:fast # typecheck + fast suite, no build needed
|
|
27
|
+
npm test # same as test:fast
|
|
28
|
+
npm run test:full # complete non-physical suite
|
|
41
29
|
```
|
|
42
30
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
A1 control state uses `%APPDATA%\\A1` and `%LOCALAPPDATA%\\A1` on Windows, and the `a1` directory under XDG config/data/runtime roots on Unix. Override it only with declared `A1_*` variables such as `A1_CONFIG_DIR`, `A1_DATA_DIR`, `A1_RUNTIME_DIR`, `A1_DATABASE_PATH`, and `A1_ENDPOINT`. Pi profile roots remain `~/.a1/agent`, `~/.pi/agent`, and `~/.a1/sandbox`. This is a no-migration identity hard cut; see [`docs/architecture/toolchain.md`](docs/architecture/toolchain.md#identity-hard-cut-and-cleanup) before removing obsolete control state.
|
|
46
|
-
|
|
47
|
-
Run the non-desktop gates with:
|
|
31
|
+
## Release
|
|
48
32
|
|
|
49
33
|
```sh
|
|
50
|
-
npm run
|
|
51
|
-
npm run check:architecture
|
|
52
|
-
npm run check:deprecated
|
|
53
|
-
npm test
|
|
54
|
-
npm run test:release
|
|
34
|
+
npm run release:next # publish current develop tip to npm next via trusted CI workflows
|
|
55
35
|
```
|
|
56
|
-
|
|
57
|
-
Automated physical-terminal interaction must never run on an active workstation. Future physical certification may run only on dedicated disposable workers or VMs with exclusive test desktops.
|
|
58
|
-
|
|
59
|
-
## Releases
|
|
60
|
-
|
|
61
|
-
An exact manually accepted `-dev.N` candidate may publish under npm tag `next` after applicable non-desktop gates pass. Such a preview is explicitly uncertified, cannot move `latest`, and cannot claim stable terminal parity or platform support. Stable claims require deferred physical and cross-platform certification against the exact package.
|
|
62
|
-
|
|
63
|
-
Trusted preview publication uses `.github/workflows/publish-next.yml` and npm provenance. Local release mechanics are documented in [`docs/architecture/toolchain.md`](docs/architecture/toolchain.md).
|
|
64
|
-
|
|
65
|
-
## Architecture
|
|
66
|
-
|
|
67
|
-
- [`docs/architecture/boundaries.md`](docs/architecture/boundaries.md)
|
|
68
|
-
- [`docs/architecture/toolchain.md`](docs/architecture/toolchain.md)
|
|
69
|
-
- [`docs/manual-transparent-checkpoint.md`](docs/manual-transparent-checkpoint.md)
|
|
70
|
-
- [`docs/features/launch-profiles.md`](docs/features/launch-profiles.md)
|
package/bin/guardian.js
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { fileURLToPath } = await import("node:url");
|
|
4
|
+
const { resolve } = await import("node:path");
|
|
5
|
+
const { runLaunchGuardian } = await import("../dist/src/foundation/launch-guardian/index.js");
|
|
6
|
+
|
|
7
|
+
const releaseRoot = process.env.A1_RELEASE_ROOT ?? fileURLToPath(new URL("..", import.meta.url));
|
|
8
|
+
const profileId = process.env.A1_LAUNCH_PROFILE ?? "a1";
|
|
9
|
+
|
|
10
|
+
runLaunchGuardian({
|
|
11
|
+
profileId,
|
|
12
|
+
releaseRoot,
|
|
13
|
+
uiEntry: resolve(releaseRoot, "bin", "ui.js"),
|
|
14
|
+
environment: process.env,
|
|
15
|
+
cwd: process.cwd(),
|
|
16
|
+
}).then(
|
|
17
|
+
code => { process.exitCode = code; },
|
|
18
|
+
error => {
|
|
19
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
20
|
+
process.exitCode = 1;
|
|
21
|
+
},
|
|
22
|
+
);
|
package/bin/{a1-ui.js → ui.js}
RENAMED
|
@@ -3,17 +3,13 @@
|
|
|
3
3
|
const { runSelectedInteractiveRuntime } = await import("../dist/src/features/launch/index.js");
|
|
4
4
|
|
|
5
5
|
runSelectedInteractiveRuntime(process.env.A1_LAUNCH_PROFILE ?? "a1", {
|
|
6
|
-
ownedUi: async () => {
|
|
7
|
-
const [{ runOwnedUi }, {
|
|
6
|
+
ownedUi: async (profileId, ownedSurfaces) => {
|
|
7
|
+
const [{ runOwnedUi }, { composeOwnedUi }] = await Promise.all([
|
|
8
8
|
import("../dist/src/features/owned-ui/index.js"),
|
|
9
9
|
import("../dist/src/composition/index.js"),
|
|
10
10
|
]);
|
|
11
|
-
const application = await
|
|
12
|
-
return await runOwnedUi({ application });
|
|
13
|
-
},
|
|
14
|
-
transparent: async profileId => {
|
|
15
|
-
const { runSelectedTransparentRuntime } = await import("../dist/src/composition/transparent-runtime.js");
|
|
16
|
-
return await runSelectedTransparentRuntime(profileId);
|
|
11
|
+
const { application, settings } = await composeOwnedUi({ cwd: process.cwd(), profileId, ownedSurfaces });
|
|
12
|
+
return await runOwnedUi({ application, ...(settings === null ? {} : { settings }) });
|
|
17
13
|
},
|
|
18
14
|
}).then(
|
|
19
15
|
code => { process.exitCode = code; },
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "a1-process-guardian-artifact-v1",
|
|
3
|
+
"protocolVersion": 1,
|
|
4
|
+
"crateVersion": "0.1.0-dev",
|
|
5
|
+
"platform": "darwin",
|
|
6
|
+
"architecture": "arm64",
|
|
7
|
+
"capability": "unsupported",
|
|
8
|
+
"builtAt": "2026-08-23T09:25:46.770Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "process-guardian",
|
|
11
|
+
"sha256": "7524bf568992517f50ed53196c861c5edeba0d7275633bb4735ab45bd5963a28",
|
|
12
|
+
"size": 356368
|
|
13
|
+
},
|
|
14
|
+
"provenance": {
|
|
15
|
+
"language": "Rust",
|
|
16
|
+
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
|
+
"sourceRoot": "native/process-guardian",
|
|
18
|
+
"signatureStatus": "ci-attestation-required"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "a1-process-guardian-artifact-v1",
|
|
3
|
+
"protocolVersion": 1,
|
|
4
|
+
"crateVersion": "0.1.0-dev",
|
|
5
|
+
"platform": "linux",
|
|
6
|
+
"architecture": "x64",
|
|
7
|
+
"capability": "supported",
|
|
8
|
+
"builtAt": "2026-08-23T09:25:43.327Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "process-guardian",
|
|
11
|
+
"sha256": "29e22fe29de2828982bc67ef418c4adcaab1490281477b7bea592ec6fe621bcd",
|
|
12
|
+
"size": 415696
|
|
13
|
+
},
|
|
14
|
+
"provenance": {
|
|
15
|
+
"language": "Rust",
|
|
16
|
+
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
|
+
"sourceRoot": "native/process-guardian",
|
|
18
|
+
"signatureStatus": "ci-attestation-required"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
Binary file
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schema": "a1-process-guardian-artifact-v1",
|
|
3
|
+
"protocolVersion": 1,
|
|
4
|
+
"crateVersion": "0.1.0-dev",
|
|
5
|
+
"platform": "win32",
|
|
6
|
+
"architecture": "x64",
|
|
7
|
+
"capability": "supported",
|
|
8
|
+
"builtAt": "2026-08-23T09:26:36.967Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "process-guardian.exe",
|
|
11
|
+
"sha256": "1fd994f340bfa8423eee47ab6b7c3a19a5b1a19dea88814af27d8a989cfa0da0",
|
|
12
|
+
"size": 172544
|
|
13
|
+
},
|
|
14
|
+
"provenance": {
|
|
15
|
+
"language": "Rust",
|
|
16
|
+
"cargoLock": "native/process-guardian/Cargo.lock",
|
|
17
|
+
"sourceRoot": "native/process-guardian",
|
|
18
|
+
"signatureStatus": "ci-attestation-required"
|
|
19
|
+
}
|
|
20
|
+
}
|
|
Binary file
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { type AgentEnginePort } from "../foundation/agent-engine-contracts/index.js";
|
|
2
2
|
import { type PiEngineAdapter } from "../foundation/pi-engine-adapter/index.js";
|
|
3
3
|
import { type OwnedUiApplicationPort, type PresentationComponentPort, type PresentationRuntimePort, type PresentationTerminalPort } from "../foundation/presentation-contracts/index.js";
|
|
4
|
+
import { OwnedUiSettingsSession } from "../foundation/owned-ui-settings/index.js";
|
|
5
|
+
import type { UiRouteHost } from "../foundation/pi-owned-ui-integration/index.js";
|
|
4
6
|
export interface ProcessCompositionOptions {
|
|
5
7
|
readonly cwd?: string;
|
|
6
8
|
readonly sessionId?: string;
|
|
@@ -12,11 +14,35 @@ export interface OwnedUiCompositionOptions {
|
|
|
12
14
|
readonly cwd?: string;
|
|
13
15
|
readonly terminal?: PresentationTerminalPort;
|
|
14
16
|
readonly createPiAdapter?: () => Promise<PiEngineAdapter>;
|
|
17
|
+
/**
|
|
18
|
+
* A1 profile whose settings this session reads and writes. Omitted keeps the
|
|
19
|
+
* session settings-free, which is what the pinned comparison paths use.
|
|
20
|
+
*/
|
|
21
|
+
readonly profileId?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Whether A1's own surfaces are reachable. Withheld for the rendering parity
|
|
24
|
+
* comparison, which measures this composition against pinned Pi and so must
|
|
25
|
+
* present Pi's interface and nothing of A1's own. It is the same composition
|
|
26
|
+
* either way: a parity run built beside the product would measure itself.
|
|
27
|
+
*/
|
|
28
|
+
readonly ownedSurfaces?: "on" | "off";
|
|
29
|
+
}
|
|
30
|
+
export interface OwnedUiComposition {
|
|
31
|
+
readonly application: OwnedUiApplicationPort;
|
|
32
|
+
/** Present when a profile was supplied, so the caller can resolve settings before start. */
|
|
33
|
+
readonly settings: OwnedUiSettingsSession | null;
|
|
15
34
|
}
|
|
16
35
|
export declare function composeOwnedUiApplication(options?: OwnedUiCompositionOptions): Promise<OwnedUiApplicationPort>;
|
|
36
|
+
export declare function composeOwnedUi(options?: OwnedUiCompositionOptions): Promise<OwnedUiComposition>;
|
|
17
37
|
export interface ProcessComposition {
|
|
18
38
|
readonly engine: AgentEnginePort;
|
|
19
39
|
createPresentation(root: PresentationComponentPort, terminal: PresentationTerminalPort): PresentationRuntimePort;
|
|
20
40
|
dispose(): Promise<void>;
|
|
21
41
|
}
|
|
22
42
|
export declare function composeProcess(options?: ProcessCompositionOptions): Promise<ProcessComposition>;
|
|
43
|
+
/**
|
|
44
|
+
* Registers the A1-owned screens and adapts the app host to the shell's route
|
|
45
|
+
* seam. The shell mounts whatever surface it is handed and forwards keys; it
|
|
46
|
+
* never learns what an app is.
|
|
47
|
+
*/
|
|
48
|
+
export declare function createOwnedRouteHost(settings: OwnedUiSettingsSession): UiRouteHost;
|
|
@@ -3,6 +3,12 @@ import { createPiEngineAdapter } from "../foundation/pi-engine-adapter/index.js"
|
|
|
3
3
|
import { createPiPresentationRuntime, createPiTerminalBridge } from "../foundation/pi-tui-runtime-adapter/index.js";
|
|
4
4
|
import { assertPresentationComponent, assertPresentationRuntime, } from "../foundation/presentation-contracts/index.js";
|
|
5
5
|
import { OwnedUiSessionShell } from "../foundation/pi-owned-ui-integration/index.js";
|
|
6
|
+
import { OwnedUiSettingsSession, OwnedUiSettingsStore } from "../foundation/owned-ui-settings/index.js";
|
|
7
|
+
import { UiAppHost, UiAppRegistry } from "../foundation/ui-apps/index.js";
|
|
8
|
+
import { applyConfiguredPiTheme, getAvailablePiThemes, piTheme } from "../foundation/pi-component-adapter/index.js";
|
|
9
|
+
import { faint } from "../foundation/ui-components/index.js";
|
|
10
|
+
import { SETTINGS_APP_ID, SETTINGS_ROUTE, SettingsApp } from "../features/owned-ui/index.js";
|
|
11
|
+
import { resolveProductPaths } from "../foundation/lifecycle/index.js";
|
|
6
12
|
const CAPABILITIES = {
|
|
7
13
|
contractVersion: AGENT_ENGINE_CONTRACT_VERSION,
|
|
8
14
|
commands: ["prompt", "steer", "follow-up", "abort", "retry", "compact", "bash", "replace-session"],
|
|
@@ -10,20 +16,37 @@ const CAPABILITIES = {
|
|
|
10
16
|
snapshots: { supported: true, maxBytes: 1024 * 1024 },
|
|
11
17
|
};
|
|
12
18
|
export async function composeOwnedUiApplication(options = {}) {
|
|
19
|
+
return (await composeOwnedUi(options)).application;
|
|
20
|
+
}
|
|
21
|
+
export async function composeOwnedUi(options = {}) {
|
|
13
22
|
const cwd = options.cwd ?? process.cwd();
|
|
14
|
-
const adapter = options.createPiAdapter
|
|
23
|
+
const adapter = options.createPiAdapter
|
|
24
|
+
? await options.createPiAdapter()
|
|
25
|
+
: await createPiEngineAdapter({ cwd, availableThemes: () => getAvailablePiThemes().map(theme => theme.name) });
|
|
26
|
+
const settings = options.profileId === undefined
|
|
27
|
+
? null
|
|
28
|
+
: new OwnedUiSettingsSession({
|
|
29
|
+
store: new OwnedUiSettingsStore({ configDir: resolveProductPaths().configDir, profileId: options.profileId }),
|
|
30
|
+
agentProvider: () => adapter.settingsPort(),
|
|
31
|
+
});
|
|
32
|
+
// Before anything is drawn, so every surface uses the configured theme rather
|
|
33
|
+
// than the one guessed from the terminal's background.
|
|
34
|
+
applyConfiguredPiTheme(adapter.configuredTheme());
|
|
35
|
+
const routeHost = settings === null || options.ownedSurfaces === "off" ? null : createOwnedRouteHost(settings);
|
|
15
36
|
const shell = new OwnedUiSessionShell({
|
|
16
37
|
backend: adapter,
|
|
17
38
|
cwd,
|
|
18
39
|
...(options.terminal === undefined ? {} : { terminal: createPiTerminalBridge(options.terminal) }),
|
|
40
|
+
...(routeHost === null ? {} : { routeHost }),
|
|
19
41
|
});
|
|
20
|
-
|
|
42
|
+
const application = {
|
|
21
43
|
get disposed() { return adapter.disposed; },
|
|
22
44
|
start: () => shell.start(),
|
|
23
45
|
flush: () => adapter.flushEvents(),
|
|
24
46
|
waitUntilStopped: () => shell.waitUntilStopped(),
|
|
25
47
|
dispose: () => shell.dispose(),
|
|
26
48
|
};
|
|
49
|
+
return { application, settings };
|
|
27
50
|
}
|
|
28
51
|
export async function composeProcess(options = {}) {
|
|
29
52
|
let engine = options.engine;
|
|
@@ -164,3 +187,72 @@ function toMessage(block) {
|
|
|
164
187
|
const role = block.kind === "user" ? "user" : block.kind === "system" ? "system" : block.kind === "tool-call" || block.kind === "tool-result" ? "tool" : "assistant";
|
|
165
188
|
return { id: block.id, role, status: block.status === "live" ? "streaming" : "final", content: [{ kind: "text", text: block.text }] };
|
|
166
189
|
}
|
|
190
|
+
/**
|
|
191
|
+
* Registers the A1-owned screens and adapts the app host to the shell's route
|
|
192
|
+
* seam. The shell mounts whatever surface it is handed and forwards keys; it
|
|
193
|
+
* never learns what an app is.
|
|
194
|
+
*/
|
|
195
|
+
export function createOwnedRouteHost(settings) {
|
|
196
|
+
const registry = new UiAppRegistry();
|
|
197
|
+
registry.register({ id: SETTINGS_APP_ID, route: SETTINGS_ROUTE, create: () => new SettingsApp(settings) });
|
|
198
|
+
return {
|
|
199
|
+
claims: route => registry.forRoute(route) !== null,
|
|
200
|
+
open: route => {
|
|
201
|
+
const registration = registry.forRoute(route);
|
|
202
|
+
if (registration === null)
|
|
203
|
+
return null;
|
|
204
|
+
let size = { width: 80, height: 24 };
|
|
205
|
+
let frame = [];
|
|
206
|
+
let closed = false;
|
|
207
|
+
let onRender = () => undefined;
|
|
208
|
+
let onExit = () => undefined;
|
|
209
|
+
const host = new UiAppHost({
|
|
210
|
+
registry,
|
|
211
|
+
closeOnInterrupt: true,
|
|
212
|
+
theme: pinnedTheme(),
|
|
213
|
+
surface: {
|
|
214
|
+
size: () => size,
|
|
215
|
+
requestRender: () => onRender(),
|
|
216
|
+
exit: () => onExit(),
|
|
217
|
+
present: lines => {
|
|
218
|
+
if (lines === null)
|
|
219
|
+
closed = true;
|
|
220
|
+
else
|
|
221
|
+
frame = lines;
|
|
222
|
+
},
|
|
223
|
+
},
|
|
224
|
+
});
|
|
225
|
+
host.open(registration.id);
|
|
226
|
+
const surface = {
|
|
227
|
+
id: registration.id,
|
|
228
|
+
render: (width, height) => {
|
|
229
|
+
size = { width, height };
|
|
230
|
+
host.render();
|
|
231
|
+
return frame.length === height ? frame : [...frame.slice(0, height), ...Array(Math.max(0, height - frame.length)).fill("")];
|
|
232
|
+
},
|
|
233
|
+
handleInput: data => host.handleInput(data).consumed,
|
|
234
|
+
handleMouse: event => host.handleMouse(event).consumed,
|
|
235
|
+
isClosed: () => closed || !host.isPresenting,
|
|
236
|
+
close: () => host.close(),
|
|
237
|
+
onRenderRequested: listener => { onRender = listener; },
|
|
238
|
+
onExitRequested: listener => { onExit = listener; },
|
|
239
|
+
};
|
|
240
|
+
return surface;
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Maps A1 UI tokens onto the pinned Pi theme so owned screens match the shell. */
|
|
245
|
+
function pinnedTheme() {
|
|
246
|
+
return {
|
|
247
|
+
fg: (token, text) => piTheme().fg(token, text),
|
|
248
|
+
bold: (text) => piTheme().bold(text),
|
|
249
|
+
// Unpainted, so a list reads against the terminal the reader actually has
|
|
250
|
+
// rather than against the background the configured theme was built for.
|
|
251
|
+
plain: (text) => text,
|
|
252
|
+
// Quiet, and quieter again: the terminal's own faint attribute over the
|
|
253
|
+
// dimmest colour the theme has.
|
|
254
|
+
disabled: (text) => faint(piTheme().fg("dim", text)),
|
|
255
|
+
highlight: (text) => `[48;2;82;82;82m[97m${text}[39m[49m`,
|
|
256
|
+
panel: (text) => `[48;2;55;55;55m${text}[49m`,
|
|
257
|
+
};
|
|
258
|
+
}
|
|
@@ -38,7 +38,7 @@ async function ensureSafeDirectoryChain(root) {
|
|
|
38
38
|
current = parent;
|
|
39
39
|
}
|
|
40
40
|
for (const path of missing.reverse())
|
|
41
|
-
await
|
|
41
|
+
await createOwnedDirectory(path, "profile path");
|
|
42
42
|
}
|
|
43
43
|
async function ensureOwnedDirectory(path) {
|
|
44
44
|
const metadata = await lstat(path).catch(error => {
|
|
@@ -51,7 +51,28 @@ async function ensureOwnedDirectory(path) {
|
|
|
51
51
|
throw new Error(`profile resource path is not an owned directory: ${path}`);
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
-
await
|
|
54
|
+
await createOwnedDirectory(path, "profile resource path");
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Creates a directory, treating "it already exists" as another launch having won
|
|
58
|
+
* the race rather than as a failure — but still refusing what it finds if that is
|
|
59
|
+
* not an owned directory.
|
|
60
|
+
*/
|
|
61
|
+
async function createOwnedDirectory(path, subject) {
|
|
62
|
+
try {
|
|
63
|
+
await mkdir(path, { mode: 0o700 });
|
|
64
|
+
return;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
if (!isAlreadyThere(error))
|
|
68
|
+
throw error;
|
|
69
|
+
}
|
|
70
|
+
const metadata = await lstat(path);
|
|
71
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
72
|
+
throw new Error(`${subject} is not an owned directory: ${path}`);
|
|
73
|
+
}
|
|
74
|
+
function isAlreadyThere(error) {
|
|
75
|
+
return typeof error === "object" && error !== null && error.code === "EEXIST";
|
|
55
76
|
}
|
|
56
77
|
function isMissing(error) {
|
|
57
78
|
return error instanceof Error && "code" in error && error.code === "ENOENT";
|
|
@@ -7,6 +7,6 @@ export interface LaunchProfileContract {
|
|
|
7
7
|
readonly productSurface: "agent" | "vanilla-baseline" | "isolated-profile";
|
|
8
8
|
readonly configurationRootPolicy: ConfigurationRootPolicy;
|
|
9
9
|
readonly projectTrust: ProjectTrustPolicy;
|
|
10
|
-
readonly terminalCapability: "owned-ui"
|
|
10
|
+
readonly terminalCapability: "owned-ui";
|
|
11
11
|
}
|
|
12
12
|
export declare function launchProfileContract(id: LaunchProfileId): LaunchProfileContract;
|
|
@@ -11,14 +11,14 @@ const contracts = Object.freeze({
|
|
|
11
11
|
productSurface: "vanilla-baseline",
|
|
12
12
|
configurationRootPolicy: "pi-default",
|
|
13
13
|
projectTrust: "pi-default",
|
|
14
|
-
terminalCapability: "
|
|
14
|
+
terminalCapability: "owned-ui",
|
|
15
15
|
}),
|
|
16
16
|
sandbox: Object.freeze({
|
|
17
17
|
id: "sandbox",
|
|
18
18
|
productSurface: "isolated-profile",
|
|
19
19
|
configurationRootPolicy: "sandbox-profile",
|
|
20
20
|
projectTrust: "ignore",
|
|
21
|
-
terminalCapability: "
|
|
21
|
+
terminalCapability: "owned-ui",
|
|
22
22
|
}),
|
|
23
23
|
});
|
|
24
24
|
export function launchProfileContract(id) {
|
|
@@ -1,14 +1,19 @@
|
|
|
1
1
|
import { type LaunchProfileId } from "../../foundation/lifecycle/index.js";
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Every interactive command is the same composition. What differs is the
|
|
4
|
+
* configuration root each one reads and whether A1's own screens are reachable:
|
|
5
|
+
* bare `a1` is the product, while `a1 pi` and `a1 sandbox` present pinned Pi's
|
|
6
|
+
* interface and nothing of A1's own, against Pi's own profile and against an
|
|
7
|
+
* isolated one.
|
|
8
|
+
*/
|
|
9
|
+
export type OwnedUiProfileId = LaunchProfileId;
|
|
10
|
+
export interface InteractiveRuntimeSelection {
|
|
4
11
|
readonly kind: "owned-ui";
|
|
5
|
-
|
|
6
|
-
readonly
|
|
7
|
-
|
|
8
|
-
};
|
|
12
|
+
readonly profileId: OwnedUiProfileId;
|
|
13
|
+
readonly ownedSurfaces: "on" | "off";
|
|
14
|
+
}
|
|
9
15
|
export interface InteractiveRuntimeRunners {
|
|
10
|
-
readonly ownedUi: () => Promise<number>;
|
|
11
|
-
readonly transparent: (profileId: TransparentInteractiveProfileId) => Promise<number>;
|
|
16
|
+
readonly ownedUi: (profileId: OwnedUiProfileId, ownedSurfaces: "on" | "off") => Promise<number>;
|
|
12
17
|
}
|
|
13
18
|
export declare function selectInteractiveRuntime(profileId: string): InteractiveRuntimeSelection;
|
|
14
19
|
export declare function runSelectedInteractiveRuntime(profileId: string, runners: InteractiveRuntimeRunners): Promise<number>;
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { assertLaunchProfileId } from "../../foundation/lifecycle/index.js";
|
|
2
2
|
export function selectInteractiveRuntime(profileId) {
|
|
3
3
|
assertLaunchProfileId(profileId);
|
|
4
|
-
return
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
return Object.freeze({
|
|
5
|
+
kind: "owned-ui",
|
|
6
|
+
profileId,
|
|
7
|
+
ownedSurfaces: profileId === "a1" ? "on" : "off",
|
|
8
|
+
});
|
|
7
9
|
}
|
|
8
10
|
export async function runSelectedInteractiveRuntime(profileId, runners) {
|
|
9
11
|
const selection = selectInteractiveRuntime(profileId);
|
|
10
|
-
return selection.
|
|
11
|
-
? await runners.ownedUi()
|
|
12
|
-
: await runners.transparent(selection.profileId);
|
|
12
|
+
return await runners.ownedUi(selection.profileId, selection.ownedSurfaces);
|
|
13
13
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
1
|
import type { OwnedUiApplicationPort } from "../../foundation/presentation-contracts/index.js";
|
|
2
|
+
import type { OwnedUiSettingsSession } from "../../foundation/owned-ui-settings/index.js";
|
|
2
3
|
export interface OwnedUiRunOptions {
|
|
3
4
|
readonly application: OwnedUiApplicationPort;
|
|
5
|
+
/**
|
|
6
|
+
* Resolved once before the application starts, so every surface reads the same
|
|
7
|
+
* values for the life of the session. Omitted when the caller runs without settings.
|
|
8
|
+
*/
|
|
9
|
+
readonly settings?: OwnedUiSettingsSession;
|
|
4
10
|
}
|
|
5
11
|
export declare function runOwnedUi(options: OwnedUiRunOptions): Promise<number>;
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { AppHostServices, UiApp } from "../../foundation/ui-apps/index.js";
|
|
2
|
+
import { ShortcutRegistry, type PaneInputResult, type PaneMouseEvent, type PaneRect } from "../../foundation/ui-components/index.js";
|
|
3
|
+
import type { OwnedUiSettingsSession } from "../../foundation/owned-ui-settings/index.js";
|
|
4
|
+
export declare const SETTINGS_APP_ID = "settings";
|
|
5
|
+
export declare const SETTINGS_ROUTE = "settings";
|
|
6
|
+
type Action = "move-up" | "move-down" | "block-up" | "block-down" | "first" | "last" | "page-up" | "page-down" | "previous-value" | "next-value" | "activate" | "open-filter" | "close" | "part-previous" | "part-next" | "part-change";
|
|
7
|
+
export declare const SETTINGS_SHORTCUTS: ShortcutRegistry<Action>;
|
|
8
|
+
/**
|
|
9
|
+
* The settings screen. Rows, sticky headers, scrolling, and the keymap come from
|
|
10
|
+
* the shared component layer; what belongs to settings is which sections exist,
|
|
11
|
+
* how a value is shown, and where an accepted change is routed.
|
|
12
|
+
*/
|
|
13
|
+
export declare class SettingsApp implements UiApp {
|
|
14
|
+
#private;
|
|
15
|
+
readonly id = "settings";
|
|
16
|
+
constructor(session: OwnedUiSettingsSession);
|
|
17
|
+
onActivate(host: AppHostServices): void;
|
|
18
|
+
render(rect: PaneRect, host: AppHostServices): readonly string[];
|
|
19
|
+
onInput(data: string, host: AppHostServices): PaneInputResult;
|
|
20
|
+
onMouse(event: PaneMouseEvent, _host: AppHostServices): PaneInputResult;
|
|
21
|
+
}
|
|
22
|
+
export {};
|