@clue-ai/cli 0.0.19 → 0.0.21
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/bin/clue-cli.mjs +97 -6
- package/package.json +1 -1
- package/src/setup-agent.mjs +56 -0
- package/src/setup-prepare.mjs +16 -1
package/bin/clue-cli.mjs
CHANGED
|
@@ -876,13 +876,93 @@ const renderEnvironmentInstructions = (instructions) => {
|
|
|
876
876
|
const lines = [
|
|
877
877
|
"",
|
|
878
878
|
`環境変数の設定内容を ${instructions.env_file_path} に書き出しました。`,
|
|
879
|
-
`Step2で ${instructions.env_file_path} を開き、各サービスの env
|
|
879
|
+
`Step2で ${instructions.env_file_path} を開き、各サービスの env、setup-agent 用AI設定、GitHub Secrets/Variables に反映してください。`,
|
|
880
|
+
`Step3で setup-agent を実行する前に ${instructions.setup_agent_required_env_names?.join(", ") ?? "CLUE_AI_PROVIDER, CLUE_AI_PROVIDER_API_KEY, CLUE_AI_MODEL"} を設定してください。`,
|
|
881
|
+
"CLUE_AI_PROVIDER_API_KEY は Clue API key ではなく、OpenAI または Anthropic の API key です。",
|
|
882
|
+
`setup-agent 実行: ${instructions.setup_agent_command ?? clueCliCommand("setup-agent --repo .")}`,
|
|
880
883
|
`${instructions.env_file_path} は秘密情報を含むため、コミットしないでください。`,
|
|
881
884
|
"",
|
|
882
885
|
];
|
|
883
886
|
return `${lines.join("\n")}\n`;
|
|
884
887
|
};
|
|
885
888
|
|
|
889
|
+
const renderSetupResult = ({ preparation }) => {
|
|
890
|
+
if (preparation?.status === "ready_for_ai") {
|
|
891
|
+
const envPath =
|
|
892
|
+
preparation.environment_instructions?.env_file_path ?? ".env.clue";
|
|
893
|
+
const manifestPath =
|
|
894
|
+
preparation.artifacts?.setup_manifest_path ?? ".clue/setup-manifest.json";
|
|
895
|
+
const workflowPath =
|
|
896
|
+
preparation.artifacts?.ci_workflow_path ??
|
|
897
|
+
".github/workflows/clue-semantic-snapshot.yml";
|
|
898
|
+
return [
|
|
899
|
+
"Clue setup Step1 が完了しました。",
|
|
900
|
+
"",
|
|
901
|
+
"作成したファイル:",
|
|
902
|
+
`- ${envPath}`,
|
|
903
|
+
`- ${manifestPath}`,
|
|
904
|
+
`- ${workflowPath}`,
|
|
905
|
+
"",
|
|
906
|
+
"次にやること:",
|
|
907
|
+
`1. setup画面のStep2を見ながら ${envPath} に各サービスのenvとsetup-agent用AI API keyを設定してください。`,
|
|
908
|
+
`2. ${clueCliCommand("setup-agent --repo .")} を実行してください。`,
|
|
909
|
+
"",
|
|
910
|
+
"補足: CLUE_AI_PROVIDER_API_KEY は Clue API key ではなく、OpenAI または Anthropic の API key です。",
|
|
911
|
+
].join("\n");
|
|
912
|
+
}
|
|
913
|
+
|
|
914
|
+
const blockers = Array.isArray(preparation?.blockers)
|
|
915
|
+
? preparation.blockers
|
|
916
|
+
.map((blocker) => blocker.message ?? blocker.reason ?? blocker.code)
|
|
917
|
+
.filter(Boolean)
|
|
918
|
+
: [];
|
|
919
|
+
return [
|
|
920
|
+
"Clue setup に失敗しました。",
|
|
921
|
+
"",
|
|
922
|
+
"原因:",
|
|
923
|
+
...(blockers.length > 0
|
|
924
|
+
? blockers.map((blocker) => `- ${blocker}`)
|
|
925
|
+
: ["- setup に必要な情報を検出できませんでした。"]),
|
|
926
|
+
].join("\n");
|
|
927
|
+
};
|
|
928
|
+
|
|
929
|
+
const renderSetupAgentResult = (report) => {
|
|
930
|
+
if (report?.status === "user_verification_pending") {
|
|
931
|
+
return [
|
|
932
|
+
"Clue setup-agent の実行が完了しました。",
|
|
933
|
+
"",
|
|
934
|
+
"コード差分を確認してください。",
|
|
935
|
+
`次の動作確認: ${clueCliCommand("setup-watch --local")}`,
|
|
936
|
+
].join("\n");
|
|
937
|
+
}
|
|
938
|
+
|
|
939
|
+
if (report?.code === "CLUE_SETUP_AGENT_AI_CONFIG_MISSING") {
|
|
940
|
+
const missingInputs = report.setup_doctor?.missing_inputs ?? [];
|
|
941
|
+
return [
|
|
942
|
+
"Clue setup-agent を開始できません。",
|
|
943
|
+
"",
|
|
944
|
+
`不足している環境変数: ${missingInputs.join(", ")}`,
|
|
945
|
+
"",
|
|
946
|
+
".env.clue の Setup Agent セクションに値を設定してから、もう一度実行してください。",
|
|
947
|
+
"",
|
|
948
|
+
"例:",
|
|
949
|
+
"CLUE_AI_PROVIDER=openai",
|
|
950
|
+
"CLUE_AI_PROVIDER_API_KEY=<your-openai-api-key>",
|
|
951
|
+
"CLUE_AI_MODEL=gpt-5.4-mini",
|
|
952
|
+
].join("\n");
|
|
953
|
+
}
|
|
954
|
+
|
|
955
|
+
const blocker = report?.blockers?.[0];
|
|
956
|
+
const reason =
|
|
957
|
+
blocker?.reason ??
|
|
958
|
+
report?.setup_doctor?.reason ??
|
|
959
|
+
report?.code ??
|
|
960
|
+
"原因を特定できませんでした。";
|
|
961
|
+
return ["Clue setup-agent に失敗しました。", "", `原因: ${reason}`].join(
|
|
962
|
+
"\n",
|
|
963
|
+
);
|
|
964
|
+
};
|
|
965
|
+
|
|
886
966
|
const main = async () => {
|
|
887
967
|
const { command, flags } = parseArgs(process.argv.slice(2));
|
|
888
968
|
if (
|
|
@@ -938,7 +1018,11 @@ const main = async () => {
|
|
|
938
1018
|
flags,
|
|
939
1019
|
repoRoot,
|
|
940
1020
|
});
|
|
941
|
-
|
|
1021
|
+
if (flags.has("json")) {
|
|
1022
|
+
process.stdout.write(`${JSON.stringify(report, null, 2)}\n`);
|
|
1023
|
+
} else {
|
|
1024
|
+
process.stdout.write(`${renderSetupAgentResult(report)}\n`);
|
|
1025
|
+
}
|
|
942
1026
|
if (report.status === "blocked") {
|
|
943
1027
|
process.exitCode = 1;
|
|
944
1028
|
}
|
|
@@ -993,12 +1077,19 @@ const main = async () => {
|
|
|
993
1077
|
const environmentInstructions = renderEnvironmentInstructions(
|
|
994
1078
|
preparation.environment_instructions,
|
|
995
1079
|
);
|
|
996
|
-
if (environmentInstructions) {
|
|
1080
|
+
if (environmentInstructions && flags.has("json")) {
|
|
997
1081
|
process.stderr.write(environmentInstructions);
|
|
998
1082
|
}
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1083
|
+
if (flags.has("json")) {
|
|
1084
|
+
process.stdout.write(
|
|
1085
|
+
`${JSON.stringify({ ...report, preparation }, null, 2)}\n`,
|
|
1086
|
+
);
|
|
1087
|
+
} else {
|
|
1088
|
+
process.stdout.write(`${renderSetupResult({ preparation })}\n`);
|
|
1089
|
+
}
|
|
1090
|
+
if (!flags.has("json") && preparation.status === "blocked") {
|
|
1091
|
+
process.exitCode = 1;
|
|
1092
|
+
}
|
|
1002
1093
|
return;
|
|
1003
1094
|
}
|
|
1004
1095
|
|
package/package.json
CHANGED
package/src/setup-agent.mjs
CHANGED
|
@@ -10,6 +10,11 @@ import { runSetupDoctor } from "./setup-doctor.mjs";
|
|
|
10
10
|
const DEFAULT_SETUP_MANIFEST_PATH = ".clue/setup-manifest.json";
|
|
11
11
|
const DEFAULT_ENV_GUIDE_PATH = ".env.clue";
|
|
12
12
|
const DEFAULT_MAX_ATTEMPTS = 3;
|
|
13
|
+
const REQUIRED_SETUP_AGENT_AI_ENV_NAMES = [
|
|
14
|
+
"CLUE_AI_PROVIDER",
|
|
15
|
+
"CLUE_AI_PROVIDER_API_KEY",
|
|
16
|
+
"CLUE_AI_MODEL",
|
|
17
|
+
];
|
|
13
18
|
const DEPENDENCY_WRITE_FILE_CANDIDATES = [
|
|
14
19
|
"package.json",
|
|
15
20
|
"package-lock.json",
|
|
@@ -80,6 +85,50 @@ const aiProviderEnvFromFlags = ({ env, flags }) => {
|
|
|
80
85
|
};
|
|
81
86
|
};
|
|
82
87
|
|
|
88
|
+
const missingSetupAgentAiEnvNames = (env) =>
|
|
89
|
+
REQUIRED_SETUP_AGENT_AI_ENV_NAMES.filter((name) => !optionalString(env[name]));
|
|
90
|
+
|
|
91
|
+
const blockedMissingAiProviderConfig = ({ manifestPath, missingInputs }) => ({
|
|
92
|
+
status: "blocked",
|
|
93
|
+
code: "CLUE_SETUP_AGENT_AI_CONFIG_MISSING",
|
|
94
|
+
manifest_path: manifestPath,
|
|
95
|
+
attempts: [],
|
|
96
|
+
setup_check: null,
|
|
97
|
+
setup_doctor: {
|
|
98
|
+
status: "skipped",
|
|
99
|
+
reason: "AI provider configuration is missing",
|
|
100
|
+
missing_inputs: missingInputs,
|
|
101
|
+
report: null,
|
|
102
|
+
},
|
|
103
|
+
blockers: [
|
|
104
|
+
{
|
|
105
|
+
reason:
|
|
106
|
+
"setup-agent requires CLUE_AI_PROVIDER, CLUE_AI_PROVIDER_API_KEY, and CLUE_AI_MODEL before lifecycle planning",
|
|
107
|
+
evidence: {
|
|
108
|
+
missing_inputs: missingInputs,
|
|
109
|
+
env_file_path: DEFAULT_ENV_GUIDE_PATH,
|
|
110
|
+
supported_providers: ["openai", "anthropic"],
|
|
111
|
+
cli_flags: [
|
|
112
|
+
"--ai-provider",
|
|
113
|
+
"--ai-provider-api-key",
|
|
114
|
+
"--ai-model",
|
|
115
|
+
],
|
|
116
|
+
},
|
|
117
|
+
},
|
|
118
|
+
],
|
|
119
|
+
next_steps: [
|
|
120
|
+
"Open .env.clue and replace CLUE_AI_PROVIDER_API_KEY with an OpenAI API key for codex or an Anthropic API key for claude_code.",
|
|
121
|
+
"Confirm CLUE_AI_PROVIDER and CLUE_AI_MODEL are set in .env.clue or process env.",
|
|
122
|
+
"Alternatively run setup-agent with --ai-provider, --ai-provider-api-key, and --ai-model.",
|
|
123
|
+
],
|
|
124
|
+
user_verification: {
|
|
125
|
+
setup_watch_owner: "user",
|
|
126
|
+
setup_watch_auto_run: false,
|
|
127
|
+
status: "not_reached",
|
|
128
|
+
required_command: "npx -y @clue-ai/cli setup-watch --local",
|
|
129
|
+
},
|
|
130
|
+
});
|
|
131
|
+
|
|
83
132
|
const requireManifest = async ({ manifestPath, repoRoot }) => {
|
|
84
133
|
try {
|
|
85
134
|
return await readJson(resolve(repoRoot, manifestPath));
|
|
@@ -344,6 +393,13 @@ export const runSetupAgent = async ({
|
|
|
344
393
|
DEFAULT_MAX_ATTEMPTS,
|
|
345
394
|
);
|
|
346
395
|
const aiEnv = aiProviderEnvFromFlags({ env: mergedEnv, flags });
|
|
396
|
+
const missingAiInputs = missingSetupAgentAiEnvNames(aiEnv);
|
|
397
|
+
if (missingAiInputs.length > 0) {
|
|
398
|
+
return blockedMissingAiProviderConfig({
|
|
399
|
+
manifestPath,
|
|
400
|
+
missingInputs: missingAiInputs,
|
|
401
|
+
});
|
|
402
|
+
}
|
|
347
403
|
const attempts = [];
|
|
348
404
|
let failureContext = null;
|
|
349
405
|
let lastSetupCheck = null;
|
package/src/setup-prepare.mjs
CHANGED
|
@@ -32,6 +32,11 @@ const BACKEND_RUNTIME_ENV_NAMES = [
|
|
|
32
32
|
"CLUE_INGEST_ENDPOINT",
|
|
33
33
|
"CLUE_API_KEY",
|
|
34
34
|
];
|
|
35
|
+
const SETUP_AGENT_AI_ENV_NAMES = [
|
|
36
|
+
"CLUE_AI_PROVIDER",
|
|
37
|
+
"CLUE_AI_PROVIDER_API_KEY",
|
|
38
|
+
"CLUE_AI_MODEL",
|
|
39
|
+
];
|
|
35
40
|
const AI_PROVIDER_GUIDES = {
|
|
36
41
|
codex: {
|
|
37
42
|
provider: "openai",
|
|
@@ -352,6 +357,14 @@ const buildEnvironmentGuideText = (instructions) => {
|
|
|
352
357
|
"",
|
|
353
358
|
);
|
|
354
359
|
}
|
|
360
|
+
lines.push(
|
|
361
|
+
"Setup Agent",
|
|
362
|
+
"# Before running `npx -y @clue-ai/cli setup-agent --repo .`, set the AI provider values below.",
|
|
363
|
+
"# setup-agent reads CLUE_AI_PROVIDER, CLUE_AI_PROVIDER_API_KEY, and CLUE_AI_MODEL from this file or process env.",
|
|
364
|
+
"# CLUE_AI_PROVIDER_API_KEY is not a Clue key. It must be an OpenAI key for codex or an Anthropic key for claude_code.",
|
|
365
|
+
"# You may also pass --ai-provider, --ai-provider-api-key, and --ai-model directly to setup-agent.",
|
|
366
|
+
"",
|
|
367
|
+
);
|
|
355
368
|
lines.push(
|
|
356
369
|
"GitHub Secrets",
|
|
357
370
|
...instructions.ci_github.secrets.flatMap(renderEnvironmentEntry),
|
|
@@ -374,7 +387,9 @@ const summarizeEnvironmentInstructions = (instructions) => {
|
|
|
374
387
|
return {
|
|
375
388
|
status: "ready",
|
|
376
389
|
env_file_path: instructions.env_file_path,
|
|
377
|
-
message: `${instructions.env_file_path} を開き、各サービスの env
|
|
390
|
+
message: `${instructions.env_file_path} を開き、各サービスの env、setup-agent 用AI設定、GitHub Secrets/Variables に反映してください。`,
|
|
391
|
+
setup_agent_required_env_names: SETUP_AGENT_AI_ENV_NAMES,
|
|
392
|
+
setup_agent_command: "npx -y @clue-ai/cli setup-agent --repo .",
|
|
378
393
|
service_env_block_count: instructions.service_env_blocks.length,
|
|
379
394
|
github_secret_names: instructions.ci_github.secrets.map(
|
|
380
395
|
(entry) => entry.name,
|