rackmind-cli 0.1.4 → 0.1.6
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 +8 -8
- package/dist/ai/models.d.ts +40 -0
- package/dist/ai/models.d.ts.map +1 -0
- package/dist/ai/models.js +90 -0
- package/dist/ai/models.js.map +1 -0
- package/dist/ai/providers/anthropic-provider.d.ts +18 -0
- package/dist/ai/providers/anthropic-provider.d.ts.map +1 -0
- package/dist/ai/providers/anthropic-provider.js +167 -0
- package/dist/ai/providers/anthropic-provider.js.map +1 -0
- package/dist/ai/providers/base.d.ts +67 -0
- package/dist/ai/providers/base.d.ts.map +1 -0
- package/dist/ai/providers/base.js +9 -0
- package/dist/ai/providers/base.js.map +1 -0
- package/dist/ai/providers/claude-code-bridge.d.ts +44 -0
- package/dist/ai/providers/claude-code-bridge.d.ts.map +1 -0
- package/dist/ai/providers/claude-code-bridge.js +371 -0
- package/dist/ai/providers/claude-code-bridge.js.map +1 -0
- package/dist/ai/providers/claude-code-provider.d.ts +24 -0
- package/dist/ai/providers/claude-code-provider.d.ts.map +1 -0
- package/dist/ai/providers/claude-code-provider.js +245 -0
- package/dist/ai/providers/claude-code-provider.js.map +1 -0
- package/dist/ai/providers/claude-code-runner.d.ts +51 -0
- package/dist/ai/providers/claude-code-runner.d.ts.map +1 -0
- package/dist/ai/providers/claude-code-runner.js +325 -0
- package/dist/ai/providers/claude-code-runner.js.map +1 -0
- package/dist/ai/providers/index.d.ts +8 -0
- package/dist/ai/providers/index.d.ts.map +1 -0
- package/dist/ai/providers/index.js +28 -0
- package/dist/ai/providers/index.js.map +1 -0
- package/dist/interactive/components/ToolOutput.d.ts +1 -1
- package/dist/interactive/components/ToolOutput.d.ts.map +1 -1
- package/dist/interactive/useRackMind.d.ts +1 -1
- package/dist/interactive/useRackMind.d.ts.map +1 -1
- package/dist/interactive/useRackMind.js +13 -5
- package/dist/interactive/useRackMind.js.map +1 -1
- package/dist/oneshot/run.d.ts.map +1 -1
- package/dist/oneshot/run.js +15 -6
- package/dist/oneshot/run.js.map +1 -1
- package/dist/server/client.d.ts +33 -2
- package/dist/server/client.d.ts.map +1 -1
- package/dist/server/client.js +50 -0
- package/dist/server/client.js.map +1 -1
- package/dist/server/proxmox.d.ts +72 -0
- package/dist/server/proxmox.d.ts.map +1 -1
- package/dist/server/proxmox.js +100 -0
- package/dist/server/proxmox.js.map +1 -1
- package/dist/utils/prompt.d.ts.map +1 -1
- package/dist/utils/prompt.js +48 -48
- package/dist/utils/prompt.js.map +1 -1
- package/package.json +25 -1
package/README.md
CHANGED
|
@@ -182,14 +182,14 @@ rackmind logout
|
|
|
182
182
|
|
|
183
183
|
### Free vs Pro
|
|
184
184
|
|
|
185
|
-
| Feature | Free
|
|
186
|
-
| -------------------------- |
|
|
187
|
-
| Server connections | 1
|
|
188
|
-
| Managed AI interactions/mo | 25
|
|
189
|
-
| Bring Your Own Key (BYOK) | --
|
|
190
|
-
| Solution memory | --
|
|
191
|
-
| Historical metrics | 1 hour
|
|
192
|
-
| Terminal AI | --
|
|
185
|
+
| Feature | Free | Pro ($15/mo) |
|
|
186
|
+
| -------------------------- | ------ | ------------ |
|
|
187
|
+
| Server connections | 1 | Unlimited |
|
|
188
|
+
| Managed AI interactions/mo | 25 | 200 |
|
|
189
|
+
| Bring Your Own Key (BYOK) | -- | Unlimited |
|
|
190
|
+
| Solution memory | -- | Included |
|
|
191
|
+
| Historical metrics | 1 hour | Unlimited |
|
|
192
|
+
| Terminal AI | -- | Included |
|
|
193
193
|
|
|
194
194
|
**Free tier** -- great for trying RackMind on a single server with basic AI assistance.
|
|
195
195
|
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export type AIProviderKind = 'anthropic' | 'claude-code';
|
|
2
|
+
export interface ModelOption {
|
|
3
|
+
/** Model id used in config and passed to getAIProvider(). */
|
|
4
|
+
id: string;
|
|
5
|
+
/** Human-readable display name. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** Provider family. */
|
|
8
|
+
provider: AIProviderKind;
|
|
9
|
+
/** Whether this is the default model for new conversations. */
|
|
10
|
+
isDefault?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const DEFAULT_ANTHROPIC_MODEL_ID = "claude-sonnet-4-5";
|
|
13
|
+
/**
|
|
14
|
+
* Feature flag for the private `claude-code` provider. Invisible to every
|
|
15
|
+
* user-facing surface unless this returns true. Do NOT document this env
|
|
16
|
+
* var or mention it in error messages.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isClaudeCodeEnabled(): boolean;
|
|
19
|
+
/** Look up a model by id. Returns undefined if unknown. */
|
|
20
|
+
export declare function getModelById(modelId: string): ModelOption | undefined;
|
|
21
|
+
/**
|
|
22
|
+
* Models that should be shown in user-facing surfaces right now. Filters
|
|
23
|
+
* out gated providers whose feature flag is off.
|
|
24
|
+
*/
|
|
25
|
+
export declare function getVisibleModels(): ModelOption[];
|
|
26
|
+
/**
|
|
27
|
+
* Get the provider kind for a model id, or undefined if the model is
|
|
28
|
+
* unknown OR gated off in the current environment. Use this instead of
|
|
29
|
+
* reaching into ALL_MODELS directly when you need to decide whether to
|
|
30
|
+
* route a request — it enforces the gate.
|
|
31
|
+
*/
|
|
32
|
+
export declare function getVisibleProviderForModel(modelId: string): AIProviderKind | undefined;
|
|
33
|
+
/**
|
|
34
|
+
* Resolve a preferred model id to one that is actually usable right now.
|
|
35
|
+
* If the preferred id is unknown or points at a gated-off provider, falls
|
|
36
|
+
* back to the default Anthropic model so the user isn't left stranded by
|
|
37
|
+
* a stale config value.
|
|
38
|
+
*/
|
|
39
|
+
export declare function resolveUsableModelId(preferredModelId: string | undefined): string;
|
|
40
|
+
//# sourceMappingURL=models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/ai/models.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,aAAa,CAAC;AAEzD,MAAM,WAAW,WAAW;IACxB,6DAA6D;IAC7D,EAAE,EAAE,MAAM,CAAC;IACX,mCAAmC;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,uBAAuB;IACvB,QAAQ,EAAE,cAAc,CAAC;IACzB,+DAA+D;IAC/D,SAAS,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,eAAO,MAAM,0BAA0B,sBAAsB,CAAC;AAiC9D;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,OAAO,CAE7C;AAED,2DAA2D;AAC3D,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAErE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,WAAW,EAAE,CAMhD;AAED;;;;;GAKG;AACH,wBAAgB,0BAA0B,CAAC,OAAO,EAAE,MAAM,GAAG,cAAc,GAAG,SAAS,CAKtF;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,gBAAgB,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAKjF"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Model registry & visibility gating
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Central catalogue of AI models the CLI knows how to route. Every surface
|
|
5
|
+
// that enumerates models for the user (slash commands, config, help text)
|
|
6
|
+
// MUST filter through getVisibleModels() so gated providers stay invisible
|
|
7
|
+
// to normal users.
|
|
8
|
+
// ---------------------------------------------------------------------------
|
|
9
|
+
export const DEFAULT_ANTHROPIC_MODEL_ID = 'claude-sonnet-4-5';
|
|
10
|
+
/**
|
|
11
|
+
* The full list of models the CLI knows about. Keep tight — every entry
|
|
12
|
+
* here shows up in the user-facing model picker once its provider is
|
|
13
|
+
* visible.
|
|
14
|
+
*/
|
|
15
|
+
const ALL_MODELS = [
|
|
16
|
+
{
|
|
17
|
+
id: 'claude-sonnet-4-5',
|
|
18
|
+
name: 'Claude Sonnet 4.5',
|
|
19
|
+
provider: 'anthropic',
|
|
20
|
+
isDefault: true,
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'claude-haiku-4-5-20251001',
|
|
24
|
+
name: 'Claude Haiku 4.5',
|
|
25
|
+
provider: 'anthropic',
|
|
26
|
+
},
|
|
27
|
+
// Intentionally undocumented entries below. Gated — never surface
|
|
28
|
+
// unless isClaudeCodeEnabled() returns true.
|
|
29
|
+
{
|
|
30
|
+
id: 'claude-code:sonnet',
|
|
31
|
+
name: 'Claude Code (Sonnet)',
|
|
32
|
+
provider: 'claude-code',
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
id: 'claude-code:opus',
|
|
36
|
+
name: 'Claude Code (Opus)',
|
|
37
|
+
provider: 'claude-code',
|
|
38
|
+
},
|
|
39
|
+
];
|
|
40
|
+
/**
|
|
41
|
+
* Feature flag for the private `claude-code` provider. Invisible to every
|
|
42
|
+
* user-facing surface unless this returns true. Do NOT document this env
|
|
43
|
+
* var or mention it in error messages.
|
|
44
|
+
*/
|
|
45
|
+
export function isClaudeCodeEnabled() {
|
|
46
|
+
return process.env.RACKMIND_CLAUDE_CODE === '1';
|
|
47
|
+
}
|
|
48
|
+
/** Look up a model by id. Returns undefined if unknown. */
|
|
49
|
+
export function getModelById(modelId) {
|
|
50
|
+
return ALL_MODELS.find((m) => m.id === modelId);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Models that should be shown in user-facing surfaces right now. Filters
|
|
54
|
+
* out gated providers whose feature flag is off.
|
|
55
|
+
*/
|
|
56
|
+
export function getVisibleModels() {
|
|
57
|
+
const claudeCodeEnabled = isClaudeCodeEnabled();
|
|
58
|
+
return ALL_MODELS.filter((m) => {
|
|
59
|
+
if (m.provider === 'claude-code')
|
|
60
|
+
return claudeCodeEnabled;
|
|
61
|
+
return true;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Get the provider kind for a model id, or undefined if the model is
|
|
66
|
+
* unknown OR gated off in the current environment. Use this instead of
|
|
67
|
+
* reaching into ALL_MODELS directly when you need to decide whether to
|
|
68
|
+
* route a request — it enforces the gate.
|
|
69
|
+
*/
|
|
70
|
+
export function getVisibleProviderForModel(modelId) {
|
|
71
|
+
const model = getModelById(modelId);
|
|
72
|
+
if (!model)
|
|
73
|
+
return undefined;
|
|
74
|
+
if (model.provider === 'claude-code' && !isClaudeCodeEnabled())
|
|
75
|
+
return undefined;
|
|
76
|
+
return model.provider;
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Resolve a preferred model id to one that is actually usable right now.
|
|
80
|
+
* If the preferred id is unknown or points at a gated-off provider, falls
|
|
81
|
+
* back to the default Anthropic model so the user isn't left stranded by
|
|
82
|
+
* a stale config value.
|
|
83
|
+
*/
|
|
84
|
+
export function resolveUsableModelId(preferredModelId) {
|
|
85
|
+
if (preferredModelId && getVisibleProviderForModel(preferredModelId)) {
|
|
86
|
+
return preferredModelId;
|
|
87
|
+
}
|
|
88
|
+
return DEFAULT_ANTHROPIC_MODEL_ID;
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/ai/models.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,qCAAqC;AACrC,8EAA8E;AAC9E,2EAA2E;AAC3E,0EAA0E;AAC1E,2EAA2E;AAC3E,mBAAmB;AACnB,8EAA8E;AAe9E,MAAM,CAAC,MAAM,0BAA0B,GAAG,mBAAmB,CAAC;AAE9D;;;;GAIG;AACH,MAAM,UAAU,GAAkB;IAC9B;QACI,EAAE,EAAE,mBAAmB;QACvB,IAAI,EAAE,mBAAmB;QACzB,QAAQ,EAAE,WAAW;QACrB,SAAS,EAAE,IAAI;KAClB;IACD;QACI,EAAE,EAAE,2BAA2B;QAC/B,IAAI,EAAE,kBAAkB;QACxB,QAAQ,EAAE,WAAW;KACxB;IACD,kEAAkE;IAClE,6CAA6C;IAC7C;QACI,EAAE,EAAE,oBAAoB;QACxB,IAAI,EAAE,sBAAsB;QAC5B,QAAQ,EAAE,aAAa;KAC1B;IACD;QACI,EAAE,EAAE,kBAAkB;QACtB,IAAI,EAAE,oBAAoB;QAC1B,QAAQ,EAAE,aAAa;KAC1B;CACJ,CAAC;AAEF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB;IAC/B,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,GAAG,CAAC;AACpD,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,YAAY,CAAC,OAAe;IACxC,OAAO,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC;AACpD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC5B,MAAM,iBAAiB,GAAG,mBAAmB,EAAE,CAAC;IAChD,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,IAAI,CAAC,CAAC,QAAQ,KAAK,aAAa;YAAE,OAAO,iBAAiB,CAAC;QAC3D,OAAO,IAAI,CAAC;IAChB,CAAC,CAAC,CAAC;AACP,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,0BAA0B,CAAC,OAAe;IACtD,MAAM,KAAK,GAAG,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,SAAS,CAAC;IAC7B,IAAI,KAAK,CAAC,QAAQ,KAAK,aAAa,IAAI,CAAC,mBAAmB,EAAE;QAAE,OAAO,SAAS,CAAC;IACjF,OAAO,KAAK,CAAC,QAAQ,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,oBAAoB,CAAC,gBAAoC;IACrE,IAAI,gBAAgB,IAAI,0BAA0B,CAAC,gBAAgB,CAAC,EAAE,CAAC;QACnE,OAAO,gBAAgB,CAAC;IAC5B,CAAC;IACD,OAAO,0BAA0B,CAAC;AACtC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import type { ServerClient } from '../../server/client.js';
|
|
2
|
+
import type { AIProvider, ChatHistory, MultiTurnCallbacks, ProviderOptions, StreamCallbacks } from './base.js';
|
|
3
|
+
export declare class AnthropicProvider implements AIProvider {
|
|
4
|
+
private readonly anthropic;
|
|
5
|
+
private readonly model;
|
|
6
|
+
private readonly maxTokens;
|
|
7
|
+
constructor(options: ProviderOptions);
|
|
8
|
+
getModel(): string;
|
|
9
|
+
chat(query: string, serverClient: ServerClient, serverAlias: string, callbacks: StreamCallbacks): Promise<void>;
|
|
10
|
+
chatMultiTurn(query: string, history: ChatHistory, serverClient: ServerClient, serverAlias: string, callbacks: MultiTurnCallbacks): Promise<ChatHistory>;
|
|
11
|
+
dispose(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Create a message with retry logic for transient errors.
|
|
14
|
+
* Rate limits and overload errors trigger exponential backoff.
|
|
15
|
+
*/
|
|
16
|
+
private createWithRetry;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=anthropic-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-provider.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/anthropic-provider.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAO3D,OAAO,KAAK,EACR,UAAU,EACV,WAAW,EACX,kBAAkB,EAClB,eAAe,EACf,eAAe,EAClB,MAAM,WAAW,CAAC;AAKnB,qBAAa,iBAAkB,YAAW,UAAU;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAY;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAS;gBAEvB,OAAO,EAAE,eAAe;IAYpC,QAAQ,IAAI,MAAM;IAIZ,IAAI,CACN,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,eAAe,GAC3B,OAAO,CAAC,IAAI,CAAC;IAyDV,aAAa,CACf,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,kBAAkB,GAC9B,OAAO,CAAC,WAAW,CAAC;IAwEjB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B;;;OAGG;IACH,OAAO,CAAC,eAAe;CAgC1B"}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// Anthropic provider — original AIClient logic, now behind AIProvider
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Wraps @anthropic-ai/sdk with the CLI's tool-use loop. This is the default
|
|
5
|
+
// provider — every unknown/missing model id falls back here via
|
|
6
|
+
// providers/index.ts::getAIProvider().
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
9
|
+
import { getToolDefinitions } from '../tools.js';
|
|
10
|
+
import { fetchServerContext, buildSystemPrompt } from '../system-prompt.js';
|
|
11
|
+
import { executeTool } from '../tool-executor.js';
|
|
12
|
+
import { logger } from '../../utils/logger.js';
|
|
13
|
+
import { withRetry, isTransientError, isRateLimitError } from '../../utils/retry.js';
|
|
14
|
+
import { DEFAULT_ANTHROPIC_MODEL_ID } from '../models.js';
|
|
15
|
+
/** Max iterations of the tool use loop — hard guard against runaway chains. */
|
|
16
|
+
const MAX_TOOL_ITERATIONS = 20;
|
|
17
|
+
export class AnthropicProvider {
|
|
18
|
+
anthropic;
|
|
19
|
+
model;
|
|
20
|
+
maxTokens;
|
|
21
|
+
constructor(options) {
|
|
22
|
+
if (!options.apiKey) {
|
|
23
|
+
throw new Error('Anthropic provider requires an API key.');
|
|
24
|
+
}
|
|
25
|
+
this.anthropic = new Anthropic({
|
|
26
|
+
apiKey: options.apiKey,
|
|
27
|
+
timeout: options.timeoutMs ?? 120_000,
|
|
28
|
+
});
|
|
29
|
+
this.model = options.model || DEFAULT_ANTHROPIC_MODEL_ID;
|
|
30
|
+
this.maxTokens = options.maxTokens ?? 4096;
|
|
31
|
+
}
|
|
32
|
+
getModel() {
|
|
33
|
+
return this.model;
|
|
34
|
+
}
|
|
35
|
+
async chat(query, serverClient, serverAlias, callbacks) {
|
|
36
|
+
const context = await fetchServerContext(serverClient);
|
|
37
|
+
const systemPrompt = buildSystemPrompt(context, serverAlias);
|
|
38
|
+
const tools = getToolDefinitions();
|
|
39
|
+
const messages = [{ role: 'user', content: query }];
|
|
40
|
+
for (let iteration = 0; iteration < MAX_TOOL_ITERATIONS; iteration++) {
|
|
41
|
+
logger.debug('AI request iteration', { iteration, messageCount: messages.length });
|
|
42
|
+
const response = await this.createWithRetry(systemPrompt, tools, messages, callbacks);
|
|
43
|
+
const assistantContent = [];
|
|
44
|
+
const toolUseBlocks = [];
|
|
45
|
+
for (const block of response.content) {
|
|
46
|
+
assistantContent.push(block);
|
|
47
|
+
if (block.type === 'text') {
|
|
48
|
+
callbacks.onText(block.text);
|
|
49
|
+
}
|
|
50
|
+
else if (block.type === 'tool_use') {
|
|
51
|
+
toolUseBlocks.push(block);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
messages.push({ role: 'assistant', content: assistantContent });
|
|
55
|
+
if (response.stop_reason === 'end_turn' || toolUseBlocks.length === 0) {
|
|
56
|
+
logger.debug('AI conversation complete', {
|
|
57
|
+
iterations: iteration + 1,
|
|
58
|
+
stopReason: response.stop_reason,
|
|
59
|
+
});
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const toolResults = [];
|
|
63
|
+
for (const toolBlock of toolUseBlocks) {
|
|
64
|
+
const toolInput = toolBlock.input;
|
|
65
|
+
callbacks.onToolStart(toolBlock.name, toolBlock.name);
|
|
66
|
+
const result = await executeTool(toolBlock.name, toolInput, serverClient);
|
|
67
|
+
callbacks.onToolEnd(toolBlock.name, result.label, result.isError);
|
|
68
|
+
toolResults.push({
|
|
69
|
+
type: 'tool_result',
|
|
70
|
+
tool_use_id: toolBlock.id,
|
|
71
|
+
content: result.content,
|
|
72
|
+
is_error: result.isError,
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
messages.push({ role: 'user', content: toolResults });
|
|
76
|
+
}
|
|
77
|
+
callbacks.onError('Reached maximum tool iterations. The AI may be stuck in a loop.');
|
|
78
|
+
}
|
|
79
|
+
async chatMultiTurn(query, history, serverClient, serverAlias, callbacks) {
|
|
80
|
+
const context = await fetchServerContext(serverClient);
|
|
81
|
+
const systemPrompt = buildSystemPrompt(context, serverAlias);
|
|
82
|
+
const tools = getToolDefinitions();
|
|
83
|
+
const messages = [
|
|
84
|
+
...history,
|
|
85
|
+
{ role: 'user', content: query },
|
|
86
|
+
];
|
|
87
|
+
for (let iteration = 0; iteration < MAX_TOOL_ITERATIONS; iteration++) {
|
|
88
|
+
logger.debug('AI multi-turn request iteration', {
|
|
89
|
+
iteration,
|
|
90
|
+
messageCount: messages.length,
|
|
91
|
+
});
|
|
92
|
+
const response = await this.createWithRetry(systemPrompt, tools, messages, callbacks);
|
|
93
|
+
const assistantContent = [];
|
|
94
|
+
const toolUseBlocks = [];
|
|
95
|
+
for (const block of response.content) {
|
|
96
|
+
assistantContent.push(block);
|
|
97
|
+
if (block.type === 'text') {
|
|
98
|
+
callbacks.onText(block.text);
|
|
99
|
+
}
|
|
100
|
+
else if (block.type === 'tool_use') {
|
|
101
|
+
toolUseBlocks.push(block);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
messages.push({ role: 'assistant', content: assistantContent });
|
|
105
|
+
if (response.stop_reason === 'end_turn' || toolUseBlocks.length === 0) {
|
|
106
|
+
logger.debug('AI multi-turn conversation turn complete', {
|
|
107
|
+
iterations: iteration + 1,
|
|
108
|
+
stopReason: response.stop_reason,
|
|
109
|
+
});
|
|
110
|
+
return messages;
|
|
111
|
+
}
|
|
112
|
+
const toolResults = [];
|
|
113
|
+
for (const toolBlock of toolUseBlocks) {
|
|
114
|
+
const toolInput = toolBlock.input;
|
|
115
|
+
callbacks.onToolStart(toolBlock.name, toolBlock.name);
|
|
116
|
+
const result = await executeTool(toolBlock.name, toolInput, serverClient);
|
|
117
|
+
callbacks.onToolEnd(toolBlock.name, result.label, result.isError);
|
|
118
|
+
if (callbacks.onToolResult) {
|
|
119
|
+
callbacks.onToolResult({
|
|
120
|
+
toolName: toolBlock.name,
|
|
121
|
+
label: result.label,
|
|
122
|
+
isError: result.isError,
|
|
123
|
+
content: result.content,
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
toolResults.push({
|
|
127
|
+
type: 'tool_result',
|
|
128
|
+
tool_use_id: toolBlock.id,
|
|
129
|
+
content: result.content,
|
|
130
|
+
is_error: result.isError,
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
messages.push({ role: 'user', content: toolResults });
|
|
134
|
+
}
|
|
135
|
+
callbacks.onError('Reached maximum tool iterations. The AI may be stuck in a loop.');
|
|
136
|
+
return messages;
|
|
137
|
+
}
|
|
138
|
+
async dispose() {
|
|
139
|
+
// Anthropic SDK has no persistent resources to release.
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Create a message with retry logic for transient errors.
|
|
143
|
+
* Rate limits and overload errors trigger exponential backoff.
|
|
144
|
+
*/
|
|
145
|
+
createWithRetry(system, tools, messages, callbacks) {
|
|
146
|
+
return withRetry(() => this.anthropic.messages.create({
|
|
147
|
+
model: this.model,
|
|
148
|
+
max_tokens: this.maxTokens,
|
|
149
|
+
system,
|
|
150
|
+
tools,
|
|
151
|
+
messages,
|
|
152
|
+
}), {
|
|
153
|
+
maxAttempts: 3,
|
|
154
|
+
initialDelayMs: 2000,
|
|
155
|
+
maxDelayMs: 30_000,
|
|
156
|
+
isRetryable: isTransientError,
|
|
157
|
+
onRetry: (attempt, error, delayMs) => {
|
|
158
|
+
const msg = error instanceof Error ? error.message : String(error);
|
|
159
|
+
const isRateLimit = isRateLimitError(error);
|
|
160
|
+
const label = isRateLimit ? 'Rate limited' : 'API error';
|
|
161
|
+
callbacks.onError(`${label}, retrying in ${Math.round(delayMs / 1000)}s (attempt ${attempt + 1}/3)...`);
|
|
162
|
+
logger.warn('API call retry', { attempt, delayMs, error: msg });
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=anthropic-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anthropic-provider.js","sourceRoot":"","sources":["../../../src/ai/providers/anthropic-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type Anthropic from '@anthropic-ai/sdk';
|
|
2
|
+
import type { ServerClient } from '../../server/client.js';
|
|
3
|
+
/** Callbacks the provider invokes while a chat turn is in flight. */
|
|
4
|
+
export interface StreamCallbacks {
|
|
5
|
+
/** Streaming text chunk from the assistant. */
|
|
6
|
+
onText: (text: string) => void;
|
|
7
|
+
/** A tool call is about to run (or has started). */
|
|
8
|
+
onToolStart: (toolName: string, label: string) => void;
|
|
9
|
+
/** A tool call finished (success or error). */
|
|
10
|
+
onToolEnd: (toolName: string, label: string, isError: boolean) => void;
|
|
11
|
+
/** A non-fatal error occurred (rate limit retries, warnings, etc.). */
|
|
12
|
+
onError: (error: string) => void;
|
|
13
|
+
}
|
|
14
|
+
/** A single tool execution observed during a turn (shown in REPL history). */
|
|
15
|
+
export interface ToolExecution {
|
|
16
|
+
toolName: string;
|
|
17
|
+
label: string;
|
|
18
|
+
isError: boolean;
|
|
19
|
+
content: string;
|
|
20
|
+
}
|
|
21
|
+
/** Extended callbacks for multi-turn mode (captures full tool result for UI). */
|
|
22
|
+
export interface MultiTurnCallbacks extends StreamCallbacks {
|
|
23
|
+
onToolResult?: (execution: ToolExecution) => void;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Conversation history shape used by multi-turn mode. We reuse Anthropic's
|
|
27
|
+
* MessageParam for wire compatibility with the anthropic provider and for
|
|
28
|
+
* easy mirroring when the user switches providers mid-conversation.
|
|
29
|
+
*/
|
|
30
|
+
export type ChatHistory = Anthropic.Messages.MessageParam[];
|
|
31
|
+
/**
|
|
32
|
+
* Every provider implements this. `chat` is one-shot (no history);
|
|
33
|
+
* `chatMultiTurn` takes the prior history, appends the new turn, and
|
|
34
|
+
* returns the updated history for the caller to persist.
|
|
35
|
+
*/
|
|
36
|
+
export interface AIProvider {
|
|
37
|
+
/** The model id this provider instance was constructed for. */
|
|
38
|
+
getModel(): string;
|
|
39
|
+
/**
|
|
40
|
+
* Send a single query with no prior history. Streams results via
|
|
41
|
+
* callbacks. Throws on fatal errors.
|
|
42
|
+
*/
|
|
43
|
+
chat(query: string, serverClient: ServerClient, serverAlias: string, callbacks: StreamCallbacks): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Send a new user message given the prior conversation history.
|
|
46
|
+
* Returns the updated history (with the new user turn and the
|
|
47
|
+
* assistant's response appended).
|
|
48
|
+
*/
|
|
49
|
+
chatMultiTurn(query: string, history: ChatHistory, serverClient: ServerClient, serverAlias: string, callbacks: MultiTurnCallbacks): Promise<ChatHistory>;
|
|
50
|
+
/**
|
|
51
|
+
* Release any resources this provider holds (HTTP bridge, child
|
|
52
|
+
* processes, etc.). Safe to call multiple times.
|
|
53
|
+
*/
|
|
54
|
+
dispose(): Promise<void>;
|
|
55
|
+
}
|
|
56
|
+
/** Construction options common to every provider. */
|
|
57
|
+
export interface ProviderOptions {
|
|
58
|
+
/** Anthropic API key (required for the anthropic provider, ignored otherwise). */
|
|
59
|
+
apiKey?: string;
|
|
60
|
+
/** Model id to route with. */
|
|
61
|
+
model: string;
|
|
62
|
+
/** Max tokens per response (anthropic only). */
|
|
63
|
+
maxTokens?: number;
|
|
64
|
+
/** Request timeout (anthropic only), ms. */
|
|
65
|
+
timeoutMs?: number;
|
|
66
|
+
}
|
|
67
|
+
//# sourceMappingURL=base.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/base.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,qEAAqE;AACrE,MAAM,WAAW,eAAe;IAC5B,+CAA+C;IAC/C,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/B,oDAAoD;IACpD,WAAW,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACvD,+CAA+C;IAC/C,SAAS,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;IACvE,uEAAuE;IACvE,OAAO,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;CACpC;AAED,8EAA8E;AAC9E,MAAM,WAAW,aAAa;IAC1B,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,iFAAiF;AACjF,MAAM,WAAW,kBAAmB,SAAQ,eAAe;IACvD,YAAY,CAAC,EAAE,CAAC,SAAS,EAAE,aAAa,KAAK,IAAI,CAAC;CACrD;AAED;;;;GAIG;AACH,MAAM,MAAM,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC;AAE5D;;;;GAIG;AACH,MAAM,WAAW,UAAU;IACvB,+DAA+D;IAC/D,QAAQ,IAAI,MAAM,CAAC;IAEnB;;;OAGG;IACH,IAAI,CACA,KAAK,EAAE,MAAM,EACb,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,eAAe,GAC3B,OAAO,CAAC,IAAI,CAAC,CAAC;IAEjB;;;;OAIG;IACH,aAAa,CACT,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,WAAW,EACpB,YAAY,EAAE,YAAY,EAC1B,WAAW,EAAE,MAAM,EACnB,SAAS,EAAE,kBAAkB,GAC9B,OAAO,CAAC,WAAW,CAAC,CAAC;IAExB;;;OAGG;IACH,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5B;AAED,qDAAqD;AACrD,MAAM,WAAW,eAAe;IAC5B,kFAAkF;IAClF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,gDAAgD;IAChD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// ---------------------------------------------------------------------------
|
|
2
|
+
// AIProvider interface — minimum surface every provider must implement
|
|
3
|
+
// ---------------------------------------------------------------------------
|
|
4
|
+
// Callers (oneshot/run.ts, interactive/useRackMind.ts) depend ONLY on this
|
|
5
|
+
// interface. Concrete providers (anthropic, claude-code) live in sibling
|
|
6
|
+
// files and are wired up by providers/index.ts via getAIProvider(modelId).
|
|
7
|
+
// ---------------------------------------------------------------------------
|
|
8
|
+
export {};
|
|
9
|
+
//# sourceMappingURL=base.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base.js","sourceRoot":"","sources":["../../../src/ai/providers/base.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,uEAAuE;AACvE,8EAA8E;AAC9E,2EAA2E;AAC3E,yEAAyE;AACzE,2EAA2E;AAC3E,8EAA8E"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ClaudeCodeBridge — loopback HTTP tool bridge for the spawned `claude`
|
|
3
|
+
* CLI child. Ported from the desktop app's bridge with one adaptation:
|
|
4
|
+
* the executor here runs the CLI's in-process tools (src/ai/tool-executor.ts)
|
|
5
|
+
* instead of delegating to Electron IPC. The security model (loopback bind,
|
|
6
|
+
* random shared secret, Host header check, body cap, request timeout) is
|
|
7
|
+
* identical to the desktop version.
|
|
8
|
+
*/
|
|
9
|
+
import type Anthropic from '@anthropic-ai/sdk';
|
|
10
|
+
import type { ServerClient } from '../../server/client.js';
|
|
11
|
+
export interface BridgeToolCallback {
|
|
12
|
+
(toolName: string, label: string, isError: boolean, content: string): void;
|
|
13
|
+
}
|
|
14
|
+
export interface BridgeHandle {
|
|
15
|
+
bridgeDir: string;
|
|
16
|
+
port: number;
|
|
17
|
+
secret: string;
|
|
18
|
+
stop(): Promise<void>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Build a concise manifest of RackMind tools for injection into the Claude
|
|
22
|
+
* Code system prompt. Lists every available tool with its description,
|
|
23
|
+
* input schema, and an example invocation so the model knows what to call
|
|
24
|
+
* via `rackmind-bridge`.
|
|
25
|
+
*/
|
|
26
|
+
export declare function buildToolManifest(tools: Anthropic.Messages.Tool[]): string;
|
|
27
|
+
export interface StartBridgeOptions {
|
|
28
|
+
/** Server client the in-process tool executor dispatches to. */
|
|
29
|
+
serverClient: ServerClient;
|
|
30
|
+
/**
|
|
31
|
+
* Optional observer called for every bridge tool invocation — lets the
|
|
32
|
+
* caller forward a display label into the REPL's tool-event stream.
|
|
33
|
+
*/
|
|
34
|
+
onToolCall?: BridgeToolCallback;
|
|
35
|
+
/** Signal that aborts pending/future tool calls (returns `cancelled`). */
|
|
36
|
+
signal?: AbortSignal;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Start the local HTTP bridge and write the `rackmind-bridge` helper
|
|
40
|
+
* script. Returns a handle with the PATH dir and port the child should
|
|
41
|
+
* see in its env.
|
|
42
|
+
*/
|
|
43
|
+
export declare function startClaudeCodeBridge(opts: StartBridgeOptions): Promise<BridgeHandle>;
|
|
44
|
+
//# sourceMappingURL=claude-code-bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-bridge.d.ts","sourceRoot":"","sources":["../../../src/ai/providers/claude-code-bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAOH,OAAO,KAAK,SAAS,MAAM,mBAAmB,CAAC;AAC/C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAc3D,MAAM,WAAW,kBAAkB;IAC/B,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9E;AAED,MAAM,WAAW,YAAY;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB;AAwCD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,QAAQ,CAAC,IAAI,EAAE,GAAG,MAAM,CA+C1E;AA6CD,MAAM,WAAW,kBAAkB;IAC/B,gEAAgE;IAChE,YAAY,EAAE,YAAY,CAAC;IAC3B;;;OAGG;IACH,UAAU,CAAC,EAAE,kBAAkB,CAAC;IAChC,0EAA0E;IAC1E,MAAM,CAAC,EAAE,WAAW,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAsB,qBAAqB,CAAC,IAAI,EAAE,kBAAkB,GAAG,OAAO,CAAC,YAAY,CAAC,CAkP3F"}
|