hub-launch 1.22.0 → 1.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +19 -0
- package/README.md +5 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +66 -23
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/launch.d.ts +14 -2
- package/dist/commands/launch.d.ts.map +1 -1
- package/dist/commands/launch.js +115 -51
- package/dist/commands/launch.js.map +1 -1
- package/dist/commands/schedule.d.ts.map +1 -1
- package/dist/commands/schedule.js +8 -7
- package/dist/commands/schedule.js.map +1 -1
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +4 -1
- package/dist/config/index.js.map +1 -1
- package/dist/templates/skills/hula-help/SKILL.md +1 -1
- package/dist/templates/skills/hula-schedule/SKILL.md +3 -3
- package/dist/types/config.schema.d.ts +34 -3
- package/dist/types/config.schema.d.ts.map +1 -1
- package/dist/types/config.schema.js +35 -1
- package/dist/types/config.schema.js.map +1 -1
- package/dist/utils/config-file-edit.d.ts +8 -4
- package/dist/utils/config-file-edit.d.ts.map +1 -1
- package/dist/utils/config-file-edit.js +13 -9
- package/dist/utils/config-file-edit.js.map +1 -1
- package/dist/utils/config-parser.d.ts.map +1 -1
- package/dist/utils/config-parser.js +4 -0
- package/dist/utils/config-parser.js.map +1 -1
- package/dist/utils/env-vars.d.ts.map +1 -1
- package/dist/utils/env-vars.js +4 -0
- package/dist/utils/env-vars.js.map +1 -1
- package/dist/utils/provider-credentials.d.ts +54 -0
- package/dist/utils/provider-credentials.d.ts.map +1 -0
- package/dist/utils/provider-credentials.js +83 -0
- package/dist/utils/provider-credentials.js.map +1 -0
- package/package.json +2 -2
- package/dist/utils/ephemeral-credentials.d.ts +0 -32
- package/dist/utils/ephemeral-credentials.d.ts.map +0 -1
- package/dist/utils/ephemeral-credentials.js +0 -26
- package/dist/utils/ephemeral-credentials.js.map +0 -1
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { LlmProviderTypeSchema } from '../types/config.schema.js';
|
|
2
|
+
/** The three valid provider types, for error messages. */
|
|
3
|
+
const VALID_PROVIDER_TYPES = LlmProviderTypeSchema.options;
|
|
4
|
+
/**
|
|
5
|
+
* Per-provider token format validation. Returns an error string when the token
|
|
6
|
+
* does not match the provider's expected format, or `null` when it is
|
|
7
|
+
* acceptable. `claude` and `openrouter` enforce a prefix (which catches
|
|
8
|
+
* cross-provider paste mistakes before any network call); `openai` only
|
|
9
|
+
* requires a non-empty string (formats vary — live validation catches bad keys).
|
|
10
|
+
*/
|
|
11
|
+
export function validateTokenFormat(providerType, authToken) {
|
|
12
|
+
switch (providerType) {
|
|
13
|
+
case 'claude':
|
|
14
|
+
if (!authToken.startsWith('sk-ant-')) {
|
|
15
|
+
return 'Claude credential must be a subscription OAuth token (sk-ant-oat01-…, from https://claude.ai/settings) or an Anthropic API key (sk-ant-api03-…, from https://platform.claude.com).';
|
|
16
|
+
}
|
|
17
|
+
return null;
|
|
18
|
+
case 'openrouter':
|
|
19
|
+
if (!authToken.startsWith('sk-or-')) {
|
|
20
|
+
return 'OpenRouter key must start with sk-or- (create one at https://openrouter.ai/settings/keys).';
|
|
21
|
+
}
|
|
22
|
+
return null;
|
|
23
|
+
case 'openai':
|
|
24
|
+
if (authToken.length === 0) {
|
|
25
|
+
return 'OpenAI API key required (create one at https://platform.openai.com/api-keys).';
|
|
26
|
+
}
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Resolve the ephemeral LLM provider credential required to launch a hula-server
|
|
32
|
+
* sandbox, via a single precedence chain shared by every command that POSTs to
|
|
33
|
+
* the sandbox APIs.
|
|
34
|
+
*
|
|
35
|
+
* Provider type (highest precedence first):
|
|
36
|
+
* 1. explicit CLI flag (--provider)
|
|
37
|
+
* 2. .hublaunch/hublaunch.config.js (config.provider.type)
|
|
38
|
+
* 3. default 'claude'
|
|
39
|
+
*
|
|
40
|
+
* Credential (highest precedence first):
|
|
41
|
+
* 1. explicit CLI flag (--provider-key)
|
|
42
|
+
* 2. .hublaunch/hublaunch.config.js (config.provider.apiKey)
|
|
43
|
+
* 3. environment variable (PROVIDER_AUTH_TOKEN)
|
|
44
|
+
*
|
|
45
|
+
* Pure and side-effect free: returns the resolved values plus a list of
|
|
46
|
+
* human-readable error strings. Callers choose how to present errors (logger,
|
|
47
|
+
* chalk) and whether to exit. This keeps resolution + validation in ONE place
|
|
48
|
+
* (DRY) while leaving presentation to each command. Never echoes secret values.
|
|
49
|
+
*/
|
|
50
|
+
export function resolveProviderCredentials(options, config) {
|
|
51
|
+
const errors = [];
|
|
52
|
+
// --- Provider type resolution ---
|
|
53
|
+
const rawProvider = options.provider ?? config.provider?.type ?? 'claude';
|
|
54
|
+
const parsedType = LlmProviderTypeSchema.safeParse(rawProvider);
|
|
55
|
+
if (!parsedType.success) {
|
|
56
|
+
errors.push(`Unknown provider '${rawProvider}'. Valid providers are: ${VALID_PROVIDER_TYPES.join(', ')}.`);
|
|
57
|
+
// Return early with a safe default type; the token is not meaningful yet.
|
|
58
|
+
return {
|
|
59
|
+
providerType: 'claude',
|
|
60
|
+
authToken: '',
|
|
61
|
+
errors,
|
|
62
|
+
missingToken: false,
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const providerType = parsedType.data;
|
|
66
|
+
// --- Credential resolution ---
|
|
67
|
+
const authToken = options.providerKey ||
|
|
68
|
+
config.provider?.apiKey ||
|
|
69
|
+
process.env.PROVIDER_AUTH_TOKEN ||
|
|
70
|
+
'';
|
|
71
|
+
const missingToken = !authToken;
|
|
72
|
+
if (!authToken) {
|
|
73
|
+
errors.push(`No credential found for provider '${providerType}'. Pass --provider-key, set provider.apiKey in .hublaunch/hublaunch.config.js, or export PROVIDER_AUTH_TOKEN.`);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
const formatError = validateTokenFormat(providerType, authToken);
|
|
77
|
+
if (formatError) {
|
|
78
|
+
errors.push(formatError);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { providerType, authToken, errors, missingToken };
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=provider-credentials.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-credentials.js","sourceRoot":"","sources":["../../src/utils/provider-credentials.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,qBAAqB,EAAE,MAAM,2BAA2B,CAAC;AA0BlE,0DAA0D;AAC1D,MAAM,oBAAoB,GAAG,qBAAqB,CAAC,OAAO,CAAC;AAE3D;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CACjC,YAA6B,EAC7B,SAAiB;IAEjB,QAAQ,YAAY,EAAE,CAAC;QACrB,KAAK,QAAQ;YACX,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,SAAS,CAAC,EAAE,CAAC;gBACrC,OAAO,oLAAoL,CAAC;YAC9L,CAAC;YACD,OAAO,IAAI,CAAC;QACd,KAAK,YAAY;YACf,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;gBACpC,OAAO,4FAA4F,CAAC;YACtG,CAAC;YACD,OAAO,IAAI,CAAC;QACd,KAAK,QAAQ;YACX,IAAI,SAAS,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;gBAC3B,OAAO,+EAA+E,CAAC;YACzF,CAAC;YACD,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,0BAA0B,CACxC,OAAkC,EAClC,MAAc;IAEd,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,mCAAmC;IACnC,MAAM,WAAW,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAC,QAAQ,EAAE,IAAI,IAAI,QAAQ,CAAC;IAC1E,MAAM,UAAU,GAAG,qBAAqB,CAAC,SAAS,CAAC,WAAW,CAAC,CAAC;IAChE,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,MAAM,CAAC,IAAI,CACT,qBAAqB,WAAW,2BAA2B,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC9F,CAAC;QACF,0EAA0E;QAC1E,OAAO;YACL,YAAY,EAAE,QAAQ;YACtB,SAAS,EAAE,EAAE;YACb,MAAM;YACN,YAAY,EAAE,KAAK;SACpB,CAAC;IACJ,CAAC;IACD,MAAM,YAAY,GAAG,UAAU,CAAC,IAAI,CAAC;IAErC,gCAAgC;IAChC,MAAM,SAAS,GACb,OAAO,CAAC,WAAW;QACnB,MAAM,CAAC,QAAQ,EAAE,MAAM;QACvB,OAAO,CAAC,GAAG,CAAC,mBAAmB;QAC/B,EAAE,CAAC;IACL,MAAM,YAAY,GAAG,CAAC,SAAS,CAAC;IAEhC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,MAAM,CAAC,IAAI,CACT,qCAAqC,YAAY,+GAA+G,CACjK,CAAC;IACJ,CAAC;SAAM,CAAC;QACN,MAAM,WAAW,GAAG,mBAAmB,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;QACjE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IAED,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,CAAC;AAC3D,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "hub-launch",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.23.0",
|
|
4
4
|
"description": "GitHub Issue and PR automation CLI tool with plugin/hook system for project-specific customizations",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"url": "https://github.com/NoStackApp/hub-launch/issues"
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "tsc && shx chmod +x dist/index.js && npm run copy-templates",
|
|
21
|
+
"build": "tsc && shx chmod +x dist/index.js && npm run copy-templates && shx echo Build complete",
|
|
22
22
|
"postbuild": "node scripts/postinstall.mjs",
|
|
23
23
|
"postinstall": "node scripts/postinstall.mjs",
|
|
24
24
|
"copy-templates": "shx mkdir -p dist/templates && shx cp src/templates/*.md dist/templates/ && shx mkdir -p dist/templates/skills && shx cp -r src/templates/skills/* dist/templates/skills/",
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import type { Config } from '../types/index.js';
|
|
2
|
-
export interface EphemeralCredentialOptions {
|
|
3
|
-
anthropicKey?: string;
|
|
4
|
-
}
|
|
5
|
-
export interface ResolvedEphemeralCredentials {
|
|
6
|
-
anthropicApiKey?: string;
|
|
7
|
-
/** Human-readable error strings. Empty when the credential is valid. */
|
|
8
|
-
errors: string[];
|
|
9
|
-
/**
|
|
10
|
-
* True only when no token was supplied at all (via flag, config, or env) —
|
|
11
|
-
* NOT for the wrong-prefix case. Lets interactive callers (e.g. `hula
|
|
12
|
-
* launch`) distinguish "prompt the user for a key" from other errors. Purely
|
|
13
|
-
* additive: `errors` behavior is unchanged, so non-interactive callers such
|
|
14
|
-
* as `hula schedule` are unaffected.
|
|
15
|
-
*/
|
|
16
|
-
missingAnthropicKey: boolean;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Resolve the ephemeral Anthropic OAuth token required to launch a hula-server
|
|
20
|
-
* sandbox via a single precedence chain shared by every command that POSTs to
|
|
21
|
-
* the sandbox APIs:
|
|
22
|
-
* 1. explicit CLI flag (--anthropic-key)
|
|
23
|
-
* 2. .hublaunch/hublaunch.config.js (config.anthropicApiKey)
|
|
24
|
-
* 3. environment variable (ANTHROPIC_API_KEY)
|
|
25
|
-
*
|
|
26
|
-
* Pure and side-effect free: returns the resolved value plus a list of
|
|
27
|
-
* human-readable error strings. Callers choose how to present errors (logger,
|
|
28
|
-
* chalk) and whether to exit. This keeps resolution + validation in ONE place
|
|
29
|
-
* (DRY) while leaving presentation to each command. Never echoes secret values.
|
|
30
|
-
*/
|
|
31
|
-
export declare function resolveEphemeralCredentials(options: EphemeralCredentialOptions, config: Config): ResolvedEphemeralCredentials;
|
|
32
|
-
//# sourceMappingURL=ephemeral-credentials.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ephemeral-credentials.d.ts","sourceRoot":"","sources":["../../src/utils/ephemeral-credentials.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,mBAAmB,CAAC;AAEhD,MAAM,WAAW,0BAA0B;IACzC,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,4BAA4B;IAC3C,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,wEAAwE;IACxE,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB;;;;;;OAMG;IACH,mBAAmB,EAAE,OAAO,CAAC;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,2BAA2B,CACzC,OAAO,EAAE,0BAA0B,EACnC,MAAM,EAAE,MAAM,GACb,4BAA4B,CAiB9B"}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the ephemeral Anthropic OAuth token required to launch a hula-server
|
|
3
|
-
* sandbox via a single precedence chain shared by every command that POSTs to
|
|
4
|
-
* the sandbox APIs:
|
|
5
|
-
* 1. explicit CLI flag (--anthropic-key)
|
|
6
|
-
* 2. .hublaunch/hublaunch.config.js (config.anthropicApiKey)
|
|
7
|
-
* 3. environment variable (ANTHROPIC_API_KEY)
|
|
8
|
-
*
|
|
9
|
-
* Pure and side-effect free: returns the resolved value plus a list of
|
|
10
|
-
* human-readable error strings. Callers choose how to present errors (logger,
|
|
11
|
-
* chalk) and whether to exit. This keeps resolution + validation in ONE place
|
|
12
|
-
* (DRY) while leaving presentation to each command. Never echoes secret values.
|
|
13
|
-
*/
|
|
14
|
-
export function resolveEphemeralCredentials(options, config) {
|
|
15
|
-
const errors = [];
|
|
16
|
-
const anthropicApiKey = options.anthropicKey || config.anthropicApiKey || process.env.ANTHROPIC_API_KEY;
|
|
17
|
-
const missingAnthropicKey = !anthropicApiKey;
|
|
18
|
-
if (!anthropicApiKey) {
|
|
19
|
-
errors.push('No Anthropic OAuth token configured. Set anthropicApiKey in .hublaunch/hublaunch.config.js, use --anthropic-key, or set ANTHROPIC_API_KEY. Get a token at https://claude.ai/settings (requires a paid Claude.ai plan — Pro or Max).');
|
|
20
|
-
}
|
|
21
|
-
else if (!anthropicApiKey.startsWith('sk-ant-oat')) {
|
|
22
|
-
errors.push('Anthropic credential must be an OAuth token (starts with sk-ant-oat01-…). Standard API keys (sk-ant-api03-…) are not supported — the container requires CLAUDE_CODE_OAUTH_TOKEN.');
|
|
23
|
-
}
|
|
24
|
-
return { anthropicApiKey, errors, missingAnthropicKey };
|
|
25
|
-
}
|
|
26
|
-
//# sourceMappingURL=ephemeral-credentials.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"ephemeral-credentials.js","sourceRoot":"","sources":["../../src/utils/ephemeral-credentials.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,2BAA2B,CACzC,OAAmC,EACnC,MAAc;IAEd,MAAM,MAAM,GAAa,EAAE,CAAC;IAE5B,MAAM,eAAe,GACnB,OAAO,CAAC,YAAY,IAAI,MAAM,CAAC,eAAe,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC;IAClF,MAAM,mBAAmB,GAAG,CAAC,eAAe,CAAC;IAC7C,IAAI,CAAC,eAAe,EAAE,CAAC;QACrB,MAAM,CAAC,IAAI,CACT,qOAAqO,CACtO,CAAC;IACJ,CAAC;SAAM,IAAI,CAAC,eAAe,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QACrD,MAAM,CAAC,IAAI,CACT,kLAAkL,CACnL,CAAC;IACJ,CAAC;IAED,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;AAC1D,CAAC"}
|