@thieung/agentkit-helper 0.1.3 → 0.1.5
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 +18 -4
- package/README.vi.md +18 -4
- package/bin/agentkit-helper.mjs +108 -49
- package/lib/args.mjs +29 -5
- package/lib/commands.mjs +36 -0
- package/lib/i18n.mjs +6 -2
- package/lib/pi-profiles.mjs +45 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -31,8 +31,11 @@ In the TUI, use:
|
|
|
31
31
|
- Esc to return to the previous step
|
|
32
32
|
|
|
33
33
|
Choose a project or user/global scope, Engineer or Marketing Kit, one or more
|
|
34
|
-
runtimes, and the Stable or Beta channel.
|
|
35
|
-
|
|
34
|
+
runtimes, and the Stable or Beta channel. When the current directory is a safe
|
|
35
|
+
project path (not `/` or your home directory), the TUI offers **Use current
|
|
36
|
+
project**; the equivalent CLI flag is `--project .`. AgentKit remains
|
|
37
|
+
responsible for Kit verification, ownership, snapshots, and runtime-specific
|
|
38
|
+
files.
|
|
36
39
|
|
|
37
40
|
For global install, the helper first runs without `--force`. If the target
|
|
38
41
|
already exists or drift is detected, the TUI shows a WARNING and asks for
|
|
@@ -46,6 +49,15 @@ it passes a real-machine smoke test; the repository includes Windows-oriented
|
|
|
46
49
|
command handling and CI coverage, but does not yet claim provider-backed E2E
|
|
47
50
|
verification.
|
|
48
51
|
|
|
52
|
+
Windows smoke checklist (manual; keep experimental until this passes on a real
|
|
53
|
+
machine):
|
|
54
|
+
|
|
55
|
+
1. Install `ak` with `irm https://agentkit.best/install.ps1 | iex`, then open a
|
|
56
|
+
new terminal.
|
|
57
|
+
2. Run `npx --yes @thieung/agentkit-helper` (or `akh` after a global npm install).
|
|
58
|
+
3. In the TUI, choose **Use current project** (or `akh install --project .`).
|
|
59
|
+
4. Install one runtime, then run `update-all` for that install.
|
|
60
|
+
|
|
49
61
|
<details>
|
|
50
62
|
<summary><strong>Advanced CLI usage</strong></summary>
|
|
51
63
|
|
|
@@ -79,10 +91,12 @@ akh update --project /path/to/project --dry-run
|
|
|
79
91
|
|
|
80
92
|
Targets:
|
|
81
93
|
|
|
82
|
-
- Install: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`
|
|
83
|
-
- Update: `claude-code`, `codex`, `cursor`, `grok`, `omp`, `pi`
|
|
94
|
+
- Install: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`, `pi-ak`, `pi-omp`
|
|
95
|
+
- Update: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`, `pi-ak`, `pi-omp`
|
|
84
96
|
- Export: `agy`, `portable`
|
|
85
97
|
|
|
98
|
+
`dsh` updates use `ak kit refresh` because remote `ak update` still rejects that runtime. `pi-ak` and `pi-omp` are global-only profile aliases (`--global`); they install/update into the custom Pi/OMP homes instead of the default `pi`/`omp` directories.
|
|
99
|
+
|
|
86
100
|
Run `akh --help` for every command and option.
|
|
87
101
|
|
|
88
102
|
</details>
|
package/README.vi.md
CHANGED
|
@@ -30,8 +30,10 @@ Trong TUI, dùng:
|
|
|
30
30
|
- Esc để trở về bước trước
|
|
31
31
|
|
|
32
32
|
Bạn chỉ cần chọn scope project hoặc user/global, Engineer hoặc Marketing Kit,
|
|
33
|
-
một hay nhiều runtime và release channel Stable hoặc Beta.
|
|
34
|
-
|
|
33
|
+
một hay nhiều runtime và release channel Stable hoặc Beta. Khi thư mục hiện tại
|
|
34
|
+
là project hợp lệ (không phải `/` hay home), TUI có **Dùng project hiện tại**;
|
|
35
|
+
CLI tương đương là `--project .`. AgentKit vẫn quản lý việc xác minh Kit,
|
|
36
|
+
ownership, snapshot và file riêng của từng runtime.
|
|
35
37
|
|
|
36
38
|
Khi cài global scope, helper chạy trước mà không có `--force`. Nếu target đã
|
|
37
39
|
tồn tại hoặc có drift, TUI hiển thị WARNING và hỏi consent riêng, mặc định No.
|
|
@@ -43,6 +45,16 @@ qua code path Node.js portable. Native Windows PowerShell đang ở mức
|
|
|
43
45
|
experimental cho đến khi được smoke-test trên máy thật; repository đã có xử lý
|
|
44
46
|
command và CI dành cho Windows nhưng chưa claim provider-backed E2E.
|
|
45
47
|
|
|
48
|
+
Checklist smoke Windows (thủ công; giữ experimental cho đến khi chạy xong trên
|
|
49
|
+
máy thật):
|
|
50
|
+
|
|
51
|
+
1. Cài `ak` bằng `irm https://agentkit.best/install.ps1 | iex`, rồi mở terminal
|
|
52
|
+
mới.
|
|
53
|
+
2. Chạy `npx --yes @thieung/agentkit-helper` (hoặc `akh` sau khi npm install
|
|
54
|
+
global).
|
|
55
|
+
3. Trong TUI, chọn **Dùng project hiện tại** (hoặc `akh install --project .`).
|
|
56
|
+
4. Cài một runtime, rồi chạy `update-all` cho install đó.
|
|
57
|
+
|
|
46
58
|
<details>
|
|
47
59
|
<summary><strong>Cách dùng CLI nâng cao</strong></summary>
|
|
48
60
|
|
|
@@ -76,10 +88,12 @@ akh update --project /path/to/project --dry-run
|
|
|
76
88
|
|
|
77
89
|
Các target:
|
|
78
90
|
|
|
79
|
-
- Cài đặt: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`
|
|
80
|
-
- Cập nhật: `claude-code`, `codex`, `cursor`, `grok`, `omp`, `pi`
|
|
91
|
+
- Cài đặt: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`, `pi-ak`, `pi-omp`
|
|
92
|
+
- Cập nhật: `claude-code`, `codex`, `cursor`, `dsh`, `grok`, `omp`, `pi`, `pi-ak`, `pi-omp`
|
|
81
93
|
- Export: `agy`, `portable`
|
|
82
94
|
|
|
95
|
+
Update `dsh` đi qua `ak kit refresh` vì `ak update` remote vẫn reject runtime này. `pi-ak` và `pi-omp` là alias profile chỉ dùng với `--global`; chúng cài/cập nhật vào home Pi/OMP custom, không phải thư mục `pi`/`omp` mặc định.
|
|
96
|
+
|
|
83
97
|
Chạy `akh --help` để xem toàn bộ command và option.
|
|
84
98
|
|
|
85
99
|
</details>
|
package/bin/agentkit-helper.mjs
CHANGED
|
@@ -6,9 +6,10 @@ import { dirname, resolve } from "node:path";
|
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
import {
|
|
8
8
|
EXPORT_TARGETS,
|
|
9
|
-
|
|
9
|
+
helperRuntimeTargets,
|
|
10
10
|
KITS,
|
|
11
11
|
parseArgs,
|
|
12
|
+
specHasProfileTarget,
|
|
12
13
|
splitTargetSpec,
|
|
13
14
|
targetSpecIsSupported,
|
|
14
15
|
UPDATE_TARGETS,
|
|
@@ -21,14 +22,17 @@ import {
|
|
|
21
22
|
globalUpdateApplyArgs,
|
|
22
23
|
globalUpdatePreviewArgs,
|
|
23
24
|
installArgs,
|
|
25
|
+
kitRefreshArgs,
|
|
24
26
|
projectUpdateApplyArgs,
|
|
25
27
|
projectUpdatePreviewArgs,
|
|
26
28
|
selfUpdateCheckArgs,
|
|
27
29
|
selfUpdateApplyArgs,
|
|
28
30
|
selfUpdateJsonApplyArgs,
|
|
29
31
|
selfUpdateJsonCheckArgs,
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
splitRuntimesForUpdate,
|
|
33
|
+
updateApplyArgsForRuntime,
|
|
34
|
+
updatePreviewArgsForRuntime,
|
|
35
|
+
usesKitRefresh,
|
|
32
36
|
} from "../lib/commands.mjs";
|
|
33
37
|
import { readProjectConfig, writeProjectConfig } from "../lib/config.mjs";
|
|
34
38
|
import { colorText } from "../lib/colors.mjs";
|
|
@@ -48,6 +52,7 @@ import { t } from "../lib/i18n.mjs";
|
|
|
48
52
|
import { isUnsafeProjectPath, resolveProjectPath } from "../lib/project.mjs";
|
|
49
53
|
import {
|
|
50
54
|
classifyPiProfiles,
|
|
55
|
+
materializeHelperTarget,
|
|
51
56
|
parsePiProfileInventory,
|
|
52
57
|
piProfileManagerInvocation,
|
|
53
58
|
piProfileProcessOptions,
|
|
@@ -140,8 +145,8 @@ Tùy chọn:
|
|
|
140
145
|
--version, -v Hiện phiên bản
|
|
141
146
|
|
|
142
147
|
Target groups:
|
|
143
|
-
Install claude-code, codex, cursor, dsh, grok, omp, pi
|
|
144
|
-
Update claude-code, codex, cursor, grok, omp, pi
|
|
148
|
+
Install claude-code, codex, cursor, dsh, grok, omp, pi, pi-ak, pi-omp
|
|
149
|
+
Update claude-code, codex, cursor, dsh, grok, omp, pi, pi-ak, pi-omp
|
|
145
150
|
Export agy, portable
|
|
146
151
|
`);
|
|
147
152
|
return;
|
|
@@ -177,8 +182,8 @@ Options:
|
|
|
177
182
|
--version, -v Show version
|
|
178
183
|
|
|
179
184
|
Target groups:
|
|
180
|
-
Install claude-code, codex, cursor, dsh, grok, omp, pi
|
|
181
|
-
Update claude-code, codex, cursor, grok, omp, pi
|
|
185
|
+
Install claude-code, codex, cursor, dsh, grok, omp, pi, pi-ak, pi-omp
|
|
186
|
+
Update claude-code, codex, cursor, dsh, grok, omp, pi, pi-ak, pi-omp
|
|
182
187
|
Export agy, portable
|
|
183
188
|
`);
|
|
184
189
|
}
|
|
@@ -369,15 +374,11 @@ async function selectTarget(
|
|
|
369
374
|
const allRuntimeValue = "__all_runtimes__";
|
|
370
375
|
const choices = [
|
|
371
376
|
{ label: ui("allRuntimes"), value: allRuntimeValue },
|
|
372
|
-
...[...targets].map((target) => ({
|
|
377
|
+
...[...targets].map((target) => ({
|
|
378
|
+
label: target === "pi-ak" ? ui("piAkProfile") : target === "pi-omp" ? ui("piOmpProfile") : target,
|
|
379
|
+
value: target,
|
|
380
|
+
})),
|
|
373
381
|
];
|
|
374
|
-
if (promptKey === "updateTargetPrompt") {
|
|
375
|
-
choices.push({
|
|
376
|
-
label: ui("dshUpdateUnsupported"),
|
|
377
|
-
value: "dsh",
|
|
378
|
-
disabled: true,
|
|
379
|
-
});
|
|
380
|
-
}
|
|
381
382
|
const initialValues = [];
|
|
382
383
|
const selected = await (allowBack ? multiChooseWithBack : multiChoose)(
|
|
383
384
|
ui(promptKey, promptValues),
|
|
@@ -415,10 +416,6 @@ function warnBetaLifecycle(channel) {
|
|
|
415
416
|
}
|
|
416
417
|
|
|
417
418
|
async function prepareBetaBinary(commandOptions, { requiresPreview = false } = {}) {
|
|
418
|
-
const currentVersion = installedAkVersion.replace(/^ak\s+/i, "");
|
|
419
|
-
if (!currentVersion || currentVersion.includes("-")) {
|
|
420
|
-
return { proceed: true, updated: false };
|
|
421
|
-
}
|
|
422
419
|
warnBetaLifecycle("beta");
|
|
423
420
|
const check = parseSelfUpdateOutput((await runCapture(
|
|
424
421
|
akBinary, selfUpdateJsonCheckArgs("beta"),
|
|
@@ -472,7 +469,9 @@ async function install(commandOptions, allowBack = false) {
|
|
|
472
469
|
{
|
|
473
470
|
key: "target",
|
|
474
471
|
select: (values) => selectTarget(
|
|
475
|
-
commandOptions, config,
|
|
472
|
+
commandOptions, config, helperRuntimeTargets({
|
|
473
|
+
command: "install", global: scope.global,
|
|
474
|
+
}), "targetPrompt", routeCanGoBack, allowBack,
|
|
476
475
|
{ kit: kitName(values.kit) },
|
|
477
476
|
),
|
|
478
477
|
},
|
|
@@ -482,12 +481,16 @@ async function install(commandOptions, allowBack = false) {
|
|
|
482
481
|
if (!scopeWasPrompted) return BACK;
|
|
483
482
|
}
|
|
484
483
|
const selection = { ...scope, ...route };
|
|
484
|
+
if (specHasProfileTarget(selection.target) && !selection.global) {
|
|
485
|
+
throw new Error(ui("profileTargetsNeedGlobal"));
|
|
486
|
+
}
|
|
487
|
+
const profiles = specHasProfileTarget(selection.target) ? await loadPiProfilesQuiet() : [];
|
|
485
488
|
const installSelections = splitTargetSpec(selection.target)
|
|
486
|
-
.map((target) => ({ ...selection, target }));
|
|
489
|
+
.map((target) => materializeHelperTarget({ ...selection, target }, profiles));
|
|
487
490
|
|
|
488
491
|
printSection(ui("installPlan"));
|
|
489
492
|
for (const targetSelection of installSelections) {
|
|
490
|
-
printPlan(installArgs(targetSelection), targetSelection.project);
|
|
493
|
+
printPlan(installArgs(targetSelection), targetSelection.project, targetSelection.envOverrides);
|
|
491
494
|
}
|
|
492
495
|
if (commandOptions.dryRun) {
|
|
493
496
|
process.stdout.write(`\n${ui("dryRunFiles")}\n`);
|
|
@@ -504,12 +507,17 @@ async function install(commandOptions, allowBack = false) {
|
|
|
504
507
|
|
|
505
508
|
for (const targetSelection of installSelections) {
|
|
506
509
|
const cwd = targetSelection.project || process.cwd();
|
|
510
|
+
const runOptions = {
|
|
511
|
+
cwd,
|
|
512
|
+
envOverrides: targetSelection.envOverrides,
|
|
513
|
+
envUnset: targetSelection.envUnset,
|
|
514
|
+
};
|
|
507
515
|
try {
|
|
508
|
-
await runAkCommand(installArgs(targetSelection),
|
|
516
|
+
await runAkCommand(installArgs(targetSelection), runOptions);
|
|
509
517
|
} catch (error) {
|
|
510
518
|
if (!requiresForceConsent(error)) throw error;
|
|
511
519
|
warning(ui(targetSelection.global ? "globalForceWarning" : "projectForceWarning", {
|
|
512
|
-
target: targetSelection.target,
|
|
520
|
+
target: targetSelection.helperTarget || targetSelection.target,
|
|
513
521
|
}));
|
|
514
522
|
if (!process.stdin.isTTY || !process.stdout.isTTY) {
|
|
515
523
|
error.message = `${error.message}\n${ui("forceNeedsConsent")}`;
|
|
@@ -521,8 +529,8 @@ async function install(commandOptions, allowBack = false) {
|
|
|
521
529
|
}
|
|
522
530
|
const forceArgs = installArgs(targetSelection, { force: true });
|
|
523
531
|
printSection(ui("forceInstallPlan"));
|
|
524
|
-
printPlan(forceArgs, targetSelection.project);
|
|
525
|
-
await runAkCommand(forceArgs,
|
|
532
|
+
printPlan(forceArgs, targetSelection.project, targetSelection.envOverrides);
|
|
533
|
+
await runAkCommand(forceArgs, runOptions);
|
|
526
534
|
}
|
|
527
535
|
}
|
|
528
536
|
if (selection.project && !commandOptions.noSave) {
|
|
@@ -695,7 +703,9 @@ async function update(commandOptions, allowBack = false) {
|
|
|
695
703
|
{
|
|
696
704
|
key: "target",
|
|
697
705
|
select: (values) => selectTarget(
|
|
698
|
-
commandOptions, config,
|
|
706
|
+
commandOptions, config, helperRuntimeTargets({
|
|
707
|
+
command: "update", global: scope.global,
|
|
708
|
+
}), "updateTargetPrompt", routeCanGoBack, allowBack,
|
|
699
709
|
{ kit: kitName(values.kit) },
|
|
700
710
|
),
|
|
701
711
|
},
|
|
@@ -718,9 +728,13 @@ async function update(commandOptions, allowBack = false) {
|
|
|
718
728
|
...scope,
|
|
719
729
|
channel,
|
|
720
730
|
};
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
731
|
+
if (specHasProfileTarget(selection.target) && !selection.global) {
|
|
732
|
+
throw new Error(ui("profileTargetsNeedGlobal"));
|
|
733
|
+
}
|
|
734
|
+
const profiles = specHasProfileTarget(selection.target) ? await loadPiProfilesQuiet() : [];
|
|
735
|
+
const updateSelections = splitTargetSpec(selection.target).map((target) => (
|
|
736
|
+
materializeHelperTarget({ ...selection, target }, profiles)
|
|
737
|
+
));
|
|
724
738
|
if (selection.global) warning(ui("globalUpdateSafety"));
|
|
725
739
|
if (channel === "beta") {
|
|
726
740
|
const betaBinary = await prepareBetaBinary(commandOptions, { requiresPreview: true });
|
|
@@ -730,15 +744,24 @@ async function update(commandOptions, allowBack = false) {
|
|
|
730
744
|
printSection(ui("updatePreview"));
|
|
731
745
|
for (const targetSelection of updateSelections) {
|
|
732
746
|
if (updateSelections.length > 1) {
|
|
733
|
-
process.stdout.write(`${colorText(targetSelection.
|
|
747
|
+
process.stdout.write(`${colorText(targetSelection.helperTarget, "target")}\n`);
|
|
748
|
+
}
|
|
749
|
+
const previewArgs = updatePreviewArgsForRuntime(targetSelection);
|
|
750
|
+
if (previewArgs) {
|
|
751
|
+
await runAkCommand(previewArgs, {
|
|
752
|
+
cwd: targetSelection.project || process.cwd(),
|
|
753
|
+
envOverrides: targetSelection.envOverrides,
|
|
754
|
+
envUnset: targetSelection.envUnset,
|
|
755
|
+
});
|
|
734
756
|
}
|
|
735
|
-
await runAkCommand(updatePreviewArgs(targetSelection), {
|
|
736
|
-
cwd: targetSelection.project || process.cwd(),
|
|
737
|
-
});
|
|
738
757
|
}
|
|
739
758
|
printSection(ui("applyPlan"));
|
|
740
759
|
for (const targetSelection of updateSelections) {
|
|
741
|
-
printPlan(
|
|
760
|
+
printPlan(
|
|
761
|
+
updateApplyArgsForRuntime(targetSelection),
|
|
762
|
+
targetSelection.project,
|
|
763
|
+
targetSelection.envOverrides,
|
|
764
|
+
);
|
|
742
765
|
}
|
|
743
766
|
if (commandOptions.dryRun) {
|
|
744
767
|
process.stdout.write(`\n${ui("dryRunFiles")}\n`);
|
|
@@ -750,8 +773,10 @@ async function update(commandOptions, allowBack = false) {
|
|
|
750
773
|
}
|
|
751
774
|
|
|
752
775
|
for (const targetSelection of updateSelections) {
|
|
753
|
-
await runAkCommand(
|
|
776
|
+
await runAkCommand(updateApplyArgsForRuntime(targetSelection), {
|
|
754
777
|
cwd: targetSelection.project || process.cwd(),
|
|
778
|
+
envOverrides: targetSelection.envOverrides,
|
|
779
|
+
envUnset: targetSelection.envUnset,
|
|
755
780
|
});
|
|
756
781
|
}
|
|
757
782
|
if (selection.project && !commandOptions.noSave) {
|
|
@@ -760,18 +785,34 @@ async function update(commandOptions, allowBack = false) {
|
|
|
760
785
|
process.stdout.write(`${ui("updateComplete")}\n`);
|
|
761
786
|
}
|
|
762
787
|
|
|
763
|
-
function
|
|
764
|
-
|
|
765
|
-
|
|
788
|
+
function updateAllCommandPlans(candidate, channel) {
|
|
789
|
+
const kit = candidate.kit;
|
|
790
|
+
if (candidate.kind === "project") {
|
|
791
|
+
if (usesKitRefresh(candidate.runtime)) {
|
|
792
|
+
return [{ preview: null, apply: kitRefreshArgs({
|
|
793
|
+
global: false, kit, channel, target: candidate.runtime,
|
|
794
|
+
}) }];
|
|
795
|
+
}
|
|
796
|
+
return [{
|
|
797
|
+
preview: projectUpdatePreviewArgs(candidate.path, candidate.runtime, channel, kit),
|
|
798
|
+
apply: projectUpdateApplyArgs(candidate.path, candidate.runtime, channel, kit),
|
|
799
|
+
}];
|
|
800
|
+
}
|
|
801
|
+
const { update, refresh } = splitRuntimesForUpdate(candidate.runtimes);
|
|
802
|
+
const plans = [];
|
|
803
|
+
if (update.length > 0) {
|
|
804
|
+
plans.push({
|
|
805
|
+
preview: globalUpdatePreviewArgs(channel, update, kit),
|
|
806
|
+
apply: globalUpdateApplyArgs(channel, update, kit),
|
|
807
|
+
});
|
|
766
808
|
}
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
return globalUpdateApplyArgs(channel, candidate.runtimes, candidate.kit);
|
|
809
|
+
for (const runtime of refresh) {
|
|
810
|
+
plans.push({
|
|
811
|
+
preview: null,
|
|
812
|
+
apply: kitRefreshArgs({ global: true, kit, channel, target: runtime }),
|
|
813
|
+
});
|
|
773
814
|
}
|
|
774
|
-
return
|
|
815
|
+
return plans;
|
|
775
816
|
}
|
|
776
817
|
|
|
777
818
|
async function askDeepScanRoots() {
|
|
@@ -858,6 +899,18 @@ function orderUpdateCandidates(candidates) {
|
|
|
858
899
|
return [...candidates].sort((left, right) => priority[left.kind] - priority[right.kind]);
|
|
859
900
|
}
|
|
860
901
|
|
|
902
|
+
async function loadPiProfilesQuiet() {
|
|
903
|
+
try {
|
|
904
|
+
const inventory = await runCapture(piProfileManager.binary, [
|
|
905
|
+
...piProfileManager.prefixArgs,
|
|
906
|
+
"profiles", "list", "--json",
|
|
907
|
+
]);
|
|
908
|
+
return parsePiProfileInventory(inventory.stdout);
|
|
909
|
+
} catch {
|
|
910
|
+
return [];
|
|
911
|
+
}
|
|
912
|
+
}
|
|
913
|
+
|
|
861
914
|
async function loadUpdateInventory(commandOptions, deepScanRoots) {
|
|
862
915
|
const registry = await withSpinner(
|
|
863
916
|
ui("loadingRegistry"),
|
|
@@ -1012,11 +1065,15 @@ async function updateAll(commandOptions, allowBack = false) {
|
|
|
1012
1065
|
printSection(ui("updateAllPreview"));
|
|
1013
1066
|
for (const candidate of selected) {
|
|
1014
1067
|
process.stdout.write(`\n${colorText(candidate.label, "target")}\n`);
|
|
1015
|
-
|
|
1068
|
+
for (const plan of updateAllCommandPlans(candidate, channel)) {
|
|
1069
|
+
if (plan.preview) await runAkCommand(plan.preview, candidate);
|
|
1070
|
+
}
|
|
1016
1071
|
}
|
|
1017
1072
|
printSection(ui("updateAllApplyPlan"));
|
|
1018
1073
|
for (const candidate of selected) {
|
|
1019
|
-
|
|
1074
|
+
for (const plan of updateAllCommandPlans(candidate, channel)) {
|
|
1075
|
+
printPlan(plan.apply, null, candidate.envOverrides);
|
|
1076
|
+
}
|
|
1020
1077
|
}
|
|
1021
1078
|
if (commandOptions.dryRun) {
|
|
1022
1079
|
process.stdout.write(`\n${ui("dryRunFiles")}\n`);
|
|
@@ -1032,7 +1089,9 @@ async function updateAll(commandOptions, allowBack = false) {
|
|
|
1032
1089
|
total: selected.length,
|
|
1033
1090
|
label: candidate.label,
|
|
1034
1091
|
})}\n`);
|
|
1035
|
-
|
|
1092
|
+
for (const plan of updateAllCommandPlans(candidate, channel)) {
|
|
1093
|
+
await runAkCommand(plan.apply, candidate);
|
|
1094
|
+
}
|
|
1036
1095
|
}
|
|
1037
1096
|
process.stdout.write(`${ui("updateAllComplete")}\n`);
|
|
1038
1097
|
return;
|
package/lib/args.mjs
CHANGED
|
@@ -4,10 +4,16 @@ export const COMMANDS = new Set([
|
|
|
4
4
|
export const INSTALL_TARGETS = new Set([
|
|
5
5
|
"claude-code", "codex", "cursor", "dsh", "grok", "omp", "pi",
|
|
6
6
|
]);
|
|
7
|
-
export const UPDATE_TARGETS = new Set([
|
|
7
|
+
export const UPDATE_TARGETS = new Set([
|
|
8
|
+
"claude-code", "codex", "cursor", "dsh", "grok", "omp", "pi",
|
|
9
|
+
]);
|
|
10
|
+
export const PROFILE_TARGETS = new Set(["pi-ak", "pi-omp"]);
|
|
11
|
+
export const PROFILE_RUNTIME = { "pi-ak": "pi", "pi-omp": "omp" };
|
|
12
|
+
export const HELPER_INSTALL_TARGETS = new Set([...INSTALL_TARGETS, ...PROFILE_TARGETS]);
|
|
13
|
+
export const HELPER_UPDATE_TARGETS = new Set([...UPDATE_TARGETS, ...PROFILE_TARGETS]);
|
|
8
14
|
export const EXPORT_TARGETS = new Set(["agy", "portable"]);
|
|
9
|
-
export const RUNTIME_TARGETS = new Set([...
|
|
10
|
-
export const KNOWN_TARGETS = new Set([...
|
|
15
|
+
export const RUNTIME_TARGETS = new Set([...HELPER_INSTALL_TARGETS]);
|
|
16
|
+
export const KNOWN_TARGETS = new Set([...HELPER_INSTALL_TARGETS, ...EXPORT_TARGETS]);
|
|
11
17
|
export const CHANNELS = new Set(["stable", "beta"]);
|
|
12
18
|
export const LANGUAGES = new Set(["vi", "en"]);
|
|
13
19
|
export const KITS = new Set(["engineer", "marketing"]);
|
|
@@ -21,6 +27,22 @@ export function targetSpecIsSupported(value, supportedTargets) {
|
|
|
21
27
|
return targets.length > 0 && targets.every((target) => supportedTargets.has(target));
|
|
22
28
|
}
|
|
23
29
|
|
|
30
|
+
export function specHasProfileTarget(value) {
|
|
31
|
+
return splitTargetSpec(value).some((target) => PROFILE_TARGETS.has(target));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export function helperRuntimeTargets({ command, global = false } = {}) {
|
|
35
|
+
const base = command === "update" ? UPDATE_TARGETS : INSTALL_TARGETS;
|
|
36
|
+
return global ? new Set([...base, ...PROFILE_TARGETS]) : new Set(base);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export function assertProfileTargetsAreGlobal(options) {
|
|
40
|
+
const selectedTarget = options.target || options.runtime;
|
|
41
|
+
if (specHasProfileTarget(selectedTarget) && options.project) {
|
|
42
|
+
throw new Error("pi-ak and pi-omp are global profile targets; use --global");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
24
46
|
export function validateForCommand(options) {
|
|
25
47
|
const selectedTarget = options.target || options.runtime;
|
|
26
48
|
const hasDiscoveryOptions = options.deepScanRoots.length > 0 ||
|
|
@@ -36,18 +58,20 @@ export function validateForCommand(options) {
|
|
|
36
58
|
return;
|
|
37
59
|
}
|
|
38
60
|
if (options.command === "install") {
|
|
39
|
-
if (selectedTarget && !targetSpecIsSupported(selectedTarget,
|
|
61
|
+
if (selectedTarget && !targetSpecIsSupported(selectedTarget, HELPER_INSTALL_TARGETS)) {
|
|
40
62
|
throw new Error(`target ${selectedTarget} is export-only; use the export command`);
|
|
41
63
|
}
|
|
64
|
+
assertProfileTargetsAreGlobal(options);
|
|
42
65
|
if (options.out) throw new Error("--out is valid only with export");
|
|
43
66
|
if (options.allowDowngrade) throw new Error("--allow-downgrade is valid only with self-update or update --binary-only");
|
|
44
67
|
if (hasDiscoveryOptions) throw new Error("deep scan options are valid only with update-all");
|
|
45
68
|
return;
|
|
46
69
|
}
|
|
47
70
|
if (options.command === "update") {
|
|
48
|
-
if (selectedTarget && !targetSpecIsSupported(selectedTarget,
|
|
71
|
+
if (selectedTarget && !targetSpecIsSupported(selectedTarget, HELPER_UPDATE_TARGETS)) {
|
|
49
72
|
throw new Error(`target ${selectedTarget} is not supported by ak update`);
|
|
50
73
|
}
|
|
74
|
+
assertProfileTargetsAreGlobal(options);
|
|
51
75
|
if (options.out) throw new Error("--out is valid only with export");
|
|
52
76
|
if (options.allowDowngrade && !options.binaryOnly) {
|
|
53
77
|
throw new Error("--allow-downgrade requires update --binary-only");
|
package/lib/commands.mjs
CHANGED
|
@@ -51,6 +51,42 @@ export function updateApplyArgs(selection) {
|
|
|
51
51
|
return [...updateBase(selection), "--yes", "--verbose"];
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
export function usesKitRefresh(runtime) {
|
|
55
|
+
return runtime === "dsh";
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function kitRefreshArgs({
|
|
59
|
+
global, kit = "engineer", channel, target = "dsh",
|
|
60
|
+
}) {
|
|
61
|
+
return [
|
|
62
|
+
"kit",
|
|
63
|
+
"refresh",
|
|
64
|
+
kit,
|
|
65
|
+
"--target",
|
|
66
|
+
target,
|
|
67
|
+
...(global ? ["--global"] : []),
|
|
68
|
+
"--channel",
|
|
69
|
+
channel,
|
|
70
|
+
"--yes",
|
|
71
|
+
"--verbose",
|
|
72
|
+
];
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function updatePreviewArgsForRuntime(selection) {
|
|
76
|
+
return usesKitRefresh(selection.target) ? null : updatePreviewArgs(selection);
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function updateApplyArgsForRuntime(selection) {
|
|
80
|
+
return usesKitRefresh(selection.target) ? kitRefreshArgs(selection) : updateApplyArgs(selection);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function splitRuntimesForUpdate(runtimes) {
|
|
84
|
+
return {
|
|
85
|
+
update: runtimes.filter((runtime) => !usesKitRefresh(runtime)),
|
|
86
|
+
refresh: runtimes.filter((runtime) => usesKitRefresh(runtime)),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
54
90
|
export function selfUpdateCheckArgs(channel) {
|
|
55
91
|
return ["self-update", "--check", "--channel", channel];
|
|
56
92
|
}
|
package/lib/i18n.mjs
CHANGED
|
@@ -32,7 +32,9 @@ const messages = {
|
|
|
32
32
|
targetPrompt: "Which coding runtimes should receive {kit}?",
|
|
33
33
|
updateTargetPrompt: "Which installed runtimes should update {kit}?",
|
|
34
34
|
allRuntimes: "All supported runtimes",
|
|
35
|
-
|
|
35
|
+
piAkProfile: "pi-ak (Pi profile)",
|
|
36
|
+
piOmpProfile: "pi-omp (OMP profile)",
|
|
37
|
+
profileTargetsNeedGlobal: "pi-ak and pi-omp are global profile targets; use --global",
|
|
36
38
|
exportTargetPrompt: "Export creates a copy; it does not install a runtime. Choose a format:",
|
|
37
39
|
savedTargetNeedsUpdateRuntime: "Saved project target {target} is install-only. Update supports {supported}. Re-run with --runtime <target> or choose interactively.",
|
|
38
40
|
agyExport: "agy (global-only export)",
|
|
@@ -167,7 +169,9 @@ const messages = {
|
|
|
167
169
|
targetPrompt: "Các runtime nào sẽ nhận {kit}?",
|
|
168
170
|
updateTargetPrompt: "Các runtime nào sẽ cập nhật {kit}?",
|
|
169
171
|
allRuntimes: "Tất cả runtime được hỗ trợ",
|
|
170
|
-
|
|
172
|
+
piAkProfile: "pi-ak (profile Pi)",
|
|
173
|
+
piOmpProfile: "pi-omp (profile OMP)",
|
|
174
|
+
profileTargetsNeedGlobal: "pi-ak và pi-omp là profile global; dùng --global",
|
|
171
175
|
exportTargetPrompt: "Export tạo một bản sao, không cài vào runtime. Chọn dạng export:",
|
|
172
176
|
savedTargetNeedsUpdateRuntime: "Target đã lưu của project là {target} và chỉ dùng cho install. Update chỉ hỗ trợ {supported}. Hãy chạy lại với --runtime <target> hoặc chọn lại trong chế độ interactive.",
|
|
173
177
|
agyExport: "agy (chỉ export global)",
|
package/lib/pi-profiles.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
|
-
import { extname, isAbsolute, resolve, win32 } from "node:path";
|
|
3
|
+
import { extname, isAbsolute, join, resolve, win32 } from "node:path";
|
|
4
|
+
import { PROFILE_RUNTIME } from "./args.mjs";
|
|
4
5
|
|
|
5
6
|
function validPath(value) {
|
|
6
7
|
return typeof value === "string" && (isAbsolute(value) || win32.isAbsolute(value));
|
|
@@ -100,3 +101,46 @@ export function classifyPiProfiles(profiles) {
|
|
|
100
101
|
)),
|
|
101
102
|
};
|
|
102
103
|
}
|
|
104
|
+
|
|
105
|
+
export function isProfileTarget(target) {
|
|
106
|
+
return Object.hasOwn(PROFILE_RUNTIME, target);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function akRuntimeForHelperTarget(target) {
|
|
110
|
+
return PROFILE_RUNTIME[target] || target;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function defaultProfileProcessOptions(id, { home = homedir() } = {}) {
|
|
114
|
+
if (id === "pi-ak") {
|
|
115
|
+
const agentDir = join(home, ".pi", "profiles", "pi-ak");
|
|
116
|
+
return piProfileProcessOptions({
|
|
117
|
+
runtime: "pi", agentDir, sessionDir: join(agentDir, "sessions"),
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
if (id === "pi-omp") {
|
|
121
|
+
return piProfileProcessOptions({
|
|
122
|
+
runtime: "omp",
|
|
123
|
+
agentDir: join(home, ".omp", "profiles", "pi-omp", "agent"),
|
|
124
|
+
sessionDir: null,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
return { envOverrides: {}, envUnset: [] };
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function resolveProfileProcessOptions(id, profiles = [], { home = homedir() } = {}) {
|
|
131
|
+
const found = profiles.find((profile) => profile.id === id);
|
|
132
|
+
return found ? piProfileProcessOptions(found) : defaultProfileProcessOptions(id, { home });
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function materializeHelperTarget(selection, profiles = [], { home = homedir() } = {}) {
|
|
136
|
+
const helperTarget = selection.target;
|
|
137
|
+
const env = isProfileTarget(helperTarget)
|
|
138
|
+
? resolveProfileProcessOptions(helperTarget, profiles, { home })
|
|
139
|
+
: { envOverrides: {}, envUnset: [] };
|
|
140
|
+
return {
|
|
141
|
+
...selection,
|
|
142
|
+
helperTarget,
|
|
143
|
+
target: akRuntimeForHelperTarget(helperTarget),
|
|
144
|
+
...env,
|
|
145
|
+
};
|
|
146
|
+
}
|