@tonyclaw/agent-inspector 3.0.43 → 3.0.45
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 +20744 -16945
- package/.output/nitro.json +1 -1
- package/.output/public/assets/{CompareDrawer-BAXxwTwT.js → CompareDrawer-B3_TLTJh.js} +1 -1
- package/.output/public/assets/{InspectorPet-xYuGV4Qz.js → InspectorPet-Cpn6hv4P.js} +1 -1
- package/.output/public/assets/{ProxyViewerContainer-B6GZnUWi.js → ProxyViewerContainer-BEAhuGOJ.js} +27 -27
- package/.output/public/assets/{ReplayDialog-D73pyIg3.js → ReplayDialog-B3EKVdJk.js} +1 -1
- package/.output/public/assets/{RequestAnatomy-CSDta_nu.js → RequestAnatomy-COOQjyUC.js} +1 -1
- package/.output/public/assets/{ResponseView-C4aIUPby.js → ResponseView-DBCjkwye.js} +1 -1
- package/.output/public/assets/{StreamingChunkSequence-D4xxosLx.js → StreamingChunkSequence-CuXhDgMo.js} +1 -1
- package/.output/public/assets/{_sessionId-CZHbJyWO.js → _sessionId-BJlM3nmt.js} +1 -1
- package/.output/public/assets/{_sessionId-DvuNLzSE.js → _sessionId-zbgYl7ZJ.js} +1 -1
- package/.output/public/assets/{index-DZ_wpqQM.js → index-BIK4bPTv.js} +1 -1
- package/.output/public/assets/{index-B17u7JMC.js → index-BZo_8koU.js} +15 -15
- package/.output/public/assets/{index-C0g79BAs.js → index-D2Qw6Ri2.js} +1 -1
- package/.output/public/assets/{index-BWjeqxbk.css → index-ZWschkCh.css} +1 -1
- package/.output/public/assets/{index-CmEO8ykj.js → index-xF_NY8Yb.js} +5 -5
- package/.output/public/assets/{json-viewer-CuWU-H6K.js → json-viewer-B-Ao6pwW.js} +1 -1
- package/.output/public/assets/{jszip.min-DPJI_UKW.js → jszip.min-B_rfAUCe.js} +1 -1
- package/.output/server/_libs/modelcontextprotocol__core.mjs +25 -25
- package/.output/server/_libs/modelcontextprotocol__server.mjs +2 -2
- package/.output/server/_libs/zod.mjs +6 -6
- package/.output/server/{_sessionId-Cun21KZF.mjs → _sessionId-CJ99gZFV.mjs} +3 -1
- package/.output/server/{_sessionId-CoFyeOti.mjs → _sessionId-DEjScBpK.mjs} +5 -3
- package/.output/server/_ssr/{CompareDrawer-Bgc2TZh_.mjs → CompareDrawer-DtOIMeQB.mjs} +4 -2
- package/.output/server/_ssr/{InspectorPet-DyK2ojeh.mjs → InspectorPet-CXc4oCBQ.mjs} +3 -1
- package/.output/server/_ssr/{ProxyViewerContainer-hvn6oVWD.mjs → ProxyViewerContainer-DVPlwfkt.mjs} +52 -27
- package/.output/server/_ssr/{ReplayDialog-KpnrGtZ-.mjs → ReplayDialog-BQEA95qC.mjs} +6 -4
- package/.output/server/_ssr/{RequestAnatomy-uCsfucn8.mjs → RequestAnatomy-BMyd8B7Q.mjs} +4 -2
- package/.output/server/_ssr/{ResponseView-C8UPqoPO.mjs → ResponseView-qrTaEIM8.mjs} +4 -2
- package/.output/server/_ssr/{StreamingChunkSequence-BP28I9sh.mjs → StreamingChunkSequence-BFTL8mIy.mjs} +5 -3
- package/.output/server/_ssr/{index-Du3YNDKx.mjs → index-Bcj1Hcy4.mjs} +4 -2
- package/.output/server/_ssr/{index-BVwVoQlZ.mjs → index-DW-M7XUG.mjs} +3 -1
- package/.output/server/_ssr/index.mjs +4 -3
- package/.output/server/_ssr/{json-viewer-DrE0vtlB.mjs → json-viewer-DiI0Yjsn.mjs} +4 -2
- package/.output/server/_ssr/publicBasePathContext-5264L3rX.mjs +148 -0
- package/.output/server/_ssr/{router-C6nWUZHK.mjs → router-BJ_ltLim.mjs} +2432 -475
- package/.output/server/_ssr/start-C6MjPjxp.mjs +57 -0
- package/.output/server/_tanstack-start-manifest_v-C6pXXX9R.mjs +4 -0
- package/.output/server/index.mjs +99 -99
- package/.output/workers/logFinalizer.worker.js +4 -0
- package/.output/workers/sessionWorkerEntry.js +4 -0
- package/README.md +221 -25
- package/docs/instance-control.openapi.yaml +306 -0
- package/package.json +4 -1
- package/src/cli/alias.ts +440 -0
- package/src/cli/instance.ts +1037 -0
- package/src/cli/instanceArgs.ts +266 -0
- package/src/cli/instanceControl.ts +183 -0
- package/src/cli/instanceModel.ts +275 -0
- package/src/cli/instanceRegistry.ts +740 -0
- package/src/cli/onboard.ts +123 -35
- package/src/cli/onboardTarget.ts +179 -0
- package/src/cli/templates/codex-skill-onboard.ts +76 -28
- package/src/cli/templates/skill-onboard.ts +93 -59
- package/src/cli.ts +154 -16
- package/src/components/ProxyViewer.tsx +13 -5
- package/src/components/providers/SettingsDialog.tsx +13 -8
- package/src/lib/basePath.ts +8 -2
- package/src/lib/codingAgentEndpoints.ts +16 -0
- package/src/lib/instanceContract.ts +220 -0
- package/src/lib/managedInstance.ts +104 -0
- package/src/lib/publicBasePathContext.ts +107 -0
- package/src/mcp/instanceHandlers.ts +149 -0
- package/src/mcp/loopback.ts +16 -5
- package/src/mcp/mode.ts +25 -0
- package/src/mcp/server.ts +258 -18
- package/src/mcp/toolHandlers.ts +2 -2
- package/src/proxy/identityProxy.ts +656 -36
- package/src/proxy/runtimeShutdown.ts +73 -1
- package/src/proxy/sessionInfo.ts +5 -4
- package/src/routes/api/-instances.ts +109 -0
- package/src/routes/api/instances.$name.connection.ts +12 -0
- package/src/routes/api/instances.$name.restart.ts +23 -0
- package/src/routes/api/instances.$name.start.ts +18 -0
- package/src/routes/api/instances.$name.stop.ts +23 -0
- package/src/routes/api/instances.$name.ts +12 -0
- package/src/routes/api/instances.ts +16 -0
- package/src/start.ts +10 -0
- package/.output/server/_ssr/start-HYkvq4Ni.mjs +0 -4
- package/.output/server/_tanstack-start-manifest_v-rshlRaiN.mjs +0 -4
package/src/cli/alias.ts
ADDED
|
@@ -0,0 +1,440 @@
|
|
|
1
|
+
import { normalizeBasePath } from "../lib/basePath";
|
|
2
|
+
|
|
3
|
+
const DEFAULT_ALIAS_HOST = "localhost";
|
|
4
|
+
const DEFAULT_ALIAS_PORT = 9527;
|
|
5
|
+
const ALIAS_CONTROL_PATH = "/.agent-inspector/base-path-aliases";
|
|
6
|
+
const REQUEST_TIMEOUT_MS = 5_000;
|
|
7
|
+
|
|
8
|
+
export type AliasFetch = (input: string, init?: RequestInit) => Promise<Response>;
|
|
9
|
+
|
|
10
|
+
export type AliasIo = {
|
|
11
|
+
stdout: (text: string) => void;
|
|
12
|
+
stderr: (text: string) => void;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
type AliasAction =
|
|
16
|
+
| { kind: "add"; basePath: string }
|
|
17
|
+
| { kind: "list" }
|
|
18
|
+
| { kind: "remove"; basePath: string };
|
|
19
|
+
|
|
20
|
+
type AliasOptions = {
|
|
21
|
+
action: AliasAction;
|
|
22
|
+
host: string;
|
|
23
|
+
port: number;
|
|
24
|
+
json: boolean;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
type AliasParseResult =
|
|
28
|
+
| { kind: "help" }
|
|
29
|
+
| { kind: "ok"; options: AliasOptions }
|
|
30
|
+
| { kind: "error"; message: string };
|
|
31
|
+
|
|
32
|
+
type AliasSnapshot = {
|
|
33
|
+
canonicalBasePath: string;
|
|
34
|
+
aliases: readonly string[];
|
|
35
|
+
runtimeScoped: true;
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
type AliasRequestResult =
|
|
39
|
+
| { kind: "success"; snapshot: AliasSnapshot }
|
|
40
|
+
| { kind: "http-error"; status: number; detail: string | null }
|
|
41
|
+
| { kind: "network-error"; timedOut: boolean }
|
|
42
|
+
| { kind: "invalid-response" };
|
|
43
|
+
|
|
44
|
+
type AliasOutput = {
|
|
45
|
+
action: AliasAction["kind"];
|
|
46
|
+
canonicalBasePath: string;
|
|
47
|
+
canonicalUrl: string;
|
|
48
|
+
aliases: readonly string[];
|
|
49
|
+
aliasUrls: readonly string[];
|
|
50
|
+
runtimeScoped: true;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
const processIo: AliasIo = {
|
|
54
|
+
stdout: (text) => {
|
|
55
|
+
process.stdout.write(text);
|
|
56
|
+
},
|
|
57
|
+
stderr: (text) => {
|
|
58
|
+
process.stderr.write(text);
|
|
59
|
+
},
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
function parsePort(raw: string | undefined): number | null {
|
|
63
|
+
if (raw === undefined || raw.trim() === "") return null;
|
|
64
|
+
const port = Number(raw);
|
|
65
|
+
if (!Number.isInteger(port) || port < 1 || port > 65_535) return null;
|
|
66
|
+
return port;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function normalizeAliasPath(raw: string): string | null {
|
|
70
|
+
const trimmed = raw.trim();
|
|
71
|
+
if (
|
|
72
|
+
!trimmed.startsWith("/") ||
|
|
73
|
+
trimmed.includes("?") ||
|
|
74
|
+
trimmed.includes("#") ||
|
|
75
|
+
trimmed.includes("\\")
|
|
76
|
+
) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
return normalizeBasePath(trimmed);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
function isValidHost(host: string): boolean {
|
|
83
|
+
const trimmed = host.trim();
|
|
84
|
+
return (
|
|
85
|
+
trimmed.length > 0 &&
|
|
86
|
+
!trimmed.includes("://") &&
|
|
87
|
+
!trimmed.includes("/") &&
|
|
88
|
+
!trimmed.includes("?") &&
|
|
89
|
+
!trimmed.includes("#") &&
|
|
90
|
+
!/\s/u.test(trimmed)
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function formatHostForUrl(host: string): string {
|
|
95
|
+
if (host.startsWith("[") && host.endsWith("]")) return host;
|
|
96
|
+
return host.includes(":") ? `[${host}]` : host;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function parseAliasArgs(argv: readonly string[]): AliasParseResult {
|
|
100
|
+
let host = DEFAULT_ALIAS_HOST;
|
|
101
|
+
let port = DEFAULT_ALIAS_PORT;
|
|
102
|
+
let json = false;
|
|
103
|
+
let help = false;
|
|
104
|
+
const positional: string[] = [];
|
|
105
|
+
|
|
106
|
+
for (let index = 0; index < argv.length; index++) {
|
|
107
|
+
const arg = argv[index];
|
|
108
|
+
switch (arg) {
|
|
109
|
+
case undefined:
|
|
110
|
+
continue;
|
|
111
|
+
case "--help":
|
|
112
|
+
case "-h":
|
|
113
|
+
help = true;
|
|
114
|
+
break;
|
|
115
|
+
case "--host": {
|
|
116
|
+
const value = argv[index + 1];
|
|
117
|
+
if (value === undefined || !isValidHost(value)) {
|
|
118
|
+
return {
|
|
119
|
+
kind: "error",
|
|
120
|
+
message: "alias: --host requires a hostname or IP address without a protocol or path",
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
host = value.trim();
|
|
124
|
+
index++;
|
|
125
|
+
break;
|
|
126
|
+
}
|
|
127
|
+
case "--port":
|
|
128
|
+
case "-p": {
|
|
129
|
+
const value = parsePort(argv[index + 1]);
|
|
130
|
+
if (value === null) {
|
|
131
|
+
return {
|
|
132
|
+
kind: "error",
|
|
133
|
+
message: "alias: --port must be an integer from 1 to 65535",
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
port = value;
|
|
137
|
+
index++;
|
|
138
|
+
break;
|
|
139
|
+
}
|
|
140
|
+
case "--json":
|
|
141
|
+
json = true;
|
|
142
|
+
break;
|
|
143
|
+
default:
|
|
144
|
+
if (arg.startsWith("-")) {
|
|
145
|
+
return { kind: "error", message: `alias: unknown option ${arg}` };
|
|
146
|
+
}
|
|
147
|
+
positional.push(arg);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
if (help) return { kind: "help" };
|
|
152
|
+
|
|
153
|
+
const command = positional[0];
|
|
154
|
+
switch (command) {
|
|
155
|
+
case "list":
|
|
156
|
+
if (positional.length !== 1) {
|
|
157
|
+
return { kind: "error", message: "alias: list does not accept a base path" };
|
|
158
|
+
}
|
|
159
|
+
return { kind: "ok", options: { action: { kind: "list" }, host, port, json } };
|
|
160
|
+
case "add":
|
|
161
|
+
case "remove": {
|
|
162
|
+
const rawBasePath = positional[1];
|
|
163
|
+
if (rawBasePath === undefined || positional.length !== 2) {
|
|
164
|
+
return { kind: "error", message: `alias: ${command} requires exactly one base path` };
|
|
165
|
+
}
|
|
166
|
+
const basePath = normalizeAliasPath(rawBasePath);
|
|
167
|
+
if (basePath === null) {
|
|
168
|
+
return {
|
|
169
|
+
kind: "error",
|
|
170
|
+
message: `alias: ${command} base path must be an absolute URL path without a query or hash`,
|
|
171
|
+
};
|
|
172
|
+
}
|
|
173
|
+
const action: AliasAction = { kind: command, basePath };
|
|
174
|
+
return { kind: "ok", options: { action, host, port, json } };
|
|
175
|
+
}
|
|
176
|
+
case undefined:
|
|
177
|
+
return { kind: "error", message: "alias: expected add <path>, list, or remove <path>" };
|
|
178
|
+
default:
|
|
179
|
+
return { kind: "error", message: `alias: unknown command ${command}` };
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function aliasHelp(): string {
|
|
184
|
+
return `agent-inspector alias - mount additional base paths on a running runtime
|
|
185
|
+
|
|
186
|
+
Usage:
|
|
187
|
+
agent-inspector alias add <path> [--host <host>] [--port <port>] [--json]
|
|
188
|
+
agent-inspector alias list [--host <host>] [--port <port>] [--json]
|
|
189
|
+
agent-inspector alias remove <path> [--host <host>] [--port <port>] [--json]
|
|
190
|
+
|
|
191
|
+
Options:
|
|
192
|
+
--host <host> Running instance host (default: localhost)
|
|
193
|
+
--port <port> Running instance port (default: 9527)
|
|
194
|
+
--json Emit machine-readable output
|
|
195
|
+
--help, -h Show this help
|
|
196
|
+
|
|
197
|
+
Aliases are runtime-scoped. This command never starts another Agent Inspector runtime.
|
|
198
|
+
`;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function isObject(value: unknown): value is Record<string, unknown> {
|
|
202
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
function parseAliasSnapshot(value: unknown): AliasSnapshot | null {
|
|
206
|
+
if (!isObject(value)) return null;
|
|
207
|
+
const canonicalBasePath = value["canonicalBasePath"];
|
|
208
|
+
const aliases = value["aliases"];
|
|
209
|
+
const runtimeScoped = value["runtimeScoped"];
|
|
210
|
+
if (
|
|
211
|
+
typeof canonicalBasePath !== "string" ||
|
|
212
|
+
!Array.isArray(aliases) ||
|
|
213
|
+
!aliases.every((alias) => typeof alias === "string") ||
|
|
214
|
+
runtimeScoped !== true
|
|
215
|
+
) {
|
|
216
|
+
return null;
|
|
217
|
+
}
|
|
218
|
+
return {
|
|
219
|
+
canonicalBasePath: normalizeBasePath(canonicalBasePath),
|
|
220
|
+
aliases: aliases.map((alias) => normalizeBasePath(alias)),
|
|
221
|
+
runtimeScoped: true,
|
|
222
|
+
};
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
function readErrorDetail(value: unknown): string | null {
|
|
226
|
+
if (!isObject(value)) return null;
|
|
227
|
+
const error = value["error"];
|
|
228
|
+
if (typeof error === "string" && error.trim() !== "") return error;
|
|
229
|
+
const message = value["message"];
|
|
230
|
+
return typeof message === "string" && message.trim() !== "" ? message : null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async function readJson(response: Response): Promise<unknown | null> {
|
|
234
|
+
try {
|
|
235
|
+
const value: unknown = await response.json();
|
|
236
|
+
return value;
|
|
237
|
+
} catch {
|
|
238
|
+
return null;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async function requestAliases(
|
|
243
|
+
endpoint: string,
|
|
244
|
+
action: AliasAction,
|
|
245
|
+
fetchImpl: AliasFetch,
|
|
246
|
+
): Promise<AliasRequestResult> {
|
|
247
|
+
const controller = new AbortController();
|
|
248
|
+
const timeout = setTimeout(() => {
|
|
249
|
+
controller.abort();
|
|
250
|
+
}, REQUEST_TIMEOUT_MS);
|
|
251
|
+
const method = action.kind === "list" ? "GET" : action.kind === "add" ? "POST" : "DELETE";
|
|
252
|
+
const basePath = action.kind === "list" ? null : action.basePath;
|
|
253
|
+
const init: RequestInit = {
|
|
254
|
+
method,
|
|
255
|
+
headers:
|
|
256
|
+
action.kind === "list"
|
|
257
|
+
? { accept: "application/json" }
|
|
258
|
+
: {
|
|
259
|
+
accept: "application/json",
|
|
260
|
+
"content-type": "application/json",
|
|
261
|
+
"x-agent-inspector-csrf": "1",
|
|
262
|
+
},
|
|
263
|
+
signal: controller.signal,
|
|
264
|
+
};
|
|
265
|
+
if (basePath !== null) init.body = JSON.stringify({ basePath });
|
|
266
|
+
|
|
267
|
+
try {
|
|
268
|
+
const response = await fetchImpl(endpoint, init);
|
|
269
|
+
const value = await readJson(response);
|
|
270
|
+
if (!response.ok) {
|
|
271
|
+
return { kind: "http-error", status: response.status, detail: readErrorDetail(value) };
|
|
272
|
+
}
|
|
273
|
+
const snapshot = parseAliasSnapshot(value);
|
|
274
|
+
return snapshot === null ? { kind: "invalid-response" } : { kind: "success", snapshot };
|
|
275
|
+
} catch (error) {
|
|
276
|
+
const timedOut =
|
|
277
|
+
controller.signal.aborted || (error instanceof Error && error.name === "AbortError");
|
|
278
|
+
return { kind: "network-error", timedOut };
|
|
279
|
+
} finally {
|
|
280
|
+
clearTimeout(timeout);
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
function displayBasePath(basePath: string): string {
|
|
285
|
+
const normalized = normalizeBasePath(basePath);
|
|
286
|
+
return normalized === "" ? "/" : normalized;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
function fullUrl(origin: string, basePath: string): string {
|
|
290
|
+
return `${origin}${normalizeBasePath(basePath)}`;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function buildOutput(origin: string, action: AliasAction, snapshot: AliasSnapshot): AliasOutput {
|
|
294
|
+
return {
|
|
295
|
+
action: action.kind,
|
|
296
|
+
canonicalBasePath: displayBasePath(snapshot.canonicalBasePath),
|
|
297
|
+
canonicalUrl: fullUrl(origin, snapshot.canonicalBasePath),
|
|
298
|
+
aliases: snapshot.aliases.map(displayBasePath),
|
|
299
|
+
aliasUrls: snapshot.aliases.map((alias) => fullUrl(origin, alias)),
|
|
300
|
+
runtimeScoped: true,
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
function formatHumanOutput(output: AliasOutput): string {
|
|
305
|
+
const heading =
|
|
306
|
+
output.action === "add"
|
|
307
|
+
? "Base-path alias added."
|
|
308
|
+
: output.action === "remove"
|
|
309
|
+
? "Base-path alias removed."
|
|
310
|
+
: "Base-path aliases for the running runtime:";
|
|
311
|
+
const aliasPaths = output.aliases.length === 0 ? "(none)" : output.aliases.join(", ");
|
|
312
|
+
const aliasUrls =
|
|
313
|
+
output.aliasUrls.length === 0
|
|
314
|
+
? " (none)"
|
|
315
|
+
: output.aliasUrls.map((url) => ` - ${url}`).join("\n");
|
|
316
|
+
return `${heading}
|
|
317
|
+
Canonical base path: ${output.canonicalBasePath}
|
|
318
|
+
Canonical URL: ${output.canonicalUrl}
|
|
319
|
+
Alias base paths: ${aliasPaths}
|
|
320
|
+
Alias URLs:
|
|
321
|
+
${aliasUrls}
|
|
322
|
+
Scope: current runtime only; no second runtime was started and aliases are not persisted.
|
|
323
|
+
`;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
function writeError(io: AliasIo, json: boolean, code: string, message: string): void {
|
|
327
|
+
if (json) {
|
|
328
|
+
io.stderr(`${JSON.stringify({ error: code, message, runtimeStarted: false })}\n`);
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
io.stderr(`agent-inspector alias: ${message}\n`);
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function oldRuntimeMessage(origin: string): string {
|
|
335
|
+
return `the runtime at ${origin} does not support base-path aliases. Upgrade Agent Inspector and restart that instance, then retry; this command did not start a runtime.`;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
async function handleHttpError(
|
|
339
|
+
options: AliasOptions,
|
|
340
|
+
endpoint: string,
|
|
341
|
+
origin: string,
|
|
342
|
+
result: Extract<AliasRequestResult, { kind: "http-error" }>,
|
|
343
|
+
fetchImpl: AliasFetch,
|
|
344
|
+
io: AliasIo,
|
|
345
|
+
): Promise<number> {
|
|
346
|
+
if (result.status === 404 && options.action.kind === "remove") {
|
|
347
|
+
const probe = await requestAliases(endpoint, { kind: "list" }, fetchImpl);
|
|
348
|
+
if (probe.kind === "success") {
|
|
349
|
+
writeError(
|
|
350
|
+
io,
|
|
351
|
+
options.json,
|
|
352
|
+
"alias_not_found",
|
|
353
|
+
`base path ${displayBasePath(options.action.basePath)} is not mounted. Run "agent-inspector alias list --host ${options.host} --port ${options.port}" to inspect the current runtime.`,
|
|
354
|
+
);
|
|
355
|
+
return 1;
|
|
356
|
+
}
|
|
357
|
+
if (probe.kind === "network-error") {
|
|
358
|
+
writeError(
|
|
359
|
+
io,
|
|
360
|
+
options.json,
|
|
361
|
+
probe.timedOut ? "request_timeout" : "runtime_unreachable",
|
|
362
|
+
`${probe.timedOut ? "timed out contacting" : "cannot reach"} ${origin}. Confirm the existing runtime is running and the --host/--port values are correct; no runtime was started.`,
|
|
363
|
+
);
|
|
364
|
+
return 1;
|
|
365
|
+
}
|
|
366
|
+
if (probe.kind === "http-error" && (probe.status === 404 || probe.status === 405)) {
|
|
367
|
+
writeError(io, options.json, "unsupported_runtime", oldRuntimeMessage(origin));
|
|
368
|
+
return 1;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
if (result.status === 404 || result.status === 405) {
|
|
373
|
+
writeError(io, options.json, "unsupported_runtime", oldRuntimeMessage(origin));
|
|
374
|
+
return 1;
|
|
375
|
+
}
|
|
376
|
+
if (result.status === 409) {
|
|
377
|
+
writeError(
|
|
378
|
+
io,
|
|
379
|
+
options.json,
|
|
380
|
+
"alias_conflict",
|
|
381
|
+
`${result.detail ?? "the base path is already mounted or conflicts with another mount"}. Run "agent-inspector alias list --host ${options.host} --port ${options.port}" to inspect the current runtime.`,
|
|
382
|
+
);
|
|
383
|
+
return 1;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
const detail = result.detail === null ? "the runtime rejected the request" : result.detail;
|
|
387
|
+
writeError(
|
|
388
|
+
io,
|
|
389
|
+
options.json,
|
|
390
|
+
"runtime_rejected_request",
|
|
391
|
+
`${detail} (HTTP ${result.status}). Check the running instance and retry; no runtime was started.`,
|
|
392
|
+
);
|
|
393
|
+
return 1;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
export async function runAlias(
|
|
397
|
+
argv: readonly string[],
|
|
398
|
+
fetchImpl: AliasFetch = fetch,
|
|
399
|
+
io: AliasIo = processIo,
|
|
400
|
+
): Promise<number> {
|
|
401
|
+
const parsed = parseAliasArgs(argv);
|
|
402
|
+
if (parsed.kind === "help") {
|
|
403
|
+
io.stdout(aliasHelp());
|
|
404
|
+
return 0;
|
|
405
|
+
}
|
|
406
|
+
if (parsed.kind === "error") {
|
|
407
|
+
io.stderr(`${parsed.message}\n\n${aliasHelp()}`);
|
|
408
|
+
return 2;
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
const { options } = parsed;
|
|
412
|
+
const origin = `http://${formatHostForUrl(options.host)}:${options.port}`;
|
|
413
|
+
const endpoint = `${origin}${ALIAS_CONTROL_PATH}`;
|
|
414
|
+
const result = await requestAliases(endpoint, options.action, fetchImpl);
|
|
415
|
+
switch (result.kind) {
|
|
416
|
+
case "success": {
|
|
417
|
+
const output = buildOutput(origin, options.action, result.snapshot);
|
|
418
|
+
io.stdout(options.json ? `${JSON.stringify(output, null, 2)}\n` : formatHumanOutput(output));
|
|
419
|
+
return 0;
|
|
420
|
+
}
|
|
421
|
+
case "network-error":
|
|
422
|
+
writeError(
|
|
423
|
+
io,
|
|
424
|
+
options.json,
|
|
425
|
+
result.timedOut ? "request_timeout" : "runtime_unreachable",
|
|
426
|
+
`${result.timedOut ? "timed out contacting" : "cannot reach"} ${origin}. Confirm the existing runtime is running and the --host/--port values are correct; no runtime was started.`,
|
|
427
|
+
);
|
|
428
|
+
return 1;
|
|
429
|
+
case "invalid-response":
|
|
430
|
+
writeError(
|
|
431
|
+
io,
|
|
432
|
+
options.json,
|
|
433
|
+
"invalid_runtime_response",
|
|
434
|
+
`the runtime at ${origin} returned an invalid alias response. Upgrade and restart that instance, then retry; no runtime was started.`,
|
|
435
|
+
);
|
|
436
|
+
return 1;
|
|
437
|
+
case "http-error":
|
|
438
|
+
return handleHttpError(options, endpoint, origin, result, fetchImpl, io);
|
|
439
|
+
}
|
|
440
|
+
}
|