@kici-dev/compiler 0.1.26 → 0.2.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/dist/auth/headless-detect.d.ts +14 -5
- package/dist/auth/headless-detect.js +50 -9
- package/dist/cli-banner.d.ts +6 -3
- package/dist/cli-banner.js +13 -5
- package/dist/cli.js +180 -48
- package/dist/commands/check-mode.d.ts +1 -1
- package/dist/commands/compile.js +31 -7
- package/dist/commands/diagnostics.js +14 -2
- package/dist/commands/doctor.d.ts +64 -0
- package/dist/commands/doctor.js +413 -0
- package/dist/commands/endpoints.js +6 -0
- package/dist/commands/fixture.js +13 -0
- package/dist/commands/hook.js +3 -2
- package/dist/commands/index.d.ts +13 -1
- package/dist/commands/index.js +10 -3
- package/dist/commands/init-host-os.d.ts +34 -0
- package/dist/commands/init-host-os.js +44 -0
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +160 -37
- package/dist/commands/local-trust-root.d.ts +6 -0
- package/dist/commands/local-trust-root.js +52 -0
- package/dist/commands/local.d.ts +65 -0
- package/dist/commands/local.js +206 -0
- package/dist/commands/login.d.ts +2 -0
- package/dist/commands/login.js +41 -1
- package/dist/commands/logout.js +7 -0
- package/dist/commands/notifications.d.ts +61 -0
- package/dist/commands/notifications.js +274 -0
- package/dist/commands/preview.js +9 -2
- package/dist/commands/run-banner.d.ts +31 -0
- package/dist/commands/run-banner.js +25 -0
- package/dist/commands/run-routed.d.ts +53 -0
- package/dist/commands/run-routed.js +185 -0
- package/dist/commands/run.d.ts +0 -17
- package/dist/commands/run.js +44 -58
- package/dist/commands/runs/artifacts/download.d.ts +24 -0
- package/dist/commands/runs/artifacts/download.js +154 -0
- package/dist/commands/runs/artifacts/list.d.ts +5 -0
- package/dist/commands/runs/artifacts/list.js +47 -0
- package/dist/commands/runs/cancel.js +2 -2
- package/dist/commands/runs/list.js +8 -2
- package/dist/commands/secrets-list.d.ts +2 -2
- package/dist/commands/secrets-list.js +4 -4
- package/dist/commands/types.d.ts +3 -3
- package/dist/commands/types.js +4 -4
- package/dist/commands/verify-attestation.d.ts +3 -1
- package/dist/commands/verify-attestation.js +18 -7
- package/dist/errors/formatter.d.ts +14 -1
- package/dist/errors/formatter.js +13 -3
- package/dist/errors/index.d.ts +2 -1
- package/dist/errors/index.js +3 -2
- package/dist/errors/source-location.d.ts +20 -0
- package/dist/errors/source-location.js +45 -0
- package/dist/execution/executor.js +32 -12
- package/dist/fixtures/defaults/index.js +2 -1
- package/dist/generators/secrets-dts.d.ts +9 -9
- package/dist/generators/secrets-dts.js +12 -12
- package/dist/llm-context/llms-architecture.txt +50 -21
- package/dist/llm-context/llms-cli.txt +2667 -1454
- package/dist/llm-context/llms-features.txt +484 -414
- package/dist/llm-context/llms-full.txt +6703 -4687
- package/dist/llm-context/llms-getting-started.txt +311 -55
- package/dist/llm-context/llms-patterns.txt +17 -29
- package/dist/llm-context/llms-providers.txt +10 -1
- package/dist/llm-context/llms-sdk-runtime.txt +2013 -0
- package/dist/llm-context/llms-sdk.txt +596 -2157
- package/dist/llm-context/llms.txt +31 -17
- package/dist/local-plane/orchestrator-process.d.ts +70 -0
- package/dist/local-plane/orchestrator-process.js +129 -0
- package/dist/local-plane/os-mismatch-hint.d.ts +16 -0
- package/dist/local-plane/os-mismatch-hint.js +34 -0
- package/dist/local-plane/paths.d.ts +39 -0
- package/dist/local-plane/paths.js +54 -0
- package/dist/local-plane/plane-liveness.d.ts +68 -0
- package/dist/local-plane/plane-liveness.js +145 -0
- package/dist/local-plane/plane-manager.d.ts +193 -0
- package/dist/local-plane/plane-manager.js +480 -0
- package/dist/local-plane/plane-seed.d.ts +76 -0
- package/dist/local-plane/plane-seed.js +59 -0
- package/dist/local-plane/plane-trigger.d.ts +71 -0
- package/dist/local-plane/plane-trigger.js +110 -0
- package/dist/local-plane/platform-attach.d.ts +53 -0
- package/dist/local-plane/platform-attach.js +107 -0
- package/dist/local-plane/port-holder.d.ts +78 -0
- package/dist/local-plane/port-holder.js +227 -0
- package/dist/local-plane/postgres.d.ts +56 -0
- package/dist/local-plane/postgres.js +187 -0
- package/dist/local-plane/resolve-plane.d.ts +37 -0
- package/dist/local-plane/resolve-plane.js +76 -0
- package/dist/local-plane/run-follow.d.ts +61 -0
- package/dist/local-plane/run-follow.js +151 -0
- package/dist/local-plane/scaler-config.d.ts +68 -0
- package/dist/local-plane/scaler-config.js +132 -0
- package/dist/local-plane/secret-seed.d.ts +59 -0
- package/dist/local-plane/secret-seed.js +112 -0
- package/dist/local-plane/source-provider.d.ts +43 -0
- package/dist/local-plane/source-provider.js +159 -0
- package/dist/local-plane/trusted-routing.d.ts +32 -0
- package/dist/local-plane/trusted-routing.js +47 -0
- package/dist/lockfile/generator.d.ts +14 -1
- package/dist/lockfile/generator.js +103 -37
- package/dist/lockfile/index.d.ts +3 -1
- package/dist/lockfile/index.js +3 -2
- package/dist/lockfile/purity-diagnostics.d.ts +31 -0
- package/dist/lockfile/purity-diagnostics.js +52 -0
- package/dist/postinstall.js +2 -1
- package/dist/remote/artifact-extract.d.ts +8 -0
- package/dist/remote/artifact-extract.js +58 -0
- package/dist/remote/config.d.ts +21 -3
- package/dist/remote/config.js +24 -5
- package/dist/remote/dashboard-client.d.ts +46 -9
- package/dist/remote/dashboard-client.js +54 -11
- package/dist/remote/fs-case.d.ts +21 -0
- package/dist/remote/fs-case.js +45 -0
- package/dist/remote/history.d.ts +9 -3
- package/dist/remote/history.js +79 -10
- package/dist/remote/local-repo-identity.d.ts +1 -1
- package/dist/remote/local-repo-identity.js +2 -1
- package/dist/remote/notifications-client.d.ts +149 -0
- package/dist/remote/notifications-client.js +103 -0
- package/dist/remote/oauth.d.ts +13 -0
- package/dist/remote/oauth.js +31 -5
- package/dist/remote/output/summary.js +76 -14
- package/dist/remote/platform-client.d.ts +1 -1
- package/dist/remote/render.js +30 -9
- package/dist/{local-executor → remote}/secret-loader.d.ts +1 -1
- package/dist/{local-executor → remote}/secret-loader.js +4 -4
- package/dist/remote/secret-upload.d.ts +1 -1
- package/dist/remote/secret-upload.js +2 -2
- package/dist/remote/uploader.d.ts +1 -1
- package/dist/remote/uploader.js +7 -6
- package/dist/templates/agents-md.d.ts +1 -1
- package/dist/templates/agents-md.js +8 -8
- package/dist/templates/index.d.ts +1 -1
- package/dist/templates/index.js +2 -2
- package/dist/templates/package-json.d.ts +15 -0
- package/dist/templates/package-json.js +26 -5
- package/dist/test-runner/dry-run.d.ts +2 -1
- package/dist/test-runner/dry-run.js +18 -1
- package/dist/test-runner/event-types.d.ts +2 -0
- package/dist/test-runner/event-types.js +3 -0
- package/dist/test-runner/job-executor.d.ts +1 -0
- package/dist/test-runner/job-executor.js +82 -44
- package/dist/test-runner/output-formatter.d.ts +5 -2
- package/dist/test-runner/output-formatter.js +6 -4
- package/dist/test-runner/payload-builder.d.ts +7 -1
- package/dist/test-runner/payload-builder.js +11 -2
- package/dist/test-runner/rule-evaluator.d.ts +7 -3
- package/dist/test-runner/rule-evaluator.js +13 -12
- package/dist/{local-executor → test-runner}/runs-on-display.js +1 -1
- package/dist/test-runner/step-context.d.ts +23 -5
- package/dist/test-runner/step-context.js +29 -119
- package/dist/types.d.ts +26 -7
- package/dist/types.js +4 -2
- package/dist/validation/index.d.ts +2 -0
- package/dist/validation/index.js +2 -1
- package/dist/validation/typecheck.d.ts +28 -0
- package/dist/validation/typecheck.js +110 -0
- package/dist/validation/validator.d.ts +9 -4
- package/dist/validation/validator.js +38 -44
- package/package.json +13 -13
- package/sbom.spdx.json +9311 -1528
- package/dist/assets/api-TJJVHrjC.json +0 -118
- package/dist/assets/descriptor-BTtjzN9L.json +0 -1382
- package/dist/assets/package-BpQF9kR8.json +0 -74
- package/dist/assets/package-Ceo2h27X.json +0 -89
- package/dist/assets/source_context-D0atuL28.json +0 -20
- package/dist/assets/type-BFqO8SCZ.json +0 -202
- package/dist/commands/cancel.d.ts +0 -22
- package/dist/commands/detect-package-manager.d.ts +0 -42
- package/dist/commands/held-run-resolve.d.ts +0 -50
- package/dist/commands/status.d.ts +0 -34
- package/dist/commands/test.d.ts +0 -88
- package/dist/errors/codes.d.ts +0 -25
- package/dist/local-executor/dag-scheduler.d.ts +0 -44
- package/dist/local-executor/dag-scheduler.js +0 -183
- package/dist/local-executor/index.d.ts +0 -23
- package/dist/local-executor/index.js +0 -378
- package/dist/local-executor/job-runner.d.ts +0 -47
- package/dist/local-executor/job-runner.js +0 -411
- package/dist/local-executor/materializer.d.ts +0 -44
- package/dist/local-executor/materializer.js +0 -132
- package/dist/local-executor/output-streamer.d.ts +0 -31
- package/dist/local-executor/output-streamer.js +0 -168
- package/dist/local-executor/payload-generator.d.ts +0 -16
- package/dist/local-executor/payload-generator.js +0 -138
- package/dist/local-executor/picker.d.ts +0 -33
- package/dist/local-executor/picker.js +0 -109
- package/dist/local-executor/to-event-payload.d.ts +0 -16
- package/dist/local-executor/to-event-payload.js +0 -21
- package/dist/local-executor/types.d.ts +0 -93
- package/dist/local-executor/types.js +0 -2
- package/dist/local-executor/workflow-lock.d.ts +0 -82
- package/dist/local-executor/workflow-lock.js +0 -0
- package/dist/package-F7UXSDHW.json +0 -74
- package/dist/remote/client.d.ts +0 -210
- package/dist/remote/observer.d.ts +0 -81
- package/dist/test-runner/summary.d.ts +0 -7
- /package/dist/{local-executor → test-runner}/runs-on-display.d.ts +0 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import { deriveOsArchLabels } from "@kici-dev/engine";
|
|
3
|
+
//#region src/commands/init-host-os.ts
|
|
4
|
+
/**
|
|
5
|
+
* Host-OS helpers for `kici init`.
|
|
6
|
+
*
|
|
7
|
+
* The starter templates target `kici:os:linux`. On a macOS or Windows host that
|
|
8
|
+
* label matches no local dev-plane agent, so the first `kici run push --local`
|
|
9
|
+
* dispatches nothing. These helpers rewrite the scaffolded `runsOn` to the
|
|
10
|
+
* host's own `kici:os:*` label so the first run lands, mirroring how `kici init`
|
|
11
|
+
* already rewrites the default branch.
|
|
12
|
+
*/
|
|
13
|
+
const OS_LABEL_PREFIX = "kici:os:";
|
|
14
|
+
/**
|
|
15
|
+
* The primary `kici:os:*` label the host reports (linux→kici:os:linux,
|
|
16
|
+
* darwin→kici:os:macos, win32→kici:os:windows). Derived from the engine's
|
|
17
|
+
* canonical mapping — the same derivation the local dev-plane routing uses — so
|
|
18
|
+
* the value is never hand-spelled here and always matches what the plane can
|
|
19
|
+
* satisfy.
|
|
20
|
+
*/
|
|
21
|
+
function primaryHostOsLabel(platform, arch) {
|
|
22
|
+
return deriveOsArchLabels(platform, arch).find((l) => l.startsWith(OS_LABEL_PREFIX)) ?? `${OS_LABEL_PREFIX}${platform}`;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Rewrite a template's `'kici:os:linux'` runsOn to the host's primary OS label.
|
|
26
|
+
* A no-op on a Linux host (the templates already target it).
|
|
27
|
+
*/
|
|
28
|
+
function rewriteRunsOnForHost(content, platform, arch) {
|
|
29
|
+
const hostLabel = primaryHostOsLabel(platform, arch);
|
|
30
|
+
if (hostLabel === "kici:os:linux") return content;
|
|
31
|
+
return content.replaceAll(`'kici:os:linux'`, `'${hostLabel}'`);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether to offer the post-init `Run it now?` prompt: interactive (TTY, not CI)
|
|
35
|
+
* and with dependencies installed (not `--mjs`, not `--skip-install`), so the
|
|
36
|
+
* offered `kici run push --local` can compile the workflow it just scaffolded.
|
|
37
|
+
*/
|
|
38
|
+
function shouldOfferFirstRun(env) {
|
|
39
|
+
return env.isTTY && !env.ci && !env.mjs && !env.skipInstall;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { primaryHostOsLabel, rewriteRunsOnForHost, shouldOfferFirstRun };
|
|
43
|
+
|
|
44
|
+
//# sourceMappingURL=init-host-os.js.map
|
package/dist/commands/init.d.ts
CHANGED
|
@@ -29,6 +29,10 @@ export interface InitOptions {
|
|
|
29
29
|
privateRegistrySecret?: string;
|
|
30
30
|
/** Skip writing the .kici/AGENTS.md LLM-authoring context file. Default: write it. */
|
|
31
31
|
noAgentsMd?: boolean;
|
|
32
|
+
/** Force integrate mode: join .kici/ to the detected workspace (skip the prompt). */
|
|
33
|
+
workspace?: boolean;
|
|
34
|
+
/** Force standalone mode even inside a workspace (skip the prompt). */
|
|
35
|
+
standalone?: boolean;
|
|
32
36
|
}
|
|
33
37
|
/**
|
|
34
38
|
* Initialize .kici/ directory with workflow templates
|
package/dist/commands/init.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
1
|
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
2
|
import { agentsMdTemplate } from "../templates/agents-md.js";
|
|
3
3
|
import { tsconfigTemplate } from "../templates/tsconfig-json.js";
|
|
4
|
-
import { generatePackageJson } from "../templates/package-json.js";
|
|
4
|
+
import { generatePackageJson, sdkDependencyRange } from "../templates/package-json.js";
|
|
5
5
|
import { workflowPaths } from "../templates/index.js";
|
|
6
6
|
import { detectHookTools, findGitDir } from "../hooks/detector.js";
|
|
7
7
|
import { installHook } from "../hooks/installer.js";
|
|
8
8
|
import "../hooks/index.js";
|
|
9
9
|
import { getTypeScriptPaths } from "../execution/sdk-alias.js";
|
|
10
|
+
import { rewriteRunsOnForHost, shouldOfferFirstRun } from "./init-host-os.js";
|
|
10
11
|
import path from "node:path";
|
|
11
12
|
import pc from "picocolors";
|
|
12
13
|
import { access, mkdir, readFile, rm, writeFile } from "node:fs/promises";
|
|
14
|
+
import { $ } from "zx";
|
|
13
15
|
import { initZx, logger, toErrorMessage } from "@kici-dev/core";
|
|
14
|
-
import { detectPackageManager, installBuildPolicyArgs, installCommand, parsePackageManager } from "@kici-dev/core/package-manager";
|
|
16
|
+
import { detectPackageManager, detectWorkspaceRoot, installBuildPolicyArgs, installCommand, parsePackageManager } from "@kici-dev/core/package-manager";
|
|
15
17
|
import { checkbox, confirm, select } from "@inquirer/prompts";
|
|
16
|
-
import {
|
|
18
|
+
import { isCiEnvironment } from "@kici-dev/core/ci-env";
|
|
19
|
+
import os from "node:os";
|
|
17
20
|
//#region src/commands/init.ts
|
|
18
21
|
/**
|
|
19
22
|
* kici init command
|
|
@@ -59,6 +62,7 @@ async function initCommand(options = {}) {
|
|
|
59
62
|
content = content.replaceAll("targeting('main')", `targeting('${defaultBranch}')`);
|
|
60
63
|
content = content.replaceAll("targeting the main branch", `targeting the ${defaultBranch} branch`);
|
|
61
64
|
}
|
|
65
|
+
content = rewriteRunsOnForHost(content, os.platform(), os.arch());
|
|
62
66
|
await writeFile(path.join(kiciDir, "workflows", `${workflow}.ts`), content, "utf-8");
|
|
63
67
|
}
|
|
64
68
|
logger.info(pc.gray("Creating .kici/tests/"));
|
|
@@ -73,34 +77,12 @@ async function initCommand(options = {}) {
|
|
|
73
77
|
await writeFile(kiciIgnorePath, kiciIgnoreTemplate, "utf-8");
|
|
74
78
|
}
|
|
75
79
|
const devMode = options.useVerdaccioLocal || await detectDevelopmentMode();
|
|
76
|
-
|
|
77
|
-
const pkgContent = generatePackageJson(devMode);
|
|
78
|
-
await writeFile(path.join(kiciDir, "package.json"), pkgContent, "utf-8");
|
|
80
|
+
const mode = await resolveScaffoldMode(options);
|
|
79
81
|
const useVerdaccio = devMode;
|
|
80
|
-
if (
|
|
81
|
-
logger.info(pc.
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
const rootNpmrc = path.resolve(".npmrc");
|
|
85
|
-
if (!await checkExists(rootNpmrc)) {
|
|
86
|
-
logger.info(pc.gray("Writing .npmrc (Verdaccio scope)"));
|
|
87
|
-
await writeFile(rootNpmrc, npmrc, "utf-8");
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
if (!options.mjs) {
|
|
91
|
-
logger.info(pc.gray("Writing .kici/tsconfig.json"));
|
|
92
|
-
const tsconfigContent = await generateTsConfig();
|
|
93
|
-
await writeFile(path.join(kiciDir, "tsconfig.json"), tsconfigContent, "utf-8");
|
|
94
|
-
await mkdir(path.join(kiciDir, "types"), { recursive: true });
|
|
95
|
-
logger.info(pc.gray("Created .kici/types/ for generated type declarations"));
|
|
96
|
-
if (!options.skipInstall) {
|
|
97
|
-
const pm = await resolvePackageManager(options.packageManager);
|
|
98
|
-
const [bin, action] = installCommand(pm);
|
|
99
|
-
const buildPolicyArgs = installBuildPolicyArgs(pm);
|
|
100
|
-
logger.info(pc.gray(`Running ${bin} ${action}...`));
|
|
101
|
-
await $`cd ${kiciDir} && ${bin} ${action} ${buildPolicyArgs}`;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
82
|
+
if (mode.kind === "integrate") {
|
|
83
|
+
logger.info(pc.cyan(`Integrating .kici/ into the ${mode.workspaceKind} workspace at ${mode.workspaceRoot}`));
|
|
84
|
+
await wireIntegrateDeps(kiciDir, mode.workspaceRoot, devMode, options);
|
|
85
|
+
} else await wireStandaloneDeps(kiciDir, devMode, options);
|
|
104
86
|
if (options.privateRegistry) await writePrivateRegistryScaffold(kiciDir, {
|
|
105
87
|
url: options.privateRegistry,
|
|
106
88
|
scope: options.privateRegistryScope,
|
|
@@ -109,13 +91,17 @@ async function initCommand(options = {}) {
|
|
|
109
91
|
if (await shouldWriteAgentsMd(options)) await writeAgentsMd(kiciDir);
|
|
110
92
|
logger.info(pc.gray("Updating .gitignore"));
|
|
111
93
|
await updateGitignore(useVerdaccio);
|
|
112
|
-
if (process.stdout.isTTY &&
|
|
94
|
+
if (process.stdout.isTTY && !isCiEnvironment()) {
|
|
113
95
|
if (await findGitDir()) await offerHookInstallation(useVerdaccio);
|
|
114
96
|
}
|
|
115
97
|
logger.info(pc.green("\n✓ kici initialized successfully!\n"));
|
|
116
98
|
logger.info(pc.gray("Next steps:"));
|
|
117
99
|
logger.info(pc.gray(" 1. Edit workflows in .kici/workflows/"));
|
|
118
|
-
if (
|
|
100
|
+
if (mode.kind === "integrate") {
|
|
101
|
+
logger.info(pc.gray(" 2. Import your workspace packages from .kici/workflows/ (e.g. @your-scope/utils)"));
|
|
102
|
+
logger.info(pc.gray(" 3. Compile: kici compile"));
|
|
103
|
+
logger.info(pc.gray(" 4. Commit .kici/ to your repository\n"));
|
|
104
|
+
} else if (options.mjs || options.skipInstall) {
|
|
119
105
|
logger.info(pc.gray(" 2. Run your package manager install in .kici/ to generate a lockfile"));
|
|
120
106
|
logger.info(pc.gray(" 3. Preview matching: kici preview push"));
|
|
121
107
|
logger.info(pc.gray(" 4. Commit .kici/ to your repository\n"));
|
|
@@ -123,6 +109,23 @@ async function initCommand(options = {}) {
|
|
|
123
109
|
logger.info(pc.gray(" 2. Preview matching: kici preview push"));
|
|
124
110
|
logger.info(pc.gray(" 3. Commit .kici/ to your repository\n"));
|
|
125
111
|
}
|
|
112
|
+
if (shouldOfferFirstRun({
|
|
113
|
+
isTTY: Boolean(process.stdout.isTTY),
|
|
114
|
+
ci: isCiEnvironment(),
|
|
115
|
+
mjs: Boolean(options.mjs),
|
|
116
|
+
skipInstall: Boolean(options.skipInstall)
|
|
117
|
+
})) {
|
|
118
|
+
if (await confirm({
|
|
119
|
+
message: "Run it now? (kici run push --local)",
|
|
120
|
+
default: false
|
|
121
|
+
})) {
|
|
122
|
+
const { runRoutedCommand } = await import("./run-routed.js");
|
|
123
|
+
await runRoutedCommand({
|
|
124
|
+
event: "push",
|
|
125
|
+
local: true
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
}
|
|
126
129
|
return true;
|
|
127
130
|
} catch (error) {
|
|
128
131
|
const message = toErrorMessage(error);
|
|
@@ -153,7 +156,7 @@ async function checkExists(targetPath) {
|
|
|
153
156
|
* @returns Array of workflow names to include
|
|
154
157
|
*/
|
|
155
158
|
async function selectWorkflows() {
|
|
156
|
-
if (!process.stdout.isTTY ||
|
|
159
|
+
if (!process.stdout.isTTY || isCiEnvironment()) return ["hello-world", "pr-checks"];
|
|
157
160
|
const selected = await checkbox({
|
|
158
161
|
message: "Which workflows would you like to include?",
|
|
159
162
|
choices: [{
|
|
@@ -217,13 +220,133 @@ async function detectDevelopmentMode() {
|
|
|
217
220
|
*
|
|
218
221
|
* @param override - The raw `--package-manager` flag value, if provided.
|
|
219
222
|
*/
|
|
220
|
-
async function resolvePackageManager(override) {
|
|
223
|
+
async function resolvePackageManager(override, dir = process.cwd()) {
|
|
221
224
|
if (override) {
|
|
222
225
|
const parsed = parsePackageManager(override);
|
|
223
226
|
if (!parsed) throw new Error(`Invalid --package-manager value '${override}'. Expected one of: npm, pnpm, yarn.`);
|
|
224
227
|
return parsed;
|
|
225
228
|
}
|
|
226
|
-
return detectPackageManager(
|
|
229
|
+
return detectPackageManager(dir);
|
|
230
|
+
}
|
|
231
|
+
/** The @kici-dev scope → local Verdaccio registry line written in dev mode. */
|
|
232
|
+
const VERDACCIO_NPMRC = "@kici-dev:registry=http://verdaccio.local:4873\n";
|
|
233
|
+
/** Write .kici/tsconfig.json + the empty types/ dir (TypeScript mode only). */
|
|
234
|
+
async function writeTsConfigAndTypesDir(kiciDir) {
|
|
235
|
+
logger.info(pc.gray("Writing .kici/tsconfig.json"));
|
|
236
|
+
await writeFile(path.join(kiciDir, "tsconfig.json"), await generateTsConfig(), "utf-8");
|
|
237
|
+
await mkdir(path.join(kiciDir, "types"), { recursive: true });
|
|
238
|
+
logger.info(pc.gray("Created .kici/types/ for generated type declarations"));
|
|
239
|
+
}
|
|
240
|
+
/** Run the given package manager's install in `dir`, with pnpm's build-gate flag. */
|
|
241
|
+
async function runInstall(pm, dir) {
|
|
242
|
+
const [bin, action] = installCommand(pm);
|
|
243
|
+
const buildPolicyArgs = installBuildPolicyArgs(pm);
|
|
244
|
+
logger.info(pc.gray(`Running ${bin} ${action}...`));
|
|
245
|
+
await $`cd ${dir} && ${bin} ${action} ${buildPolicyArgs}`;
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Standalone dep wiring: write .kici/package.json (+ .kici/.npmrc and root
|
|
249
|
+
* .npmrc in dev mode), then tsconfig + isolated install in TypeScript mode.
|
|
250
|
+
*/
|
|
251
|
+
async function wireStandaloneDeps(kiciDir, devMode, options) {
|
|
252
|
+
logger.info(pc.gray("Writing .kici/package.json"));
|
|
253
|
+
await writeFile(path.join(kiciDir, "package.json"), generatePackageJson(devMode), "utf-8");
|
|
254
|
+
if (devMode) {
|
|
255
|
+
logger.info(pc.yellow("Pointing @kici-dev to local Verdaccio registry."));
|
|
256
|
+
await writeFile(path.join(kiciDir, ".npmrc"), VERDACCIO_NPMRC, "utf-8");
|
|
257
|
+
const rootNpmrc = path.resolve(".npmrc");
|
|
258
|
+
if (!await checkExists(rootNpmrc)) {
|
|
259
|
+
logger.info(pc.gray("Writing .npmrc (Verdaccio scope)"));
|
|
260
|
+
await writeFile(rootNpmrc, VERDACCIO_NPMRC, "utf-8");
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
if (!options.mjs) {
|
|
264
|
+
await writeTsConfigAndTypesDir(kiciDir);
|
|
265
|
+
if (!options.skipInstall) await runInstall(await resolvePackageManager(options.packageManager), kiciDir);
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Integrate dep wiring: NO .kici/package.json (its absence is the
|
|
270
|
+
* externally-managed signal the compiler honors). Add @kici-dev/sdk to the
|
|
271
|
+
* workspace-root manifest, write a root .npmrc in dev mode, write .kici/tsconfig
|
|
272
|
+
* in TypeScript mode, and run a root install.
|
|
273
|
+
*/
|
|
274
|
+
async function wireIntegrateDeps(kiciDir, workspaceRoot, devMode, options) {
|
|
275
|
+
await addSdkToRootManifest(workspaceRoot, devMode);
|
|
276
|
+
if (devMode) {
|
|
277
|
+
const rootNpmrc = path.join(workspaceRoot, ".npmrc");
|
|
278
|
+
if (!await checkExists(rootNpmrc)) {
|
|
279
|
+
logger.info(pc.gray("Writing workspace-root .npmrc (Verdaccio scope)"));
|
|
280
|
+
await writeFile(rootNpmrc, VERDACCIO_NPMRC, "utf-8");
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
if (!options.mjs) await writeTsConfigAndTypesDir(kiciDir);
|
|
284
|
+
if (!options.skipInstall) await runInstall(await resolvePackageManager(options.packageManager, workspaceRoot), workspaceRoot);
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Add @kici-dev/sdk to the workspace-root package.json devDependencies.
|
|
288
|
+
* Never clobbers an existing @kici-dev/sdk declaration (dev or prod dep).
|
|
289
|
+
*/
|
|
290
|
+
async function addSdkToRootManifest(workspaceRoot, devMode) {
|
|
291
|
+
const manifestPath = path.join(workspaceRoot, "package.json");
|
|
292
|
+
let raw;
|
|
293
|
+
try {
|
|
294
|
+
raw = await readFile(manifestPath, "utf-8");
|
|
295
|
+
} catch {
|
|
296
|
+
throw new Error(`Cannot integrate: no package.json at workspace root ${workspaceRoot}`);
|
|
297
|
+
}
|
|
298
|
+
const pkg = JSON.parse(raw);
|
|
299
|
+
const existing = pkg.devDependencies?.["@kici-dev/sdk"] ?? pkg.dependencies?.["@kici-dev/sdk"];
|
|
300
|
+
if (existing) {
|
|
301
|
+
logger.info(pc.gray(`@kici-dev/sdk already declared in ${manifestPath} (${existing}) — leaving as-is`));
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const range = sdkDependencyRange(devMode);
|
|
305
|
+
pkg.devDependencies = {
|
|
306
|
+
...pkg.devDependencies ?? {},
|
|
307
|
+
"@kici-dev/sdk": range
|
|
308
|
+
};
|
|
309
|
+
await writeFile(manifestPath, JSON.stringify(pkg, null, 2) + "\n", "utf-8");
|
|
310
|
+
logger.info(pc.gray(`Added @kici-dev/sdk (${range}) to ${manifestPath}`));
|
|
311
|
+
}
|
|
312
|
+
/**
|
|
313
|
+
* Decide standalone vs integrate. Flags win; otherwise, when a workspace is
|
|
314
|
+
* detected, prompt in interactive mode and default to standalone in CI/non-TTY.
|
|
315
|
+
* With no workspace and no --workspace, always standalone (unchanged behavior).
|
|
316
|
+
*/
|
|
317
|
+
async function resolveScaffoldMode(options) {
|
|
318
|
+
if (options.workspace && options.standalone) throw new Error("Cannot combine --workspace and --standalone.");
|
|
319
|
+
if (options.standalone) return { kind: "standalone" };
|
|
320
|
+
const ws = await detectWorkspaceRoot(process.cwd());
|
|
321
|
+
if (options.workspace) {
|
|
322
|
+
if (!ws) throw new Error("Cannot integrate: no pnpm/npm/yarn workspace found at or above the current directory. Run from a workspace root, or omit --workspace for a standalone .kici/.");
|
|
323
|
+
return {
|
|
324
|
+
kind: "integrate",
|
|
325
|
+
workspaceRoot: ws.root,
|
|
326
|
+
workspaceKind: ws.kind
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
if (!ws) return { kind: "standalone" };
|
|
330
|
+
if (!process.stdout.isTTY || isCiEnvironment()) return { kind: "standalone" };
|
|
331
|
+
return await promptScaffoldMode(ws.kind) === "integrate" ? {
|
|
332
|
+
kind: "integrate",
|
|
333
|
+
workspaceRoot: ws.root,
|
|
334
|
+
workspaceKind: ws.kind
|
|
335
|
+
} : { kind: "standalone" };
|
|
336
|
+
}
|
|
337
|
+
/** Interactive standalone-vs-integrate select. Defaults to standalone. */
|
|
338
|
+
async function promptScaffoldMode(kind) {
|
|
339
|
+
return await select({
|
|
340
|
+
message: `A ${kind} workspace was detected. How should the workflows be set up?`,
|
|
341
|
+
choices: [{
|
|
342
|
+
name: "Standalone — self-contained .kici/ with its own package.json",
|
|
343
|
+
value: "standalone"
|
|
344
|
+
}, {
|
|
345
|
+
name: "Integrate — join the workspace; workflows can import your other packages",
|
|
346
|
+
value: "integrate"
|
|
347
|
+
}],
|
|
348
|
+
default: "standalone"
|
|
349
|
+
});
|
|
227
350
|
}
|
|
228
351
|
/**
|
|
229
352
|
* Generate tsconfig.json content with optional TypeScript path mappings.
|
|
@@ -280,7 +403,7 @@ async function writePrivateRegistryScaffold(kiciDir, args) {
|
|
|
280
403
|
//
|
|
281
404
|
// The agent renders these into the .kici/.npmrc before running \`npm install\`.
|
|
282
405
|
// The token is resolved from the qualified secret reference at dispatch time
|
|
283
|
-
// (the orchestrator looks it up under the named
|
|
406
|
+
// (the orchestrator looks it up under the named context's scoped secrets).
|
|
284
407
|
import { workflow, job, step } from '@kici-dev/sdk';
|
|
285
408
|
|
|
286
409
|
export default workflow('private-registry-example', {
|
|
@@ -355,7 +478,7 @@ coverage/
|
|
|
355
478
|
*/
|
|
356
479
|
async function shouldWriteAgentsMd(options) {
|
|
357
480
|
if (options.noAgentsMd) return false;
|
|
358
|
-
if (!process.stdout.isTTY ||
|
|
481
|
+
if (!process.stdout.isTTY || isCiEnvironment()) return true;
|
|
359
482
|
return await confirm({
|
|
360
483
|
message: "Add LLM authoring context (.kici/AGENTS.md)?",
|
|
361
484
|
default: true
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import { devIdentityPublicJwkFile } from "../local-plane/plane-manager.js";
|
|
3
|
+
import fs from "node:fs";
|
|
4
|
+
import pc from "picocolors";
|
|
5
|
+
import { logger } from "@kici-dev/core";
|
|
6
|
+
//#region src/commands/local-trust-root.ts
|
|
7
|
+
/**
|
|
8
|
+
* `kici local trust-root <file>` — export the offline local dev plane's
|
|
9
|
+
* dev-signed identity trust root as a self-contained `{ issuer, jwks }` file.
|
|
10
|
+
*
|
|
11
|
+
* The plane's dev identity mints tokens with issuer `kici-local` (clearly
|
|
12
|
+
* non-prod). To self-test a dev-signed attestation offline, `kici
|
|
13
|
+
* verify-attestation --trust-root <file>` needs the plane's public JWKS + its
|
|
14
|
+
* issuer, supplied out-of-band. This command writes exactly the shape
|
|
15
|
+
* `verify-attestation`'s `--trust-root` file path consumes.
|
|
16
|
+
*
|
|
17
|
+
* The exported issuer is the fixed sentinel `kici-local` — it can NEVER
|
|
18
|
+
* masquerade as the prod issuer (`https://api.kici.dev`), so verifying the same
|
|
19
|
+
* bundle against the default (prod) trust root still rejects structurally.
|
|
20
|
+
*/
|
|
21
|
+
/** The plane's fixed non-prod dev-identity issuer. */
|
|
22
|
+
const KICI_LOCAL_ISSUER = "kici-local";
|
|
23
|
+
/**
|
|
24
|
+
* Write the local dev plane's `{ issuer, jwks }` trust root to `outFile`.
|
|
25
|
+
* Returns true on success.
|
|
26
|
+
*/
|
|
27
|
+
async function localTrustRootCommand(outFile) {
|
|
28
|
+
if (!outFile) {
|
|
29
|
+
logger.error(pc.red("Error: an output file path is required (`kici local trust-root <file>`)."));
|
|
30
|
+
return false;
|
|
31
|
+
}
|
|
32
|
+
const pubFile = devIdentityPublicJwkFile();
|
|
33
|
+
let pubJwk;
|
|
34
|
+
try {
|
|
35
|
+
pubJwk = JSON.parse(fs.readFileSync(pubFile, "utf-8"));
|
|
36
|
+
} catch {
|
|
37
|
+
logger.error(pc.red("Error: no dev-signed identity found for the local plane. Boot the plane first (`kici local up`) so it generates + publishes its public key."));
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
const trustRoot = {
|
|
41
|
+
issuer: KICI_LOCAL_ISSUER,
|
|
42
|
+
jwks: { keys: [pubJwk] }
|
|
43
|
+
};
|
|
44
|
+
fs.writeFileSync(outFile, JSON.stringify(trustRoot, null, 2) + "\n");
|
|
45
|
+
logger.info(`${pc.green("✓")} Wrote local dev trust root to ${pc.bold(outFile)} ` + pc.dim(`(issuer ${KICI_LOCAL_ISSUER} — NOT prod)`));
|
|
46
|
+
logger.info(pc.dim(`Verify a dev-signed bundle offline with:\n kici verify-attestation --bundle <bundle> --trust-root ${outFile}`));
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
//#endregion
|
|
50
|
+
export { localTrustRootCommand };
|
|
51
|
+
|
|
52
|
+
//# sourceMappingURL=local-trust-root.js.map
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* kici local commands
|
|
3
|
+
*
|
|
4
|
+
* Manage the warm, per-user local dev orchestrator plane: a real independent
|
|
5
|
+
* orchestrator plus a local Postgres (embedded, with a podman fallback) that
|
|
6
|
+
* `kici run --local` dispatches through. `up` boots or reuses the plane,
|
|
7
|
+
* `status` reports it plus the control commands, `down` stops it, and `logs`
|
|
8
|
+
* prints the orchestrator log path.
|
|
9
|
+
*/
|
|
10
|
+
import type { PlaneStatus, PlaneMode } from '../local-plane/plane-manager.js';
|
|
11
|
+
import type { PlaneState } from '../local-plane/plane-liveness.js';
|
|
12
|
+
/**
|
|
13
|
+
* Boot (or reuse) the local dev plane, honoring the durable attachment record.
|
|
14
|
+
*
|
|
15
|
+
* Routes through the same `resolvePlaneForRun` resolver `kici run --local` uses,
|
|
16
|
+
* so the two commands share one plane-resolution path and never diverge: an
|
|
17
|
+
* attached + reachable plane comes up hybrid, an attached-but-unreachable plane
|
|
18
|
+
* falls back to offline with a loud banner, and a never-attached plane comes up
|
|
19
|
+
* offline. `--offline` forces the independent boot (without clearing the durable
|
|
20
|
+
* attachment record — only `detach` does that); `--connected` requires an
|
|
21
|
+
* attached, reachable Platform.
|
|
22
|
+
*/
|
|
23
|
+
export declare function localUpCommand(flags?: {
|
|
24
|
+
offline?: boolean;
|
|
25
|
+
connected?: boolean;
|
|
26
|
+
}): Promise<boolean>;
|
|
27
|
+
/**
|
|
28
|
+
* The machine-readable projection of a plane status.
|
|
29
|
+
*
|
|
30
|
+
* An explicit allow-list, NOT `JSON.stringify(status)`. `PlaneStatus` carries
|
|
31
|
+
* `adminToken` — the bootstrap admin token the CLI presents to the plane's
|
|
32
|
+
* admin API — so serializing the whole object would publish it on stdout, and
|
|
33
|
+
* from there into any consumer's logs. `attachment` is omitted for the same
|
|
34
|
+
* reason in miniature: no consumer needs it, and a field that is never emitted
|
|
35
|
+
* cannot leak a field added to it later.
|
|
36
|
+
*/
|
|
37
|
+
export interface LocalStatusJson {
|
|
38
|
+
state: PlaneState;
|
|
39
|
+
running: boolean;
|
|
40
|
+
pid: number | null;
|
|
41
|
+
port: number | null;
|
|
42
|
+
url: string | null;
|
|
43
|
+
pgKind: 'embedded' | 'podman' | null;
|
|
44
|
+
stampVersion: number | null;
|
|
45
|
+
mode: PlaneMode | null;
|
|
46
|
+
}
|
|
47
|
+
/** Project a PlaneStatus onto the published JSON shape, absent fields as null. */
|
|
48
|
+
export declare function toLocalStatusJson(status: PlaneStatus): LocalStatusJson;
|
|
49
|
+
/** Show the local dev plane status and its control commands. */
|
|
50
|
+
export declare function localStatusCommand(options?: {
|
|
51
|
+
json?: boolean;
|
|
52
|
+
}): Promise<boolean>;
|
|
53
|
+
/** Stop the local dev plane, reporting success only once the port is released. */
|
|
54
|
+
export declare function localDownCommand(): Promise<boolean>;
|
|
55
|
+
/** Print the local dev plane orchestrator log path. */
|
|
56
|
+
export declare function localLogsCommand(): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Attach the local dev plane to the hosted Platform so `kici run --local` uses
|
|
59
|
+
* real Platform-minted OIDC + attestation. Mints an org-scoped orchestrator key
|
|
60
|
+
* with the logged-in PAT, then (re)boots the plane hybrid.
|
|
61
|
+
*/
|
|
62
|
+
export declare function localAttachCommand(): Promise<boolean>;
|
|
63
|
+
/** Detach the local dev plane from the Platform and reboot it offline (independent). */
|
|
64
|
+
export declare function localDetachCommand(): Promise<boolean>;
|
|
65
|
+
//# sourceMappingURL=local.d.ts.map
|
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
import "../rolldown-runtime-ClRpJifh.js";
|
|
2
|
+
import { loadGlobalConfig } from "../remote/config.js";
|
|
3
|
+
import { attachPlane, detachPlane, planeDown, planeLogPath, planeStatus } from "../local-plane/plane-manager.js";
|
|
4
|
+
import { resolvePlaneForRun } from "../local-plane/resolve-plane.js";
|
|
5
|
+
import pc from "picocolors";
|
|
6
|
+
import { toErrorMessage } from "@kici-dev/core";
|
|
7
|
+
//#region src/commands/local.ts
|
|
8
|
+
/**
|
|
9
|
+
* kici local commands
|
|
10
|
+
*
|
|
11
|
+
* Manage the warm, per-user local dev orchestrator plane: a real independent
|
|
12
|
+
* orchestrator plus a local Postgres (embedded, with a podman fallback) that
|
|
13
|
+
* `kici run --local` dispatches through. `up` boots or reuses the plane,
|
|
14
|
+
* `status` reports it plus the control commands, `down` stops it, and `logs`
|
|
15
|
+
* prints the orchestrator log path.
|
|
16
|
+
*/
|
|
17
|
+
/** Print the control commands a user needs once the plane is running. */
|
|
18
|
+
function printControlHints() {
|
|
19
|
+
console.log("");
|
|
20
|
+
console.log(pc.dim("Control commands:"));
|
|
21
|
+
console.log(` ${pc.cyan("kici local status")} Show plane status`);
|
|
22
|
+
console.log(` ${pc.cyan("kici local logs")} Print the orchestrator log path`);
|
|
23
|
+
console.log(` ${pc.cyan("kici local down")} Stop the plane`);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Boot (or reuse) the local dev plane, honoring the durable attachment record.
|
|
27
|
+
*
|
|
28
|
+
* Routes through the same `resolvePlaneForRun` resolver `kici run --local` uses,
|
|
29
|
+
* so the two commands share one plane-resolution path and never diverge: an
|
|
30
|
+
* attached + reachable plane comes up hybrid, an attached-but-unreachable plane
|
|
31
|
+
* falls back to offline with a loud banner, and a never-attached plane comes up
|
|
32
|
+
* offline. `--offline` forces the independent boot (without clearing the durable
|
|
33
|
+
* attachment record — only `detach` does that); `--connected` requires an
|
|
34
|
+
* attached, reachable Platform.
|
|
35
|
+
*/
|
|
36
|
+
async function localUpCommand(flags = {}) {
|
|
37
|
+
console.log(pc.dim("Starting the local dev plane…"));
|
|
38
|
+
const resolved = await resolvePlaneForRun({
|
|
39
|
+
offline: flags.offline ?? false,
|
|
40
|
+
connected: flags.connected ?? false
|
|
41
|
+
});
|
|
42
|
+
if ("error" in resolved) {
|
|
43
|
+
console.log(pc.red(`✗ ${resolved.error}`));
|
|
44
|
+
return false;
|
|
45
|
+
}
|
|
46
|
+
const { plane } = resolved;
|
|
47
|
+
const url = plane.url ?? "";
|
|
48
|
+
const pg = pc.dim(`(postgres: ${plane.pgKind ?? "unknown"})`);
|
|
49
|
+
if (resolved.kind === "attached") console.log(pc.green("✓") + ` Local dev plane running (hybrid → Platform, org: ${pc.bold(resolved.orgId)}) at ${pc.bold(url)} ` + pg);
|
|
50
|
+
else {
|
|
51
|
+
console.log(pc.green("✓") + ` Local dev plane running (independent/offline) at ${pc.bold(url)} ` + pg);
|
|
52
|
+
if (resolved.kind === "fallback") console.log(pc.yellow(` ⚠ Attached, but booted offline: ${resolved.reason}`));
|
|
53
|
+
}
|
|
54
|
+
printControlHints();
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Render the branch for a plane port held by a process that is not a KiCI plane
|
|
59
|
+
* orchestrator. Kept apart from the not-serving branch because `kici local down`
|
|
60
|
+
* deliberately refuses to signal such a holder, so pointing at it here would
|
|
61
|
+
* send the operator to a command that cannot act.
|
|
62
|
+
*/
|
|
63
|
+
function printForeignHolder(status) {
|
|
64
|
+
console.log(pc.yellow("⚠") + ` Port ${pc.bold(String(status.port))} is held by a process that is not a KiCI plane orchestrator.`);
|
|
65
|
+
console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
|
|
66
|
+
console.log("The local dev plane cannot start while that process holds the port.");
|
|
67
|
+
console.log(`Stop it yourself, or point the plane elsewhere with ${pc.cyan("KICI_LOCAL_ORCH_PORT")}.`);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Render the branch for a plane port held by a KiCI plane orchestrator that is
|
|
71
|
+
* not serving this config dir: our own stamped orchestrator failing its
|
|
72
|
+
* readiness probe, or a plane no stamp here accounts for. Split out of
|
|
73
|
+
* `localStatusCommand` so each branch stays readable.
|
|
74
|
+
*
|
|
75
|
+
* The two get different headlines because only one of them has been probed:
|
|
76
|
+
* readiness is checked for a plane we stamped, so `unready` is a measurement,
|
|
77
|
+
* while a plane we did not stamp is only known to be holding the port.
|
|
78
|
+
*/
|
|
79
|
+
function printNotServing(status) {
|
|
80
|
+
if (status.state === "foreign-kici") {
|
|
81
|
+
console.log(pc.yellow("⚠") + ` Port ${pc.bold(String(status.port))} is held by a KiCI plane orchestrator this config dir did not start.`);
|
|
82
|
+
console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
|
|
83
|
+
console.log(pc.dim(" owner: another KiCI plane — no stamp in this config dir"));
|
|
84
|
+
console.log(`Stop it with ${pc.cyan("kici local down")}.`);
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
console.log(pc.yellow("⚠") + ` Local dev plane is running but NOT ready at ${pc.bold(status.url ?? "")}`);
|
|
88
|
+
console.log(pc.dim(` port: ${status.port}`));
|
|
89
|
+
console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
|
|
90
|
+
if (status.checks && Object.keys(status.checks).length > 0) {
|
|
91
|
+
const rendered = Object.entries(status.checks).map(([name, ok]) => `${name}=${ok}`).join(" ");
|
|
92
|
+
console.log(pc.dim(` checks: ${rendered}`));
|
|
93
|
+
}
|
|
94
|
+
console.log(`Stop it with ${pc.cyan("kici local down")}.`);
|
|
95
|
+
}
|
|
96
|
+
/** Project a PlaneStatus onto the published JSON shape, absent fields as null. */
|
|
97
|
+
function toLocalStatusJson(status) {
|
|
98
|
+
return {
|
|
99
|
+
state: status.state,
|
|
100
|
+
running: status.running,
|
|
101
|
+
pid: status.pid ?? null,
|
|
102
|
+
port: status.port ?? null,
|
|
103
|
+
url: status.url ?? null,
|
|
104
|
+
pgKind: status.pgKind ?? null,
|
|
105
|
+
stampVersion: status.stampVersion ?? null,
|
|
106
|
+
mode: status.mode ?? null
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/** Show the local dev plane status and its control commands. */
|
|
110
|
+
async function localStatusCommand(options) {
|
|
111
|
+
const status = await planeStatus();
|
|
112
|
+
if (options?.json) {
|
|
113
|
+
console.log(JSON.stringify(toLocalStatusJson(status)));
|
|
114
|
+
return true;
|
|
115
|
+
}
|
|
116
|
+
if (status.state === "stopped") {
|
|
117
|
+
console.log(pc.yellow("Local dev plane is not running."));
|
|
118
|
+
console.log(`Start it with ${pc.cyan("kici local up")}.`);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
if (status.state === "foreign-unknown") {
|
|
122
|
+
printForeignHolder(status);
|
|
123
|
+
return true;
|
|
124
|
+
}
|
|
125
|
+
if (status.state !== "ready") {
|
|
126
|
+
printNotServing(status);
|
|
127
|
+
return true;
|
|
128
|
+
}
|
|
129
|
+
console.log(pc.green("✓") + ` Local dev plane running at ${pc.bold(status.url ?? "")}`);
|
|
130
|
+
console.log(pc.dim(` port: ${status.port}`));
|
|
131
|
+
console.log(pc.dim(` pid: ${status.pid ?? "unknown"}`));
|
|
132
|
+
console.log(pc.dim(` postgres: ${status.pgKind ?? "unknown"}`));
|
|
133
|
+
if (status.mode === "hybrid" && status.attachment) console.log(pc.dim(` attached: hybrid → Platform (org: ${status.attachment.orgId})`));
|
|
134
|
+
else console.log(pc.dim(" attached: no (independent/offline)"));
|
|
135
|
+
printControlHints();
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
/** Stop the local dev plane, reporting success only once the port is released. */
|
|
139
|
+
async function localDownCommand() {
|
|
140
|
+
console.log(pc.dim("Stopping the local dev plane…"));
|
|
141
|
+
const result = await planeDown();
|
|
142
|
+
if (!result.stopped) {
|
|
143
|
+
console.error(pc.red(`✗ Local dev plane NOT stopped: ${result.reason ?? "port still held"}`));
|
|
144
|
+
if (result.holderPid !== void 0) console.error(pc.dim(` holder pid: ${result.holderPid} port: ${result.port}`));
|
|
145
|
+
return false;
|
|
146
|
+
}
|
|
147
|
+
console.log(pc.green("✓") + " Local dev plane stopped.");
|
|
148
|
+
return true;
|
|
149
|
+
}
|
|
150
|
+
/** Print the local dev plane orchestrator log path. */
|
|
151
|
+
async function localLogsCommand() {
|
|
152
|
+
console.log(planeLogPath());
|
|
153
|
+
return true;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Attach the local dev plane to the hosted Platform so `kici run --local` uses
|
|
157
|
+
* real Platform-minted OIDC + attestation. Mints an org-scoped orchestrator key
|
|
158
|
+
* with the logged-in PAT, then (re)boots the plane hybrid.
|
|
159
|
+
*/
|
|
160
|
+
async function localAttachCommand() {
|
|
161
|
+
const config = await loadGlobalConfig();
|
|
162
|
+
if (!config.pat) {
|
|
163
|
+
console.error(pc.red("Not authenticated. Run `kici login` first."));
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
if (!config.platformEndpoint) {
|
|
167
|
+
console.error(pc.red("No Platform endpoint configured. Run `kici login` first."));
|
|
168
|
+
return false;
|
|
169
|
+
}
|
|
170
|
+
const orgId = config.activeOrgId;
|
|
171
|
+
if (!orgId) {
|
|
172
|
+
console.error(pc.red("No active organization. Select one with `kici org use <org>` before attaching."));
|
|
173
|
+
return false;
|
|
174
|
+
}
|
|
175
|
+
try {
|
|
176
|
+
console.log(pc.dim("Attaching the local dev plane to the Platform…"));
|
|
177
|
+
const status = await attachPlane({
|
|
178
|
+
apiBase: config.platformEndpoint,
|
|
179
|
+
pat: config.pat,
|
|
180
|
+
orgId
|
|
181
|
+
});
|
|
182
|
+
console.log(pc.green("✓") + ` Local dev plane attached (hybrid) at ${pc.bold(status.url ?? "")} ` + pc.dim(`(org: ${orgId})`));
|
|
183
|
+
console.log(pc.dim("`kici run --local` now uses real Platform OIDC + attestation. Detach: ") + pc.cyan("kici local detach"));
|
|
184
|
+
return true;
|
|
185
|
+
} catch (err) {
|
|
186
|
+
console.error(pc.red(`Attach failed: ${toErrorMessage(err)}`));
|
|
187
|
+
return false;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/** Detach the local dev plane from the Platform and reboot it offline (independent). */
|
|
191
|
+
async function localDetachCommand() {
|
|
192
|
+
const config = await loadGlobalConfig();
|
|
193
|
+
try {
|
|
194
|
+
console.log(pc.dim("Detaching the local dev plane…"));
|
|
195
|
+
await detachPlane({ pat: config.pat });
|
|
196
|
+
console.log(pc.green("✓") + " Local dev plane detached (independent/offline).");
|
|
197
|
+
return true;
|
|
198
|
+
} catch (err) {
|
|
199
|
+
console.error(pc.red(`Detach failed: ${toErrorMessage(err)}`));
|
|
200
|
+
return false;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
//#endregion
|
|
204
|
+
export { localAttachCommand, localDetachCommand, localDownCommand, localLogsCommand, localStatusCommand, localUpCommand, toLocalStatusJson };
|
|
205
|
+
|
|
206
|
+
//# sourceMappingURL=local.js.map
|