theroundtaible 0.2.0 → 0.3.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/README.md +61 -1
- package/dist/adapters/base.d.ts +4 -10
- package/dist/adapters/base.d.ts.map +1 -1
- package/dist/adapters/base.js +5 -62
- package/dist/adapters/base.js.map +1 -1
- package/dist/adapters/claude-api.d.ts +11 -0
- package/dist/adapters/claude-api.d.ts.map +1 -0
- package/dist/adapters/claude-api.js +61 -0
- package/dist/adapters/claude-api.js.map +1 -0
- package/dist/adapters/claude-cli.d.ts.map +1 -1
- package/dist/adapters/claude-cli.js +22 -12
- package/dist/adapters/claude-cli.js.map +1 -1
- package/dist/adapters/gemini-api.d.ts +11 -0
- package/dist/adapters/gemini-api.d.ts.map +1 -0
- package/dist/adapters/gemini-api.js +57 -0
- package/dist/adapters/gemini-api.js.map +1 -0
- package/dist/adapters/gemini-cli.d.ts.map +1 -1
- package/dist/adapters/gemini-cli.js +28 -11
- package/dist/adapters/gemini-cli.js.map +1 -1
- package/dist/adapters/openai-api.d.ts +1 -1
- package/dist/adapters/openai-api.d.ts.map +1 -1
- package/dist/adapters/openai-api.js +14 -7
- package/dist/adapters/openai-api.js.map +1 -1
- package/dist/adapters/openai-cli.d.ts.map +1 -1
- package/dist/adapters/openai-cli.js +15 -9
- package/dist/adapters/openai-cli.js.map +1 -1
- package/dist/commands/apply.d.ts +14 -2
- package/dist/commands/apply.d.ts.map +1 -1
- package/dist/commands/apply.js +561 -89
- package/dist/commands/apply.js.map +1 -1
- package/dist/commands/chronicle.d.ts.map +1 -1
- package/dist/commands/chronicle.js +2 -3
- package/dist/commands/chronicle.js.map +1 -1
- package/dist/commands/code-red.d.ts.map +1 -1
- package/dist/commands/code-red.js +23 -25
- package/dist/commands/code-red.js.map +1 -1
- package/dist/commands/decrees.d.ts +6 -0
- package/dist/commands/decrees.d.ts.map +1 -0
- package/dist/commands/decrees.js +35 -0
- package/dist/commands/decrees.js.map +1 -0
- package/dist/commands/discuss.d.ts.map +1 -1
- package/dist/commands/discuss.js +54 -16
- package/dist/commands/discuss.js.map +1 -1
- package/dist/commands/init.d.ts +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +103 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/manifest.d.ts +17 -0
- package/dist/commands/manifest.d.ts.map +1 -0
- package/dist/commands/manifest.js +91 -0
- package/dist/commands/manifest.js.map +1 -0
- package/dist/commands/summon.d.ts.map +1 -1
- package/dist/commands/summon.js +3 -12
- package/dist/commands/summon.js.map +1 -1
- package/dist/consensus.d.ts +12 -1
- package/dist/consensus.d.ts.map +1 -1
- package/dist/consensus.js +183 -44
- package/dist/consensus.js.map +1 -1
- package/dist/index.js +96 -18
- package/dist/index.js.map +1 -1
- package/dist/orchestrator.d.ts +6 -6
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +103 -42
- package/dist/orchestrator.js.map +1 -1
- package/dist/types.d.ts +104 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/utils/adapters.d.ts.map +1 -1
- package/dist/utils/adapters.js +10 -0
- package/dist/utils/adapters.js.map +1 -1
- package/dist/utils/block-scanner.d.ts +28 -0
- package/dist/utils/block-scanner.d.ts.map +1 -0
- package/dist/utils/block-scanner.js +432 -0
- package/dist/utils/block-scanner.js.map +1 -0
- package/dist/utils/config.d.ts +2 -3
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +7 -8
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/context.d.ts +10 -1
- package/dist/utils/context.d.ts.map +1 -1
- package/dist/utils/context.js +56 -1
- package/dist/utils/context.js.map +1 -1
- package/dist/utils/decree-log.d.ts +20 -0
- package/dist/utils/decree-log.d.ts.map +1 -0
- package/dist/utils/decree-log.js +85 -0
- package/dist/utils/decree-log.js.map +1 -0
- package/dist/utils/decree.d.ts +6 -0
- package/dist/utils/decree.d.ts.map +1 -1
- package/dist/utils/decree.js +27 -2
- package/dist/utils/decree.js.map +1 -1
- package/dist/utils/diff-parser.d.ts +28 -0
- package/dist/utils/diff-parser.d.ts.map +1 -0
- package/dist/utils/diff-parser.js +233 -0
- package/dist/utils/diff-parser.js.map +1 -0
- package/dist/utils/edit-parser.d.ts +20 -0
- package/dist/utils/edit-parser.d.ts.map +1 -0
- package/dist/utils/edit-parser.js +208 -0
- package/dist/utils/edit-parser.js.map +1 -0
- package/dist/utils/errors.d.ts +65 -0
- package/dist/utils/errors.d.ts.map +1 -0
- package/dist/utils/errors.js +136 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/file-writer.d.ts +63 -4
- package/dist/utils/file-writer.d.ts.map +1 -1
- package/dist/utils/file-writer.js +288 -10
- package/dist/utils/file-writer.js.map +1 -1
- package/dist/utils/format.d.ts +9 -0
- package/dist/utils/format.d.ts.map +1 -0
- package/dist/utils/format.js +23 -0
- package/dist/utils/format.js.map +1 -0
- package/dist/utils/keys.d.ts +19 -0
- package/dist/utils/keys.d.ts.map +1 -0
- package/dist/utils/keys.js +62 -0
- package/dist/utils/keys.js.map +1 -0
- package/dist/utils/manifest.d.ts +38 -0
- package/dist/utils/manifest.d.ts.map +1 -0
- package/dist/utils/manifest.js +144 -0
- package/dist/utils/manifest.js.map +1 -0
- package/dist/utils/prompt.d.ts +2 -2
- package/dist/utils/prompt.d.ts.map +1 -1
- package/dist/utils/prompt.js +16 -8
- package/dist/utils/prompt.js.map +1 -1
- package/dist/utils/validation.d.ts +32 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +223 -0
- package/dist/utils/validation.js.map +1 -0
- package/package.json +1 -1
- package/templates/code-red-prompt.md +1 -1
- package/templates/system-prompt.md +17 -2
package/README.md
CHANGED
|
@@ -87,9 +87,15 @@ roundtable code-red "login page crashes on submit"
|
|
|
87
87
|
| `roundtable init` | Interactive setup wizard — detects your AI tools |
|
|
88
88
|
| `roundtable discuss "topic"` | Start a multi-AI discussion |
|
|
89
89
|
| `roundtable summon` | Start a discussion based on your `git diff` |
|
|
90
|
-
| `roundtable apply` | Execute the consensus decision (Lead Knight writes code) |
|
|
90
|
+
| `roundtable apply` | Execute the consensus decision (Lead Knight writes code) — **BETA** |
|
|
91
91
|
| `roundtable apply --noparley` | Execute without file-by-file review (dangerous) |
|
|
92
|
+
| `roundtable apply --dry-run` | Run full pipeline without writing files — see what would happen |
|
|
93
|
+
| `roundtable apply --override-scope` | Bypass file scope enforcement (requires reason) |
|
|
92
94
|
| `roundtable code-red "symptoms"` | Emergency diagnostic mode — knights become doctors |
|
|
95
|
+
| `roundtable manifest list` | Show all tracked features in the implementation manifest |
|
|
96
|
+
| `roundtable manifest check` | Check manifest for stale entries (deleted files) |
|
|
97
|
+
| `roundtable manifest add <id> --files` | Manually add a feature to the manifest |
|
|
98
|
+
| `roundtable manifest deprecate <id>` | Mark a feature as deprecated |
|
|
93
99
|
| `roundtable status` | Show current session status |
|
|
94
100
|
| `roundtable list` | List all discussion sessions |
|
|
95
101
|
| `roundtable chronicle` | View the decision log |
|
|
@@ -152,6 +158,37 @@ When they agree on a diagnosis, you choose: **Fix now**, **Report only**, or **L
|
|
|
152
158
|
|
|
153
159
|
All diagnoses are tracked in `.roundtable/error-log.md` with CR-XXX IDs.
|
|
154
160
|
|
|
161
|
+
## Implementation Manifest
|
|
162
|
+
|
|
163
|
+
TheRoundtAIble tracks what has been built. After each `roundtable apply`, the manifest is automatically updated so knights don't re-propose features that already exist.
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
# See what's been built
|
|
167
|
+
roundtable manifest list
|
|
168
|
+
|
|
169
|
+
[+] auth-refactor — JWT with NextAuth wrapper
|
|
170
|
+
Status: implemented | Knight: Claude | 2026-02-17
|
|
171
|
+
Files: src/lib/auth.ts, src/middleware.ts
|
|
172
|
+
|
|
173
|
+
[~] user-dashboard — Dashboard component with charts
|
|
174
|
+
Status: partial | Knight: Gemini | 2026-02-17
|
|
175
|
+
Files: src/components/Dashboard.tsx
|
|
176
|
+
Skipped: src/components/Charts.tsx
|
|
177
|
+
|
|
178
|
+
# Check for stale entries (files that no longer exist)
|
|
179
|
+
roundtable manifest check
|
|
180
|
+
```
|
|
181
|
+
|
|
182
|
+
Knights see the manifest in their system prompt, preventing duplicate proposals.
|
|
183
|
+
|
|
184
|
+
### Scoped Apply
|
|
185
|
+
|
|
186
|
+
When knights reach consensus (score >= 9), they declare which files they intend to modify. The `apply` command enforces this scope:
|
|
187
|
+
|
|
188
|
+
- Files outside the agreed scope are **blocked** (shown in red)
|
|
189
|
+
- Use `--override-scope` to bypass (requires typing "YES" + a reason, logged for audit)
|
|
190
|
+
- Old sessions without scope data work normally (no enforcement)
|
|
191
|
+
|
|
155
192
|
## Project structure
|
|
156
193
|
|
|
157
194
|
```
|
|
@@ -159,6 +196,7 @@ your-project/
|
|
|
159
196
|
.roundtable/
|
|
160
197
|
config.json # Which knights, rules, capabilities
|
|
161
198
|
chronicle.md # Decision log (persistent memory)
|
|
199
|
+
manifest.json # Implementation manifest (what's been built)
|
|
162
200
|
error-log.md # Code-red diagnostic log
|
|
163
201
|
sessions/
|
|
164
202
|
2026-02-16-auth-refactor/
|
|
@@ -181,11 +219,33 @@ See [architecture-docs.md](architecture-docs.md) for the full technical architec
|
|
|
181
219
|
- [x] Code-Red emergency diagnostic mode
|
|
182
220
|
- [x] Git-diff based discussions (`summon`)
|
|
183
221
|
- [x] Chronicle (persistent decision memory)
|
|
222
|
+
- [x] Implementation Manifest (tracks what's been built)
|
|
223
|
+
- [x] Scoped Apply (knights declare files, apply enforces scope)
|
|
184
224
|
- [ ] VS Code extension
|
|
185
225
|
- [ ] Web dashboard for session visualization
|
|
186
226
|
- [ ] More adapters (DeepSeek, Llama, Mistral)
|
|
187
227
|
- [ ] CI/CD integration (GitHub Actions)
|
|
188
228
|
|
|
229
|
+
## Known Limitations
|
|
230
|
+
|
|
231
|
+
### `roundtable apply` — BETA, use at own risk
|
|
232
|
+
|
|
233
|
+
`roundtable apply` works but is in beta. The block-level system (RTDIFF/1) lets knights target specific functions and classes instead of rewriting entire files, which solved the reliability issues with large files. Validation catches bad output before anything is written — your code is safe.
|
|
234
|
+
|
|
235
|
+
**What works:**
|
|
236
|
+
- `roundtable discuss` — multi-AI discussions work reliably
|
|
237
|
+
- `roundtable apply` — writes code via block-level operations (tested on 600+ line files)
|
|
238
|
+
- `roundtable apply --dry-run` — test the full pipeline without writing anything
|
|
239
|
+
- Validation pipeline — blocks bad output (157 tests, no corrupted files)
|
|
240
|
+
- Scope enforcement + backup system
|
|
241
|
+
|
|
242
|
+
**Known risks:**
|
|
243
|
+
- Output quality depends on the LLM — validation blocks bad code but nothing gets written
|
|
244
|
+
- Single attempt, no retry — if the knight fails, you re-run or apply manually
|
|
245
|
+
- More real-world testing needed
|
|
246
|
+
|
|
247
|
+
If apply fails, read the decision in `.roundtable/sessions/*/decisions.md` and apply manually.
|
|
248
|
+
|
|
189
249
|
## License
|
|
190
250
|
|
|
191
251
|
MIT — Tarik Polat ([polatinos](https://github.com/polatinos))
|
package/dist/adapters/base.d.ts
CHANGED
|
@@ -1,14 +1,8 @@
|
|
|
1
1
|
import type { ConsensusBlock } from "../types.js";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
constructor(message: string, kind: AdapterErrorKind, adapterName: string);
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* Classify an error thrown during adapter execution into a known kind.
|
|
10
|
-
*/
|
|
11
|
-
export declare function classifyError(error: unknown, adapterName: string): AdapterError;
|
|
2
|
+
import { AdapterError, classifyError } from "../utils/errors.js";
|
|
3
|
+
import type { AdapterErrorKind } from "../utils/errors.js";
|
|
4
|
+
export { AdapterError, classifyError };
|
|
5
|
+
export type { AdapterErrorKind };
|
|
12
6
|
export declare abstract class BaseAdapter {
|
|
13
7
|
abstract readonly name: string;
|
|
14
8
|
abstract execute(prompt: string, timeoutMs?: number): Promise<string>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAElD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACjE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AACvC,YAAY,EAAE,gBAAgB,EAAE,CAAC;AAEjC,8BAAsB,WAAW;IAC/B,QAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAE/B,QAAQ,CAAC,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAErE,QAAQ,CAAC,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAExC,cAAc,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,cAAc,GAAG,IAAI;CAGvE"}
|
package/dist/adapters/base.js
CHANGED
|
@@ -1,67 +1,10 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
super(message);
|
|
6
|
-
this.name = "AdapterError";
|
|
7
|
-
this.kind = kind;
|
|
8
|
-
this.adapterName = adapterName;
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
/**
|
|
12
|
-
* Classify an error thrown during adapter execution into a known kind.
|
|
13
|
-
*/
|
|
14
|
-
export function classifyError(error, adapterName) {
|
|
15
|
-
const msg = error instanceof Error ? error.message : String(error);
|
|
16
|
-
const lower = msg.toLowerCase();
|
|
17
|
-
if (lower.includes("enoent") || lower.includes("not found") || lower.includes("not recognized")) {
|
|
18
|
-
return new AdapterError(msg, "not_installed", adapterName);
|
|
19
|
-
}
|
|
20
|
-
if (lower.includes("timeout") || lower.includes("timed out") || lower.includes("etimedout")) {
|
|
21
|
-
return new AdapterError(msg, "timeout", adapterName);
|
|
22
|
-
}
|
|
23
|
-
if (lower.includes("401") || lower.includes("403") || lower.includes("unauthorized") || lower.includes("api key")) {
|
|
24
|
-
return new AdapterError(msg, "auth", adapterName);
|
|
25
|
-
}
|
|
26
|
-
if (lower.includes("api error") || lower.includes("429") || lower.includes("500") || lower.includes("502") || lower.includes("503")) {
|
|
27
|
-
return new AdapterError(msg, "api", adapterName);
|
|
28
|
-
}
|
|
29
|
-
return new AdapterError(msg, "unknown", adapterName);
|
|
30
|
-
}
|
|
1
|
+
import { parseConsensusFromResponse } from "../consensus.js";
|
|
2
|
+
import { AdapterError, classifyError } from "../utils/errors.js";
|
|
3
|
+
// Re-export for backward compatibility (orchestrator imports from here)
|
|
4
|
+
export { AdapterError, classifyError };
|
|
31
5
|
export class BaseAdapter {
|
|
32
6
|
parseConsensus(response, round) {
|
|
33
|
-
|
|
34
|
-
// Knights are instructed to end with a JSON block containing consensus_score
|
|
35
|
-
const jsonPatterns = [
|
|
36
|
-
// Fenced code block with json
|
|
37
|
-
/```json\s*\n?([\s\S]*?)\n?\s*```/,
|
|
38
|
-
// Fenced code block without language
|
|
39
|
-
/```\s*\n?([\s\S]*?)\n?\s*```/,
|
|
40
|
-
// Raw JSON object containing consensus_score
|
|
41
|
-
/(\{[^{}]*"consensus_score"\s*:[^{}]*\})/,
|
|
42
|
-
];
|
|
43
|
-
for (const pattern of jsonPatterns) {
|
|
44
|
-
const match = response.match(pattern);
|
|
45
|
-
if (!match?.[1])
|
|
46
|
-
continue;
|
|
47
|
-
try {
|
|
48
|
-
const parsed = JSON.parse(match[1].trim());
|
|
49
|
-
if (typeof parsed.consensus_score === "number") {
|
|
50
|
-
return {
|
|
51
|
-
knight: parsed.knight || this.name,
|
|
52
|
-
round: parsed.round || round,
|
|
53
|
-
consensus_score: parsed.consensus_score,
|
|
54
|
-
agrees_with: Array.isArray(parsed.agrees_with) ? parsed.agrees_with : [],
|
|
55
|
-
pending_issues: Array.isArray(parsed.pending_issues) ? parsed.pending_issues : [],
|
|
56
|
-
proposal: parsed.proposal,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
catch {
|
|
61
|
-
// Try next pattern
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
return null;
|
|
7
|
+
return parseConsensusFromResponse(response, this.name, round);
|
|
65
8
|
}
|
|
66
9
|
}
|
|
67
10
|
//# sourceMappingURL=base.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../src/adapters/base.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,0BAA0B,EAAE,MAAM,iBAAiB,CAAC;AAC7D,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAGjE,wEAAwE;AACxE,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,CAAC;AAGvC,MAAM,OAAgB,WAAW;IAO/B,cAAc,CAAC,QAAgB,EAAE,KAAa;QAC5C,OAAO,0BAA0B,CAAC,QAAQ,EAAE,IAAI,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;IAChE,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseAdapter } from "./base.js";
|
|
2
|
+
export declare class ClaudeApiAdapter extends BaseAdapter {
|
|
3
|
+
readonly name = "Claude";
|
|
4
|
+
private model;
|
|
5
|
+
private envKey;
|
|
6
|
+
private defaultTimeout;
|
|
7
|
+
constructor(model?: string, envKey?: string, timeoutMs?: number);
|
|
8
|
+
isAvailable(): Promise<boolean>;
|
|
9
|
+
execute(prompt: string, timeoutMs?: number): Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=claude-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-api.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAIxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;gBAEnB,KAAK,GAAE,MAAmC,EAAE,MAAM,GAAE,MAA4B,EAAE,SAAS,GAAE,MAAgB;IAOnH,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkDnE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { BaseAdapter } from "./base.js";
|
|
2
|
+
import { classifyError } from "../utils/errors.js";
|
|
3
|
+
import { getKey } from "../utils/keys.js";
|
|
4
|
+
export class ClaudeApiAdapter extends BaseAdapter {
|
|
5
|
+
name = "Claude";
|
|
6
|
+
model;
|
|
7
|
+
envKey;
|
|
8
|
+
defaultTimeout;
|
|
9
|
+
constructor(model = "claude-sonnet-4-20250514", envKey = "ANTHROPIC_API_KEY", timeoutMs = 120_000) {
|
|
10
|
+
super();
|
|
11
|
+
this.model = model;
|
|
12
|
+
this.envKey = envKey;
|
|
13
|
+
this.defaultTimeout = timeoutMs;
|
|
14
|
+
}
|
|
15
|
+
async isAvailable() {
|
|
16
|
+
const key = await getKey(this.envKey);
|
|
17
|
+
return typeof key === "string" && key.length > 0;
|
|
18
|
+
}
|
|
19
|
+
async execute(prompt, timeoutMs) {
|
|
20
|
+
const apiKey = await getKey(this.envKey);
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw classifyError(new Error(`Anthropic API key not set. Set ${this.envKey} or run 'roundtable init'.`), this.name);
|
|
23
|
+
}
|
|
24
|
+
const timeout = timeoutMs ?? this.defaultTimeout;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
27
|
+
try {
|
|
28
|
+
const response = await fetch("https://api.anthropic.com/v1/messages", {
|
|
29
|
+
method: "POST",
|
|
30
|
+
headers: {
|
|
31
|
+
"Content-Type": "application/json",
|
|
32
|
+
"x-api-key": apiKey,
|
|
33
|
+
"anthropic-version": "2023-06-01",
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
model: this.model,
|
|
37
|
+
max_tokens: 16384,
|
|
38
|
+
messages: [{ role: "user", content: prompt }],
|
|
39
|
+
}),
|
|
40
|
+
signal: controller.signal,
|
|
41
|
+
});
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const errorBody = await response.text();
|
|
44
|
+
throw new Error(`Anthropic API error (${response.status}): ${errorBody}`);
|
|
45
|
+
}
|
|
46
|
+
const data = (await response.json());
|
|
47
|
+
const text = data.content?.find((c) => c.type === "text")?.text;
|
|
48
|
+
if (!text) {
|
|
49
|
+
throw new Error("Anthropic API returned empty response");
|
|
50
|
+
}
|
|
51
|
+
return text;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
throw classifyError(error, this.name);
|
|
55
|
+
}
|
|
56
|
+
finally {
|
|
57
|
+
clearTimeout(timer);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=claude-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-api.js","sourceRoot":"","sources":["../../src/adapters/claude-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IACtC,IAAI,GAAG,QAAQ,CAAC;IAEjB,KAAK,CAAS;IACd,MAAM,CAAS;IACf,cAAc,CAAS;IAE/B,YAAY,QAAgB,0BAA0B,EAAE,SAAiB,mBAAmB,EAAE,YAAoB,OAAO;QACvH,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAkB;QAC9C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,aAAa,CACjB,IAAI,KAAK,CAAC,kCAAkC,IAAI,CAAC,MAAM,4BAA4B,CAAC,EACpF,IAAI,CAAC,IAAI,CACV,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,uCAAuC,EAAE;gBACpE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,MAAM;oBACnB,mBAAmB,EAAE,YAAY;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,UAAU,EAAE,KAAK;oBACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;iBAC9C,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,wBAAwB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;YAC5E,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;YAEF,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,EAAE,IAAI,CAAC;YAChE,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;YAC3D,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/claude-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,MAAiB,EAAE,SAAS,GAAE,MAAgB;IAM7D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAgCnE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
2
|
import { BaseAdapter } from "./base.js";
|
|
3
|
+
import { classifyError } from "../utils/errors.js";
|
|
3
4
|
export class ClaudeCliAdapter extends BaseAdapter {
|
|
4
5
|
name = "Claude";
|
|
5
6
|
command;
|
|
@@ -11,8 +12,8 @@ export class ClaudeCliAdapter extends BaseAdapter {
|
|
|
11
12
|
}
|
|
12
13
|
async isAvailable() {
|
|
13
14
|
try {
|
|
14
|
-
|
|
15
|
-
return
|
|
15
|
+
await execa(this.command, ["--version"]);
|
|
16
|
+
return true;
|
|
16
17
|
}
|
|
17
18
|
catch {
|
|
18
19
|
return false;
|
|
@@ -26,17 +27,26 @@ export class ClaudeCliAdapter extends BaseAdapter {
|
|
|
26
27
|
// terminal where Claude Code is running. Empty string is not enough.
|
|
27
28
|
const env = { ...process.env };
|
|
28
29
|
delete env.CLAUDECODE;
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
30
|
+
try {
|
|
31
|
+
const result = await execa(this.command, [
|
|
32
|
+
"--print",
|
|
33
|
+
"--output-format", "text",
|
|
34
|
+
"--disallowedTools", "Edit,Write,Bash,Read,Glob,Grep,NotebookEdit,WebFetch,WebSearch,Task",
|
|
35
|
+
], {
|
|
36
|
+
input: prompt,
|
|
37
|
+
timeout,
|
|
38
|
+
reject: false,
|
|
39
|
+
env,
|
|
40
|
+
});
|
|
41
|
+
if (result.exitCode !== 0) {
|
|
42
|
+
const errorMsg = result.stderr || result.stdout || "Unknown error";
|
|
43
|
+
throw new Error(`Claude CLI failed (exit ${result.exitCode}): ${errorMsg}`);
|
|
44
|
+
}
|
|
45
|
+
return result.stdout;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw classifyError(error, this.name);
|
|
38
49
|
}
|
|
39
|
-
return result.stdout;
|
|
40
50
|
}
|
|
41
51
|
}
|
|
42
52
|
//# sourceMappingURL=claude-cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"claude-cli.js","sourceRoot":"","sources":["../../src/adapters/claude-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"claude-cli.js","sourceRoot":"","sources":["../../src/adapters/claude-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IACtC,IAAI,GAAG,QAAQ,CAAC;IAEjB,OAAO,CAAS;IAChB,cAAc,CAAS;IAE/B,YAAY,UAAkB,QAAQ,EAAE,YAAoB,OAAO;QACjE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAkB;QAC9C,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QAEjD,oDAAoD;QACpD,0CAA0C;QAC1C,6EAA6E;QAC7E,qEAAqE;QACrE,MAAM,GAAG,GAAG,EAAE,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;QAC/B,OAAO,GAAG,CAAC,UAAU,CAAC;QAEtB,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;gBACvC,SAAS;gBACT,iBAAiB,EAAE,MAAM;gBACzB,mBAAmB,EAAE,qEAAqE;aAC3F,EAAE;gBACD,KAAK,EAAE,MAAM;gBACb,OAAO;gBACP,MAAM,EAAE,KAAK;gBACb,GAAG;aACJ,CAAC,CAAC;YAEH,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;gBACnE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,QAAQ,MAAM,QAAQ,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { BaseAdapter } from "./base.js";
|
|
2
|
+
export declare class GeminiApiAdapter extends BaseAdapter {
|
|
3
|
+
readonly name = "Gemini";
|
|
4
|
+
private model;
|
|
5
|
+
private envKey;
|
|
6
|
+
private defaultTimeout;
|
|
7
|
+
constructor(model?: string, envKey?: string, timeoutMs?: number);
|
|
8
|
+
isAvailable(): Promise<boolean>;
|
|
9
|
+
execute(prompt: string, timeoutMs?: number): Promise<string>;
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=gemini-api.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-api.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAIxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;gBAEnB,KAAK,GAAE,MAA2B,EAAE,MAAM,GAAE,MAAyB,EAAE,SAAS,GAAE,MAAgB;IAOxG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA8CnE"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { BaseAdapter } from "./base.js";
|
|
2
|
+
import { classifyError } from "../utils/errors.js";
|
|
3
|
+
import { getKey } from "../utils/keys.js";
|
|
4
|
+
export class GeminiApiAdapter extends BaseAdapter {
|
|
5
|
+
name = "Gemini";
|
|
6
|
+
model;
|
|
7
|
+
envKey;
|
|
8
|
+
defaultTimeout;
|
|
9
|
+
constructor(model = "gemini-2.0-flash", envKey = "GEMINI_API_KEY", timeoutMs = 120_000) {
|
|
10
|
+
super();
|
|
11
|
+
this.model = model;
|
|
12
|
+
this.envKey = envKey;
|
|
13
|
+
this.defaultTimeout = timeoutMs;
|
|
14
|
+
}
|
|
15
|
+
async isAvailable() {
|
|
16
|
+
const key = await getKey(this.envKey);
|
|
17
|
+
return typeof key === "string" && key.length > 0;
|
|
18
|
+
}
|
|
19
|
+
async execute(prompt, timeoutMs) {
|
|
20
|
+
const apiKey = await getKey(this.envKey);
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw classifyError(new Error(`Gemini API key not set. Set ${this.envKey} or run 'roundtable init'.`), this.name);
|
|
23
|
+
}
|
|
24
|
+
const timeout = timeoutMs ?? this.defaultTimeout;
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
27
|
+
try {
|
|
28
|
+
const url = `https://generativelanguage.googleapis.com/v1beta/models/${this.model}:generateContent?key=${apiKey}`;
|
|
29
|
+
const response = await fetch(url, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "Content-Type": "application/json" },
|
|
32
|
+
body: JSON.stringify({
|
|
33
|
+
contents: [{ parts: [{ text: prompt }] }],
|
|
34
|
+
generationConfig: { maxOutputTokens: 16384 },
|
|
35
|
+
}),
|
|
36
|
+
signal: controller.signal,
|
|
37
|
+
});
|
|
38
|
+
if (!response.ok) {
|
|
39
|
+
const errorBody = await response.text();
|
|
40
|
+
throw new Error(`Gemini API error (${response.status}): ${errorBody}`);
|
|
41
|
+
}
|
|
42
|
+
const data = (await response.json());
|
|
43
|
+
const text = data.candidates?.[0]?.content?.parts?.[0]?.text;
|
|
44
|
+
if (!text) {
|
|
45
|
+
throw new Error("Gemini API returned empty response");
|
|
46
|
+
}
|
|
47
|
+
return text;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw classifyError(error, this.name);
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
clearTimeout(timer);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=gemini-api.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini-api.js","sourceRoot":"","sources":["../../src/adapters/gemini-api.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,YAAY;IAEzB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,MAAiB,EAAE,SAAS,GAAE,MAAgB;IAM7D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAkCnE"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { execa } from "execa";
|
|
2
2
|
import { BaseAdapter } from "./base.js";
|
|
3
|
+
import { classifyError } from "../utils/errors.js";
|
|
3
4
|
export class GeminiCliAdapter extends BaseAdapter {
|
|
4
5
|
name = "Gemini";
|
|
5
6
|
command;
|
|
@@ -20,18 +21,34 @@ export class GeminiCliAdapter extends BaseAdapter {
|
|
|
20
21
|
}
|
|
21
22
|
async execute(prompt, timeoutMs) {
|
|
22
23
|
const timeout = timeoutMs ?? this.defaultTimeout;
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
24
|
+
// --approval-mode plan = read-only mode (no tool execution).
|
|
25
|
+
// -e with empty string disables skills/extensions that cause conflicts.
|
|
26
|
+
// Gemini may still attempt tools in plan mode (exit_plan_mode, write_file)
|
|
27
|
+
// which get denied — so we accept output even on non-zero exit if stdout exists.
|
|
28
|
+
try {
|
|
29
|
+
const result = await execa(this.command, [
|
|
30
|
+
"-p", "",
|
|
31
|
+
"--approval-mode", "plan",
|
|
32
|
+
"-e", "",
|
|
33
|
+
], {
|
|
34
|
+
input: prompt,
|
|
35
|
+
timeout,
|
|
36
|
+
reject: false,
|
|
37
|
+
});
|
|
38
|
+
// Gemini often exits non-zero due to tool denials in plan mode,
|
|
39
|
+
// but still produces valid output on stdout. Use it if available.
|
|
40
|
+
if (result.stdout && result.stdout.trim().length > 50) {
|
|
41
|
+
return result.stdout;
|
|
42
|
+
}
|
|
43
|
+
if (result.exitCode !== 0) {
|
|
44
|
+
const errorMsg = result.stderr || result.stdout || "Unknown error";
|
|
45
|
+
throw new Error(`Gemini CLI failed (exit ${result.exitCode}): ${errorMsg}`);
|
|
46
|
+
}
|
|
47
|
+
return result.stdout;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
throw classifyError(error, this.name);
|
|
33
51
|
}
|
|
34
|
-
return result.stdout;
|
|
35
52
|
}
|
|
36
53
|
}
|
|
37
54
|
//# sourceMappingURL=gemini-cli.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"gemini-cli.js","sourceRoot":"","sources":["../../src/adapters/gemini-cli.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAC9B,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AAEnD,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IACtC,IAAI,GAAG,QAAQ,CAAC;IAEjB,OAAO,CAAS;IAChB,cAAc,CAAS;IAE/B,YAAY,UAAkB,QAAQ,EAAE,YAAoB,OAAO;QACjE,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;QACvB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC;YACzC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAkB;QAC9C,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QAEjD,6DAA6D;QAC7D,wEAAwE;QACxE,2EAA2E;QAC3E,iFAAiF;QACjF,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE;gBACvC,IAAI,EAAE,EAAE;gBACR,iBAAiB,EAAE,MAAM;gBACzB,IAAI,EAAE,EAAE;aACT,EAAE;gBACD,KAAK,EAAE,MAAM;gBACb,OAAO;gBACP,MAAM,EAAE,KAAK;aACd,CAAC,CAAC;YAEH,gEAAgE;YAChE,kEAAkE;YAClE,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,EAAE,EAAE,CAAC;gBACtD,OAAO,MAAM,CAAC,MAAM,CAAC;YACvB,CAAC;YAED,IAAI,MAAM,CAAC,QAAQ,KAAK,CAAC,EAAE,CAAC;gBAC1B,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,eAAe,CAAC;gBACnE,MAAM,IAAI,KAAK,CAAC,2BAA2B,MAAM,CAAC,QAAQ,MAAM,QAAQ,EAAE,CAAC,CAAC;YAC9E,CAAC;YAED,OAAO,MAAM,CAAC,MAAM,CAAC;QACvB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;CACF"}
|
|
@@ -2,7 +2,7 @@ import { BaseAdapter } from "./base.js";
|
|
|
2
2
|
export declare class OpenAIApiAdapter extends BaseAdapter {
|
|
3
3
|
readonly name = "GPT";
|
|
4
4
|
private model;
|
|
5
|
-
private
|
|
5
|
+
private envKey;
|
|
6
6
|
private defaultTimeout;
|
|
7
7
|
constructor(model?: string, envKey?: string, timeoutMs?: number);
|
|
8
8
|
isAvailable(): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-api.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-api.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAIxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,SAAS;IAEtB,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAS;gBAEnB,KAAK,GAAE,MAAiB,EAAE,MAAM,GAAE,MAAyB,EAAE,SAAS,GAAE,MAAgB;IAO9F,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAK/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAiDnE"}
|
|
@@ -1,21 +1,25 @@
|
|
|
1
1
|
import { BaseAdapter } from "./base.js";
|
|
2
|
+
import { classifyError } from "../utils/errors.js";
|
|
3
|
+
import { getKey } from "../utils/keys.js";
|
|
2
4
|
export class OpenAIApiAdapter extends BaseAdapter {
|
|
3
5
|
name = "GPT";
|
|
4
6
|
model;
|
|
5
|
-
|
|
7
|
+
envKey;
|
|
6
8
|
defaultTimeout;
|
|
7
9
|
constructor(model = "gpt-4o", envKey = "OPENAI_API_KEY", timeoutMs = 120_000) {
|
|
8
10
|
super();
|
|
9
11
|
this.model = model;
|
|
10
|
-
this.
|
|
12
|
+
this.envKey = envKey;
|
|
11
13
|
this.defaultTimeout = timeoutMs;
|
|
12
14
|
}
|
|
13
15
|
async isAvailable() {
|
|
14
|
-
|
|
16
|
+
const key = await getKey(this.envKey);
|
|
17
|
+
return typeof key === "string" && key.length > 0;
|
|
15
18
|
}
|
|
16
19
|
async execute(prompt, timeoutMs) {
|
|
17
|
-
|
|
18
|
-
|
|
20
|
+
const apiKey = await getKey(this.envKey);
|
|
21
|
+
if (!apiKey) {
|
|
22
|
+
throw classifyError(new Error(`OpenAI API key not set. Set ${this.envKey} or run 'roundtable init'.`), this.name);
|
|
19
23
|
}
|
|
20
24
|
const timeout = timeoutMs ?? this.defaultTimeout;
|
|
21
25
|
const controller = new AbortController();
|
|
@@ -25,12 +29,12 @@ export class OpenAIApiAdapter extends BaseAdapter {
|
|
|
25
29
|
method: "POST",
|
|
26
30
|
headers: {
|
|
27
31
|
"Content-Type": "application/json",
|
|
28
|
-
Authorization: `Bearer ${
|
|
32
|
+
Authorization: `Bearer ${apiKey}`,
|
|
29
33
|
},
|
|
30
34
|
body: JSON.stringify({
|
|
31
35
|
model: this.model,
|
|
32
36
|
messages: [{ role: "user", content: prompt }],
|
|
33
|
-
max_tokens:
|
|
37
|
+
max_tokens: 16384,
|
|
34
38
|
}),
|
|
35
39
|
signal: controller.signal,
|
|
36
40
|
});
|
|
@@ -45,6 +49,9 @@ export class OpenAIApiAdapter extends BaseAdapter {
|
|
|
45
49
|
}
|
|
46
50
|
return content;
|
|
47
51
|
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
throw classifyError(error, this.name);
|
|
54
|
+
}
|
|
48
55
|
finally {
|
|
49
56
|
clearTimeout(timer);
|
|
50
57
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-api.js","sourceRoot":"","sources":["../../src/adapters/openai-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-api.js","sourceRoot":"","sources":["../../src/adapters/openai-api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,MAAM,OAAO,gBAAiB,SAAQ,WAAW;IACtC,IAAI,GAAG,KAAK,CAAC;IAEd,KAAK,CAAS;IACd,MAAM,CAAS;IACf,cAAc,CAAS;IAE/B,YAAY,QAAgB,QAAQ,EAAE,SAAiB,gBAAgB,EAAE,YAAoB,OAAO;QAClG,KAAK,EAAE,CAAC;QACR,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;QACnB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,cAAc,GAAG,SAAS,CAAC;IAClC,CAAC;IAED,KAAK,CAAC,WAAW;QACf,MAAM,GAAG,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACtC,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,OAAO,CAAC,MAAc,EAAE,SAAkB;QAC9C,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,MAAM,aAAa,CACjB,IAAI,KAAK,CAAC,+BAA+B,IAAI,CAAC,MAAM,4BAA4B,CAAC,EACjF,IAAI,CAAC,IAAI,CACV,CAAC;QACJ,CAAC;QAED,MAAM,OAAO,GAAG,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC;QACjD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,OAAO,CAAC,CAAC;QAE5D,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,4CAA4C,EAAE;gBACzE,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,aAAa,EAAE,UAAU,MAAM,EAAE;iBAClC;gBACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC;oBACnB,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,QAAQ,EAAE,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC;oBAC7C,UAAU,EAAE,KAAK;iBAClB,CAAC;gBACF,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;gBACjB,MAAM,SAAS,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;gBACxC,MAAM,IAAI,KAAK,CAAC,qBAAqB,QAAQ,CAAC,MAAM,MAAM,SAAS,EAAE,CAAC,CAAC;YACzE,CAAC;YAED,MAAM,IAAI,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAElC,CAAC;YAEF,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC;YACpD,IAAI,CAAC,OAAO,EAAE,CAAC;gBACb,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;YACxD,CAAC;YAED,OAAO,OAAO,CAAC;QACjB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;gBAAS,CAAC;YACT,YAAY,CAAC,KAAK,CAAC,CAAC;QACtB,CAAC;IACH,CAAC;CACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openai-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"openai-cli.d.ts","sourceRoot":"","sources":["../../src/adapters/openai-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AAGxC,qBAAa,gBAAiB,SAAQ,WAAW;IAC/C,QAAQ,CAAC,IAAI,SAAS;IAEtB,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,GAAE,MAAgB,EAAE,SAAS,GAAE,MAAgB;IAM5D,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAS/B,OAAO,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CA0BnE"}
|