@oscharko-dev/keiko 0.2.0-beta.2 → 0.2.0-beta.3
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/dist/ui/csp-hashes.json +28 -27
- package/dist/ui/static/404.html +1 -1
- package/dist/ui/static/_next/static/chunks/258-e3b5ee46b0669967.js +1 -0
- package/dist/ui/static/_next/static/chunks/422-4c94c107b90d3ccc.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/_not-found/page-c4d800f366186be0.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/launch/page-17ca39367f25f372.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/layout-0f75a39edc90325d.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/local-knowledge/capsule/page-87a2ea239308ed34.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/local-knowledge/page-98bb7704fc7fd0ad.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/consolidation/page-f912263f1ee5d2dd.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/detail/page-fa590f135356e0af.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/page-b8555600c1113f14.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/review-queue/page-85cfbeb3598c0a36.js +1 -0
- package/dist/ui/static/_next/static/chunks/app/page-2881856ad25d9935.js +1 -0
- package/dist/ui/static/_next/static/chunks/{main-app-b52a8fa1d8127a5f.js → main-app-5b043f6c611974ae.js} +1 -1
- package/dist/ui/static/_next/static/css/eac94895f3edc5a5.css +1 -0
- package/dist/ui/static/index.html +1 -1
- package/dist/ui/static/index.txt +4 -4
- package/dist/ui/static/launch.html +1 -1
- package/dist/ui/static/launch.txt +4 -4
- package/dist/ui/static/local-knowledge/capsule.html +1 -1
- package/dist/ui/static/local-knowledge/capsule.txt +4 -4
- package/dist/ui/static/local-knowledge.html +1 -1
- package/dist/ui/static/local-knowledge.txt +4 -4
- package/dist/ui/static/manifest.webmanifest +2 -2
- package/dist/ui/static/memoriaviva/consolidation.html +1 -1
- package/dist/ui/static/memoriaviva/consolidation.txt +4 -4
- package/dist/ui/static/memoriaviva/detail.html +1 -1
- package/dist/ui/static/memoriaviva/detail.txt +4 -4
- package/dist/ui/static/memoriaviva/review-queue.html +1 -1
- package/dist/ui/static/memoriaviva/review-queue.txt +4 -4
- package/dist/ui/static/memoriaviva.html +1 -1
- package/dist/ui/static/memoriaviva.txt +4 -4
- package/node_modules/@oscharko-dev/keiko-cli/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/lifecycle.d.ts +2 -0
- package/node_modules/@oscharko-dev/keiko-cli/dist/lifecycle.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/lifecycle.js +51 -10
- package/node_modules/@oscharko-dev/keiko-cli/dist/ui.d.ts +3 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/ui.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-cli/dist/ui.js +93 -28
- package/node_modules/@oscharko-dev/keiko-cli/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.d.ts +2 -2
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/index.js +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/bffWire.d.ts +15 -0
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/bffWire.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/bffWire.js +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/index.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/dist/qualityIntelligence/index.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-contracts/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-evaluations/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-evaluations/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-evidence/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-harness/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-harness/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/indexing/orchestrator.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/indexing/orchestrator.js +5 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/pdf-parser.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/dist/parsers/pdf-parser.js +3 -1
- package/node_modules/@oscharko-dev/keiko-local-knowledge/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-capture/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-consolidation/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-governance/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-retrieval/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/paths.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-memory-vault/dist/paths.js +11 -5
- package/node_modules/@oscharko-dev/keiko-memory-vault/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-model-gateway/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-model-gateway/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-quality-intelligence/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-sdk/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-sdk/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-security/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-security/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/deps.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/deps.js +3 -3
- package/node_modules/@oscharko-dev/keiko-server/dist/local-knowledge-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/local-knowledge-handlers.js +9 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-handlers.d.ts +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-handlers.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/memory-handlers.js +6 -5
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/reCheckRoutes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/reCheckRoutes.js +25 -4
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runExecution.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runExecution.js +11 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runIngestion.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/runIngestion.js +39 -4
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/uiRoutes.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/qualityIntelligence/uiRoutes.js +13 -0
- package/node_modules/@oscharko-dev/keiko-server/dist/store/paths.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-server/dist/store/paths.js +9 -2
- package/node_modules/@oscharko-dev/keiko-server/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-tools/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-tools/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-verification/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-verification/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/qualityIntelligence/modelRoutedTestDesign.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workflows/dist/qualityIntelligence/modelRoutedTestDesign.js +41 -19
- package/node_modules/@oscharko-dev/keiko-workflows/package.json +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/.tsbuildinfo +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/ignore.d.ts.map +1 -1
- package/node_modules/@oscharko-dev/keiko-workspace/dist/ignore.js +3 -0
- package/node_modules/@oscharko-dev/keiko-workspace/package.json +1 -1
- package/package.json +1 -1
- package/dist/ui/static/_next/static/chunks/923-4141696576191bc0.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/_not-found/page-03d642dcd0f15b52.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/launch/page-c725ff0c02b50663.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/layout-aadefe615729db05.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/local-knowledge/capsule/page-4a7f242906e19a07.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/local-knowledge/page-3361769b8964e659.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/consolidation/page-44b3f4fa3e10085f.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/detail/page-0cdfb3eeb659daeb.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/page-e78e0cd2876fec41.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/memoriaviva/review-queue/page-e32fe86466827484.js +0 -1
- package/dist/ui/static/_next/static/chunks/app/page-9ad91065d05ddfa0.js +0 -1
- package/dist/ui/static/_next/static/css/51fdcfdc624e723d.css +0 -1
- /package/dist/ui/static/_next/static/{BNiyfCos3TiM2QdurajIZ → RAzN8WLtYaktD-ZePowXl}/_buildManifest.js +0 -0
- /package/dist/ui/static/_next/static/{BNiyfCos3TiM2QdurajIZ → RAzN8WLtYaktD-ZePowXl}/_ssgManifest.js +0 -0
|
@@ -6,6 +6,7 @@ type SpawnFn = (command: string, args: readonly string[], opts: SpawnOptions) =>
|
|
|
6
6
|
type FetchFn = (input: string, init?: RequestInit) => Promise<Response>;
|
|
7
7
|
type SleepFn = (ms: number) => Promise<void>;
|
|
8
8
|
type ProcessKiller = (pid: number, signal?: NodeJS.Signals | 0) => void;
|
|
9
|
+
type PortAvailabilityFn = (host: string, port: number) => Promise<boolean>;
|
|
9
10
|
export interface LifecycleCliDeps {
|
|
10
11
|
readonly cwd?: string | undefined;
|
|
11
12
|
readonly spawnFn?: SpawnFn | undefined;
|
|
@@ -13,6 +14,7 @@ export interface LifecycleCliDeps {
|
|
|
13
14
|
readonly sleep?: SleepFn | undefined;
|
|
14
15
|
readonly isProcessAlive?: ((pid: number) => boolean) | undefined;
|
|
15
16
|
readonly killProcess?: ProcessKiller | undefined;
|
|
17
|
+
readonly isPortAvailable?: PortAvailabilityFn | undefined;
|
|
16
18
|
}
|
|
17
19
|
export declare function runLifecycleCli(command: LifecycleCommand, args: readonly string[], io: CliIo, env: EnvSource, deps?: LifecycleCliDeps): Promise<number>;
|
|
18
20
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AASA,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"lifecycle.d.ts","sourceRoot":"","sources":["../src/lifecycle.ts"],"names":[],"mappings":"AASA,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAIjF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AAGnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEzC,KAAK,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,QAAQ,GAAG,SAAS,CAAC;AAChE,KAAK,OAAO,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,MAAM,EAAE,EAAE,IAAI,EAAE,YAAY,KAAK,YAAY,CAAC;AAC9F,KAAK,OAAO,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;AACxE,KAAK,OAAO,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AAC7C,KAAK,aAAa,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,CAAC,OAAO,GAAG,CAAC,KAAK,IAAI,CAAC;AACxE,KAAK,kBAAkB,GAAG,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;AAgD3E,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAClC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACvC,QAAQ,CAAC,SAAS,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IACrC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,GAAG,SAAS,CAAC;IACjE,QAAQ,CAAC,WAAW,CAAC,EAAE,aAAa,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,eAAe,CAAC,EAAE,kBAAkB,GAAG,SAAS,CAAC;CAC3D;AAwaD,wBAAsB,eAAe,CACnC,OAAO,EAAE,gBAAgB,EACzB,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,KAAK,EACT,GAAG,EAAE,SAAS,EACd,IAAI,GAAE,gBAAqB,GAC1B,OAAO,CAAC,MAAM,CAAC,CAqBjB"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { closeSync, existsSync, mkdirSync, openSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
2
2
|
import { spawn } from "node:child_process";
|
|
3
|
+
import { createServer as createNetServer } from "node:net";
|
|
3
4
|
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
4
5
|
import { fileURLToPath } from "node:url";
|
|
5
6
|
import { SDK_VERSION } from "@oscharko-dev/keiko-sdk";
|
|
@@ -151,6 +152,33 @@ function defaultIsProcessAlive(pid) {
|
|
|
151
152
|
return typeof error === "object" && error !== null && "code" in error && error.code === "EPERM";
|
|
152
153
|
}
|
|
153
154
|
}
|
|
155
|
+
function defaultIsPortAvailable(host, port) {
|
|
156
|
+
return new Promise((resolveAvailable) => {
|
|
157
|
+
const server = createNetServer();
|
|
158
|
+
let settled = false;
|
|
159
|
+
const settle = (available) => {
|
|
160
|
+
if (settled)
|
|
161
|
+
return;
|
|
162
|
+
settled = true;
|
|
163
|
+
server.removeAllListeners("error");
|
|
164
|
+
server.removeAllListeners("listening");
|
|
165
|
+
if (server.listening) {
|
|
166
|
+
server.close(() => {
|
|
167
|
+
resolveAvailable(available);
|
|
168
|
+
});
|
|
169
|
+
return;
|
|
170
|
+
}
|
|
171
|
+
resolveAvailable(available);
|
|
172
|
+
};
|
|
173
|
+
server.once("error", () => {
|
|
174
|
+
settle(false);
|
|
175
|
+
});
|
|
176
|
+
server.once("listening", () => {
|
|
177
|
+
settle(true);
|
|
178
|
+
});
|
|
179
|
+
server.listen(port, host);
|
|
180
|
+
});
|
|
181
|
+
}
|
|
154
182
|
function runningPid(options, isAlive) {
|
|
155
183
|
const path = pidFile(options);
|
|
156
184
|
const pid = readPid(path);
|
|
@@ -193,12 +221,13 @@ function spawnUiProcess(options, env, deps, cwd) {
|
|
|
193
221
|
mkdirSync(options.stateDir, { recursive: true, mode: 0o700 });
|
|
194
222
|
const logPath = logFile(options);
|
|
195
223
|
const fd = openSync(logPath, "a", 0o600);
|
|
224
|
+
const uiEnv = childEnv({ ...env, KEIKO_STATE_DIR: options.stateDir });
|
|
196
225
|
try {
|
|
197
226
|
return {
|
|
198
227
|
child: deps.spawnFn(process.execPath, [cliEntryPath(), "ui", "--port", String(options.port), "--host", options.host], {
|
|
199
228
|
cwd,
|
|
200
229
|
detached: true,
|
|
201
|
-
env:
|
|
230
|
+
env: uiEnv,
|
|
202
231
|
stdio: ["ignore", fd, fd],
|
|
203
232
|
}),
|
|
204
233
|
logPath,
|
|
@@ -217,7 +246,7 @@ async function waitForHealth(options, pid, deps) {
|
|
|
217
246
|
const response = await deps.fetchImpl(healthUrl(options), {
|
|
218
247
|
signal: AbortSignal.timeout(1_000),
|
|
219
248
|
});
|
|
220
|
-
if (response.ok) {
|
|
249
|
+
if (response.ok && deps.isProcessAlive(pid)) {
|
|
221
250
|
return true;
|
|
222
251
|
}
|
|
223
252
|
}
|
|
@@ -228,6 +257,12 @@ async function waitForHealth(options, pid, deps) {
|
|
|
228
257
|
}
|
|
229
258
|
return false;
|
|
230
259
|
}
|
|
260
|
+
async function ensureStartPortAvailable(options, io, deps) {
|
|
261
|
+
if (await deps.isPortAvailable(options.host, options.port))
|
|
262
|
+
return true;
|
|
263
|
+
io.err(`keiko start: port ${options.host}:${String(options.port)} is already in use. Stop the existing process or choose another port with --port.\n`);
|
|
264
|
+
return false;
|
|
265
|
+
}
|
|
231
266
|
async function cmdStart(options, io, env, deps, cwd) {
|
|
232
267
|
const running = runningPid(options, deps.isProcessAlive);
|
|
233
268
|
if (running !== undefined) {
|
|
@@ -246,6 +281,8 @@ async function cmdStart(options, io, env, deps, cwd) {
|
|
|
246
281
|
if (stopped !== 0)
|
|
247
282
|
return stopped;
|
|
248
283
|
}
|
|
284
|
+
if (!(await ensureStartPortAvailable(options, io, deps)))
|
|
285
|
+
return 1;
|
|
249
286
|
const { child, logPath } = spawnUiProcess(options, env, deps, cwd);
|
|
250
287
|
if (child.pid === undefined) {
|
|
251
288
|
io.err("keiko start: failed to spawn the UI process.\n");
|
|
@@ -308,6 +345,17 @@ async function cmdRestart(options, io, env, deps, cwd) {
|
|
|
308
345
|
return stopped;
|
|
309
346
|
return cmdStart(options, io, env, deps, cwd);
|
|
310
347
|
}
|
|
348
|
+
function runtimeDeps(deps) {
|
|
349
|
+
return {
|
|
350
|
+
spawnFn: deps.spawnFn ?? spawn,
|
|
351
|
+
fetchImpl: deps.fetchImpl ?? fetch,
|
|
352
|
+
sleep: deps.sleep ??
|
|
353
|
+
((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))),
|
|
354
|
+
isProcessAlive: deps.isProcessAlive ?? defaultIsProcessAlive,
|
|
355
|
+
killProcess: deps.killProcess ?? process.kill.bind(process),
|
|
356
|
+
isPortAvailable: deps.isPortAvailable ?? defaultIsPortAvailable,
|
|
357
|
+
};
|
|
358
|
+
}
|
|
311
359
|
export async function runLifecycleCli(command, args, io, env, deps = {}) {
|
|
312
360
|
const cwd = deps.cwd ?? process.cwd();
|
|
313
361
|
const options = parseLifecycleArgs(args, cwd, env);
|
|
@@ -319,14 +367,7 @@ export async function runLifecycleCli(command, args, io, env, deps = {}) {
|
|
|
319
367
|
io.err(USAGE);
|
|
320
368
|
return 2;
|
|
321
369
|
}
|
|
322
|
-
const fullDeps =
|
|
323
|
-
spawnFn: deps.spawnFn ?? spawn,
|
|
324
|
-
fetchImpl: deps.fetchImpl ?? fetch,
|
|
325
|
-
sleep: deps.sleep ??
|
|
326
|
-
((ms) => new Promise((resolveSleep) => setTimeout(resolveSleep, ms))),
|
|
327
|
-
isProcessAlive: deps.isProcessAlive ?? defaultIsProcessAlive,
|
|
328
|
-
killProcess: deps.killProcess ?? process.kill.bind(process),
|
|
329
|
-
};
|
|
370
|
+
const fullDeps = runtimeDeps(deps);
|
|
330
371
|
const handlers = {
|
|
331
372
|
start: () => cmdStart(options, io, env, fullDeps, cwd),
|
|
332
373
|
stop: () => cmdStop(options, io, fullDeps),
|
|
@@ -9,6 +9,7 @@ export interface UiCliArgs {
|
|
|
9
9
|
readonly config: string | undefined;
|
|
10
10
|
readonly uiDbPath: string | undefined;
|
|
11
11
|
}
|
|
12
|
+
type UiParseResult = UiCliArgs | "help" | null;
|
|
12
13
|
export interface UiCliDeps {
|
|
13
14
|
readonly createServer?: (deps: {
|
|
14
15
|
staticRoot: string;
|
|
@@ -24,9 +25,10 @@ export interface UiCliDeps {
|
|
|
24
25
|
readonly cwd?: string | undefined;
|
|
25
26
|
}
|
|
26
27
|
export type SpawnFn = (command: string, args: readonly string[], opts: SpawnOptions) => ChildProcess;
|
|
27
|
-
export declare function parseUiArgs(args: readonly string[]):
|
|
28
|
+
export declare function parseUiArgs(args: readonly string[]): UiParseResult;
|
|
28
29
|
export declare function applyServerTimeouts(server: Server): void;
|
|
29
30
|
export declare function waitForShutdown(server: Server): Promise<void>;
|
|
30
31
|
export declare function reExecWithSqliteFlag(_env: EnvSource, spawnFn: SpawnFn): Promise<number>;
|
|
31
32
|
export declare function runUiCli(args: readonly string[], io: CliIo, env: EnvSource, deps?: UiCliDeps): Promise<number>;
|
|
33
|
+
export {};
|
|
32
34
|
//# sourceMappingURL=ui.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAKxC,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../src/ui.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAKxC,OAAO,EAAS,KAAK,YAAY,EAAE,KAAK,YAAY,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAOL,KAAK,aAAa,EACnB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,mCAAmC,CAAC;AACnE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAczC,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,CAAC;IACzC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;CACvC;AAED,KAAK,aAAa,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;AAa/C,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE;QAC7B,UAAU,EAAE,MAAM,CAAC;QACnB,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,EAAE,MAAM,CAAC;QACb,WAAW,EAAE,aAAa,CAAC;KAC5B,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAC/B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAI7B,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,OAAO,CAAC;IACrC,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAG3B,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,SAAS,MAAM,EAAE,CAAC;IAEnD,QAAQ,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACnC;AAED,MAAM,MAAM,OAAO,GAAG,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE,YAAY,KACf,YAAY,CAAC;AA8DlB,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,MAAM,EAAE,GAAG,aAAa,CAYlE;AAkFD,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAGxD;AAWD,wBAAgB,eAAe,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiB7D;AA0BD,wBAAsB,oBAAoB,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAwB7F;AAgED,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,EAAE,EAAE,KAAK,EACT,GAAG,EAAE,SAAS,EACd,IAAI,GAAE,SAAc,GACnB,OAAO,CAAC,MAAM,CAAC,CA2BjB"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
// inheriting stdio and forwarding SIGINT/SIGTERM to the child, then propagates the child's exit
|
|
12
12
|
// code. Injected-test invocations skip the guard entirely.
|
|
13
13
|
import { existsSync, readFileSync } from "node:fs";
|
|
14
|
-
import { dirname, join, resolve } from "node:path";
|
|
14
|
+
import { dirname, isAbsolute, join, resolve } from "node:path";
|
|
15
15
|
import { fileURLToPath } from "node:url";
|
|
16
16
|
import { createRequire } from "node:module";
|
|
17
17
|
import { spawn } from "node:child_process";
|
|
@@ -19,20 +19,13 @@ import { createUiServer, loadCspHeader, buildUiHandlerDeps, DEFAULT_UI_PORT, UI_
|
|
|
19
19
|
const ALLOWED_HOSTS = new Set(["127.0.0.1", "localhost"]);
|
|
20
20
|
const SQLITE_FLAG = "--experimental-sqlite";
|
|
21
21
|
const KEIKO_ENV_NAME_RE = /^KEIKO_[A-Z0-9_]+$/;
|
|
22
|
+
const DEFAULT_STATE_DIR = ".keiko";
|
|
22
23
|
const USAGE = `Usage:
|
|
23
24
|
keiko ui [--port PORT] [--host 127.0.0.1|localhost] [--evidence-dir PATH] [--config PATH] [--ui-db PATH]
|
|
24
25
|
|
|
25
26
|
Launches the local Keiko UI on the loopback interface and prints its URL. The server
|
|
26
27
|
binds 127.0.0.1 only and serves the packaged UI assets (built with \`npm run build:ui\`).
|
|
27
28
|
`;
|
|
28
|
-
function flagValue(args, name) {
|
|
29
|
-
const i = args.indexOf(name);
|
|
30
|
-
if (i === -1) {
|
|
31
|
-
return undefined;
|
|
32
|
-
}
|
|
33
|
-
const value = args[i + 1];
|
|
34
|
-
return value === undefined || value.startsWith("--") ? null : value;
|
|
35
|
-
}
|
|
36
29
|
function parsePort(raw) {
|
|
37
30
|
if (!/^\d{1,5}$/.test(raw)) {
|
|
38
31
|
return null;
|
|
@@ -40,21 +33,61 @@ function parsePort(raw) {
|
|
|
40
33
|
const port = Number(raw);
|
|
41
34
|
return port >= 1 && port <= 65535 ? port : null;
|
|
42
35
|
}
|
|
36
|
+
function readFlagValue(args, index) {
|
|
37
|
+
const value = args[index + 1];
|
|
38
|
+
return value === undefined || value.startsWith("--") ? null : value;
|
|
39
|
+
}
|
|
40
|
+
function isUiFlag(arg) {
|
|
41
|
+
return (arg === "--port" ||
|
|
42
|
+
arg === "--host" ||
|
|
43
|
+
arg === "--evidence-dir" ||
|
|
44
|
+
arg === "--config" ||
|
|
45
|
+
arg === "--ui-db");
|
|
46
|
+
}
|
|
47
|
+
function setRawUiOption(raw, flag, value) {
|
|
48
|
+
switch (flag) {
|
|
49
|
+
case "--port":
|
|
50
|
+
raw.portRaw = value;
|
|
51
|
+
return;
|
|
52
|
+
case "--host":
|
|
53
|
+
raw.hostRaw = value;
|
|
54
|
+
return;
|
|
55
|
+
case "--evidence-dir":
|
|
56
|
+
raw.evidenceRaw = value;
|
|
57
|
+
return;
|
|
58
|
+
case "--config":
|
|
59
|
+
raw.configRaw = value;
|
|
60
|
+
return;
|
|
61
|
+
case "--ui-db":
|
|
62
|
+
raw.uiDbRaw = value;
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function collectUiOptions(args) {
|
|
67
|
+
const raw = {};
|
|
68
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
69
|
+
const arg = args[i];
|
|
70
|
+
if (arg === undefined)
|
|
71
|
+
return null;
|
|
72
|
+
if (arg === "--help" || arg === "-h")
|
|
73
|
+
return "help";
|
|
74
|
+
if (!isUiFlag(arg))
|
|
75
|
+
return null;
|
|
76
|
+
const value = readFlagValue(args, i);
|
|
77
|
+
if (value === null)
|
|
78
|
+
return null;
|
|
79
|
+
setRawUiOption(raw, arg, value);
|
|
80
|
+
i += 1;
|
|
81
|
+
}
|
|
82
|
+
return raw;
|
|
83
|
+
}
|
|
43
84
|
// Parses flags. Returns the parsed args, or null on any usage error (missing flag value, invalid
|
|
44
85
|
// port, or a host other than the two loopback names).
|
|
45
86
|
export function parseUiArgs(args) {
|
|
46
|
-
const
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
const configRaw =
|
|
50
|
-
const uiDbRaw = flagValue(args, "--ui-db");
|
|
51
|
-
if (portRaw === null ||
|
|
52
|
-
hostRaw === null ||
|
|
53
|
-
evidenceRaw === null ||
|
|
54
|
-
configRaw === null ||
|
|
55
|
-
uiDbRaw === null) {
|
|
56
|
-
return null;
|
|
57
|
-
}
|
|
87
|
+
const raw = collectUiOptions(args);
|
|
88
|
+
if (raw === "help" || raw === null)
|
|
89
|
+
return raw;
|
|
90
|
+
const { portRaw, hostRaw, evidenceRaw, configRaw, uiDbRaw } = raw;
|
|
58
91
|
if (hostRaw !== undefined && !ALLOWED_HOSTS.has(hostRaw)) {
|
|
59
92
|
return null;
|
|
60
93
|
}
|
|
@@ -111,6 +144,27 @@ function loadLocalKeikoEnv(cwd, env) {
|
|
|
111
144
|
function resolveUiConfigPath(parsed, env) {
|
|
112
145
|
return parsed.config ?? env.KEIKO_CONFIG_FILE;
|
|
113
146
|
}
|
|
147
|
+
function hasEnvValue(value) {
|
|
148
|
+
return value !== undefined && value.length > 0;
|
|
149
|
+
}
|
|
150
|
+
function resolveRuntimeStateDir(cwd, env) {
|
|
151
|
+
const raw = env.KEIKO_STATE_DIR;
|
|
152
|
+
if (hasEnvValue(raw)) {
|
|
153
|
+
return isAbsolute(raw) ? raw : resolve(cwd, raw);
|
|
154
|
+
}
|
|
155
|
+
return resolve(cwd, DEFAULT_STATE_DIR);
|
|
156
|
+
}
|
|
157
|
+
function withDefaultLocalRuntimeStateEnv(cwd, parsed, env) {
|
|
158
|
+
const stateDir = resolveRuntimeStateDir(cwd, env);
|
|
159
|
+
const next = { ...env, KEIKO_STATE_DIR: stateDir };
|
|
160
|
+
if (parsed.uiDbPath === undefined && !hasEnvValue(next.KEIKO_UI_DATA_DIR)) {
|
|
161
|
+
next.KEIKO_UI_DATA_DIR = join(stateDir, "ui");
|
|
162
|
+
}
|
|
163
|
+
if (!hasEnvValue(next.KEIKO_MEMORY_DIR)) {
|
|
164
|
+
next.KEIKO_MEMORY_DIR = join(stateDir, "memory");
|
|
165
|
+
}
|
|
166
|
+
return next;
|
|
167
|
+
}
|
|
114
168
|
// Conservative request/header timeouts on the loopback BFF (defense in depth, L2/L3): even on
|
|
115
169
|
// 127.0.0.1 a slow or stuck client must not hold a connection indefinitely. headersTimeout must be
|
|
116
170
|
// at or below requestTimeout so an incomplete request line/header set is cut first.
|
|
@@ -235,6 +289,18 @@ function ensureStaticRoot(staticRoot, io) {
|
|
|
235
289
|
io.err(`keiko ui: UI assets not found at ${staticRoot}. Run \`npm run build:ui\` first.\n`);
|
|
236
290
|
return false;
|
|
237
291
|
}
|
|
292
|
+
function parseUiArgsOrExit(args, io) {
|
|
293
|
+
const parsed = parseUiArgs(args);
|
|
294
|
+
if (parsed === "help") {
|
|
295
|
+
io.out(USAGE);
|
|
296
|
+
return 0;
|
|
297
|
+
}
|
|
298
|
+
if (parsed === null) {
|
|
299
|
+
io.err(USAGE);
|
|
300
|
+
return 2;
|
|
301
|
+
}
|
|
302
|
+
return parsed;
|
|
303
|
+
}
|
|
238
304
|
async function maybeWaitForShutdown(server, deps) {
|
|
239
305
|
if (deps.createServer !== undefined) {
|
|
240
306
|
return;
|
|
@@ -242,21 +308,20 @@ async function maybeWaitForShutdown(server, deps) {
|
|
|
242
308
|
await waitForShutdown(server);
|
|
243
309
|
}
|
|
244
310
|
export async function runUiCli(args, io, env, deps = {}) {
|
|
245
|
-
const
|
|
311
|
+
const cwd = deps.cwd ?? process.cwd();
|
|
312
|
+
const effectiveEnv = loadLocalKeikoEnv(cwd, env);
|
|
313
|
+
const parsed = parseUiArgsOrExit(args, io);
|
|
314
|
+
if (typeof parsed === "number")
|
|
315
|
+
return parsed;
|
|
246
316
|
const reExec = await maybeReExecForSqlite(effectiveEnv, deps);
|
|
247
317
|
if (reExec !== undefined)
|
|
248
318
|
return reExec;
|
|
249
|
-
const parsed = parseUiArgs(args);
|
|
250
|
-
if (parsed === null) {
|
|
251
|
-
io.err(USAGE);
|
|
252
|
-
return 2;
|
|
253
|
-
}
|
|
254
319
|
const staticRoot = deps.staticRoot ?? defaultStaticRoot();
|
|
255
320
|
if (!ensureStaticRoot(staticRoot, io)) {
|
|
256
321
|
return 1;
|
|
257
322
|
}
|
|
258
323
|
const csp = await loadCspHeader(deps.hashesFile ?? join(staticRoot, "..", "csp-hashes.json"));
|
|
259
|
-
const handlerDeps = buildHandlerDepsOrReport(parsed, effectiveEnv, io);
|
|
324
|
+
const handlerDeps = buildHandlerDepsOrReport(parsed, withDefaultLocalRuntimeStateEnv(cwd, parsed, effectiveEnv), io);
|
|
260
325
|
if (typeof handlerDeps === "number")
|
|
261
326
|
return handlerDeps;
|
|
262
327
|
const factory = deps.createServer ?? createUiServer;
|