@agi-cli/sdk 0.1.49 → 0.1.51
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 +237 -538
- package/package.json +11 -7
- package/src/agent/types.ts +1 -1
- package/src/index.ts +99 -64
- 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,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agi-cli/sdk",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "AI agent SDK for building intelligent assistants",
|
|
3
|
+
"version": "0.1.51",
|
|
4
|
+
"description": "AI agent SDK for building intelligent assistants - tree-shakable and comprehensive",
|
|
5
5
|
"author": "ntishxyz",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"homepage": "https://github.com/ntishxyz/agi#readme",
|
|
@@ -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,10 +43,12 @@
|
|
|
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",
|
|
49
50
|
"@agi-cli/server": "0.1.0",
|
|
51
|
+
"@agi-cli/types": "0.1.0",
|
|
50
52
|
"ai": "^5.0.43",
|
|
51
53
|
"@ai-sdk/anthropic": "^2.0.16",
|
|
52
54
|
"@ai-sdk/openai": "^2.0.30",
|
|
@@ -69,6 +71,8 @@
|
|
|
69
71
|
"anthropic",
|
|
70
72
|
"openai",
|
|
71
73
|
"development",
|
|
72
|
-
"assistant"
|
|
74
|
+
"assistant",
|
|
75
|
+
"tree-shakable",
|
|
76
|
+
"typescript"
|
|
73
77
|
]
|
|
74
78
|
}
|
package/src/agent/types.ts
CHANGED
package/src/index.ts
CHANGED
|
@@ -1,67 +1,56 @@
|
|
|
1
|
-
//
|
|
2
|
-
//
|
|
3
|
-
//
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
//
|
|
14
|
-
//
|
|
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';
|
|
1
|
+
// ============================================================================
|
|
2
|
+
// @agi-cli/sdk - Tree-shakable AI Agent SDK
|
|
3
|
+
// ============================================================================
|
|
4
|
+
// This is the SINGLE source of truth for all AGI CLI functionality.
|
|
5
|
+
// All exports are tree-shakable - bundlers will only include what you use.
|
|
6
|
+
//
|
|
7
|
+
// Usage:
|
|
8
|
+
// import { generateText, resolveModel } from '@agi-cli/sdk';
|
|
9
|
+
// import type { ProviderId, AGIConfig } from '@agi-cli/sdk';
|
|
10
|
+
//
|
|
11
|
+
// Note: Direct package imports are still available but discouraged:
|
|
12
|
+
// import { catalog } from '@agi-cli/providers'; // ❌ Discouraged
|
|
13
|
+
// import { catalog } from '@agi-cli/sdk'; // ✅ Recommended
|
|
14
|
+
// ============================================================================
|
|
28
15
|
|
|
29
16
|
// =======================
|
|
30
|
-
//
|
|
17
|
+
// Types (from @agi-cli/types)
|
|
31
18
|
// =======================
|
|
32
|
-
|
|
33
|
-
export type {
|
|
19
|
+
// Provider types
|
|
20
|
+
export type { ProviderId, ModelInfo } from '@agi-cli/types';
|
|
34
21
|
|
|
35
|
-
//
|
|
36
|
-
export {
|
|
37
|
-
export { buildGitTools } from './tools/builtin/git.ts';
|
|
22
|
+
// Auth types
|
|
23
|
+
export type { ApiAuth, OAuth, AuthInfo, AuthFile } from '@agi-cli/types';
|
|
38
24
|
|
|
39
|
-
//
|
|
40
|
-
// Streaming & Artifacts
|
|
41
|
-
// =======================
|
|
42
|
-
export {
|
|
43
|
-
createFileDiffArtifact,
|
|
44
|
-
createToolResultPayload,
|
|
45
|
-
} from './streaming/artifacts.ts';
|
|
25
|
+
// Config types
|
|
46
26
|
export type {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// Server
|
|
54
|
-
// =======================
|
|
55
|
-
export { createApp as createServer } from '@agi-cli/server';
|
|
27
|
+
Scope,
|
|
28
|
+
ProviderConfig,
|
|
29
|
+
DefaultConfig,
|
|
30
|
+
PathConfig,
|
|
31
|
+
AGIConfig,
|
|
32
|
+
} from '@agi-cli/types';
|
|
56
33
|
|
|
57
34
|
// =======================
|
|
58
|
-
//
|
|
35
|
+
// Providers (from @agi-cli/providers)
|
|
59
36
|
// =======================
|
|
60
|
-
export {
|
|
61
|
-
export
|
|
37
|
+
export { catalog } from '@agi-cli/providers';
|
|
38
|
+
export {
|
|
39
|
+
isProviderId,
|
|
40
|
+
providerIds,
|
|
41
|
+
defaultModelFor,
|
|
42
|
+
hasModel,
|
|
43
|
+
} from '@agi-cli/providers';
|
|
44
|
+
export {
|
|
45
|
+
isProviderAuthorized,
|
|
46
|
+
ensureProviderEnv,
|
|
47
|
+
} from '@agi-cli/providers';
|
|
48
|
+
export { validateProviderModel } from '@agi-cli/providers';
|
|
49
|
+
export { estimateModelCostUsd } from '@agi-cli/providers';
|
|
50
|
+
export { providerEnvVar, readEnvKey, setEnvKey } from '@agi-cli/providers';
|
|
62
51
|
|
|
63
52
|
// =======================
|
|
64
|
-
// Authentication
|
|
53
|
+
// Authentication (from @agi-cli/auth)
|
|
65
54
|
// =======================
|
|
66
55
|
export {
|
|
67
56
|
getAllAuth,
|
|
@@ -74,28 +63,61 @@ export {
|
|
|
74
63
|
openAuthUrl,
|
|
75
64
|
createApiKey,
|
|
76
65
|
} from '@agi-cli/auth';
|
|
77
|
-
export type { AuthInfo, OAuth } from '@agi-cli/auth';
|
|
78
66
|
|
|
79
67
|
// =======================
|
|
80
|
-
//
|
|
68
|
+
// Configuration (from @agi-cli/config)
|
|
81
69
|
// =======================
|
|
82
|
-
export {
|
|
83
|
-
export * as dbSchema from '@agi-cli/database/schema';
|
|
70
|
+
export { loadConfig, read as readConfig } from '@agi-cli/config';
|
|
84
71
|
|
|
85
72
|
// =======================
|
|
86
|
-
//
|
|
73
|
+
// Prompts (from @agi-cli/prompts)
|
|
87
74
|
// =======================
|
|
88
|
-
export
|
|
89
|
-
export type { AgentConfig, AgentConfigEntry } from './agent/types.ts';
|
|
75
|
+
export { providerBasePrompt } from '@agi-cli/prompts';
|
|
90
76
|
|
|
91
77
|
// =======================
|
|
92
|
-
//
|
|
78
|
+
// Database (from @agi-cli/database)
|
|
93
79
|
// =======================
|
|
94
|
-
export {
|
|
80
|
+
export { getDb } from '@agi-cli/database';
|
|
81
|
+
export * as dbSchema from '@agi-cli/database/schema';
|
|
95
82
|
|
|
96
83
|
// =======================
|
|
97
|
-
//
|
|
84
|
+
// Core AI Functions (from @agi-cli/core)
|
|
98
85
|
// =======================
|
|
86
|
+
// AI SDK re-exports
|
|
87
|
+
export {
|
|
88
|
+
generateText,
|
|
89
|
+
streamText,
|
|
90
|
+
generateObject,
|
|
91
|
+
streamObject,
|
|
92
|
+
tool,
|
|
93
|
+
} from '@agi-cli/core';
|
|
94
|
+
export type { CoreMessage, Tool } from '@agi-cli/core';
|
|
95
|
+
|
|
96
|
+
// Provider & Model Resolution
|
|
97
|
+
export { resolveModel } from '@agi-cli/core';
|
|
98
|
+
export type { ProviderName, ModelConfig } from '@agi-cli/core';
|
|
99
|
+
|
|
100
|
+
// Tools
|
|
101
|
+
export { discoverProjectTools } from '@agi-cli/core';
|
|
102
|
+
export type { DiscoveredTool } from '@agi-cli/core';
|
|
103
|
+
export { buildFsTools } from '@agi-cli/core';
|
|
104
|
+
export { buildGitTools } from '@agi-cli/core';
|
|
105
|
+
|
|
106
|
+
// Streaming & Artifacts
|
|
107
|
+
export {
|
|
108
|
+
createFileDiffArtifact,
|
|
109
|
+
createToolResultPayload,
|
|
110
|
+
} from '@agi-cli/core';
|
|
111
|
+
export type {
|
|
112
|
+
Artifact,
|
|
113
|
+
FileDiffArtifact,
|
|
114
|
+
FileArtifact,
|
|
115
|
+
} from '@agi-cli/core';
|
|
116
|
+
|
|
117
|
+
// Core Types
|
|
118
|
+
export type { ExecutionContext, ToolResult } from '@agi-cli/core';
|
|
119
|
+
|
|
120
|
+
// Error Handling
|
|
99
121
|
export {
|
|
100
122
|
AGIError,
|
|
101
123
|
AuthError,
|
|
@@ -106,4 +128,17 @@ export {
|
|
|
106
128
|
ValidationError,
|
|
107
129
|
NotFoundError,
|
|
108
130
|
ServiceError,
|
|
109
|
-
} from '
|
|
131
|
+
} from '@agi-cli/core';
|
|
132
|
+
|
|
133
|
+
// Schema Validation
|
|
134
|
+
export { z } from '@agi-cli/core';
|
|
135
|
+
|
|
136
|
+
// =======================
|
|
137
|
+
// Server (from @agi-cli/server)
|
|
138
|
+
// =======================
|
|
139
|
+
export { createApp as createServer } from '@agi-cli/server';
|
|
140
|
+
|
|
141
|
+
// =======================
|
|
142
|
+
// SDK-specific Agent Types
|
|
143
|
+
// =======================
|
|
144
|
+
export type { AgentConfig, AgentConfigEntry } from './agent/types.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
|