@kya-os/cli 1.8.1 → 1.8.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/commands/agent.d.ts +35 -0
- package/dist/commands/agent.d.ts.map +1 -0
- package/dist/commands/agent.js +321 -0
- package/dist/commands/agent.js.map +1 -0
- package/dist/commands/build.js +2 -2
- package/dist/commands/build.js.map +1 -1
- package/dist/commands/check.js +3 -3
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/checkpoint-init.d.ts +1 -1
- package/dist/commands/checkpoint-init.d.ts.map +1 -1
- package/dist/commands/checkpoint-init.js +8 -41
- package/dist/commands/checkpoint-init.js.map +1 -1
- package/dist/commands/claim.js +2 -2
- package/dist/commands/claim.js.map +1 -1
- package/dist/commands/dco.d.ts +59 -0
- package/dist/commands/dco.d.ts.map +1 -1
- package/dist/commands/dco.js +280 -5
- package/dist/commands/dco.js.map +1 -1
- package/dist/commands/dev.js +1 -1
- package/dist/commands/dev.js.map +1 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -24
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/env.js +6 -6
- package/dist/commands/env.js.map +1 -1
- package/dist/commands/identity.js +3 -3
- package/dist/commands/identity.js.map +1 -1
- package/dist/commands/init-stages.d.ts +141 -0
- package/dist/commands/init-stages.d.ts.map +1 -0
- package/dist/commands/init-stages.js +684 -0
- package/dist/commands/init-stages.js.map +1 -0
- package/dist/commands/init.d.ts +46 -16
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +229 -279
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/orchestrator.d.ts +18 -0
- package/dist/commands/orchestrator.d.ts.map +1 -0
- package/dist/commands/orchestrator.js +251 -0
- package/dist/commands/orchestrator.js.map +1 -0
- package/dist/commands/register.d.ts +1 -1
- package/dist/commands/register.d.ts.map +1 -1
- package/dist/commands/register.js +35 -7
- package/dist/commands/register.js.map +1 -1
- package/dist/commands/review.d.ts +48 -0
- package/dist/commands/review.d.ts.map +1 -0
- package/dist/commands/review.js +220 -0
- package/dist/commands/review.js.map +1 -0
- package/dist/commands/rotate.js +4 -4
- package/dist/commands/rotate.js.map +1 -1
- package/dist/commands/score.d.ts +15 -0
- package/dist/commands/score.d.ts.map +1 -0
- package/dist/commands/score.js +471 -0
- package/dist/commands/score.js.map +1 -0
- package/dist/commands/start.js +3 -3
- package/dist/commands/start.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/verify.js +6 -6
- package/dist/commands/verify.js.map +1 -1
- package/dist/dco.d.ts +4 -0
- package/dist/dco.d.ts.map +1 -0
- package/dist/dco.js +23 -0
- package/dist/dco.js.map +1 -0
- package/dist/index.js +52 -9
- package/dist/orchestrator/daemon.d.ts +137 -0
- package/dist/orchestrator/daemon.d.ts.map +1 -0
- package/dist/orchestrator/daemon.js +242 -0
- package/dist/orchestrator/daemon.js.map +1 -0
- package/dist/orchestrator/db/dispatches.d.ts +108 -0
- package/dist/orchestrator/db/dispatches.d.ts.map +1 -0
- package/dist/orchestrator/db/dispatches.js +122 -0
- package/dist/orchestrator/db/dispatches.js.map +1 -0
- package/dist/orchestrator/db/index.d.ts +50 -0
- package/dist/orchestrator/db/index.d.ts.map +1 -0
- package/dist/orchestrator/db/index.js +116 -0
- package/dist/orchestrator/db/index.js.map +1 -0
- package/dist/orchestrator/db/journal.d.ts +93 -0
- package/dist/orchestrator/db/journal.d.ts.map +1 -0
- package/dist/orchestrator/db/journal.js +91 -0
- package/dist/orchestrator/db/journal.js.map +1 -0
- package/dist/orchestrator/db/liveness.d.ts +97 -0
- package/dist/orchestrator/db/liveness.d.ts.map +1 -0
- package/dist/orchestrator/db/liveness.js +105 -0
- package/dist/orchestrator/db/liveness.js.map +1 -0
- package/dist/orchestrator/db/mission.d.ts +78 -0
- package/dist/orchestrator/db/mission.d.ts.map +1 -0
- package/dist/orchestrator/db/mission.js +99 -0
- package/dist/orchestrator/db/mission.js.map +1 -0
- package/dist/orchestrator/db/schema.d.ts +14 -0
- package/dist/orchestrator/db/schema.d.ts.map +1 -0
- package/dist/orchestrator/db/schema.js +169 -0
- package/dist/orchestrator/db/schema.js.map +1 -0
- package/dist/orchestrator/db/tickets.d.ts +147 -0
- package/dist/orchestrator/db/tickets.d.ts.map +1 -0
- package/dist/orchestrator/db/tickets.js +238 -0
- package/dist/orchestrator/db/tickets.js.map +1 -0
- package/dist/orchestrator/db/verdicts.d.ts +187 -0
- package/dist/orchestrator/db/verdicts.d.ts.map +1 -0
- package/dist/orchestrator/db/verdicts.js +197 -0
- package/dist/orchestrator/db/verdicts.js.map +1 -0
- package/dist/orchestrator/events.d.ts +69 -0
- package/dist/orchestrator/events.d.ts.map +1 -0
- package/dist/orchestrator/events.js +20 -0
- package/dist/orchestrator/events.js.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts +159 -0
- package/dist/orchestrator/github-credential-anchor-sender.d.ts.map +1 -0
- package/dist/orchestrator/github-credential-anchor-sender.js +313 -0
- package/dist/orchestrator/github-credential-anchor-sender.js.map +1 -0
- package/dist/orchestrator/hub-dispatch.d.ts +120 -0
- package/dist/orchestrator/hub-dispatch.d.ts.map +1 -0
- package/dist/orchestrator/hub-dispatch.js +257 -0
- package/dist/orchestrator/hub-dispatch.js.map +1 -0
- package/dist/orchestrator/hub-observer.d.ts +201 -0
- package/dist/orchestrator/hub-observer.d.ts.map +1 -0
- package/dist/orchestrator/hub-observer.js +474 -0
- package/dist/orchestrator/hub-observer.js.map +1 -0
- package/dist/orchestrator/journal-writer.d.ts +80 -0
- package/dist/orchestrator/journal-writer.d.ts.map +1 -0
- package/dist/orchestrator/journal-writer.js +113 -0
- package/dist/orchestrator/journal-writer.js.map +1 -0
- package/dist/orchestrator/mcp/server.d.ts +136 -0
- package/dist/orchestrator/mcp/server.d.ts.map +1 -0
- package/dist/orchestrator/mcp/server.js +582 -0
- package/dist/orchestrator/mcp/server.js.map +1 -0
- package/dist/orchestrator/mcp/stdio.d.ts +22 -0
- package/dist/orchestrator/mcp/stdio.d.ts.map +1 -0
- package/dist/orchestrator/mcp/stdio.js +51 -0
- package/dist/orchestrator/mcp/stdio.js.map +1 -0
- package/dist/orchestrator/review.d.ts +131 -0
- package/dist/orchestrator/review.d.ts.map +1 -0
- package/dist/orchestrator/review.js +322 -0
- package/dist/orchestrator/review.js.map +1 -0
- package/dist/tui/app.d.ts +33 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +71 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/components.d.ts +110 -0
- package/dist/tui/components.d.ts.map +1 -0
- package/dist/tui/components.js +118 -0
- package/dist/tui/components.js.map +1 -0
- package/dist/tui/index.d.ts +30 -0
- package/dist/tui/index.d.ts.map +1 -0
- package/dist/tui/index.js +95 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/keymap.d.ts +33 -0
- package/dist/tui/keymap.d.ts.map +1 -0
- package/dist/tui/keymap.js +49 -0
- package/dist/tui/keymap.js.map +1 -0
- package/dist/tui/nav.d.ts +29 -0
- package/dist/tui/nav.d.ts.map +1 -0
- package/dist/tui/nav.js +39 -0
- package/dist/tui/nav.js.map +1 -0
- package/dist/tui/sanitize.d.ts +25 -0
- package/dist/tui/sanitize.d.ts.map +1 -0
- package/dist/tui/sanitize.js +36 -0
- package/dist/tui/sanitize.js.map +1 -0
- package/dist/tui/theme.d.ts +32 -0
- package/dist/tui/theme.d.ts.map +1 -0
- package/dist/tui/theme.js +63 -0
- package/dist/tui/theme.js.map +1 -0
- package/dist/tui/views/agents.d.ts +67 -0
- package/dist/tui/views/agents.d.ts.map +1 -0
- package/dist/tui/views/agents.js +231 -0
- package/dist/tui/views/agents.js.map +1 -0
- package/dist/tui/views/index.d.ts +93 -0
- package/dist/tui/views/index.d.ts.map +1 -0
- package/dist/tui/views/index.js +150 -0
- package/dist/tui/views/index.js.map +1 -0
- package/dist/tui/views/registry.d.ts +22 -0
- package/dist/tui/views/registry.d.ts.map +1 -0
- package/dist/tui/views/registry.js +110 -0
- package/dist/tui/views/registry.js.map +1 -0
- package/dist/utils/agent/backoff.d.ts +31 -0
- package/dist/utils/agent/backoff.d.ts.map +1 -0
- package/dist/utils/agent/backoff.js +51 -0
- package/dist/utils/agent/backoff.js.map +1 -0
- package/dist/utils/agent/markers.d.ts +87 -0
- package/dist/utils/agent/markers.d.ts.map +1 -0
- package/dist/utils/agent/markers.js +147 -0
- package/dist/utils/agent/markers.js.map +1 -0
- package/dist/utils/agent/review.d.ts +67 -0
- package/dist/utils/agent/review.d.ts.map +1 -0
- package/dist/utils/agent/review.js +305 -0
- package/dist/utils/agent/review.js.map +1 -0
- package/dist/utils/agent/spawn-agent.d.ts +117 -0
- package/dist/utils/agent/spawn-agent.d.ts.map +1 -0
- package/dist/utils/agent/spawn-agent.js +177 -0
- package/dist/utils/agent/spawn-agent.js.map +1 -0
- package/dist/utils/agent/task.d.ts +101 -0
- package/dist/utils/agent/task.d.ts.map +1 -0
- package/dist/utils/agent/task.js +357 -0
- package/dist/utils/agent/task.js.map +1 -0
- package/dist/utils/agent/verify.d.ts +47 -0
- package/dist/utils/agent/verify.d.ts.map +1 -0
- package/dist/utils/agent/verify.js +144 -0
- package/dist/utils/agent/verify.js.map +1 -0
- package/dist/utils/agent-detector.d.ts +48 -0
- package/dist/utils/agent-detector.d.ts.map +1 -0
- package/dist/utils/agent-detector.js +74 -0
- package/dist/utils/agent-detector.js.map +1 -0
- package/dist/utils/agent-profile-stage.d.ts +70 -0
- package/dist/utils/agent-profile-stage.d.ts.map +1 -0
- package/dist/utils/agent-profile-stage.js +153 -0
- package/dist/utils/agent-profile-stage.js.map +1 -0
- package/dist/utils/agent-profiles.d.ts +27 -0
- package/dist/utils/agent-profiles.d.ts.map +1 -0
- package/dist/utils/agent-profiles.js +61 -0
- package/dist/utils/agent-profiles.js.map +1 -0
- package/dist/utils/checkpoint-api.d.ts +1 -1
- package/dist/utils/checkpoint-api.js +1 -1
- package/dist/utils/checkpoint-env.d.ts +1 -1
- package/dist/utils/checkpoint-env.js +2 -2
- package/dist/utils/checkpoint-env.js.map +1 -1
- package/dist/utils/checkpoint-scaffold.d.ts +1 -1
- package/dist/utils/checkpoint-scaffold.js +1 -1
- package/dist/utils/cli-kit/browser.d.ts +24 -0
- package/dist/utils/cli-kit/browser.d.ts.map +1 -0
- package/dist/utils/cli-kit/browser.js +58 -0
- package/dist/utils/cli-kit/browser.js.map +1 -0
- package/dist/utils/cli-kit/claim-polling.d.ts +18 -0
- package/dist/utils/cli-kit/claim-polling.d.ts.map +1 -0
- package/dist/utils/{claim-polling.js → cli-kit/claim-polling.js} +19 -26
- package/dist/utils/cli-kit/claim-polling.js.map +1 -0
- package/dist/utils/cli-kit/diagnostics.d.ts +9 -0
- package/dist/utils/cli-kit/diagnostics.d.ts.map +1 -0
- package/dist/utils/cli-kit/diagnostics.js +11 -0
- package/dist/utils/cli-kit/diagnostics.js.map +1 -0
- package/dist/utils/cli-kit/fs-safe.d.ts +14 -0
- package/dist/utils/cli-kit/fs-safe.d.ts.map +1 -0
- package/dist/utils/cli-kit/fs-safe.js +20 -0
- package/dist/utils/cli-kit/fs-safe.js.map +1 -0
- package/dist/utils/cli-kit/index.d.ts +15 -0
- package/dist/utils/cli-kit/index.d.ts.map +1 -0
- package/dist/utils/cli-kit/index.js +10 -0
- package/dist/utils/cli-kit/index.js.map +1 -0
- package/dist/utils/cli-kit/json-file.d.ts +21 -0
- package/dist/utils/cli-kit/json-file.d.ts.map +1 -0
- package/dist/utils/cli-kit/json-file.js +51 -0
- package/dist/utils/cli-kit/json-file.js.map +1 -0
- package/dist/utils/cli-kit/marker-block.d.ts +26 -0
- package/dist/utils/cli-kit/marker-block.d.ts.map +1 -0
- package/dist/utils/cli-kit/marker-block.js +61 -0
- package/dist/utils/cli-kit/marker-block.js.map +1 -0
- package/dist/utils/cli-kit/paths.d.ts +15 -0
- package/dist/utils/cli-kit/paths.d.ts.map +1 -0
- package/dist/utils/cli-kit/paths.js +21 -0
- package/dist/utils/cli-kit/paths.js.map +1 -0
- package/dist/utils/cli-kit/secure-storage.d.ts +14 -0
- package/dist/utils/cli-kit/secure-storage.d.ts.map +1 -0
- package/dist/utils/cli-kit/secure-storage.js +20 -0
- package/dist/utils/cli-kit/secure-storage.js.map +1 -0
- package/dist/utils/cli-kit/step-report.d.ts +16 -0
- package/dist/utils/cli-kit/step-report.d.ts.map +1 -0
- package/dist/utils/cli-kit/step-report.js +36 -0
- package/dist/utils/cli-kit/step-report.js.map +1 -0
- package/dist/utils/dco/agent-metadata.d.ts +1 -1
- package/dist/utils/dco/agent-metadata.js +1 -1
- package/dist/utils/dco/agent-metadata.js.map +1 -1
- package/dist/utils/dco/claude-config.d.ts +18 -14
- package/dist/utils/dco/claude-config.d.ts.map +1 -1
- package/dist/utils/dco/claude-config.js +31 -97
- package/dist/utils/dco/claude-config.js.map +1 -1
- package/dist/utils/dco/dispatch.d.ts +134 -0
- package/dist/utils/dco/dispatch.d.ts.map +1 -0
- package/dist/utils/dco/dispatch.js +399 -0
- package/dist/utils/dco/dispatch.js.map +1 -0
- package/dist/utils/dco/fix.d.ts +122 -0
- package/dist/utils/dco/fix.d.ts.map +1 -0
- package/dist/utils/dco/fix.js +560 -0
- package/dist/utils/dco/fix.js.map +1 -0
- package/dist/utils/dco/git-config.d.ts.map +1 -1
- package/dist/utils/dco/git-config.js +5 -3
- package/dist/utils/dco/git-config.js.map +1 -1
- package/dist/utils/dco/github.d.ts +101 -0
- package/dist/utils/dco/github.d.ts.map +1 -1
- package/dist/utils/dco/github.js +133 -0
- package/dist/utils/dco/github.js.map +1 -1
- package/dist/utils/dco/paths.d.ts +1 -8
- package/dist/utils/dco/paths.d.ts.map +1 -1
- package/dist/utils/dco/paths.js +3 -12
- package/dist/utils/dco/paths.js.map +1 -1
- package/dist/utils/dco/render.d.ts +1 -1
- package/dist/utils/dco/render.d.ts.map +1 -1
- package/dist/utils/dco/render.js +4 -21
- package/dist/utils/dco/render.js.map +1 -1
- package/dist/utils/dco/resolve-agent.d.ts +54 -0
- package/dist/utils/dco/resolve-agent.d.ts.map +1 -0
- package/dist/utils/dco/resolve-agent.js +164 -0
- package/dist/utils/dco/resolve-agent.js.map +1 -0
- package/dist/utils/dco/setup.d.ts +10 -7
- package/dist/utils/dco/setup.d.ts.map +1 -1
- package/dist/utils/dco/setup.js +264 -200
- package/dist/utils/dco/setup.js.map +1 -1
- package/dist/utils/dco/signing-key-writer.d.ts +40 -0
- package/dist/utils/dco/signing-key-writer.d.ts.map +1 -0
- package/dist/utils/dco/signing-key-writer.js +76 -0
- package/dist/utils/dco/signing-key-writer.js.map +1 -0
- package/dist/utils/dco/ssh-key.d.ts +50 -0
- package/dist/utils/dco/ssh-key.d.ts.map +1 -1
- package/dist/utils/dco/ssh-key.js +129 -8
- package/dist/utils/dco/ssh-key.js.map +1 -1
- package/dist/utils/dco/status.d.ts +1 -1
- package/dist/utils/dco/status.d.ts.map +1 -1
- package/dist/utils/dco/status.js +3 -3
- package/dist/utils/dco/status.js.map +1 -1
- package/dist/utils/dco/verify.d.ts +170 -0
- package/dist/utils/dco/verify.d.ts.map +1 -0
- package/dist/utils/dco/verify.js +550 -0
- package/dist/utils/dco/verify.js.map +1 -0
- package/dist/utils/dependency-installer.d.ts +37 -0
- package/dist/utils/dependency-installer.d.ts.map +1 -0
- package/dist/utils/dependency-installer.js +32 -0
- package/dist/utils/dependency-installer.js.map +1 -0
- package/dist/utils/github-credential-stage.d.ts +87 -0
- package/dist/utils/github-credential-stage.d.ts.map +1 -0
- package/dist/utils/github-credential-stage.js +168 -0
- package/dist/utils/github-credential-stage.js.map +1 -0
- package/dist/utils/github-credential.d.ts +160 -0
- package/dist/utils/github-credential.d.ts.map +1 -0
- package/dist/utils/github-credential.js +308 -0
- package/dist/utils/github-credential.js.map +1 -0
- package/dist/utils/gitignore.d.ts +17 -0
- package/dist/utils/gitignore.d.ts.map +1 -0
- package/dist/utils/gitignore.js +40 -0
- package/dist/utils/gitignore.js.map +1 -0
- package/dist/utils/hub-config.d.ts +21 -0
- package/dist/utils/hub-config.d.ts.map +1 -0
- package/dist/utils/hub-config.js +28 -0
- package/dist/utils/hub-config.js.map +1 -0
- package/dist/utils/identity-heal.d.ts +16 -0
- package/dist/utils/identity-heal.d.ts.map +1 -0
- package/dist/utils/identity-heal.js +37 -0
- package/dist/utils/identity-heal.js.map +1 -0
- package/dist/utils/init/pipeline.d.ts +74 -0
- package/dist/utils/init/pipeline.d.ts.map +1 -0
- package/dist/utils/init/pipeline.js +96 -0
- package/dist/utils/init/pipeline.js.map +1 -0
- package/dist/utils/poll.d.ts +15 -1
- package/dist/utils/poll.d.ts.map +1 -1
- package/dist/utils/poll.js +6 -3
- package/dist/utils/poll.js.map +1 -1
- package/dist/utils/register-agent-identity.d.ts +67 -0
- package/dist/utils/register-agent-identity.d.ts.map +1 -0
- package/dist/utils/register-agent-identity.js +34 -0
- package/dist/utils/register-agent-identity.js.map +1 -0
- package/dist/utils/review/did-web-key.d.ts +34 -0
- package/dist/utils/review/did-web-key.d.ts.map +1 -0
- package/dist/utils/review/did-web-key.js +104 -0
- package/dist/utils/review/did-web-key.js.map +1 -0
- package/dist/utils/review/load-registry.d.ts +33 -0
- package/dist/utils/review/load-registry.d.ts.map +1 -0
- package/dist/utils/review/load-registry.js +62 -0
- package/dist/utils/review/load-registry.js.map +1 -0
- package/dist/utils/review/verdict-verify.d.ts +43 -0
- package/dist/utils/review/verdict-verify.d.ts.map +1 -0
- package/dist/utils/review/verdict-verify.js +53 -0
- package/dist/utils/review/verdict-verify.js.map +1 -0
- package/dist/utils/review-registry-writer.d.ts +52 -0
- package/dist/utils/review-registry-writer.d.ts.map +1 -0
- package/dist/utils/review-registry-writer.js +79 -0
- package/dist/utils/review-registry-writer.js.map +1 -0
- package/dist/utils/should-install-dependency.d.ts +17 -0
- package/dist/utils/should-install-dependency.d.ts.map +1 -0
- package/dist/utils/should-install-dependency.js +25 -0
- package/dist/utils/should-install-dependency.js.map +1 -0
- package/dist/utils/tool-readiness.d.ts +57 -0
- package/dist/utils/tool-readiness.d.ts.map +1 -0
- package/dist/utils/tool-readiness.js +114 -0
- package/dist/utils/tool-readiness.js.map +1 -0
- package/dist/utils/which.d.ts +2 -0
- package/dist/utils/which.d.ts.map +1 -0
- package/dist/utils/which.js +22 -0
- package/dist/utils/which.js.map +1 -0
- package/dist/version.d.ts +15 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +29 -0
- package/dist/version.js.map +1 -0
- package/package.json +19 -6
- package/dist/utils/claim-polling.d.ts +0 -21
- package/dist/utils/claim-polling.d.ts.map +0 -1
- package/dist/utils/claim-polling.js.map +0 -1
- package/dist/utils/dco/fs-safe.d.ts +0 -14
- package/dist/utils/dco/fs-safe.d.ts.map +0 -1
- package/dist/utils/dco/fs-safe.js +0 -20
- package/dist/utils/dco/fs-safe.js.map +0 -1
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { execFile } from "node:child_process";
|
|
2
|
+
import { createHash, randomBytes as nodeRandomBytes } from "node:crypto";
|
|
3
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { promisify } from "node:util";
|
|
6
|
+
import { ensureSecureDir, stateDir, writeFileAtomicSafe, writeSecureFile, } from "./cli-kit/index.js";
|
|
7
|
+
import { GhNotInstalledError, isGhAuthenticated, isGhInstalled } from "./dco/github.js";
|
|
8
|
+
const execFileAsync = promisify(execFile);
|
|
9
|
+
/** Absolute path to the credential directory, e.g. ~/.mcpi/github. Overridable for tests via MCPI_GITHUB_DIR. */
|
|
10
|
+
export function credentialsDir() {
|
|
11
|
+
return resolve(process.env.MCPI_GITHUB_DIR || stateDir("mcpi", "github"));
|
|
12
|
+
}
|
|
13
|
+
/** Absolute path to the credential store file. */
|
|
14
|
+
export function credentialsPath() {
|
|
15
|
+
return join(credentialsDir(), "credentials.json");
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* sha256 hex digest of a secret's raw bytes (the token, or the webhook
|
|
19
|
+
* secret). GitHub PATs and this module's hex-encoded webhook secrets are
|
|
20
|
+
* always ASCII, so UTF-8 encoding is exact-byte equivalent to hashing the
|
|
21
|
+
* secret's actual byte representation. This is the ONLY form either secret
|
|
22
|
+
* is ever allowed to leave this module in -- the anchor (see
|
|
23
|
+
* `github-credential-anchor.ts`) carries fingerprints exclusively.
|
|
24
|
+
*/
|
|
25
|
+
export function fingerprintSecret(secret) {
|
|
26
|
+
return createHash("sha256").update(secret, "utf8").digest("hex");
|
|
27
|
+
}
|
|
28
|
+
/** Runtime shape guard: a corrupt or hand-edited file must never crash a caller. */
|
|
29
|
+
function isStoredGithubCredential(value) {
|
|
30
|
+
if (!value || typeof value !== "object")
|
|
31
|
+
return false;
|
|
32
|
+
const v = value;
|
|
33
|
+
return (typeof v.githubLogin === "string" &&
|
|
34
|
+
typeof v.token === "string" &&
|
|
35
|
+
typeof v.webhookSecret === "string" &&
|
|
36
|
+
typeof v.createdAt === "string" &&
|
|
37
|
+
Array.isArray(v.scopes) &&
|
|
38
|
+
v.scopes.every((s) => typeof s === "string"));
|
|
39
|
+
}
|
|
40
|
+
/** The currently stored credential, or undefined if none exists (or the file is unreadable/corrupt). */
|
|
41
|
+
export function readStoredCredential() {
|
|
42
|
+
const path = credentialsPath();
|
|
43
|
+
if (!existsSync(path))
|
|
44
|
+
return undefined;
|
|
45
|
+
try {
|
|
46
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
47
|
+
return isStoredGithubCredential(parsed) ? parsed : undefined;
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Persist `credential` at {@link credentialsPath}, 0600 inside a 0700
|
|
55
|
+
* directory ({@link credentialsDir}).
|
|
56
|
+
*
|
|
57
|
+
* A pre-existing file is never silently overwritten (sentinel `8297a1e`'s
|
|
58
|
+
* lesson, transposed: operate only on YOUR OWN prior credential, and only
|
|
59
|
+
* once that's been confirmed, never by assuming the file is stale). This
|
|
60
|
+
* check is on FILE PRESENCE, not on `readStoredCredential`'s shape-validated
|
|
61
|
+
* result: a file that exists but fails the shape guard (corrupt, truncated
|
|
62
|
+
* by an interrupted prior write, or a future incompatible format) still has
|
|
63
|
+
* a live token sitting in it and must still gate on confirmation -- treating
|
|
64
|
+
* "can't parse it" the same as "nothing here" would silently discard that
|
|
65
|
+
* token with no rotation record, exactly the audit-trail gap anchoring
|
|
66
|
+
* exists to close. On a confirmed rotation the old file is replaced
|
|
67
|
+
* atomically (write temp + rename, `writeFileAtomicSafe`) and, when the
|
|
68
|
+
* prior file WAS well-formed, the result carries its token's fingerprint as
|
|
69
|
+
* `supersedesFingerprint` for the caller to bind into the next anchor's
|
|
70
|
+
* `supersedes` field -- absent when the prior file was corrupt, since there
|
|
71
|
+
* is no valid token to fingerprint.
|
|
72
|
+
*/
|
|
73
|
+
export async function saveGithubCredential(credential, options) {
|
|
74
|
+
const path = credentialsPath();
|
|
75
|
+
const fileExists = existsSync(path);
|
|
76
|
+
const existing = readStoredCredential();
|
|
77
|
+
if (fileExists) {
|
|
78
|
+
const confirmed = await options.confirmRotateImpl();
|
|
79
|
+
if (!confirmed) {
|
|
80
|
+
return { status: "declined" };
|
|
81
|
+
}
|
|
82
|
+
ensureSecureDir(credentialsDir());
|
|
83
|
+
writeFileAtomicSafe(path, JSON.stringify(credential, null, 2) + "\n", 0o600);
|
|
84
|
+
return {
|
|
85
|
+
status: "saved",
|
|
86
|
+
credential,
|
|
87
|
+
...(existing ? { supersedesFingerprint: fingerprintSecret(existing.token) } : {}),
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
ensureSecureDir(credentialsDir());
|
|
91
|
+
writeSecureFile(path, JSON.stringify(credential, null, 2) + "\n");
|
|
92
|
+
return { status: "saved", credential };
|
|
93
|
+
}
|
|
94
|
+
// ── Acquisition ─────────────────────────────────────────────────────────
|
|
95
|
+
/** Sentinel's proven classic-token grant list (README:33-35, `Know-That-Ai/sentinel` @ 83c0ed5). */
|
|
96
|
+
export const CLASSIC_REQUIRED_SCOPES = ["repo", "admin:repo_hook"];
|
|
97
|
+
/** Sentinel's proven fine-grained equivalent, printed verbatim for the user to grant. */
|
|
98
|
+
export const FINE_GRAINED_GRANTS = [
|
|
99
|
+
"Metadata: Read",
|
|
100
|
+
"Pull requests: Read & Write",
|
|
101
|
+
"Contents: Read",
|
|
102
|
+
"Webhooks: Read & Write",
|
|
103
|
+
];
|
|
104
|
+
export const GITHUB_PAT_SETTINGS_URL = "https://github.com/settings/personal-access-tokens/new";
|
|
105
|
+
/**
|
|
106
|
+
* Parse `gh api user -i` output (headers followed by a blank line, then the
|
|
107
|
+
* JSON body) into a {@link ScopeProbeResult}. Pure -- no process spawning --
|
|
108
|
+
* so this is unit-testable directly against canned `gh` output without a
|
|
109
|
+
* live GitHub call or even a `gh` binary on PATH.
|
|
110
|
+
*/
|
|
111
|
+
export function parseGhApiUserWithHeaders(raw) {
|
|
112
|
+
const normalized = raw.replace(/\r\n/g, "\n");
|
|
113
|
+
const blankIndex = normalized.indexOf("\n\n");
|
|
114
|
+
const headerBlock = blankIndex === -1 ? normalized : normalized.slice(0, blankIndex);
|
|
115
|
+
const bodyBlock = blankIndex === -1 ? "" : normalized.slice(blankIndex + 2);
|
|
116
|
+
let login;
|
|
117
|
+
try {
|
|
118
|
+
const parsedBody = JSON.parse(bodyBlock.trim());
|
|
119
|
+
if (parsedBody &&
|
|
120
|
+
typeof parsedBody === "object" &&
|
|
121
|
+
typeof parsedBody.login === "string") {
|
|
122
|
+
login = parsedBody.login;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch {
|
|
126
|
+
// Body isn't parseable JSON -- login stays undefined; handled below.
|
|
127
|
+
}
|
|
128
|
+
const scopesLine = headerBlock
|
|
129
|
+
.split("\n")
|
|
130
|
+
.find((line) => /^x-oauth-scopes:/i.test(line.trim()));
|
|
131
|
+
if (scopesLine) {
|
|
132
|
+
const value = scopesLine.slice(scopesLine.indexOf(":") + 1).trim();
|
|
133
|
+
const scopes = value.length === 0
|
|
134
|
+
? []
|
|
135
|
+
: value
|
|
136
|
+
.split(",")
|
|
137
|
+
.map((s) => s.trim())
|
|
138
|
+
.filter((s) => s.length > 0);
|
|
139
|
+
const missing = CLASSIC_REQUIRED_SCOPES.filter((required) => !scopes.includes(required));
|
|
140
|
+
if (missing.length > 0) {
|
|
141
|
+
return {
|
|
142
|
+
probe: "classic-x-oauth-scopes",
|
|
143
|
+
ok: false,
|
|
144
|
+
login,
|
|
145
|
+
scopes,
|
|
146
|
+
missing,
|
|
147
|
+
detail: `classic token via gh is missing required scope(s): ${missing.join(", ")}`,
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
return {
|
|
151
|
+
probe: "classic-x-oauth-scopes",
|
|
152
|
+
ok: true,
|
|
153
|
+
login,
|
|
154
|
+
scopes,
|
|
155
|
+
detail: `classic token scopes verified via X-OAuth-Scopes: ${scopes.join(", ")}`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
if (login) {
|
|
159
|
+
return {
|
|
160
|
+
probe: "fine-grained-user-read",
|
|
161
|
+
ok: true,
|
|
162
|
+
login,
|
|
163
|
+
detail: "fine-grained token does not report scopes over the API; verified only that it authenticates via a GET /user probe",
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
return {
|
|
167
|
+
probe: "fine-grained-user-read",
|
|
168
|
+
ok: false,
|
|
169
|
+
detail: "fine-grained probe (GET /user) did not return a usable login",
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
async function runGh(args, env) {
|
|
173
|
+
try {
|
|
174
|
+
const { stdout } = await execFileAsync("gh", args, {
|
|
175
|
+
encoding: "utf8",
|
|
176
|
+
maxBuffer: 10 * 1024 * 1024,
|
|
177
|
+
env: env ? { ...process.env, ...env } : process.env,
|
|
178
|
+
});
|
|
179
|
+
return stdout;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (error?.code === "ENOENT") {
|
|
183
|
+
throw new GhNotInstalledError();
|
|
184
|
+
}
|
|
185
|
+
throw error;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
async function defaultApiUserWithHeaders() {
|
|
189
|
+
return runGh(["api", "user", "-i"]);
|
|
190
|
+
}
|
|
191
|
+
/** Same probe, but authenticated as a specific pasted token rather than gh's own stored auth -- never as a CLI arg (visible in `ps`), only via env. */
|
|
192
|
+
async function defaultApiUserWithHeadersForToken(token) {
|
|
193
|
+
return runGh(["api", "user", "-i"], { GH_TOKEN: token });
|
|
194
|
+
}
|
|
195
|
+
async function defaultGhAuthToken() {
|
|
196
|
+
return (await runGh(["auth", "token"])).trim();
|
|
197
|
+
}
|
|
198
|
+
/** Masked paste prompt -- inquirer's "password" type never echoes input. */
|
|
199
|
+
async function defaultPromptForToken() {
|
|
200
|
+
const inquirer = (await import("inquirer")).default;
|
|
201
|
+
const { token } = await inquirer.prompt([
|
|
202
|
+
{
|
|
203
|
+
type: "password",
|
|
204
|
+
name: "token",
|
|
205
|
+
message: "Paste your fine-grained GitHub PAT (input hidden):",
|
|
206
|
+
mask: "*",
|
|
207
|
+
},
|
|
208
|
+
]);
|
|
209
|
+
return token.trim();
|
|
210
|
+
}
|
|
211
|
+
async function tryExistingGhCredential(options) {
|
|
212
|
+
const installed = await options.isGhInstalledImpl().catch(() => false);
|
|
213
|
+
if (!installed)
|
|
214
|
+
return undefined;
|
|
215
|
+
const authenticated = await options.isGhAuthenticatedImpl().catch(() => false);
|
|
216
|
+
if (!authenticated)
|
|
217
|
+
return undefined;
|
|
218
|
+
const raw = await options.apiUserWithHeadersImpl();
|
|
219
|
+
const probe = parseGhApiUserWithHeaders(raw);
|
|
220
|
+
options.onNotice(probe.detail);
|
|
221
|
+
if (!probe.ok || !probe.login)
|
|
222
|
+
return undefined;
|
|
223
|
+
const token = await options.ghAuthTokenImpl();
|
|
224
|
+
return {
|
|
225
|
+
githubLogin: probe.login,
|
|
226
|
+
token,
|
|
227
|
+
scopes: probe.scopes ?? [...FINE_GRAINED_GRANTS],
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/** Verify a specific token (pasted, or supplied via --github-token-env) and derive its login/scopes. Shared by both paths so neither can drift. */
|
|
231
|
+
async function verifyAndDeriveFromToken(token, options, failureContext) {
|
|
232
|
+
const raw = await options.apiUserWithHeadersForTokenImpl(token);
|
|
233
|
+
const probe = parseGhApiUserWithHeaders(raw);
|
|
234
|
+
options.onNotice(probe.detail);
|
|
235
|
+
if (!probe.ok || !probe.login) {
|
|
236
|
+
throw new Error(`Could not verify the ${failureContext}: ${probe.detail}`);
|
|
237
|
+
}
|
|
238
|
+
return {
|
|
239
|
+
githubLogin: probe.login,
|
|
240
|
+
token,
|
|
241
|
+
scopes: probe.scopes ?? [...FINE_GRAINED_GRANTS],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
async function acquireViaPaste(options) {
|
|
245
|
+
options.onNotice([
|
|
246
|
+
"Create a fine-grained personal access token with exactly these grants, then paste it below:",
|
|
247
|
+
...FINE_GRAINED_GRANTS.map((g) => ` - ${g}`),
|
|
248
|
+
`Create one at: ${GITHUB_PAT_SETTINGS_URL}`,
|
|
249
|
+
].join("\n"));
|
|
250
|
+
const token = await options.promptForTokenImpl();
|
|
251
|
+
if (!token) {
|
|
252
|
+
throw new Error("No GitHub token provided.");
|
|
253
|
+
}
|
|
254
|
+
return verifyAndDeriveFromToken(token, options, "pasted GitHub token");
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Acquire the single GitHub credential for this person on this machine.
|
|
258
|
+
*
|
|
259
|
+
* Acquisition order:
|
|
260
|
+
* 0. `options.presetToken`, when supplied (`kya-os init --github-token-env
|
|
261
|
+
* NAME`) -- skips both of the below entirely, for a fully
|
|
262
|
+
* non-interactive run. Verified the same way a pasted token is.
|
|
263
|
+
* 1. `gh auth token`, when `gh` is installed, authenticated, and the
|
|
264
|
+
* scope probe against its stored token passes (classic: all of
|
|
265
|
+
* {@link CLASSIC_REQUIRED_SCOPES} present via `X-OAuth-Scopes`;
|
|
266
|
+
* fine-grained: the `GET /user` probe authenticates).
|
|
267
|
+
* 2. Otherwise, prompt for a pasted fine-grained PAT created with
|
|
268
|
+
* {@link FINE_GRAINED_GRANTS}, verified the same way.
|
|
269
|
+
*
|
|
270
|
+
* Always generates a fresh `webhookSecret` (32 random bytes, hex) even
|
|
271
|
+
* though the webhook receiver itself ships in P17 -- the anchor binds it
|
|
272
|
+
* from day one so the rotation history the hub sees is complete from the
|
|
273
|
+
* very first anchor.
|
|
274
|
+
*/
|
|
275
|
+
export async function acquireGithubCredential(options = {}) {
|
|
276
|
+
const isGhInstalledImpl = options.isGhInstalledImpl ?? isGhInstalled;
|
|
277
|
+
const isGhAuthenticatedImpl = options.isGhAuthenticatedImpl ?? isGhAuthenticated;
|
|
278
|
+
const apiUserWithHeadersImpl = options.apiUserWithHeadersImpl ?? defaultApiUserWithHeaders;
|
|
279
|
+
const apiUserWithHeadersForTokenImpl = options.apiUserWithHeadersForTokenImpl ?? defaultApiUserWithHeadersForToken;
|
|
280
|
+
const ghAuthTokenImpl = options.ghAuthTokenImpl ?? defaultGhAuthToken;
|
|
281
|
+
const promptForTokenImpl = options.promptForTokenImpl ?? defaultPromptForToken;
|
|
282
|
+
const randomBytesImpl = options.randomBytesImpl ?? nodeRandomBytes;
|
|
283
|
+
const now = options.now ?? (() => new Date().toISOString());
|
|
284
|
+
const onNotice = options.onNotice ?? (() => { });
|
|
285
|
+
let acquired;
|
|
286
|
+
if (options.presetToken) {
|
|
287
|
+
acquired = await verifyAndDeriveFromToken(options.presetToken, { apiUserWithHeadersForTokenImpl, onNotice }, "GitHub token from the environment");
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
const existing = await tryExistingGhCredential({
|
|
291
|
+
isGhInstalledImpl,
|
|
292
|
+
isGhAuthenticatedImpl,
|
|
293
|
+
apiUserWithHeadersImpl,
|
|
294
|
+
ghAuthTokenImpl,
|
|
295
|
+
onNotice,
|
|
296
|
+
});
|
|
297
|
+
acquired =
|
|
298
|
+
existing ?? (await acquireViaPaste({ apiUserWithHeadersForTokenImpl, promptForTokenImpl, onNotice }));
|
|
299
|
+
}
|
|
300
|
+
return {
|
|
301
|
+
githubLogin: acquired.githubLogin,
|
|
302
|
+
token: acquired.token,
|
|
303
|
+
webhookSecret: randomBytesImpl(32).toString("hex"),
|
|
304
|
+
scopes: acquired.scopes,
|
|
305
|
+
createdAt: now(),
|
|
306
|
+
};
|
|
307
|
+
}
|
|
308
|
+
//# sourceMappingURL=github-credential.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"github-credential.js","sourceRoot":"","sources":["../../src/utils/github-credential.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adds `entry` to .gitignore if no existing pattern already covers it,
|
|
3
|
+
* including a trailing-`*` wildcard pattern (e.g. `.env*`, create-next-app's
|
|
4
|
+
* own default), the same glob EnvManager.checkGitignore() already honors, so
|
|
5
|
+
* this doesn't append a redundant, already-covered line.
|
|
6
|
+
*
|
|
7
|
+
* Shared by every command that writes a credential-bearing path into a
|
|
8
|
+
* project directory it doesn't fully control (`.env.local`, `.checkpoint/`,
|
|
9
|
+
* `.mcpi/`). Neither write is safe to leave ungitignored: a repo whose
|
|
10
|
+
* `.gitignore` doesn't already cover it (hand-rolled apps, a pruned/custom
|
|
11
|
+
* .gitignore, a repo that was never scaffolded by this CLI) would otherwise
|
|
12
|
+
* let `git add .` stage a real credential straight into history. Callers
|
|
13
|
+
* should call this BEFORE writing the secret, not after, so there's no
|
|
14
|
+
* window where the file exists ungitignored.
|
|
15
|
+
*/
|
|
16
|
+
export declare function ensureGitignored(projectRoot: string, entry: string, label: string): void;
|
|
17
|
+
//# sourceMappingURL=gitignore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.d.ts","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,WAAW,EAAE,MAAM,EACnB,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,GACZ,IAAI,CAwBN"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { existsSync, readFileSync, writeFileSync } from "fs";
|
|
2
|
+
import { join } from "path";
|
|
3
|
+
/**
|
|
4
|
+
* Adds `entry` to .gitignore if no existing pattern already covers it,
|
|
5
|
+
* including a trailing-`*` wildcard pattern (e.g. `.env*`, create-next-app's
|
|
6
|
+
* own default), the same glob EnvManager.checkGitignore() already honors, so
|
|
7
|
+
* this doesn't append a redundant, already-covered line.
|
|
8
|
+
*
|
|
9
|
+
* Shared by every command that writes a credential-bearing path into a
|
|
10
|
+
* project directory it doesn't fully control (`.env.local`, `.checkpoint/`,
|
|
11
|
+
* `.mcpi/`). Neither write is safe to leave ungitignored: a repo whose
|
|
12
|
+
* `.gitignore` doesn't already cover it (hand-rolled apps, a pruned/custom
|
|
13
|
+
* .gitignore, a repo that was never scaffolded by this CLI) would otherwise
|
|
14
|
+
* let `git add .` stage a real credential straight into history. Callers
|
|
15
|
+
* should call this BEFORE writing the secret, not after, so there's no
|
|
16
|
+
* window where the file exists ungitignored.
|
|
17
|
+
*/
|
|
18
|
+
export function ensureGitignored(projectRoot, entry, label) {
|
|
19
|
+
const gitignorePath = join(projectRoot, ".gitignore");
|
|
20
|
+
const bare = entry.replace(/\/$/, "");
|
|
21
|
+
let content = existsSync(gitignorePath)
|
|
22
|
+
? readFileSync(gitignorePath, "utf-8")
|
|
23
|
+
: "";
|
|
24
|
+
const alreadyIgnored = content
|
|
25
|
+
.split("\n")
|
|
26
|
+
.map((line) => line.trim())
|
|
27
|
+
.filter((line) => line && !line.startsWith("#"))
|
|
28
|
+
.some((line) => line === entry ||
|
|
29
|
+
line === bare ||
|
|
30
|
+
line === `/${bare}` ||
|
|
31
|
+
line === `/${entry}` ||
|
|
32
|
+
(line.endsWith("*") && bare.startsWith(line.slice(0, -1))));
|
|
33
|
+
if (alreadyIgnored)
|
|
34
|
+
return;
|
|
35
|
+
if (content && !content.endsWith("\n"))
|
|
36
|
+
content += "\n";
|
|
37
|
+
content += `${content ? "\n" : ""}# ${label}\n${entry}\n`;
|
|
38
|
+
writeFileSync(gitignorePath, content, "utf-8");
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=gitignore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gitignore.js","sourceRoot":"","sources":["../../src/utils/gitignore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,gBAAgB,CAC9B,WAAmB,EACnB,KAAa,EACb,KAAa;IAEb,MAAM,aAAa,GAAG,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IACtD,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;IACtC,IAAI,OAAO,GAAG,UAAU,CAAC,aAAa,CAAC;QACrC,CAAC,CAAC,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC;QACtC,CAAC,CAAC,EAAE,CAAC;IAEP,MAAM,cAAc,GAAG,OAAO;SAC3B,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;SAC/C,IAAI,CACH,CAAC,IAAI,EAAE,EAAE,CACP,IAAI,KAAK,KAAK;QACd,IAAI,KAAK,IAAI;QACb,IAAI,KAAK,IAAI,IAAI,EAAE;QACnB,IAAI,KAAK,IAAI,KAAK,EAAE;QACpB,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAC7D,CAAC;IACJ,IAAI,cAAc;QAAE,OAAO;IAE3B,IAAI,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,IAAI,CAAC;IACxD,OAAO,IAAI,GAAG,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,KAAK,KAAK,IAAI,CAAC;IAC1D,aAAa,CAAC,aAAa,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;AACjD,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reads `~/.mcpi/hub.json`, written by review-loop P17's hub-context stage
|
|
3
|
+
* (`packages/cli/src/utils/hub-context.ts`, not yet on `main`). This file
|
|
4
|
+
* is deliberately READ-ONLY and does not write that shape: P17 owns the
|
|
5
|
+
* resolution order (explicit endpoint, reachable production hub, local
|
|
6
|
+
* hub offer) and the write side. This exists so anything that only needs
|
|
7
|
+
* to know "is a hub configured, and where" -- today, the TUI agents view's
|
|
8
|
+
* hub-connection column and dispatch gate -- does not have to wait for
|
|
9
|
+
* P17 to land to read a file P17's own prompt already pins the shape of.
|
|
10
|
+
*
|
|
11
|
+
* @module cli/utils/hub-config
|
|
12
|
+
*/
|
|
13
|
+
export interface HubConfig {
|
|
14
|
+
endpoint: string;
|
|
15
|
+
mode: "remote" | "local";
|
|
16
|
+
installedService?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function hubConfigPath(): string;
|
|
19
|
+
/** Undefined for a missing, unreadable, or malformed file -- never throws. */
|
|
20
|
+
export declare function readHubConfig(): HubConfig | undefined;
|
|
21
|
+
//# sourceMappingURL=hub-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-config.d.ts","sourceRoot":"","sources":["../../src/utils/hub-config.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;GAWG;AAEH,MAAM,WAAW,SAAS;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,QAAQ,GAAG,OAAO,CAAC;IACzB,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAaD,wBAAgB,aAAa,IAAI,MAAM,CAEtC;AAED,8EAA8E;AAC9E,wBAAgB,aAAa,IAAI,SAAS,GAAG,SAAS,CASrD"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { existsSync, readFileSync } from "fs";
|
|
2
|
+
import { stateDir } from "./cli-kit/index.js";
|
|
3
|
+
function isHubConfig(value) {
|
|
4
|
+
if (!value || typeof value !== "object")
|
|
5
|
+
return false;
|
|
6
|
+
const v = value;
|
|
7
|
+
return (typeof v.endpoint === "string" &&
|
|
8
|
+
v.endpoint.length > 0 &&
|
|
9
|
+
(v.mode === "remote" || v.mode === "local") &&
|
|
10
|
+
(v.installedService === undefined || typeof v.installedService === "string"));
|
|
11
|
+
}
|
|
12
|
+
export function hubConfigPath() {
|
|
13
|
+
return process.env.MCPI_HUB_CONFIG_PATH || stateDir("mcpi", "hub.json");
|
|
14
|
+
}
|
|
15
|
+
/** Undefined for a missing, unreadable, or malformed file -- never throws. */
|
|
16
|
+
export function readHubConfig() {
|
|
17
|
+
const path = hubConfigPath();
|
|
18
|
+
if (!existsSync(path))
|
|
19
|
+
return undefined;
|
|
20
|
+
try {
|
|
21
|
+
const parsed = JSON.parse(readFileSync(path, "utf-8"));
|
|
22
|
+
return isHubConfig(parsed) ? parsed : undefined;
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
return undefined;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=hub-config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hub-config.js","sourceRoot":"","sources":["../../src/utils/hub-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAC9C,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAqB9C,SAAS,WAAW,CAAC,KAAc;IACjC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACtD,MAAM,CAAC,GAAG,KAAgC,CAAC;IAC3C,OAAO,CACL,OAAO,CAAC,CAAC,QAAQ,KAAK,QAAQ;QAC9B,CAAC,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC;QACrB,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO,CAAC;QAC3C,CAAC,CAAC,CAAC,gBAAgB,KAAK,SAAS,IAAI,OAAO,CAAC,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAC7E,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,IAAI,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AAC1E,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,aAAa;IAC3B,MAAM,IAAI,GAAG,aAAa,EAAE,CAAC;IAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;QAAE,OAAO,SAAS,CAAC;IACxC,IAAI,CAAC;QACH,MAAM,MAAM,GAAY,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC,CAAC;QAChE,OAAO,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAC;IAClD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Patches only the `did` field of an on-disk `.mcpi/identity.json`,
|
|
3
|
+
* preserving every other field (privateKey, publicKey, kid, createdAt, ...).
|
|
4
|
+
*
|
|
5
|
+
* Both `init` and `register` mint or accept a locally-generated placeholder
|
|
6
|
+
* did before the registry assigns the real did:web record; once the
|
|
7
|
+
* canonical did is known, this heals identity.json in place so it never
|
|
8
|
+
* drifts from agent.json (dco setup.ts throws "for a different agent" the
|
|
9
|
+
* moment they disagree).
|
|
10
|
+
*
|
|
11
|
+
* Returns false, without writing anything, when the file does not exist or
|
|
12
|
+
* already has the target did. Read/parse/write errors are left to THROW:
|
|
13
|
+
* callers each keep their own catch-and-warn behavior around this call.
|
|
14
|
+
*/
|
|
15
|
+
export declare function patchIdentityDidInPlace(identityFilePath: string, newDid: string): boolean;
|
|
16
|
+
//# sourceMappingURL=identity-heal.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-heal.d.ts","sourceRoot":"","sources":["../../src/utils/identity-heal.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;GAaG;AACH,wBAAgB,uBAAuB,CACrC,gBAAgB,EAAE,MAAM,EACxB,MAAM,EAAE,MAAM,GACb,OAAO,CAsBT"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { existsSync, readFileSync, chmodSync } from "fs";
|
|
2
|
+
import { writeFileAtomicSafe } from "./cli-kit/index.js";
|
|
3
|
+
/**
|
|
4
|
+
* Patches only the `did` field of an on-disk `.mcpi/identity.json`,
|
|
5
|
+
* preserving every other field (privateKey, publicKey, kid, createdAt, ...).
|
|
6
|
+
*
|
|
7
|
+
* Both `init` and `register` mint or accept a locally-generated placeholder
|
|
8
|
+
* did before the registry assigns the real did:web record; once the
|
|
9
|
+
* canonical did is known, this heals identity.json in place so it never
|
|
10
|
+
* drifts from agent.json (dco setup.ts throws "for a different agent" the
|
|
11
|
+
* moment they disagree).
|
|
12
|
+
*
|
|
13
|
+
* Returns false, without writing anything, when the file does not exist or
|
|
14
|
+
* already has the target did. Read/parse/write errors are left to THROW:
|
|
15
|
+
* callers each keep their own catch-and-warn behavior around this call.
|
|
16
|
+
*/
|
|
17
|
+
export function patchIdentityDidInPlace(identityFilePath, newDid) {
|
|
18
|
+
if (!existsSync(identityFilePath)) {
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
21
|
+
const existing = JSON.parse(readFileSync(identityFilePath, "utf-8"));
|
|
22
|
+
if (!existing || typeof existing !== "object" || existing.did === newDid) {
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
// Atomic + symlink-safe: identity.json holds a private key, so a crash
|
|
26
|
+
// mid-write must never truncate it, and a planted symlink at the write's
|
|
27
|
+
// temp sibling must never be followed into an arbitrary file.
|
|
28
|
+
writeFileAtomicSafe(identityFilePath, JSON.stringify({ ...existing, did: newDid }, null, 2), 0o600);
|
|
29
|
+
try {
|
|
30
|
+
chmodSync(identityFilePath, 0o600);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// Best-effort; e.g. unsupported on Windows.
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
//# sourceMappingURL=identity-heal.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"identity-heal.js","sourceRoot":"","sources":["../../src/utils/identity-heal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,IAAI,CAAC;AACzD,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAEzD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,uBAAuB,CACrC,gBAAwB,EACxB,MAAc;IAEd,IAAI,CAAC,UAAU,CAAC,gBAAgB,CAAC,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,gBAAgB,EAAE,OAAO,CAAC,CAAC,CAAC;IACrE,IAAI,CAAC,QAAQ,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,GAAG,KAAK,MAAM,EAAE,CAAC;QACzE,OAAO,KAAK,CAAC;IACf,CAAC;IACD,uEAAuE;IACvE,yEAAyE;IACzE,8DAA8D;IAC9D,mBAAmB,CACjB,gBAAgB,EAChB,IAAI,CAAC,SAAS,CAAC,EAAE,GAAG,QAAQ,EAAE,GAAG,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EACrD,KAAK,CACN,CAAC;IACF,IAAI,CAAC;QACH,SAAS,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,4CAA4C;IAC9C,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The stage pipeline `kya-os init` runs.
|
|
3
|
+
*
|
|
4
|
+
* `init.ts`'s flow is seven ordered stages (readiness/install, identity,
|
|
5
|
+
* claim, agent profiles, GitHub credentials, hub context, summary+TUI
|
|
6
|
+
* handoff). Each stage decides for itself whether it applies at all
|
|
7
|
+
* (`when`) and reports one summary line plus any warnings (`run`) instead
|
|
8
|
+
* of printing ad hoc -- the pipeline collects every stage's report so the
|
|
9
|
+
* caller can print one consolidated block before the TUI handoff question,
|
|
10
|
+
* which is what makes a re-run ("already set up" in one line each, per
|
|
11
|
+
* stage) possible without every stage re-implementing that summary itself.
|
|
12
|
+
*
|
|
13
|
+
* `when` is also the seam P16/P17 runtime-optionality depends on: a guard
|
|
14
|
+
* that checks whether the stage's own module exists (a dynamic import
|
|
15
|
+
* wrapped in try/catch) rather than a hardcoded flag means a stage
|
|
16
|
+
* activates itself the moment its dependency lands on `main`, with zero
|
|
17
|
+
* code change here.
|
|
18
|
+
*
|
|
19
|
+
* A stage's `run` is expected to catch its own recoverable failures and
|
|
20
|
+
* report them as `{ ok: false, warnings: [...] }` -- exactly how init.ts's
|
|
21
|
+
* existing non-fatal error handling already works. A `run` that needs to
|
|
22
|
+
* stop the whole pipeline (today: only a missing `git` or an identity
|
|
23
|
+
* failure) throws a {@link StageFatalError}; anything else it throws is
|
|
24
|
+
* treated as an unexpected bug, not a modeled failure, and propagates
|
|
25
|
+
* uncaught. This module never touches `process.exit` itself -- the caller
|
|
26
|
+
* owns the NODE_ENV=test guard and the exit code, which is what keeps this
|
|
27
|
+
* file trivially unit-testable on its own.
|
|
28
|
+
*
|
|
29
|
+
* @module cli/utils/init/pipeline
|
|
30
|
+
*/
|
|
31
|
+
export interface StageResult {
|
|
32
|
+
ok: boolean;
|
|
33
|
+
summaryLine: string;
|
|
34
|
+
warnings?: string[];
|
|
35
|
+
}
|
|
36
|
+
/** Raised by a stage's `run` to stop the pipeline with a specific exit code. */
|
|
37
|
+
export declare class StageFatalError extends Error {
|
|
38
|
+
readonly exitCode: number;
|
|
39
|
+
constructor(exitCode: number, message: string);
|
|
40
|
+
}
|
|
41
|
+
export interface Stage<Ctx> {
|
|
42
|
+
name: string;
|
|
43
|
+
/**
|
|
44
|
+
* Whether this stage applies at all. A stage that returns false is
|
|
45
|
+
* omitted from the report entirely -- reserved for a stage whose
|
|
46
|
+
* dependency genuinely does not exist yet (P16/P17 modules absent) or
|
|
47
|
+
* whose skip flag was passed. A stage that DOES apply but finds nothing
|
|
48
|
+
* new to do still runs and reports that itself via `run`'s
|
|
49
|
+
* `summaryLine` (e.g. "already set up"), so the caller sees one line
|
|
50
|
+
* either way.
|
|
51
|
+
*/
|
|
52
|
+
when: (ctx: Ctx) => boolean | Promise<boolean>;
|
|
53
|
+
run: (ctx: Ctx) => Promise<StageResult>;
|
|
54
|
+
}
|
|
55
|
+
export interface RanStage {
|
|
56
|
+
name: string;
|
|
57
|
+
result: StageResult;
|
|
58
|
+
}
|
|
59
|
+
export interface RunStagesReport {
|
|
60
|
+
ran: RanStage[];
|
|
61
|
+
/** Names of stages whose `when` returned false. */
|
|
62
|
+
omitted: string[];
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Runs every applicable stage in order, stopping immediately (and
|
|
66
|
+
* rethrowing) if a stage throws. Callers that want a "skipped" line for an
|
|
67
|
+
* omitted stage build it from {@link RunStagesReport.omitted} themselves --
|
|
68
|
+
* this function does not synthesize one, since a stage's own `when` is the
|
|
69
|
+
* only place that knows WHY it does not apply (module absent vs. a --skip
|
|
70
|
+
* flag vs. platform mismatch).
|
|
71
|
+
*/
|
|
72
|
+
export declare function runStages<Ctx>(stages: ReadonlyArray<Stage<Ctx>>, ctx: Ctx): Promise<RunStagesReport>;
|
|
73
|
+
export declare function moduleExists(specifier: string, fromUrl: string): Promise<boolean>;
|
|
74
|
+
//# sourceMappingURL=pipeline.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pipeline.d.ts","sourceRoot":"","sources":["../../../src/utils/init/pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AAEH,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,OAAO,CAAC;IACZ,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,gFAAgF;AAChF,qBAAa,eAAgB,SAAQ,KAAK;IACxC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;gBACd,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAK9C;AAED,MAAM,WAAW,KAAK,CAAC,GAAG;IACxB,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;;;OAQG;IACH,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/C,GAAG,EAAE,CAAC,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,WAAW,CAAC,CAAC;CACzC;AAED,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC9B,GAAG,EAAE,QAAQ,EAAE,CAAC;IAChB,mDAAmD;IACnD,OAAO,EAAE,MAAM,EAAE,CAAC;CACnB;AAED;;;;;;;GAOG;AACH,wBAAsB,SAAS,CAAC,GAAG,EACjC,MAAM,EAAE,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,EACjC,GAAG,EAAE,GAAG,GACP,OAAO,CAAC,eAAe,CAAC,CAY1B;AA6BD,wBAAsB,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAWvF"}
|