@interf/compiler 0.9.5 → 0.13.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.
Files changed (214) hide show
  1. package/README.md +96 -92
  2. package/TRADEMARKS.md +2 -13
  3. package/agent-skills/interf-actions/SKILL.md +95 -36
  4. package/agent-skills/interf-actions/references/cli.md +118 -51
  5. package/builtin-methods/interf-default/README.md +3 -4
  6. package/builtin-methods/interf-default/compile/stages/shape/SKILL.md +2 -2
  7. package/builtin-methods/interf-default/compile/stages/summarize/SKILL.md +2 -1
  8. package/builtin-methods/interf-default/improve/SKILL.md +1 -1
  9. package/builtin-methods/interf-default/method.json +10 -4
  10. package/builtin-methods/interf-default/method.schema.json +0 -9
  11. package/builtin-methods/interf-default/use/query/SKILL.md +5 -5
  12. package/dist/cli/commands/compile.d.ts +8 -25
  13. package/dist/cli/commands/compile.js +75 -360
  14. package/dist/cli/commands/doctor.js +1 -1
  15. package/dist/cli/commands/login.d.ts +7 -0
  16. package/dist/cli/commands/login.js +39 -0
  17. package/dist/cli/commands/logout.d.ts +2 -0
  18. package/dist/cli/commands/logout.js +16 -0
  19. package/dist/cli/commands/method.d.ts +2 -0
  20. package/dist/cli/commands/method.js +113 -0
  21. package/dist/cli/commands/prep.d.ts +2 -0
  22. package/dist/cli/commands/prep.js +134 -0
  23. package/dist/cli/commands/reset.d.ts +8 -1
  24. package/dist/cli/commands/reset.js +47 -26
  25. package/dist/cli/commands/runs.d.ts +2 -0
  26. package/dist/cli/commands/runs.js +120 -0
  27. package/dist/cli/commands/status.d.ts +6 -1
  28. package/dist/cli/commands/status.js +68 -111
  29. package/dist/cli/commands/test.d.ts +6 -14
  30. package/dist/cli/commands/test.js +65 -181
  31. package/dist/cli/commands/web.d.ts +0 -9
  32. package/dist/cli/commands/web.js +147 -120
  33. package/dist/cli/commands/wizard.d.ts +9 -0
  34. package/dist/cli/commands/wizard.js +442 -0
  35. package/dist/cli/index.d.ts +7 -6
  36. package/dist/cli/index.js +13 -10
  37. package/dist/compiler-ui/404.html +1 -1
  38. package/dist/compiler-ui/__next.__PAGE__.txt +2 -2
  39. package/dist/compiler-ui/__next._full.txt +3 -3
  40. package/dist/compiler-ui/__next._head.txt +1 -1
  41. package/dist/compiler-ui/__next._index.txt +2 -2
  42. package/dist/compiler-ui/__next._tree.txt +2 -2
  43. package/dist/compiler-ui/_next/static/chunks/{18a8f2jkv3z.c.css → 045gole2ojo3g.css} +1 -1
  44. package/dist/compiler-ui/_next/static/chunks/{177mvn4rse235.js → 17t-lulmyawg5.js} +9 -9
  45. package/dist/compiler-ui/_not-found/__next._full.txt +2 -2
  46. package/dist/compiler-ui/_not-found/__next._head.txt +1 -1
  47. package/dist/compiler-ui/_not-found/__next._index.txt +2 -2
  48. package/dist/compiler-ui/_not-found/__next._not-found.__PAGE__.txt +1 -1
  49. package/dist/compiler-ui/_not-found/__next._not-found.txt +1 -1
  50. package/dist/compiler-ui/_not-found/__next._tree.txt +2 -2
  51. package/dist/compiler-ui/_not-found.html +1 -1
  52. package/dist/compiler-ui/_not-found.txt +2 -2
  53. package/dist/compiler-ui/index.html +1 -1
  54. package/dist/compiler-ui/index.txt +3 -3
  55. package/dist/packages/agents/lib/shells.d.ts +1 -1
  56. package/dist/packages/agents/lib/shells.js +111 -52
  57. package/dist/packages/agents/lib/user-config.d.ts +4 -2
  58. package/dist/packages/agents/lib/user-config.js +15 -7
  59. package/dist/packages/compiler/compiled-paths.d.ts +9 -2
  60. package/dist/packages/compiler/compiled-paths.js +30 -15
  61. package/dist/packages/compiler/compiled-pipeline.js +23 -3
  62. package/dist/packages/compiler/compiled-stage-plan.js +4 -0
  63. package/dist/packages/compiler/compiled-target.d.ts +1 -1
  64. package/dist/packages/compiler/compiled-target.js +1 -1
  65. package/dist/packages/compiler/index.d.ts +1 -0
  66. package/dist/packages/compiler/index.js +1 -0
  67. package/dist/packages/compiler/lib/schema.d.ts +26 -31
  68. package/dist/packages/compiler/lib/schema.js +1 -12
  69. package/dist/packages/compiler/method-runs.d.ts +2 -3
  70. package/dist/packages/compiler/method-runs.js +2 -3
  71. package/dist/packages/compiler/reset.js +3 -1
  72. package/dist/packages/compiler/runtime-contracts.js +0 -3
  73. package/dist/packages/compiler/runtime-prompt.js +1 -1
  74. package/dist/packages/compiler/source-files.d.ts +46 -0
  75. package/dist/packages/compiler/source-files.js +149 -0
  76. package/dist/packages/compiler/state-artifacts.d.ts +3 -2
  77. package/dist/packages/compiler/state-artifacts.js +4 -3
  78. package/dist/packages/compiler/state-io.d.ts +3 -2
  79. package/dist/packages/compiler/state-io.js +11 -5
  80. package/dist/packages/compiler/state-paths.d.ts +2 -1
  81. package/dist/packages/compiler/state-paths.js +6 -3
  82. package/dist/packages/compiler/state-view.d.ts +3 -2
  83. package/dist/packages/compiler/state-view.js +18 -28
  84. package/dist/packages/compiler/state.d.ts +4 -4
  85. package/dist/packages/compiler/state.js +3 -3
  86. package/dist/packages/contracts/index.d.ts +1 -1
  87. package/dist/packages/contracts/lib/preparation-paths.d.ts +117 -0
  88. package/dist/packages/contracts/lib/preparation-paths.js +177 -0
  89. package/dist/packages/contracts/lib/schema.d.ts +85 -5
  90. package/dist/packages/contracts/lib/schema.js +46 -1
  91. package/dist/packages/execution/lib/schema.d.ts +50 -50
  92. package/dist/packages/execution/lib/schema.js +1 -1
  93. package/dist/packages/local-service/action-definitions.d.ts +14 -14
  94. package/dist/packages/local-service/action-definitions.js +27 -28
  95. package/dist/packages/local-service/action-planner.js +2 -1
  96. package/dist/packages/local-service/client.d.ts +51 -52
  97. package/dist/packages/local-service/client.js +132 -140
  98. package/dist/packages/local-service/connection-config.d.ts +38 -0
  99. package/dist/packages/local-service/connection-config.js +75 -0
  100. package/dist/packages/local-service/index.d.ts +11 -7
  101. package/dist/packages/local-service/index.js +6 -4
  102. package/dist/packages/local-service/instance-paths.d.ts +100 -0
  103. package/dist/packages/local-service/instance-paths.js +165 -0
  104. package/dist/packages/local-service/lib/schema.d.ts +405 -2297
  105. package/dist/packages/local-service/lib/schema.js +146 -62
  106. package/dist/packages/local-service/native-run-handlers.js +3 -3
  107. package/dist/packages/local-service/preparation-store.d.ts +92 -0
  108. package/dist/packages/local-service/preparation-store.js +171 -0
  109. package/dist/packages/local-service/routes.d.ts +33 -16
  110. package/dist/packages/local-service/routes.js +44 -20
  111. package/dist/packages/local-service/run-observability.js +11 -11
  112. package/dist/packages/local-service/runtime-caches.d.ts +76 -0
  113. package/dist/packages/local-service/runtime-caches.js +191 -0
  114. package/dist/packages/local-service/runtime-event-applier.d.ts +12 -0
  115. package/dist/packages/local-service/runtime-event-applier.js +177 -0
  116. package/dist/packages/local-service/runtime-persistence.d.ts +47 -0
  117. package/dist/packages/local-service/runtime-persistence.js +137 -0
  118. package/dist/packages/local-service/runtime-proposal-helpers.d.ts +35 -0
  119. package/dist/packages/local-service/runtime-proposal-helpers.js +251 -0
  120. package/dist/packages/local-service/runtime-resource-builders.d.ts +52 -0
  121. package/dist/packages/local-service/runtime-resource-builders.js +149 -0
  122. package/dist/packages/local-service/runtime.d.ts +197 -43
  123. package/dist/packages/local-service/runtime.js +800 -974
  124. package/dist/packages/local-service/server.d.ts +15 -0
  125. package/dist/packages/local-service/server.js +641 -273
  126. package/dist/packages/local-service/service-registry.d.ts +47 -0
  127. package/dist/packages/local-service/service-registry.js +137 -0
  128. package/dist/packages/method-authoring/method-authoring.d.ts +1 -1
  129. package/dist/packages/method-authoring/method-authoring.js +2 -2
  130. package/dist/packages/method-authoring/method-improvement.js +1 -1
  131. package/dist/packages/method-package/builtin-compiled-method.d.ts +4 -5
  132. package/dist/packages/method-package/builtin-compiled-method.js +8 -14
  133. package/dist/packages/method-package/context-interface.d.ts +4 -40
  134. package/dist/packages/method-package/context-interface.js +1 -23
  135. package/dist/packages/method-package/interf-method-package.d.ts +4 -4
  136. package/dist/packages/method-package/interf-method-package.js +21 -33
  137. package/dist/packages/method-package/local-methods.d.ts +10 -6
  138. package/dist/packages/method-package/local-methods.js +57 -39
  139. package/dist/packages/method-package/method-definitions.d.ts +8 -34
  140. package/dist/packages/method-package/method-definitions.js +49 -37
  141. package/dist/packages/method-package/method-helpers.d.ts +1 -13
  142. package/dist/packages/method-package/method-helpers.js +8 -42
  143. package/dist/packages/method-package/method-stage-runner.js +2 -2
  144. package/dist/packages/method-package/user-methods.d.ts +17 -0
  145. package/dist/packages/method-package/user-methods.js +77 -0
  146. package/dist/packages/project-model/index.d.ts +0 -1
  147. package/dist/packages/project-model/index.js +0 -1
  148. package/dist/packages/project-model/interf-detect.d.ts +8 -3
  149. package/dist/packages/project-model/interf-detect.js +34 -34
  150. package/dist/packages/project-model/interf-scaffold.d.ts +3 -3
  151. package/dist/packages/project-model/interf-scaffold.js +23 -32
  152. package/dist/packages/project-model/lib/schema.js +38 -1
  153. package/dist/packages/project-model/preparation-entries.d.ts +5 -5
  154. package/dist/packages/project-model/preparation-entries.js +14 -14
  155. package/dist/packages/project-model/source-config.d.ts +11 -11
  156. package/dist/packages/project-model/source-config.js +74 -46
  157. package/dist/packages/project-model/source-folders.d.ts +5 -5
  158. package/dist/packages/project-model/source-folders.js +14 -14
  159. package/dist/packages/shared/filesystem.d.ts +7 -0
  160. package/dist/packages/shared/filesystem.js +97 -10
  161. package/dist/packages/testing/lib/schema.d.ts +10 -10
  162. package/dist/packages/testing/lib/schema.js +2 -2
  163. package/dist/packages/testing/readiness-check-run.d.ts +4 -4
  164. package/dist/packages/testing/readiness-check-run.js +36 -36
  165. package/dist/packages/testing/test-execution.js +6 -6
  166. package/dist/packages/testing/test-paths.js +4 -3
  167. package/dist/packages/testing/test-sandbox.d.ts +0 -1
  168. package/dist/packages/testing/test-sandbox.js +14 -30
  169. package/dist/packages/testing/test-targets.d.ts +1 -1
  170. package/dist/packages/testing/test-targets.js +6 -6
  171. package/dist/packages/testing/test.d.ts +1 -1
  172. package/dist/packages/testing/test.js +1 -1
  173. package/package.json +3 -4
  174. package/CHANGELOG.md +0 -93
  175. package/LICENSE +0 -183
  176. package/dist/cli/commands/action-input-cli.d.ts +0 -25
  177. package/dist/cli/commands/action-input-cli.js +0 -73
  178. package/dist/cli/commands/control-path.d.ts +0 -11
  179. package/dist/cli/commands/control-path.js +0 -72
  180. package/dist/cli/commands/create-method-wizard.d.ts +0 -64
  181. package/dist/cli/commands/create-method-wizard.js +0 -434
  182. package/dist/cli/commands/create.d.ts +0 -6
  183. package/dist/cli/commands/create.js +0 -183
  184. package/dist/cli/commands/default.d.ts +0 -2
  185. package/dist/cli/commands/default.js +0 -39
  186. package/dist/cli/commands/executor-flow.d.ts +0 -29
  187. package/dist/cli/commands/executor-flow.js +0 -163
  188. package/dist/cli/commands/init.d.ts +0 -26
  189. package/dist/cli/commands/init.js +0 -771
  190. package/dist/cli/commands/list.d.ts +0 -2
  191. package/dist/cli/commands/list.js +0 -30
  192. package/dist/cli/commands/preparation-action.d.ts +0 -8
  193. package/dist/cli/commands/preparation-action.js +0 -29
  194. package/dist/cli/commands/preparation-picker.d.ts +0 -5
  195. package/dist/cli/commands/preparation-picker.js +0 -36
  196. package/dist/cli/commands/preparation-selection.d.ts +0 -6
  197. package/dist/cli/commands/preparation-selection.js +0 -11
  198. package/dist/cli/commands/service-action-flow.d.ts +0 -9
  199. package/dist/cli/commands/service-action-flow.js +0 -19
  200. package/dist/cli/commands/source-config-wizard.d.ts +0 -51
  201. package/dist/cli/commands/source-config-wizard.js +0 -670
  202. package/dist/cli/commands/verify.d.ts +0 -2
  203. package/dist/cli/commands/verify.js +0 -94
  204. package/dist/packages/compiler/raw-snapshot.d.ts +0 -49
  205. package/dist/packages/compiler/raw-snapshot.js +0 -101
  206. package/dist/packages/method-package/index.d.ts +0 -11
  207. package/dist/packages/method-package/index.js +0 -11
  208. package/dist/packages/method-package/method-stage-policy.d.ts +0 -5
  209. package/dist/packages/method-package/method-stage-policy.js +0 -31
  210. package/dist/packages/project-model/project-paths.d.ts +0 -12
  211. package/dist/packages/project-model/project-paths.js +0 -33
  212. /package/dist/compiler-ui/_next/static/{84FaeF3EzBF9kKTMjSEVN → C6vVfy3aeYuIO3d2AoNvC}/_buildManifest.js +0 -0
  213. /package/dist/compiler-ui/_next/static/{84FaeF3EzBF9kKTMjSEVN → C6vVfy3aeYuIO3d2AoNvC}/_clientMiddlewareManifest.js +0 -0
  214. /package/dist/compiler-ui/_next/static/{84FaeF3EzBF9kKTMjSEVN → C6vVfy3aeYuIO3d2AoNvC}/_ssgManifest.js +0 -0
