@agi-cli/sdk 0.1.49 → 0.1.50
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/package.json +6 -5
- package/src/agent/types.ts +1 -1
- package/src/index.ts +10 -77
- package/src/errors.ts +0 -102
- package/src/providers/resolver.ts +0 -84
- package/src/streaming/artifacts.ts +0 -41
- package/src/tools/builtin/bash.ts +0 -73
- package/src/tools/builtin/bash.txt +0 -7
- package/src/tools/builtin/edit.ts +0 -145
- package/src/tools/builtin/edit.txt +0 -7
- package/src/tools/builtin/file-cache.ts +0 -39
- package/src/tools/builtin/finish.ts +0 -11
- package/src/tools/builtin/finish.txt +0 -5
- package/src/tools/builtin/fs/cd.ts +0 -19
- package/src/tools/builtin/fs/cd.txt +0 -5
- package/src/tools/builtin/fs/index.ts +0 -20
- package/src/tools/builtin/fs/ls.ts +0 -57
- package/src/tools/builtin/fs/ls.txt +0 -8
- package/src/tools/builtin/fs/pwd.ts +0 -17
- package/src/tools/builtin/fs/pwd.txt +0 -5
- package/src/tools/builtin/fs/read.ts +0 -49
- package/src/tools/builtin/fs/read.txt +0 -8
- package/src/tools/builtin/fs/tree.ts +0 -67
- package/src/tools/builtin/fs/tree.txt +0 -8
- package/src/tools/builtin/fs/util.ts +0 -95
- package/src/tools/builtin/fs/write.ts +0 -61
- package/src/tools/builtin/fs/write.txt +0 -8
- package/src/tools/builtin/git.commit.txt +0 -6
- package/src/tools/builtin/git.diff.txt +0 -5
- package/src/tools/builtin/git.status.txt +0 -5
- package/src/tools/builtin/git.ts +0 -112
- package/src/tools/builtin/glob.ts +0 -82
- package/src/tools/builtin/glob.txt +0 -8
- package/src/tools/builtin/grep.ts +0 -138
- package/src/tools/builtin/grep.txt +0 -9
- package/src/tools/builtin/ignore.ts +0 -45
- package/src/tools/builtin/patch.ts +0 -273
- package/src/tools/builtin/patch.txt +0 -7
- package/src/tools/builtin/plan.ts +0 -58
- package/src/tools/builtin/plan.txt +0 -6
- package/src/tools/builtin/progress.ts +0 -55
- package/src/tools/builtin/progress.txt +0 -7
- package/src/tools/builtin/ripgrep.ts +0 -71
- package/src/tools/builtin/ripgrep.txt +0 -7
- package/src/tools/builtin/websearch.ts +0 -219
- package/src/tools/builtin/websearch.txt +0 -12
- package/src/tools/loader.ts +0 -390
- package/src/types/index.ts +0 -11
- package/src/types/types.ts +0 -4
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.50",
|
|
4
4
|
"description": "AI agent SDK for building intelligent assistants",
|
|
5
5
|
"author": "ntishxyz",
|
|
6
6
|
"license": "MIT",
|
|
@@ -22,12 +22,12 @@
|
|
|
22
22
|
"types": "./src/index.ts"
|
|
23
23
|
},
|
|
24
24
|
"./tools/builtin/fs": {
|
|
25
|
-
"import": "
|
|
26
|
-
"types": "
|
|
25
|
+
"import": "@agi-cli/core/tools/builtin/fs",
|
|
26
|
+
"types": "@agi-cli/core/tools/builtin/fs"
|
|
27
27
|
},
|
|
28
28
|
"./tools/builtin/git": {
|
|
29
|
-
"import": "
|
|
30
|
-
"types": "
|
|
29
|
+
"import": "@agi-cli/core/tools/builtin/git",
|
|
30
|
+
"types": "@agi-cli/core/tools/builtin/git"
|
|
31
31
|
}
|
|
32
32
|
},
|
|
33
33
|
"files": [
|
|
@@ -43,6 +43,7 @@
|
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"@agi-cli/auth": "0.1.0",
|
|
45
45
|
"@agi-cli/config": "0.1.0",
|
|
46
|
+
"@agi-cli/core": "0.1.0",
|
|
46
47
|
"@agi-cli/database": "0.1.0",
|
|
47
48
|
"@agi-cli/providers": "0.1.0",
|
|
48
49
|
"@agi-cli/prompts": "0.1.0",
|
package/src/agent/types.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,67 +1,27 @@
|
|
|
1
1
|
// =======================
|
|
2
|
-
//
|
|
2
|
+
// Re-export everything from @agi-cli/core
|
|
3
3
|
// =======================
|
|
4
|
-
export
|
|
5
|
-
generateText,
|
|
6
|
-
streamText,
|
|
7
|
-
generateObject,
|
|
8
|
-
streamObject,
|
|
9
|
-
tool,
|
|
10
|
-
} from 'ai';
|
|
11
|
-
export type { CoreMessage, Tool } from 'ai';
|
|
12
|
-
|
|
13
|
-
// =======================
|
|
14
|
-
// Provider & Model Resolution
|
|
15
|
-
// =======================
|
|
16
|
-
export { resolveModel } from './providers/resolver.ts';
|
|
17
|
-
export type { ProviderName, ModelConfig } from './providers/resolver.ts';
|
|
18
|
-
|
|
19
|
-
// Re-export provider catalog and utilities for easy access
|
|
20
|
-
export {
|
|
21
|
-
catalog,
|
|
22
|
-
providerIds,
|
|
23
|
-
isProviderId,
|
|
24
|
-
isProviderAuthorized,
|
|
25
|
-
validateProviderModel,
|
|
26
|
-
} from '@agi-cli/providers';
|
|
27
|
-
export type { ProviderId, ModelInfo } from '@agi-cli/providers';
|
|
28
|
-
|
|
29
|
-
// =======================
|
|
30
|
-
// Tools
|
|
31
|
-
// =======================
|
|
32
|
-
export { discoverProjectTools } from './tools/loader.ts';
|
|
33
|
-
export type { DiscoveredTool } from './tools/loader.ts';
|
|
34
|
-
|
|
35
|
-
// Re-export for testing/advanced usage
|
|
36
|
-
export { buildFsTools } from './tools/builtin/fs/index.ts';
|
|
37
|
-
export { buildGitTools } from './tools/builtin/git.ts';
|
|
4
|
+
export * from '@agi-cli/core';
|
|
38
5
|
|
|
39
6
|
// =======================
|
|
40
|
-
//
|
|
7
|
+
// Server (batteries included)
|
|
41
8
|
// =======================
|
|
42
|
-
export {
|
|
43
|
-
createFileDiffArtifact,
|
|
44
|
-
createToolResultPayload,
|
|
45
|
-
} from './streaming/artifacts.ts';
|
|
46
|
-
export type {
|
|
47
|
-
Artifact,
|
|
48
|
-
FileDiffArtifact,
|
|
49
|
-
FileArtifact,
|
|
50
|
-
} from './streaming/artifacts.ts';
|
|
9
|
+
export { createApp as createServer } from '@agi-cli/server';
|
|
51
10
|
|
|
52
11
|
// =======================
|
|
53
|
-
//
|
|
12
|
+
// Database (convenience re-export)
|
|
54
13
|
// =======================
|
|
55
|
-
export {
|
|
14
|
+
export { getDb } from '@agi-cli/database';
|
|
15
|
+
export * as dbSchema from '@agi-cli/database/schema';
|
|
56
16
|
|
|
57
17
|
// =======================
|
|
58
|
-
// Configuration
|
|
18
|
+
// Configuration (convenience re-export)
|
|
59
19
|
// =======================
|
|
60
20
|
export { loadConfig, read as readConfig } from '@agi-cli/config';
|
|
61
21
|
export type { AGIConfig, ProviderConfig, Scope } from '@agi-cli/config';
|
|
62
22
|
|
|
63
23
|
// =======================
|
|
64
|
-
// Authentication
|
|
24
|
+
// Authentication (convenience re-export)
|
|
65
25
|
// =======================
|
|
66
26
|
export {
|
|
67
27
|
getAllAuth,
|
|
@@ -77,33 +37,6 @@ export {
|
|
|
77
37
|
export type { AuthInfo, OAuth } from '@agi-cli/auth';
|
|
78
38
|
|
|
79
39
|
// =======================
|
|
80
|
-
//
|
|
40
|
+
// Agent Types (from SDK-specific modules)
|
|
81
41
|
// =======================
|
|
82
|
-
export { getDb } from '@agi-cli/database';
|
|
83
|
-
export * as dbSchema from '@agi-cli/database/schema';
|
|
84
|
-
|
|
85
|
-
// =======================
|
|
86
|
-
// Types
|
|
87
|
-
// =======================
|
|
88
|
-
export type { ExecutionContext, ToolResult } from './types/index.ts';
|
|
89
42
|
export type { AgentConfig, AgentConfigEntry } from './agent/types.ts';
|
|
90
|
-
|
|
91
|
-
// =======================
|
|
92
|
-
// Schema Validation
|
|
93
|
-
// =======================
|
|
94
|
-
export { z } from 'zod';
|
|
95
|
-
|
|
96
|
-
// =======================
|
|
97
|
-
// Error Handling
|
|
98
|
-
// =======================
|
|
99
|
-
export {
|
|
100
|
-
AGIError,
|
|
101
|
-
AuthError,
|
|
102
|
-
ConfigError,
|
|
103
|
-
ToolError,
|
|
104
|
-
ProviderError,
|
|
105
|
-
DatabaseError,
|
|
106
|
-
ValidationError,
|
|
107
|
-
NotFoundError,
|
|
108
|
-
ServiceError,
|
|
109
|
-
} from './errors.ts';
|
package/src/errors.ts
DELETED
|
@@ -1,102 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Base error class for all AGI errors
|
|
3
|
-
*/
|
|
4
|
-
export class AGIError extends Error {
|
|
5
|
-
constructor(
|
|
6
|
-
message: string,
|
|
7
|
-
public readonly code: string,
|
|
8
|
-
public readonly status: number = 500,
|
|
9
|
-
public readonly details?: Record<string, unknown>,
|
|
10
|
-
) {
|
|
11
|
-
super(message);
|
|
12
|
-
this.name = this.constructor.name;
|
|
13
|
-
Error.captureStackTrace(this, this.constructor);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
toJSON() {
|
|
17
|
-
return {
|
|
18
|
-
name: this.name,
|
|
19
|
-
message: this.message,
|
|
20
|
-
code: this.code,
|
|
21
|
-
status: this.status,
|
|
22
|
-
details: this.details,
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Authentication and authorization errors
|
|
29
|
-
*/
|
|
30
|
-
export class AuthError extends AGIError {
|
|
31
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
32
|
-
super(message, 'AUTH_ERROR', 401, details);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
/**
|
|
37
|
-
* Configuration errors
|
|
38
|
-
*/
|
|
39
|
-
export class ConfigError extends AGIError {
|
|
40
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
41
|
-
super(message, 'CONFIG_ERROR', 500, details);
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
/**
|
|
46
|
-
* Tool execution errors
|
|
47
|
-
*/
|
|
48
|
-
export class ToolError extends AGIError {
|
|
49
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
50
|
-
super(message, 'TOOL_ERROR', 500, details);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
/**
|
|
55
|
-
* Provider errors (API, model not found, etc.)
|
|
56
|
-
*/
|
|
57
|
-
export class ProviderError extends AGIError {
|
|
58
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
59
|
-
super(message, 'PROVIDER_ERROR', 500, details);
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
* Database errors
|
|
65
|
-
*/
|
|
66
|
-
export class DatabaseError extends AGIError {
|
|
67
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
68
|
-
super(message, 'DATABASE_ERROR', 500, details);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Validation errors (bad input, schema mismatch, etc.)
|
|
74
|
-
*/
|
|
75
|
-
export class ValidationError extends AGIError {
|
|
76
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
77
|
-
super(message, 'VALIDATION_ERROR', 400, details);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
/**
|
|
82
|
-
* Not found errors (session, agent, tool, etc.)
|
|
83
|
-
*/
|
|
84
|
-
export class NotFoundError extends AGIError {
|
|
85
|
-
constructor(message: string, details?: Record<string, unknown>) {
|
|
86
|
-
super(message, 'NOT_FOUND', 404, details);
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
/**
|
|
91
|
-
* Service errors from ask-service, session-manager, etc.
|
|
92
|
-
*/
|
|
93
|
-
export class ServiceError extends AGIError {
|
|
94
|
-
constructor(
|
|
95
|
-
message: string,
|
|
96
|
-
code = 'SERVICE_ERROR',
|
|
97
|
-
status = 500,
|
|
98
|
-
details?: Record<string, unknown>,
|
|
99
|
-
) {
|
|
100
|
-
super(message, code, status, details);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
import { openai, createOpenAI } from '@ai-sdk/openai';
|
|
2
|
-
import { anthropic, createAnthropic } from '@ai-sdk/anthropic';
|
|
3
|
-
import { google } from '@ai-sdk/google';
|
|
4
|
-
import { createOpenRouter } from '@openrouter/ai-sdk-provider';
|
|
5
|
-
import { createOpenAICompatible } from '@ai-sdk/openai-compatible';
|
|
6
|
-
|
|
7
|
-
export type ProviderName =
|
|
8
|
-
| 'openai'
|
|
9
|
-
| 'anthropic'
|
|
10
|
-
| 'google'
|
|
11
|
-
| 'openrouter'
|
|
12
|
-
| 'opencode';
|
|
13
|
-
|
|
14
|
-
export type ModelConfig = {
|
|
15
|
-
apiKey?: string;
|
|
16
|
-
customFetch?: typeof fetch;
|
|
17
|
-
baseURL?: string;
|
|
18
|
-
};
|
|
19
|
-
|
|
20
|
-
export async function resolveModel(
|
|
21
|
-
provider: ProviderName,
|
|
22
|
-
model: string,
|
|
23
|
-
config: ModelConfig = {},
|
|
24
|
-
) {
|
|
25
|
-
if (provider === 'openai') {
|
|
26
|
-
if (config.apiKey) {
|
|
27
|
-
const instance = createOpenAI({ apiKey: config.apiKey });
|
|
28
|
-
return instance(model);
|
|
29
|
-
}
|
|
30
|
-
return openai(model);
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
if (provider === 'anthropic') {
|
|
34
|
-
if (config.customFetch) {
|
|
35
|
-
return createAnthropic({
|
|
36
|
-
apiKey: config.apiKey || '',
|
|
37
|
-
fetch: config.customFetch as typeof fetch,
|
|
38
|
-
});
|
|
39
|
-
}
|
|
40
|
-
if (config.apiKey) {
|
|
41
|
-
const instance = createAnthropic({ apiKey: config.apiKey });
|
|
42
|
-
return instance(model);
|
|
43
|
-
}
|
|
44
|
-
return anthropic(model);
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (provider === 'google') {
|
|
48
|
-
if (config.apiKey) {
|
|
49
|
-
throw new Error('Google provider config not yet supported in SDK');
|
|
50
|
-
}
|
|
51
|
-
return google(model);
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (provider === 'openrouter') {
|
|
55
|
-
const apiKey = config.apiKey || process.env.OPENROUTER_API_KEY || '';
|
|
56
|
-
const openrouter = createOpenRouter({ apiKey });
|
|
57
|
-
return openrouter.chat(model);
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
if (provider === 'opencode') {
|
|
61
|
-
const baseURL = config.baseURL || 'https://opencode.ai/zen/v1';
|
|
62
|
-
const apiKey = config.apiKey || process.env.OPENCODE_API_KEY || '';
|
|
63
|
-
|
|
64
|
-
const ocOpenAI = createOpenAI({ apiKey, baseURL });
|
|
65
|
-
const ocAnthropic = createAnthropic({ apiKey, baseURL });
|
|
66
|
-
const ocCompat = createOpenAICompatible({
|
|
67
|
-
name: 'opencode',
|
|
68
|
-
baseURL,
|
|
69
|
-
headers: apiKey ? { Authorization: `Bearer ${apiKey}` } : undefined,
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
const id = model.toLowerCase();
|
|
73
|
-
if (id.includes('claude')) return ocAnthropic(model);
|
|
74
|
-
if (
|
|
75
|
-
id.includes('qwen3-coder') ||
|
|
76
|
-
id.includes('grok-code') ||
|
|
77
|
-
id.includes('kimi-k2')
|
|
78
|
-
)
|
|
79
|
-
return ocCompat(model);
|
|
80
|
-
return ocOpenAI(model);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
throw new Error(`Unsupported provider: ${provider}`);
|
|
84
|
-
}
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
// Shared types and helpers for tool artifacts persisted in message parts.
|
|
2
|
-
|
|
3
|
-
export type FileDiffArtifact = {
|
|
4
|
-
kind: 'file_diff';
|
|
5
|
-
patchFormat: 'unified';
|
|
6
|
-
patch: string; // full unified patch text
|
|
7
|
-
summary?: { files?: number; additions?: number; deletions?: number };
|
|
8
|
-
};
|
|
9
|
-
|
|
10
|
-
export type FileArtifact = {
|
|
11
|
-
kind: 'file';
|
|
12
|
-
path: string; // repository-relative path
|
|
13
|
-
mime?: string;
|
|
14
|
-
size?: number;
|
|
15
|
-
sha256?: string;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
export type Artifact =
|
|
19
|
-
| FileDiffArtifact
|
|
20
|
-
| FileArtifact
|
|
21
|
-
| { kind: string; [k: string]: unknown };
|
|
22
|
-
|
|
23
|
-
export function createFileDiffArtifact(
|
|
24
|
-
patch: string,
|
|
25
|
-
summary?: { files?: number; additions?: number; deletions?: number },
|
|
26
|
-
): FileDiffArtifact {
|
|
27
|
-
return { kind: 'file_diff', patchFormat: 'unified', patch, summary };
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export function createToolResultPayload(
|
|
31
|
-
name: string,
|
|
32
|
-
result?: unknown,
|
|
33
|
-
artifact?: Artifact,
|
|
34
|
-
) {
|
|
35
|
-
const payload: { name: string; result?: unknown; artifact?: Artifact } = {
|
|
36
|
-
name,
|
|
37
|
-
};
|
|
38
|
-
if (result !== undefined) payload.result = result;
|
|
39
|
-
if (artifact) payload.artifact = artifact;
|
|
40
|
-
return payload;
|
|
41
|
-
}
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
import { tool, type Tool } from 'ai';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import { spawn } from 'bun';
|
|
4
|
-
import DESCRIPTION from './bash.txt' with { type: 'text' };
|
|
5
|
-
|
|
6
|
-
function normalizePath(p: string) {
|
|
7
|
-
const parts = p.replace(/\\/g, '/').split('/');
|
|
8
|
-
const stack: string[] = [];
|
|
9
|
-
for (const part of parts) {
|
|
10
|
-
if (!part || part === '.') continue;
|
|
11
|
-
if (part === '..') stack.pop();
|
|
12
|
-
else stack.push(part);
|
|
13
|
-
}
|
|
14
|
-
return `/${stack.join('/')}`;
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
function resolveSafePath(projectRoot: string, p: string) {
|
|
18
|
-
const root = normalizePath(projectRoot);
|
|
19
|
-
const abs = normalizePath(`${root}/${p || '.'}`);
|
|
20
|
-
if (!(abs === root || abs.startsWith(`${root}/`))) {
|
|
21
|
-
throw new Error(`cwd escapes project root: ${p}`);
|
|
22
|
-
}
|
|
23
|
-
return abs;
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
export function buildBashTool(projectRoot: string): {
|
|
27
|
-
name: string;
|
|
28
|
-
tool: Tool;
|
|
29
|
-
} {
|
|
30
|
-
const bash = tool({
|
|
31
|
-
description: DESCRIPTION,
|
|
32
|
-
inputSchema: z
|
|
33
|
-
.object({
|
|
34
|
-
cmd: z.string().describe('Shell command to run (bash -lc <cmd>)'),
|
|
35
|
-
cwd: z
|
|
36
|
-
.string()
|
|
37
|
-
.default('.')
|
|
38
|
-
.describe('Working directory relative to project root'),
|
|
39
|
-
allowNonZeroExit: z
|
|
40
|
-
.boolean()
|
|
41
|
-
.optional()
|
|
42
|
-
.default(false)
|
|
43
|
-
.describe('If true, do not throw on non-zero exit'),
|
|
44
|
-
})
|
|
45
|
-
.strict(),
|
|
46
|
-
async execute({
|
|
47
|
-
cmd,
|
|
48
|
-
cwd,
|
|
49
|
-
allowNonZeroExit,
|
|
50
|
-
}: {
|
|
51
|
-
cmd: string;
|
|
52
|
-
cwd?: string;
|
|
53
|
-
allowNonZeroExit?: boolean;
|
|
54
|
-
}) {
|
|
55
|
-
const absCwd = resolveSafePath(projectRoot, cwd || '.');
|
|
56
|
-
const proc = spawn({
|
|
57
|
-
cmd: ['bash', '-lc', cmd],
|
|
58
|
-
cwd: absCwd,
|
|
59
|
-
stdout: 'pipe',
|
|
60
|
-
stderr: 'pipe',
|
|
61
|
-
});
|
|
62
|
-
const exitCode = await proc.exited;
|
|
63
|
-
const stdout = await new Response(proc.stdout).text();
|
|
64
|
-
const stderr = await new Response(proc.stderr).text();
|
|
65
|
-
if (exitCode !== 0 && !allowNonZeroExit) {
|
|
66
|
-
const msg = (stderr || stdout || `Command failed: ${cmd}`).trim();
|
|
67
|
-
throw new Error(msg);
|
|
68
|
-
}
|
|
69
|
-
return { exitCode, stdout, stderr };
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
return { name: 'bash', tool: bash };
|
|
73
|
-
}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
- Execute a shell command using `bash -lc`
|
|
2
|
-
- Returns `stdout`, `stderr`, and `exitCode`
|
|
3
|
-
- `cwd` is relative to the project root and sandboxed within it
|
|
4
|
-
|
|
5
|
-
Usage tips:
|
|
6
|
-
- Chain multiple commands with `&&` to fail-fast
|
|
7
|
-
- For long outputs, consider redirecting to a file and reading it
|
|
@@ -1,145 +0,0 @@
|
|
|
1
|
-
import { tool, type Tool } from 'ai';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import DESCRIPTION from './edit.txt' with { type: 'text' };
|
|
4
|
-
|
|
5
|
-
const replaceOp = z.object({
|
|
6
|
-
type: z.literal('replace'),
|
|
7
|
-
find: z.string().describe('String or regex (when regex=true)'),
|
|
8
|
-
replace: z.string().default(''),
|
|
9
|
-
regex: z.boolean().optional().default(false),
|
|
10
|
-
flags: z.string().optional().default('g'),
|
|
11
|
-
count: z
|
|
12
|
-
.number()
|
|
13
|
-
.int()
|
|
14
|
-
.min(1)
|
|
15
|
-
.optional()
|
|
16
|
-
.describe('Limit number of replacements'),
|
|
17
|
-
});
|
|
18
|
-
|
|
19
|
-
const insertOp = z.object({
|
|
20
|
-
type: z.literal('insert'),
|
|
21
|
-
position: z.enum(['before', 'after', 'start', 'end']).default('after'),
|
|
22
|
-
pattern: z.string().optional().describe('Anchor pattern for before/after'),
|
|
23
|
-
content: z.string(),
|
|
24
|
-
once: z.boolean().optional().default(true),
|
|
25
|
-
});
|
|
26
|
-
|
|
27
|
-
const deleteRangeOp = z.object({
|
|
28
|
-
type: z.literal('delete_range'),
|
|
29
|
-
start: z.string().describe('Start marker (first occurrence)'),
|
|
30
|
-
end: z.string().describe('End marker (first occurrence after start)'),
|
|
31
|
-
includeBoundaries: z.boolean().optional().default(false),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
const opSchema = z.discriminatedUnion('type', [
|
|
35
|
-
replaceOp,
|
|
36
|
-
insertOp,
|
|
37
|
-
deleteRangeOp,
|
|
38
|
-
]);
|
|
39
|
-
|
|
40
|
-
export const editTool: Tool = tool({
|
|
41
|
-
description: DESCRIPTION,
|
|
42
|
-
inputSchema: z.object({
|
|
43
|
-
path: z.string().min(1),
|
|
44
|
-
ops: z.array(opSchema).min(1),
|
|
45
|
-
create: z.boolean().optional().default(false),
|
|
46
|
-
}),
|
|
47
|
-
async execute({
|
|
48
|
-
path,
|
|
49
|
-
ops,
|
|
50
|
-
create,
|
|
51
|
-
}: {
|
|
52
|
-
path: string;
|
|
53
|
-
ops: z.infer<typeof opSchema>[];
|
|
54
|
-
create?: boolean;
|
|
55
|
-
}) {
|
|
56
|
-
const file = Bun.file(path);
|
|
57
|
-
if (!(await file.exists())) {
|
|
58
|
-
if (!create) throw new Error(`File not found: ${path}`);
|
|
59
|
-
await Bun.write(path, '');
|
|
60
|
-
}
|
|
61
|
-
let text = await Bun.file(path).text();
|
|
62
|
-
let applied = 0;
|
|
63
|
-
|
|
64
|
-
for (const op of ops) {
|
|
65
|
-
if (op.type === 'replace') {
|
|
66
|
-
const originalText = text;
|
|
67
|
-
if (op.regex) {
|
|
68
|
-
const re = new RegExp(op.find, op.flags || 'g');
|
|
69
|
-
if (op.count && op.count > 0) {
|
|
70
|
-
let n = 0;
|
|
71
|
-
text = text.replace(re, (m) => {
|
|
72
|
-
if (n < (op.count as number)) {
|
|
73
|
-
n += 1;
|
|
74
|
-
return op.replace;
|
|
75
|
-
}
|
|
76
|
-
return m;
|
|
77
|
-
});
|
|
78
|
-
} else text = text.replace(re, op.replace);
|
|
79
|
-
} else {
|
|
80
|
-
// Check if the text to find exists
|
|
81
|
-
if (!text.includes(op.find)) {
|
|
82
|
-
console.warn(
|
|
83
|
-
`Warning: Text not found for replace operation: "${op.find.substring(0, 50)}${op.find.length > 50 ? '...' : ''}"`,
|
|
84
|
-
);
|
|
85
|
-
}
|
|
86
|
-
if (op.count && op.count > 0) {
|
|
87
|
-
let remaining = op.count as number;
|
|
88
|
-
let idx = text.indexOf(op.find);
|
|
89
|
-
while (idx !== -1 && remaining > 0) {
|
|
90
|
-
text =
|
|
91
|
-
text.slice(0, idx) +
|
|
92
|
-
op.replace +
|
|
93
|
-
text.slice(idx + op.find.length);
|
|
94
|
-
remaining -= 1;
|
|
95
|
-
idx = text.indexOf(op.find, idx + op.replace.length);
|
|
96
|
-
}
|
|
97
|
-
} else {
|
|
98
|
-
text = text.split(op.find).join(op.replace);
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
// Only count as applied if text actually changed
|
|
102
|
-
if (text !== originalText) {
|
|
103
|
-
applied += 1;
|
|
104
|
-
}
|
|
105
|
-
} else if (op.type === 'insert') {
|
|
106
|
-
if (op.position === 'start') {
|
|
107
|
-
text = `${op.content}${text}`;
|
|
108
|
-
applied += 1;
|
|
109
|
-
continue;
|
|
110
|
-
}
|
|
111
|
-
if (op.position === 'end') {
|
|
112
|
-
text = `${text}${op.content}`;
|
|
113
|
-
applied += 1;
|
|
114
|
-
continue;
|
|
115
|
-
}
|
|
116
|
-
if (!op.pattern)
|
|
117
|
-
throw new Error('insert requires pattern for before/after');
|
|
118
|
-
const idx = text.indexOf(op.pattern);
|
|
119
|
-
if (idx === -1) continue;
|
|
120
|
-
if (op.position === 'before')
|
|
121
|
-
text = text.slice(0, idx) + op.content + text.slice(idx);
|
|
122
|
-
else
|
|
123
|
-
text =
|
|
124
|
-
text.slice(0, idx + op.pattern.length) +
|
|
125
|
-
op.content +
|
|
126
|
-
text.slice(idx + op.pattern.length);
|
|
127
|
-
applied += 1;
|
|
128
|
-
if (op.once) continue;
|
|
129
|
-
} else if (op.type === 'delete_range') {
|
|
130
|
-
const startIdx = text.indexOf(op.start);
|
|
131
|
-
if (startIdx === -1) continue;
|
|
132
|
-
const after = startIdx + op.start.length;
|
|
133
|
-
const endIdx = text.indexOf(op.end, after);
|
|
134
|
-
if (endIdx === -1) continue;
|
|
135
|
-
const from = op.includeBoundaries ? startIdx : after;
|
|
136
|
-
const to = op.includeBoundaries ? endIdx + op.end.length : endIdx;
|
|
137
|
-
text = text.slice(0, from) + text.slice(to);
|
|
138
|
-
applied += 1;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
await Bun.write(path, text);
|
|
143
|
-
return { path, opsApplied: applied, bytes: text.length };
|
|
144
|
-
},
|
|
145
|
-
});
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
- Edit a file using structured operations
|
|
2
|
-
- Supported ops: `replace`, `insert`, `delete_range`
|
|
3
|
-
- Paths are relative to the project root; can create files if flagged
|
|
4
|
-
|
|
5
|
-
Usage tips:
|
|
6
|
-
- Prefer minimal, targeted changes for clarity
|
|
7
|
-
- For sweeping refactors, consider Write or Patch to replace full content
|
|
@@ -1,39 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* File content cache to track modifications during a session/step
|
|
3
|
-
* This helps ensure tools always work with the latest file content
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
const fileContentCache = new Map<string, Map<string, string>>();
|
|
7
|
-
|
|
8
|
-
export function getFileCache(sessionId: string): Map<string, string> {
|
|
9
|
-
if (!fileContentCache.has(sessionId)) {
|
|
10
|
-
fileContentCache.set(sessionId, new Map());
|
|
11
|
-
}
|
|
12
|
-
return fileContentCache.get(sessionId) as Map<string, string>;
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
export function updateFileCache(
|
|
16
|
-
sessionId: string,
|
|
17
|
-
filePath: string,
|
|
18
|
-
content: string,
|
|
19
|
-
): void {
|
|
20
|
-
const cache = getFileCache(sessionId);
|
|
21
|
-
cache.set(filePath, content);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export function getCachedContent(
|
|
25
|
-
sessionId: string,
|
|
26
|
-
filePath: string,
|
|
27
|
-
): string | undefined {
|
|
28
|
-
const cache = getFileCache(sessionId);
|
|
29
|
-
return cache.get(filePath);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function clearFileCache(sessionId: string): void {
|
|
33
|
-
fileContentCache.delete(sessionId);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function clearFileCacheEntry(sessionId: string, filePath: string): void {
|
|
37
|
-
const cache = getFileCache(sessionId);
|
|
38
|
-
cache.delete(filePath);
|
|
39
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod';
|
|
2
|
-
import { tool } from 'ai';
|
|
3
|
-
import DESCRIPTION from './finish.txt' with { type: 'text' };
|
|
4
|
-
|
|
5
|
-
export const finishTool = tool({
|
|
6
|
-
description: DESCRIPTION,
|
|
7
|
-
inputSchema: z.object({}),
|
|
8
|
-
async execute() {
|
|
9
|
-
return { done: true } as const;
|
|
10
|
-
},
|
|
11
|
-
});
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import { tool, type Tool } from 'ai';
|
|
2
|
-
import { z } from 'zod';
|
|
3
|
-
import DESCRIPTION from './cd.txt' with { type: 'text' };
|
|
4
|
-
|
|
5
|
-
// description imported above
|
|
6
|
-
|
|
7
|
-
export function buildCdTool(): { name: string; tool: Tool } {
|
|
8
|
-
const cd = tool({
|
|
9
|
-
description: DESCRIPTION,
|
|
10
|
-
inputSchema: z.object({
|
|
11
|
-
path: z.string().describe('Relative directory path'),
|
|
12
|
-
}),
|
|
13
|
-
async execute({ path }: { path: string }) {
|
|
14
|
-
// Actual cwd update is handled in the adapter; this is a placeholder schema
|
|
15
|
-
return { cwd: path };
|
|
16
|
-
},
|
|
17
|
-
});
|
|
18
|
-
return { name: 'cd', tool: cd };
|
|
19
|
-
}
|