@moda-ai/cli 1.22.1 → 1.22.2
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/cli-g8qs2tj9.js +9777 -0
- package/dist/cli-pwbvtes8.js +2312 -0
- package/dist/cli-qszcpda3.js +284 -0
- package/dist/cli.js +4775 -1159
- package/dist/index-6h0nc1r5.js +2765 -0
- package/dist/provision-j5gq8cvx.js +72 -0
- package/package.json +3 -2
- package/skills/integration/index.json +2 -2
- package/dist/agent-schemas.d.ts +0 -3
- package/dist/agent-schemas.js +0 -358
- package/dist/agent.d.ts +0 -5
- package/dist/agent.js +0 -477
- package/dist/analyst-tui.d.ts +0 -81
- package/dist/analyst-tui.js +0 -314
- package/dist/api-client.d.ts +0 -46
- package/dist/api-client.js +0 -120
- package/dist/ask-stream.d.ts +0 -146
- package/dist/ask-stream.js +0 -473
- package/dist/auth-storage.d.ts +0 -35
- package/dist/auth-storage.js +0 -159
- package/dist/auth.d.ts +0 -50
- package/dist/auth.js +0 -694
- package/dist/cli-session.d.ts +0 -26
- package/dist/cli-session.js +0 -169
- package/dist/cli.d.ts +0 -44
- package/dist/command-context.d.ts +0 -62
- package/dist/command-context.js +0 -57
- package/dist/command-registry.d.ts +0 -22
- package/dist/command-registry.js +0 -15
- package/dist/config.d.ts +0 -60
- package/dist/config.js +0 -110
- package/dist/doctor.d.ts +0 -79
- package/dist/doctor.js +0 -1182
- package/dist/errors.d.ts +0 -50
- package/dist/errors.js +0 -64
- package/dist/exit-funnel.d.ts +0 -14
- package/dist/exit-funnel.js +0 -53
- package/dist/harness-artifact-bodies.d.ts +0 -28
- package/dist/harness-artifact-bodies.js +0 -276
- package/dist/harness-candidates.d.ts +0 -77
- package/dist/harness-candidates.js +0 -482
- package/dist/harness-remote.d.ts +0 -135
- package/dist/harness-remote.js +0 -540
- package/dist/harness-report.d.ts +0 -145
- package/dist/harness-report.js +0 -1579
- package/dist/harness-sync-limits.d.ts +0 -8
- package/dist/harness-sync-limits.js +0 -21
- package/dist/harness.d.ts +0 -463
- package/dist/harness.js +0 -4009
- package/dist/init/index.d.ts +0 -78
- package/dist/init/index.js +0 -1442
- package/dist/init/mcp.d.ts +0 -2
- package/dist/init/mcp.js +0 -27
- package/dist/init/progress-board.d.ts +0 -80
- package/dist/init/progress-board.js +0 -225
- package/dist/init/rules.d.ts +0 -6
- package/dist/init/rules.js +0 -171
- package/dist/init/sdk-catalog.d.ts +0 -10
- package/dist/init/sdk-catalog.js +0 -80
- package/dist/init/sdk-guide.d.ts +0 -19
- package/dist/init/sdk-guide.js +0 -185
- package/dist/init/sdk-integration.d.ts +0 -53
- package/dist/init/sdk-integration.js +0 -835
- package/dist/init/sdk-protocol.d.ts +0 -135
- package/dist/init/sdk-protocol.js +0 -152
- package/dist/init/sdk-verification.d.ts +0 -27
- package/dist/init/sdk-verification.js +0 -123
- package/dist/init/tenant.d.ts +0 -67
- package/dist/init/tenant.js +0 -421
- package/dist/intelligence-schema.d.ts +0 -349
- package/dist/intelligence-schema.js +0 -174
- package/dist/keys.d.ts +0 -47
- package/dist/keys.js +0 -136
- package/dist/manifest.d.ts +0 -5
- package/dist/manifest.js +0 -114
- package/dist/markdown-terminal.d.ts +0 -49
- package/dist/markdown-terminal.js +0 -212
- package/dist/output.d.ts +0 -191
- package/dist/output.js +0 -624
- package/dist/production-intelligence.d.ts +0 -175
- package/dist/production-intelligence.js +0 -1430
- package/dist/profile-commands.d.ts +0 -10
- package/dist/profile-commands.js +0 -342
- package/dist/profiles.d.ts +0 -112
- package/dist/profiles.js +0 -573
- package/dist/prompts-ab.d.ts +0 -71
- package/dist/prompts-ab.js +0 -313
- package/dist/prompts-propose.d.ts +0 -15
- package/dist/prompts-propose.js +0 -212
- package/dist/prompts.d.ts +0 -58
- package/dist/prompts.js +0 -418
- package/dist/provision.d.ts +0 -28
- package/dist/provision.js +0 -104
- package/dist/redact.d.ts +0 -2
- package/dist/redact.js +0 -90
- package/dist/schemas.d.ts +0 -225
- package/dist/schemas.js +0 -126
- package/dist/skills-bundled.d.ts +0 -35
- package/dist/skills-bundled.js +0 -157
- package/dist/skills-manifest.d.ts +0 -33
- package/dist/skills-manifest.js +0 -244
- package/dist/skills.d.ts +0 -57
- package/dist/skills.js +0 -783
- package/dist/sync.d.ts +0 -5
- package/dist/sync.js +0 -36
- package/dist/telemetry.d.ts +0 -56
- package/dist/telemetry.js +0 -167
- package/dist/transforms.d.ts +0 -25
- package/dist/transforms.js +0 -102
- package/dist/tui.d.ts +0 -48
- package/dist/tui.js +0 -393
- package/dist/update-check.d.ts +0 -31
- package/dist/update-check.js +0 -141
- package/dist/workspace.d.ts +0 -12
- package/dist/workspace.js +0 -1294
package/dist/cli-session.d.ts
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { CliAuthError } from './errors.js';
|
|
2
|
-
import { type AuthSessionOptions, type StoredAuth } from './auth-storage.js';
|
|
3
|
-
/**
|
|
4
|
-
* Fire-and-forget sliding-expiry renewal, invoked on every authenticated
|
|
5
|
-
* request: a no-op unless the session is a moda_ct token inside the renewal
|
|
6
|
-
* window. Never awaited by callers, never throws, never holds the process
|
|
7
|
-
* open (unref'd socket); on success the stored expires_at is rewritten in
|
|
8
|
-
* place.
|
|
9
|
-
*/
|
|
10
|
-
export declare function scheduleRenewalIfNearExpiry(session: StoredAuth, authOptions: AuthSessionOptions): void;
|
|
11
|
-
/** The CliAuthError thrown whenever a stored moda_ct session has expired. */
|
|
12
|
-
export declare function cliSessionExpiredError(): CliAuthError;
|
|
13
|
-
/**
|
|
14
|
-
* Classify a 401 for a moda_ct session. Returns the CliAuthError to throw,
|
|
15
|
-
* or null when the renew probe says the token is actually alive (the caller
|
|
16
|
-
* then surfaces the original response unchanged).
|
|
17
|
-
*/
|
|
18
|
-
export declare function classifyModaCtUnauthorized(session: StoredAuth, authOptions: AuthSessionOptions): Promise<CliAuthError | null>;
|
|
19
|
-
/**
|
|
20
|
-
* Best-effort server-side revocation of a stored moda_ct session token,
|
|
21
|
-
* called by `moda auth logout` before local deletion. No-op for legacy
|
|
22
|
-
* auth0-kind sessions; all failures are swallowed (the local deletion is
|
|
23
|
-
* the contract).
|
|
24
|
-
*/
|
|
25
|
-
export declare function revokeCliSessionToken(options?: AuthSessionOptions): Promise<void>;
|
|
26
|
-
//# sourceMappingURL=cli-session.d.ts.map
|
package/dist/cli-session.js
DELETED
|
@@ -1,169 +0,0 @@
|
|
|
1
|
-
// src/cli-session.ts — moda_ct CLI session token lifecycle: renewal
|
|
2
|
-
// (sliding expiry), revocation, and 401 classification against the
|
|
3
|
-
// /api/cli/auth/* endpoints.
|
|
4
|
-
import { request as httpRequest } from 'node:http';
|
|
5
|
-
import { request as httpsRequest } from 'node:https';
|
|
6
|
-
import { resolveModaBaseUrl } from './config.js';
|
|
7
|
-
import { CliAuthError } from './errors.js';
|
|
8
|
-
import { isModaCtSession, loadAuthSession, persistAuthSession, } from './auth-storage.js';
|
|
9
|
-
// Background sliding-expiry renewal fires when a moda_ct session has less
|
|
10
|
-
// than this long left.
|
|
11
|
-
const RENEW_WINDOW_SECONDS = 7 * 86_400;
|
|
12
|
-
const RENEW_TIMEOUT_MS = 10_000;
|
|
13
|
-
// Synchronous renew probe used to classify a 401, and best-effort revoke on
|
|
14
|
-
// logout: both must never stall a command, so they get a tight budget.
|
|
15
|
-
const RENEW_PROBE_TIMEOUT_MS = 2_000;
|
|
16
|
-
const REVOKE_TIMEOUT_MS = 2_000;
|
|
17
|
-
/**
|
|
18
|
-
* POST an Authorization-bearer request to a CLI session lifecycle endpoint
|
|
19
|
-
* (/api/cli/auth/renew or /api/cli/auth/revoke) over raw node http/https.
|
|
20
|
-
* Not fetch: the background renewal must never delay process exit, and only
|
|
21
|
-
* a raw socket can be unref'd. Rejects on network failure or timeout.
|
|
22
|
-
*/
|
|
23
|
-
function postCliSessionEndpoint(path, token, timeoutMs, opts = {}) {
|
|
24
|
-
return new Promise((resolve, reject) => {
|
|
25
|
-
let url;
|
|
26
|
-
try {
|
|
27
|
-
// Resolve the origin from the same profile/env context the session was
|
|
28
|
-
// loaded with: a `--profile staging` session's renew/revoke must hit the
|
|
29
|
-
// staging backend that minted it, not the active/default profile's.
|
|
30
|
-
url = new URL(`${resolveModaBaseUrl(opts.authOptions)}${path}`);
|
|
31
|
-
}
|
|
32
|
-
catch (err) {
|
|
33
|
-
reject(err instanceof Error ? err : new Error(String(err)));
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
const requestFn = url.protocol === 'https:' ? httpsRequest : httpRequest;
|
|
37
|
-
const req = requestFn(url, {
|
|
38
|
-
method: 'POST',
|
|
39
|
-
headers: { Authorization: `Bearer ${token}` },
|
|
40
|
-
timeout: timeoutMs,
|
|
41
|
-
}, (res) => {
|
|
42
|
-
const chunks = [];
|
|
43
|
-
res.on('data', (chunk) => chunks.push(chunk));
|
|
44
|
-
res.on('end', () => {
|
|
45
|
-
resolve({
|
|
46
|
-
status: res.statusCode ?? 0,
|
|
47
|
-
body: Buffer.concat(chunks).toString('utf8'),
|
|
48
|
-
});
|
|
49
|
-
});
|
|
50
|
-
res.on('error', reject);
|
|
51
|
-
});
|
|
52
|
-
if (opts.unrefSocket) {
|
|
53
|
-
req.on('socket', (socket) => {
|
|
54
|
-
socket.unref();
|
|
55
|
-
});
|
|
56
|
-
}
|
|
57
|
-
req.on('timeout', () => {
|
|
58
|
-
req.destroy(new Error(`CLI session request timed out after ${timeoutMs}ms`));
|
|
59
|
-
});
|
|
60
|
-
req.on('error', reject);
|
|
61
|
-
req.end();
|
|
62
|
-
});
|
|
63
|
-
}
|
|
64
|
-
/**
|
|
65
|
-
* Parse a renew response body and rewrite the stored session's expiry in
|
|
66
|
-
* place, preserving the profile scoping the session was loaded with.
|
|
67
|
-
* Best-effort: an unreadable or incomplete body is simply ignored.
|
|
68
|
-
*/
|
|
69
|
-
function persistRenewedExpiry(session, body, authOptions) {
|
|
70
|
-
try {
|
|
71
|
-
const parsed = JSON.parse(body);
|
|
72
|
-
const expiresAtMs = typeof parsed.expires_at === 'string' ? Date.parse(parsed.expires_at) : NaN;
|
|
73
|
-
if (!Number.isFinite(expiresAtMs))
|
|
74
|
-
return;
|
|
75
|
-
persistAuthSession({ ...session, expires_at: Math.floor(expiresAtMs / 1000) }, authOptions);
|
|
76
|
-
}
|
|
77
|
-
catch {
|
|
78
|
-
// Best-effort persistence only.
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
// Stampede guard: at most one background renewal in flight per process.
|
|
82
|
-
let renewInFlight = false;
|
|
83
|
-
/**
|
|
84
|
-
* Fire-and-forget sliding-expiry renewal, invoked on every authenticated
|
|
85
|
-
* request: a no-op unless the session is a moda_ct token inside the renewal
|
|
86
|
-
* window. Never awaited by callers, never throws, never holds the process
|
|
87
|
-
* open (unref'd socket); on success the stored expires_at is rewritten in
|
|
88
|
-
* place.
|
|
89
|
-
*/
|
|
90
|
-
export function scheduleRenewalIfNearExpiry(session, authOptions) {
|
|
91
|
-
if (!isModaCtSession(session))
|
|
92
|
-
return;
|
|
93
|
-
if (session.expires_at - Date.now() / 1000 >= RENEW_WINDOW_SECONDS)
|
|
94
|
-
return;
|
|
95
|
-
if (renewInFlight)
|
|
96
|
-
return;
|
|
97
|
-
renewInFlight = true;
|
|
98
|
-
void (async () => {
|
|
99
|
-
try {
|
|
100
|
-
const result = await postCliSessionEndpoint('/api/cli/auth/renew', session.access_token, RENEW_TIMEOUT_MS, { unrefSocket: true, authOptions });
|
|
101
|
-
if (result.status !== 200)
|
|
102
|
-
return;
|
|
103
|
-
persistRenewedExpiry(session, result.body, authOptions);
|
|
104
|
-
}
|
|
105
|
-
catch {
|
|
106
|
-
// Silent by design: renewal is opportunistic, the command result must
|
|
107
|
-
// not depend on it.
|
|
108
|
-
}
|
|
109
|
-
finally {
|
|
110
|
-
renewInFlight = false;
|
|
111
|
-
}
|
|
112
|
-
})();
|
|
113
|
-
}
|
|
114
|
-
/** The CliAuthError thrown whenever a stored moda_ct session has expired. */
|
|
115
|
-
export function cliSessionExpiredError() {
|
|
116
|
-
return new CliAuthError('The stored CLI session token has expired. Run "moda auth login" to sign in again.', { reason: 'token_expired', login_command: ['moda', 'auth', 'login'] });
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Classify a 401 for a moda_ct session. Returns the CliAuthError to throw,
|
|
120
|
-
* or null when the renew probe says the token is actually alive (the caller
|
|
121
|
-
* then surfaces the original response unchanged).
|
|
122
|
-
*/
|
|
123
|
-
export async function classifyModaCtUnauthorized(session, authOptions) {
|
|
124
|
-
const loginCommand = ['moda', 'auth', 'login'];
|
|
125
|
-
if (Date.now() / 1000 > session.expires_at) {
|
|
126
|
-
return cliSessionExpiredError();
|
|
127
|
-
}
|
|
128
|
-
let probe;
|
|
129
|
-
try {
|
|
130
|
-
probe = await postCliSessionEndpoint('/api/cli/auth/renew', session.access_token, RENEW_PROBE_TIMEOUT_MS, { authOptions });
|
|
131
|
-
}
|
|
132
|
-
catch {
|
|
133
|
-
return new CliAuthError('The Moda API rejected the stored CLI session token, and the renewal check could not reach the server. ' +
|
|
134
|
-
'The token has not expired, so this is likely transient: retry the command instead of logging in again.', { reason: 'renew_failed', login_command: loginCommand });
|
|
135
|
-
}
|
|
136
|
-
if (probe.status === 401) {
|
|
137
|
-
return new CliAuthError('The stored CLI session token has been revoked. Run "moda auth login" to sign in again.', { reason: 'token_revoked', login_command: loginCommand });
|
|
138
|
-
}
|
|
139
|
-
if (probe.status === 200) {
|
|
140
|
-
// The token is demonstrably alive (the probe just slid its expiry) but
|
|
141
|
-
// the original request still 401'd; persist the fresh expiry and let the
|
|
142
|
-
// caller see the original response.
|
|
143
|
-
persistRenewedExpiry(session, probe.body, authOptions);
|
|
144
|
-
return null;
|
|
145
|
-
}
|
|
146
|
-
// Any other renew status (e.g. a 5xx) is indistinguishable from a
|
|
147
|
-
// transient server problem: same retry guidance as a network failure.
|
|
148
|
-
return new CliAuthError('The Moda API rejected the stored CLI session token, and the renewal check failed ' +
|
|
149
|
-
`(HTTP ${probe.status}). The token has not expired, so this is likely transient: ` +
|
|
150
|
-
'retry the command instead of logging in again.', { reason: 'renew_failed', login_command: loginCommand });
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Best-effort server-side revocation of a stored moda_ct session token,
|
|
154
|
-
* called by `moda auth logout` before local deletion. No-op for legacy
|
|
155
|
-
* auth0-kind sessions; all failures are swallowed (the local deletion is
|
|
156
|
-
* the contract).
|
|
157
|
-
*/
|
|
158
|
-
export async function revokeCliSessionToken(options = {}) {
|
|
159
|
-
const session = loadAuthSession({ ...options, includeExpired: true });
|
|
160
|
-
if (!session || !isModaCtSession(session))
|
|
161
|
-
return;
|
|
162
|
-
try {
|
|
163
|
-
await postCliSessionEndpoint('/api/cli/auth/revoke', session.access_token, REVOKE_TIMEOUT_MS, { authOptions: options });
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
// Best-effort: logout proceeds with local deletion regardless.
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
//# sourceMappingURL=cli-session.js.map
|
package/dist/cli.d.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
import { type TelemetryErrorType } from './telemetry.js';
|
|
3
|
-
import { type CommandContext } from './command-context.js';
|
|
4
|
-
import { type CommandDefinition } from './command-registry.js';
|
|
5
|
-
export { CliInputError } from './errors.js';
|
|
6
|
-
export interface ParsedArgs {
|
|
7
|
-
command: string;
|
|
8
|
-
positional: string | undefined;
|
|
9
|
-
positionals: string[];
|
|
10
|
-
flags: Record<string, string>;
|
|
11
|
-
}
|
|
12
|
-
export declare function parseArgs(argv: string[]): ParsedArgs;
|
|
13
|
-
export declare function flagsToArgs(flags: Record<string, string>, positionalKey?: string, positionalValue?: string): Record<string, unknown>;
|
|
14
|
-
/**
|
|
15
|
-
* Build the argv the caller should re-run to resume an interrupted command,
|
|
16
|
-
* echoing back the raw flags exactly as parsed (so per-invocation opt-outs
|
|
17
|
-
* like --no-telemetry survive). Treats `--flag` and `--flag=true` identically.
|
|
18
|
-
*
|
|
19
|
-
* Limitation: positional arguments are not included — the current callers
|
|
20
|
-
* (`moda init`, `moda provision`) take none. Extend the signature before
|
|
21
|
-
* reusing this for a command with positionals.
|
|
22
|
-
*/
|
|
23
|
-
export declare function buildResumeCommand(command: string, flags: Record<string, string>): string[];
|
|
24
|
-
/**
|
|
25
|
-
* Coarse caller identity for the feedback body's `agent` field. Same
|
|
26
|
-
* truthy-env semantics as the agent-environment detection in output.ts;
|
|
27
|
-
* never sourced from flags, because `--agent` is the output-mode flag.
|
|
28
|
-
*/
|
|
29
|
-
export declare function detectCallerAgent(env: NodeJS.ProcessEnv): string;
|
|
30
|
-
export declare function runCommand(command: string, positional: string | undefined, flags: Record<string, string>, positionals?: string[], context?: CommandContext): Promise<number>;
|
|
31
|
-
interface CommandDispatchResult {
|
|
32
|
-
exitCode: number;
|
|
33
|
-
apiKey?: string;
|
|
34
|
-
}
|
|
35
|
-
interface CliCommandDefinition extends CommandDefinition<CommandContext, CommandDispatchResult> {
|
|
36
|
-
validateConfigBeforeRun: boolean;
|
|
37
|
-
resetApiRequestCountBeforeRun: boolean;
|
|
38
|
-
telemetry: 'none' | 'result' | 'result-and-error';
|
|
39
|
-
}
|
|
40
|
-
export declare const commandRegistry: import("./command-registry.js").CommandRegistry<CommandContext, CommandDispatchResult, CliCommandDefinition>;
|
|
41
|
-
export declare function classifyCliError(error: unknown): TelemetryErrorType;
|
|
42
|
-
export declare function printCliError(error: unknown): void;
|
|
43
|
-
export declare function dispatchParsedCommand(parsed: ParsedArgs, startedAt?: number): Promise<number>;
|
|
44
|
-
//# sourceMappingURL=cli.d.ts.map
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { type CliOutput, type CliOutputMode } from './output.js';
|
|
2
|
-
export interface CommandContextInput {
|
|
3
|
-
command: string;
|
|
4
|
-
positional: string | undefined;
|
|
5
|
-
positionals: string[];
|
|
6
|
-
flags: Record<string, string>;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Response-derived telemetry a handler can surface back to the dispatcher after
|
|
10
|
-
* the API call completes. Static fields (surface, requested mode, query length,
|
|
11
|
-
* etc.) are derived from the command + flags in the dispatcher and don't belong
|
|
12
|
-
* here — only values that require the runtime response are recorded.
|
|
13
|
-
*/
|
|
14
|
-
export interface CommandTelemetryMeta {
|
|
15
|
-
search_mode_effective?: 'na' | 'keyword' | 'semantic' | 'hybrid';
|
|
16
|
-
result_count?: number;
|
|
17
|
-
has_more?: 'na' | 'no' | 'yes';
|
|
18
|
-
}
|
|
19
|
-
export interface CommandContext {
|
|
20
|
-
command: string;
|
|
21
|
-
positional: string | undefined;
|
|
22
|
-
positionals: string[];
|
|
23
|
-
flags: Record<string, string>;
|
|
24
|
-
rawFlags: Record<string, string>;
|
|
25
|
-
startedAt: number;
|
|
26
|
-
cwd: string;
|
|
27
|
-
env: NodeJS.ProcessEnv;
|
|
28
|
-
outputMode: CliOutputMode;
|
|
29
|
-
output: CliOutput;
|
|
30
|
-
profile: string | undefined;
|
|
31
|
-
dryRun: boolean;
|
|
32
|
-
yes: boolean;
|
|
33
|
-
quiet: boolean;
|
|
34
|
-
verbose: boolean;
|
|
35
|
-
interactive: boolean;
|
|
36
|
-
/** Merge response-derived telemetry; safe to call multiple times. */
|
|
37
|
-
recordTelemetry(meta: Partial<CommandTelemetryMeta>): void;
|
|
38
|
-
/** Snapshot of telemetry recorded so far by the handler. */
|
|
39
|
-
getTelemetryMeta(): CommandTelemetryMeta;
|
|
40
|
-
}
|
|
41
|
-
/**
|
|
42
|
-
* Normalize a raw flag/env value to a trimmed non-empty string. Accepts
|
|
43
|
-
* non-string values because flagsToArgs number-coerces numeric-looking flag
|
|
44
|
-
* values (which must never happen to tenant ids, profile names, or labels);
|
|
45
|
-
* empty values (`--label=`) become undefined so defaults apply.
|
|
46
|
-
*/
|
|
47
|
-
export declare function stringOption(value: unknown): string | undefined;
|
|
48
|
-
export declare function createCommandContext(input: CommandContextInput, options?: {
|
|
49
|
-
commandName?: string;
|
|
50
|
-
commandFlags?: Record<string, string>;
|
|
51
|
-
rawFlags?: Record<string, string>;
|
|
52
|
-
startedAt?: number;
|
|
53
|
-
cwd?: string;
|
|
54
|
-
env?: NodeJS.ProcessEnv;
|
|
55
|
-
/**
|
|
56
|
-
* Pre-resolved output mode from the dispatcher (TTY/env auto-detection).
|
|
57
|
-
* When omitted we fall back to flag-only resolution so direct callers
|
|
58
|
-
* (tests, internal helpers) keep their explicit behavior.
|
|
59
|
-
*/
|
|
60
|
-
outputMode?: CliOutputMode;
|
|
61
|
-
}): CommandContext;
|
|
62
|
-
//# sourceMappingURL=command-context.d.ts.map
|
package/dist/command-context.js
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
import { createCliOutput, outputModeFromFlags } from './output.js';
|
|
2
|
-
function flagEnabled(flags, key) {
|
|
3
|
-
return flags[key] === 'true';
|
|
4
|
-
}
|
|
5
|
-
/**
|
|
6
|
-
* Normalize a raw flag/env value to a trimmed non-empty string. Accepts
|
|
7
|
-
* non-string values because flagsToArgs number-coerces numeric-looking flag
|
|
8
|
-
* values (which must never happen to tenant ids, profile names, or labels);
|
|
9
|
-
* empty values (`--label=`) become undefined so defaults apply.
|
|
10
|
-
*/
|
|
11
|
-
export function stringOption(value) {
|
|
12
|
-
if (value === undefined || value === null)
|
|
13
|
-
return undefined;
|
|
14
|
-
const text = String(value).trim();
|
|
15
|
-
return text.length > 0 ? text : undefined;
|
|
16
|
-
}
|
|
17
|
-
export function createCommandContext(input, options = {}) {
|
|
18
|
-
const flags = options.commandFlags ?? input.flags;
|
|
19
|
-
const rawFlags = options.rawFlags ?? input.flags;
|
|
20
|
-
const outputMode = options.outputMode ?? outputModeFromFlags(flags);
|
|
21
|
-
const quiet = flagEnabled(flags, 'quiet');
|
|
22
|
-
const interactive = outputMode === 'human' &&
|
|
23
|
-
!quiet &&
|
|
24
|
-
!flagEnabled(flags, 'yes') &&
|
|
25
|
-
process.stdin.isTTY === true &&
|
|
26
|
-
process.stderr.isTTY === true;
|
|
27
|
-
const telemetryMeta = {};
|
|
28
|
-
return {
|
|
29
|
-
command: options.commandName ?? input.command,
|
|
30
|
-
positional: input.positional,
|
|
31
|
-
positionals: input.positionals,
|
|
32
|
-
flags,
|
|
33
|
-
rawFlags,
|
|
34
|
-
startedAt: options.startedAt ?? Date.now(),
|
|
35
|
-
cwd: options.cwd ?? process.cwd(),
|
|
36
|
-
env: options.env ?? process.env,
|
|
37
|
-
outputMode,
|
|
38
|
-
output: createCliOutput({
|
|
39
|
-
command: options.commandName ?? input.command,
|
|
40
|
-
mode: outputMode,
|
|
41
|
-
quiet,
|
|
42
|
-
}),
|
|
43
|
-
profile: flags.profile,
|
|
44
|
-
dryRun: flagEnabled(flags, 'dry-run'),
|
|
45
|
-
yes: flagEnabled(flags, 'yes'),
|
|
46
|
-
quiet,
|
|
47
|
-
verbose: flagEnabled(flags, 'verbose'),
|
|
48
|
-
interactive,
|
|
49
|
-
recordTelemetry(meta) {
|
|
50
|
-
Object.assign(telemetryMeta, meta);
|
|
51
|
-
},
|
|
52
|
-
getTelemetryMeta() {
|
|
53
|
-
return telemetryMeta;
|
|
54
|
-
},
|
|
55
|
-
};
|
|
56
|
-
}
|
|
57
|
-
//# sourceMappingURL=command-context.js.map
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import type { CliOutputMode } from './output.js';
|
|
2
|
-
export type CommandAuthRequirement = 'none' | 'api-key';
|
|
3
|
-
export type CommandMutability = 'read' | 'write';
|
|
4
|
-
export interface CommandMetadata {
|
|
5
|
-
name: string;
|
|
6
|
-
aliases?: string[];
|
|
7
|
-
description: string;
|
|
8
|
-
examples: string[];
|
|
9
|
-
auth: CommandAuthRequirement;
|
|
10
|
-
outputModes: readonly CliOutputMode[];
|
|
11
|
-
mutability: CommandMutability;
|
|
12
|
-
}
|
|
13
|
-
export interface CommandDefinition<TContext, TResult> extends CommandMetadata {
|
|
14
|
-
handler: (context: TContext) => Promise<TResult>;
|
|
15
|
-
}
|
|
16
|
-
export interface CommandRegistry<TContext, TResult, TDefinition extends CommandDefinition<TContext, TResult> = CommandDefinition<TContext, TResult>> {
|
|
17
|
-
all(): TDefinition[];
|
|
18
|
-
find(name: string): TDefinition | undefined;
|
|
19
|
-
has(name: string): boolean;
|
|
20
|
-
}
|
|
21
|
-
export declare function createCommandRegistry<TContext, TResult, TDefinition extends CommandDefinition<TContext, TResult>>(definitions: TDefinition[]): CommandRegistry<TContext, TResult, TDefinition>;
|
|
22
|
-
//# sourceMappingURL=command-registry.d.ts.map
|
package/dist/command-registry.js
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
export function createCommandRegistry(definitions) {
|
|
2
|
-
const lookup = new Map();
|
|
3
|
-
for (const definition of definitions) {
|
|
4
|
-
lookup.set(definition.name, definition);
|
|
5
|
-
for (const alias of definition.aliases ?? []) {
|
|
6
|
-
lookup.set(alias, definition);
|
|
7
|
-
}
|
|
8
|
-
}
|
|
9
|
-
return {
|
|
10
|
-
all: () => [...definitions],
|
|
11
|
-
find: (name) => lookup.get(name),
|
|
12
|
-
has: (name) => lookup.has(name),
|
|
13
|
-
};
|
|
14
|
-
}
|
|
15
|
-
//# sourceMappingURL=command-registry.js.map
|
package/dist/config.d.ts
DELETED
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { type ProfileIOOptions } from './profiles.js';
|
|
2
|
-
export declare const VERSION: string;
|
|
3
|
-
export declare const MODA_BASE_URL: string;
|
|
4
|
-
/**
|
|
5
|
-
* Persisted CLI configuration written by `moda init` to `~/.moda/config.json`
|
|
6
|
-
* (mode 0600). This lets the snapshot/session-end hook authenticate without
|
|
7
|
-
* the user having to export MODA_API_KEY into whatever shell launched Claude
|
|
8
|
-
* (e.g. via Infisical, a login shell, or a `.claude/settings.json` env block).
|
|
9
|
-
* Mirrors the existing token persistence in `auth.ts`.
|
|
10
|
-
*/
|
|
11
|
-
export interface CliConfig {
|
|
12
|
-
api_key?: string;
|
|
13
|
-
ingest_url?: string;
|
|
14
|
-
tenant_id?: string;
|
|
15
|
-
}
|
|
16
|
-
export declare function loadCliConfig(options?: ProfileIOOptions): CliConfig;
|
|
17
|
-
/**
|
|
18
|
-
* Merge-and-write the persisted config. Always chmod 0600 since it holds the
|
|
19
|
-
* API key. Best-effort: never throws on chmod failure (some filesystems).
|
|
20
|
-
* `options.profile` scopes the best-effort profile sync (e.g. `moda init
|
|
21
|
-
* --profile staging`), so the key is synced to the requested profile rather
|
|
22
|
-
* than whatever profile happens to be active.
|
|
23
|
-
*/
|
|
24
|
-
export declare function saveCliConfig(update: CliConfig, options?: ProfileIOOptions): void;
|
|
25
|
-
/**
|
|
26
|
-
* Resolve the API key: prefer the environment (so CI / explicit exports win),
|
|
27
|
-
* then fall back to the persisted `~/.moda/config.json`. Read lazily so a
|
|
28
|
-
* long-lived process (or a test) sees the current value.
|
|
29
|
-
*/
|
|
30
|
-
export declare function resolveApiKey(options?: ProfileIOOptions): string | undefined;
|
|
31
|
-
/**
|
|
32
|
-
* Signed CLI keys embed their tenant: the format is
|
|
33
|
-
* moda_sk_<base64url("v1:keyId:tenantId:timestamp:signature")> — see
|
|
34
|
-
* createApiKey/parseAndVerifySignedKey in
|
|
35
|
-
* apps/moda-backend/src/api-keys/api-keys.service.ts. The server derives the
|
|
36
|
-
* upload destination tenant from the key alone, so this is the only
|
|
37
|
-
* client-side tenant source that matches where data actually lands
|
|
38
|
-
* (config / MODA_TENANT_ID can disagree with a shadowing env key). The HMAC
|
|
39
|
-
* signature can only be verified server-side; treat the result as
|
|
40
|
-
* informational.
|
|
41
|
-
*/
|
|
42
|
-
export declare function embeddedTenantIdFromApiKey(key: string): string | undefined;
|
|
43
|
-
/**
|
|
44
|
-
* Resolve the ingest worker base URL used by `moda workspace snapshot`.
|
|
45
|
-
* Env override -> active profile -> legacy config -> production default.
|
|
46
|
-
* Loopback URLs are rejected unless the active profile is `local`.
|
|
47
|
-
*/
|
|
48
|
-
export declare function resolveIngestUrl(options?: ProfileIOOptions): string;
|
|
49
|
-
/**
|
|
50
|
-
* Resolve the active tenant id: env override first, then the persisted
|
|
51
|
-
* `~/.moda/config.json` written by `moda init`. Used by the local dev
|
|
52
|
-
* orchestrator hook so the user doesn't have to export MODA_TENANT_ID.
|
|
53
|
-
*/
|
|
54
|
-
export declare function resolveTenantId(options?: ProfileIOOptions): string | undefined;
|
|
55
|
-
export declare const MODA_API_KEY: string | undefined;
|
|
56
|
-
export declare const MODA_INGEST_URL: string;
|
|
57
|
-
export declare function resolveModaBaseUrl(options?: ProfileIOOptions): string;
|
|
58
|
-
export declare function validateConfig(): void;
|
|
59
|
-
export declare function legacyConfigPath(): string;
|
|
60
|
-
//# sourceMappingURL=config.d.ts.map
|
package/dist/config.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { readFileSync } from 'node:fs';
|
|
2
|
-
import { DEFAULT_INGEST_URL, PROD_BASE_URL, getLegacyConfigPath, loadLegacyCliConfig, resolveApiKeyFromActiveProfile, resolveBaseUrl, resolveIngestUrl as resolveProfileIngestUrl, resolveTenantIdFromActiveProfile, syncLegacyConfigToProfile, writeLegacyCliConfig, } from './profiles.js';
|
|
3
|
-
import { CliAuthError } from './errors.js';
|
|
4
|
-
const pkg = JSON.parse(readFileSync(new URL('../package.json', import.meta.url), 'utf8'));
|
|
5
|
-
export const VERSION = pkg.version;
|
|
6
|
-
// Canonical host is moda.dev. The www host 308-redirects to the apex, and
|
|
7
|
-
// cross-host redirects strip the Authorization header (fetch/undici), so using
|
|
8
|
-
// www breaks `moda init`'s authenticated calls with a 401. Default to the
|
|
9
|
-
// canonical host directly; resolveBaseUrl() also rewrites legacy www URLs.
|
|
10
|
-
export const MODA_BASE_URL = resolveBaseUrl();
|
|
11
|
-
export function loadCliConfig(options = {}) {
|
|
12
|
-
return loadLegacyCliConfig(options);
|
|
13
|
-
}
|
|
14
|
-
/**
|
|
15
|
-
* Merge-and-write the persisted config. Always chmod 0600 since it holds the
|
|
16
|
-
* API key. Best-effort: never throws on chmod failure (some filesystems).
|
|
17
|
-
* `options.profile` scopes the best-effort profile sync (e.g. `moda init
|
|
18
|
-
* --profile staging`), so the key is synced to the requested profile rather
|
|
19
|
-
* than whatever profile happens to be active.
|
|
20
|
-
*/
|
|
21
|
-
export function saveCliConfig(update, options = {}) {
|
|
22
|
-
const merged = writeLegacyCliConfig(update, options);
|
|
23
|
-
try {
|
|
24
|
-
syncLegacyConfigToProfile(merged, options);
|
|
25
|
-
}
|
|
26
|
-
catch {
|
|
27
|
-
// The legacy config write is the compatibility contract; profile sync is a
|
|
28
|
-
// best-effort migration aid until profile commands own the flow.
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Resolve the API key: prefer the environment (so CI / explicit exports win),
|
|
33
|
-
* then fall back to the persisted `~/.moda/config.json`. Read lazily so a
|
|
34
|
-
* long-lived process (or a test) sees the current value.
|
|
35
|
-
*/
|
|
36
|
-
export function resolveApiKey(options = {}) {
|
|
37
|
-
const env = options.env ?? process.env;
|
|
38
|
-
return (env.MODA_API_KEY ||
|
|
39
|
-
resolveApiKeyFromActiveProfile(options) ||
|
|
40
|
-
loadCliConfig(options).api_key ||
|
|
41
|
-
undefined);
|
|
42
|
-
}
|
|
43
|
-
const SIGNED_API_KEY_PREFIX = 'moda_sk_';
|
|
44
|
-
const SIGNED_API_KEY_VERSION = 'v1';
|
|
45
|
-
/**
|
|
46
|
-
* Signed CLI keys embed their tenant: the format is
|
|
47
|
-
* moda_sk_<base64url("v1:keyId:tenantId:timestamp:signature")> — see
|
|
48
|
-
* createApiKey/parseAndVerifySignedKey in
|
|
49
|
-
* apps/moda-backend/src/api-keys/api-keys.service.ts. The server derives the
|
|
50
|
-
* upload destination tenant from the key alone, so this is the only
|
|
51
|
-
* client-side tenant source that matches where data actually lands
|
|
52
|
-
* (config / MODA_TENANT_ID can disagree with a shadowing env key). The HMAC
|
|
53
|
-
* signature can only be verified server-side; treat the result as
|
|
54
|
-
* informational.
|
|
55
|
-
*/
|
|
56
|
-
export function embeddedTenantIdFromApiKey(key) {
|
|
57
|
-
if (!key.startsWith(SIGNED_API_KEY_PREFIX))
|
|
58
|
-
return undefined;
|
|
59
|
-
try {
|
|
60
|
-
const decoded = Buffer.from(key.slice(SIGNED_API_KEY_PREFIX.length), 'base64url').toString('utf8');
|
|
61
|
-
// Expected format: version:keyId:tenantId:timestamp:signature
|
|
62
|
-
const parts = decoded.split(':');
|
|
63
|
-
if (parts.length !== 5 || parts[0] !== SIGNED_API_KEY_VERSION)
|
|
64
|
-
return undefined;
|
|
65
|
-
return parts[2] || undefined;
|
|
66
|
-
}
|
|
67
|
-
catch {
|
|
68
|
-
return undefined;
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
/**
|
|
72
|
-
* Resolve the ingest worker base URL used by `moda workspace snapshot`.
|
|
73
|
-
* Env override -> active profile -> legacy config -> production default.
|
|
74
|
-
* Loopback URLs are rejected unless the active profile is `local`.
|
|
75
|
-
*/
|
|
76
|
-
export function resolveIngestUrl(options = {}) {
|
|
77
|
-
return resolveProfileIngestUrl(options);
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* Resolve the active tenant id: env override first, then the persisted
|
|
81
|
-
* `~/.moda/config.json` written by `moda init`. Used by the local dev
|
|
82
|
-
* orchestrator hook so the user doesn't have to export MODA_TENANT_ID.
|
|
83
|
-
*/
|
|
84
|
-
export function resolveTenantId(options = {}) {
|
|
85
|
-
const env = options.env ?? process.env;
|
|
86
|
-
return (env.MODA_TENANT_ID ||
|
|
87
|
-
resolveTenantIdFromActiveProfile(options) ||
|
|
88
|
-
loadCliConfig(options).tenant_id ||
|
|
89
|
-
undefined);
|
|
90
|
-
}
|
|
91
|
-
// Back-compat exports. Prefer resolveApiKey()/resolveIngestUrl() for the lazy
|
|
92
|
-
// file fallback; these only reflect the environment at module-load time.
|
|
93
|
-
export const MODA_API_KEY = process.env.MODA_API_KEY;
|
|
94
|
-
export const MODA_INGEST_URL = process.env.MODA_INGEST_URL || DEFAULT_INGEST_URL;
|
|
95
|
-
export function resolveModaBaseUrl(options = {}) {
|
|
96
|
-
return resolveBaseUrl(options) || PROD_BASE_URL;
|
|
97
|
-
}
|
|
98
|
-
export function validateConfig() {
|
|
99
|
-
if (!resolveApiKey()) {
|
|
100
|
-
throw new CliAuthError('No Moda API key found. Set MODA_API_KEY or run "moda init".', {
|
|
101
|
-
reason: 'no_stored_credentials',
|
|
102
|
-
login_command: ['moda', 'init'],
|
|
103
|
-
}, 'Get your API key from https://moda.dev/settings');
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
// Kept for callers/tests that need the legacy path during migration.
|
|
107
|
-
export function legacyConfigPath() {
|
|
108
|
-
return getLegacyConfigPath();
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=config.js.map
|
package/dist/doctor.d.ts
DELETED
|
@@ -1,79 +0,0 @@
|
|
|
1
|
-
import type { CommandContext } from './command-context.js';
|
|
2
|
-
export type DoctorCheckStatus = 'pass' | 'warning' | 'fail' | 'skipped';
|
|
3
|
-
export type DoctorSeverity = 'info' | 'warning' | 'critical';
|
|
4
|
-
export interface DoctorEvidence {
|
|
5
|
-
label: string;
|
|
6
|
-
value: string;
|
|
7
|
-
}
|
|
8
|
-
export interface DoctorCheck {
|
|
9
|
-
id: string;
|
|
10
|
-
group: string;
|
|
11
|
-
title: string;
|
|
12
|
-
status: DoctorCheckStatus;
|
|
13
|
-
severity: DoctorSeverity;
|
|
14
|
-
evidence: DoctorEvidence[];
|
|
15
|
-
remediation?: string;
|
|
16
|
-
nextCommand?: string;
|
|
17
|
-
}
|
|
18
|
-
export interface DoctorReport {
|
|
19
|
-
schemaVersion: 'doctor.v0.1';
|
|
20
|
-
generatedAt: string;
|
|
21
|
-
profile: {
|
|
22
|
-
active: string;
|
|
23
|
-
requested?: string;
|
|
24
|
-
};
|
|
25
|
-
summary: {
|
|
26
|
-
status: DoctorCheckStatus;
|
|
27
|
-
pass: number;
|
|
28
|
-
warning: number;
|
|
29
|
-
fail: number;
|
|
30
|
-
skipped: number;
|
|
31
|
-
};
|
|
32
|
-
checks: DoctorCheck[];
|
|
33
|
-
nextCommands: string[];
|
|
34
|
-
fixPlan: Array<{
|
|
35
|
-
checkId: string;
|
|
36
|
-
command?: string;
|
|
37
|
-
action: string;
|
|
38
|
-
}>;
|
|
39
|
-
}
|
|
40
|
-
export interface StatusPayload {
|
|
41
|
-
schemaVersion: 'status.v0.1';
|
|
42
|
-
generatedAt: string;
|
|
43
|
-
status: DoctorCheckStatus;
|
|
44
|
-
activeProfile: string;
|
|
45
|
-
auth: {
|
|
46
|
-
apiKey: 'configured' | 'missing';
|
|
47
|
-
};
|
|
48
|
-
workspace: {
|
|
49
|
-
tenantId: string | null;
|
|
50
|
-
baseUrl: string;
|
|
51
|
-
ingestUrl: string;
|
|
52
|
-
};
|
|
53
|
-
dataFlow: DoctorCheckStatus;
|
|
54
|
-
harness: DoctorCheckStatus;
|
|
55
|
-
harnessSync: DoctorCheckStatus;
|
|
56
|
-
harnessReport: DoctorCheckStatus;
|
|
57
|
-
shadowSpark: DoctorCheckStatus;
|
|
58
|
-
prompts: DoctorCheckStatus;
|
|
59
|
-
skills: DoctorCheckStatus;
|
|
60
|
-
topBrokenCheck: {
|
|
61
|
-
id: string;
|
|
62
|
-
status: DoctorCheckStatus;
|
|
63
|
-
severity: DoctorSeverity;
|
|
64
|
-
nextCommand?: string;
|
|
65
|
-
} | null;
|
|
66
|
-
nextCommands: string[];
|
|
67
|
-
}
|
|
68
|
-
interface DoctorOptions {
|
|
69
|
-
offline: boolean;
|
|
70
|
-
}
|
|
71
|
-
export declare function runDoctorCommand(context: CommandContext): Promise<{
|
|
72
|
-
exitCode: number;
|
|
73
|
-
}>;
|
|
74
|
-
export declare function runStatusCommand(context: CommandContext): Promise<{
|
|
75
|
-
exitCode: number;
|
|
76
|
-
}>;
|
|
77
|
-
export declare function buildDoctorReport(context: CommandContext, options: DoctorOptions): Promise<DoctorReport>;
|
|
78
|
-
export {};
|
|
79
|
-
//# sourceMappingURL=doctor.d.ts.map
|