@interf/compiler 0.33.0 → 0.50.0
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/README.md +122 -226
- package/dist/cli/commands/agents.js +1 -32
- package/dist/cli/commands/benchmark.d.ts +2 -3
- package/dist/cli/commands/benchmark.js +1 -31
- package/dist/cli/commands/build-plan.js +26 -50
- package/dist/cli/commands/build.d.ts +2 -3
- package/dist/cli/commands/build.js +1 -31
- package/dist/cli/commands/graphs.js +177 -32
- package/dist/cli/commands/mcp.d.ts +1 -0
- package/dist/cli/commands/mcp.js +223 -126
- package/dist/cli/commands/project.js +10 -36
- package/dist/cli/commands/reset.d.ts +2 -3
- package/dist/cli/commands/reset.js +1 -22
- package/dist/cli/commands/runs.js +86 -33
- package/dist/cli/commands/status.js +3 -24
- package/dist/cli/commands/traces.js +1 -29
- package/dist/cli/commands/wizard.js +17 -29
- package/dist/cli/lib/http-client.d.ts +39 -0
- package/dist/cli/lib/http-client.js +73 -0
- package/dist/packages/build-plans/authoring/brief.d.ts +25 -4
- package/dist/packages/build-plans/authoring/build-plan-authoring.d.ts +42 -1
- package/dist/packages/build-plans/authoring/build-plan-authoring.js +470 -63
- package/dist/packages/build-plans/authoring/build-plan-edit-session.d.ts +9 -0
- package/dist/packages/build-plans/authoring/build-plan-edit-session.js +27 -10
- package/dist/packages/build-plans/authoring/build-plan-improvement.js +62 -8
- package/dist/packages/build-plans/authoring/lib/build-plan-edit-utils.d.ts +1 -0
- package/dist/packages/build-plans/package/build-plan-definitions.d.ts +0 -1
- package/dist/packages/build-plans/package/build-plan-definitions.js +5 -3
- package/dist/packages/build-plans/package/build-plan-stage-runner.d.ts +1 -0
- package/dist/packages/build-plans/package/build-plan-stage-runner.js +2 -1
- package/dist/packages/build-plans/package/builtin-build-plan.d.ts +2 -2
- package/dist/packages/build-plans/package/builtin-build-plan.js +3 -3
- package/dist/packages/build-plans/package/context-interface.d.ts +3 -0
- package/dist/packages/build-plans/package/context-interface.js +5 -5
- package/dist/packages/build-plans/package/interf-build-plan-package.js +22 -22
- package/dist/packages/build-plans/package/local-build-plans.d.ts +10 -5
- package/dist/packages/build-plans/package/local-build-plans.js +57 -32
- package/dist/packages/contracts/index.d.ts +4 -3
- package/dist/packages/contracts/index.js +2 -1
- package/dist/packages/contracts/lib/context-graph-layer.d.ts +161 -0
- package/dist/packages/contracts/lib/context-graph-layer.js +216 -0
- package/dist/packages/contracts/lib/project-paths.d.ts +7 -0
- package/dist/packages/contracts/lib/project-paths.js +9 -0
- package/dist/packages/contracts/lib/project-schema.d.ts +264 -1
- package/dist/packages/contracts/lib/project-schema.js +38 -13
- package/dist/packages/contracts/lib/schema.d.ts +556 -23
- package/dist/packages/contracts/lib/schema.js +279 -18
- package/dist/packages/contracts/utils/filesystem.d.ts +1 -0
- package/dist/packages/contracts/utils/filesystem.js +29 -1
- package/dist/packages/projects/lib/schema.d.ts +6 -8
- package/dist/packages/projects/lib/schema.js +3 -1
- package/dist/packages/projects/source-config.d.ts +0 -5
- package/dist/packages/projects/source-config.js +9 -22
- package/dist/packages/runtime/actions/fields.d.ts +4 -0
- package/dist/packages/runtime/actions/form-builders.js +79 -31
- package/dist/packages/runtime/actions/form-validators.js +9 -3
- package/dist/packages/runtime/actions/helpers.js +3 -3
- package/dist/packages/runtime/actions/registry.d.ts +1 -1
- package/dist/packages/runtime/actions/registry.js +1 -1
- package/dist/packages/runtime/actions/requests.d.ts +1 -1
- package/dist/packages/runtime/actions/requests.js +12 -6
- package/dist/packages/runtime/actions/schemas.d.ts +7 -0
- package/dist/packages/runtime/actions/schemas.js +1 -0
- package/dist/packages/runtime/agent-handoff.js +8 -7
- package/dist/packages/runtime/agents/lib/execution-profile.d.ts +14 -0
- package/dist/packages/runtime/agents/lib/execution-profile.js +23 -0
- package/dist/packages/runtime/agents/lib/execution.js +14 -8
- package/dist/packages/runtime/agents/lib/executors.d.ts +1 -0
- package/dist/packages/runtime/agents/lib/executors.js +11 -2
- package/dist/packages/runtime/agents/lib/logs.d.ts +10 -0
- package/dist/packages/runtime/agents/lib/logs.js +32 -8
- package/dist/packages/runtime/agents/lib/preflight.js +4 -1
- package/dist/packages/runtime/agents/lib/render.d.ts +18 -0
- package/dist/packages/runtime/agents/lib/render.js +44 -18
- package/dist/packages/runtime/agents/lib/shell-templates.js +105 -63
- package/dist/packages/runtime/agents/lib/shells.d.ts +29 -0
- package/dist/packages/runtime/agents/lib/shells.js +158 -32
- package/dist/packages/runtime/agents/lib/source-context-scan.d.ts +10 -0
- package/dist/packages/runtime/agents/lib/source-context-scan.js +388 -0
- package/dist/packages/runtime/agents/lib/status.js +1 -14
- package/dist/packages/runtime/agents/lib/string-utils.d.ts +16 -0
- package/dist/packages/runtime/agents/lib/string-utils.js +36 -0
- package/dist/packages/runtime/agents/lib/types.d.ts +1 -0
- package/dist/packages/runtime/agents/providers/codex.js +2 -0
- package/dist/packages/runtime/agents/role-executors.js +2 -1
- package/dist/packages/runtime/auth/session-store.js +11 -3
- package/dist/packages/runtime/benchmark-question-draft.d.ts +3 -0
- package/dist/packages/runtime/benchmark-question-draft.js +57 -28
- package/dist/packages/runtime/build/artifact-status.d.ts +1 -1
- package/dist/packages/runtime/build/artifact-status.js +1 -1
- package/dist/packages/runtime/build/build-evidence.d.ts +2 -1
- package/dist/packages/runtime/build/build-evidence.js +11 -5
- package/dist/packages/runtime/build/build-pipeline.js +89 -5
- package/dist/packages/runtime/build/build-stage-plan.js +3 -1
- package/dist/packages/runtime/build/build-stage-runner.js +169 -32
- package/dist/packages/runtime/build/build-target.d.ts +3 -0
- package/dist/packages/runtime/build/build-target.js +25 -1
- package/dist/packages/runtime/build/check-evaluator.d.ts +1 -1
- package/dist/packages/runtime/build/check-evaluator.js +655 -4
- package/dist/packages/runtime/build/context-graph-paths.d.ts +13 -0
- package/dist/packages/runtime/build/context-graph-paths.js +27 -0
- package/dist/packages/runtime/build/index.d.ts +2 -2
- package/dist/packages/runtime/build/index.js +2 -2
- package/dist/packages/runtime/build/inspect-map.d.ts +10 -0
- package/dist/packages/runtime/build/inspect-map.js +270 -0
- package/dist/packages/runtime/build/lib/schema.d.ts +246 -53
- package/dist/packages/runtime/build/lib/schema.js +173 -15
- package/dist/packages/runtime/build/native-entrypoint.d.ts +2 -0
- package/dist/packages/runtime/build/native-entrypoint.js +286 -0
- package/dist/packages/runtime/build/runtime-contracts.js +9 -3
- package/dist/packages/runtime/build/runtime-log-paths.d.ts +3 -0
- package/dist/packages/runtime/build/runtime-log-paths.js +16 -0
- package/dist/packages/runtime/build/runtime-prompt.js +6 -4
- package/dist/packages/runtime/build/runtime-runs.js +63 -10
- package/dist/packages/runtime/build/runtime-types.d.ts +4 -1
- package/dist/packages/runtime/build/runtime.d.ts +3 -1
- package/dist/packages/runtime/build/runtime.js +3 -1
- package/dist/packages/runtime/build/source-files.js +11 -2
- package/dist/packages/runtime/build/source-inventory.d.ts +1 -0
- package/dist/packages/runtime/build/source-inventory.js +246 -7
- package/dist/packages/runtime/build/source-manifest.d.ts +11 -0
- package/dist/packages/runtime/build/source-manifest.js +30 -2
- package/dist/packages/runtime/build/stage-evidence.js +80 -11
- package/dist/packages/runtime/build/stage-manifest.d.ts +45 -0
- package/dist/packages/runtime/build/stage-manifest.js +1125 -0
- package/dist/packages/runtime/build/stage-reuse.js +12 -0
- package/dist/packages/runtime/build/stage-session.d.ts +81 -0
- package/dist/packages/runtime/build/stage-session.js +308 -0
- package/dist/packages/runtime/build/state-io.js +10 -11
- package/dist/packages/runtime/build/state-view.js +1 -1
- package/dist/packages/runtime/build/state.d.ts +1 -1
- package/dist/packages/runtime/build/state.js +1 -1
- package/dist/packages/runtime/build/summary-coverage-index.d.ts +21 -0
- package/dist/packages/runtime/build/summary-coverage-index.js +189 -0
- package/dist/packages/runtime/build/traces.js +3 -3
- package/dist/packages/runtime/build/validate-context-graph.d.ts +1 -1
- package/dist/packages/runtime/build/validate-context-graph.js +5 -5
- package/dist/packages/runtime/build/validate.d.ts +1 -1
- package/dist/packages/runtime/build/validate.js +1 -1
- package/dist/packages/runtime/client.d.ts +3 -3
- package/dist/packages/runtime/client.js +8 -13
- package/dist/packages/runtime/context-checks.js +13 -0
- package/dist/packages/runtime/context-graph-scaffold.js +2 -1
- package/dist/packages/runtime/context-graph-semantic-graph.d.ts +9 -0
- package/dist/packages/runtime/context-graph-semantic-graph.js +416 -0
- package/dist/packages/runtime/execution/lib/schema.d.ts +34 -31
- package/dist/packages/runtime/index.d.ts +2 -2
- package/dist/packages/runtime/index.js +1 -1
- package/dist/packages/runtime/native-run-handlers.d.ts +38 -0
- package/dist/packages/runtime/native-run-handlers.js +52 -33
- package/dist/packages/runtime/plan-artifact-contract.js +1 -1
- package/dist/packages/runtime/project-source-state.d.ts +4 -4
- package/dist/packages/runtime/project-source-state.js +5 -2
- package/dist/packages/runtime/project-store.d.ts +5 -0
- package/dist/packages/runtime/project-store.js +30 -3
- package/dist/packages/runtime/requested-artifacts.js +1 -1
- package/dist/packages/runtime/run-observability.js +9 -4
- package/dist/packages/runtime/runtime-action-proposals.js +3 -3
- package/dist/packages/runtime/runtime-build-plans.js +47 -3
- package/dist/packages/runtime/runtime-build-runs.js +9 -16
- package/dist/packages/runtime/runtime-caches.d.ts +26 -0
- package/dist/packages/runtime/runtime-caches.js +47 -0
- package/dist/packages/runtime/runtime-jobs.js +6 -6
- package/dist/packages/runtime/runtime-project-mutations.js +1 -0
- package/dist/packages/runtime/runtime-project-reads.d.ts +4 -1
- package/dist/packages/runtime/runtime-project-reads.js +229 -36
- package/dist/packages/runtime/runtime-proposal-helpers.js +6 -6
- package/dist/packages/runtime/runtime-resource-builders.d.ts +4 -2
- package/dist/packages/runtime/runtime-resource-builders.js +16 -14
- package/dist/packages/runtime/runtime-status.d.ts +14 -0
- package/dist/packages/runtime/runtime-status.js +15 -0
- package/dist/packages/runtime/runtime-verify-runs.js +6 -5
- package/dist/packages/runtime/runtime.d.ts +439 -22
- package/dist/packages/runtime/runtime.js +16 -2
- package/dist/packages/runtime/schemas/actions.d.ts +24 -0
- package/dist/packages/runtime/schemas/agents.d.ts +28 -0
- package/dist/packages/runtime/schemas/agents.js +33 -0
- package/dist/packages/runtime/schemas/build-plans.d.ts +181 -8
- package/dist/packages/runtime/schemas/build-plans.js +36 -2
- package/dist/packages/runtime/schemas/context-graphs.d.ts +1522 -0
- package/dist/packages/runtime/schemas/context-graphs.js +110 -0
- package/dist/packages/runtime/schemas/files.d.ts +7 -347
- package/dist/packages/runtime/schemas/files.js +1 -24
- package/dist/packages/runtime/schemas/index.d.ts +1 -0
- package/dist/packages/runtime/schemas/index.js +1 -0
- package/dist/packages/runtime/schemas/jobs.js +4 -0
- package/dist/packages/runtime/schemas/projects.d.ts +48 -21
- package/dist/packages/runtime/schemas/projects.js +34 -10
- package/dist/packages/runtime/schemas/runs.d.ts +1009 -240
- package/dist/packages/runtime/schemas/runs.js +17 -0
- package/dist/packages/runtime/service/openapi.js +1 -0
- package/dist/packages/runtime/service/operations.d.ts +1666 -145
- package/dist/packages/runtime/service/operations.js +147 -17
- package/dist/packages/runtime/service/routes.d.ts +11 -3
- package/dist/packages/runtime/service/routes.js +11 -3
- package/dist/packages/runtime/service/server-app-boot.js +2 -2
- package/dist/packages/runtime/service/server-helpers.d.ts +11 -0
- package/dist/packages/runtime/service/server-helpers.js +19 -0
- package/dist/packages/runtime/service/server-routes-action-proposals.js +4 -2
- package/dist/packages/runtime/service/server-routes-agents.js +19 -85
- package/dist/packages/runtime/service/server-routes-build-plans.js +14 -11
- package/dist/packages/runtime/service/server-routes-project-context.js +102 -7
- package/dist/packages/runtime/service/server-routes-project-jobs.js +19 -12
- package/dist/packages/runtime/service/server-routes-project-runs.js +5 -2
- package/dist/packages/runtime/service/server-routes-projects.js +6 -2
- package/dist/packages/runtime/service/server-routes-runs.js +11 -4
- package/dist/packages/runtime/verify/lib/schema.js +12 -0
- package/dist/packages/runtime/verify/test-file-guard.d.ts +2 -0
- package/dist/packages/runtime/verify/test-file-guard.js +29 -0
- package/dist/packages/runtime/verify/verify-execution.d.ts +7 -0
- package/dist/packages/runtime/verify/verify-execution.js +109 -35
- package/dist/packages/runtime/verify/verify-paths.d.ts +1 -0
- package/dist/packages/runtime/verify/verify-paths.js +4 -0
- package/dist/packages/runtime/verify/verify-specs.js +49 -39
- package/dist/packages/runtime/wire-schemas.d.ts +1 -1
- package/dist/packages/runtime/wire-schemas.js +1 -1
- package/package.json +2 -8
- package/public-repo/CONTRIBUTING.md +10 -3
- package/public-repo/README.md +122 -226
- package/public-repo/build-plans/interf-default/README.md +15 -12
- package/public-repo/build-plans/interf-default/build/stages/entrypoint/SKILL.md +74 -0
- package/public-repo/build-plans/interf-default/build/stages/knowledge/SKILL.md +95 -0
- package/public-repo/build-plans/interf-default/build/stages/summarize/SKILL.md +38 -5
- package/public-repo/build-plans/interf-default/build-plan.json +27 -23
- package/public-repo/build-plans/interf-default/build-plan.schema.json +24 -20
- package/public-repo/build-plans/interf-default/use/query/SKILL.md +8 -7
- package/public-repo/openapi/local-service.openapi.json +11637 -4213
- package/public-repo/skills/interf/SKILL.md +174 -134
- package/dist/packages/runtime/build/runtime-paths.d.ts +0 -8
- package/dist/packages/runtime/build/runtime-paths.js +0 -26
- package/dist/packages/runtime/build/state-paths.d.ts +0 -7
- package/dist/packages/runtime/build/state-paths.js +0 -22
- package/public-repo/build-plans/interf-default/build/stages/shape/SKILL.md +0 -34
- package/public-repo/build-plans/interf-default/build/stages/structure/SKILL.md +0 -28
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* `interf project` — Project CRUD against a connected instance.
|
|
3
3
|
*
|
|
4
4
|
* interf project ls
|
|
5
|
-
* interf project create <id> --source <path> [--build-plan <id>]
|
|
5
|
+
* interf project create <id> --source <path> --intent "..." [--build-plan <id>]
|
|
6
6
|
* interf project show <id>
|
|
7
7
|
* interf project rm <id>
|
|
8
8
|
* Every subcommand requires an active connection. If `~/.interf/connection.json`
|
|
@@ -11,40 +11,9 @@
|
|
|
11
11
|
*/
|
|
12
12
|
import { resolve } from "node:path";
|
|
13
13
|
import chalk from "chalk";
|
|
14
|
-
import {
|
|
14
|
+
import { callJson, resolveConnection as requireConnection } from "../lib/http-client.js";
|
|
15
15
|
import { projectResourcePath } from "../../packages/runtime/service/routes.js";
|
|
16
16
|
import { ProjectListResponseSchema, ProjectResourceSchema, ProjectWireShapeSchema, } from "../../packages/runtime/schemas/index.js";
|
|
17
|
-
function requireConnection(args) {
|
|
18
|
-
const conn = readActiveConnection({
|
|
19
|
-
urlOverride: args.url,
|
|
20
|
-
authTokenOverride: args.token,
|
|
21
|
-
});
|
|
22
|
-
if (!conn) {
|
|
23
|
-
console.error(CONNECT_OR_ERROR_HINT);
|
|
24
|
-
process.exit(1);
|
|
25
|
-
}
|
|
26
|
-
return { url: conn.url.replace(/\/+$/, ""), token: conn.auth_token };
|
|
27
|
-
}
|
|
28
|
-
async function callJson(url, token, init = {}) {
|
|
29
|
-
const headers = new Headers(init.headers ?? {});
|
|
30
|
-
if (token)
|
|
31
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
32
|
-
if (init.body && !headers.has("content-type")) {
|
|
33
|
-
headers.set("content-type", "application/json");
|
|
34
|
-
}
|
|
35
|
-
const response = await fetch(url, { ...init, headers });
|
|
36
|
-
const raw = await response.text();
|
|
37
|
-
let body = null;
|
|
38
|
-
if (raw.length > 0) {
|
|
39
|
-
try {
|
|
40
|
-
body = JSON.parse(raw);
|
|
41
|
-
}
|
|
42
|
-
catch {
|
|
43
|
-
body = null;
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
return { status: response.status, body, raw };
|
|
47
|
-
}
|
|
48
17
|
function statusColor(status) {
|
|
49
18
|
if (status === "ready")
|
|
50
19
|
return chalk.green;
|
|
@@ -58,6 +27,8 @@ function renderProjectSummary(project) {
|
|
|
58
27
|
console.log();
|
|
59
28
|
console.log(` ${chalk.bold(project.name)}`);
|
|
60
29
|
console.log(chalk.dim(` Build Plan: ${project.build_plan_id ?? "(not selected)"}`));
|
|
30
|
+
if (project.intent)
|
|
31
|
+
console.log(chalk.dim(` agent task: ${project.intent}`));
|
|
61
32
|
if (project.source_path)
|
|
62
33
|
console.log(chalk.dim(` source: ${project.source_path}`));
|
|
63
34
|
const contextGraphPath = project.context_graph_path;
|
|
@@ -70,7 +41,7 @@ function renderProjectSummary(project) {
|
|
|
70
41
|
}
|
|
71
42
|
if (project.artifacts && project.artifacts.length > 0) {
|
|
72
43
|
console.log();
|
|
73
|
-
console.log(chalk.bold("
|
|
44
|
+
console.log(chalk.bold(" Outputs"));
|
|
74
45
|
const idWidth = Math.max(...project.artifacts.map((entry) => entry.artifact_id.length), 8);
|
|
75
46
|
for (const artifact of project.artifacts) {
|
|
76
47
|
const colored = statusColor(artifact.status)(artifact.status);
|
|
@@ -114,7 +85,7 @@ export const projectCommand = {
|
|
|
114
85
|
}
|
|
115
86
|
const projects = parsed.data.projects;
|
|
116
87
|
if (projects.length === 0) {
|
|
117
|
-
console.log(chalk.dim(" No Projects yet. Create one with `interf project create <id> --source <path
|
|
88
|
+
console.log(chalk.dim(" No Projects yet. Create one with `interf project create <id> --source <path> --intent \"<agent task>\"`."));
|
|
118
89
|
return;
|
|
119
90
|
}
|
|
120
91
|
console.log();
|
|
@@ -124,6 +95,7 @@ export const projectCommand = {
|
|
|
124
95
|
const sourceLabel = project.source.locator;
|
|
125
96
|
const buildPlan = project.build_plan_id ?? "(no Build Plan)";
|
|
126
97
|
console.log(` ${project.id}`);
|
|
98
|
+
console.log(chalk.dim(` agent task: ${project.intent}`));
|
|
127
99
|
console.log(chalk.dim(` source: ${sourceLabel}`));
|
|
128
100
|
console.log(chalk.dim(` Build Plan: ${buildPlan}`));
|
|
129
101
|
}
|
|
@@ -131,11 +103,13 @@ export const projectCommand = {
|
|
|
131
103
|
.command("create <project-id>", "Create a Project (Build Plan optional — select or draft it later)", (y) => y
|
|
132
104
|
.positional("project-id", { type: "string", demandOption: true, describe: "Project id (lowercase, dash-separated)" })
|
|
133
105
|
.option("source", { type: "string", demandOption: true, describe: "Path to the Source" })
|
|
106
|
+
.option("intent", { type: "string", demandOption: true, describe: "Agent task this Project's Context Graph should support" })
|
|
134
107
|
.option("build-plan", { type: "string", describe: "Build Plan id. Optional — select later with `interf plan select`." }), async (args) => {
|
|
135
108
|
const { url, token } = requireConnection(args);
|
|
136
109
|
const sourceAbs = resolve(process.cwd(), args.source);
|
|
137
110
|
const requestBody = {
|
|
138
111
|
id: args.projectId,
|
|
112
|
+
intent: args.intent,
|
|
139
113
|
source: { kind: "local-folder", locator: sourceAbs },
|
|
140
114
|
...(args.buildPlan ? { build_plan_id: args.buildPlan } : {}),
|
|
141
115
|
};
|
|
@@ -150,7 +124,7 @@ export const projectCommand = {
|
|
|
150
124
|
if (!args.buildPlan) {
|
|
151
125
|
console.log(chalk.dim(` no Build Plan selected yet — pick or draft one before building:`));
|
|
152
126
|
console.log(chalk.dim(` interf plan select ${args.projectId} <plan-id>`));
|
|
153
|
-
console.log(chalk.dim(` interf plan draft ${args.projectId}
|
|
127
|
+
console.log(chalk.dim(` interf plan draft ${args.projectId}`));
|
|
154
128
|
}
|
|
155
129
|
const parsed = ProjectWireShapeSchema.safeParse(body);
|
|
156
130
|
if (parsed.success && parsed.data.build_plan_id && parsed.data.context_graph.value) {
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import type { CommandModule } from "yargs";
|
|
2
|
-
|
|
2
|
+
import { type ConnectionArgs } from "../lib/http-client.js";
|
|
3
|
+
interface ResetArgs extends ConnectionArgs {
|
|
3
4
|
projectId: string;
|
|
4
5
|
mode?: "build" | "all";
|
|
5
|
-
url?: string;
|
|
6
|
-
token?: string;
|
|
7
6
|
}
|
|
8
7
|
export declare const resetCommand: CommandModule<unknown, ResetArgs>;
|
|
9
8
|
export {};
|
|
@@ -5,28 +5,7 @@
|
|
|
5
5
|
* interf reset bristol --mode all # also clear Build Plan draft runs
|
|
6
6
|
*/
|
|
7
7
|
import chalk from "chalk";
|
|
8
|
-
import {
|
|
9
|
-
function resolveConnection(args) {
|
|
10
|
-
const conn = readActiveConnection({
|
|
11
|
-
urlOverride: args.url,
|
|
12
|
-
authTokenOverride: args.token,
|
|
13
|
-
});
|
|
14
|
-
if (!conn) {
|
|
15
|
-
console.error(CONNECT_OR_ERROR_HINT);
|
|
16
|
-
process.exit(1);
|
|
17
|
-
}
|
|
18
|
-
return { url: conn.url.replace(/\/+$/, ""), token: conn.auth_token };
|
|
19
|
-
}
|
|
20
|
-
async function callJson(url, token, init = {}) {
|
|
21
|
-
const headers = new Headers(init.headers ?? {});
|
|
22
|
-
if (token)
|
|
23
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
24
|
-
if (init.body && !headers.has("content-type"))
|
|
25
|
-
headers.set("content-type", "application/json");
|
|
26
|
-
const response = await fetch(url, { ...init, headers });
|
|
27
|
-
const raw = await response.text();
|
|
28
|
-
return { status: response.status, raw };
|
|
29
|
-
}
|
|
8
|
+
import { callJson, resolveConnection } from "../lib/http-client.js";
|
|
30
9
|
export const resetCommand = {
|
|
31
10
|
command: "reset <project-id>",
|
|
32
11
|
describe: "Reset a Project's built output",
|
|
@@ -3,41 +3,13 @@
|
|
|
3
3
|
*
|
|
4
4
|
* interf runs ls [--project <id>]
|
|
5
5
|
* interf runs status <run-id>
|
|
6
|
+
* interf runs events <run-id>
|
|
7
|
+
* interf runs artifacts <run-id>
|
|
6
8
|
* interf runs cancel <run-id>
|
|
7
9
|
*/
|
|
8
10
|
import chalk from "chalk";
|
|
9
|
-
import {
|
|
10
|
-
import { RunObservabilityListResponseSchema, RunObservabilityResourceSchema, } from "../../packages/runtime/schemas/index.js";
|
|
11
|
-
function resolveConnection(args) {
|
|
12
|
-
const conn = readActiveConnection({
|
|
13
|
-
urlOverride: args.url,
|
|
14
|
-
authTokenOverride: args.token,
|
|
15
|
-
});
|
|
16
|
-
if (!conn) {
|
|
17
|
-
console.error(CONNECT_OR_ERROR_HINT);
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
return { url: conn.url.replace(/\/+$/, ""), token: conn.auth_token };
|
|
21
|
-
}
|
|
22
|
-
async function callJson(url, token, init = {}) {
|
|
23
|
-
const headers = new Headers(init.headers ?? {});
|
|
24
|
-
if (token)
|
|
25
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
26
|
-
if (init.body && !headers.has("content-type"))
|
|
27
|
-
headers.set("content-type", "application/json");
|
|
28
|
-
const response = await fetch(url, { ...init, headers });
|
|
29
|
-
const raw = await response.text();
|
|
30
|
-
let body = null;
|
|
31
|
-
if (raw) {
|
|
32
|
-
try {
|
|
33
|
-
body = JSON.parse(raw);
|
|
34
|
-
}
|
|
35
|
-
catch {
|
|
36
|
-
body = null;
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return { status: response.status, body, raw };
|
|
40
|
-
}
|
|
11
|
+
import { callJson, resolveConnection } from "../lib/http-client.js";
|
|
12
|
+
import { RunArtifactsResponseSchema, RunEventsResponseSchema, RunObservabilityListResponseSchema, RunObservabilityResourceSchema, } from "../../packages/runtime/schemas/index.js";
|
|
41
13
|
function runStatusColor(status) {
|
|
42
14
|
if (status === "succeeded" || status === "completed")
|
|
43
15
|
return chalk.green;
|
|
@@ -90,7 +62,7 @@ function renderRunStatus(run) {
|
|
|
90
62
|
const artifacts = run.artifacts ?? [];
|
|
91
63
|
if (artifacts.length > 0) {
|
|
92
64
|
console.log();
|
|
93
|
-
console.log(chalk.bold("
|
|
65
|
+
console.log(chalk.bold(" Outputs"));
|
|
94
66
|
for (const artifact of artifacts.slice(0, 12)) {
|
|
95
67
|
const stage = artifact.stage_id ? chalk.dim(` ← ${artifact.stage_id}`) : "";
|
|
96
68
|
console.log(` ${artifact.label ?? "output"}: ${chalk.dim(artifact.path)}${stage}`);
|
|
@@ -121,6 +93,35 @@ function renderRunStatus(run) {
|
|
|
121
93
|
console.log(chalk.dim(" Run with --json for the raw run resource."));
|
|
122
94
|
console.log();
|
|
123
95
|
}
|
|
96
|
+
function renderEvents(events) {
|
|
97
|
+
if (events.length === 0) {
|
|
98
|
+
console.log(chalk.dim(" No events recorded for this run."));
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
console.log();
|
|
102
|
+
for (const event of events) {
|
|
103
|
+
// stage_id / path exist only on some event variants; read defensively.
|
|
104
|
+
const stageId = "stage_id" in event ? event.stage_id : undefined;
|
|
105
|
+
const path = "path" in event ? event.path : undefined;
|
|
106
|
+
const detail = [stageId, path].filter(Boolean).join(" · ");
|
|
107
|
+
console.log(` ${chalk.dim(event.timestamp)} ${chalk.bold(event.type)}${detail ? chalk.dim(` ${detail}`) : ""}`);
|
|
108
|
+
}
|
|
109
|
+
console.log();
|
|
110
|
+
console.log(chalk.dim(" Run with --json for full event payloads."));
|
|
111
|
+
console.log();
|
|
112
|
+
}
|
|
113
|
+
function renderArtifacts(artifacts) {
|
|
114
|
+
if (artifacts.length === 0) {
|
|
115
|
+
console.log(chalk.dim(" No artifacts recorded for this run."));
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
console.log();
|
|
119
|
+
for (const artifact of artifacts) {
|
|
120
|
+
const stage = artifact.stage_id ? chalk.dim(` ← ${artifact.stage_id}`) : "";
|
|
121
|
+
console.log(` ${artifact.label ?? artifact.role}: ${chalk.dim(artifact.path)}${stage}`);
|
|
122
|
+
}
|
|
123
|
+
console.log();
|
|
124
|
+
}
|
|
124
125
|
export const runsCommand = {
|
|
125
126
|
command: "runs <subcommand>",
|
|
126
127
|
describe: "Inspect durable Runs on the connected instance",
|
|
@@ -198,6 +199,58 @@ export const runsCommand = {
|
|
|
198
199
|
process.exit(1);
|
|
199
200
|
}
|
|
200
201
|
renderRunStatus(parsed.data);
|
|
202
|
+
})
|
|
203
|
+
.command("events <run-id>", "Read the durable event log for a Build run", (y) => y
|
|
204
|
+
.positional("run-id", { type: "string", demandOption: true, describe: "Run id" })
|
|
205
|
+
.option("json", {
|
|
206
|
+
type: "boolean",
|
|
207
|
+
default: false,
|
|
208
|
+
describe: "Print the raw JSON event array",
|
|
209
|
+
}), async (args) => {
|
|
210
|
+
const { url, token } = resolveConnection(args);
|
|
211
|
+
const { status, body, raw } = await callJson(`${url}/v1/runs/${encodeURIComponent(args.runId)}/events`, token);
|
|
212
|
+
if (status !== 200) {
|
|
213
|
+
console.error(chalk.red(`Failed to read events for ${args.runId} (HTTP ${status}).`));
|
|
214
|
+
if (raw)
|
|
215
|
+
console.error(raw);
|
|
216
|
+
process.exit(1);
|
|
217
|
+
}
|
|
218
|
+
const parsed = RunEventsResponseSchema.safeParse(body);
|
|
219
|
+
if (!parsed.success) {
|
|
220
|
+
console.error(chalk.red(`Failed to parse events for ${args.runId}.`));
|
|
221
|
+
process.exit(1);
|
|
222
|
+
}
|
|
223
|
+
if (args.json) {
|
|
224
|
+
console.log(JSON.stringify(parsed.data.events, null, 2));
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
renderEvents(parsed.data.events);
|
|
228
|
+
})
|
|
229
|
+
.command("artifacts <run-id>", "Read the artifact manifest for a finished Build run", (y) => y
|
|
230
|
+
.positional("run-id", { type: "string", demandOption: true, describe: "Run id" })
|
|
231
|
+
.option("json", {
|
|
232
|
+
type: "boolean",
|
|
233
|
+
default: false,
|
|
234
|
+
describe: "Print the raw JSON artifact array",
|
|
235
|
+
}), async (args) => {
|
|
236
|
+
const { url, token } = resolveConnection(args);
|
|
237
|
+
const { status, body, raw } = await callJson(`${url}/v1/runs/${encodeURIComponent(args.runId)}/artifacts`, token);
|
|
238
|
+
if (status !== 200) {
|
|
239
|
+
console.error(chalk.red(`Failed to read artifacts for ${args.runId} (HTTP ${status}).`));
|
|
240
|
+
if (raw)
|
|
241
|
+
console.error(raw);
|
|
242
|
+
process.exit(1);
|
|
243
|
+
}
|
|
244
|
+
const parsed = RunArtifactsResponseSchema.safeParse(body);
|
|
245
|
+
if (!parsed.success) {
|
|
246
|
+
console.error(chalk.red(`Failed to parse artifacts for ${args.runId}.`));
|
|
247
|
+
process.exit(1);
|
|
248
|
+
}
|
|
249
|
+
if (args.json) {
|
|
250
|
+
console.log(JSON.stringify(parsed.data.artifacts, null, 2));
|
|
251
|
+
return;
|
|
252
|
+
}
|
|
253
|
+
renderArtifacts(parsed.data.artifacts);
|
|
201
254
|
})
|
|
202
255
|
.command("cancel <run-id>", "Cancel a running run", (y) => y.positional("run-id", { type: "string", demandOption: true, describe: "Run id" }), async (args) => {
|
|
203
256
|
const { url, token } = resolveConnection(args);
|
|
@@ -3,29 +3,8 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import chalk from "chalk";
|
|
5
5
|
import { CONNECT_OR_ERROR_HINT, readActiveConnection } from "../../packages/runtime/connection-config.js";
|
|
6
|
+
import { callJsonSafe } from "../lib/http-client.js";
|
|
6
7
|
import { InstanceResourceSchema, ProjectListResponseSchema, } from "../../packages/runtime/schemas/index.js";
|
|
7
|
-
async function callJson(url, token) {
|
|
8
|
-
const headers = new Headers();
|
|
9
|
-
if (token)
|
|
10
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
11
|
-
try {
|
|
12
|
-
const response = await fetch(url, { headers });
|
|
13
|
-
const raw = await response.text();
|
|
14
|
-
let body = null;
|
|
15
|
-
if (raw) {
|
|
16
|
-
try {
|
|
17
|
-
body = JSON.parse(raw);
|
|
18
|
-
}
|
|
19
|
-
catch {
|
|
20
|
-
body = null;
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return { status: response.status, body };
|
|
24
|
-
}
|
|
25
|
-
catch {
|
|
26
|
-
return { status: 0, body: null };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
8
|
export const statusCommand = {
|
|
30
9
|
command: "status",
|
|
31
10
|
describe: "Show connection + Project summary",
|
|
@@ -44,7 +23,7 @@ export const statusCommand = {
|
|
|
44
23
|
}
|
|
45
24
|
const url = conn.url.replace(/\/+$/, "");
|
|
46
25
|
const token = conn.auth_token;
|
|
47
|
-
const instance = await
|
|
26
|
+
const instance = await callJsonSafe(`${url}/v1/instance`, token);
|
|
48
27
|
if (instance.status === 0) {
|
|
49
28
|
console.error(chalk.red(`Connection ${url} is unreachable.`));
|
|
50
29
|
console.error(CONNECT_OR_ERROR_HINT);
|
|
@@ -67,7 +46,7 @@ export const statusCommand = {
|
|
|
67
46
|
console.log(` Uptime: ${instanceResource.data.uptime_seconds}s`);
|
|
68
47
|
}
|
|
69
48
|
console.log(` Auth: ${instanceResource.data.auth_required ? "required (token in connection.json)" : "open (explicit dev/test mode)"}`);
|
|
70
|
-
const projects = await
|
|
49
|
+
const projects = await callJsonSafe(`${url}/v1/projects`, token);
|
|
71
50
|
const parsedProjects = ProjectListResponseSchema.safeParse(projects.body);
|
|
72
51
|
if (!parsedProjects.success) {
|
|
73
52
|
console.error(chalk.red("Connected service returned an invalid Project list."));
|
|
@@ -5,37 +5,9 @@
|
|
|
5
5
|
* interf traces show <trace-kind> --project <id>
|
|
6
6
|
*/
|
|
7
7
|
import chalk from "chalk";
|
|
8
|
-
import {
|
|
8
|
+
import { callJson, resolveConnection } from "../lib/http-client.js";
|
|
9
9
|
import { TracesSchema, } from "../../packages/contracts/lib/project-schema.js";
|
|
10
10
|
import { projectSubresourcePath } from "../../packages/runtime/service/routes.js";
|
|
11
|
-
function resolveConnection(args) {
|
|
12
|
-
const conn = readActiveConnection({
|
|
13
|
-
urlOverride: args.url,
|
|
14
|
-
authTokenOverride: args.token,
|
|
15
|
-
});
|
|
16
|
-
if (!conn) {
|
|
17
|
-
console.error(CONNECT_OR_ERROR_HINT);
|
|
18
|
-
process.exit(1);
|
|
19
|
-
}
|
|
20
|
-
return { url: conn.url.replace(/\/+$/, ""), token: conn.auth_token };
|
|
21
|
-
}
|
|
22
|
-
async function callJson(url, token) {
|
|
23
|
-
const headers = new Headers();
|
|
24
|
-
if (token)
|
|
25
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
26
|
-
const response = await fetch(url, { headers });
|
|
27
|
-
const raw = await response.text();
|
|
28
|
-
let body = null;
|
|
29
|
-
if (raw) {
|
|
30
|
-
try {
|
|
31
|
-
body = JSON.parse(raw);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
body = null;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return { status: response.status, body, raw };
|
|
38
|
-
}
|
|
39
11
|
function tracesUrl(baseUrl, projectId) {
|
|
40
12
|
return `${baseUrl}${projectSubresourcePath(projectId, "traces")}`;
|
|
41
13
|
}
|
|
@@ -17,29 +17,8 @@ import { homedir } from "node:os";
|
|
|
17
17
|
import { basename, resolve } from "node:path";
|
|
18
18
|
import { spawn } from "node:child_process";
|
|
19
19
|
import { ConnectionRecordSchema, readActiveConnection, writeConnection, } from "../../packages/runtime/connection-config.js";
|
|
20
|
+
import { callJsonSafe } from "../lib/http-client.js";
|
|
20
21
|
import { LOCAL_SERVICE_DEFAULT_HOST, LOCAL_SERVICE_DEFAULT_PORT } from "../../packages/runtime/service/routes.js";
|
|
21
|
-
async function callJson(url, token) {
|
|
22
|
-
const headers = new Headers();
|
|
23
|
-
if (token)
|
|
24
|
-
headers.set("authorization", `Bearer ${token}`);
|
|
25
|
-
try {
|
|
26
|
-
const response = await fetch(url, { headers });
|
|
27
|
-
const raw = await response.text();
|
|
28
|
-
let body = null;
|
|
29
|
-
if (raw) {
|
|
30
|
-
try {
|
|
31
|
-
body = JSON.parse(raw);
|
|
32
|
-
}
|
|
33
|
-
catch {
|
|
34
|
-
body = null;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
return { status: response.status, body };
|
|
38
|
-
}
|
|
39
|
-
catch {
|
|
40
|
-
return { status: 0, body: null };
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
22
|
function spawnInterf(args) {
|
|
44
23
|
return new Promise((resolveSpawn) => {
|
|
45
24
|
const child = spawn(process.argv[1] ?? "interf", args, { stdio: "inherit" });
|
|
@@ -233,7 +212,7 @@ async function promptForConnection(reason) {
|
|
|
233
212
|
auth_token: String(tokenValue ?? "").trim() || null,
|
|
234
213
|
});
|
|
235
214
|
const url = record.url.replace(/\/+$/, "");
|
|
236
|
-
const probe = await
|
|
215
|
+
const probe = await callJsonSafe(`${url}/health`, record.auth_token);
|
|
237
216
|
if (probe.status === 0) {
|
|
238
217
|
return promptForConnection(`Connection ${url} is unreachable.`);
|
|
239
218
|
}
|
|
@@ -308,10 +287,17 @@ async function flowCreateProject(conn) {
|
|
|
308
287
|
const sourcePath = await promptSourcePath();
|
|
309
288
|
if (!sourcePath)
|
|
310
289
|
return null;
|
|
290
|
+
const intent = await p.text({
|
|
291
|
+
message: "What should the agent do with this Source?",
|
|
292
|
+
placeholder: "Compare the launch timeline against approval notes and produce a sourced handoff.",
|
|
293
|
+
validate: (value) => String(value).trim().length > 0 ? undefined : "Agent task is required.",
|
|
294
|
+
});
|
|
295
|
+
if (p.isCancel(intent))
|
|
296
|
+
return null;
|
|
311
297
|
// Offer saved Build Plans, but keep selection optional. The agent-first
|
|
312
298
|
// path usually creates the Project from Source first, then drafts a
|
|
313
299
|
// custom Build Plan for review.
|
|
314
|
-
const buildPlansResp = await
|
|
300
|
+
const buildPlansResp = await callJsonSafe(`${conn.url}/v1/build-plans`, conn.token);
|
|
315
301
|
const buildPlans = buildPlansResp.body?.build_plans ?? [];
|
|
316
302
|
const buildPlanOptions = buildPlans
|
|
317
303
|
.map((plan) => ({ value: plan.build_plan_id ?? plan.id ?? "", label: `${plan.build_plan_id ?? plan.id ?? "(?)"}${plan.label ? ` - ${plan.label}` : ""}` }))
|
|
@@ -369,6 +355,8 @@ async function flowCreateProject(conn) {
|
|
|
369
355
|
String(projectId),
|
|
370
356
|
"--source",
|
|
371
357
|
resolve(String(sourcePath)),
|
|
358
|
+
"--intent",
|
|
359
|
+
String(intent),
|
|
372
360
|
...(buildPlanId ? ["--build-plan", buildPlanId] : []),
|
|
373
361
|
]);
|
|
374
362
|
if (exitCode !== 0)
|
|
@@ -376,7 +364,7 @@ async function flowCreateProject(conn) {
|
|
|
376
364
|
return { id: String(projectId), buildPlanId };
|
|
377
365
|
}
|
|
378
366
|
async function pickProject(conn, message) {
|
|
379
|
-
const projects = await
|
|
367
|
+
const projects = await callJsonSafe(`${conn.url}/v1/projects`, conn.token);
|
|
380
368
|
const list = projects.body?.projects ?? [];
|
|
381
369
|
if (list.length === 0) {
|
|
382
370
|
console.log(chalk.dim(" No Projects yet. Create one first."));
|
|
@@ -590,8 +578,8 @@ async function showAgentInstallCards() {
|
|
|
590
578
|
return "rerun";
|
|
591
579
|
}
|
|
592
580
|
async function fetchAgentState(conn) {
|
|
593
|
-
const instance = await
|
|
594
|
-
const agentsResponse = await
|
|
581
|
+
const instance = await callJsonSafe(`${conn.url}/v1/instance`, conn.token);
|
|
582
|
+
const agentsResponse = await callJsonSafe(`${conn.url}/v1/agents`, conn.token);
|
|
595
583
|
if (instance.status !== 200)
|
|
596
584
|
return null;
|
|
597
585
|
// Older engines don't expose /v1/agents. Surface the gap explicitly so
|
|
@@ -632,7 +620,7 @@ async function runWizard(args) {
|
|
|
632
620
|
}
|
|
633
621
|
else {
|
|
634
622
|
const url = initial.url.replace(/\/+$/, "");
|
|
635
|
-
const probe = await
|
|
623
|
+
const probe = await callJsonSafe(`${url}/health`, initial.auth_token);
|
|
636
624
|
if (probe.status === 0) {
|
|
637
625
|
if (!args.url && await probeHealth(DEFAULT_ENGINE_URL)) {
|
|
638
626
|
conn = await connectToReachableEngine(DEFAULT_ENGINE_URL);
|
|
@@ -655,7 +643,7 @@ async function runWizard(args) {
|
|
|
655
643
|
if (!conn) {
|
|
656
644
|
return;
|
|
657
645
|
}
|
|
658
|
-
const instance = await
|
|
646
|
+
const instance = await callJsonSafe(`${conn.url}/v1/instance`, conn.token);
|
|
659
647
|
console.log();
|
|
660
648
|
console.log(chalk.bold(` Connected to ${conn.url}`));
|
|
661
649
|
console.log(chalk.dim(` ${instance.body?.project_count ?? 0} project(s)`));
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Per-call connection overrides parsed from `--url` / `--token` flags. */
|
|
2
|
+
export interface ConnectionArgs {
|
|
3
|
+
url?: string;
|
|
4
|
+
token?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Resolved connection: normalized base URL plus an optional bearer token. */
|
|
7
|
+
export interface ResolvedConnection {
|
|
8
|
+
url: string;
|
|
9
|
+
token: string | null;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Resolve the active connection or exit non-zero with the connect-or-error
|
|
13
|
+
* hint. Mutating CLI commands never auto-start a service, so absence here is a
|
|
14
|
+
* hard error.
|
|
15
|
+
*/
|
|
16
|
+
export declare function resolveConnection(args: ConnectionArgs): ResolvedConnection;
|
|
17
|
+
/** Outcome of a JSON request: HTTP status, parsed body (null on empty/parse-fail), and the raw text. */
|
|
18
|
+
export interface JsonResponse<T> {
|
|
19
|
+
status: number;
|
|
20
|
+
body: T | null;
|
|
21
|
+
raw: string;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Issue a request and parse the response body as JSON.
|
|
25
|
+
*
|
|
26
|
+
* - Attaches the bearer token and a JSON content-type for bodied requests.
|
|
27
|
+
* - Returns `body: null` when the response is empty or not valid JSON; callers
|
|
28
|
+
* inspect `status`/`raw` to handle those cases.
|
|
29
|
+
* - Network/transport errors reject (callers that need reachability probing use
|
|
30
|
+
* {@link callJsonSafe}).
|
|
31
|
+
*/
|
|
32
|
+
export declare function callJson<T = unknown>(url: string, token: string | null, init?: RequestInit): Promise<JsonResponse<T>>;
|
|
33
|
+
/**
|
|
34
|
+
* Reachability-tolerant variant of {@link callJson}. A network/transport error
|
|
35
|
+
* is reported as `status: 0` instead of rejecting, so probe paths (e.g.
|
|
36
|
+
* `interf status`, the wizard) can distinguish "unreachable" from an HTTP
|
|
37
|
+
* error.
|
|
38
|
+
*/
|
|
39
|
+
export declare function callJsonSafe<T = unknown>(url: string, token: string | null, init?: RequestInit): Promise<JsonResponse<T>>;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI-owned HTTP + connection helpers.
|
|
3
|
+
*
|
|
4
|
+
* Every `interf` command is a thin authorized client of one connected
|
|
5
|
+
* instance. The connection-resolution and JSON-fetch logic was previously
|
|
6
|
+
* copy-pasted into every command file; this module is the single definition
|
|
7
|
+
* the commands import.
|
|
8
|
+
*
|
|
9
|
+
* This is deliberately CLI-scoped. The runtime's own `fetchJson`
|
|
10
|
+
* (`runtime/client.ts`) is private and 500ms-timeout-scoped — it is not the
|
|
11
|
+
* reuse target for interactive CLI calls, which must not impose a short
|
|
12
|
+
* timeout on long Build/benchmark requests.
|
|
13
|
+
*/
|
|
14
|
+
import { CONNECT_OR_ERROR_HINT, readActiveConnection, } from "../../packages/runtime/connection-config.js";
|
|
15
|
+
/**
|
|
16
|
+
* Resolve the active connection or exit non-zero with the connect-or-error
|
|
17
|
+
* hint. Mutating CLI commands never auto-start a service, so absence here is a
|
|
18
|
+
* hard error.
|
|
19
|
+
*/
|
|
20
|
+
export function resolveConnection(args) {
|
|
21
|
+
const conn = readActiveConnection({
|
|
22
|
+
urlOverride: args.url,
|
|
23
|
+
authTokenOverride: args.token,
|
|
24
|
+
});
|
|
25
|
+
if (!conn) {
|
|
26
|
+
console.error(CONNECT_OR_ERROR_HINT);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
return { url: conn.url.replace(/\/+$/, ""), token: conn.auth_token };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Issue a request and parse the response body as JSON.
|
|
33
|
+
*
|
|
34
|
+
* - Attaches the bearer token and a JSON content-type for bodied requests.
|
|
35
|
+
* - Returns `body: null` when the response is empty or not valid JSON; callers
|
|
36
|
+
* inspect `status`/`raw` to handle those cases.
|
|
37
|
+
* - Network/transport errors reject (callers that need reachability probing use
|
|
38
|
+
* {@link callJsonSafe}).
|
|
39
|
+
*/
|
|
40
|
+
export async function callJson(url, token, init = {}) {
|
|
41
|
+
const headers = new Headers(init.headers ?? {});
|
|
42
|
+
if (token)
|
|
43
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
44
|
+
if (init.body && !headers.has("content-type")) {
|
|
45
|
+
headers.set("content-type", "application/json");
|
|
46
|
+
}
|
|
47
|
+
const response = await fetch(url, { ...init, headers });
|
|
48
|
+
const raw = await response.text();
|
|
49
|
+
let body = null;
|
|
50
|
+
if (raw.length > 0) {
|
|
51
|
+
try {
|
|
52
|
+
body = JSON.parse(raw);
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
body = null;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return { status: response.status, body, raw };
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Reachability-tolerant variant of {@link callJson}. A network/transport error
|
|
62
|
+
* is reported as `status: 0` instead of rejecting, so probe paths (e.g.
|
|
63
|
+
* `interf status`, the wizard) can distinguish "unreachable" from an HTTP
|
|
64
|
+
* error.
|
|
65
|
+
*/
|
|
66
|
+
export async function callJsonSafe(url, token, init = {}) {
|
|
67
|
+
try {
|
|
68
|
+
return await callJson(url, token, init);
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return { status: 0, body: null, raw: "" };
|
|
72
|
+
}
|
|
73
|
+
}
|