@tonyclaw/agent-inspector 2.0.16 → 2.0.18
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/.output/cli.js +394 -55
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-DPs4UHwd.js → CompareDrawer-CepU-dLW.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-B1KylMPs.js → ProxyViewerContainer-BG7rc33d.js} +16 -16
- package/.output/public/assets/{ReplayDialog-8ISC28XF.js → ReplayDialog-DK6SPv8X.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-BhbsgfBO.js → RequestAnatomy-C_C6ZU3T.js} +1 -1
- package/.output/public/assets/{ResponseView-CyM7JXeA.js → ResponseView-Bqpra4Zw.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-BaX0x38n.js → StreamingChunkSequence-CdPbpprq.js} +1 -1
- package/.output/public/assets/_sessionId-CsNARHj5.js +1 -0
- package/.output/public/assets/index-37NfO0zx.js +1 -0
- package/.output/public/assets/{main-B2t-3SYj.js → main-BRXsrxtv.js} +2 -2
- package/.output/server/{_sessionId-CEbZTs68.mjs → _sessionId-B8Bbfs-v.mjs} +2 -2
- package/.output/server/_ssr/{CompareDrawer-CEo48Wsu.mjs → CompareDrawer-TgGZLf1J.mjs} +2 -2
- package/.output/server/_ssr/{ProxyViewerContainer-5ekIK_jx.mjs → ProxyViewerContainer-B_ppaNmQ.mjs} +41 -12
- package/.output/server/_ssr/{ReplayDialog-C0nEvbYo.mjs → ReplayDialog-BXlajnMC.mjs} +3 -3
- package/.output/server/_ssr/{RequestAnatomy-CT55prmM.mjs → RequestAnatomy-CCrx09-i.mjs} +2 -2
- package/.output/server/_ssr/{ResponseView-DBZSBCOD.mjs → ResponseView-BxtMJrov.mjs} +2 -2
- package/.output/server/_ssr/{StreamingChunkSequence-BuVT7Oke.mjs → StreamingChunkSequence-BlpdSPb8.mjs} +2 -2
- package/.output/server/_ssr/{index-Cw_zJVQv.mjs → index-BeTMNSJy.mjs} +2 -2
- package/.output/server/_ssr/index.mjs +2 -2
- package/.output/server/_ssr/{router-DxjqHipT.mjs → router-Ddl1tuU7.mjs} +27 -11
- package/.output/server/{_tanstack-start-manifest_v-xeOo5gW5.mjs → _tanstack-start-manifest_v-Bvdz_U0f.mjs} +1 -1
- package/.output/server/index.mjs +56 -56
- package/README.md +37 -5
- package/package.json +3 -3
- package/scripts/setup-agent-skills.mjs +64 -0
- package/src/cli/doctor.ts +12 -5
- package/src/cli/onboard.ts +407 -13
- package/src/cli/templates/codex-skill-onboard.ts +5 -0
- package/src/cli/templates/command-onboard.ts +12 -4
- package/src/cli/templates/skill-onboard.ts +17 -21
- package/src/components/OnboardingBanner.tsx +5 -0
- package/src/components/providers/SettingsDialog.tsx +22 -4
- package/src/proxy/dataDir.ts +35 -13
- package/.output/public/assets/_sessionId-CShO0OrR.js +0 -1
- package/.output/public/assets/index-BkdYiTpV.js +0 -1
- package/scripts/setup-codex-skill.mjs +0 -38
package/.output/cli.js
CHANGED
|
@@ -98,14 +98,17 @@ var init_detect_tools = __esm({
|
|
|
98
98
|
});
|
|
99
99
|
|
|
100
100
|
// src/cli/templates/command-onboard.ts
|
|
101
|
-
function renderCommandOnboard() {
|
|
101
|
+
function renderCommandOnboard(ctx) {
|
|
102
102
|
return `---
|
|
103
|
-
description: Walk through agent-inspector setup
|
|
103
|
+
description: Walk through agent-inspector setup - start the proxy, wire your AI tool, capture your first request.
|
|
104
|
+
metadata:
|
|
105
|
+
author: agent-inspector
|
|
106
|
+
version: ${ctx.version}
|
|
104
107
|
---
|
|
105
108
|
|
|
106
109
|
Invoke the \`agent-inspector-onboard\` skill and follow its phases.
|
|
107
110
|
|
|
108
|
-
The user wants to set up agent-inspector. If they have specific context (e.g. "I'm on Windows", "I already added my API key"), honor it
|
|
111
|
+
The user wants to set up agent-inspector. If they have specific context (e.g. "I'm on Windows", "I already added my API key"), honor it - but otherwise just run the skill end-to-end and let the \`EXPLAIN / DO / PAUSE\` markers drive the conversation.
|
|
109
112
|
`;
|
|
110
113
|
}
|
|
111
114
|
var init_command_onboard = __esm({
|
|
@@ -150,12 +153,14 @@ Check that the package and Codex home exist without printing secrets.
|
|
|
150
153
|
|
|
151
154
|
\`\`\`powershell
|
|
152
155
|
Get-Command agent-inspector -ErrorAction SilentlyContinue | Select-Object -ExpandProperty Source
|
|
156
|
+
agent-inspector onboard --status
|
|
153
157
|
Test-Path (Join-Path $env:USERPROFILE ".codex")
|
|
154
158
|
Test-Path (Join-Path $env:USERPROFILE ".codex\\config.toml")
|
|
155
159
|
\`\`\`
|
|
156
160
|
|
|
157
161
|
\`\`\`bash
|
|
158
162
|
command -v agent-inspector || true
|
|
163
|
+
agent-inspector onboard --status
|
|
159
164
|
test -d "$HOME/.codex" && echo "codex home: present" || echo "codex home: missing"
|
|
160
165
|
test -f "$HOME/.codex/config.toml" && echo "config: present" || echo "config: missing"
|
|
161
166
|
\`\`\`
|
|
@@ -166,6 +171,9 @@ If \`agent-inspector\` is missing, ask the user to install it first:
|
|
|
166
171
|
npm install -g @tonyclaw/agent-inspector
|
|
167
172
|
\`\`\`
|
|
168
173
|
|
|
174
|
+
If \`agent-inspector onboard --status\` reports \`outdated\` or \`missing\`, ask the user to run
|
|
175
|
+
\`agent-inspector onboard --force\` and restart this skill before continuing.
|
|
176
|
+
|
|
169
177
|
Do not read \`~/.codex/auth.json\`, token files, or unrelated Codex state files.
|
|
170
178
|
|
|
171
179
|
---
|
|
@@ -352,7 +360,19 @@ Default proxy port: \`${port}\` (override with \`PORT=<n> agent-inspector\` or \
|
|
|
352
360
|
|
|
353
361
|
**EXPLAIN:** "Before we do anything, let me see what's already set up. If some of the steps are already done, we can skip them."
|
|
354
362
|
|
|
355
|
-
**DO:**
|
|
363
|
+
**DO:** First check whether the generated onboarding files match the installed npm package. If any
|
|
364
|
+
entry is \`outdated\` or \`missing\`, tell the user to run \`agent-inspector onboard --force\` before
|
|
365
|
+
continuing so they are not guided by stale instructions.
|
|
366
|
+
|
|
367
|
+
\`\`\`bash
|
|
368
|
+
agent-inspector onboard --status
|
|
369
|
+
\`\`\`
|
|
370
|
+
|
|
371
|
+
\`\`\`powershell
|
|
372
|
+
agent-inspector onboard --status
|
|
373
|
+
\`\`\`
|
|
374
|
+
|
|
375
|
+
**DO:** Then probe the three pieces of state this skill touches. Use targeted checks \u2014 do **not** read large JSON files into the conversation.
|
|
356
376
|
|
|
357
377
|
\`\`\`bash
|
|
358
378
|
# 1. Is the proxy already up?
|
|
@@ -369,9 +389,6 @@ agent_inspector_data_dir() {
|
|
|
369
389
|
case "$AGENT_INSPECTOR_CONFIG_DIR" in /*) printf '%s
|
|
370
390
|
' "$AGENT_INSPECTOR_CONFIG_DIR" ;; *) printf '%s
|
|
371
391
|
' "$base/$AGENT_INSPECTOR_CONFIG_DIR" ;; esac
|
|
372
|
-
elif { [ ! -e "$base/.agent-inspector/providers.json" ] && [ ! -e "$base/.agent-inspector/config.json" ] && [ ! -e "$base/.agent-inspector/logs" ] && [ ! -e "$base/.agent-inspector/chunks" ]; } && { [ -e "$base/.llm-inspector/providers.json" ] || [ -e "$base/.llm-inspector/config.json" ] || [ -e "$base/.llm-inspector/logs" ] || [ -e "$base/.llm-inspector/chunks" ]; }; then
|
|
373
|
-
printf '%s
|
|
374
|
-
' "$base/.llm-inspector"
|
|
375
392
|
else
|
|
376
393
|
printf '%s
|
|
377
394
|
' "$base/.agent-inspector"
|
|
@@ -419,14 +436,7 @@ function Resolve-AgentInspectorDataDir {
|
|
|
419
436
|
if ([System.IO.Path]::IsPathRooted($env:AGENT_INSPECTOR_CONFIG_DIR)) { return $env:AGENT_INSPECTOR_CONFIG_DIR }
|
|
420
437
|
return (Join-Path $base $env:AGENT_INSPECTOR_CONFIG_DIR)
|
|
421
438
|
}
|
|
422
|
-
|
|
423
|
-
$legacy = Join-Path $base '.llm-inspector'
|
|
424
|
-
$currentHasState = (Test-Path (Join-Path $current 'providers.json')) -or (Test-Path (Join-Path $current 'config.json')) -or (Test-Path (Join-Path $current 'logs')) -or (Test-Path (Join-Path $current 'chunks'))
|
|
425
|
-
$legacyHasState = (Test-Path (Join-Path $legacy 'providers.json')) -or (Test-Path (Join-Path $legacy 'config.json')) -or (Test-Path (Join-Path $legacy 'logs')) -or (Test-Path (Join-Path $legacy 'chunks'))
|
|
426
|
-
if (-not $currentHasState -and $legacyHasState) {
|
|
427
|
-
return $legacy
|
|
428
|
-
}
|
|
429
|
-
return $current
|
|
439
|
+
return (Join-Path $base '.agent-inspector')
|
|
430
440
|
}
|
|
431
441
|
$dataDir = Resolve-AgentInspectorDataDir
|
|
432
442
|
$providers = Join-Path $dataDir 'providers.json'
|
|
@@ -546,9 +556,6 @@ agent_inspector_data_dir() {
|
|
|
546
556
|
case "$AGENT_INSPECTOR_CONFIG_DIR" in /*) printf '%s
|
|
547
557
|
' "$AGENT_INSPECTOR_CONFIG_DIR" ;; *) printf '%s
|
|
548
558
|
' "$base/$AGENT_INSPECTOR_CONFIG_DIR" ;; esac
|
|
549
|
-
elif { [ ! -e "$base/.agent-inspector/providers.json" ] && [ ! -e "$base/.agent-inspector/config.json" ] && [ ! -e "$base/.agent-inspector/logs" ] && [ ! -e "$base/.agent-inspector/chunks" ]; } && { [ -e "$base/.llm-inspector/providers.json" ] || [ -e "$base/.llm-inspector/config.json" ] || [ -e "$base/.llm-inspector/logs" ] || [ -e "$base/.llm-inspector/chunks" ]; }; then
|
|
550
|
-
printf '%s
|
|
551
|
-
' "$base/.llm-inspector"
|
|
552
559
|
else
|
|
553
560
|
printf '%s
|
|
554
561
|
' "$base/.agent-inspector"
|
|
@@ -593,14 +600,7 @@ function Resolve-AgentInspectorDataDir {
|
|
|
593
600
|
if ([System.IO.Path]::IsPathRooted($env:AGENT_INSPECTOR_CONFIG_DIR)) { return $env:AGENT_INSPECTOR_CONFIG_DIR }
|
|
594
601
|
return (Join-Path $base $env:AGENT_INSPECTOR_CONFIG_DIR)
|
|
595
602
|
}
|
|
596
|
-
|
|
597
|
-
$legacy = Join-Path $base '.llm-inspector'
|
|
598
|
-
$currentHasState = (Test-Path (Join-Path $current 'providers.json')) -or (Test-Path (Join-Path $current 'config.json')) -or (Test-Path (Join-Path $current 'logs')) -or (Test-Path (Join-Path $current 'chunks'))
|
|
599
|
-
$legacyHasState = (Test-Path (Join-Path $legacy 'providers.json')) -or (Test-Path (Join-Path $legacy 'config.json')) -or (Test-Path (Join-Path $legacy 'logs')) -or (Test-Path (Join-Path $legacy 'chunks'))
|
|
600
|
-
if (-not $currentHasState -and $legacyHasState) {
|
|
601
|
-
return $legacy
|
|
602
|
-
}
|
|
603
|
-
return $current
|
|
603
|
+
return (Join-Path $base '.agent-inspector')
|
|
604
604
|
}
|
|
605
605
|
$dir = Resolve-AgentInspectorDataDir
|
|
606
606
|
$file = Join-Path $dir 'providers.json'
|
|
@@ -834,6 +834,8 @@ done
|
|
|
834
834
|
\`\`\`
|
|
835
835
|
|
|
836
836
|
- **Re-run onboard**: \`agent-inspector onboard --force\` refreshes this skill.
|
|
837
|
+
- **Check onboard files**: \`agent-inspector onboard --status\` shows whether generated skills are
|
|
838
|
+
current, outdated, missing, newer, or custom.
|
|
837
839
|
- **Full docs**: see the project README (linked from the Web UI footer).
|
|
838
840
|
|
|
839
841
|
> **PAUSE** \u2014 use \`AskUserQuestion\` with header \`All set?\` and options \`["All set, I'm done", "Wait, I want to revisit a phase"]\`. Wait for the answer.
|
|
@@ -864,10 +866,42 @@ var onboard_exports = {};
|
|
|
864
866
|
__export(onboard_exports, {
|
|
865
867
|
runOnboard: () => runOnboard
|
|
866
868
|
});
|
|
867
|
-
import {
|
|
869
|
+
import {
|
|
870
|
+
mkdirSync,
|
|
871
|
+
writeFileSync,
|
|
872
|
+
existsSync as existsSync2,
|
|
873
|
+
readFileSync,
|
|
874
|
+
unlinkSync,
|
|
875
|
+
readdirSync,
|
|
876
|
+
rmdirSync
|
|
877
|
+
} from "node:fs";
|
|
868
878
|
import { homedir as homedir2 } from "node:os";
|
|
869
879
|
import { dirname, join as join2 } from "node:path";
|
|
870
880
|
import { fileURLToPath } from "node:url";
|
|
881
|
+
function actionForStatus(label, state) {
|
|
882
|
+
switch (state) {
|
|
883
|
+
case "missing":
|
|
884
|
+
switch (label) {
|
|
885
|
+
case "Codex skill":
|
|
886
|
+
return "agent-inspector onboard --codex-only";
|
|
887
|
+
case "Claude skill":
|
|
888
|
+
case "Claude command":
|
|
889
|
+
return "agent-inspector onboard --skip-codex-skill";
|
|
890
|
+
default:
|
|
891
|
+
return "agent-inspector onboard";
|
|
892
|
+
}
|
|
893
|
+
case "outdated":
|
|
894
|
+
return "agent-inspector onboard --force";
|
|
895
|
+
case "custom":
|
|
896
|
+
return "preserved; use agent-inspector onboard --force to replace";
|
|
897
|
+
case "newer":
|
|
898
|
+
return "no action; installed file is newer than this package";
|
|
899
|
+
case "current":
|
|
900
|
+
return "no action";
|
|
901
|
+
default:
|
|
902
|
+
return "agent-inspector onboard";
|
|
903
|
+
}
|
|
904
|
+
}
|
|
871
905
|
function parseFlags(argv) {
|
|
872
906
|
const flags = {
|
|
873
907
|
force: false,
|
|
@@ -876,6 +910,9 @@ function parseFlags(argv) {
|
|
|
876
910
|
skipToolWire: false,
|
|
877
911
|
codexOnly: false,
|
|
878
912
|
skipCodexSkill: false,
|
|
913
|
+
uninstall: false,
|
|
914
|
+
status: false,
|
|
915
|
+
json: false,
|
|
879
916
|
skillDir: null,
|
|
880
917
|
codexSkillDir: null
|
|
881
918
|
};
|
|
@@ -902,6 +939,15 @@ function parseFlags(argv) {
|
|
|
902
939
|
case "--skip-codex-skill":
|
|
903
940
|
flags.skipCodexSkill = true;
|
|
904
941
|
break;
|
|
942
|
+
case "--uninstall":
|
|
943
|
+
flags.uninstall = true;
|
|
944
|
+
break;
|
|
945
|
+
case "--status":
|
|
946
|
+
flags.status = true;
|
|
947
|
+
break;
|
|
948
|
+
case "--json":
|
|
949
|
+
flags.json = true;
|
|
950
|
+
break;
|
|
905
951
|
case "--skill-dir": {
|
|
906
952
|
const next = argv[i + 1];
|
|
907
953
|
if (next === void 0) {
|
|
@@ -950,6 +996,9 @@ Options:
|
|
|
950
996
|
--skip-tool-wire Skip the wire-tool phase in the Claude skill body
|
|
951
997
|
--skip-codex-skill Install only the Claude Code skill and slash command
|
|
952
998
|
--codex-only Install only the Codex skill
|
|
999
|
+
--uninstall Remove generated files whose version matches this package
|
|
1000
|
+
--status Show installed onboarding file versions and suggested action
|
|
1001
|
+
--json Emit machine-readable JSON with --status
|
|
953
1002
|
--skill-dir <path> Override the target Claude root directory (default: ~/.claude)
|
|
954
1003
|
--codex-skill-dir <path> Override the target Codex skills directory (default: ~/.codex/skills)
|
|
955
1004
|
-h, --help Show this help
|
|
@@ -985,15 +1034,173 @@ function buildDetectedSummary() {
|
|
|
985
1034
|
- Not detected: ${absentList}`;
|
|
986
1035
|
}
|
|
987
1036
|
function readPackageVersion() {
|
|
1037
|
+
const packageJsonPaths = [
|
|
1038
|
+
join2(__dirname, "..", "package.json"),
|
|
1039
|
+
join2(__dirname, "..", "..", "package.json")
|
|
1040
|
+
];
|
|
988
1041
|
try {
|
|
989
|
-
const
|
|
990
|
-
|
|
991
|
-
|
|
1042
|
+
for (const packageJsonPath of packageJsonPaths) {
|
|
1043
|
+
if (existsSync2(packageJsonPath)) {
|
|
1044
|
+
const raw = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
1045
|
+
if (isObject(raw) && typeof raw["version"] === "string") {
|
|
1046
|
+
return raw["version"];
|
|
1047
|
+
}
|
|
1048
|
+
}
|
|
992
1049
|
}
|
|
993
1050
|
} catch {
|
|
994
1051
|
}
|
|
995
1052
|
return "0.0.0";
|
|
996
1053
|
}
|
|
1054
|
+
function parseVersion(version) {
|
|
1055
|
+
const match = SEMVER_PATTERN.exec(version);
|
|
1056
|
+
if (match === null) {
|
|
1057
|
+
return null;
|
|
1058
|
+
}
|
|
1059
|
+
const majorText = match[1];
|
|
1060
|
+
const minorText = match[2];
|
|
1061
|
+
const patchText = match[3];
|
|
1062
|
+
if (majorText === void 0 || minorText === void 0 || patchText === void 0) {
|
|
1063
|
+
return null;
|
|
1064
|
+
}
|
|
1065
|
+
const major = Number(majorText);
|
|
1066
|
+
const minor = Number(minorText);
|
|
1067
|
+
const patch = Number(patchText);
|
|
1068
|
+
if (!Number.isInteger(major) || !Number.isInteger(minor) || !Number.isInteger(patch)) {
|
|
1069
|
+
return null;
|
|
1070
|
+
}
|
|
1071
|
+
return { major, minor, patch };
|
|
1072
|
+
}
|
|
1073
|
+
function compareVersions(left, right) {
|
|
1074
|
+
const leftVersion = parseVersion(left);
|
|
1075
|
+
const rightVersion = parseVersion(right);
|
|
1076
|
+
if (leftVersion === null || rightVersion === null) {
|
|
1077
|
+
return null;
|
|
1078
|
+
}
|
|
1079
|
+
const leftParts = [leftVersion.major, leftVersion.minor, leftVersion.patch];
|
|
1080
|
+
const rightParts = [rightVersion.major, rightVersion.minor, rightVersion.patch];
|
|
1081
|
+
for (let index = 0; index < leftParts.length; index++) {
|
|
1082
|
+
const leftPart = leftParts[index];
|
|
1083
|
+
const rightPart = rightParts[index];
|
|
1084
|
+
if (leftPart === void 0 || rightPart === void 0) {
|
|
1085
|
+
return null;
|
|
1086
|
+
}
|
|
1087
|
+
if (leftPart > rightPart) {
|
|
1088
|
+
return 1;
|
|
1089
|
+
}
|
|
1090
|
+
if (leftPart < rightPart) {
|
|
1091
|
+
return -1;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
return 0;
|
|
1095
|
+
}
|
|
1096
|
+
function extractGeneratedVersion(body) {
|
|
1097
|
+
const frontmatterMatch = FRONTMATTER_PATTERN.exec(body);
|
|
1098
|
+
if (frontmatterMatch === null) {
|
|
1099
|
+
return null;
|
|
1100
|
+
}
|
|
1101
|
+
const frontmatter = frontmatterMatch[1];
|
|
1102
|
+
if (frontmatter === void 0) {
|
|
1103
|
+
return null;
|
|
1104
|
+
}
|
|
1105
|
+
const versionMatch = GENERATED_VERSION_PATTERN.exec(frontmatter);
|
|
1106
|
+
if (versionMatch === null) {
|
|
1107
|
+
return null;
|
|
1108
|
+
}
|
|
1109
|
+
return versionMatch[1] ?? null;
|
|
1110
|
+
}
|
|
1111
|
+
function hasAgentInspectorAuthor(body) {
|
|
1112
|
+
const frontmatterMatch = FRONTMATTER_PATTERN.exec(body);
|
|
1113
|
+
if (frontmatterMatch === null) {
|
|
1114
|
+
return false;
|
|
1115
|
+
}
|
|
1116
|
+
const frontmatter = frontmatterMatch[1];
|
|
1117
|
+
if (frontmatter === void 0) {
|
|
1118
|
+
return false;
|
|
1119
|
+
}
|
|
1120
|
+
return /^\s*author:\s*agent-inspector\s*$/m.test(frontmatter);
|
|
1121
|
+
}
|
|
1122
|
+
function readGeneratedVersion(path) {
|
|
1123
|
+
try {
|
|
1124
|
+
return extractGeneratedVersion(readFileSync(path, "utf8"));
|
|
1125
|
+
} catch {
|
|
1126
|
+
return null;
|
|
1127
|
+
}
|
|
1128
|
+
}
|
|
1129
|
+
function isMatchingGeneratedFile(path, currentVersion) {
|
|
1130
|
+
try {
|
|
1131
|
+
const body = readFileSync(path, "utf8");
|
|
1132
|
+
return hasAgentInspectorAuthor(body) && extractGeneratedVersion(body) === currentVersion;
|
|
1133
|
+
} catch {
|
|
1134
|
+
return false;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
function readGeneratedFileStatus(file, currentVersion) {
|
|
1138
|
+
if (!existsSync2(file.path)) {
|
|
1139
|
+
return {
|
|
1140
|
+
label: file.label,
|
|
1141
|
+
path: file.path,
|
|
1142
|
+
state: "missing",
|
|
1143
|
+
version: null,
|
|
1144
|
+
action: actionForStatus(file.label, "missing")
|
|
1145
|
+
};
|
|
1146
|
+
}
|
|
1147
|
+
try {
|
|
1148
|
+
const body = readFileSync(file.path, "utf8");
|
|
1149
|
+
const version = extractGeneratedVersion(body);
|
|
1150
|
+
if (!hasAgentInspectorAuthor(body) || version === null) {
|
|
1151
|
+
return {
|
|
1152
|
+
label: file.label,
|
|
1153
|
+
path: file.path,
|
|
1154
|
+
state: "custom",
|
|
1155
|
+
version,
|
|
1156
|
+
action: actionForStatus(file.label, "custom")
|
|
1157
|
+
};
|
|
1158
|
+
}
|
|
1159
|
+
const comparison = compareVersions(version, currentVersion);
|
|
1160
|
+
if (comparison === null) {
|
|
1161
|
+
return {
|
|
1162
|
+
label: file.label,
|
|
1163
|
+
path: file.path,
|
|
1164
|
+
state: "custom",
|
|
1165
|
+
version,
|
|
1166
|
+
action: actionForStatus(file.label, "custom")
|
|
1167
|
+
};
|
|
1168
|
+
}
|
|
1169
|
+
if (comparison < 0) {
|
|
1170
|
+
return {
|
|
1171
|
+
label: file.label,
|
|
1172
|
+
path: file.path,
|
|
1173
|
+
state: "outdated",
|
|
1174
|
+
version,
|
|
1175
|
+
action: actionForStatus(file.label, "outdated")
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
if (comparison > 0) {
|
|
1179
|
+
return {
|
|
1180
|
+
label: file.label,
|
|
1181
|
+
path: file.path,
|
|
1182
|
+
state: "newer",
|
|
1183
|
+
version,
|
|
1184
|
+
action: actionForStatus(file.label, "newer")
|
|
1185
|
+
};
|
|
1186
|
+
}
|
|
1187
|
+
return {
|
|
1188
|
+
label: file.label,
|
|
1189
|
+
path: file.path,
|
|
1190
|
+
state: "current",
|
|
1191
|
+
version,
|
|
1192
|
+
action: actionForStatus(file.label, "current")
|
|
1193
|
+
};
|
|
1194
|
+
} catch {
|
|
1195
|
+
return {
|
|
1196
|
+
label: file.label,
|
|
1197
|
+
path: file.path,
|
|
1198
|
+
state: "custom",
|
|
1199
|
+
version: null,
|
|
1200
|
+
action: actionForStatus(file.label, "custom")
|
|
1201
|
+
};
|
|
1202
|
+
}
|
|
1203
|
+
}
|
|
997
1204
|
function buildPlannedFiles(flags, targets, version) {
|
|
998
1205
|
const installClaude = !flags.codexOnly;
|
|
999
1206
|
const installCodex = !flags.skipCodexSkill;
|
|
@@ -1003,7 +1210,7 @@ function buildPlannedFiles(flags, targets, version) {
|
|
|
1003
1210
|
port: DEFAULT_PORT,
|
|
1004
1211
|
detectedSummary
|
|
1005
1212
|
}) : "";
|
|
1006
|
-
const commandBody = installClaude ? renderCommandOnboard() : "";
|
|
1213
|
+
const commandBody = installClaude ? renderCommandOnboard({ version }) : "";
|
|
1007
1214
|
const codexSkillBody = installCodex ? renderCodexSkillOnboard({
|
|
1008
1215
|
version,
|
|
1009
1216
|
port: DEFAULT_PORT
|
|
@@ -1029,8 +1236,125 @@ function buildPlannedFiles(flags, targets, version) {
|
|
|
1029
1236
|
}
|
|
1030
1237
|
];
|
|
1031
1238
|
}
|
|
1032
|
-
function shouldWrite(file, force) {
|
|
1033
|
-
|
|
1239
|
+
function shouldWrite(file, force, currentVersion) {
|
|
1240
|
+
if (!file.enabled) {
|
|
1241
|
+
return false;
|
|
1242
|
+
}
|
|
1243
|
+
if (force || !existsSync2(file.path)) {
|
|
1244
|
+
return true;
|
|
1245
|
+
}
|
|
1246
|
+
const existingVersion = readGeneratedVersion(file.path);
|
|
1247
|
+
if (existingVersion === null) {
|
|
1248
|
+
return false;
|
|
1249
|
+
}
|
|
1250
|
+
const comparison = compareVersions(existingVersion, currentVersion);
|
|
1251
|
+
return comparison !== null && comparison < 0;
|
|
1252
|
+
}
|
|
1253
|
+
function shouldUninstall(file, currentVersion) {
|
|
1254
|
+
return file.enabled && existsSync2(file.path) && isMatchingGeneratedFile(file.path, currentVersion);
|
|
1255
|
+
}
|
|
1256
|
+
function removeEmptyDirectory(path) {
|
|
1257
|
+
try {
|
|
1258
|
+
if (readdirSync(path).length === 0) {
|
|
1259
|
+
rmdirSync(path);
|
|
1260
|
+
}
|
|
1261
|
+
} catch {
|
|
1262
|
+
}
|
|
1263
|
+
}
|
|
1264
|
+
function runUninstall(plannedFiles, currentVersion, dryRun) {
|
|
1265
|
+
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1266
|
+
const filesToRemove = enabledFiles.filter((file) => shouldUninstall(file, currentVersion));
|
|
1267
|
+
if (dryRun) {
|
|
1268
|
+
process.stdout.write(`agent-inspector onboard --uninstall --dry-run
|
|
1269
|
+
|
|
1270
|
+
`);
|
|
1271
|
+
for (const file of enabledFiles) {
|
|
1272
|
+
const status = shouldUninstall(file, currentVersion) ? "matching" : "skipped";
|
|
1273
|
+
process.stdout.write(`${file.label}: ${file.path} (${status})
|
|
1274
|
+
`);
|
|
1275
|
+
}
|
|
1276
|
+
process.stdout.write(`
|
|
1277
|
+
No files were removed.
|
|
1278
|
+
`);
|
|
1279
|
+
return 0;
|
|
1280
|
+
}
|
|
1281
|
+
if (filesToRemove.length === 0) {
|
|
1282
|
+
process.stdout.write(
|
|
1283
|
+
"agent-inspector onboard: no generated onboarding files match this package version\n"
|
|
1284
|
+
);
|
|
1285
|
+
return 0;
|
|
1286
|
+
}
|
|
1287
|
+
try {
|
|
1288
|
+
for (const file of filesToRemove) {
|
|
1289
|
+
unlinkSync(file.path);
|
|
1290
|
+
removeEmptyDirectory(dirname(file.path));
|
|
1291
|
+
process.stdout.write(`Removed ${file.label}: ${file.path}
|
|
1292
|
+
`);
|
|
1293
|
+
}
|
|
1294
|
+
} catch (err) {
|
|
1295
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
1296
|
+
process.stderr.write(`agent-inspector onboard: failed to remove files: ${msg}
|
|
1297
|
+
`);
|
|
1298
|
+
return 1;
|
|
1299
|
+
}
|
|
1300
|
+
return 0;
|
|
1301
|
+
}
|
|
1302
|
+
function formatStatusVersion(status) {
|
|
1303
|
+
return status.version ?? "-";
|
|
1304
|
+
}
|
|
1305
|
+
function summarizeStatusAction(statuses) {
|
|
1306
|
+
const actionable = statuses.filter(
|
|
1307
|
+
(status) => status.state === "missing" || status.state === "outdated"
|
|
1308
|
+
);
|
|
1309
|
+
if (actionable.length > 0) {
|
|
1310
|
+
const actions = Array.from(new Set(actionable.map((status) => status.action)));
|
|
1311
|
+
return `Run: ${actions.join(" && ")}`;
|
|
1312
|
+
}
|
|
1313
|
+
if (statuses.some((status) => status.state === "custom")) {
|
|
1314
|
+
return "Custom files are preserved. Use --force only if you want to replace them.";
|
|
1315
|
+
}
|
|
1316
|
+
if (statuses.some((status) => status.state === "newer")) {
|
|
1317
|
+
return "Installed files are newer than this package. No action needed.";
|
|
1318
|
+
}
|
|
1319
|
+
return "All selected onboarding files are current.";
|
|
1320
|
+
}
|
|
1321
|
+
function runStatus(plannedFiles, currentVersion, json) {
|
|
1322
|
+
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1323
|
+
const statuses = enabledFiles.map((file) => readGeneratedFileStatus(file, currentVersion));
|
|
1324
|
+
const summary = summarizeStatusAction(statuses);
|
|
1325
|
+
if (json) {
|
|
1326
|
+
process.stdout.write(
|
|
1327
|
+
`${JSON.stringify(
|
|
1328
|
+
{
|
|
1329
|
+
packageVersion: currentVersion,
|
|
1330
|
+
files: statuses,
|
|
1331
|
+
suggestedAction: summary
|
|
1332
|
+
},
|
|
1333
|
+
null,
|
|
1334
|
+
2
|
|
1335
|
+
)}
|
|
1336
|
+
`
|
|
1337
|
+
);
|
|
1338
|
+
return 0;
|
|
1339
|
+
}
|
|
1340
|
+
process.stdout.write(`agent-inspector onboard status
|
|
1341
|
+
`);
|
|
1342
|
+
process.stdout.write(`Package version: ${currentVersion}
|
|
1343
|
+
|
|
1344
|
+
`);
|
|
1345
|
+
for (const status of statuses) {
|
|
1346
|
+
process.stdout.write(`${status.label}: ${status.state}`);
|
|
1347
|
+
process.stdout.write(`, version ${formatStatusVersion(status)}
|
|
1348
|
+
`);
|
|
1349
|
+
process.stdout.write(` ${status.path}
|
|
1350
|
+
`);
|
|
1351
|
+
process.stdout.write(` Action: ${status.action}
|
|
1352
|
+
`);
|
|
1353
|
+
}
|
|
1354
|
+
process.stdout.write(`
|
|
1355
|
+
Suggested action: ${summary}
|
|
1356
|
+
`);
|
|
1357
|
+
return 0;
|
|
1034
1358
|
}
|
|
1035
1359
|
function runOnboard(argv) {
|
|
1036
1360
|
try {
|
|
@@ -1049,10 +1373,20 @@ function runOnboardSync(argv) {
|
|
|
1049
1373
|
const version = readPackageVersion();
|
|
1050
1374
|
const plannedFiles = buildPlannedFiles(flags, targets, version);
|
|
1051
1375
|
const enabledFiles = plannedFiles.filter((file) => file.enabled);
|
|
1376
|
+
if (flags.json && !flags.status) {
|
|
1377
|
+
process.stderr.write("agent-inspector onboard: --json is only supported with --status\n");
|
|
1378
|
+
return 2;
|
|
1379
|
+
}
|
|
1052
1380
|
if (enabledFiles.length === 0) {
|
|
1053
1381
|
process.stderr.write("agent-inspector onboard: no onboarding target selected\n");
|
|
1054
1382
|
return 2;
|
|
1055
1383
|
}
|
|
1384
|
+
if (flags.status) {
|
|
1385
|
+
return runStatus(plannedFiles, version, flags.json);
|
|
1386
|
+
}
|
|
1387
|
+
if (flags.uninstall) {
|
|
1388
|
+
return runUninstall(plannedFiles, version, flags.dryRun);
|
|
1389
|
+
}
|
|
1056
1390
|
if (flags.dryRun) {
|
|
1057
1391
|
process.stdout.write(`agent-inspector onboard --dry-run
|
|
1058
1392
|
|
|
@@ -1097,9 +1431,11 @@ No files were written.
|
|
|
1097
1431
|
`);
|
|
1098
1432
|
return 0;
|
|
1099
1433
|
}
|
|
1100
|
-
const filesToWrite = plannedFiles.filter((file) => shouldWrite(file, flags.force));
|
|
1434
|
+
const filesToWrite = plannedFiles.filter((file) => shouldWrite(file, flags.force, version));
|
|
1101
1435
|
if (filesToWrite.length === 0) {
|
|
1102
|
-
process.stdout.write(
|
|
1436
|
+
process.stdout.write(
|
|
1437
|
+
"agent-inspector onboard: all selected onboarding files are already up to date\n"
|
|
1438
|
+
);
|
|
1103
1439
|
process.stdout.write("Re-run with --force to refresh.\n");
|
|
1104
1440
|
return 0;
|
|
1105
1441
|
}
|
|
@@ -1117,7 +1453,7 @@ No files were written.
|
|
|
1117
1453
|
const firstTool = detectFirst();
|
|
1118
1454
|
const toolHint = firstTool !== null ? firstTool.displayName : "no known tool detected";
|
|
1119
1455
|
for (const file of filesToWrite) {
|
|
1120
|
-
process.stdout.write(`Installed ${file.label} to: ${file.path}
|
|
1456
|
+
process.stdout.write(`Installed/updated ${file.label} to: ${file.path}
|
|
1121
1457
|
`);
|
|
1122
1458
|
}
|
|
1123
1459
|
process.stdout.write(`
|
|
@@ -1137,7 +1473,7 @@ Next steps:
|
|
|
1137
1473
|
`);
|
|
1138
1474
|
return 0;
|
|
1139
1475
|
}
|
|
1140
|
-
var __filename, __dirname, DEFAULT_PORT, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME;
|
|
1476
|
+
var __filename, __dirname, DEFAULT_PORT, SKILL_DIR_NAME, SKILL_FILE_NAME, COMMAND_FILE_NAME, GENERATED_VERSION_PATTERN, FRONTMATTER_PATTERN, SEMVER_PATTERN;
|
|
1141
1477
|
var init_onboard = __esm({
|
|
1142
1478
|
"src/cli/onboard.ts"() {
|
|
1143
1479
|
"use strict";
|
|
@@ -1151,17 +1487,19 @@ var init_onboard = __esm({
|
|
|
1151
1487
|
SKILL_DIR_NAME = "agent-inspector-onboard";
|
|
1152
1488
|
SKILL_FILE_NAME = "SKILL.md";
|
|
1153
1489
|
COMMAND_FILE_NAME = process.platform === "win32" ? "agent-inspector-onboard.md" : "agent-inspector:onboard.md";
|
|
1490
|
+
GENERATED_VERSION_PATTERN = /^\s*version:\s*([0-9]+\.[0-9]+\.[0-9]+(?:[-+][^\s]+)?)\s*$/m;
|
|
1491
|
+
FRONTMATTER_PATTERN = /^---\r?\n([\s\S]*?)\r?\n---/;
|
|
1492
|
+
SEMVER_PATTERN = /^(\d+)\.(\d+)\.(\d+)(?:[-+].*)?$/;
|
|
1154
1493
|
}
|
|
1155
1494
|
});
|
|
1156
1495
|
|
|
1157
1496
|
// src/proxy/dataDir.ts
|
|
1158
1497
|
import { isAbsolute, join as join3 } from "node:path";
|
|
1159
|
-
function
|
|
1160
|
-
return
|
|
1498
|
+
function defaultBaseDir(env = process.env, platform = process.platform) {
|
|
1499
|
+
return platform === "win32" ? env["USERPROFILE"] ?? env["APPDATA"] ?? "C:\\" : env["HOME"] ?? "/tmp";
|
|
1161
1500
|
}
|
|
1162
|
-
function resolveDataDir(
|
|
1163
|
-
const
|
|
1164
|
-
const base = isWindows ? env["USERPROFILE"] ?? env["APPDATA"] ?? "C:\\" : env["HOME"] ?? "/tmp";
|
|
1501
|
+
function resolveDataDir(_pathExists, env = process.env, platform = process.platform) {
|
|
1502
|
+
const base = defaultBaseDir(env, platform);
|
|
1165
1503
|
const dirEnv = env["AGENT_INSPECTOR_DATA_DIR"];
|
|
1166
1504
|
if (dirEnv !== void 0 && dirEnv !== "") {
|
|
1167
1505
|
return isAbsolute(dirEnv) ? dirEnv : join3(base, dirEnv);
|
|
@@ -1170,16 +1508,13 @@ function resolveDataDir(pathExists, env = process.env, platform = process.platfo
|
|
|
1170
1508
|
if (legacyDirEnv !== void 0 && legacyDirEnv !== "") {
|
|
1171
1509
|
return isAbsolute(legacyDirEnv) ? legacyDirEnv : join3(base, legacyDirEnv);
|
|
1172
1510
|
}
|
|
1173
|
-
|
|
1174
|
-
const legacyDir = join3(base, LEGACY_DATA_DIR_NAME);
|
|
1175
|
-
return !hasDataDirState(pathExists, currentDir) && hasDataDirState(pathExists, legacyDir) ? legacyDir : currentDir;
|
|
1511
|
+
return join3(base, CURRENT_DATA_DIR_NAME);
|
|
1176
1512
|
}
|
|
1177
|
-
var CURRENT_DATA_DIR_NAME
|
|
1513
|
+
var CURRENT_DATA_DIR_NAME;
|
|
1178
1514
|
var init_dataDir = __esm({
|
|
1179
1515
|
"src/proxy/dataDir.ts"() {
|
|
1180
1516
|
"use strict";
|
|
1181
1517
|
CURRENT_DATA_DIR_NAME = ".agent-inspector";
|
|
1182
|
-
LEGACY_DATA_DIR_NAME = ".llm-inspector";
|
|
1183
1518
|
}
|
|
1184
1519
|
});
|
|
1185
1520
|
|
|
@@ -1193,7 +1528,7 @@ __export(doctor_exports, {
|
|
|
1193
1528
|
parseDoctorArgs: () => parseDoctorArgs,
|
|
1194
1529
|
runDoctor: () => runDoctor
|
|
1195
1530
|
});
|
|
1196
|
-
import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync } from "node:fs";
|
|
1531
|
+
import { existsSync as existsSync3, readFileSync as readFileSync2, readdirSync as readdirSync2 } from "node:fs";
|
|
1197
1532
|
import { isAbsolute as isAbsolute2, join as join4, resolve } from "node:path";
|
|
1198
1533
|
import { createConnection } from "node:net";
|
|
1199
1534
|
function check(name, severity, message, hint = "") {
|
|
@@ -1216,6 +1551,7 @@ function parseDoctorArgs(argv, env = process.env) {
|
|
|
1216
1551
|
port: envPort ?? DEFAULT_PORT2,
|
|
1217
1552
|
configDir: null,
|
|
1218
1553
|
providersJson: null,
|
|
1554
|
+
chromeExtension: false,
|
|
1219
1555
|
help: false
|
|
1220
1556
|
};
|
|
1221
1557
|
for (let i = 0; i < argv.length; i++) {
|
|
@@ -1255,6 +1591,9 @@ function parseDoctorArgs(argv, env = process.env) {
|
|
|
1255
1591
|
i++;
|
|
1256
1592
|
break;
|
|
1257
1593
|
}
|
|
1594
|
+
case "--chrome-extension":
|
|
1595
|
+
options.chromeExtension = true;
|
|
1596
|
+
break;
|
|
1258
1597
|
default:
|
|
1259
1598
|
return { kind: "error", message: `doctor: unknown option ${arg}` };
|
|
1260
1599
|
}
|
|
@@ -1496,13 +1835,12 @@ function checkExtensionPackage(rootDir, deps) {
|
|
|
1496
1835
|
}
|
|
1497
1836
|
async function buildDoctorReport(options, deps = createDoctorDeps()) {
|
|
1498
1837
|
const rootDir = findProjectRoot(deps.cwd, deps);
|
|
1499
|
-
const
|
|
1838
|
+
const coreChecks = [
|
|
1500
1839
|
await checkProxyHealth(options.port, deps),
|
|
1501
1840
|
checkProviderConfig(options, deps),
|
|
1502
|
-
checkPackage(rootDir, deps)
|
|
1503
|
-
checkExtensionSource(rootDir, deps),
|
|
1504
|
-
checkExtensionPackage(rootDir, deps)
|
|
1841
|
+
checkPackage(rootDir, deps)
|
|
1505
1842
|
];
|
|
1843
|
+
const checks = options.chromeExtension ? [...coreChecks, checkExtensionSource(rootDir, deps), checkExtensionPackage(rootDir, deps)] : coreChecks;
|
|
1506
1844
|
const passCount = checks.filter((item) => item.severity === "pass").length;
|
|
1507
1845
|
const warnCount = checks.filter((item) => item.severity === "warn").length;
|
|
1508
1846
|
const failCount = checks.filter((item) => item.severity === "fail").length;
|
|
@@ -1534,9 +1872,10 @@ function doctorHelp() {
|
|
|
1534
1872
|
"agent-inspector doctor",
|
|
1535
1873
|
"",
|
|
1536
1874
|
"Usage:",
|
|
1537
|
-
" agent-inspector doctor [--port <port>] [--config-dir <dir>] [--providers <json>]",
|
|
1875
|
+
" agent-inspector doctor [--port <port>] [--config-dir <dir>] [--providers <json>] [--chrome-extension]",
|
|
1538
1876
|
"",
|
|
1539
|
-
"Checks local proxy health, provider config presence, package metadata
|
|
1877
|
+
"Checks local proxy health, provider config presence, and package metadata.",
|
|
1878
|
+
"Pass --chrome-extension to also check Chrome companion source and packaged artifacts.",
|
|
1540
1879
|
""
|
|
1541
1880
|
].join("\n");
|
|
1542
1881
|
}
|
|
@@ -1578,7 +1917,7 @@ function readText(path) {
|
|
|
1578
1917
|
}
|
|
1579
1918
|
function listDir(path) {
|
|
1580
1919
|
try {
|
|
1581
|
-
return
|
|
1920
|
+
return readdirSync2(path);
|
|
1582
1921
|
} catch {
|
|
1583
1922
|
return null;
|
|
1584
1923
|
}
|
package/.output/nitro.json
CHANGED