agents-reverse-engineer 0.3.6 → 0.4.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/dist/ai/backends/claude.d.ts +92 -0
- package/dist/ai/backends/claude.d.ts.map +1 -0
- package/dist/ai/backends/claude.js +213 -0
- package/dist/ai/backends/claude.js.map +1 -0
- package/dist/ai/backends/gemini.d.ts +53 -0
- package/dist/ai/backends/gemini.d.ts.map +1 -0
- package/dist/ai/backends/gemini.js +66 -0
- package/dist/ai/backends/gemini.js.map +1 -0
- package/dist/ai/backends/opencode.d.ts +53 -0
- package/dist/ai/backends/opencode.d.ts.map +1 -0
- package/dist/ai/backends/opencode.js +66 -0
- package/dist/ai/backends/opencode.js.map +1 -0
- package/dist/ai/index.d.ts +39 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +54 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/pricing.d.ts +84 -0
- package/dist/ai/pricing.d.ts.map +1 -0
- package/dist/ai/pricing.js +149 -0
- package/dist/ai/pricing.js.map +1 -0
- package/dist/ai/pricing.test.d.ts +2 -0
- package/dist/ai/pricing.test.d.ts.map +1 -0
- package/dist/ai/pricing.test.js +164 -0
- package/dist/ai/pricing.test.js.map +1 -0
- package/dist/ai/registry.d.ts +128 -0
- package/dist/ai/registry.d.ts.map +1 -0
- package/dist/ai/registry.js +192 -0
- package/dist/ai/registry.js.map +1 -0
- package/dist/ai/retry.d.ts +77 -0
- package/dist/ai/retry.d.ts.map +1 -0
- package/dist/ai/retry.js +100 -0
- package/dist/ai/retry.js.map +1 -0
- package/dist/ai/service.d.ts +124 -0
- package/dist/ai/service.d.ts.map +1 -0
- package/dist/ai/service.js +239 -0
- package/dist/ai/service.js.map +1 -0
- package/dist/ai/subprocess.d.ts +45 -0
- package/dist/ai/subprocess.d.ts.map +1 -0
- package/dist/ai/subprocess.js +90 -0
- package/dist/ai/subprocess.js.map +1 -0
- package/dist/ai/telemetry/cleanup.d.ts +30 -0
- package/dist/ai/telemetry/cleanup.d.ts.map +1 -0
- package/dist/ai/telemetry/cleanup.js +56 -0
- package/dist/ai/telemetry/cleanup.js.map +1 -0
- package/dist/ai/telemetry/logger.d.ts +76 -0
- package/dist/ai/telemetry/logger.d.ts.map +1 -0
- package/dist/ai/telemetry/logger.js +130 -0
- package/dist/ai/telemetry/logger.js.map +1 -0
- package/dist/ai/telemetry/run-log.d.ts +29 -0
- package/dist/ai/telemetry/run-log.d.ts.map +1 -0
- package/dist/ai/telemetry/run-log.js +43 -0
- package/dist/ai/telemetry/run-log.js.map +1 -0
- package/dist/ai/types.d.ts +235 -0
- package/dist/ai/types.d.ts.map +1 -0
- package/dist/ai/types.js +34 -0
- package/dist/ai/types.js.map +1 -0
- package/dist/cli/discover.d.ts.map +1 -1
- package/dist/cli/discover.js +0 -2
- package/dist/cli/discover.js.map +1 -1
- package/dist/cli/generate.d.ts +22 -14
- package/dist/cli/generate.d.ts.map +1 -1
- package/dist/cli/generate.js +91 -50
- package/dist/cli/generate.js.map +1 -1
- package/dist/cli/index.js +12 -3
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/update.d.ts +13 -4
- package/dist/cli/update.d.ts.map +1 -1
- package/dist/cli/update.js +93 -131
- package/dist/cli/update.js.map +1 -1
- package/dist/config/defaults.d.ts +2 -2
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +2 -0
- package/dist/config/defaults.js.map +1 -1
- package/dist/config/schema.d.ts +175 -1
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js +36 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/generation/executor.d.ts.map +1 -1
- package/dist/generation/executor.js +2 -5
- package/dist/generation/executor.js.map +1 -1
- package/dist/generation/prompts/builder.d.ts +10 -0
- package/dist/generation/prompts/builder.d.ts.map +1 -1
- package/dist/generation/prompts/builder.js +77 -1
- package/dist/generation/prompts/builder.js.map +1 -1
- package/dist/generation/prompts/index.d.ts +1 -1
- package/dist/generation/prompts/index.d.ts.map +1 -1
- package/dist/generation/prompts/index.js +1 -1
- package/dist/generation/prompts/index.js.map +1 -1
- package/dist/generation/prompts/templates.d.ts +5 -0
- package/dist/generation/prompts/templates.d.ts.map +1 -1
- package/dist/generation/prompts/templates.js +94 -7
- package/dist/generation/prompts/templates.js.map +1 -1
- package/dist/generation/prompts/types.d.ts +2 -2
- package/dist/generation/prompts/types.js +1 -1
- package/dist/generation/writers/agents-md.d.ts +3 -59
- package/dist/generation/writers/agents-md.d.ts.map +1 -1
- package/dist/generation/writers/agents-md.js +11 -249
- package/dist/generation/writers/agents-md.js.map +1 -1
- package/dist/generation/writers/index.d.ts +1 -1
- package/dist/generation/writers/index.d.ts.map +1 -1
- package/dist/generation/writers/index.js +1 -1
- package/dist/generation/writers/index.js.map +1 -1
- package/dist/orchestration/index.d.ts +27 -0
- package/dist/orchestration/index.d.ts.map +1 -0
- package/dist/orchestration/index.js +34 -0
- package/dist/orchestration/index.js.map +1 -0
- package/dist/orchestration/pool.d.ts +62 -0
- package/dist/orchestration/pool.d.ts.map +1 -0
- package/dist/orchestration/pool.js +75 -0
- package/dist/orchestration/pool.js.map +1 -0
- package/dist/orchestration/progress.d.ts +124 -0
- package/dist/orchestration/progress.d.ts.map +1 -0
- package/dist/orchestration/progress.js +214 -0
- package/dist/orchestration/progress.js.map +1 -0
- package/dist/orchestration/runner.d.ts +76 -0
- package/dist/orchestration/runner.d.ts.map +1 -0
- package/dist/orchestration/runner.js +494 -0
- package/dist/orchestration/runner.js.map +1 -0
- package/dist/orchestration/types.d.ts +123 -0
- package/dist/orchestration/types.d.ts.map +1 -0
- package/dist/orchestration/types.js +11 -0
- package/dist/orchestration/types.js.map +1 -0
- package/dist/quality/density/validator.d.ts +38 -0
- package/dist/quality/density/validator.d.ts.map +1 -0
- package/dist/quality/density/validator.js +61 -0
- package/dist/quality/density/validator.js.map +1 -0
- package/dist/quality/inconsistency/code-vs-code.d.ts +26 -0
- package/dist/quality/inconsistency/code-vs-code.d.ts.map +1 -0
- package/dist/quality/inconsistency/code-vs-code.js +51 -0
- package/dist/quality/inconsistency/code-vs-code.js.map +1 -0
- package/dist/quality/inconsistency/code-vs-doc.d.ts +35 -0
- package/dist/quality/inconsistency/code-vs-doc.d.ts.map +1 -0
- package/dist/quality/inconsistency/code-vs-doc.js +59 -0
- package/dist/quality/inconsistency/code-vs-doc.js.map +1 -0
- package/dist/quality/inconsistency/code-vs-doc.test.d.ts +2 -0
- package/dist/quality/inconsistency/code-vs-doc.test.d.ts.map +1 -0
- package/dist/quality/inconsistency/code-vs-doc.test.js +196 -0
- package/dist/quality/inconsistency/code-vs-doc.test.js.map +1 -0
- package/dist/quality/inconsistency/reporter.d.ts +49 -0
- package/dist/quality/inconsistency/reporter.d.ts.map +1 -0
- package/dist/quality/inconsistency/reporter.js +99 -0
- package/dist/quality/inconsistency/reporter.js.map +1 -0
- package/dist/quality/index.d.ts +15 -0
- package/dist/quality/index.d.ts.map +1 -0
- package/dist/quality/index.js +25 -0
- package/dist/quality/index.js.map +1 -0
- package/dist/quality/types.d.ts +63 -0
- package/dist/quality/types.d.ts.map +1 -0
- package/dist/quality/types.js +5 -0
- package/dist/quality/types.js.map +1 -0
- package/dist/update/orchestrator.d.ts.map +1 -1
- package/dist/update/orchestrator.js +2 -1
- package/dist/update/orchestrator.js.map +1 -1
- package/dist/update/orphan-cleaner.js +1 -1
- package/dist/update/orphan-cleaner.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI backend adapter.
|
|
3
|
+
*
|
|
4
|
+
* Full implementation of the {@link AIBackend} interface for the Claude Code
|
|
5
|
+
* CLI (`claude`). Builds CLI arguments, parses structured JSON responses
|
|
6
|
+
* with Zod validation, detects CLI availability on PATH, and provides
|
|
7
|
+
* install instructions.
|
|
8
|
+
*
|
|
9
|
+
* The prompt is NOT included in the args array -- it goes to stdin via
|
|
10
|
+
* the subprocess wrapper ({@link runSubprocess}).
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import type { AIBackend, AICallOptions, AIResponse } from '../types.js';
|
|
15
|
+
/**
|
|
16
|
+
* Check whether a command is available on the system PATH.
|
|
17
|
+
*
|
|
18
|
+
* Splits `process.env.PATH` by the platform delimiter and checks each
|
|
19
|
+
* directory for a file matching the command name. On Windows, also checks
|
|
20
|
+
* each extension from `process.env.PATHEXT` (e.g., `.exe`, `.cmd`, `.bat`).
|
|
21
|
+
*
|
|
22
|
+
* Uses `fs.stat` (not `fs.access` with execute bit) for cross-platform
|
|
23
|
+
* compatibility -- Windows does not have Unix execute permissions.
|
|
24
|
+
*
|
|
25
|
+
* @param command - The bare command name to look for (e.g., "claude")
|
|
26
|
+
* @returns `true` if the command exists as a file in any PATH directory
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* ```typescript
|
|
30
|
+
* if (await isCommandOnPath('claude')) {
|
|
31
|
+
* console.log('Claude CLI is available');
|
|
32
|
+
* }
|
|
33
|
+
* ```
|
|
34
|
+
*/
|
|
35
|
+
export declare function isCommandOnPath(command: string): Promise<boolean>;
|
|
36
|
+
/**
|
|
37
|
+
* Claude Code CLI backend adapter.
|
|
38
|
+
*
|
|
39
|
+
* Implements the {@link AIBackend} interface for the `claude` CLI.
|
|
40
|
+
* This is the primary (and currently only fully implemented) backend.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* const backend = new ClaudeBackend();
|
|
45
|
+
* if (await backend.isAvailable()) {
|
|
46
|
+
* const args = backend.buildArgs({ prompt: 'Summarize this file' });
|
|
47
|
+
* const result = await runSubprocess('claude', args, {
|
|
48
|
+
* timeoutMs: 120_000,
|
|
49
|
+
* input: 'Summarize this file',
|
|
50
|
+
* });
|
|
51
|
+
* const response = backend.parseResponse(result.stdout, result.durationMs, result.exitCode);
|
|
52
|
+
* }
|
|
53
|
+
* ```
|
|
54
|
+
*/
|
|
55
|
+
export declare class ClaudeBackend implements AIBackend {
|
|
56
|
+
readonly name = "claude";
|
|
57
|
+
readonly cliCommand = "claude";
|
|
58
|
+
/**
|
|
59
|
+
* Check if the `claude` CLI is available on PATH.
|
|
60
|
+
*/
|
|
61
|
+
isAvailable(): Promise<boolean>;
|
|
62
|
+
/**
|
|
63
|
+
* Build CLI arguments for a Claude invocation.
|
|
64
|
+
*
|
|
65
|
+
* Returns the argument array for `claude -p --output-format json`. The
|
|
66
|
+
* prompt itself is NOT included -- it goes to stdin via the subprocess
|
|
67
|
+
* wrapper.
|
|
68
|
+
*
|
|
69
|
+
* @param options - Call options (model, systemPrompt, maxTurns)
|
|
70
|
+
* @returns Argument array suitable for {@link runSubprocess}
|
|
71
|
+
*/
|
|
72
|
+
buildArgs(options: AICallOptions): string[];
|
|
73
|
+
/**
|
|
74
|
+
* Parse Claude CLI JSON output into a normalized {@link AIResponse}.
|
|
75
|
+
*
|
|
76
|
+
* Handles non-JSON prefix text by finding the first `{` character
|
|
77
|
+
* (defensive parsing per RESEARCH.md Pitfall 4). Validates the response
|
|
78
|
+
* against the Zod schema and extracts the model name from `modelUsage`.
|
|
79
|
+
*
|
|
80
|
+
* @param stdout - Raw stdout from the Claude CLI process
|
|
81
|
+
* @param durationMs - Wall-clock duration of the subprocess
|
|
82
|
+
* @param exitCode - Process exit code
|
|
83
|
+
* @returns Normalized AI response
|
|
84
|
+
* @throws {AIServiceError} With code `PARSE_ERROR` if JSON is missing or schema validation fails
|
|
85
|
+
*/
|
|
86
|
+
parseResponse(stdout: string, durationMs: number, exitCode: number): AIResponse;
|
|
87
|
+
/**
|
|
88
|
+
* Get user-facing install instructions for the Claude CLI.
|
|
89
|
+
*/
|
|
90
|
+
getInstallInstructions(): string;
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=claude.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.d.ts","sourceRoot":"","sources":["../../../src/ai/backends/claude.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AA2CxE;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAsB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CA2BvE;AAMD;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,UAAU,YAAY;IAE/B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;;;;OASG;IACH,SAAS,CAAC,OAAO,EAAE,aAAa,GAAG,MAAM,EAAE;IAuB3C;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,UAAU;IAsC/E;;OAEG;IACH,sBAAsB,IAAI,MAAM;CAOjC"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Claude CLI backend adapter.
|
|
3
|
+
*
|
|
4
|
+
* Full implementation of the {@link AIBackend} interface for the Claude Code
|
|
5
|
+
* CLI (`claude`). Builds CLI arguments, parses structured JSON responses
|
|
6
|
+
* with Zod validation, detects CLI availability on PATH, and provides
|
|
7
|
+
* install instructions.
|
|
8
|
+
*
|
|
9
|
+
* The prompt is NOT included in the args array -- it goes to stdin via
|
|
10
|
+
* the subprocess wrapper ({@link runSubprocess}).
|
|
11
|
+
*
|
|
12
|
+
* @module
|
|
13
|
+
*/
|
|
14
|
+
import * as fs from 'node:fs/promises';
|
|
15
|
+
import * as path from 'node:path';
|
|
16
|
+
import { z } from 'zod';
|
|
17
|
+
import { AIServiceError } from '../types.js';
|
|
18
|
+
// ---------------------------------------------------------------------------
|
|
19
|
+
// Zod schema for Claude CLI JSON output
|
|
20
|
+
// ---------------------------------------------------------------------------
|
|
21
|
+
/**
|
|
22
|
+
* Schema validated against Claude CLI v2.1.31 JSON output.
|
|
23
|
+
*
|
|
24
|
+
* When invoked with `claude -p --output-format json`, the CLI produces a
|
|
25
|
+
* single JSON object on stdout matching this shape. See RESEARCH.md for
|
|
26
|
+
* the live verification details.
|
|
27
|
+
*/
|
|
28
|
+
const ClaudeResponseSchema = z.object({
|
|
29
|
+
type: z.literal('result'),
|
|
30
|
+
subtype: z.enum(['success', 'error']),
|
|
31
|
+
is_error: z.boolean(),
|
|
32
|
+
duration_ms: z.number(),
|
|
33
|
+
duration_api_ms: z.number(),
|
|
34
|
+
num_turns: z.number(),
|
|
35
|
+
result: z.string(),
|
|
36
|
+
session_id: z.string(),
|
|
37
|
+
total_cost_usd: z.number(),
|
|
38
|
+
usage: z.object({
|
|
39
|
+
input_tokens: z.number(),
|
|
40
|
+
cache_creation_input_tokens: z.number(),
|
|
41
|
+
cache_read_input_tokens: z.number(),
|
|
42
|
+
output_tokens: z.number(),
|
|
43
|
+
}),
|
|
44
|
+
modelUsage: z.record(z.object({
|
|
45
|
+
inputTokens: z.number(),
|
|
46
|
+
outputTokens: z.number(),
|
|
47
|
+
cacheReadInputTokens: z.number(),
|
|
48
|
+
cacheCreationInputTokens: z.number(),
|
|
49
|
+
costUSD: z.number(),
|
|
50
|
+
})),
|
|
51
|
+
});
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
// PATH detection utility
|
|
54
|
+
// ---------------------------------------------------------------------------
|
|
55
|
+
/**
|
|
56
|
+
* Check whether a command is available on the system PATH.
|
|
57
|
+
*
|
|
58
|
+
* Splits `process.env.PATH` by the platform delimiter and checks each
|
|
59
|
+
* directory for a file matching the command name. On Windows, also checks
|
|
60
|
+
* each extension from `process.env.PATHEXT` (e.g., `.exe`, `.cmd`, `.bat`).
|
|
61
|
+
*
|
|
62
|
+
* Uses `fs.stat` (not `fs.access` with execute bit) for cross-platform
|
|
63
|
+
* compatibility -- Windows does not have Unix execute permissions.
|
|
64
|
+
*
|
|
65
|
+
* @param command - The bare command name to look for (e.g., "claude")
|
|
66
|
+
* @returns `true` if the command exists as a file in any PATH directory
|
|
67
|
+
*
|
|
68
|
+
* @example
|
|
69
|
+
* ```typescript
|
|
70
|
+
* if (await isCommandOnPath('claude')) {
|
|
71
|
+
* console.log('Claude CLI is available');
|
|
72
|
+
* }
|
|
73
|
+
* ```
|
|
74
|
+
*/
|
|
75
|
+
export async function isCommandOnPath(command) {
|
|
76
|
+
const envPath = process.env.PATH ?? '';
|
|
77
|
+
const pathDirs = envPath
|
|
78
|
+
.replace(/["]+/g, '')
|
|
79
|
+
.split(path.delimiter)
|
|
80
|
+
.filter(Boolean);
|
|
81
|
+
// On Windows, PATHEXT lists executable extensions (e.g., ".EXE;.CMD;.BAT").
|
|
82
|
+
// On other platforms, PATHEXT is unset; check the bare command name only.
|
|
83
|
+
const envExt = process.env.PATHEXT ?? '';
|
|
84
|
+
const extensions = envExt ? envExt.split(';') : [''];
|
|
85
|
+
for (const dir of pathDirs) {
|
|
86
|
+
for (const ext of extensions) {
|
|
87
|
+
try {
|
|
88
|
+
const candidate = path.join(dir, command + ext);
|
|
89
|
+
const stat = await fs.stat(candidate);
|
|
90
|
+
if (stat.isFile()) {
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Not found in this dir/ext combination, continue
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
// ---------------------------------------------------------------------------
|
|
102
|
+
// Claude backend
|
|
103
|
+
// ---------------------------------------------------------------------------
|
|
104
|
+
/**
|
|
105
|
+
* Claude Code CLI backend adapter.
|
|
106
|
+
*
|
|
107
|
+
* Implements the {@link AIBackend} interface for the `claude` CLI.
|
|
108
|
+
* This is the primary (and currently only fully implemented) backend.
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* ```typescript
|
|
112
|
+
* const backend = new ClaudeBackend();
|
|
113
|
+
* if (await backend.isAvailable()) {
|
|
114
|
+
* const args = backend.buildArgs({ prompt: 'Summarize this file' });
|
|
115
|
+
* const result = await runSubprocess('claude', args, {
|
|
116
|
+
* timeoutMs: 120_000,
|
|
117
|
+
* input: 'Summarize this file',
|
|
118
|
+
* });
|
|
119
|
+
* const response = backend.parseResponse(result.stdout, result.durationMs, result.exitCode);
|
|
120
|
+
* }
|
|
121
|
+
* ```
|
|
122
|
+
*/
|
|
123
|
+
export class ClaudeBackend {
|
|
124
|
+
name = 'claude';
|
|
125
|
+
cliCommand = 'claude';
|
|
126
|
+
/**
|
|
127
|
+
* Check if the `claude` CLI is available on PATH.
|
|
128
|
+
*/
|
|
129
|
+
async isAvailable() {
|
|
130
|
+
return isCommandOnPath(this.cliCommand);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Build CLI arguments for a Claude invocation.
|
|
134
|
+
*
|
|
135
|
+
* Returns the argument array for `claude -p --output-format json`. The
|
|
136
|
+
* prompt itself is NOT included -- it goes to stdin via the subprocess
|
|
137
|
+
* wrapper.
|
|
138
|
+
*
|
|
139
|
+
* @param options - Call options (model, systemPrompt, maxTurns)
|
|
140
|
+
* @returns Argument array suitable for {@link runSubprocess}
|
|
141
|
+
*/
|
|
142
|
+
buildArgs(options) {
|
|
143
|
+
const args = [
|
|
144
|
+
'-p', // Non-interactive print mode
|
|
145
|
+
'--output-format', 'json', // Structured JSON output
|
|
146
|
+
'--no-session-persistence', // Don't save session to disk
|
|
147
|
+
'--permission-mode', 'bypassPermissions', // Non-interactive: skip permission prompts (PITFALLS.md §8)
|
|
148
|
+
];
|
|
149
|
+
if (options.model) {
|
|
150
|
+
args.push('--model', options.model);
|
|
151
|
+
}
|
|
152
|
+
if (options.systemPrompt) {
|
|
153
|
+
args.push('--system-prompt', options.systemPrompt);
|
|
154
|
+
}
|
|
155
|
+
if (options.maxTurns !== undefined) {
|
|
156
|
+
args.push('--max-turns', String(options.maxTurns));
|
|
157
|
+
}
|
|
158
|
+
return args;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parse Claude CLI JSON output into a normalized {@link AIResponse}.
|
|
162
|
+
*
|
|
163
|
+
* Handles non-JSON prefix text by finding the first `{` character
|
|
164
|
+
* (defensive parsing per RESEARCH.md Pitfall 4). Validates the response
|
|
165
|
+
* against the Zod schema and extracts the model name from `modelUsage`.
|
|
166
|
+
*
|
|
167
|
+
* @param stdout - Raw stdout from the Claude CLI process
|
|
168
|
+
* @param durationMs - Wall-clock duration of the subprocess
|
|
169
|
+
* @param exitCode - Process exit code
|
|
170
|
+
* @returns Normalized AI response
|
|
171
|
+
* @throws {AIServiceError} With code `PARSE_ERROR` if JSON is missing or schema validation fails
|
|
172
|
+
*/
|
|
173
|
+
parseResponse(stdout, durationMs, exitCode) {
|
|
174
|
+
// Find JSON object in stdout (handle any prefix text like upgrade notices)
|
|
175
|
+
const jsonStart = stdout.indexOf('{');
|
|
176
|
+
if (jsonStart === -1) {
|
|
177
|
+
throw new AIServiceError('PARSE_ERROR', `No JSON object found in Claude CLI output. Raw output (first 200 chars): ${stdout.slice(0, 200)}`);
|
|
178
|
+
}
|
|
179
|
+
let parsed;
|
|
180
|
+
try {
|
|
181
|
+
parsed = ClaudeResponseSchema.parse(JSON.parse(stdout.slice(jsonStart)));
|
|
182
|
+
}
|
|
183
|
+
catch (error) {
|
|
184
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
185
|
+
throw new AIServiceError('PARSE_ERROR', `Failed to parse Claude CLI JSON response: ${message}`);
|
|
186
|
+
}
|
|
187
|
+
// Extract model name from modelUsage keys (first key is the model used)
|
|
188
|
+
const modelName = Object.keys(parsed.modelUsage)[0] ?? 'unknown';
|
|
189
|
+
return {
|
|
190
|
+
text: parsed.result,
|
|
191
|
+
model: modelName,
|
|
192
|
+
inputTokens: parsed.usage.input_tokens,
|
|
193
|
+
outputTokens: parsed.usage.output_tokens,
|
|
194
|
+
cacheReadTokens: parsed.usage.cache_read_input_tokens,
|
|
195
|
+
cacheCreationTokens: parsed.usage.cache_creation_input_tokens,
|
|
196
|
+
costUsd: parsed.total_cost_usd,
|
|
197
|
+
durationMs,
|
|
198
|
+
exitCode,
|
|
199
|
+
raw: parsed,
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Get user-facing install instructions for the Claude CLI.
|
|
204
|
+
*/
|
|
205
|
+
getInstallInstructions() {
|
|
206
|
+
return [
|
|
207
|
+
'Claude Code (recommended):',
|
|
208
|
+
' npm install -g @anthropic-ai/claude-code',
|
|
209
|
+
' https://code.claude.com',
|
|
210
|
+
].join('\n');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=claude.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude.js","sourceRoot":"","sources":["../../../src/ai/backends/claude.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini CLI backend stub.
|
|
3
|
+
*
|
|
4
|
+
* Implements the {@link AIBackend} interface for the Gemini CLI (`gemini`).
|
|
5
|
+
* This is a stub that demonstrates the extension pattern -- `parseResponse`
|
|
6
|
+
* throws "not implemented". Full implementation deferred to a future phase
|
|
7
|
+
* once the Gemini CLI JSON output is stable (see RESEARCH.md Open Question 2).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { AIBackend, AICallOptions, AIResponse } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* Gemini CLI backend stub.
|
|
14
|
+
*
|
|
15
|
+
* Detects CLI availability and builds argument arrays, but throws when
|
|
16
|
+
* `parseResponse` is called since the Gemini adapter is not yet implemented.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const backend = new GeminiBackend();
|
|
21
|
+
* console.log(await backend.isAvailable()); // true if `gemini` is on PATH
|
|
22
|
+
* backend.parseResponse('{}', 0, 0); // throws AIServiceError
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class GeminiBackend implements AIBackend {
|
|
26
|
+
readonly name = "gemini";
|
|
27
|
+
readonly cliCommand = "gemini";
|
|
28
|
+
/**
|
|
29
|
+
* Check if the `gemini` CLI is available on PATH.
|
|
30
|
+
*/
|
|
31
|
+
isAvailable(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Build CLI arguments for a Gemini invocation.
|
|
34
|
+
*
|
|
35
|
+
* Based on documented Gemini CLI flags from RESEARCH.md.
|
|
36
|
+
* The prompt goes to stdin via the subprocess wrapper.
|
|
37
|
+
*
|
|
38
|
+
* @param _options - Call options (unused in stub)
|
|
39
|
+
* @returns Argument array for the Gemini CLI
|
|
40
|
+
*/
|
|
41
|
+
buildArgs(_options: AICallOptions): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Parse Gemini CLI output into a normalized {@link AIResponse}.
|
|
44
|
+
*
|
|
45
|
+
* @throws {AIServiceError} Always -- Gemini backend is not yet implemented
|
|
46
|
+
*/
|
|
47
|
+
parseResponse(_stdout: string, _durationMs: number, _exitCode: number): AIResponse;
|
|
48
|
+
/**
|
|
49
|
+
* Get user-facing install instructions for the Gemini CLI.
|
|
50
|
+
*/
|
|
51
|
+
getInstallInstructions(): string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=gemini.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.d.ts","sourceRoot":"","sources":["../../../src/ai/backends/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIxE;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,YAAW,SAAS;IAC7C,QAAQ,CAAC,IAAI,YAAY;IACzB,QAAQ,CAAC,UAAU,YAAY;IAE/B;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE;IAI5C;;;;OAIG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU;IAOlF;;OAEG;IACH,sBAAsB,IAAI,MAAM;CAOjC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Gemini CLI backend stub.
|
|
3
|
+
*
|
|
4
|
+
* Implements the {@link AIBackend} interface for the Gemini CLI (`gemini`).
|
|
5
|
+
* This is a stub that demonstrates the extension pattern -- `parseResponse`
|
|
6
|
+
* throws "not implemented". Full implementation deferred to a future phase
|
|
7
|
+
* once the Gemini CLI JSON output is stable (see RESEARCH.md Open Question 2).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { AIServiceError } from '../types.js';
|
|
12
|
+
import { isCommandOnPath } from './claude.js';
|
|
13
|
+
/**
|
|
14
|
+
* Gemini CLI backend stub.
|
|
15
|
+
*
|
|
16
|
+
* Detects CLI availability and builds argument arrays, but throws when
|
|
17
|
+
* `parseResponse` is called since the Gemini adapter is not yet implemented.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const backend = new GeminiBackend();
|
|
22
|
+
* console.log(await backend.isAvailable()); // true if `gemini` is on PATH
|
|
23
|
+
* backend.parseResponse('{}', 0, 0); // throws AIServiceError
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class GeminiBackend {
|
|
27
|
+
name = 'gemini';
|
|
28
|
+
cliCommand = 'gemini';
|
|
29
|
+
/**
|
|
30
|
+
* Check if the `gemini` CLI is available on PATH.
|
|
31
|
+
*/
|
|
32
|
+
async isAvailable() {
|
|
33
|
+
return isCommandOnPath(this.cliCommand);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build CLI arguments for a Gemini invocation.
|
|
37
|
+
*
|
|
38
|
+
* Based on documented Gemini CLI flags from RESEARCH.md.
|
|
39
|
+
* The prompt goes to stdin via the subprocess wrapper.
|
|
40
|
+
*
|
|
41
|
+
* @param _options - Call options (unused in stub)
|
|
42
|
+
* @returns Argument array for the Gemini CLI
|
|
43
|
+
*/
|
|
44
|
+
buildArgs(_options) {
|
|
45
|
+
return ['-p', '--output-format', 'json'];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse Gemini CLI output into a normalized {@link AIResponse}.
|
|
49
|
+
*
|
|
50
|
+
* @throws {AIServiceError} Always -- Gemini backend is not yet implemented
|
|
51
|
+
*/
|
|
52
|
+
parseResponse(_stdout, _durationMs, _exitCode) {
|
|
53
|
+
throw new AIServiceError('SUBPROCESS_ERROR', 'Gemini backend is not yet implemented. Use Claude backend.');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get user-facing install instructions for the Gemini CLI.
|
|
57
|
+
*/
|
|
58
|
+
getInstallInstructions() {
|
|
59
|
+
return [
|
|
60
|
+
'Gemini CLI (experimental):',
|
|
61
|
+
' npm install -g @anthropic-ai/gemini-cli',
|
|
62
|
+
' https://github.com/google-gemini/gemini-cli',
|
|
63
|
+
].join('\n');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=gemini.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gemini.js","sourceRoot":"","sources":["../../../src/ai/backends/gemini.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,aAAa;IACf,IAAI,GAAG,QAAQ,CAAC;IAChB,UAAU,GAAG,QAAQ,CAAC;IAE/B;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAuB;QAC/B,OAAO,CAAC,IAAI,EAAE,iBAAiB,EAAE,MAAM,CAAC,CAAC;IAC3C,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,OAAe,EAAE,WAAmB,EAAE,SAAiB;QACnE,MAAM,IAAI,cAAc,CACtB,kBAAkB,EAClB,4DAA4D,CAC7D,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,OAAO;YACL,4BAA4B;YAC5B,2CAA2C;YAC3C,+CAA+C;SAChD,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode CLI backend stub.
|
|
3
|
+
*
|
|
4
|
+
* Implements the {@link AIBackend} interface for the OpenCode CLI (`opencode`).
|
|
5
|
+
* This is a stub that demonstrates the extension pattern -- `parseResponse`
|
|
6
|
+
* throws "not implemented". Full implementation deferred to a future phase
|
|
7
|
+
* once the OpenCode JSONL output parsing is built (see RESEARCH.md Open Question 3).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import type { AIBackend, AICallOptions, AIResponse } from '../types.js';
|
|
12
|
+
/**
|
|
13
|
+
* OpenCode CLI backend stub.
|
|
14
|
+
*
|
|
15
|
+
* Detects CLI availability and builds argument arrays, but throws when
|
|
16
|
+
* `parseResponse` is called since the OpenCode adapter is not yet implemented.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```typescript
|
|
20
|
+
* const backend = new OpenCodeBackend();
|
|
21
|
+
* console.log(await backend.isAvailable()); // true if `opencode` is on PATH
|
|
22
|
+
* backend.parseResponse('{}', 0, 0); // throws AIServiceError
|
|
23
|
+
* ```
|
|
24
|
+
*/
|
|
25
|
+
export declare class OpenCodeBackend implements AIBackend {
|
|
26
|
+
readonly name = "opencode";
|
|
27
|
+
readonly cliCommand = "opencode";
|
|
28
|
+
/**
|
|
29
|
+
* Check if the `opencode` CLI is available on PATH.
|
|
30
|
+
*/
|
|
31
|
+
isAvailable(): Promise<boolean>;
|
|
32
|
+
/**
|
|
33
|
+
* Build CLI arguments for an OpenCode invocation.
|
|
34
|
+
*
|
|
35
|
+
* Based on documented OpenCode CLI flags from RESEARCH.md.
|
|
36
|
+
* The prompt goes to stdin via the subprocess wrapper.
|
|
37
|
+
*
|
|
38
|
+
* @param _options - Call options (unused in stub)
|
|
39
|
+
* @returns Argument array for the OpenCode CLI
|
|
40
|
+
*/
|
|
41
|
+
buildArgs(_options: AICallOptions): string[];
|
|
42
|
+
/**
|
|
43
|
+
* Parse OpenCode CLI output into a normalized {@link AIResponse}.
|
|
44
|
+
*
|
|
45
|
+
* @throws {AIServiceError} Always -- OpenCode backend is not yet implemented
|
|
46
|
+
*/
|
|
47
|
+
parseResponse(_stdout: string, _durationMs: number, _exitCode: number): AIResponse;
|
|
48
|
+
/**
|
|
49
|
+
* Get user-facing install instructions for the OpenCode CLI.
|
|
50
|
+
*/
|
|
51
|
+
getInstallInstructions(): string;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=opencode.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.d.ts","sourceRoot":"","sources":["../../../src/ai/backends/opencode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,SAAS,EAAE,aAAa,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAIxE;;;;;;;;;;;;GAYG;AACH,qBAAa,eAAgB,YAAW,SAAS;IAC/C,QAAQ,CAAC,IAAI,cAAc;IAC3B,QAAQ,CAAC,UAAU,cAAc;IAEjC;;OAEG;IACG,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAIrC;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAQ,EAAE,aAAa,GAAG,MAAM,EAAE;IAI5C;;;;OAIG;IACH,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,UAAU;IAOlF;;OAEG;IACH,sBAAsB,IAAI,MAAM;CAOjC"}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCode CLI backend stub.
|
|
3
|
+
*
|
|
4
|
+
* Implements the {@link AIBackend} interface for the OpenCode CLI (`opencode`).
|
|
5
|
+
* This is a stub that demonstrates the extension pattern -- `parseResponse`
|
|
6
|
+
* throws "not implemented". Full implementation deferred to a future phase
|
|
7
|
+
* once the OpenCode JSONL output parsing is built (see RESEARCH.md Open Question 3).
|
|
8
|
+
*
|
|
9
|
+
* @module
|
|
10
|
+
*/
|
|
11
|
+
import { AIServiceError } from '../types.js';
|
|
12
|
+
import { isCommandOnPath } from './claude.js';
|
|
13
|
+
/**
|
|
14
|
+
* OpenCode CLI backend stub.
|
|
15
|
+
*
|
|
16
|
+
* Detects CLI availability and builds argument arrays, but throws when
|
|
17
|
+
* `parseResponse` is called since the OpenCode adapter is not yet implemented.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const backend = new OpenCodeBackend();
|
|
22
|
+
* console.log(await backend.isAvailable()); // true if `opencode` is on PATH
|
|
23
|
+
* backend.parseResponse('{}', 0, 0); // throws AIServiceError
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export class OpenCodeBackend {
|
|
27
|
+
name = 'opencode';
|
|
28
|
+
cliCommand = 'opencode';
|
|
29
|
+
/**
|
|
30
|
+
* Check if the `opencode` CLI is available on PATH.
|
|
31
|
+
*/
|
|
32
|
+
async isAvailable() {
|
|
33
|
+
return isCommandOnPath(this.cliCommand);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Build CLI arguments for an OpenCode invocation.
|
|
37
|
+
*
|
|
38
|
+
* Based on documented OpenCode CLI flags from RESEARCH.md.
|
|
39
|
+
* The prompt goes to stdin via the subprocess wrapper.
|
|
40
|
+
*
|
|
41
|
+
* @param _options - Call options (unused in stub)
|
|
42
|
+
* @returns Argument array for the OpenCode CLI
|
|
43
|
+
*/
|
|
44
|
+
buildArgs(_options) {
|
|
45
|
+
return ['run', '--format', 'json'];
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse OpenCode CLI output into a normalized {@link AIResponse}.
|
|
49
|
+
*
|
|
50
|
+
* @throws {AIServiceError} Always -- OpenCode backend is not yet implemented
|
|
51
|
+
*/
|
|
52
|
+
parseResponse(_stdout, _durationMs, _exitCode) {
|
|
53
|
+
throw new AIServiceError('SUBPROCESS_ERROR', 'OpenCode backend is not yet implemented. Use Claude backend.');
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Get user-facing install instructions for the OpenCode CLI.
|
|
57
|
+
*/
|
|
58
|
+
getInstallInstructions() {
|
|
59
|
+
return [
|
|
60
|
+
'OpenCode (experimental):',
|
|
61
|
+
' curl -fsSL https://opencode.ai/install | bash',
|
|
62
|
+
' https://opencode.ai',
|
|
63
|
+
].join('\n');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
//# sourceMappingURL=opencode.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"opencode.js","sourceRoot":"","sources":["../../../src/ai/backends/opencode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAE9C;;;;;;;;;;;;GAYG;AACH,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,UAAU,CAAC;IAClB,UAAU,GAAG,UAAU,CAAC;IAEjC;;OAEG;IACH,KAAK,CAAC,WAAW;QACf,OAAO,eAAe,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED;;;;;;;;OAQG;IACH,SAAS,CAAC,QAAuB;QAC/B,OAAO,CAAC,KAAK,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED;;;;OAIG;IACH,aAAa,CAAC,OAAe,EAAE,WAAmB,EAAE,SAAiB;QACnE,MAAM,IAAI,cAAc,CACtB,kBAAkB,EAClB,8DAA8D,CAC/D,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,sBAAsB;QACpB,OAAO;YACL,0BAA0B;YAC1B,iDAAiD;YACjD,uBAAuB;SACxB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACf,CAAC;CACF"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API for the AI service layer.
|
|
3
|
+
*
|
|
4
|
+
* This barrel export is the ONLY import point for the AI service layer.
|
|
5
|
+
* No other module should reach into `src/ai/backends/` or `src/ai/telemetry/`
|
|
6
|
+
* directly.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import {
|
|
13
|
+
* AIService,
|
|
14
|
+
* createBackendRegistry,
|
|
15
|
+
* resolveBackend,
|
|
16
|
+
* } from './ai/index.js';
|
|
17
|
+
*
|
|
18
|
+
* const registry = createBackendRegistry();
|
|
19
|
+
* const backend = await resolveBackend(registry, 'auto');
|
|
20
|
+
* const service = new AIService(backend, {
|
|
21
|
+
* timeoutMs: 120_000,
|
|
22
|
+
* maxRetries: 3,
|
|
23
|
+
* telemetry: { keepRuns: 10 },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* const response = await service.call({ prompt: 'Hello' });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export type { AIBackend, AIResponse, AICallOptions, SubprocessResult, RetryOptions, TelemetryEntry, RunLog, FileRead, CostSource, } from './types.js';
|
|
30
|
+
export { AIServiceError } from './types.js';
|
|
31
|
+
export { AIService } from './service.js';
|
|
32
|
+
export type { AIServiceOptions } from './service.js';
|
|
33
|
+
export { BackendRegistry, createBackendRegistry, resolveBackend, detectBackend, getInstallInstructions, } from './registry.js';
|
|
34
|
+
export { withRetry, DEFAULT_RETRY_OPTIONS } from './retry.js';
|
|
35
|
+
export { runSubprocess } from './subprocess.js';
|
|
36
|
+
export { isCommandOnPath } from './backends/claude.js';
|
|
37
|
+
export { DEFAULT_MODEL_PRICING, estimateCost, lookupPricing, formatCost, formatTokens } from './pricing.js';
|
|
38
|
+
export type { ModelPricing, CostEstimate } from './pricing.js';
|
|
39
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AAMH,YAAY,EACV,SAAS,EACT,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,MAAM,EACN,QAAQ,EACR,UAAU,GACX,MAAM,YAAY,CAAC;AAEpB,OAAO,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAM5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,YAAY,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAMrD,OAAO,EACL,eAAe,EACf,qBAAqB,EACrB,cAAc,EACd,aAAa,EACb,sBAAsB,GACvB,MAAM,eAAe,CAAC;AAMvB,OAAO,EAAE,SAAS,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAM9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAMhD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAMvD,OAAO,EAAE,qBAAqB,EAAE,YAAY,EAAE,aAAa,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC5G,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/ai/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public API for the AI service layer.
|
|
3
|
+
*
|
|
4
|
+
* This barrel export is the ONLY import point for the AI service layer.
|
|
5
|
+
* No other module should reach into `src/ai/backends/` or `src/ai/telemetry/`
|
|
6
|
+
* directly.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```typescript
|
|
12
|
+
* import {
|
|
13
|
+
* AIService,
|
|
14
|
+
* createBackendRegistry,
|
|
15
|
+
* resolveBackend,
|
|
16
|
+
* } from './ai/index.js';
|
|
17
|
+
*
|
|
18
|
+
* const registry = createBackendRegistry();
|
|
19
|
+
* const backend = await resolveBackend(registry, 'auto');
|
|
20
|
+
* const service = new AIService(backend, {
|
|
21
|
+
* timeoutMs: 120_000,
|
|
22
|
+
* maxRetries: 3,
|
|
23
|
+
* telemetry: { keepRuns: 10 },
|
|
24
|
+
* });
|
|
25
|
+
*
|
|
26
|
+
* const response = await service.call({ prompt: 'Hello' });
|
|
27
|
+
* ```
|
|
28
|
+
*/
|
|
29
|
+
export { AIServiceError } from './types.js';
|
|
30
|
+
// ---------------------------------------------------------------------------
|
|
31
|
+
// Service orchestrator
|
|
32
|
+
// ---------------------------------------------------------------------------
|
|
33
|
+
export { AIService } from './service.js';
|
|
34
|
+
// ---------------------------------------------------------------------------
|
|
35
|
+
// Backend registry
|
|
36
|
+
// ---------------------------------------------------------------------------
|
|
37
|
+
export { BackendRegistry, createBackendRegistry, resolveBackend, detectBackend, getInstallInstructions, } from './registry.js';
|
|
38
|
+
// ---------------------------------------------------------------------------
|
|
39
|
+
// Retry utility
|
|
40
|
+
// ---------------------------------------------------------------------------
|
|
41
|
+
export { withRetry, DEFAULT_RETRY_OPTIONS } from './retry.js';
|
|
42
|
+
// ---------------------------------------------------------------------------
|
|
43
|
+
// Subprocess wrapper
|
|
44
|
+
// ---------------------------------------------------------------------------
|
|
45
|
+
export { runSubprocess } from './subprocess.js';
|
|
46
|
+
// ---------------------------------------------------------------------------
|
|
47
|
+
// Backend utilities
|
|
48
|
+
// ---------------------------------------------------------------------------
|
|
49
|
+
export { isCommandOnPath } from './backends/claude.js';
|
|
50
|
+
// ---------------------------------------------------------------------------
|
|
51
|
+
// Pricing
|
|
52
|
+
// ---------------------------------------------------------------------------
|
|
53
|
+
export { DEFAULT_MODEL_PRICING, estimateCost, lookupPricing, formatCost, formatTokens } from './pricing.js';
|
|
54
|
+
//# sourceMappingURL=index.js.map
|