@almightygpt/core 0.7.1 → 0.8.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.
Files changed (46) hide show
  1. package/dist/adapters/claude.d.ts +8 -1
  2. package/dist/adapters/claude.d.ts.map +1 -1
  3. package/dist/adapters/claude.js +26 -7
  4. package/dist/adapters/claude.js.map +1 -1
  5. package/dist/adapters/gemini.d.ts +5 -1
  6. package/dist/adapters/gemini.d.ts.map +1 -1
  7. package/dist/adapters/gemini.js +23 -10
  8. package/dist/adapters/gemini.js.map +1 -1
  9. package/dist/adapters/openai.d.ts +6 -1
  10. package/dist/adapters/openai.d.ts.map +1 -1
  11. package/dist/adapters/openai.js +28 -16
  12. package/dist/adapters/openai.js.map +1 -1
  13. package/dist/auth/keychain.d.ts +30 -0
  14. package/dist/auth/keychain.d.ts.map +1 -0
  15. package/dist/auth/keychain.js +106 -0
  16. package/dist/auth/keychain.js.map +1 -0
  17. package/dist/auth/resolver.d.ts +32 -0
  18. package/dist/auth/resolver.d.ts.map +1 -0
  19. package/dist/auth/resolver.js +58 -0
  20. package/dist/auth/resolver.js.map +1 -0
  21. package/dist/auth/types.d.ts +45 -0
  22. package/dist/auth/types.d.ts.map +1 -0
  23. package/dist/auth/types.js +51 -0
  24. package/dist/auth/types.js.map +1 -0
  25. package/dist/auth/validator.d.ts +33 -0
  26. package/dist/auth/validator.d.ts.map +1 -0
  27. package/dist/auth/validator.js +130 -0
  28. package/dist/auth/validator.js.map +1 -0
  29. package/dist/index.d.ts +5 -1
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +6 -1
  32. package/dist/index.js.map +1 -1
  33. package/dist/templates/install.d.ts +10 -0
  34. package/dist/templates/install.d.ts.map +1 -1
  35. package/dist/templates/install.js +84 -1
  36. package/dist/templates/install.js.map +1 -1
  37. package/package.json +4 -1
  38. package/src/adapters/claude.ts +24 -7
  39. package/src/adapters/gemini.ts +21 -11
  40. package/src/adapters/openai.ts +26 -15
  41. package/src/auth/keychain.ts +132 -0
  42. package/src/auth/resolver.ts +81 -0
  43. package/src/auth/types.ts +68 -0
  44. package/src/auth/validator.ts +145 -0
  45. package/src/index.ts +22 -1
  46. package/src/templates/install.ts +101 -1
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Auth subsystem types — provider identifiers, resolution sources,
3
+ * error classes.
4
+ *
5
+ * The auth module's job is to answer one question per call:
6
+ * "where is the API key for <provider>, and what is it?"
7
+ *
8
+ * Resolution priority (top to bottom):
9
+ * 1. Explicit parameter (passed by caller — tests, extension handoff)
10
+ * 2. Environment variable (per-process override; wins over keychain)
11
+ * 3. OS keychain (persistent convenience; @napi-rs/keyring optional)
12
+ * 4. Missing -> throw AuthMissingError
13
+ *
14
+ * Env-wins-over-keychain is intentional. The original draft had the
15
+ * order flipped; Codex's independent review caught that it would
16
+ * silently override the VS Code extension's freshly-stored key with
17
+ * a stale keychain copy. See docs/claude/v0.8-auth-plan.md.
18
+ */
19
+ export type ProviderId = "openai" | "anthropic" | "google";
20
+ export type KeySource = "explicit" | "env" | "keychain" | "missing";
21
+ export interface KeyResolution {
22
+ provider: ProviderId;
23
+ source: KeySource;
24
+ /** Present iff source !== "missing". */
25
+ key?: string;
26
+ /** Which env var was used (only set when source === "env"). */
27
+ envVar?: string;
28
+ }
29
+ /**
30
+ * Thrown when no key is found in any source. Caller should surface
31
+ * the message verbatim — it tells the user exactly how to fix it.
32
+ */
33
+ export declare class AuthMissingError extends Error {
34
+ readonly provider: ProviderId;
35
+ readonly envVar: string;
36
+ constructor(provider: ProviderId, envVar: string);
37
+ }
38
+ /** Maps each provider to the canonical env var name(s) we read. */
39
+ export declare const PROVIDER_ENV_VARS: Record<ProviderId, readonly string[]>;
40
+ /**
41
+ * Browser-launchable URL where a user creates / manages keys for each
42
+ * provider. Used by the `almightygpt auth <provider>` flow.
43
+ */
44
+ export declare const PROVIDER_KEY_URLS: Record<ProviderId, string>;
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,MAAM,MAAM,UAAU,GAAG,QAAQ,GAAG,WAAW,GAAG,QAAQ,CAAC;AAE3D,MAAM,MAAM,SAAS,GAAG,UAAU,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC;AAEpE,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,UAAU,CAAC;IACrB,MAAM,EAAE,SAAS,CAAC;IAClB,wCAAwC;IACxC,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED;;;GAGG;AACH,qBAAa,gBAAiB,SAAQ,KAAK;IACzC,QAAQ,CAAC,QAAQ,EAAE,UAAU,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBACZ,QAAQ,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM;CAUjD;AAED,mEAAmE;AACnE,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAKnE,CAAC;AAEF;;;GAGG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,UAAU,EAAE,MAAM,CAIxD,CAAC"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Auth subsystem types — provider identifiers, resolution sources,
3
+ * error classes.
4
+ *
5
+ * The auth module's job is to answer one question per call:
6
+ * "where is the API key for <provider>, and what is it?"
7
+ *
8
+ * Resolution priority (top to bottom):
9
+ * 1. Explicit parameter (passed by caller — tests, extension handoff)
10
+ * 2. Environment variable (per-process override; wins over keychain)
11
+ * 3. OS keychain (persistent convenience; @napi-rs/keyring optional)
12
+ * 4. Missing -> throw AuthMissingError
13
+ *
14
+ * Env-wins-over-keychain is intentional. The original draft had the
15
+ * order flipped; Codex's independent review caught that it would
16
+ * silently override the VS Code extension's freshly-stored key with
17
+ * a stale keychain copy. See docs/claude/v0.8-auth-plan.md.
18
+ */
19
+ /**
20
+ * Thrown when no key is found in any source. Caller should surface
21
+ * the message verbatim — it tells the user exactly how to fix it.
22
+ */
23
+ export class AuthMissingError extends Error {
24
+ provider;
25
+ envVar;
26
+ constructor(provider, envVar) {
27
+ super(`No API key found for ${provider}. ` +
28
+ `Run "almightygpt auth ${provider}" to set one up interactively, ` +
29
+ `or export ${envVar} in your shell.`);
30
+ this.name = "AuthMissingError";
31
+ this.provider = provider;
32
+ this.envVar = envVar;
33
+ }
34
+ }
35
+ /** Maps each provider to the canonical env var name(s) we read. */
36
+ export const PROVIDER_ENV_VARS = {
37
+ openai: ["OPENAI_API_KEY"],
38
+ anthropic: ["ANTHROPIC_API_KEY"],
39
+ // Google's SDK historically accepted both names; honor both.
40
+ google: ["GOOGLE_API_KEY", "GEMINI_API_KEY"],
41
+ };
42
+ /**
43
+ * Browser-launchable URL where a user creates / manages keys for each
44
+ * provider. Used by the `almightygpt auth <provider>` flow.
45
+ */
46
+ export const PROVIDER_KEY_URLS = {
47
+ openai: "https://platform.openai.com/api-keys",
48
+ anthropic: "https://console.anthropic.com/settings/keys",
49
+ google: "https://aistudio.google.com/apikey",
50
+ };
51
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAeH;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,KAAK;IAChC,QAAQ,CAAa;IACrB,MAAM,CAAS;IACxB,YAAY,QAAoB,EAAE,MAAc;QAC9C,KAAK,CACH,wBAAwB,QAAQ,IAAI;YAClC,yBAAyB,QAAQ,iCAAiC;YAClE,aAAa,MAAM,iBAAiB,CACvC,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAC;QAC/B,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;CACF;AAED,mEAAmE;AACnE,MAAM,CAAC,MAAM,iBAAiB,GAA0C;IACtE,MAAM,EAAE,CAAC,gBAAgB,CAAC;IAC1B,SAAS,EAAE,CAAC,mBAAmB,CAAC;IAChC,6DAA6D;IAC7D,MAAM,EAAE,CAAC,gBAAgB,EAAE,gBAAgB,CAAC;CAC7C,CAAC;AAEF;;;GAGG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA+B;IAC3D,MAAM,EAAE,sCAAsC;IAC9C,SAAS,EAAE,6CAA6C;IACxD,MAAM,EAAE,oCAAoC;CAC7C,CAAC"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Model-level key validation.
3
+ *
4
+ * Codex's review caught that listing models (e.g. `GET /v1/models`) can
5
+ * succeed when the key lacks model permission, has quota issues, or
6
+ * has billing-state problems. The user doesn't care that list-models
7
+ * works — they care that AlmightyGPT can run the configured review
8
+ * model.
9
+ *
10
+ * So we validate with the same operation class real reviews use:
11
+ * - OpenAI: tiny chat completion against gpt-4o
12
+ * - Anthropic: tiny messages call against claude-sonnet-4-6
13
+ * - Google: tiny generateContent call against gemini-2.5-flash
14
+ *
15
+ * Cost is fractions of a cent per call. Latency is ~1-3 seconds.
16
+ * Failure surfaces the provider's exact error message so the user
17
+ * can fix it.
18
+ */
19
+ import type { ProviderId } from "./types.js";
20
+ export interface ValidationResult {
21
+ ok: boolean;
22
+ /** Provider-reported model used (e.g. "gpt-4o-2024-08-06"). */
23
+ model?: string;
24
+ /** Provider's error message verbatim if ok === false. */
25
+ error?: string;
26
+ }
27
+ /**
28
+ * Validate that a key can actually invoke the model real reviews use.
29
+ * Returns a result object — never throws on validation failure (only
30
+ * on programmer errors like an unsupported provider).
31
+ */
32
+ export declare function validateKey(provider: ProviderId, key: string): Promise<ValidationResult>;
33
+ //# sourceMappingURL=validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../../src/auth/validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAE7C,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,OAAO,CAAC;IACZ,+DAA+D;IAC/D,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAUD;;;;GAIG;AACH,wBAAsB,WAAW,CAC/B,QAAQ,EAAE,UAAU,EACpB,GAAG,EAAE,MAAM,GACV,OAAO,CAAC,gBAAgB,CAAC,CAgB3B"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Model-level key validation.
3
+ *
4
+ * Codex's review caught that listing models (e.g. `GET /v1/models`) can
5
+ * succeed when the key lacks model permission, has quota issues, or
6
+ * has billing-state problems. The user doesn't care that list-models
7
+ * works — they care that AlmightyGPT can run the configured review
8
+ * model.
9
+ *
10
+ * So we validate with the same operation class real reviews use:
11
+ * - OpenAI: tiny chat completion against gpt-4o
12
+ * - Anthropic: tiny messages call against claude-sonnet-4-6
13
+ * - Google: tiny generateContent call against gemini-2.5-flash
14
+ *
15
+ * Cost is fractions of a cent per call. Latency is ~1-3 seconds.
16
+ * Failure surfaces the provider's exact error message so the user
17
+ * can fix it.
18
+ */
19
+ const DEFAULT_VALIDATION_MODELS = {
20
+ openai: "gpt-4o",
21
+ anthropic: "claude-sonnet-4-6",
22
+ google: "gemini-2.5-flash",
23
+ };
24
+ const VALIDATION_TIMEOUT_MS = 15_000;
25
+ /**
26
+ * Validate that a key can actually invoke the model real reviews use.
27
+ * Returns a result object — never throws on validation failure (only
28
+ * on programmer errors like an unsupported provider).
29
+ */
30
+ export async function validateKey(provider, key) {
31
+ try {
32
+ switch (provider) {
33
+ case "openai":
34
+ return await validateOpenAI(key);
35
+ case "anthropic":
36
+ return await validateAnthropic(key);
37
+ case "google":
38
+ return await validateGoogle(key);
39
+ }
40
+ }
41
+ catch (err) {
42
+ return {
43
+ ok: false,
44
+ error: err instanceof Error ? err.message : String(err),
45
+ };
46
+ }
47
+ }
48
+ async function validateOpenAI(key) {
49
+ const model = DEFAULT_VALIDATION_MODELS.openai;
50
+ const controller = new AbortController();
51
+ const timer = setTimeout(() => controller.abort(), VALIDATION_TIMEOUT_MS);
52
+ try {
53
+ const res = await fetch("https://api.openai.com/v1/chat/completions", {
54
+ method: "POST",
55
+ headers: {
56
+ "content-type": "application/json",
57
+ authorization: `Bearer ${key}`,
58
+ },
59
+ body: JSON.stringify({
60
+ model,
61
+ messages: [{ role: "user", content: "hi" }],
62
+ max_tokens: 1,
63
+ }),
64
+ signal: controller.signal,
65
+ });
66
+ if (!res.ok) {
67
+ return { ok: false, error: await res.text().catch(() => res.statusText) };
68
+ }
69
+ const data = (await res.json());
70
+ return { ok: true, model: data.model ?? model };
71
+ }
72
+ finally {
73
+ clearTimeout(timer);
74
+ }
75
+ }
76
+ async function validateAnthropic(key) {
77
+ const model = DEFAULT_VALIDATION_MODELS.anthropic;
78
+ const controller = new AbortController();
79
+ const timer = setTimeout(() => controller.abort(), VALIDATION_TIMEOUT_MS);
80
+ try {
81
+ const res = await fetch("https://api.anthropic.com/v1/messages", {
82
+ method: "POST",
83
+ headers: {
84
+ "content-type": "application/json",
85
+ "x-api-key": key,
86
+ "anthropic-version": "2023-06-01",
87
+ },
88
+ body: JSON.stringify({
89
+ model,
90
+ max_tokens: 5,
91
+ messages: [{ role: "user", content: "hi" }],
92
+ }),
93
+ signal: controller.signal,
94
+ });
95
+ if (!res.ok) {
96
+ return { ok: false, error: await res.text().catch(() => res.statusText) };
97
+ }
98
+ const data = (await res.json());
99
+ return { ok: true, model: data.model ?? model };
100
+ }
101
+ finally {
102
+ clearTimeout(timer);
103
+ }
104
+ }
105
+ async function validateGoogle(key) {
106
+ const model = DEFAULT_VALIDATION_MODELS.google;
107
+ const controller = new AbortController();
108
+ const timer = setTimeout(() => controller.abort(), VALIDATION_TIMEOUT_MS);
109
+ try {
110
+ const url = `https://generativelanguage.googleapis.com/v1beta/models/${model}:generateContent?key=` +
111
+ encodeURIComponent(key);
112
+ const res = await fetch(url, {
113
+ method: "POST",
114
+ headers: { "content-type": "application/json" },
115
+ body: JSON.stringify({
116
+ contents: [{ parts: [{ text: "hi" }] }],
117
+ generationConfig: { maxOutputTokens: 5 },
118
+ }),
119
+ signal: controller.signal,
120
+ });
121
+ if (!res.ok) {
122
+ return { ok: false, error: await res.text().catch(() => res.statusText) };
123
+ }
124
+ return { ok: true, model };
125
+ }
126
+ finally {
127
+ clearTimeout(timer);
128
+ }
129
+ }
130
+ //# sourceMappingURL=validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validator.js","sourceRoot":"","sources":["../../src/auth/validator.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -12,7 +12,7 @@
12
12
  * - review/ ✅ task #11 diff review pipeline (with #12/#13/#14 wiring)
