@timurproko/a1 0.1.8-dev.0aceebe → 0.1.8-dev.112
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 +41 -31
- package/dist/native/darwin-arm64/manifest.json +1 -1
- package/dist/native/linux-x64/manifest.json +1 -1
- package/dist/native/win32-x64/manifest.json +2 -2
- package/dist/native/win32-x64/process-guardian.exe +0 -0
- package/dist/src/cli/dispatch.js +67 -30
- package/dist/src/cli/packages.d.ts +9 -1
- package/dist/src/cli/packages.js +24 -20
- package/dist/src/cli/version-stats.js +4 -4
- package/dist/src/foundation/pi-component-adapter/index.d.ts +1 -1
- package/dist/src/foundation/pi-component-adapter/index.js +1 -1
- package/dist/src/foundation/pi-component-adapter/shell-presenters-transcript.js +2 -1
- package/dist/src/foundation/pi-engine-adapter/adapter.d.ts +7 -0
- package/dist/src/foundation/pi-engine-adapter/adapter.js +193 -39
- 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 +223 -13
- package/dist/src/foundation/release/index.d.ts +0 -1
- package/dist/src/foundation/release/index.js +0 -1
- package/dist/src/foundation/release/update.d.ts +1 -1
- package/dist/src/foundation/release/update.js +13 -15
- package/docs/architecture/toolchain.md +1 -1
- package/docs/ci-release-runbook.md +76 -79
- package/docs/features/launch-profiles.md +1 -1
- package/docs/manual-transparent-checkpoint.md +1 -1
- package/package.json +3 -1
- package/dist/src/foundation/release/development-preview-release.d.ts +0 -49
- package/dist/src/foundation/release/development-preview-release.js +0 -114
package/README.md
CHANGED
|
@@ -9,13 +9,15 @@ npm install --global @timurproko/a1@latest
|
|
|
9
9
|
## Commands
|
|
10
10
|
|
|
11
11
|
```sh
|
|
12
|
-
a1
|
|
13
|
-
a1 version
|
|
14
|
-
a1 update
|
|
15
|
-
a1 update:
|
|
12
|
+
a1 # A1-owned UI and profile: ~/.a1/agent
|
|
13
|
+
a1 version # show Installed, Release, and Develop versions
|
|
14
|
+
a1 update # update to the current release
|
|
15
|
+
a1 update:develop # update to the current development preview
|
|
16
|
+
a1 update:107 # install numbered development preview 107
|
|
17
|
+
a1 update --models # refresh A1's model catalogs
|
|
16
18
|
```
|
|
17
19
|
|
|
18
|
-
Prerelease builds — what `a1 update:
|
|
20
|
+
Prerelease builds — what `a1 update:develop` installs — add two development profiles
|
|
19
21
|
for comparing against pinned Pi and for experimenting against an isolated profile.
|
|
20
22
|
A release build does not carry them.
|
|
21
23
|
|
|
@@ -30,16 +32,19 @@ Pi extension packages install into A1's own profile, so bare `a1` loads them and
|
|
|
30
32
|
`a1 pi` and `a1 sandbox` do not. Sources are Pi's: `npm:`, git, or a local path.
|
|
31
33
|
|
|
32
34
|
```sh
|
|
33
|
-
a1 install npm:pi-mcp-adapter # install a package into ~/.a1/agent
|
|
34
|
-
a1 remove npm:pi-mcp-adapter # remove it again (alias: a1 uninstall)
|
|
35
|
-
a1 list # list packages installed for a1
|
|
36
|
-
a1 update --extensions # update every installed package
|
|
37
|
-
a1 update npm:pi-mcp-adapter # update one of them
|
|
38
|
-
a1 update --models # refresh model catalogs
|
|
35
|
+
a1 pi install npm:pi-mcp-adapter # install a package into ~/.a1/agent
|
|
36
|
+
a1 pi remove npm:pi-mcp-adapter # remove it again (alias: a1 pi uninstall)
|
|
37
|
+
a1 pi list # list packages installed for a1
|
|
38
|
+
a1 pi update --extensions # update every installed package
|
|
39
|
+
a1 pi update npm:pi-mcp-adapter # update one of them
|
|
39
40
|
```
|
|
40
41
|
|
|
41
42
|
A running session loads a newly installed package after a restart. Pi's own
|
|
42
|
-
profile at `~/.pi/agent` is managed by Pi itself.
|
|
43
|
+
profile at `~/.pi/agent` is managed by Pi itself. Extension configuration is
|
|
44
|
+
isolated too: for example, MCP configuration for bare `a1` belongs under
|
|
45
|
+
`~/.a1/agent` (or the project), so `~/.pi/agent/mcp.json` is not read. Run
|
|
46
|
+
`/mcp setup` inside bare `a1` to configure it; the MCP footer status appears
|
|
47
|
+
when that A1 configuration contains a server.
|
|
43
48
|
|
|
44
49
|
## Develop
|
|
45
50
|
|
|
@@ -59,24 +64,30 @@ npm run test:full # complete non-physical suite
|
|
|
59
64
|
Two channels, both published by CI from the exact bytes it validated. Nothing is
|
|
60
65
|
ever published from a workstation.
|
|
61
66
|
|
|
62
|
-
###
|
|
67
|
+
### Development previews
|
|
63
68
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
installed preview says exactly which source produced it.
|
|
69
|
+
Ordinary pushes to `develop` do not publish. The nightly run at `03:17 UTC` always
|
|
70
|
+
performs complete verification of current `origin/develop`; it publishes only when
|
|
71
|
+
that source's preview is absent. A maintainer can request the same authoritative
|
|
72
|
+
GitHub Actions path and wait for its result:
|
|
69
73
|
|
|
70
74
|
```sh
|
|
71
|
-
|
|
72
|
-
a1 update:7eabe9e # install the preview built from that commit
|
|
75
|
+
npm run develop
|
|
73
76
|
```
|
|
74
77
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
78
|
+
A preview is `<major.minor.patch>-dev.<pull-request number>`, stamped only into the
|
|
79
|
+
package. For example, the source GitHub presents as `develop (#107)` produces
|
|
80
|
+
`0.1.8-dev.107`. Repeating a request for immutable version 107 succeeds without
|
|
81
|
+
building or publishing again.
|
|
82
|
+
|
|
83
|
+
```sh
|
|
84
|
+
a1 update:develop # install the current development preview
|
|
85
|
+
a1 update:107 # install preview 107
|
|
86
|
+
a1 update:0.1.8-dev.107 # install that exact full preview version
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
The published version list is authoritative: an unpublished number is refused
|
|
90
|
+
rather than guessed. npm's `next` dist-tag remains an internal registry detail.
|
|
80
91
|
|
|
81
92
|
### Stable — npm `latest`
|
|
82
93
|
|
|
@@ -89,12 +100,11 @@ npm run release -- major # 0.1.1 -> 1.0.0
|
|
|
89
100
|
npm run release -- 0.4.0 # an exact version
|
|
90
101
|
```
|
|
91
102
|
|
|
92
|
-
It lands the version on `develop` through a pull request that merges itself
|
|
93
|
-
|
|
94
|
-
on Windows, Linux, and macOS, publishes to npm
|
|
95
|
-
then writes the `v<version>` tag and records the
|
|
96
|
-
|
|
97
|
-
immediately.
|
|
103
|
+
It lands the version on `develop` through a pull request that merges itself, then
|
|
104
|
+
explicitly dispatches publication for that exact commit. GitHub Actions builds,
|
|
105
|
+
validates the packed release on Windows, Linux, and macOS, publishes to npm
|
|
106
|
+
`latest` with provenance, and only then writes the `v<version>` tag and records the
|
|
107
|
+
GitHub Release. The command waits for success before opening the next `-dev` line.
|
|
98
108
|
|
|
99
109
|
```sh
|
|
100
110
|
a1 update # install the newest stable release
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "darwin",
|
|
6
6
|
"architecture": "arm64",
|
|
7
7
|
"capability": "unsupported",
|
|
8
|
-
"builtAt": "2026-08-
|
|
8
|
+
"builtAt": "2026-08-25T09:42:56.359Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "7524bf568992517f50ed53196c861c5edeba0d7275633bb4735ab45bd5963a28",
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
"platform": "linux",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-08-
|
|
8
|
+
"builtAt": "2026-08-25T09:43:23.793Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian",
|
|
11
11
|
"sha256": "29e22fe29de2828982bc67ef418c4adcaab1490281477b7bea592ec6fe621bcd",
|
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
"platform": "win32",
|
|
6
6
|
"architecture": "x64",
|
|
7
7
|
"capability": "supported",
|
|
8
|
-
"builtAt": "2026-08-
|
|
8
|
+
"builtAt": "2026-08-25T09:44:35.937Z",
|
|
9
9
|
"artifact": {
|
|
10
10
|
"filename": "process-guardian.exe",
|
|
11
|
-
"sha256": "
|
|
11
|
+
"sha256": "0e2919843f1cdc824ce48203dace68df43f8ebb4b24b190ff7baf6c13d4846b1",
|
|
12
12
|
"size": 172544
|
|
13
13
|
},
|
|
14
14
|
"provenance": {
|
|
Binary file
|
package/dist/src/cli/dispatch.js
CHANGED
|
@@ -5,12 +5,13 @@ export function cliUsage(capabilities) {
|
|
|
5
5
|
"",
|
|
6
6
|
...(capabilities.developmentProfiles ? ["pi", "sandbox"] : []),
|
|
7
7
|
"version",
|
|
8
|
-
"update [self
|
|
9
|
-
"update:
|
|
10
|
-
"update:<
|
|
11
|
-
"install <source>",
|
|
12
|
-
"remove <source>",
|
|
13
|
-
"list",
|
|
8
|
+
"update [self|--models]",
|
|
9
|
+
"update:develop",
|
|
10
|
+
"update:<number>",
|
|
11
|
+
"pi install <source>",
|
|
12
|
+
"pi remove <source>",
|
|
13
|
+
"pi list",
|
|
14
|
+
"pi update [--extensions|<source>]",
|
|
14
15
|
]);
|
|
15
16
|
}
|
|
16
17
|
const PROFILE_WORDS = new Set(["pi", "sandbox"]);
|
|
@@ -32,7 +33,13 @@ export function parseCliCommand(arguments_, capabilities) {
|
|
|
32
33
|
if (arguments_.length === 0)
|
|
33
34
|
return { kind: "launch", profileId: "a1" };
|
|
34
35
|
const [command, ...rest] = arguments_;
|
|
35
|
-
if (
|
|
36
|
+
if (command === "pi") {
|
|
37
|
+
if (rest.length > 0)
|
|
38
|
+
return parsePiPackageCommand(rest);
|
|
39
|
+
if (capabilities.developmentProfiles)
|
|
40
|
+
return { kind: "launch", profileId: "pi" };
|
|
41
|
+
}
|
|
42
|
+
if (capabilities.developmentProfiles && command === "sandbox") {
|
|
36
43
|
return withoutArguments(rest, { kind: "launch", profileId: command });
|
|
37
44
|
}
|
|
38
45
|
if (command === "version")
|
|
@@ -41,11 +48,9 @@ export function parseCliCommand(arguments_, capabilities) {
|
|
|
41
48
|
return parseColonUpdate(command.slice("update:".length), rest);
|
|
42
49
|
if (command === "update")
|
|
43
50
|
return parseUpdate(rest);
|
|
44
|
-
if (command === "install" || command === "remove" || command === "uninstall") {
|
|
45
|
-
return
|
|
51
|
+
if (command === "install" || command === "remove" || command === "uninstall" || command === "list") {
|
|
52
|
+
return packageNamespaceRejection(command, rest.join(" ") || undefined);
|
|
46
53
|
}
|
|
47
|
-
if (command === "list")
|
|
48
|
-
return withoutArguments(rest, { kind: "packages", request: { verb: "list", source: null } });
|
|
49
54
|
if (command === "ui")
|
|
50
55
|
return { kind: "error", message: `The ui subcommand was removed; run bare ${PRODUCT_TEXT.commandName} for the owned UI.` };
|
|
51
56
|
if (command === "agent")
|
|
@@ -53,28 +58,29 @@ export function parseCliCommand(arguments_, capabilities) {
|
|
|
53
58
|
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`received an unknown command: ${command ?? ""}`) };
|
|
54
59
|
}
|
|
55
60
|
/**
|
|
56
|
-
* What follows the colon says which build to move to. `
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
* commit alone is enough to find it.
|
|
61
|
+
* What follows the colon says which development build to move to. `develop`
|
|
62
|
+
* selects the channel head; a positive decimal or a full numbered preview names
|
|
63
|
+
* one immutable publication.
|
|
60
64
|
*/
|
|
61
65
|
function parseColonUpdate(suffix, rest) {
|
|
62
66
|
if (rest.length > 0)
|
|
63
67
|
return { kind: "error", message: PRODUCT_TEXT.diagnostic("update takes what to move to after the colon, and nothing else.") };
|
|
64
|
-
if (suffix === "next")
|
|
68
|
+
if (suffix === "next") {
|
|
69
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`renamed its development channel; run ${PRODUCT_TEXT.commandName} update:develop.`) };
|
|
70
|
+
}
|
|
71
|
+
if (suffix === "develop")
|
|
65
72
|
return { kind: "update", channel: "next" };
|
|
66
73
|
if (suffix.length === 0)
|
|
67
|
-
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`update: needs a preview after the colon, as in ${PRODUCT_TEXT.commandName} update:
|
|
68
|
-
if (!/^[
|
|
69
|
-
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`received an unusable preview: ${suffix}`) };
|
|
74
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`update: needs a preview after the colon, as in ${PRODUCT_TEXT.commandName} update:develop.`) };
|
|
75
|
+
if (!/^[1-9]\d*$/.test(suffix) && !/^\d+\.\d+\.\d+-dev\.[1-9]\d*$/.test(suffix)) {
|
|
76
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`received an unusable numbered preview: ${suffix}`) };
|
|
70
77
|
}
|
|
71
78
|
return { kind: "update", channel: "next", target: suffix };
|
|
72
79
|
}
|
|
73
80
|
/**
|
|
74
|
-
* `update`
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
* invalidate what was certified.
|
|
81
|
+
* Top-level `update` owns A1 itself and A1's model catalogs. Extension package
|
|
82
|
+
* maintenance lives under the `pi` compatibility namespace, while updating the
|
|
83
|
+
* pinned Pi runtime remains impossible.
|
|
78
84
|
*/
|
|
79
85
|
function parseUpdate(rest) {
|
|
80
86
|
if (rest.length === 0)
|
|
@@ -90,18 +96,42 @@ function parseUpdate(rest) {
|
|
|
90
96
|
message: PRODUCT_TEXT.diagnostic(`pins the Pi version it was certified against; run ${PRODUCT_TEXT.commandName} update to move ${PRODUCT_TEXT.displayName} itself.`),
|
|
91
97
|
};
|
|
92
98
|
}
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if (target === "next" || target === "stable") {
|
|
96
|
-
const form = target === "next" ? `${PRODUCT_TEXT.commandName} update:next` : `${PRODUCT_TEXT.commandName} update`;
|
|
99
|
+
if (target === "next" || target === "develop" || target === "stable") {
|
|
100
|
+
const form = target === "stable" ? `${PRODUCT_TEXT.commandName} update` : `${PRODUCT_TEXT.commandName} update:develop`;
|
|
97
101
|
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`selects a release channel with a colon; run ${form}.`) };
|
|
98
102
|
}
|
|
99
|
-
if (target === "--extensions")
|
|
100
|
-
return { kind: "packages", request: { verb: "update", source: null } };
|
|
101
103
|
if (target === "--models")
|
|
102
104
|
return { kind: "packages", request: { verb: "refresh-models", source: null } };
|
|
105
|
+
if (target === "--extensions" || (target !== undefined && !target.startsWith("-"))) {
|
|
106
|
+
return packageNamespaceRejection("update", target === "--extensions" ? "--extensions" : target);
|
|
107
|
+
}
|
|
108
|
+
return unknownOption(target ?? "", "update");
|
|
109
|
+
}
|
|
110
|
+
function parsePiPackageCommand(arguments_) {
|
|
111
|
+
const [verb, ...rest] = arguments_;
|
|
112
|
+
if (verb === "install" || verb === "remove" || verb === "uninstall") {
|
|
113
|
+
return parseSourceCommand(verb === "install" ? "install" : "remove", rest);
|
|
114
|
+
}
|
|
115
|
+
if (verb === "list")
|
|
116
|
+
return withoutArguments(rest, { kind: "packages", request: { verb: "list", source: null } });
|
|
117
|
+
if (verb === "update")
|
|
118
|
+
return parsePiPackageUpdate(rest);
|
|
119
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`received an unknown pi package command: ${verb ?? ""}`) };
|
|
120
|
+
}
|
|
121
|
+
function parsePiPackageUpdate(rest) {
|
|
122
|
+
if (rest.length === 0) {
|
|
123
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`pi update needs --extensions or a package source.`) };
|
|
124
|
+
}
|
|
125
|
+
if (rest.length > 1)
|
|
126
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic("pi update accepts one target.") };
|
|
127
|
+
const [target] = rest;
|
|
128
|
+
if (target === "--extensions")
|
|
129
|
+
return { kind: "packages", request: { verb: "update", source: null } };
|
|
130
|
+
if (target === "--models") {
|
|
131
|
+
return { kind: "error", message: PRODUCT_TEXT.diagnostic(`refreshes its model catalogs at the top level; run ${PRODUCT_TEXT.commandName} update --models.`) };
|
|
132
|
+
}
|
|
103
133
|
if (target === undefined || target.startsWith("-"))
|
|
104
|
-
return unknownOption(target ?? "", "update");
|
|
134
|
+
return unknownOption(target ?? "", "pi update");
|
|
105
135
|
if (PROFILE_WORDS.has(target))
|
|
106
136
|
return profileRejection("update");
|
|
107
137
|
return { kind: "packages", request: { verb: "update", source: target } };
|
|
@@ -129,6 +159,13 @@ function withoutArguments(rest, command) {
|
|
|
129
159
|
return profileRejection("list");
|
|
130
160
|
return { kind: "error", message: PRODUCT_TEXT.diagnostic("commands do not accept additional arguments.") };
|
|
131
161
|
}
|
|
162
|
+
function packageNamespaceRejection(verb, target) {
|
|
163
|
+
const suffix = target === undefined ? "" : ` ${target}`;
|
|
164
|
+
return {
|
|
165
|
+
kind: "error",
|
|
166
|
+
message: PRODUCT_TEXT.diagnostic(`manages extension packages under its pi namespace; run ${PRODUCT_TEXT.commandName} pi ${verb}${suffix}.`),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
132
169
|
function profileRejection(verb) {
|
|
133
170
|
return {
|
|
134
171
|
kind: "error",
|
|
@@ -11,6 +11,12 @@ export interface PackageCommandRequest {
|
|
|
11
11
|
readonly verb: PackageCommandVerb;
|
|
12
12
|
readonly source: string | null;
|
|
13
13
|
}
|
|
14
|
+
export interface PackageCommandStyle {
|
|
15
|
+
readonly dim: (message: string) => string;
|
|
16
|
+
readonly bold: (message: string) => string;
|
|
17
|
+
readonly green: (message: string) => string;
|
|
18
|
+
readonly red: (message: string) => string;
|
|
19
|
+
}
|
|
14
20
|
export interface PackageCommandEnvironment {
|
|
15
21
|
readonly createPort: (input: AgentPackagesPortInput) => AgentPackagesPort;
|
|
16
22
|
readonly cwd?: string;
|
|
@@ -18,6 +24,8 @@ export interface PackageCommandEnvironment {
|
|
|
18
24
|
readonly stdout?: (message: string) => void;
|
|
19
25
|
readonly stderr?: (message: string) => void;
|
|
20
26
|
readonly initializeProfile?: typeof initializeProductProfile;
|
|
27
|
+
/** Defaults to Chalk's terminal-aware styles; injectable for transcript tests. */
|
|
28
|
+
readonly style?: PackageCommandStyle;
|
|
21
29
|
}
|
|
22
30
|
export declare function runPackageCommand(request: PackageCommandRequest, environment: PackageCommandEnvironment): Promise<number>;
|
|
23
|
-
export declare function renderPackageOutcome(outcome: AgentPackageOutcome, profileRoot: string): string;
|
|
31
|
+
export declare function renderPackageOutcome(outcome: AgentPackageOutcome, profileRoot: string, style?: PackageCommandStyle): string;
|
package/dist/src/cli/packages.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
1
2
|
import { configurationRootForProfile, initializeProductProfile, resolveLaunchProfilePaths } from "../features/launch/index.js";
|
|
2
3
|
import { PRODUCT_TEXT } from "../product-identity.js";
|
|
3
4
|
export async function runPackageCommand(request, environment) {
|
|
@@ -5,6 +6,7 @@ export async function runPackageCommand(request, environment) {
|
|
|
5
6
|
const stderr = environment.stderr ?? (message => process.stderr.write(message));
|
|
6
7
|
const cwd = environment.cwd ?? process.cwd();
|
|
7
8
|
const processEnvironment = environment.environment ?? process.env;
|
|
9
|
+
const style = environment.style ?? chalk;
|
|
8
10
|
const paths = resolveLaunchProfilePaths({ environment: processEnvironment });
|
|
9
11
|
const profileRoot = configurationRootForProfile("a1", paths);
|
|
10
12
|
if (profileRoot === null)
|
|
@@ -19,10 +21,10 @@ export async function runPackageCommand(request, environment) {
|
|
|
19
21
|
const port = environment.createPort({
|
|
20
22
|
profileRoot,
|
|
21
23
|
cwd,
|
|
22
|
-
onProgress: progress => stdout(`${progress.message}\n`),
|
|
24
|
+
onProgress: progress => stdout(`${style.dim(progress.message)}\n`),
|
|
23
25
|
});
|
|
24
26
|
const outcome = await runVerb(port, request);
|
|
25
|
-
const rendered = renderPackageOutcome(outcome, profileRoot);
|
|
27
|
+
const rendered = renderPackageOutcome(outcome, profileRoot, style);
|
|
26
28
|
(outcome.status === "completed" ? stdout : stderr)(rendered);
|
|
27
29
|
return outcome.status === "completed" ? 0 : 1;
|
|
28
30
|
}
|
|
@@ -37,38 +39,40 @@ async function runVerb(port, request) {
|
|
|
37
39
|
throw new Error(PRODUCT_TEXT.diagnostic(`requires a source for ${request.verb}`));
|
|
38
40
|
return request.verb === "install" ? await port.install(request.source) : await port.remove(request.source);
|
|
39
41
|
}
|
|
40
|
-
export function renderPackageOutcome(outcome, profileRoot) {
|
|
41
|
-
|
|
42
|
+
export function renderPackageOutcome(outcome, profileRoot, style = chalk) {
|
|
43
|
+
// Model refresh remains an A1 top-level command. The `a1 pi` compatibility
|
|
44
|
+
// transcript applies to package operations only.
|
|
45
|
+
if (outcome.operation === "refresh-models") {
|
|
46
|
+
if (outcome.status === "failed") {
|
|
47
|
+
return `${PRODUCT_TEXT.diagnostic(`could not ${describeOperation(outcome.operation)}: ${outcome.detail ?? "unknown failure"}`)}\n`;
|
|
48
|
+
}
|
|
49
|
+
return `${PRODUCT_TEXT.displayName} refreshed the model catalogs in ${profileRoot}.\n`;
|
|
50
|
+
}
|
|
42
51
|
if (outcome.status === "failed") {
|
|
43
|
-
return `${
|
|
52
|
+
return `${style.red(`Error: ${outcome.detail ?? "Unknown package command error"}`)}\n`;
|
|
44
53
|
}
|
|
45
54
|
if (outcome.status === "not-found") {
|
|
46
|
-
return `${
|
|
55
|
+
return `${style.red(`No matching package found for ${outcome.source ?? "that source"}`)}\n`;
|
|
47
56
|
}
|
|
48
57
|
switch (outcome.operation) {
|
|
49
58
|
case "install":
|
|
50
|
-
return `${
|
|
51
|
-
+ `Restart ${PRODUCT_TEXT.commandName} for a running session to load it.\n`;
|
|
59
|
+
return `${style.green(`Installed ${outcome.source}`)}\n`;
|
|
52
60
|
case "remove":
|
|
53
|
-
return `${
|
|
61
|
+
return `${style.green(`Removed ${outcome.source}`)}\n`;
|
|
54
62
|
case "update":
|
|
55
|
-
return outcome.source === null
|
|
56
|
-
? `${name} updated the packages in ${profileRoot}.\n`
|
|
57
|
-
: `${name} updated ${outcome.source}.\n`;
|
|
58
|
-
case "refresh-models":
|
|
59
|
-
return `${name} refreshed the model catalogs in ${profileRoot}.\n`;
|
|
63
|
+
return `${style.green(outcome.source === null ? "Updated packages" : `Updated ${outcome.source}`)}\n`;
|
|
60
64
|
case "list":
|
|
61
|
-
return renderPackageList(outcome,
|
|
65
|
+
return renderPackageList(outcome, style);
|
|
62
66
|
}
|
|
63
67
|
}
|
|
64
|
-
function renderPackageList(outcome,
|
|
68
|
+
function renderPackageList(outcome, style) {
|
|
65
69
|
if (outcome.packages.length === 0)
|
|
66
|
-
return `${
|
|
67
|
-
const lines = [
|
|
70
|
+
return `${style.dim("No packages installed.")}\n`;
|
|
71
|
+
const lines = [style.bold("User packages:")];
|
|
68
72
|
for (const entry of outcome.packages) {
|
|
69
|
-
lines.push(` ${entry.source}${entry.filtered ? " (
|
|
73
|
+
lines.push(` ${entry.source}${entry.filtered ? " (filtered)" : ""}`);
|
|
70
74
|
if (entry.installedPath !== null)
|
|
71
|
-
lines.push(` ${entry.installedPath}`);
|
|
75
|
+
lines.push(style.dim(` ${entry.installedPath}`));
|
|
72
76
|
}
|
|
73
77
|
return `${lines.join("\n")}\n`;
|
|
74
78
|
}
|
|
@@ -21,7 +21,7 @@ export async function runVersionStats(options) {
|
|
|
21
21
|
return 1;
|
|
22
22
|
}
|
|
23
23
|
const remote = await queryDistTags(runner);
|
|
24
|
-
output.stdout(`Installed: ${installed}\nRelease: ${remote.release ?? "unavailable"}\
|
|
24
|
+
output.stdout(`Installed: ${installed}\nRelease: ${remote.release ?? "unavailable"}\nDevelop: ${remote.develop ?? "unavailable"}\n`);
|
|
25
25
|
if (remote.error)
|
|
26
26
|
output.stderr(`${PRODUCT_TEXT.diagnostic(`could not resolve npm dist-tags: ${remote.error}`)}\n`);
|
|
27
27
|
return 0;
|
|
@@ -42,15 +42,15 @@ async function queryDistTags(runner) {
|
|
|
42
42
|
throw new TypeError("npm returned a non-object dist-tags value");
|
|
43
43
|
const tags = metadata;
|
|
44
44
|
const release = parseVersion(tags.latest, "npm latest");
|
|
45
|
-
const
|
|
46
|
-
return { release,
|
|
45
|
+
const develop = tags.next === undefined ? null : parseVersion(tags.next, "npm development channel");
|
|
46
|
+
return { release, develop, error: null };
|
|
47
47
|
}
|
|
48
48
|
catch (error) {
|
|
49
49
|
return unavailable(message(error));
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
function unavailable(error) {
|
|
53
|
-
return { release: null,
|
|
53
|
+
return { release: null, develop: null, error };
|
|
54
54
|
}
|
|
55
55
|
function createVersionProcessRunner() {
|
|
56
56
|
return async (command, arguments_) => await new Promise((resolvePromise, rejectPromise) => {
|
|
@@ -3,7 +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 { applyConfiguredPiTheme, getAvailablePiThemes } from "./upstream/theme/theme.js";
|
|
6
|
+
export { applyConfiguredPiTheme, getAvailablePiThemes, onPiThemeChange } from "./upstream/theme/theme.js";
|
|
7
7
|
export * from "./upstream/components/countdown-timer.js";
|
|
8
8
|
export * from "./upstream/components/extension-editor.js";
|
|
9
9
|
export * from "./upstream/components/session-selector.js";
|
|
@@ -3,7 +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 { applyConfiguredPiTheme, getAvailablePiThemes } from "./upstream/theme/theme.js";
|
|
6
|
+
export { applyConfiguredPiTheme, getAvailablePiThemes, onPiThemeChange } from "./upstream/theme/theme.js";
|
|
7
7
|
export * from "./upstream/components/countdown-timer.js";
|
|
8
8
|
export * from "./upstream/components/extension-editor.js";
|
|
9
9
|
export * from "./upstream/components/session-selector.js";
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AssistantMessageComponent, BashExecutionComponent, CompactionSummaryMessageComponent, CustomMessageComponent, DynamicBorder, getMarkdownTheme, parseSkillBlock, ToolExecutionComponent, UserMessageComponent, } from "@earendil-works/pi-coding-agent";
|
|
2
2
|
import { SkillInvocationMessageComponent, } from "./upstream/components/skill-invocation-message.js";
|
|
3
3
|
import { Container, Markdown, Spacer, Text, } from "#pi-tui";
|
|
4
|
+
import { PRODUCT_TEXT } from "../../product-identity.js";
|
|
4
5
|
import { KeybindingsManager, } from "./upstream/adjacent/core/keybindings.js";
|
|
5
6
|
import { PINNED_PI_LAYOUT, piTheme, } from "./theme.js";
|
|
6
7
|
import { componentPort, createTuiFacade, ensureTheme, formatSessionTokens, isRecord, } from "./shell-shared-facade.js";
|
|
@@ -168,7 +169,7 @@ export function renderPiShellPackageUpdateNotice(packages, width) {
|
|
|
168
169
|
container.addChild(new Spacer(1));
|
|
169
170
|
container.addChild(new DynamicBorder(text => theme.fg("warning", text)));
|
|
170
171
|
container.addChild(new Text(`${theme.bold(theme.fg("warning", "Package Updates Available"))}\n`
|
|
171
|
-
+ `${theme.fg("muted", "Package updates are available. Run ")}${theme.fg("accent",
|
|
172
|
+
+ `${theme.fg("muted", "Package updates are available. Run ")}${theme.fg("accent", `${PRODUCT_TEXT.commandName} pi update --extensions`)}\n`
|
|
172
173
|
+ `${theme.fg("muted", "Packages:")}\n`
|
|
173
174
|
+ packages.map(name => `- ${name}`).join("\n"), 1, 0));
|
|
174
175
|
container.addChild(new DynamicBorder(text => theme.fg("warning", text)));
|
|
@@ -60,11 +60,18 @@ export interface OwnedPiResourceSummary {
|
|
|
60
60
|
readonly sourcePath: string | null;
|
|
61
61
|
readonly diagnostic: string | null;
|
|
62
62
|
}
|
|
63
|
+
export interface OwnedPiExtensionSourceSummary {
|
|
64
|
+
readonly source: string;
|
|
65
|
+
readonly scope: "user" | "project" | "temporary";
|
|
66
|
+
readonly origin: "package" | "top-level";
|
|
67
|
+
readonly baseDir: string | null;
|
|
68
|
+
}
|
|
63
69
|
export interface OwnedPiExtensionResourceSummary {
|
|
64
70
|
readonly kind: "extension";
|
|
65
71
|
readonly id: string;
|
|
66
72
|
readonly sourcePath: string | null;
|
|
67
73
|
readonly resolvedPath: string | null;
|
|
74
|
+
readonly sourceInfo: OwnedPiExtensionSourceSummary | null;
|
|
68
75
|
readonly loaded: boolean;
|
|
69
76
|
readonly hidden: boolean;
|
|
70
77
|
readonly diagnostic: string | null;
|