@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.
- package/dist/bin/actant.js +1 -1
- package/dist/{chunk-2FKBVXMH.js → chunk-I3QY66Y6.js} +797 -9
- package/dist/chunk-I3QY66Y6.js.map +1 -0
- package/dist/index.js +1 -1
- package/dist/{program-3Y3ULHTY.js → program-BFSBXPW7.js} +2 -2
- package/dist/{repl-JIMJ2V2Y.js → repl-7TMOU5HY.js} +2 -2
- package/package.json +4 -3
- package/dist/chunk-2FKBVXMH.js.map +0 -1
- /package/dist/{program-3Y3ULHTY.js.map → program-BFSBXPW7.js.map} +0 -0
- /package/dist/{repl-JIMJ2V2Y.js.map → repl-7TMOU5HY.js.map} +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// src/program.ts
|
|
2
|
-
import { Command as
|
|
3
|
-
import {
|
|
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.
|
|
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: [
|
|
1252
|
+
keywords: [
|
|
1253
|
+
"actant",
|
|
1254
|
+
"ai-agent",
|
|
1255
|
+
"cli",
|
|
1256
|
+
"agent-platform"
|
|
1257
|
+
],
|
|
1251
1258
|
publishConfig: {
|
|
1252
1259
|
access: "public"
|
|
1253
1260
|
},
|
|
1254
|
-
files: [
|
|
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
|
-
|
|
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
|
|
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-
|
|
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-
|
|
3451
|
+
//# sourceMappingURL=chunk-I3QY66Y6.js.map
|