13
13
  * - budget/ ✅ task #14 BudgetTracker + BudgetExceededError
14
14
  */
15
- export declare const VERSION = "0.7.1";
15
+ export declare const VERSION = "0.8.0";
16
16
  export { checkGitStatus, assertSafeToWrite, GitStatusDirtyError, type GitStatusCheck, } from "./git/status.js";
17
17
  export { installTemplate, hasExistingConfig, type InstallOptions, type InstallResult, } from "./templates/install.js";
18
18
  export { loadConfig, ConfigError } from "./config/load.js";
@@ -30,4 +30,8 @@ export { collectGitDiff, type DiffOptions, type DiffResult } from "./review/diff
30
30
  export { writeHumanReviewFile, ReviewFileExistsError, reviewFilePathFor, preflightReviewFileCollision, type WriteReviewFileOptions, } from "./review/write.js";
31
31
  export { BudgetTracker, BudgetExceededError, type BudgetCaps, } from "./review/budget.js";
32
32
  export type { ReviewEvent, ReviewEventHandler, AgentRoleInRun, } from "./review/events.js";
33
+ export { resolveApiKey, requireApiKey, type ResolveOptions, } from "./auth/resolver.js";
34
+ export { getKeychain, _resetKeychainCache, type KeychainAdapter, } from "./auth/keychain.js";
35
+ export { validateKey, type ValidationResult } from "./auth/validator.js";
36
+ export { AuthMissingError, PROVIDER_ENV_VARS, PROVIDER_KEY_URLS, type ProviderId, type KeySource, type KeyResolution, } from "./auth/types.js";
33
37
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,GACf,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,KAAK,cAAc,GACpB,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,eAAe,EACf,iBAAiB,EACjB,KAAK,cAAc,EACnB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAGhC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,EACf,KAAK,MAAM,EACX,KAAK,WAAW,GACjB,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,EACb,KAAK,OAAO,EACZ,KAAK,YAAY,EACjB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,EACzB,KAAK,oBAAoB,GAC1B,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,aAAa,EAAE,KAAK,eAAe,EAAE,KAAK,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,EACpB,KAAK,eAAe,EACpB,KAAK,YAAY,GAClB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,KAAK,gBAAgB,GACtB,MAAM,kBAAkB,CAAC;AAC1B,YAAY,EACV,WAAW,EACX,SAAS,EACT,OAAO,EACP,YAAY,EACZ,aAAa,EACb,cAAc,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACnB,KAAK,eAAe,GACrB,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,EACd,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,aAAa,EACb,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,GACtB,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,EACvB,KAAK,qBAAqB,EAC1B,KAAK,oBAAoB,GAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAE,KAAK,WAAW,EAAE,KAAK,UAAU,EAAE,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,EAC5B,KAAK,sBAAsB,GAC5B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,EACnB,KAAK,UAAU,GAChB,MAAM,oBAAoB,CAAC;AAC5B,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,cAAc,GACf,MAAM,oBAAoB,CAAC;AAG5B,OAAO,EACL,aAAa,EACb,aAAa,EACb,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,EACnB,KAAK,eAAe,GACrB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,EACjB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,aAAa,GACnB,MAAM,iBAAiB,CAAC"}
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@
12
12
  * - review/ ✅ task #11 diff review pipeline (with #12/#13/#14 wiring)