@@ -1,188 +1,72 @@
1
+ /**
2
+ * `interf test <prep-id>` — start a readiness-check (test) run for a preparation.
3
+ *
4
+ * interf test bristol
5
+ * interf test bristol --target source-files
6
+ * interf test bristol --target portable-context
7
+ * interf test bristol --target both
8
+ */
1
9
  import chalk from "chalk";
2
- import * as p from "@clack/prompts";
3
- import { detectInterf, resolveSourceControlPath, } from "../../packages/project-model/interf.js";
4
- import { loadCompiledPreparationConfig, sourcePreparationConfigFromInterfConfig, } from "../../packages/project-model/source-config.js";
5
- import { choosePreparationConfig, } from "./preparation-picker.js";
6
- import { findBuiltPortableContextPath, } from "../../packages/project-model/preparation-entries.js";
7
- import { resolveConfiguredPreparationSelection } from "./preparation-selection.js";
8
- import { createCompiledTestTarget } from "../../packages/testing/test-targets.js";
9
- import { resolveMethodId } from "../../packages/methods/method-resolution.js";
10
- import { submitTestRunToLocalService, waitForLocalTestRun, } from "../../packages/local-service/index.js";
11
- import { resolveCommandControlPath } from "./control-path.js";
10
+ import { CONNECT_OR_ERROR_HINT, readActiveConnection } from "../../packages/local-service/connection-config.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.length > 0) {
32
+ try {
33
+ body = JSON.parse(raw);
34
+ }
35
+ catch {
36
+ body = null;
37
+ }
38
+ }
39
+ return { status: response.status, body, raw };
40
+ }
12
41
  export const testCommand = {
13
- command: "test",
14
- describe: "Run readiness checks against source files and Portable Context",
42
+ command: "test <prep-id>",
43
+ describe: "Run readiness checks for a preparation",
15
44
  builder: (yargs) => yargs
16
- .option("preparation", {
45
+ .positional("prep-id", { type: "string", demandOption: true, describe: "Preparation id" })
46
+ .option("target", {
17
47
  type: "string",
18
- describe: "Preparation id to check when this Source Folder has more than one Preparation",
48
+ choices: ["source-files", "portable-context", "both"],
49
+ default: "both",
50
+ describe: "Which surface to test against",
19
51
  })
20
- .option("target", {
21
- choices: ["both", "source-files", "portable-context"],
22
- describe: "Check source files, Portable Context, or both. Default: both when Portable Context exists, otherwise source files.",
23
- }),
24
- handler: async (argv) => {
25
- await runTestCommand(argv);
52
+ .option("url", { type: "string", describe: "Override the active connection URL" })
53
+ .option("token", { type: "string", describe: "Override the active bearer token" }),
54
+ handler: async (args) => {
55
+ const { url, token } = resolveConnection(args);
56
+ const mode = args.target === "portable-context" ? "compiled" : args.target === "source-files" ? "source-files" : "both";
57
+ const { status, body, raw } = await callJson(`${url}/v1/preparations/${encodeURIComponent(args.prepId)}/test-runs`, token, { method: "POST", body: JSON.stringify({ mode }) });
58
+ if (status !== 201 && status !== 200) {
59
+ console.error(chalk.red(`Failed to start test run for ${args.prepId} (HTTP ${status}).`));
60
+ if (raw)
61
+ console.error(raw);
62
+ process.exit(1);
63
+ }
64
+ console.log();
65
+ console.log(` Run ${chalk.bold(body?.run_id ?? "(?)")} ${chalk.dim(`(${body?.status ?? "started"})`)}`);
66
+ if (body?.readiness?.status)
67
+ console.log(` Readiness: ${body.readiness.status}`);
68
+ if (body?.error)
69
+ console.log(chalk.red(` Error: ${body.error}`));
70
+ console.log();
26
71
  },
27
72
  };
28
- function readRequestedMode(argv) {
29
- const value = argv.target;
30
- const target = value === "source-files" || value === "portable-context" || value === "both"
31
- ? value
32
- : null;
33
- if (!target)
34
- return null;
35
- return modeFromTargetChoice(target);
36
- }
37
- function modeFromTargetChoice(target) {
38
- if (target === "source-files")
39
- return "raw";
40
- if (target === "portable-context")
41
- return "compiled";
42
- return "both";
43
- }
44
- function reportTestCommandFailure(argv, message, hints = []) {
45
- process.exitCode = 1;
46
- console.log(chalk.red(` ${message}`));
47
- for (const hint of hints) {
48
- console.log(chalk.dim(` ${hint}`));
49
- }
50
- const onFailure = typeof argv.onFailure === "function"
51
- ? argv.onFailure
52
- : null;
53
- void onFailure?.({ message, hints });
54
- return false;
55
- }
56
- async function promptTestMode(hasBuiltCompiled) {
57
- if (!hasBuiltCompiled) {
58
- return "raw";
59
- }
60
- const selected = await p.select({
61
- message: "What do you want to check?",
62
- options: [
63
- {
64
- value: "both",
65
- label: "Source files and Portable Context (Recommended)",
66
- hint: "Check whether the data is ready with and without Portable Context",
67
- },
68
- {
69
- value: "raw",
70
- label: "Source files only",
71
- hint: "Measure the current baseline on the Source Folder files",
72
- },
73
- {
74
- value: "compiled",
75
- label: "Portable Context only",
76
- hint: "Run the saved readiness checks against the current Portable Context",
77
- },
78
- ],
79
- });
80
- if (p.isCancel(selected))
81
- return null;
82
- return selected;
83
- }
84
- export async function runTestCommand(argv = {}) {
85
- const cwd = process.cwd();
86
- const detected = detectInterf(cwd);
87
- const sourcePath = typeof argv.sourcePath === "string" && argv.sourcePath.trim().length > 0
88
- ? argv.sourcePath.trim()
89
- : (detected ? resolveSourceControlPath(detected.path) : resolveCommandControlPath(cwd));
90
- const requestedPreparation = argv.preparation;
91
- const requestedPreparationName = typeof requestedPreparation === "string" && requestedPreparation.trim().length > 0
92
- ? requestedPreparation.trim()
93
- : null;
94
- const hintedPreparationConfig = (argv.preparationConfig ?? null);
95
- const selectedCompiled = detected
96
- ? (() => {
97
- const targetName = requestedPreparationName ?? hintedPreparationConfig?.name ?? detected.config.name;
98
- return resolveConfiguredPreparationSelection({
99
- sourcePath,
100
- requestedPreparationName: targetName,
101
- hintedPreparationConfig,
102
- }) ?? (targetName === detected.config.name
103
- ? (loadCompiledPreparationConfig(detected.path)
104
- ?? sourcePreparationConfigFromInterfConfig(detected.config))
105
- : null);
106
- })()
107
- : requestedPreparationName || hintedPreparationConfig
108
- ? resolveConfiguredPreparationSelection({
109
- sourcePath,
110
- requestedPreparationName,
111
- hintedPreparationConfig,
112
- })
113
- : await choosePreparationConfig({
114
- sourcePath,
115
- selectMessage: "Which saved Preparation do you want to test?",
116
- });
117
- if (selectedCompiled === undefined)
118
- return false;
119
- if (!selectedCompiled) {
120
- if (requestedPreparationName) {
121
- return reportTestCommandFailure(argv, `Preparation "${requestedPreparationName}" is not saved in this Source Folder.`, ["Run `interf list` to see the saved Preparations."]);
122
- }
123
- return reportTestCommandFailure(argv, "No saved Preparations are configured for this Source Folder yet.", ["Start with `interf` or `interf init`."]);
124
- }
125
- if (selectedCompiled.checks.length === 0) {
126
- return reportTestCommandFailure(argv, `Preparation "${selectedCompiled.name}" does not have any readiness checks yet.`, [
127
- "Run `interf`, edit this Preparation, and add a few readiness checks first.",
128
- "Then rerun `interf test`.",
129
- ]);
130
- }
131
- const builtCompiledPath = detected?.config.name === selectedCompiled.name
132
- ? detected.path
133
- : findBuiltPortableContextPath(sourcePath, selectedCompiled.name);
134
- const hasBuiltCompiled = builtCompiledPath
135
- ? createCompiledTestTarget(builtCompiledPath, selectedCompiled.name, resolveMethodId(selectedCompiled)).eligible
136
- : false;
137
- const requestedMode = readRequestedMode(argv);
138
- const selectedMode = requestedMode ?? (process.stdin.isTTY && process.stdout.isTTY
139
- ? await promptTestMode(hasBuiltCompiled)
140
- : (hasBuiltCompiled ? "both" : "raw"));
141
- if (!selectedMode)
142
- return false;
143
- const mode = selectedMode;
144
- const submitted = await submitTestRunToLocalService({
145
- projectPath: sourcePath,
146
- request: {
147
- preparation: selectedCompiled.name,
148
- mode,
149
- },
150
- });
151
- if (!submitted) {
152
- return reportTestCommandFailure(argv, "Interf local service is not running for this Workspace.", ["Start it with `interf web`, then rerun `interf test` so the readiness-check run is visible in Interf."]);
153
- }
154
- console.log(chalk.dim(` Visible in Interf: ${submitted.serviceUrl}/`));
155
- let lastStatus = "";
156
- const completed = await waitForLocalTestRun({
157
- serviceUrl: submitted.serviceUrl,
158
- runId: submitted.resource.run_id,
159
- onUpdate(resource) {
160
- if (resource.status === lastStatus)
161
- return;
162
- lastStatus = resource.status;
163
- console.log(chalk.dim(` Readiness check run: ${resource.status}`));
164
- },
165
- });
166
- if (completed.status !== "succeeded") {
167
- return reportTestCommandFailure(argv, `Readiness check run ${completed.status}.`, completed.error ? [completed.error] : []);
168
- }
169
- const compiledScore = completed.readiness_run?.compiled;
170
- const rawScore = completed.readiness_run?.raw;
171
- if (compiledScore) {
172
- console.log(chalk.green(` Portable Context readiness checks: ${compiledScore.passed_cases}/${compiledScore.total_cases}`));
173
- }
174
- if (rawScore) {
175
- console.log(chalk.dim(` Source files readiness checks: ${rawScore.passed_cases}/${rawScore.total_cases}`));
176
- }
177
- const onComplete = typeof argv.onComplete === "function"
178
- ? argv.onComplete
179
- : null;
180
- await onComplete?.({
181
- sourcePath,
182
- preparationConfig: selectedCompiled,
183
- builtCompiledPath: builtCompiledPath ?? null,
184
- mode,
185
- rows: [],
186
- });
187
- return true;
188
- }
@@ -1,11 +1,2 @@
1
1
  import type { CommandModule } from "yargs";
2
2
  export declare const webCommand: CommandModule;
3
- export interface WebProjectPaths {
4
- controlPath: string;
5
- sourceFolderPath: string | null;
6
- }
7
- export declare function resolveWebProjectPaths(argv?: Record<string, unknown>, cwd?: string): WebProjectPaths;
8
- export declare function ensureWebProjectInitialized(controlPath: string, options?: {
9
- sourceFolderPath?: string | null;
10
- }): void;
11
- export declare function runWebCommand(argv?: Record<string, unknown>): Promise<void>;
@@ -1,132 +1,159 @@
1
- import { existsSync, } from "node:fs";
2
- import { resolve } from "node:path";
1
+ /**
2
+ * `interf web` start the engine in the foreground until Ctrl-C.
3
+ *
4
+ * interf web # start on default port; hard error if port busy
5
+ * interf web stop # send SIGTERM to the running engine
6
+ * interf web status # print engine info via the connected URL
7
+ *
8
+ * Pure server. No reuse / register-with-existing logic. Writes
9
+ * `~/.interf/connection.json` on startup so subsequent CLI commands can
10
+ * connect without a pointer file.
11
+ */
3
12
  import chalk from "chalk";
4
- import { startLocalService, } from "../../packages/local-service/index.js";
5
- import { createNativeLocalServiceRunHandlers, } from "../../packages/local-service/native-run-handlers.js";
6
- import { loadSourceFolderConfig, saveSourceFolderConfig, sourceFolderConfigPath, } from "../../packages/project-model/source-config.js";
7
- import { seedLocalDefaultMethod } from "../../packages/method-package/local-methods.js";
8
- import { findNearestInterfInstanceConfig, hasInterfInstanceConfig, relativeSourceFolderPath, resolveInterfInstanceContext, } from "./control-path.js";
9
- import { listSourceFolderChoices, } from "../../packages/project-model/source-folders.js";
10
- export const webCommand = {
11
- command: "web",
12
- describe: "Start Interf Compiler UI and the local Interf service",
13
- builder: (yargs) => yargs
14
- .option("host", {
15
- type: "string",
16
- describe: "Host for the local Interf service",
17
- })
18
- .option("port", {
19
- type: "number",
20
- describe: "Port for the local Interf service",
21
- })
22
- .option("control-path", {
23
- type: "string",
24
- describe: "Folder where Interf stores local config, Methods, runs, and portable context",
25
- })
26
- .option("source-folder", {
27
- type: "string",
28
- describe: "Source Folder to prepare when initializing a new Interf Workspace",
29
- }),
30
- handler: async (argv) => {
31
- await runWebCommand(argv);
32
- },
33
- };
34
- function stringOption(value) {
35
- return typeof value === "string" && value.trim().length > 0
36
- ? value.trim()
37
- : undefined;
38
- }
39
- function numberOption(value) {
40
- if (typeof value !== "number" || !Number.isInteger(value))
13
+ import { readFileSync } from "node:fs";
14
+ import { LOCAL_SERVICE_DEFAULT_HOST, LOCAL_SERVICE_DEFAULT_PORT, buildLocalServiceUrl, } from "../../packages/local-service/routes.js";
15
+ import { startLocalService } from "../../packages/local-service/server.js";
16
+ import { createNativeLocalServiceRunHandlers } from "../../packages/local-service/native-run-handlers.js";
17
+ import { CONNECT_OR_ERROR_HINT, clearConnection, readActiveConnection, } from "../../packages/local-service/connection-config.js";
18
+ import { serviceRegistryPath } from "../../packages/local-service/instance-paths.js";
19
+ function packageVersionFromManifest() {
20
+ try {
21
+ const url = new URL("../../../package.json", import.meta.url);
22
+ const raw = readFileSync(url, "utf8");
23
+ const parsed = JSON.parse(raw);
24
+ return parsed.version;
25
+ }
26
+ catch {
41
27
  return undefined;
42
- return value;
43
- }
44
- export function resolveWebProjectPaths(argv = {}, cwd = process.cwd()) {
45
- const currentPath = resolve(cwd);
46
- const configuredControlPath = stringOption(argv["control-path"]);
47
- const configuredSourceFolder = stringOption(argv["source-folder"]);
48
- if (configuredControlPath) {
49
- return {
50
- controlPath: resolve(currentPath, configuredControlPath),
51
- sourceFolderPath: configuredSourceFolder ? resolve(currentPath, configuredSourceFolder) : null,
52
- };
53
28
  }
54
- const existingControlPath = findNearestInterfInstanceConfig(currentPath);
55
- if (existingControlPath) {
56
- return {
57
- controlPath: existingControlPath,
58
- sourceFolderPath: configuredSourceFolder ? resolve(currentPath, configuredSourceFolder) : null,
59
- };
29
+ }
30
+ function isPortInUseError(error) {
31
+ if (!error || typeof error !== "object")
32
+ return false;
33
+ const code = error.code;
34
+ return code === "EADDRINUSE";
35
+ }
36
+ async function runWebForeground(args) {
37
+ const host = args.host ?? LOCAL_SERVICE_DEFAULT_HOST;
38
+ const port = args.port ?? LOCAL_SERVICE_DEFAULT_PORT;
39
+ let service;
40
+ try {
41
+ service = await startLocalService({
42
+ host,
43
+ port,
44
+ packageVersion: packageVersionFromManifest(),
45
+ handlers: createNativeLocalServiceRunHandlers(),
46
+ });
60
47
  }
61
- if (configuredSourceFolder) {
62
- const resolvedSourceFolder = resolve(currentPath, configuredSourceFolder);
63
- const context = resolveInterfInstanceContext(resolvedSourceFolder);
64
- return {
65
- controlPath: context.controlPath,
66
- sourceFolderPath: resolvedSourceFolder,
67
- };
48
+ catch (error) {
49
+ if (isPortInUseError(error)) {
50
+ console.error(chalk.red(`Error: another Interf engine is already running at ${buildLocalServiceUrl({ host, port })}.`));
51
+ console.error(`Stop it first with \`interf web stop\`.`);
52
+ process.exit(1);
53
+ }
54
+ throw error;
68
55
  }
69
- const context = resolveInterfInstanceContext(currentPath);
70
- return {
71
- controlPath: context.controlPath,
72
- sourceFolderPath: context.defaultSourceFolderPath ?? currentPath,
73
- };
74
- }
75
- export function ensureWebProjectInitialized(controlPath, options = {}) {
76
- const inferSourceFolderPath = () => {
77
- if (options.sourceFolderPath)
78
- return options.sourceFolderPath;
79
- const choices = listSourceFolderChoices(controlPath);
80
- return choices.length === 1 ? resolve(controlPath, choices[0]?.value ?? "") : null;
81
- };
82
- if (existsSync(sourceFolderConfigPath(controlPath))) {
83
- if (!hasInterfInstanceConfig(controlPath)) {
84
- throw new Error(`Interf Workspace path is not usable: ${sourceFolderConfigPath(controlPath)}. Choose a different --control-path.`);
56
+ console.log();
57
+ console.log(` Interf engine: ${chalk.bold(service.url)}`);
58
+ console.log(` Compiler UI: ${service.url}/`);
59
+ console.log(` Health: ${service.url}/health`);
60
+ console.log(chalk.dim(" Press Ctrl-C to stop."));
61
+ console.log();
62
+ const shutdown = async () => {
63
+ try {
64
+ await service.close();
85
65
  }
86
- const existing = loadSourceFolderConfig(controlPath);
87
- const sourceFolderPath = existing?.source_folder ? null : inferSourceFolderPath();
88
- if (existing && sourceFolderPath) {
89
- saveSourceFolderConfig(controlPath, {
90
- source_folder: {
91
- path: relativeSourceFolderPath(controlPath, sourceFolderPath),
92
- },
93
- preparations: existing.preparations ?? [],
94
- });
66
+ catch {
67
+ // best effort
95
68
  }
96
- return;
97
- }
98
- seedLocalDefaultMethod({ sourcePath: controlPath });
99
- const sourceFolderPath = inferSourceFolderPath();
100
- saveSourceFolderConfig(controlPath, {
101
- ...(sourceFolderPath
102
- ? {
103
- source_folder: {
104
- path: relativeSourceFolderPath(controlPath, sourceFolderPath),
105
- },
106
- }
107
- : {}),
108
- preparations: [],
69
+ process.exit(0);
70
+ };
71
+ process.on("SIGINT", shutdown);
72
+ process.on("SIGTERM", shutdown);
73
+ await new Promise(() => {
74
+ /* block forever; signals trigger shutdown */
109
75
  });
110
76
  }
111
- export async function runWebCommand(argv = {}) {
112
- const { controlPath, sourceFolderPath } = resolveWebProjectPaths(argv);
113
- ensureWebProjectInitialized(controlPath, { sourceFolderPath });
114
- const handlers = createNativeLocalServiceRunHandlers();
115
- const service = await startLocalService({
116
- rootPath: controlPath,
117
- host: stringOption(argv.host),
118
- port: numberOption(argv.port),
119
- handlers,
77
+ function findEnginePidByUrl(url) {
78
+ try {
79
+ const raw = readFileSync(serviceRegistryPath(), "utf8");
80
+ const parsed = JSON.parse(raw);
81
+ const entry = parsed.services?.find((s) => s.url === url);
82
+ return entry?.pid ?? null;
83
+ }
84
+ catch {
85
+ return null;
86
+ }
87
+ }
88
+ async function runWebStop(args) {
89
+ const conn = readActiveConnection({
90
+ urlOverride: args.url,
91
+ authTokenOverride: args.token,
120
92
  });
121
- console.log(chalk.green(` Interf Compiler service: ${service.url}`));
122
- console.log(chalk.dim(` Compiler UI: ${service.url}/`));
123
- console.log(chalk.dim(` Health: ${service.url}/health`));
124
- console.log(chalk.dim(" Press Ctrl-C to stop the local Interf service."));
125
- await new Promise((resolve) => {
126
- const shutdown = () => {
127
- void service.close().finally(resolve);
128
- };
129
- process.once("SIGINT", shutdown);
130
- process.once("SIGTERM", shutdown);
93
+ if (!conn) {
94
+ console.error("No active Interf connection to stop.");
95
+ process.exit(1);
96
+ }
97
+ const url = conn.url.replace(/\/+$/, "");
98
+ const pid = findEnginePidByUrl(url);
99
+ if (!pid) {
100
+ console.error(`Could not locate engine PID for ${url}.`);
101
+ process.exit(1);
102
+ }
103
+ try {
104
+ process.kill(pid, "SIGTERM");
105
+ console.log(chalk.green(`Sent SIGTERM to engine pid ${pid} (${url}).`));
106
+ clearConnection();
107
+ }
108
+ catch (error) {
109
+ console.error(`Failed to stop engine pid ${pid}: ${error instanceof Error ? error.message : String(error)}`);
110
+ process.exit(1);
111
+ }
112
+ }
113
+ async function runWebStatus(args) {
114
+ const conn = readActiveConnection({
115
+ urlOverride: args.url,
116
+ authTokenOverride: args.token,
131
117
  });
118
+ if (!conn) {
119
+ console.error(CONNECT_OR_ERROR_HINT);
120
+ process.exit(1);
121
+ }
122
+ const url = conn.url.replace(/\/+$/, "");
123
+ try {
124
+ const headers = new Headers();
125
+ if (conn.auth_token)
126
+ headers.set("authorization", `Bearer ${conn.auth_token}`);
127
+ const response = await fetch(`${url}/v1/instance`, { headers });
128
+ const raw = await response.text();
129
+ if (response.status !== 200) {
130
+ console.error(chalk.red(`Engine status request failed (HTTP ${response.status}).`));
131
+ if (raw)
132
+ console.error(raw);
133
+ process.exit(1);
134
+ }
135
+ console.log(raw);
136
+ }
137
+ catch (error) {
138
+ console.error(chalk.red(`Engine ${url} unreachable: ${error instanceof Error ? error.message : String(error)}`));
139
+ process.exit(1);
140
+ }
132
141
  }
142
+ export const webCommand = {
143
+ command: "web [subcommand]",
144
+ describe: "Start / stop / inspect the Interf engine",
145
+ builder: (yargs) => yargs
146
+ .command("stop", "Stop the connected engine", (y) => y
147
+ .option("url", { type: "string", describe: "Override the active connection URL" })
148
+ .option("token", { type: "string", describe: "Override the active bearer token" }), runWebStop)
149
+ .command("status", "Show engine status via the connected URL", (y) => y
150
+ .option("url", { type: "string", describe: "Override the active connection URL" })
151
+ .option("token", { type: "string", describe: "Override the active bearer token" }), runWebStatus)
152
+ .command("$0", "Start the engine in the foreground (default)", (y) => y
153
+ .option("host", { type: "string", default: LOCAL_SERVICE_DEFAULT_HOST, describe: "Host to bind" })
154
+ .option("port", { type: "number", default: LOCAL_SERVICE_DEFAULT_PORT, describe: "Port to bind" }), runWebForeground)
155
+ .strict(),
156
+ handler: () => {
157
+ /* yargs subcommand handlers do the work */
158
+ },
159
+ };
@@ -0,0 +1,9 @@
1
+ import type { CommandModule } from "yargs";
2
+ interface WizardArgs {
3
+ url?: string;
4
+ token?: string;
5
+ }
6
+ export declare const wizardCommand: CommandModule<unknown, WizardArgs>;
7
+ /** Alias: `interf init` runs the same wizard. */
8
+ export declare const initCommand: CommandModule<unknown, WizardArgs>;
9
+ export {};