@actant/cli 0.1.2 → 0.1.3

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.
@@ -1,6 +1,8 @@
1
1
  // src/program.ts
2
- import { Command as Command72 } from "commander";
3
- import { getDefaultIpcPath } from "@actant/shared";
2
+ import { Command as Command73 } from "commander";
3
+ import { readFileSync as readFileSync4 } from "fs";
4
+ import { join as join7 } from "path";
5
+ import { getDefaultIpcPath as getDefaultIpcPath2 } from "@actant/shared";
4
6
 
5
7
  // src/client/rpc-client.ts
6
8
  import { createConnection } from "net";
@@ -1235,7 +1237,7 @@ import chalk15 from "chalk";
1235
1237
  // package.json
1236
1238
  var package_default = {
1237
1239
  name: "@actant/cli",
1238
- version: "0.1.2",
1240
+ version: "0.1.3",
1239
1241
  description: "CLI for the Actant AI agent platform \u2014 build, manage, and compose AI agents",
1240
1242
  type: "module",
1241
1243
  license: "MIT",
@@ -1247,11 +1249,19 @@ var package_default = {
1247
1249
  },
1248
1250
  homepage: "https://github.com/blackplume233/Actant#readme",
1249
1251
  bugs: "https://github.com/blackplume233/Actant/issues",
1250
- keywords: ["actant", "ai-agent", "cli", "agent-platform"],
1252
+ keywords: [
1253
+ "actant",
1254
+ "ai-agent",
1255
+ "cli",
1256
+ "agent-platform"
1257
+ ],
1251
1258
  publishConfig: {
1252
1259
  access: "public"
1253
1260
  },
1254
- files: ["dist", "scripts/postinstall.mjs"],
1261
+ files: [
1262
+ "dist",
1263
+ "scripts/postinstall.mjs"
1264
+ ],
1255
1265
  bin: {
1256
1266
  actant: "./dist/bin/actant.js"
1257
1267
  },
@@ -1269,6 +1279,7 @@ var package_default = {
1269
1279
  "@actant/api": "workspace:*",
1270
1280
  "@actant/core": "workspace:*",
1271
1281
  "@actant/shared": "workspace:*",
1282
+ "@inquirer/prompts": "^8.3.0",
1272
1283
  chalk: "^5.6.2",
1273
1284
  "cli-table3": "^0.6.5",
1274
1285
  commander: "^14.0.3"
@@ -2597,14 +2608,790 @@ function showVersionCheck(sourcePath, actantHome) {
2597
2608
  }
2598
2609
  }
2599
2610
 
2611
+ // src/commands/setup/setup.ts
2612
+ import { Command as Command72 } from "commander";
2613
+ import chalk27 from "chalk";
2614
+ import { getDefaultIpcPath } from "@actant/shared";
2615
+
2616
+ // src/commands/setup/steps/choose-home.ts
2617
+ import { join as join3 } from "path";
2618
+ import { homedir as homedir2 } from "os";
2619
+ import { mkdirSync as mkdirSync2, existsSync as existsSync3, writeFileSync as writeFileSync2 } from "fs";
2620
+ import { select, input } from "@inquirer/prompts";
2621
+ import chalk20 from "chalk";
2622
+ var DEFAULT_HOME = join3(homedir2(), ".actant");
2623
+ var SUBDIRS = [
2624
+ "configs/skills",
2625
+ "configs/prompts",
2626
+ "configs/mcp",
2627
+ "configs/workflows",
2628
+ "configs/plugins",
2629
+ "configs/templates",
2630
+ "instances",
2631
+ "sources/cache",
2632
+ "logs",
2633
+ "backups"
2634
+ ];
2635
+ async function chooseHome(printer) {
2636
+ printer.log(`
2637
+ ${chalk20.cyan("[ Step 1/7 ]")} ${chalk20.bold("\u9009\u62E9\u5DE5\u4F5C\u76EE\u5F55")}
2638
+ `);
2639
+ const choice = await select({
2640
+ message: "Actant \u5DE5\u4F5C\u76EE\u5F55 (ACTANT_HOME):",
2641
+ choices: [
2642
+ { name: `\u4F7F\u7528\u9ED8\u8BA4 ${DEFAULT_HOME}`, value: "default" },
2643
+ { name: "\u81EA\u5B9A\u4E49\u8DEF\u5F84...", value: "custom" }
2644
+ ]
2645
+ });
2646
+ let actantHome = DEFAULT_HOME;
2647
+ if (choice === "custom") {
2648
+ actantHome = await input({
2649
+ message: "\u8BF7\u8F93\u5165\u5DE5\u4F5C\u76EE\u5F55\u8DEF\u5F84:",
2650
+ validate: (val) => val.trim().length > 0 || "\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A"
2651
+ });
2652
+ actantHome = actantHome.trim();
2653
+ }
2654
+ ensureDirectoryStructure(actantHome);
2655
+ const configFile = join3(actantHome, "config.json");
2656
+ if (!existsSync3(configFile)) {
2657
+ writeFileSync2(
2658
+ configFile,
2659
+ JSON.stringify(
2660
+ {
2661
+ devSourcePath: "",
2662
+ update: {
2663
+ maxBackups: 3,
2664
+ preUpdateTestCommand: "pnpm test:changed",
2665
+ autoRestartAgents: true
2666
+ }
2667
+ },
2668
+ null,
2669
+ 2
2670
+ ) + "\n"
2671
+ );
2672
+ }
2673
+ printer.success(`\u2713 \u5DE5\u4F5C\u76EE\u5F55: ${actantHome}`);
2674
+ if (actantHome !== DEFAULT_HOME) {
2675
+ printer.warn(
2676
+ ` \u8BF7\u5C06\u4EE5\u4E0B\u5185\u5BB9\u6DFB\u52A0\u5230\u4F60\u7684 shell \u914D\u7F6E\u6587\u4EF6 (~/.bashrc, ~/.zshrc, \u6216 $PROFILE):
2677
+ ${chalk20.cyan(`export ACTANT_HOME="${actantHome}"`)}`
2678
+ );
2679
+ }
2680
+ return actantHome;
2681
+ }
2682
+ function ensureDirectoryStructure(base) {
2683
+ for (const dir of SUBDIRS) {
2684
+ mkdirSync2(join3(base, dir), { recursive: true });
2685
+ }
2686
+ }
2687
+
2688
+ // src/commands/setup/steps/configure-provider.ts
2689
+ import { join as join4 } from "path";
2690
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
2691
+ import { select as select2, input as input2, password, confirm } from "@inquirer/prompts";
2692
+ import chalk21 from "chalk";
2693
+ var PROVIDER_DEFAULTS = {
2694
+ anthropic: { protocol: "http", baseUrl: "https://api.anthropic.com", apiKeyEnv: "ANTHROPIC_API_KEY" },
2695
+ openai: { protocol: "http", baseUrl: "https://api.openai.com/v1", apiKeyEnv: "OPENAI_API_KEY" },
2696
+ "openai-compatible": { protocol: "http", baseUrl: "http://localhost:11434/v1", apiKeyEnv: "LLM_API_KEY" },
2697
+ custom: { protocol: "http", baseUrl: "http://localhost:8080", apiKeyEnv: "LLM_API_KEY" }
2698
+ };
2699
+ async function configureProvider(printer, actantHome) {
2700
+ printer.log(`
2701
+ ${chalk21.cyan("[ Step 2/7 ]")} ${chalk21.bold("\u914D\u7F6E Model Provider")}
2702
+ `);
2703
+ const providerType = await select2({
2704
+ message: "\u9009\u62E9 Model Provider:",
2705
+ default: "anthropic",
2706
+ choices: [
2707
+ { name: "Anthropic (Claude)", value: "anthropic" },
2708
+ { name: "OpenAI", value: "openai" },
2709
+ { name: "OpenAI-Compatible (vLLM / Ollama / LM Studio \u7B49)", value: "openai-compatible" },
2710
+ { name: "Custom", value: "custom" }
2711
+ ]
2712
+ });
2713
+ const fallback = {
2714
+ protocol: "http",
2715
+ baseUrl: "",
2716
+ apiKeyEnv: "LLM_API_KEY"
2717
+ };
2718
+ const defaults = PROVIDER_DEFAULTS[providerType] ?? fallback;
2719
+ const protocol = await select2({
2720
+ message: "\u534F\u8BAE\u7C7B\u578B:",
2721
+ choices: [
2722
+ { name: "HTTP / REST", value: "http" },
2723
+ { name: "WebSocket", value: "websocket" },
2724
+ { name: "gRPC", value: "grpc" }
2725
+ ],
2726
+ default: defaults.protocol
2727
+ });
2728
+ const baseUrl = await input2({
2729
+ message: "Base URL:",
2730
+ default: defaults.baseUrl,
2731
+ validate: (val) => {
2732
+ try {
2733
+ new URL(val);
2734
+ return true;
2735
+ } catch {
2736
+ return "\u8BF7\u8F93\u5165\u6709\u6548\u7684 URL";
2737
+ }
2738
+ }
2739
+ });
2740
+ const apiKeyEnvName = await input2({
2741
+ message: "API Key \u73AF\u5883\u53D8\u91CF\u540D:",
2742
+ default: defaults.apiKeyEnv
2743
+ });
2744
+ const apiKey = await password({
2745
+ message: `${apiKeyEnvName} \u7684\u503C (API Key):`,
2746
+ mask: "*"
2747
+ });
2748
+ if (apiKey) {
2749
+ const shouldValidate = await confirm({
2750
+ message: "\u9A8C\u8BC1\u8FDE\u63A5?",
2751
+ default: true
2752
+ });
2753
+ if (shouldValidate) {
2754
+ printer.log(chalk21.dim(" \u6B63\u5728\u9A8C\u8BC1\u8FDE\u63A5..."));
2755
+ const ok = await validateConnection(providerType, protocol, baseUrl, apiKey);
2756
+ if (ok) {
2757
+ printer.success(" \u2713 \u8FDE\u63A5\u9A8C\u8BC1\u6210\u529F");
2758
+ } else {
2759
+ printer.warn(" \u26A0 \u8FDE\u63A5\u9A8C\u8BC1\u5931\u8D25\uFF0C\u914D\u7F6E\u5DF2\u4FDD\u5B58\u4F46\u53EF\u80FD\u9700\u8981\u68C0\u67E5");
2760
+ }
2761
+ }
2762
+ printer.warn(
2763
+ ` \u8BF7\u786E\u4FDD\u73AF\u5883\u53D8\u91CF ${chalk21.cyan(apiKeyEnvName)} \u5DF2\u8BBE\u7F6E:
2764
+ ${chalk21.dim(`export ${apiKeyEnvName}="${apiKey.slice(0, 8)}..."`)}`
2765
+ );
2766
+ }
2767
+ const providerConfig = {
2768
+ type: providerType,
2769
+ protocol,
2770
+ baseUrl,
2771
+ apiKeyEnv: apiKeyEnvName
2772
+ };
2773
+ saveProviderConfig(actantHome, providerConfig);
2774
+ printer.success(`\u2713 Model Provider \u5DF2\u914D\u7F6E: ${providerType} (${protocol}) \u2192 ${baseUrl}`);
2775
+ }
2776
+ function saveProviderConfig(actantHome, provider) {
2777
+ const configFile = join4(actantHome, "config.json");
2778
+ let config = {};
2779
+ try {
2780
+ config = JSON.parse(readFileSync2(configFile, "utf-8"));
2781
+ } catch {
2782
+ }
2783
+ config.provider = provider;
2784
+ writeFileSync3(configFile, JSON.stringify(config, null, 2) + "\n");
2785
+ }
2786
+ async function validateConnection(type, _protocol, baseUrl, apiKey) {
2787
+ try {
2788
+ if (type === "anthropic") {
2789
+ const res2 = await fetch(`${baseUrl}/v1/messages`, {
2790
+ method: "POST",
2791
+ headers: {
2792
+ "x-api-key": apiKey,
2793
+ "anthropic-version": "2023-06-01",
2794
+ "content-type": "application/json"
2795
+ },
2796
+ body: JSON.stringify({
2797
+ model: "claude-sonnet-4-20250514",
2798
+ max_tokens: 1,
2799
+ messages: [{ role: "user", content: "hi" }]
2800
+ }),
2801
+ signal: AbortSignal.timeout(15e3)
2802
+ });
2803
+ return res2.status === 200 || res2.status === 400;
2804
+ }
2805
+ if (type === "openai" || type === "openai-compatible") {
2806
+ const res2 = await fetch(`${baseUrl}/models`, {
2807
+ headers: { Authorization: `Bearer ${apiKey}` },
2808
+ signal: AbortSignal.timeout(1e4)
2809
+ });
2810
+ return res2.ok;
2811
+ }
2812
+ const res = await fetch(baseUrl, {
2813
+ headers: { Authorization: `Bearer ${apiKey}` },
2814
+ signal: AbortSignal.timeout(1e4)
2815
+ });
2816
+ return res.ok;
2817
+ } catch {
2818
+ return false;
2819
+ }
2820
+ }
2821
+
2822
+ // src/commands/setup/steps/configure-source.ts
2823
+ import { confirm as confirm2, input as input3, select as select3 } from "@inquirer/prompts";
2824
+ import chalk22 from "chalk";
2825
+ var DEFAULT_SOURCE_NAME = "actant-hub";
2826
+ var DEFAULT_SOURCE_URL = "https://github.com/blackplume233/actant-hub.git";
2827
+ async function configureSource(printer, client) {
2828
+ printer.log(`
2829
+ ${chalk22.cyan("[ Step 3/7 ]")} ${chalk22.bold("\u914D\u7F6E\u7EC4\u4EF6\u6E90 (Source)")}
2830
+ `);
2831
+ const addDefault = await confirm2({
2832
+ message: `\u6DFB\u52A0\u5B98\u65B9\u7EC4\u4EF6\u6E90 ${DEFAULT_SOURCE_NAME}?`,
2833
+ default: true
2834
+ });
2835
+ if (addDefault) {
2836
+ try {
2837
+ printer.log(chalk22.dim(` \u6B63\u5728\u6CE8\u518C ${DEFAULT_SOURCE_NAME}...`));
2838
+ const result = await client.call("source.add", {
2839
+ name: DEFAULT_SOURCE_NAME,
2840
+ config: { type: "github", url: DEFAULT_SOURCE_URL, branch: "main" }
2841
+ });
2842
+ const c = result.components;
2843
+ printer.success(
2844
+ ` \u2713 ${DEFAULT_SOURCE_NAME} \u5DF2\u6DFB\u52A0: ${c.skills} skills, ${c.prompts} prompts, ${c.mcp} mcp, ${c.workflows} workflows, ${c.presets} presets`
2845
+ );
2846
+ } catch (err) {
2847
+ const message = err instanceof Error ? err.message : String(err);
2848
+ if (message.includes("already exists") || message.includes("already registered")) {
2849
+ printer.dim(` ${DEFAULT_SOURCE_NAME} \u5DF2\u5B58\u5728\uFF0C\u8DF3\u8FC7`);
2850
+ } else {
2851
+ printer.warn(` \u26A0 \u6DFB\u52A0 ${DEFAULT_SOURCE_NAME} \u5931\u8D25: ${message}`);
2852
+ printer.dim(" \u4F60\u53EF\u4EE5\u7A0D\u540E\u624B\u52A8\u8FD0\u884C: actant source add --name actant-hub <url>");
2853
+ }
2854
+ }
2855
+ }
2856
+ let addMore = await confirm2({
2857
+ message: "\u6DFB\u52A0\u5176\u4ED6 Source?",
2858
+ default: false
2859
+ });
2860
+ while (addMore) {
2861
+ const sourceType = await select3({
2862
+ message: "Source \u7C7B\u578B:",
2863
+ choices: [
2864
+ { name: "GitHub \u4ED3\u5E93", value: "github" },
2865
+ { name: "\u672C\u5730\u76EE\u5F55", value: "local" }
2866
+ ]
2867
+ });
2868
+ const name = await input3({
2869
+ message: "Source \u540D\u79F0 (\u547D\u540D\u7A7A\u95F4\u524D\u7F00):",
2870
+ validate: (val) => val.trim().length > 0 || "\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A"
2871
+ });
2872
+ if (sourceType === "github") {
2873
+ const url = await input3({
2874
+ message: "GitHub \u4ED3\u5E93 URL:",
2875
+ validate: (val) => val.trim().length > 0 || "URL \u4E0D\u80FD\u4E3A\u7A7A"
2876
+ });
2877
+ const branch = await input3({
2878
+ message: "\u5206\u652F:",
2879
+ default: "main"
2880
+ });
2881
+ try {
2882
+ const result = await client.call("source.add", {
2883
+ name: name.trim(),
2884
+ config: { type: "github", url: url.trim(), branch }
2885
+ });
2886
+ const c = result.components;
2887
+ printer.success(
2888
+ ` \u2713 ${name.trim()} \u5DF2\u6DFB\u52A0: ${c.skills} skills, ${c.prompts} prompts`
2889
+ );
2890
+ } catch (err) {
2891
+ printer.warn(` \u26A0 \u6DFB\u52A0\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
2892
+ }
2893
+ } else {
2894
+ const path = await input3({
2895
+ message: "\u672C\u5730\u76EE\u5F55\u8DEF\u5F84:",
2896
+ validate: (val) => val.trim().length > 0 || "\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A"
2897
+ });
2898
+ try {
2899
+ const result = await client.call("source.add", {
2900
+ name: name.trim(),
2901
+ config: { type: "local", path: path.trim() }
2902
+ });
2903
+ const c = result.components;
2904
+ printer.success(
2905
+ ` \u2713 ${name.trim()} \u5DF2\u6DFB\u52A0: ${c.skills} skills, ${c.prompts} prompts`
2906
+ );
2907
+ } catch (err) {
2908
+ printer.warn(` \u26A0 \u6DFB\u52A0\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
2909
+ }
2910
+ }
2911
+ addMore = await confirm2({
2912
+ message: "\u7EE7\u7EED\u6DFB\u52A0\u5176\u4ED6 Source?",
2913
+ default: false
2914
+ });
2915
+ }
2916
+ printer.success("\u2713 \u7EC4\u4EF6\u6E90\u914D\u7F6E\u5B8C\u6210");
2917
+ }
2918
+
2919
+ // src/commands/setup/steps/materialize-agent.ts
2920
+ import { checkbox, input as input4 } from "@inquirer/prompts";
2921
+ import chalk23 from "chalk";
2922
+ async function materializeAgent(printer, client) {
2923
+ printer.log(`
2924
+ ${chalk23.cyan("[ Step 4/7 ]")} ${chalk23.bold("\u9009\u62E9\u5E76\u521B\u5EFA Agent")}
2925
+ `);
2926
+ let templates;
2927
+ try {
2928
+ templates = await client.call("template.list", {});
2929
+ } catch (err) {
2930
+ printer.warn(` \u26A0 \u65E0\u6CD5\u83B7\u53D6\u6A21\u677F\u5217\u8868: ${err instanceof Error ? err.message : String(err)}`);
2931
+ printer.dim(" \u4F60\u53EF\u4EE5\u7A0D\u540E\u4F7F\u7528 actant agent create <name> -t <template> \u521B\u5EFA Agent");
2932
+ return [];
2933
+ }
2934
+ if (templates.length === 0) {
2935
+ printer.dim(" \u6682\u65E0\u53EF\u7528\u6A21\u677F\u3002\u8BF7\u5148\u901A\u8FC7 actant source sync \u540C\u6B65\u7EC4\u4EF6\uFF0C\u6216\u4F7F\u7528 actant template load \u52A0\u8F7D\u6A21\u677F\u3002");
2936
+ return [];
2937
+ }
2938
+ const selected = await checkbox({
2939
+ message: "\u9009\u62E9\u8981\u521B\u5EFA\u7684 Agent \u6A21\u677F (\u7A7A\u683C\u9009\u62E9, \u56DE\u8F66\u786E\u8BA4):",
2940
+ choices: templates.map((t, i) => ({
2941
+ name: `${t.name} (v${t.version})${t.description ? ` \u2014 ${t.description}` : ""}`,
2942
+ value: t.name,
2943
+ checked: i === 0
2944
+ }))
2945
+ });
2946
+ if (selected.length === 0) {
2947
+ printer.dim(" \u672A\u9009\u62E9\u4EFB\u4F55\u6A21\u677F\uFF0C\u8DF3\u8FC7 Agent \u521B\u5EFA");
2948
+ return [];
2949
+ }
2950
+ const createdAgents = [];
2951
+ for (const templateName of selected) {
2952
+ const instanceName = await input4({
2953
+ message: `Agent \u5B9E\u4F8B\u540D\u79F0 (\u6A21\u677F: ${templateName}):`,
2954
+ default: templateName,
2955
+ validate: (val) => {
2956
+ if (val.trim().length === 0) return "\u540D\u79F0\u4E0D\u80FD\u4E3A\u7A7A";
2957
+ if (!/^[a-zA-Z0-9_-]+$/.test(val.trim())) return "\u4EC5\u5141\u8BB8\u5B57\u6BCD\u3001\u6570\u5B57\u3001\u4E0B\u5212\u7EBF\u548C\u8FDE\u5B57\u7B26";
2958
+ return true;
2959
+ }
2960
+ });
2961
+ try {
2962
+ printer.log(chalk23.dim(` \u6B63\u5728\u521B\u5EFA ${instanceName.trim()}...`));
2963
+ await client.call("agent.create", {
2964
+ name: instanceName.trim(),
2965
+ template: templateName
2966
+ });
2967
+ printer.success(` \u2713 Agent "${instanceName.trim()}" \u5DF2\u521B\u5EFA (\u6A21\u677F: ${templateName})`);
2968
+ createdAgents.push(instanceName.trim());
2969
+ } catch (err) {
2970
+ printer.warn(` \u26A0 \u521B\u5EFA "${instanceName.trim()}" \u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
2971
+ }
2972
+ }
2973
+ if (createdAgents.length > 0) {
2974
+ printer.success(`\u2713 \u5DF2\u521B\u5EFA ${createdAgents.length} \u4E2A Agent`);
2975
+ }
2976
+ return createdAgents;
2977
+ }
2978
+
2979
+ // src/commands/setup/steps/configure-autostart.ts
2980
+ import { execSync } from "child_process";
2981
+ import { writeFileSync as writeFileSync4, mkdirSync as mkdirSync3 } from "fs";
2982
+ import { join as join5 } from "path";
2983
+ import { homedir as homedir3 } from "os";
2984
+ import { confirm as confirm3 } from "@inquirer/prompts";
2985
+ import chalk24 from "chalk";
2986
+ import { isWindows as isWindows2 } from "@actant/shared";
2987
+ async function configureAutostart(printer) {
2988
+ printer.log(`
2989
+ ${chalk24.cyan("[ Step 5/7 ]")} ${chalk24.bold("\u914D\u7F6E\u81EA\u52A8\u542F\u52A8")}
2990
+ `);
2991
+ const platform = process.platform;
2992
+ const platformName = platform === "win32" ? "Windows" : platform === "darwin" ? "macOS" : "Linux";
2993
+ printer.log(` \u68C0\u6D4B\u5230\u5E73\u53F0: ${chalk24.bold(platformName)}`);
2994
+ const enable = await confirm3({
2995
+ message: "\u914D\u7F6E Actant Daemon \u5F00\u673A\u81EA\u542F?",
2996
+ default: true
2997
+ });
2998
+ if (!enable) {
2999
+ printer.dim(" \u8DF3\u8FC7\u81EA\u52A8\u542F\u52A8\u914D\u7F6E");
3000
+ return;
3001
+ }
3002
+ try {
3003
+ if (isWindows2()) {
3004
+ configureWindows(printer);
3005
+ } else if (platform === "darwin") {
3006
+ configureMacOS(printer);
3007
+ } else {
3008
+ configureLinux(printer);
3009
+ }
3010
+ printer.success("\u2713 \u81EA\u52A8\u542F\u52A8\u5DF2\u914D\u7F6E");
3011
+ } catch (err) {
3012
+ printer.warn(` \u26A0 \u81EA\u52A8\u542F\u52A8\u914D\u7F6E\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
3013
+ printer.dim(" \u4F60\u53EF\u4EE5\u7A0D\u540E\u624B\u52A8\u914D\u7F6E\u81EA\u52A8\u542F\u52A8");
3014
+ }
3015
+ }
3016
+ function configureWindows(printer) {
3017
+ printer.log(chalk24.dim(" \u6B63\u5728\u6CE8\u518C Windows Task Scheduler \u4EFB\u52A1..."));
3018
+ const actantPath = findActantExecutable();
3019
+ const taskXml = `<?xml version="1.0" encoding="UTF-16"?>
3020
+ <Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
3021
+ <Triggers>
3022
+ <LogonTrigger>
3023
+ <Enabled>true</Enabled>
3024
+ </LogonTrigger>
3025
+ </Triggers>
3026
+ <Principals>
3027
+ <Principal>
3028
+ <LogonType>InteractiveToken</LogonType>
3029
+ <RunLevel>LeastPrivilege</RunLevel>
3030
+ </Principal>
3031
+ </Principals>
3032
+ <Settings>
3033
+ <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
3034
+ <DisallowStartIfOnBatteries>false</DisallowStartIfOnBatteries>
3035
+ <StopIfGoingOnBatteries>false</StopIfGoingOnBatteries>
3036
+ <ExecutionTimeLimit>PT0S</ExecutionTimeLimit>
3037
+ </Settings>
3038
+ <Actions>
3039
+ <Exec>
3040
+ <Command>${actantPath}</Command>
3041
+ <Arguments>daemon start</Arguments>
3042
+ </Exec>
3043
+ </Actions>
3044
+ </Task>`;
3045
+ const tempXmlPath = join5(process.env["TEMP"] || homedir3(), "actant-task.xml");
3046
+ writeFileSync4(tempXmlPath, taskXml, "utf-16le");
3047
+ execSync(`schtasks /Create /TN "ActantDaemon" /XML "${tempXmlPath}" /F`, { stdio: "pipe" });
3048
+ printer.dim(" \u5DF2\u6CE8\u518C\u4EFB\u52A1: ActantDaemon (\u767B\u5F55\u65F6\u81EA\u52A8\u542F\u52A8)");
3049
+ }
3050
+ function configureMacOS(printer) {
3051
+ printer.log(chalk24.dim(" \u6B63\u5728\u751F\u6210 launchd plist..."));
3052
+ const actantPath = findActantExecutable();
3053
+ const plistDir = join5(homedir3(), "Library", "LaunchAgents");
3054
+ mkdirSync3(plistDir, { recursive: true });
3055
+ const plistPath = join5(plistDir, "com.actant.daemon.plist");
3056
+ const plist = `<?xml version="1.0" encoding="UTF-8"?>
3057
+ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3058
+ <plist version="1.0">
3059
+ <dict>
3060
+ <key>Label</key>
3061
+ <string>com.actant.daemon</string>
3062
+ <key>ProgramArguments</key>
3063
+ <array>
3064
+ <string>${actantPath}</string>
3065
+ <string>daemon</string>
3066
+ <string>start</string>
3067
+ <string>--foreground</string>
3068
+ </array>
3069
+ <key>RunAtLoad</key>
3070
+ <true/>
3071
+ <key>KeepAlive</key>
3072
+ <true/>
3073
+ <key>StandardOutPath</key>
3074
+ <string>${join5(homedir3(), ".actant", "logs", "daemon-stdout.log")}</string>
3075
+ <key>StandardErrorPath</key>
3076
+ <string>${join5(homedir3(), ".actant", "logs", "daemon-stderr.log")}</string>
3077
+ </dict>
3078
+ </plist>`;
3079
+ writeFileSync4(plistPath, plist);
3080
+ execSync(`launchctl load "${plistPath}"`, { stdio: "pipe" });
3081
+ printer.dim(` \u5DF2\u52A0\u8F7D: ${plistPath}`);
3082
+ }
3083
+ function configureLinux(printer) {
3084
+ printer.log(chalk24.dim(" \u6B63\u5728\u751F\u6210 systemd user service..."));
3085
+ const actantPath = findActantExecutable();
3086
+ const serviceDir = join5(homedir3(), ".config", "systemd", "user");
3087
+ mkdirSync3(serviceDir, { recursive: true });
3088
+ const servicePath = join5(serviceDir, "actant-daemon.service");
3089
+ const unit = `[Unit]
3090
+ Description=Actant Daemon \u2014 AI Agent Platform
3091
+ After=network.target
3092
+
3093
+ [Service]
3094
+ Type=simple
3095
+ ExecStart=${actantPath} daemon start --foreground
3096
+ Restart=on-failure
3097
+ RestartSec=5
3098
+ Environment=NODE_ENV=production
3099
+
3100
+ [Install]
3101
+ WantedBy=default.target
3102
+ `;
3103
+ writeFileSync4(servicePath, unit);
3104
+ execSync("systemctl --user daemon-reload", { stdio: "pipe" });
3105
+ execSync("systemctl --user enable actant-daemon.service", { stdio: "pipe" });
3106
+ printer.dim(` \u5DF2\u542F\u7528: actant-daemon.service`);
3107
+ }
3108
+ function findActantExecutable() {
3109
+ try {
3110
+ const result = execSync(isWindows2() ? "where.exe actant" : "which actant", {
3111
+ encoding: "utf-8",
3112
+ stdio: ["pipe", "pipe", "pipe"]
3113
+ });
3114
+ const first = result.trim().split("\n")[0];
3115
+ return first ? first.trim() : "actant";
3116
+ } catch {
3117
+ return "actant";
3118
+ }
3119
+ }
3120
+
3121
+ // src/commands/setup/steps/hello-world.ts
3122
+ import chalk25 from "chalk";
3123
+ async function helloWorld(printer, client, createdAgents) {
3124
+ printer.log(`
3125
+ ${chalk25.cyan("[ Step 6/7 ]")} ${chalk25.bold("Hello World \u9A8C\u8BC1")}
3126
+ `);
3127
+ const alive = await client.ping();
3128
+ if (!alive) {
3129
+ printer.warn(" \u26A0 Daemon \u672A\u8FD0\u884C\uFF0C\u8DF3\u8FC7\u9A8C\u8BC1");
3130
+ printer.dim(' \u542F\u52A8\u540E\u53EF\u624B\u52A8\u9A8C\u8BC1: actant agent run <name> --prompt "Hello, World!"');
3131
+ return;
3132
+ }
3133
+ printer.success(" \u2713 Daemon \u8FDE\u63A5\u6B63\u5E38");
3134
+ if (createdAgents.length === 0) {
3135
+ printer.dim(" \u65E0\u5DF2\u521B\u5EFA\u7684 Agent\uFF0C\u8DF3\u8FC7\u7AEF\u5230\u7AEF\u9A8C\u8BC1");
3136
+ printer.dim(' \u521B\u5EFA Agent \u540E\u53EF\u8FD0\u884C: actant agent run <name> --prompt "Hello, World!"');
3137
+ return;
3138
+ }
3139
+ const testAgent = createdAgents[0];
3140
+ if (!testAgent) {
3141
+ printer.dim(" \u65E0\u53EF\u7528 Agent\uFF0C\u8DF3\u8FC7\u7AEF\u5230\u7AEF\u9A8C\u8BC1");
3142
+ return;
3143
+ }
3144
+ printer.log(chalk25.dim(` \u6B63\u5728\u4F7F\u7528 Agent "${testAgent}" \u8FDB\u884C\u9A8C\u8BC1...`));
3145
+ try {
3146
+ await client.call("agent.start", { name: testAgent });
3147
+ printer.success(` \u2713 Agent "${testAgent}" \u5DF2\u542F\u52A8`);
3148
+ await waitForAgentReady(client, testAgent, 15e3);
3149
+ printer.log(chalk25.dim(` \u53D1\u9001\u6D4B\u8BD5\u6D88\u606F: "Hello, World!"`));
3150
+ const runResult = await client.call("agent.run", {
3151
+ name: testAgent,
3152
+ prompt: "Please respond with exactly: Hello from Actant! (keep it short)"
3153
+ });
3154
+ if (runResult) {
3155
+ printer.success(" \u2713 \u6536\u5230 Agent \u56DE\u590D \u2014 \u7AEF\u5230\u7AEF\u9A8C\u8BC1\u901A\u8FC7!");
3156
+ } else {
3157
+ printer.warn(" \u26A0 Agent \u672A\u8FD4\u56DE\u7ED3\u679C\uFF0C\u4F46\u542F\u52A8\u6B63\u5E38");
3158
+ }
3159
+ } catch (err) {
3160
+ const message = err instanceof Error ? err.message : String(err);
3161
+ if (message.includes("not found") || message.includes("NOT_FOUND")) {
3162
+ printer.warn(` \u26A0 Agent "${testAgent}" \u672A\u627E\u5230\uFF0C\u8DF3\u8FC7\u9A8C\u8BC1`);
3163
+ } else if (message.includes("Cannot connect")) {
3164
+ printer.warn(" \u26A0 \u65E0\u6CD5\u8FDE\u63A5\u540E\u7AEF (backend)\uFF0C\u8BF7\u786E\u8BA4\u540E\u7AEF\u5DF2\u5B89\u88C5");
3165
+ printer.dim(" \u63D0\u793A: claude-code \u540E\u7AEF\u9700\u8981\u5B89\u88C5 claude-agent-acp");
3166
+ } else {
3167
+ printer.warn(` \u26A0 \u9A8C\u8BC1\u8FC7\u7A0B\u4E2D\u51FA\u73B0\u9519\u8BEF: ${message}`);
3168
+ }
3169
+ printer.dim(' \u4F60\u53EF\u4EE5\u7A0D\u540E\u624B\u52A8\u9A8C\u8BC1: actant agent run <name> --prompt "Hello!"');
3170
+ }
3171
+ }
3172
+ async function waitForAgentReady(client, name, timeoutMs) {
3173
+ const start = Date.now();
3174
+ while (Date.now() - start < timeoutMs) {
3175
+ try {
3176
+ const status = await client.call("agent.status", { name });
3177
+ if (status.status === "running") return;
3178
+ } catch {
3179
+ }
3180
+ await new Promise((r) => setTimeout(r, 1e3));
3181
+ }
3182
+ }
3183
+
3184
+ // src/commands/setup/steps/configure-update.ts
3185
+ import { join as join6 } from "path";
3186
+ import { readFileSync as readFileSync3, writeFileSync as writeFileSync5, existsSync as existsSync4 } from "fs";
3187
+ import { confirm as confirm4, input as input5 } from "@inquirer/prompts";
3188
+ import chalk26 from "chalk";
3189
+ function detectDevSourcePath() {
3190
+ const candidates = [
3191
+ process.cwd(),
3192
+ join6(process.cwd(), "..")
3193
+ ];
3194
+ for (const dir of candidates) {
3195
+ if (existsSync4(join6(dir, "packages", "cli", "package.json"))) {
3196
+ return dir;
3197
+ }
3198
+ }
3199
+ return process.cwd();
3200
+ }
3201
+ async function configureUpdate(printer, actantHome) {
3202
+ printer.log(`
3203
+ ${chalk26.cyan("[ Step 7/7 ]")} ${chalk26.bold("\u66F4\u65B0\u9009\u9879")}
3204
+ `);
3205
+ const wantConfigure = await confirm4({
3206
+ message: "\u914D\u7F6E\u81EA\u52A8\u66F4\u65B0\u6E90? (\u7528\u4E8E\u4ECE\u672C\u5730\u6E90\u7801\u66F4\u65B0 Actant)",
3207
+ default: false
3208
+ });
3209
+ if (!wantConfigure) {
3210
+ printer.dim(" \u8DF3\u8FC7\u66F4\u65B0\u914D\u7F6E");
3211
+ printUpdateHelp(printer);
3212
+ return;
3213
+ }
3214
+ const defaultPath = detectDevSourcePath();
3215
+ const devSourcePath = await input5({
3216
+ message: "\u5F00\u53D1\u6E90\u76EE\u5F55\u8DEF\u5F84 (AgentCraft \u9879\u76EE\u6839\u76EE\u5F55):",
3217
+ default: defaultPath,
3218
+ validate: (val) => val.trim().length > 0 || "\u8DEF\u5F84\u4E0D\u80FD\u4E3A\u7A7A"
3219
+ });
3220
+ const configFile = join6(actantHome, "config.json");
3221
+ let config = {};
3222
+ try {
3223
+ config = JSON.parse(readFileSync3(configFile, "utf-8"));
3224
+ } catch {
3225
+ }
3226
+ config.devSourcePath = devSourcePath.trim();
3227
+ writeFileSync5(configFile, JSON.stringify(config, null, 2) + "\n");
3228
+ printer.success(`\u2713 \u66F4\u65B0\u6E90\u5DF2\u914D\u7F6E: ${devSourcePath.trim()}`);
3229
+ printUpdateHelp(printer);
3230
+ }
3231
+ function printUpdateHelp(printer) {
3232
+ printer.log("");
3233
+ printer.dim(" \u66F4\u65B0\u547D\u4EE4:");
3234
+ printer.dim(` ${chalk26.cyan("actant self-update")} \u4ECE\u6E90\u7801\u6784\u5EFA\u5E76\u66F4\u65B0`);
3235
+ printer.dim(` ${chalk26.cyan("actant self-update --check")} \u68C0\u67E5\u7248\u672C\u5DEE\u5F02`);
3236
+ printer.dim(` ${chalk26.cyan("npm install -g @actant/cli")} \u4ECE npm \u66F4\u65B0`);
3237
+ }
3238
+
3239
+ // src/commands/setup/setup.ts
3240
+ function createSetupCommand(printer = defaultPrinter) {
3241
+ return new Command72("setup").description("Interactive setup wizard \u2014 configure Actant step by step").option("--skip-home", "Skip work directory selection").option("--skip-provider", "Skip model provider configuration").option("--skip-source", "Skip component source configuration").option("--skip-agent", "Skip agent creation").option("--skip-autostart", "Skip auto-start configuration").option("--skip-hello", "Skip hello world verification").option("--skip-update", "Skip update options").action(async (opts) => {
3242
+ try {
3243
+ printBanner(printer);
3244
+ let actantHome;
3245
+ if (opts.skipHome) {
3246
+ const { homedir: homedir4 } = await import("os");
3247
+ const { join: join8 } = await import("path");
3248
+ const { existsSync: existsSync5, writeFileSync: writeFileSync6 } = await import("fs");
3249
+ actantHome = process.env["ACTANT_HOME"] || join8(homedir4(), ".actant");
3250
+ ensureDirectoryStructure(actantHome);
3251
+ const configFile = join8(actantHome, "config.json");
3252
+ if (!existsSync5(configFile)) {
3253
+ writeFileSync6(configFile, JSON.stringify({
3254
+ devSourcePath: "",
3255
+ update: { maxBackups: 3, preUpdateTestCommand: "pnpm test:changed", autoRestartAgents: true }
3256
+ }, null, 2) + "\n");
3257
+ }
3258
+ printer.dim(` \u4F7F\u7528\u9ED8\u8BA4\u5DE5\u4F5C\u76EE\u5F55: ${actantHome}`);
3259
+ } else {
3260
+ actantHome = await chooseHome(printer);
3261
+ }
3262
+ if (!opts.skipProvider) {
3263
+ await configureProvider(printer, actantHome);
3264
+ }
3265
+ const daemonNeeded = !opts.skipSource || !opts.skipAgent || !opts.skipHello;
3266
+ let client;
3267
+ let daemonStartedBySetup = false;
3268
+ if (daemonNeeded) {
3269
+ const socketPath = process.env["ACTANT_SOCKET"] ?? getDefaultIpcPath(actantHome);
3270
+ client = new RpcClient(socketPath);
3271
+ const alive = await client.ping();
3272
+ if (!alive) {
3273
+ printer.log(chalk27.dim("\n \u6B63\u5728\u542F\u52A8 Daemon..."));
3274
+ daemonStartedBySetup = await tryStartDaemon(printer, socketPath);
3275
+ if (!daemonStartedBySetup) {
3276
+ printer.warn(" \u26A0 \u65E0\u6CD5\u81EA\u52A8\u542F\u52A8 Daemon\uFF0C\u8DF3\u8FC7\u9700\u8981 Daemon \u7684\u6B65\u9AA4");
3277
+ printer.dim(" \u8BF7\u624B\u52A8\u8FD0\u884C: actant daemon start");
3278
+ client = void 0;
3279
+ }
3280
+ } else {
3281
+ printer.dim("\n Daemon \u5DF2\u5728\u8FD0\u884C\u4E2D");
3282
+ }
3283
+ }
3284
+ if (!opts.skipSource && client) {
3285
+ await configureSource(printer, client);
3286
+ }
3287
+ let createdAgents = [];
3288
+ if (!opts.skipAgent && client) {
3289
+ createdAgents = await materializeAgent(printer, client);
3290
+ }
3291
+ if (!opts.skipAutostart) {
3292
+ await configureAutostart(printer);
3293
+ }
3294
+ if (!opts.skipHello && client) {
3295
+ await helloWorld(printer, client, createdAgents);
3296
+ }
3297
+ if (!opts.skipUpdate) {
3298
+ await configureUpdate(printer, actantHome);
3299
+ }
3300
+ printSummary(printer, actantHome);
3301
+ } catch (err) {
3302
+ if (isUserCancellation(err)) {
3303
+ printer.log(chalk27.dim("\n \u5DF2\u53D6\u6D88\u8BBE\u7F6E\u5411\u5BFC"));
3304
+ return;
3305
+ }
3306
+ presentError(err, printer);
3307
+ process.exitCode = 1;
3308
+ }
3309
+ });
3310
+ }
3311
+ function printBanner(printer) {
3312
+ printer.log("");
3313
+ printer.log(chalk27.cyan("\u2554\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2557"));
3314
+ printer.log(chalk27.cyan("\u2551") + chalk27.bold(" Actant Setup Wizard ") + chalk27.cyan("\u2551"));
3315
+ printer.log(chalk27.cyan("\u2551") + chalk27.dim(" Build, manage, and compose AI agents ") + chalk27.cyan("\u2551"));
3316
+ printer.log(chalk27.cyan("\u255A\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u255D"));
3317
+ }
3318
+ function printSummary(printer, actantHome) {
3319
+ printer.log("");
3320
+ printer.log(chalk27.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
3321
+ printer.log(chalk27.green.bold(" Setup Complete!"));
3322
+ printer.log(chalk27.green("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550"));
3323
+ printer.log("");
3324
+ printer.dim(` \u5DE5\u4F5C\u76EE\u5F55: ${actantHome}`);
3325
+ printer.log("");
3326
+ printer.log(" \u5FEB\u901F\u5F00\u59CB:");
3327
+ printer.log(` ${chalk27.cyan("actant daemon start")} \u542F\u52A8 Daemon`);
3328
+ printer.log(` ${chalk27.cyan("actant template list")} \u6D4F\u89C8\u6A21\u677F`);
3329
+ printer.log(` ${chalk27.cyan("actant agent list")} \u67E5\u770B Agent`);
3330
+ printer.log(` ${chalk27.cyan("actant agent chat <n>")} \u4E0E Agent \u5BF9\u8BDD`);
3331
+ printer.log(` ${chalk27.cyan("actant setup")} \u91CD\u65B0\u8FD0\u884C\u6B64\u5411\u5BFC`);
3332
+ printer.log("");
3333
+ printer.dim(" \u66F4\u591A\u5E2E\u52A9: actant help");
3334
+ printer.log("");
3335
+ }
3336
+ async function tryStartDaemon(printer, socketPath) {
3337
+ try {
3338
+ const { fork: fork2, spawn: spawn4 } = await import("child_process");
3339
+ const { join: join8 } = await import("path");
3340
+ const { isWindows: isWindows3, isSingleExecutable: isSingleExecutable2 } = await import("@actant/shared");
3341
+ let child;
3342
+ if (isSingleExecutable2()) {
3343
+ child = spawn4(process.execPath, ["--__actant-daemon"], {
3344
+ detached: true,
3345
+ stdio: ["ignore", "ignore", "ignore"],
3346
+ env: process.env
3347
+ });
3348
+ } else {
3349
+ const daemonScript = join8(import.meta.dirname, "..", "daemon-entry.js");
3350
+ child = isWindows3() ? spawn4(process.execPath, [daemonScript], {
3351
+ detached: true,
3352
+ stdio: ["ignore", "ignore", "ignore"],
3353
+ env: process.env
3354
+ }) : fork2(daemonScript, [], {
3355
+ detached: true,
3356
+ stdio: ["ignore", "ignore", "ignore", "ipc"],
3357
+ env: process.env
3358
+ });
3359
+ }
3360
+ if ("connected" in child && child.connected) child.disconnect();
3361
+ child.unref();
3362
+ const client = new RpcClient(socketPath);
3363
+ for (let i = 0; i < 10; i++) {
3364
+ await new Promise((r) => setTimeout(r, 1e3));
3365
+ if (await client.ping()) {
3366
+ printer.success(" \u2713 Daemon \u5DF2\u542F\u52A8");
3367
+ return true;
3368
+ }
3369
+ }
3370
+ printer.warn(" \u26A0 Daemon \u8FDB\u7A0B\u5DF2\u542F\u52A8\u4F46\u672A\u54CD\u5E94");
3371
+ return false;
3372
+ } catch (err) {
3373
+ printer.warn(` \u26A0 \u542F\u52A8 Daemon \u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`);
3374
+ return false;
3375
+ }
3376
+ }
3377
+ function isUserCancellation(err) {
3378
+ if (err instanceof Error) {
3379
+ return err.message.includes("User force closed") || err.message.includes("prompt was canceled") || err.name === "ExitPromptError";
3380
+ }
3381
+ return false;
3382
+ }
3383
+
2600
3384
  // src/program.ts
2601
3385
  function defaultSocketPath() {
2602
- return process.env["ACTANT_SOCKET"] ?? getDefaultIpcPath();
3386
+ const home = process.env["ACTANT_HOME"];
3387
+ return process.env["ACTANT_SOCKET"] ?? getDefaultIpcPath2(home);
2603
3388
  }
2604
3389
  function createProgram(socketPath, printer) {
2605
3390
  const sock = socketPath ?? defaultSocketPath();
2606
3391
  const client = new RpcClient(sock);
2607
- const program = new Command72("actant").version("0.1.0").description("Actant \u2014 Build, manage, and compose AI agents");
3392
+ const pkgPath = join7(import.meta.dirname, "..", "package.json");
3393
+ const { version } = JSON.parse(readFileSync4(pkgPath, "utf-8"));
3394
+ const program = new Command73("actant").version(version).description("Actant \u2014 Build, manage, and compose AI agents");
2608
3395
  program.addCommand(createTemplateCommand(client, printer));
2609
3396
  program.addCommand(createAgentCommand(client, printer));
2610
3397
  program.addCommand(createSkillCommand(client, printer));
@@ -2619,6 +3406,7 @@ function createProgram(socketPath, printer) {
2619
3406
  program.addCommand(createProxyCommand(printer));
2620
3407
  program.addCommand(createHelpCommand());
2621
3408
  program.addCommand(createSelfUpdateCommand());
3409
+ program.addCommand(createSetupCommand(printer));
2622
3410
  program.exitOverride();
2623
3411
  return program;
2624
3412
  }
@@ -2631,7 +3419,7 @@ async function run(argv) {
2631
3419
  if (!versionRequested && !helpRequested) {
2632
3420
  const sock = defaultSocketPath();
2633
3421
  const client = new RpcClient(sock);
2634
- const { startRepl } = await import("./repl-JIMJ2V2Y.js");
3422
+ const { startRepl } = await import("./repl-7TMOU5HY.js");
2635
3423
  await startRepl(client, sock);
2636
3424
  return;
2637
3425
  }
@@ -2660,4 +3448,4 @@ export {
2660
3448
  createProgram,
2661
3449
  run
2662
3450
  };
2663
- //# sourceMappingURL=chunk-2FKBVXMH.js.map
3451
+ //# sourceMappingURL=chunk-I3QY66Y6.js.map