13
13
  * - budget/ ✅ task #14 BudgetTracker + BudgetExceededError
14
14
  */
15
- export const VERSION = "0.7.1";
15
+ export const VERSION = "0.8.0";
16
16
  // Git safety primitives
17
17
  export { checkGitStatus, assertSafeToWrite, GitStatusDirtyError, } from "./git/status.js";
18
18
  // Template installer
@@ -35,4 +35,9 @@ export { runWorkerReviewerReview, } from "./review/run-worker-reviewer.js";
35
35
  export { collectGitDiff } from "./review/diff.js";
36
36
  export { writeHumanReviewFile, ReviewFileExistsError, reviewFilePathFor, preflightReviewFileCollision, } from "./review/write.js";
37
37
  export { BudgetTracker, BudgetExceededError, } from "./review/budget.js";
38
+ // Auth subsystem (v0.8.0+) — resolver, keychain, validator
39
+ export { resolveApiKey, requireApiKey, } from "./auth/resolver.js";
40
+ export { getKeychain, _resetKeychainCache, } from "./auth/keychain.js";
41
+ export { validateKey } from "./auth/validator.js";
42
+ export { AuthMissingError, PROVIDER_ENV_VARS, PROVIDER_KEY_URLS, } from "./auth/types.js";
38
43
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,eAAe,EACf,iBAAiB,GAGlB,MAAM,wBAAwB,CAAC;AAEhC,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAE5B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GAQd,MAAM,qBAAqB,CAAC;AAE7B,sBAAsB;AACtB,OAAO,EAAE,aAAa,EAA6C,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO;AACP,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,GAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EACL,aAAa,GAGd,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,GAGxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAqC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAE7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,wBAAwB;AACxB,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,mBAAmB,GAEpB,MAAM,iBAAiB,CAAC;AAEzB,qBAAqB;AACrB,OAAO,EACL,eAAe,EACf,iBAAiB,GAGlB,MAAM,wBAAwB,CAAC;AAEhC,SAAS;AACT,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,EACL,YAAY,EACZ,iBAAiB,EACjB,eAAe,GAGhB,MAAM,oBAAoB,CAAC;AAE5B,WAAW;AACX,OAAO,EACL,YAAY,EACZ,WAAW,EACX,aAAa,EACb,aAAa,EACb,aAAa,GAQd,MAAM,qBAAqB,CAAC;AAE7B,sBAAsB;AACtB,OAAO,EAAE,aAAa,EAA6C,MAAM,qBAAqB,CAAC;AAC/F,OAAO,EACL,oBAAoB,EACpB,oBAAoB,GAGrB,MAAM,uBAAuB,CAAC;AAE/B,OAAO;AACP,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,aAAa,EACb,gBAAgB,EAChB,iBAAiB,GAElB,MAAM,kBAAkB,CAAC;AAS1B,OAAO,EACL,QAAQ,EACR,WAAW,EACX,aAAa,EACb,cAAc,GAIf,MAAM,gBAAgB,CAAC;AACxB,OAAO,EACL,cAAc,GAGf,MAAM,kBAAkB,CAAC;AAE1B,kBAAkB;AAClB,OAAO,EACL,aAAa,GAGd,MAAM,6BAA6B,CAAC;AACrC,OAAO,EACL,uBAAuB,GAGxB,MAAM,iCAAiC,CAAC;AACzC,OAAO,EAAE,cAAc,EAAqC,MAAM,kBAAkB,CAAC;AACrF,OAAO,EACL,oBAAoB,EACpB,qBAAqB,EACrB,iBAAiB,EACjB,4BAA4B,GAE7B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EACL,aAAa,EACb,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAO5B,2DAA2D;AAC3D,OAAO,EACL,aAAa,EACb,aAAa,GAEd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EACL,WAAW,EACX,mBAAmB,GAEpB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,WAAW,EAAyB,MAAM,qBAAqB,CAAC;AACzE,OAAO,EACL,gBAAgB,EAChB,iBAAiB,EACjB,iBAAiB,GAIlB,MAAM,iBAAiB,CAAC"}
@@ -41,6 +41,16 @@ export interface InstallResult {
41
41
  from: string;
42
42
  to: string;
43
43
  }[];
