@capgo/cli 8.8.2 → 8.9.1

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@capgo/cli",
3
3
  "type": "module",
4
- "version": "8.8.2",
4
+ "version": "8.9.1",
5
5
  "description": "A CLI to upload to capgo servers",
6
6
  "author": "Martin martin@capgo.app",
7
7
  "license": "Apache 2.0",
@@ -89,6 +89,17 @@
89
89
  "test:supabase-perf": "bun test/test-supabase-perf.mjs",
90
90
  "test:preview-qr": "bun test/test-preview-qr.mjs",
91
91
  "test:mcp-analytics": "bun test/test-mcp-analytics.mjs",
92
+ "test:mcp-instructions": "bun test/test-mcp-instructions.mjs",
93
+ "test:mcp-stdout-guard": "bun test/test-mcp-stdout-guard.mjs",
94
+ "test:mcp-platform-select": "bun test/test-mcp-platform-select.mjs",
95
+ "test:mcp-explain-scopes": "bun test/test-mcp-explain-scopes.mjs",
96
+ "test:mcp-oauth-reopen": "bun test/test-mcp-oauth-reopen.mjs",
97
+ "test:mcp-broker-oauth": "bun test/test-mcp-broker-oauth.mjs",
98
+ "test:mcp-broker-session": "bun test/test-mcp-broker-session.mjs",
99
+ "test:mcp-credentials-manage": "bun test/test-mcp-credentials-manage.mjs",
100
+ "test:mcp-resume-prompt": "bun test/test-mcp-resume-prompt.mjs",
101
+ "test:mcp-build-job": "bun test/test-mcp-build-job.mjs",
102
+ "test:mcp-build-tools": "bun test/test-mcp-build-tools.mjs",
92
103
  "test:app-created-source": "bun test/test-app-created-source.mjs",
93
104
  "test:doctor-analytics": "bun test/test-doctor-analytics.mjs",
94
105
  "test:posthog-exception": "bun test/test-posthog-exception.mjs",
@@ -140,7 +151,7 @@
140
151
  "test:ios-verify-app": "bun test/test-ios-verify-app.mjs",
141
152
  "test:platform-flow-contract": "bun test/test-platform-flow-contract.mjs",
142
153
  "test:tail-engine-shared": "bun test/test-tail-engine-shared.mjs",
