@timurproko/a1 0.1.1-dev.5 → 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
package/README.md
CHANGED
|
@@ -9,6 +9,8 @@ Requirements:
|
|
|
9
9
|
- Node.js 22.19 through 24.x
|
|
10
10
|
- npm 11
|
|
11
11
|
|
|
12
|
+
Published packages include the integrity-verified process guardian for supported platforms. Building A1 from source additionally requires Rust/Cargo 1.85 or newer.
|
|
13
|
+
|
|
12
14
|
```sh
|
|
13
15
|
npm install --global @timurproko/a1@latest
|
|
14
16
|
```
|
|
@@ -32,6 +34,8 @@ Bare `a1` owns its Pi-compatible TUI composition and uses the public Pi engine,
|
|
|
32
34
|
|
|
33
35
|
`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
36
|
|
|
37
|
+
Every interactive command creates an independent, non-detachable launch instance. Any number of `a1`, `a1 pi`, and `a1 sandbox` commands may run in separate terminals at the same time. Closing one command closes only its owned UI/Pi process and all agents, extensions, tools, daemons, and descendants created by that invocation; it never requires finding PIDs, deleting control state, or restarting the supervisor. The idle supervisor may remain available for release coordination after all interactive instances close, but it owns no surviving instance runtime.
|
|
38
|
+
|
|
35
39
|
## Develop
|
|
36
40
|
|
|
37
41
|
```sh
|
|
@@ -44,18 +48,37 @@ npm start
|
|
|
44
48
|
|
|
45
49
|
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
50
|
|
|
47
|
-
###
|
|
51
|
+
### Worktree lifecycle
|
|
52
|
+
|
|
53
|
+
The primary worktree stays on `develop` and is integration-only. Each task uses a detached worktree under the repository's ignored `.worktrees/` directory, based on current `origin/develop` unless another base is selected.
|
|
54
|
+
|
|
55
|
+
```sh
|
|
56
|
+
git fetch origin --prune
|
|
57
|
+
git worktree add --detach .worktrees/<task-id> origin/develop
|
|
58
|
+
cd .worktrees/<task-id>
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Commit and validate coherent work there. Because `develop` is protected, push the detached commit to one temporary remote branch and merge one pull request for the requested change. After merge, update the primary worktree and remove the task worktree only when its commits are reachable from `develop`:
|
|
62
|
+
|
|
63
|
+
```sh
|
|
64
|
+
git push origin HEAD:refs/heads/<task-id>
|
|
65
|
+
gh pr create --base develop --head <task-id>
|
|
66
|
+
# After the pull request is merged:
|
|
67
|
+
cd <repository-root>
|
|
68
|
+
git fetch origin --prune
|
|
69
|
+
git merge --ff-only origin/develop
|
|
70
|
+
git worktree remove .worktrees/<task-id>
|
|
71
|
+
git worktree prune
|
|
72
|
+
```
|
|
48
73
|
|
|
49
|
-
|
|
74
|
+
Manual acceptance does not leave a permanent validation checkout. Once acceptance is recorded, archive the completed OpenSpec change, integrate the archive commit into `develop`, then remove and prune every task or acceptance worktree retained for that change. Never remove a worktree before all of its implementation, acceptance, and archive commits are reachable from `develop`.
|
|
50
75
|
|
|
51
|
-
|
|
52
|
-
2. Merge it into `develop` and push the merged `develop` commit.
|
|
53
|
-
3. Switch to `develop`.
|
|
54
|
-
4. Preview the exact cleanup set with `npm run branches:prune -- --branch <source>`.
|
|
55
|
-
5. Safely delete the reviewed local source with `npm run branches:prune -- --apply --branch <source>`.
|
|
56
|
-
6. When the non-protected remote source exists, delete it in the same cleanup with `npm run branches:prune -- --apply --branch <source> --remote origin`.
|
|
76
|
+
Local package archives and ad hoc test builds belong under `.builds/`, never in the repository root. For manual package tests, use:
|
|
57
77
|
|
|
58
|
-
|
|
78
|
+
```sh
|
|
79
|
+
mkdir -p .builds
|
|
80
|
+
npm pack --ignore-scripts --pack-destination .builds
|
|
81
|
+
```
|
|
59
82
|
|
|
60
83
|
Run the non-desktop gates with:
|
|
61
84
|
|
|
@@ -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", "a1-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
CHANGED
|
@@ -3,13 +3,16 @@
|
|
|
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 => {
|
|
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
|
-
|
|
12
|
-
|
|
11
|
+
// A1_OWNED_SURFACES=off presents pinned Pi's interface through A1's own
|
|
12
|
+
// rendering and input, which is what the parity comparison measures.
|
|
13
|
+
const ownedSurfaces = process.env.A1_OWNED_SURFACES === "off" ? "off" : "on";
|
|
14
|
+
const { application, settings } = await composeOwnedUi({ cwd: process.cwd(), profileId, ownedSurfaces });
|
|
15
|
+
return await runOwnedUi({ application, ...(settings === null ? {} : { settings }) });
|
|
13
16
|
},
|
|
14
17
|
transparent: async profileId => {
|
|
15
18
|
const { runSelectedTransparentRuntime } = await import("../dist/src/composition/transparent-runtime.js");
|
|
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": "darwin",
|
|
6
|
+
"architecture": "arm64",
|
|
7
|
+
"capability": "unsupported",
|
|
8
|
+
"builtAt": "2026-08-22T13:11:56.818Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "a1-process-guardian",
|
|
11
|
+
"sha256": "bb07d029b67a5eae4fbf3dea64f96cdf03462920949f2ea7e9e7b1bd33dbabc1",
|
|
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-22T13:12:07.615Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "a1-process-guardian",
|
|
11
|
+
"sha256": "f66cc7ac6d30ad424bc00992e4c5425259d36f055893d872eda9cf518bdb2ed0",
|
|
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-22T13:12:29.999Z",
|
|
9
|
+
"artifact": {
|
|
10
|
+
"filename": "a1-process-guardian.exe",
|
|
11
|
+
"sha256": "83641a8a264dae32e57020ef1f37823ffe186b5acd28df18eae1afa80d25854c",
|
|
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
|
+
}
|
|
@@ -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 { 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,34 @@ 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
|
+
const routeHost = settings === null || options.ownedSurfaces === "off" ? null : createOwnedRouteHost(settings);
|
|
15
33
|
const shell = new OwnedUiSessionShell({
|
|
16
34
|
backend: adapter,
|
|
17
35
|
cwd,
|
|
18
36
|
...(options.terminal === undefined ? {} : { terminal: createPiTerminalBridge(options.terminal) }),
|
|
37
|
+
...(routeHost === null ? {} : { routeHost }),
|
|
19
38
|
});
|
|
20
|
-
|
|
39
|
+
const application = {
|
|
21
40
|
get disposed() { return adapter.disposed; },
|
|
22
41
|
start: () => shell.start(),
|
|
23
42
|
flush: () => adapter.flushEvents(),
|
|
24
43
|
waitUntilStopped: () => shell.waitUntilStopped(),
|
|
25
44
|
dispose: () => shell.dispose(),
|
|
26
45
|
};
|
|
46
|
+
return { application, settings };
|
|
27
47
|
}
|
|
28
48
|
export async function composeProcess(options = {}) {
|
|
29
49
|
let engine = options.engine;
|
|
@@ -164,3 +184,69 @@ function toMessage(block) {
|
|
|
164
184
|
const role = block.kind === "user" ? "user" : block.kind === "system" ? "system" : block.kind === "tool-call" || block.kind === "tool-result" ? "tool" : "assistant";
|
|
165
185
|
return { id: block.id, role, status: block.status === "live" ? "streaming" : "final", content: [{ kind: "text", text: block.text }] };
|
|
166
186
|
}
|
|
187
|
+
/**
|
|
188
|
+
* Registers the A1-owned screens and adapts the app host to the shell's route
|
|
189
|
+
* seam. The shell mounts whatever surface it is handed and forwards keys; it
|
|
190
|
+
* never learns what an app is.
|
|
191
|
+
*/
|
|
192
|
+
export function createOwnedRouteHost(settings) {
|
|
193
|
+
const registry = new UiAppRegistry();
|
|
194
|
+
registry.register({ id: SETTINGS_APP_ID, route: SETTINGS_ROUTE, create: () => new SettingsApp(settings) });
|
|
195
|
+
return {
|
|
196
|
+
claims: route => registry.forRoute(route) !== null,
|
|
197
|
+
open: route => {
|
|
198
|
+
const registration = registry.forRoute(route);
|
|
199
|
+
if (registration === null)
|
|
200
|
+
return null;
|
|
201
|
+
let size = { width: 80, height: 24 };
|
|
202
|
+
let frame = [];
|
|
203
|
+
let closed = false;
|
|
204
|
+
let onRender = () => undefined;
|
|
205
|
+
let onExit = () => undefined;
|
|
206
|
+
const host = new UiAppHost({
|
|
207
|
+
registry,
|
|
208
|
+
closeOnInterrupt: true,
|
|
209
|
+
theme: pinnedTheme(),
|
|
210
|
+
surface: {
|
|
211
|
+
size: () => size,
|
|
212
|
+
requestRender: () => onRender(),
|
|
213
|
+
exit: () => onExit(),
|
|
214
|
+
present: lines => {
|
|
215
|
+
if (lines === null)
|
|
216
|
+
closed = true;
|
|
217
|
+
else
|
|
218
|
+
frame = lines;
|
|
219
|
+
},
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
host.open(registration.id);
|
|
223
|
+
const surface = {
|
|
224
|
+
id: registration.id,
|
|
225
|
+
render: (width, height) => {
|
|
226
|
+
size = { width, height };
|
|
227
|
+
host.render();
|
|
228
|
+
return frame.length === height ? frame : [...frame.slice(0, height), ...Array(Math.max(0, height - frame.length)).fill("")];
|
|
229
|
+
},
|
|
230
|
+
handleInput: data => host.handleInput(data).consumed,
|
|
231
|
+
handleMouse: event => host.handleMouse(event).consumed,
|
|
232
|
+
isClosed: () => closed || !host.isPresenting,
|
|
233
|
+
close: () => host.close(),
|
|
234
|
+
onRenderRequested: listener => { onRender = listener; },
|
|
235
|
+
onExitRequested: listener => { onExit = listener; },
|
|
236
|
+
};
|
|
237
|
+
return surface;
|
|
238
|
+
},
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/** Maps A1 UI tokens onto the pinned Pi theme so owned screens match the shell. */
|
|
242
|
+
function pinnedTheme() {
|
|
243
|
+
return {
|
|
244
|
+
fg: (token, text) => piTheme().fg(token, text),
|
|
245
|
+
bold: (text) => piTheme().bold(text),
|
|
246
|
+
// Quiet, and quieter again: the terminal's own faint attribute over the
|
|
247
|
+
// dimmest colour the theme has.
|
|
248
|
+
disabled: (text) => faint(piTheme().fg("dim", text)),
|
|
249
|
+
highlight: (text) => `[48;2;82;82;82m[97m${text}[39m[49m`,
|
|
250
|
+
panel: (text) => `[48;2;55;55;55m${text}[49m`,
|
|
251
|
+
};
|
|
252
|
+
}
|
|
@@ -2,12 +2,13 @@ import { type LaunchProfileId } from "../../foundation/lifecycle/index.js";
|
|
|
2
2
|
export type TransparentInteractiveProfileId = Exclude<LaunchProfileId, "a1">;
|
|
3
3
|
export type InteractiveRuntimeSelection = {
|
|
4
4
|
readonly kind: "owned-ui";
|
|
5
|
+
readonly profileId: Extract<LaunchProfileId, "a1">;
|
|
5
6
|
} | {
|
|
6
7
|
readonly kind: "transparent";
|
|
7
8
|
readonly profileId: TransparentInteractiveProfileId;
|
|
8
9
|
};
|
|
9
10
|
export interface InteractiveRuntimeRunners {
|
|
10
|
-
readonly ownedUi: () => Promise<number>;
|
|
11
|
+
readonly ownedUi: (profileId: Extract<LaunchProfileId, "a1">) => Promise<number>;
|
|
11
12
|
readonly transparent: (profileId: TransparentInteractiveProfileId) => Promise<number>;
|
|
12
13
|
}
|
|
13
14
|
export declare function selectInteractiveRuntime(profileId: string): InteractiveRuntimeSelection;
|
|
@@ -2,12 +2,12 @@ import { assertLaunchProfileId } from "../../foundation/lifecycle/index.js";
|
|
|
2
2
|
export function selectInteractiveRuntime(profileId) {
|
|
3
3
|
assertLaunchProfileId(profileId);
|
|
4
4
|
return profileId === "a1"
|
|
5
|
-
? Object.freeze({ kind: "owned-ui" })
|
|
5
|
+
? Object.freeze({ kind: "owned-ui", profileId: "a1" })
|
|
6
6
|
: Object.freeze({ kind: "transparent", profileId });
|
|
7
7
|
}
|
|
8
8
|
export async function runSelectedInteractiveRuntime(profileId, runners) {
|
|
9
9
|
const selection = selectInteractiveRuntime(profileId);
|
|
10
10
|
return selection.kind === "owned-ui"
|
|
11
|
-
? await runners.ownedUi()
|
|
11
|
+
? await runners.ownedUi(selection.profileId)
|
|
12
12
|
: await runners.transparent(selection.profileId);
|
|
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 {};
|