44
+ /**
45
+ * Entries appended to the target repo's `.gitignore`. Empty if everything
46
+ * was already covered (e.g. user had `.almightygpt/` blanket-ignored, or
47
+ * had previously run init).
48
+ */
49
+ gitignoreAppended: string[];
50
+ /** Entries that were already present in `.gitignore` and didn't need adding. */
51
+ gitignoreAlreadyPresent: string[];
52
+ /** True if init created the `.gitignore` file (didn't exist). */
53
+ gitignoreCreated: boolean;
44
54
  }
45
55
  export declare function installTemplate(options: InstallOptions): Promise<InstallResult>;
46
56
  export declare function relativeFromCwd(targetDir: string, absPath: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/templates/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,0DAA0D;IAC1D,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AA0CD,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CA4ExB;AAmBD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED,2EAA2E;AAC3E,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
1
+ {"version":3,"file":"install.d.ts","sourceRoot":"","sources":["../../src/templates/install.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAQH,MAAM,WAAW,cAAc;IAC7B,iEAAiE;IACjE,SAAS,EAAE,MAAM,CAAC;IAClB,0DAA0D;IAC1D,KAAK,EAAE,MAAM,CAAC;IACd,gEAAgE;IAChE,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAC5C,0DAA0D;IAC1D,QAAQ,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IACzC;;;;OAIG;IACH,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,gFAAgF;IAChF,uBAAuB,EAAE,MAAM,EAAE,CAAC;IAClC,iEAAiE;IACjE,gBAAgB,EAAE,OAAO,CAAC;CAC3B;AAwDD,wBAAsB,eAAe,CACnC,OAAO,EAAE,cAAc,GACtB,OAAO,CAAC,aAAa,CAAC,CAqFxB;AAsFD,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,MAAM,CAG1E;AAED,2EAA2E;AAC3E,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAO3E"}
@@ -18,6 +18,18 @@ import { dirname, join, relative } from "node:path";
18
18
  import { existsSync } from "node:fs";
19
19
  import { fileURLToPath } from "node:url";
20
20
  import { assertSafeToWrite } from "../git/status.js";
21
+ /**
22
+ * Entries appended to the host repo's `.gitignore`. The product's machine
23
+ * metadata (per-run outputs) must never land in git — but `.almightygpt/
24
+ * config.yaml` and `.almightygpt/rules.md` MUST. So we ignore the runs
25
+ * subfolder, not the whole `.almightygpt/` directory.
26
+ */
27
+ const GITIGNORE_HEADER = "# AlmightyGPT — machine-only run metadata (do not commit)";
28
+ const GITIGNORE_ENTRIES = [
29
+ ".almightygpt/runs/",
30
+ ".almightygpt/credentials.yaml",
31
+ ".almightygpt/credentials.json",
32
+ ];
21
33
  const __filename = fileURLToPath(import.meta.url);
22
34
  // In dev (ts-node-esm) and in built form, the templates package lives at the
23
35
  // same monorepo root. Find it by walking up until we hit packages/templates.
@@ -120,7 +132,78 @@ export async function installTemplate(options) {
120
132
  await writeFile(destAbs, content);
121
133
  written.push(destRel);
122
134
  }
123
- return { written, skipped, backedUp };
135
+ const gitignoreResult = await ensureGitignoreCovers(targetDir, dryRun);
136
+ return {
137
+ written,
138
+ skipped,
139
+ backedUp,
140
+ gitignoreAppended: gitignoreResult.added,
141
+ gitignoreAlreadyPresent: gitignoreResult.alreadyPresent,
142
+ gitignoreCreated: gitignoreResult.created,
143
+ };
144
+ }
145
+ /**
146
+ * Ensure the host repo's `.gitignore` covers `.almightygpt/runs/` and
147
+ * credential files. Creates `.gitignore` if it doesn't exist. Appends only
148
+ * the missing entries (idempotent — safe to call on every `init`).
149
+ *
150
+ * Returns a report so the CLI can show the user what changed.
151
+ */
152
+ async function ensureGitignoreCovers(targetDir, dryRun) {
153
+ const gitignorePath = join(targetDir, ".gitignore");
154
+ let existing = "";
155
+ let created = false;
156
+ try {
157
+ existing = await readFile(gitignorePath, "utf-8");
158
+ }
159
+ catch {
160
+ // File doesn't exist — we'll create it.
161
+ created = true;
162
+ }
163
+ const lines = new Set(existing
164
+ .split(/\r?\n/)
165
+ .map((l) => l.trim())
166
+ .filter(Boolean));
167
+ // An entry is already covered if (a) it's literally there, (b) its
168
+ // no-trailing-slash form is there, or (c) the user has `.almightygpt/`
169
+ // or `.almightygpt` ignoring the whole folder.
170
+ const alreadyCovers = (entry) => {
171
+ if (lines.has(entry))
172
+ return true;
173
+ if (lines.has(entry.replace(/\/$/, "")))
174
+ return true;
175
+ if (lines.has(".almightygpt/"))
176
+ return true;
177
+ if (lines.has(".almightygpt"))
178
+ return true;
179
+ return false;
180
+ };
181
+ const toAdd = [];
182
+ const alreadyPresent = [];
183
+ for (const entry of GITIGNORE_ENTRIES) {
184
+ if (alreadyCovers(entry))
185
+ alreadyPresent.push(entry);
186
+ else
187
+ toAdd.push(entry);
188
+ }
189
+ if (toAdd.length === 0 || dryRun) {
190
+ return { added: toAdd, alreadyPresent, created: created && !dryRun };
191
+ }
192
+ const hasHeader = existing.includes(GITIGNORE_HEADER);
193
+ const headerLine = hasHeader ? "" : `${GITIGNORE_HEADER}\n`;
194
+ const block = headerLine + toAdd.join("\n") + "\n";
195
+ let newContent;
196
+ if (!existing) {
197
+ newContent = block;
198
+ }
199
+ else if (existing.endsWith("\n")) {
200
+ newContent = existing + (existing.endsWith("\n\n") ? "" : "\n") + block;
201
+ }
202
+ else {
203
+ newContent = existing + "\n\n" + block;
204
+ }
205
+ await writeFile(gitignorePath, newContent);
206
+ return { added: toAdd, alreadyPresent, created };
124
207
  }
125
208
  /**
126
209
  * Find a free `<file>.almighty-bak[.N]` slot for an existing file.
@@ -1 +1 @@
1
- {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/templates/install.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../../src/templates/install.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@almightygpt/core",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "Core orchestrator, adapters, config, runs, and review logic for AlmightyGPT",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -31,5 +31,8 @@
31
31
  "p-limit": "^5.0.0",
32
32
  "yaml": "^2.4.0",
33
33
  "zod": "^3.23.0"
34
+ },
35
+ "optionalDependencies": {
36
+ "@napi-rs/keyring": "^1.1.6"
34
37
  }
35
38
  }
@@ -21,6 +21,7 @@ import {
21
21
  type AdapterInput,
22
22
  type AdapterOutput,
23
23
  } from "./types.js";
24
+ import { resolveApiKey } from "../auth/resolver.js";
24
25
 
25
26
  const PRICING_USD_PER_1M: Record<string, { input: number; output: number }> = {
26
27
  // Claude 4.x family (current)
@@ -47,7 +48,9 @@ export class ClaudeAdapter implements Adapter {
47
48
  readonly name: string;
48
49
  readonly provider = "anthropic";
49
50
 
50
- private readonly client: Anthropic | null;
51
+ private client: Anthropic | null = null;
52
+ private resolved = false;
53
+ private readonly explicitApiKey: string | undefined;
51
54
  readonly defaultModel: string;
52
55
  private readonly defaultMaxOutputTokens: number;
53
56
  private readonly defaultTimeoutMs: number;
@@ -57,19 +60,33 @@ export class ClaudeAdapter implements Adapter {
57
60
  this.defaultModel = options.defaultModel ?? DEFAULT_MODEL;
58
61
  this.defaultMaxOutputTokens = options.defaultMaxOutputTokens ?? 4096;
59
62
  this.defaultTimeoutMs = options.defaultTimeoutMs ?? 120_000;
63
+ this.explicitApiKey = options.apiKey;
64
+ }
60
65
 
61
- const apiKey = options.apiKey ?? process.env["ANTHROPIC_API_KEY"];
62
- this.client = apiKey ? new Anthropic({ apiKey }) : null;
66
+ /**
67
+ * Lazily resolve the API key on first need. Goes through the
68
+ * unified resolver: explicit → env → keychain → missing.
69
+ */
70
+ private async ensureClient(): Promise<Anthropic | null> {
71
+ if (this.resolved) return this.client;
72
+ this.resolved = true;
73
+ const opts = this.explicitApiKey ? { explicit: this.explicitApiKey } : {};
74
+ const result = await resolveApiKey("anthropic", opts);
75
+ if (result.source === "missing") return null;
76
+ this.client = new Anthropic({ apiKey: result.key! });
77
+ return this.client;
63
78
  }
64
79
 
65
80
  async isAvailable(): Promise<boolean> {
66
- return this.client !== null;
81
+ return (await this.ensureClient()) !== null;
67
82
  }
68
83
 
69
84
  async execute(input: AdapterInput): Promise<AdapterOutput> {
70
- if (!this.client) {
85
+ const client = await this.ensureClient();
86
+ if (!client) {
71
87
  throw new AdapterError(
72
- "ANTHROPIC_API_KEY is not set. Export it in your environment.",
88
+ 'No Anthropic API key found. Run "almightygpt auth anthropic" ' +
89
+ "or export ANTHROPIC_API_KEY in your environment.",
73
90
  this.name,
74
91
  );
75
92
  }
@@ -81,7 +98,7 @@ export class ClaudeAdapter implements Adapter {
81
98
  const start = Date.now();
82
99
  let response: Anthropic.Message;
83
100
  try {
84
- response = await this.client.messages.create(
101
+ response = await client.messages.create(
85
102
  {
86
103
  model,
87
104
  max_tokens: maxOutputTokens,
@@ -29,6 +29,7 @@ import {
29
29
  type AdapterInput,
30
30
  type AdapterOutput,
31
31
  } from "./types.js";
32
+ import { resolveApiKey } from "../auth/resolver.js";
32
33
 
33
34
  const PRICING_USD_PER_1M: Record<string, { input: number; output: number }> = {
34
35
  "gemini-2.5-pro": { input: 1.25, output: 10.0 },
@@ -58,7 +59,9 @@ export class GeminiAdapter implements Adapter {
58
59
  readonly name: string;
59
60
  readonly provider = "google";
60
61
 
61
- private readonly client: GoogleGenerativeAI | null;
62
+ private client: GoogleGenerativeAI | null = null;
63
+ private resolved = false;
64
+ private readonly explicitApiKey: string | undefined;
62
65
  readonly defaultModel: string;
63
66
  private readonly defaultMaxOutputTokens: number;
64
67
  private readonly defaultTimeoutMs: number;
@@ -73,23 +76,30 @@ export class GeminiAdapter implements Adapter {
73
76
  // below to make sure the visible response gets the full budget.
74
77
  this.defaultMaxOutputTokens = options.defaultMaxOutputTokens ?? 8192;
75
78
  this.defaultTimeoutMs = options.defaultTimeoutMs ?? 120_000;
79
+ this.explicitApiKey = options.apiKey;
80
+ }
76
81
 
77
- const apiKey =
78
- options.apiKey ??
79
- process.env["GOOGLE_API_KEY"] ??
80
- process.env["GEMINI_API_KEY"];
81
- this.client = apiKey ? new GoogleGenerativeAI(apiKey) : null;
82
+ /** Lazily resolve via the unified resolver: explicit → env → keychain. */
83
+ private async ensureClient(): Promise<GoogleGenerativeAI | null> {
84
+ if (this.resolved) return this.client;
85
+ this.resolved = true;
86
+ const opts = this.explicitApiKey ? { explicit: this.explicitApiKey } : {};
87
+ const result = await resolveApiKey("google", opts);
88
+ if (result.source === "missing") return null;
89
+ this.client = new GoogleGenerativeAI(result.key!);
90
+ return this.client;
82
91
  }
83
92
 
84
93
  async isAvailable(): Promise<boolean> {
85
- return this.client !== null;
94
+ return (await this.ensureClient()) !== null;
86
95
  }
87
96
 
88
97
  async execute(input: AdapterInput): Promise<AdapterOutput> {
89
- if (!this.client) {
98
+ const client = await this.ensureClient();
99
+ if (!client) {
90
100
  throw new AdapterError(
91
- "GOOGLE_API_KEY (or GEMINI_API_KEY) is not set. " +
92
- "Export one in your environment.",
101
+ 'No Google API key found. Run "almightygpt auth google" ' +
102
+ "or export GOOGLE_API_KEY (or GEMINI_API_KEY) in your environment.",
93
103
  this.name,
94
104
  );
95
105
  }
@@ -112,7 +122,7 @@ export class GeminiAdapter implements Adapter {
112
122
  generationConfig["responseMimeType"] = "application/json";
113
123
  }
114
124
 
115
- const generative = this.client.getGenerativeModel({
125
+ const generative = client.getGenerativeModel({
116
126
  model,
117
127
  systemInstruction: input.systemPrompt,
118
128
  // eslint-disable-next-line @typescript-eslint/no-explicit-any