143
- "test": "bun run build && bun run test:helper-dce && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:preview-qr && bun run test:mcp-analytics && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:project-type-detection && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:asc-key-protocol && bun run test:apple-api-import-helpers && bun run test:bundle-id-detector && bun run test:apple-api-app-list && bun run test:app-verification && bun run test:pbxproj-parser && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-sse-parser && bun run test:ai-render-markdown && bun run test:ai-stream-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit && bun run test:ai-analyze-stream && bun run test:support-mailto && bun run test:support-redact && bun run test:support-internal-log && bun run test:support-help-menu && bun run test:support-contact && bun run test:support-bundle-files && bun run test:self-update && bun run test:update-prompt && bun run test:apple-api-cert-create && bun run test:android-tail-engine && bun run test:android-tail-render && bun run test:android-tail-routing && bun run test:dev-gate-stripped && bun run test:frame-fit-ios-shared && bun run test:ios-confirm-app-id && bun run test:ios-create-new && bun run test:ios-e2e && bun run test:ios-flow-contract && bun run test:ios-import-discovery && bun run test:ios-import-export && bun run test:ios-import-pickers && bun run test:ios-import-recovery && bun run test:ios-recovery && bun run test:ios-resume && bun run test:ios-tail-handoff && bun run test:ios-tui-render && bun run test:p8-error && bun run test:ios-tui-routing && bun run test:ios-updater-sync-validation && bun run test:ios-verify-app && bun run test:platform-flow-contract && bun run test:tail-engine-shared",
154
+ "test": "bun run build && bun run test:helper-dce && bun run test:version-detection:setup && bun run test:bundle && bun run test:functional && bun run test:semver && bun run test:version-edge-cases && bun run test:regex && bun run test:upload && bun run test:fail-on-incompatible && bun run test:credentials && bun run test:credentials-validation && bun run test:android-service-account-validation && bun run test:build-zip-filter && bun run test:checksum && bun run test:build-needed && bun run test:ci-prompts && bun run test:ci-secrets && bun run test:android-onboarding-progress && bun run test:onboarding-telemetry && bun run test:v2-event-migration && bun run test:analytics && bun run test:analytics-error-category && bun run test:analytics-org-resolver && bun run test:supabase-perf && bun run test:preview-qr && bun run test:mcp-analytics && bun run test:mcp-instructions && bun run test:mcp-stdout-guard && bun run test:mcp-platform-select && bun run test:mcp-explain-scopes && bun run test:mcp-oauth-reopen && bun run test:mcp-broker-oauth && bun run test:mcp-broker-session && bun run test:mcp-credentials-manage && bun run test:mcp-resume-prompt && bun run test:mcp-build-job && bun run test:mcp-build-tools && bun run test:app-created-source && bun run test:doctor-analytics && bun run test:posthog-exception && bun run test:build-platform-selection && bun run test:onboarding-recovery && bun run test:onboarding-progress && bun run test:onboarding-run-targets && bun run test:run-device-command && bun run test:init-app-conflict && bun run test:init-guardrails && bun run test:prompt-preferences && bun run test:esm-sdk && bun run test:mcp && bun run test:version-detection && bun run test:platform-paths && bun run test:project-type-detection && bun run test:payload-split && bun run test:manifest-path-encoding && bun run test:macos-signing && bun run test:asc-key-protocol && bun run test:apple-api-import-helpers && bun run test:bundle-id-detector && bun run test:apple-api-app-list && bun run test:app-verification && bun run test:pbxproj-parser && bun run test:ai-log-capture && bun run test:ai-analyze-flow && bun run test:ai-sse-parser && bun run test:ai-render-markdown && bun run test:ai-stream-markdown && bun run test:ai-onboarding-mode && bun run test:ai-fit && bun run test:platform-layout && bun run test:frame-fit && bun run test:onboarding-min-size && bun run test:min-size-gate && bun run test:shell-size-gate && bun run test:build-log-sanitize && bun run test:build-output-viewport && bun run test:diff-viewer-viewport && bun run test:build-complete-exit && bun run test:ai-analyze-stream && bun run test:support-mailto && bun run test:support-redact && bun run test:support-internal-log && bun run test:support-help-menu && bun run test:support-contact && bun run test:support-bundle-files && bun run test:self-update && bun run test:update-prompt && bun run test:apple-api-cert-create && bun run test:android-tail-engine && bun run test:android-tail-render && bun run test:android-tail-routing && bun run test:dev-gate-stripped && bun run test:frame-fit-ios-shared && bun run test:ios-confirm-app-id && bun run test:ios-create-new && bun run test:ios-e2e && bun run test:ios-flow-contract && bun run test:ios-import-discovery && bun run test:ios-import-export && bun run test:ios-import-pickers && bun run test:ios-import-recovery && bun run test:ios-recovery && bun run test:ios-resume && bun run test:ios-tail-handoff && bun run test:ios-tui-render && bun run test:p8-error && bun run test:ios-tui-routing && bun run test:ios-updater-sync-validation && bun run test:ios-verify-app && bun run test:platform-flow-contract && bun run test:tail-engine-shared",
144
155
  "test:build-platform-selection": "bun test/test-build-platform-selection.mjs",
145
156
  "test:ai-log-capture": "bun test/test-ai-log-capture.mjs",
146
157
  "test:ai-analyze-flow": "bun test/test-ai-analyze-flow.mjs",
@@ -21,6 +21,13 @@ import type { WorkflowWriteOptions, WorkflowWriteResult } from '../workflow-writ
21
21
  * MCP bridge so both produce identical progress objects.
22
22
  */
23
23
  export declare function applyGoogleSignIn(progress: AndroidOnboardingProgress, tokens: GoogleOAuthTokens, info: GoogleUserInfo): AndroidOnboardingProgress;
24
+ /**
25
+ * Apply a BROKER (access-token) Google sign-in. The MCP path receives a short-lived access token from the
26
+ * Capgo OAuth broker and CANNOT refresh it (the token is issued to the broker's confidential Web client), so
27
+ * it stores the access token + its expiry and re-signs-in on expiry — no `_oauthRefreshToken`. Mirrors
28
+ * applyGoogleSignIn for the refresh-token (TUI loopback) path.
29
+ */
30
+ export declare function applyGoogleSignInBroker(progress: AndroidOnboardingProgress, accessToken: string, expiresAt: number | null, info: GoogleUserInfo): AndroidOnboardingProgress;
24
31
  export type AndroidStepKind = 'auto' | 'input' | 'choice' | 'done' | 'error';
25
32
  export interface AndroidStepOption {
26
33
  value: string;
@@ -289,6 +296,12 @@ export interface AndroidEffectDeps {
289
296
  * The driver pre-binds OAuth client config (clientId, clientSecret, scopes).
290
297
  */
291
298
  startOAuthFlow?: (callbacks?: Pick<RunOAuthFlowOptions, 'onAuthUrl' | 'onStatus'>) => Promise<PendingOAuthSession>;
299
+ /**
300
+ * Open a URL in the user's default browser — used by the MCP broker sign-in to (optionally) open the
301
+ * sign-in link for the user. Best-effort: the engine falls back to showing the link if this throws or is
302
+ * absent. Optional (the Ink driver never uses it).
303
+ */
304
+ openBrowser?: (url: string) => Promise<void>;
292
305
  /** Fetch the signed-in user's profile (email, sub). */
293
306
  fetchUserInfo: (accessToken: string) => Promise<GoogleUserInfo>;
294
307
  /**
@@ -398,6 +411,12 @@ export interface AndroidEffectDeps {
398
411
  * Mirrors env-export.ts: defaultExportPath(appId, platform).
399
412
  */
400
413
  defaultExportPath?: (appId: string, platform: 'ios' | 'android') => string;
414
+ /**
415
+ * Lockfile-based package-manager detection (pure, read-only). Drives the
416
+ * pick-package-manager 'recommended — matches your lockfile' note.
417
+ * Mirrors @capgo/find-package-manager: findPackageManagerType(cwd, 'npm').
418
+ */
419
+ detectPackageManager?: () => string;
401
420
  /**
402
421
  * Generate the GitHub Actions workflow YAML (pure).
403
422
  * Mirrors workflow-generator.ts: generateWorkflow(opts).
@@ -85,6 +85,14 @@ export interface AndroidOnboardingProgress extends TailProgress {
85
85
  ciSecretsUploaded?: CiSecretsUploaded;
86
86
  };
87
87
  _oauthRefreshToken?: string;
88
+ _oauthAccessToken?: string;
89
+ _oauthAccessTokenExpiresAt?: number;
90
+ _brokerOAuth?: {
91
+ pubId: string;
92
+ pollSecret: string;
93
+ signInUrl: string;
94
+ expiresAt: number;
95
+ };
88
96
  _keystoreBase64?: string;
89
97
  /** Base64 of the downloaded SA JSON key — saved as PLAY_CONFIG_JSON at end. */
90
98
  _serviceAccountKeyBase64?: string;
@@ -332,6 +332,8 @@ export interface IosEffectDeps {
332
332
  uploadCiSecretsAsync?: (target: CiSecretTarget, entries: CiSecretEntry[], existingKeys?: string[], runner?: AsyncCommandRunner, onProgress?: (current: number, total: number, keyName: string) => void) => Promise<void>;
333
333
  exportCredentialsToEnv?: (opts: EnvExportOpts) => EnvExportResult;
334
334
  defaultExportPath?: (appId: string, platform: 'ios' | 'android') => string;
335
+ /** Lockfile-based package-manager detection (the pick-package-manager 'recommended' note). */
336
+ detectPackageManager?: () => string;
335
337
  generateWorkflow?: (opts: WorkflowGeneratorOpts) => GeneratedWorkflow;
336
338
  writeWorkflowFile?: (opts: WorkflowGeneratorOpts, writeOptions?: WorkflowWriteOptions) => WorkflowWriteResult;
337
339
  requestBuildInternal?: (appId: string, options: BuildRequestOptions, silent?: boolean, logger?: BuildLogger) => Promise<BuildRequestResult>;
@@ -432,6 +434,17 @@ export interface IosEffectDeps {
432
434
  * resume that lost the in-memory state.
433
435
  */
434
436
  importedP12Password?: string;
437
+ /**
438
+ * The existing Apple Distribution certs surfaced when the per-team cert
439
+ * limit was hit (cert-limit recovery). Produced by `creating-certificate`
440
+ * into transient.existingCerts; the driver threads the list back here so a
441
+ * parked `cert-limit-prompt` re-renders (and resolves the user's pick by
442
+ * cert id) WITHOUT re-hitting Apple. EPHEMERAL — never persisted (the TUI's
443
+ * `existingCerts` React state); cleared together with `certToRevoke` after
444
+ * a successful revoke. A restart that loses it re-enters via a fresh
445
+ * creating-certificate attempt, which re-derives the list.
446
+ */
447
+ existingCerts?: AscDistributionCert[];
435
448
  /**
436
449
  * The cert the user picked at `cert-limit-prompt` (cert-limit recovery). The
437
450
  * choice is EPHEMERAL — `applyIosInput` persists nothing; the driver records
@@ -496,6 +509,15 @@ export interface IosEffectDeps {
496
509
  * variant. Mirrors the TUI leaving `noMatchReason` untouched on back-nav.
497
510
  */
498
511
  noMatchReason?: IosNoMatchReason;
512
+ /**
513
+ * The failing step's human error message — the error screen's content
514
+ * (BATCH 8). EPHEMERAL — set by the failing effect into transient.error and
515
+ * threaded back here by the driver so a parked 'error' view re-renders the
516
+ * message (iosViewForStep('error') reads ctx.error). NEVER persisted —
517
+ * mirrors the TUI's setError React state; a crash-recovery resume re-enters
518
+ * the failing phase fresh.
519
+ */
520
+ error?: string;
499
521
  /**
500
522
  * The step to re-run when the user picks "Try again" on the error screen
501
523
  * (BATCH 8). EPHEMERAL — set by the failing effect into transient.retryStep,
@@ -152,14 +152,24 @@ export interface ResolveHelperBinaryOptions {
152
152
  /** Override `process.arch` (tests). */
153
153
  arch?: string;
154
154
  /**
155
- * Override module resolution (tests). Receives the package's
156
- * `package.json` specifier; must return its absolute path or throw.
155
+ * Override module resolution (tests). Each resolver receives the package's
156
+ * `package.json` specifier and must return its absolute path or throw. Pass an
157
+ * ARRAY to test the fallback chain (each base is tried in order until one
158
+ * resolves); a single function is treated as a one-element chain.
157
159
  */
158
- resolve?: (specifier: string) => string;
160
+ resolve?: ((specifier: string) => string) | Array<(specifier: string) => string>;
159
161
  /** Override the codesign spawn (tests). */
160
162
  codesignRunner?: CodesignRunner;
161
163
  /** Force the dev env-override gate (tests). Defaults to the build-time flag. */
162
164
  allowEnvOverride?: boolean;
165
+ /**
166
+ * Project directory to ALSO resolve the helper package from, in addition to the
167
+ * CLI's own node_modules. Lets a project-local `npm i @capgo/cli-helper-darwin-*`
168
+ * be picked up even when the CLI runs from a global install or the MCP server
169
+ * (which doesn't resolve from the user's project). Defaults to `process.cwd()`.
170
+ * Ignored when `resolve` is provided (tests).
171
+ */
172
+ cwd?: string;
163
173
  }
164
174
  /**
165
175
  * Locate the precompiled `helper` binary for this machine and verify its code
@@ -3,6 +3,6 @@
3
3
  * that can be embedded in a shell command string without risk of injection.
4
4
  *
5
5
  * Valid examples: com.example.app io.capgo.app_1 com.acme.my-app
6
- * Invalid examples: com.x; rm -rf ~ com.x$(cmd) nodots ""
6
+ * Invalid examples: com.x; rm -rf ~ com.x$(cmd) nodots com-example foo_bar ""
7
7
  */
8
8
  export declare function isSafeAppIdForCommand(appId: string): boolean;
@@ -0,0 +1,30 @@
1
+ export interface BrokerSession {
2
+ pubId: string;
3
+ pollSecret: string;
4
+ signInUrl: string;
5
+ /** Epoch ms when the sign-in window closes (the broker's 15-min session TTL). */
6
+ expiresAt: number;
7
+ }
8
+ export type BrokerPollResult = {
9
+ status: 'pending';
10
+ } | {
11
+ status: 'awaiting_code';
12
+ error?: string;
13
+ } | {
14
+ status: 'done';
15
+ accessToken: string;
16
+ expiresAt: number | null;
17
+ } | {
18
+ status: 'error';
19
+ error: string;
20
+ };
21
+ /** Create a broker sign-in session for `appId`. Throws on a transport/HTTP failure. */
22
+ export declare function createBrokerSession(appId: string): Promise<BrokerSession>;
23
+ /**
24
+ * Poll a broker session. Pass `confirmCode` (the code the user read off the success page) to release the
25
+ * token — the broker withholds it (status 'awaiting_code') until the matching code is presented.
26
+ */
27
+ export declare function pollBrokerSession(session: {
28
+ pubId: string;
29
+ pollSecret: string;
30
+ }, confirmCode?: string): Promise<BrokerPollResult>;
@@ -0,0 +1,19 @@
1
+ export interface BrokerSessionState {
2
+ status: 'absent' | 'pending' | 'awaiting_code' | 'done' | 'error';
3
+ /** The Google sign-in URL the user opens — present once a session exists. */
4
+ signInUrl?: string;
5
+ /** Short-lived Google access token, only on 'done'. */
6
+ accessToken?: string;
7
+ /** Epoch ms the access token expires, on 'done'. */
8
+ expiresAt?: number | null;
9
+ /** Human-readable failure reason for 'awaiting_code' (wrong code) / 'error'. */
10
+ error?: string;
11
+ }
12
+ /** Create a broker sign-in session for `appId`, persist its handle, and return the URL to show the user. */
13
+ export declare function brokerBegin(appId: string, baseDir?: string): Promise<{
14
+ signInUrl: string;
15
+ }>;
16
+ /** Poll the persisted broker session. Pass `confirmCode` (the code the user read off the page) to release the token. */
17
+ export declare function brokerPoll(appId: string, confirmCode?: string, baseDir?: string): Promise<BrokerSessionState>;
18
+ /** Drop the in-flight broker session handle (reopen / error recovery). */
19
+ export declare function brokerClear(appId: string, baseDir?: string): Promise<void>;
@@ -0,0 +1,94 @@
1
+ import type { BuildOutputRecord } from '../../output-record.js';
2
+ import type { Platform } from './contract.js';
3
+ export type BuildJobStatus = 'running' | 'completed' | 'failed' | 'cancelled' | 'unknown';
4
+ export interface BuildJobResult {
5
+ jobId: string;
6
+ status: BuildJobStatus;
7
+ platform: Platform;
8
+ appId: string;
9
+ /** Absolute path to the local log file the user can tail. NEVER read by the agent directly. */
10
+ logsPath: string;
11
+ outputUrl?: string;
12
+ qrCodeAscii?: string;
13
+ error?: string;
14
+ /** True when start found an in-flight build for this target and returned it instead of starting a second. */
15
+ alreadyRunning?: boolean;
16
+ }
17
+ /** A handle to the spawned build process (injectable so tests never spawn anything). */
18
+ export interface BuildChild {
19
+ pid: number;
20
+ kill: (signal?: NodeJS.Signals) => void;
21
+ /** Resolves with the exit code (or null on signal) when the process exits. */
22
+ exited: Promise<number | null>;
23
+ }
24
+ export interface BuildJobDeps {
25
+ /** Spawn the build command, streaming stdout+stderr to `logPath`. Returns a handle. */
26
+ spawnBuild: (args: {
27
+ appId: string;
28
+ platform: Platform;
29
+ recordPath: string;
30
+ logPath: string;
31
+ }) => BuildChild;
32
+ buildRecordPath: (appId: string, platform: Platform) => string;
33
+ /** Read the build record; resolves null when absent, THROWS on a present-but-corrupt record. */
34
+ readBuildRecord: (path: string) => Promise<BuildOutputRecord | null>;
35
+ /** Remove a stale record before a fresh build so wait can't read last run's result as this one's. */
36
+ clearBuildRecord?: (path: string) => Promise<void>;
37
+ /** Absolute path of the local log file for a target. */
38
+ logPath: (appId: string, platform: Platform) => string;
39
+ /** Read `logPath` from byte offset `cursor`; returns new text, the next cursor, and whether at EOF. */
40
+ readLogSlice: (logPath: string, cursor: number) => Promise<{
41
+ text: string;
42
+ nextCursor: number;
43
+ eof: boolean;
44
+ }>;
45
+ /** Best-effort cloud cancel by the cloud jobId (POST /build/cancel/:jobId). Optional. */
46
+ cancelCloud?: (cloudJobId: string) => Promise<void>;
47
+ /** Injected so the bounded wait loop is deterministic in tests. */
48
+ sleep: (ms: number) => Promise<void>;
49
+ now: () => number;
50
+ }
51
+ /** Bounded wait window (seconds), kept under the ~60s client tool-call timeout. */
52
+ export declare const DEFAULT_WAIT_SECONDS = 40;
53
+ export declare const MAX_WAIT_SECONDS = 59;
54
+ /** Drop every tracked build job (test isolation only). */
55
+ export declare function clearAllBuildJobs(): void;
56
+ /**
57
+ * Start (or re-attach to) the cloud build for a target. Idempotent: if a build
58
+ * for this (appId, platform) is already running this session, returns that job
59
+ * instead of spawning a second.
60
+ */
61
+ export declare function startBuild(deps: BuildJobDeps, args: {
62
+ appId: string;
63
+ platform: Platform;
64
+ }): Promise<BuildJobResult>;
65
+ /**
66
+ * Bounded wait: block up to `timeoutSeconds` (default 40, max 59 — kept under the
67
+ * client tool-call timeout), returning the instant the build reaches a terminal
68
+ * state, otherwise 'running' for the caller to re-call.
69
+ */
70
+ export declare function waitBuild(deps: BuildJobDeps, args: {
71
+ jobId: string;
72
+ timeoutSeconds?: number;
73
+ }): Promise<BuildJobResult>;
74
+ /** Non-blocking status peek. */
75
+ export declare function statusBuild(deps: BuildJobDeps, args: {
76
+ jobId: string;
77
+ }): Promise<BuildJobResult>;
78
+ /**
79
+ * Drain new log output since `cursor`. `eof` is true only once the build is
80
+ * terminal AND the read reached the end of the file, so a streamer knows to stop.
81
+ */
82
+ export declare function buildLogs(deps: BuildJobDeps, args: {
83
+ jobId: string;
84
+ cursor?: number;
85
+ }): Promise<{
86
+ jobId: string;
87
+ text: string;
88
+ nextCursor: number;
89
+ eof: boolean;
90
+ }>;
91
+ /** Cancel a running build: kill the local child + best-effort cloud cancel. */
92
+ export declare function cancelBuild(deps: BuildJobDeps, args: {
93
+ jobId: string;
94
+ }): Promise<BuildJobResult>;
@@ -0,0 +1,25 @@
1
+ import type { BuildJobDeps } from './build-job.js';
2
+ /** Minimal shape of the MCP server's tool registrar (matches McpServer.tool / McpLike). */
3
+ interface ToolRegistrar {
4
+ tool: (name: string, description: string, schema: Record<string, unknown>, handler: (args: any) => Promise<{
5
+ content: Array<{
6
+ type: 'text';
7
+ text: string;
8
+ }>;
9
+ }>) => unknown;
10
+ }
11
+ /**
12
+ * Production build-job deps: spawn the published CLI's `build request` as a
13
+ * tracked background child streaming to a local log file, read/clear the build
14
+ * record, and drain the log file by byte offset. No cloud cancel in v1 (cancel
15
+ * stops the local watcher; the cloud build may still finish — surfaced in the
16
+ * result). All injectable for tests (test-mcp-build-job covers the manager).
17
+ */
18
+ export declare function buildJobDeps(cwd: string): BuildJobDeps;
19
+ /**
20
+ * Register the build tools onto an MCP server. `getAppId` resolves the current
21
+ * project's Capgo app id; `deps` are the build-job mechanics (production via
22
+ * buildJobDeps; injectable fakes in tests).
23
+ */
24
+ export declare function registerBuildTools(server: ToolRegistrar, getAppId: () => Promise<string | undefined>, deps: BuildJobDeps): void;
25
+ export {};
@@ -0,0 +1,79 @@
1
+ import { z } from 'zod';
2
+ import { loadSavedCredentials, removeSavedCredentialKeys, updateSavedCredentials } from '../../credentials.js';
3
+ import { exportCredentialsToEnv } from '../env-export.js';
4
+ /** The canonical Capgo credential field names (buildCredentialsSchema). Used only for a gentle typo nudge. */
5
+ export declare const KNOWN_CREDENTIAL_KEYS: ReadonlySet<string>;
6
+ /**
7
+ * Screen a valueFile path BEFORE reading it. The MCP caller (an LLM) supplies this path, so an injected
8
+ * prompt could try to read ~/.ssh/id_ed25519 or another app's ~/.capgo-credentials into the store (which
9
+ * is then sent to the build server). Allow only credential-file extensions, and never read from a known
10
+ * secret directory. Returns an error string to surface to the caller, or null when the path is acceptable.
11
+ */
12
+ export declare function screenValueFilePath(filePath: string): string | null;
13
+ /**
14
+ * Screen an export targetPath: the .env (which holds real secrets) must stay INSIDE the project
15
+ * directory so the tool can never be steered into writing to e.g. /etc/cron.d or ~/.bashrc. Returns an
16
+ * error string, or null when the path stays in the project.
17
+ */
18
+ export declare function screenExportPath(targetPath: string, projectDir: string): string | null;
19
+ export interface CredentialsManageInput {
20
+ action: 'list' | 'export' | 'set' | 'remove';
21
+ platform?: 'ios' | 'android';
22
+ key?: string;
23
+ value?: string;
24
+ /** For set: a path to a credential file whose base64 becomes the value (keystores, .p12, .p8, service-account JSON). */
25
+ valueFile?: string;
26
+ path?: string;
27
+ overwrite?: boolean;
28
+ appId?: string;
29
+ }
30
+ /** Injectable seam — the registration wires the real credential store + env export; tests pass fakes. */
31
+ export interface CredentialsManageDeps {
32
+ getAppId: () => Promise<string | undefined>;
33
+ loadSavedCredentials: (appId: string) => Promise<Awaited<ReturnType<typeof loadSavedCredentials>>>;
34
+ updateSavedCredentials: typeof updateSavedCredentials;
35
+ removeSavedCredentialKeys: typeof removeSavedCredentialKeys;
36
+ exportCredentialsToEnv: typeof exportCredentialsToEnv;
37
+ /** Read a file and return its base64 — used by set + valueFile. Must reject symlinks. */
38
+ readFileBase64: (path: string) => Promise<string>;
39
+ /** True when a project-local .capgo-credentials.json holds this app — so set/remove write there, not global. */
40
+ localCredentialsExist: (appId: string) => Promise<boolean>;
41
+ }
42
+ /** Build the real deps (global credential store) bound to a getAppId resolver. */
43
+ export declare function buildCredentialsManageDeps(getAppId: () => Promise<string | undefined>): CredentialsManageDeps;
44
+ /**
45
+ * Run one credentials-manage action and return human-facing text (the MCP tool wraps it as a text block).
46
+ * Returns guidance instead of throwing for every expected "can't do that" case so the assistant can recover.
47
+ */
48
+ export declare function runCredentialsManage(input: CredentialsManageInput, deps: CredentialsManageDeps): Promise<string>;
49
+ /** zod shape for the tool's arguments. */
50
+ export declare const credentialsManageSchema: {
51
+ action: z.ZodEnum<{
52
+ set: "set";
53
+ list: "list";
54
+ export: "export";
55
+ remove: "remove";
56
+ }>;
57
+ platform: z.ZodOptional<z.ZodEnum<{
58
+ android: "android";
59
+ ios: "ios";
60
+ }>>;
61
+ key: z.ZodOptional<z.ZodString>;
62
+ value: z.ZodOptional<z.ZodString>;
63
+ valueFile: z.ZodOptional<z.ZodString>;
64
+ path: z.ZodOptional<z.ZodString>;
65
+ overwrite: z.ZodOptional<z.ZodBoolean>;
66
+ appId: z.ZodOptional<z.ZodString>;
67
+ };
68
+ /** Minimal MCP server surface this registers against (mirrors onboarding-tools' McpLike.tool). */
69
+ interface ToolRegistrar {
70
+ tool: (name: string, description: string, schema: Record<string, unknown>, handler: (args: CredentialsManageInput) => Promise<{
71
+ content: Array<{
72
+ type: 'text';
73
+ text: string;
74
+ }>;
75
+ }>) => unknown;
76
+ }
77
+ /** Register `capgo_builder_credentials_manage` on the given MCP server, bound to a getAppId resolver. */
78
+ export declare function registerCredentialsManageTool(server: ToolRegistrar, getAppId: () => Promise<string | undefined>, depsOverride?: CredentialsManageDeps): void;
79
+ export {};