@cuylabs/agent-core 0.7.0 → 0.9.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/{builder-BRvqCcIk.d.ts → builder-BgZ_j4Vs.d.ts} +3 -2
- package/dist/chunk-4QFNWPIF.js +202 -0
- package/dist/chunk-5ARZJWD2.js +259 -0
- package/dist/chunk-DXFBQMXP.js +53 -0
- package/dist/chunk-EKR6PKXU.js +180 -0
- package/dist/{chunk-IVUJDISU.js → chunk-GFTW23FV.js} +5 -14
- package/dist/{chunk-IEFIQENH.js → chunk-H3FUYU52.js} +15 -7
- package/dist/chunk-I6PKJ7XQ.js +292 -0
- package/dist/chunk-IYWQOJMQ.js +102 -0
- package/dist/{chunk-3HNO5SVI.js → chunk-J4QDGZIA.js} +20 -4
- package/dist/{chunk-7MUFEN4K.js → chunk-JLXG2SH7.js} +349 -3
- package/dist/{chunk-CDTV2UYU.js → chunk-MAZ5DY5B.js} +64 -276
- package/dist/{chunk-P6YF7USR.js → chunk-MHKK374K.js} +12 -11
- package/dist/{chunk-VBWWUHWI.js → chunk-OFDKHNCX.js} +4 -1
- package/dist/{chunk-YUUJK53A.js → chunk-RKEW5WXI.js} +1 -1
- package/dist/{chunk-LRHOS4ZN.js → chunk-SPILYYDF.js} +3 -2
- package/dist/{chunk-QGOGIP7T.js → chunk-UDCZ673N.js} +385 -233
- package/dist/{chunk-BDBZ3SLK.js → chunk-UHCJEM2E.js} +39 -2
- package/dist/chunk-WGZAPU6N.js +929 -0
- package/dist/{chunk-5K7AQVOU.js → chunk-WKHDSSXG.js} +130 -209
- package/dist/{chunk-BNSHUWCV.js → chunk-WWYYNWEW.js} +1 -1
- package/dist/context/index.js +1 -1
- package/dist/events-CE72w8W4.d.ts +149 -0
- package/dist/index-BCqEGzBj.d.ts +251 -0
- package/dist/{index-C33hlD6H.d.ts → index-DQuTZ8xL.d.ts} +319 -56
- package/dist/index.d.ts +42 -121
- package/dist/index.js +951 -848
- package/dist/inference/errors/index.d.ts +11 -0
- package/dist/inference/errors/index.js +16 -0
- package/dist/inference/index.d.ts +12 -8
- package/dist/inference/index.js +35 -7
- package/dist/llm-error-D93FNNLY.d.ts +32 -0
- package/dist/middleware/index.d.ts +246 -7
- package/dist/middleware/index.js +3 -1
- package/dist/models/index.d.ts +132 -9
- package/dist/models/index.js +48 -8
- package/dist/models/reasoning/index.d.ts +4 -0
- package/dist/{reasoning → models/reasoning}/index.js +2 -7
- package/dist/plugin/index.d.ts +414 -0
- package/dist/plugin/index.js +32 -0
- package/dist/presets/index.d.ts +53 -0
- package/dist/presets/index.js +30 -0
- package/dist/prompt/index.d.ts +11 -8
- package/dist/prompt/index.js +3 -2
- package/dist/{registry-BDLIHOQB.d.ts → registry-DwYqsQkX.d.ts} +1 -1
- package/dist/runner-CI-XeR16.d.ts +91 -0
- package/dist/runtime/index.d.ts +12 -8
- package/dist/runtime/index.js +8 -7
- package/dist/safety/index.d.ts +38 -0
- package/dist/safety/index.js +12 -0
- package/dist/scope/index.d.ts +2 -2
- package/dist/{session-manager-B_CWGTsl.d.ts → session-manager-KbYt2WUh.d.ts} +8 -0
- package/dist/signal/index.d.ts +28 -0
- package/dist/signal/index.js +6 -0
- package/dist/skill/index.d.ts +7 -6
- package/dist/skill/index.js +3 -3
- package/dist/storage/index.d.ts +2 -2
- package/dist/storage/index.js +1 -1
- package/dist/sub-agent/index.d.ts +16 -10
- package/dist/sub-agent/index.js +21 -4
- package/dist/tool/index.d.ts +22 -6
- package/dist/tool/index.js +3 -3
- package/dist/tool-CZWN3KbO.d.ts +141 -0
- package/dist/{tool-HUtkiVBx.d.ts → tool-DkhSCV2Y.d.ts} +2 -2
- package/dist/tracking/index.d.ts +2 -2
- package/dist/tracking/index.js +1 -1
- package/dist/{tool-Db1Ue-1U.d.ts → types-BfNpU8NS.d.ts} +1 -150
- package/dist/{types-FRpzzg_9.d.ts → types-BlOKk-Bb.d.ts} +10 -35
- package/dist/types-BlZwmnuW.d.ts +50 -0
- package/dist/{types-9jGQUjqW.d.ts → types-CQL-SvTn.d.ts} +1 -1
- package/dist/types-CWm-7rvB.d.ts +55 -0
- package/dist/{runner-DSKaEz3z.d.ts → types-DTSkxakL.d.ts} +7 -235
- package/dist/{types-CqDZTh4d.d.ts → types-DmDwi2zI.d.ts} +8 -4
- package/dist/types-YuWV4ag7.d.ts +72 -0
- package/package.json +67 -6
- package/dist/capability-resolver-CgRGsWVX.d.ts +0 -254
- package/dist/chunk-ZPMACVZK.js +0 -305
- package/dist/index-CfBGYrpd.d.ts +0 -317
- package/dist/reasoning/index.d.ts +0 -117
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { S as SkillRegistry } from './registry-
|
|
1
|
+
import { d as PromptConfig, P as PromptBuildContext, c as PromptSection, e as ModelFamily } from './types-DTSkxakL.js';
|
|
2
|
+
import { S as SkillRegistry } from './registry-DwYqsQkX.js';
|
|
3
|
+
import { M as MiddlewareRunner } from './runner-CI-XeR16.js';
|
|
3
4
|
|
|
4
5
|
interface PromptSectionPreview {
|
|
5
6
|
id: string;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
// src/inference/errors/classify.ts
|
|
2
|
+
function isRetryableCategory(category) {
|
|
3
|
+
switch (category) {
|
|
4
|
+
case "rate_limit":
|
|
5
|
+
case "overloaded":
|
|
6
|
+
case "network":
|
|
7
|
+
case "timeout":
|
|
8
|
+
return true;
|
|
9
|
+
case "auth":
|
|
10
|
+
case "invalid_request":
|
|
11
|
+
case "context_overflow":
|
|
12
|
+
case "content_filter":
|
|
13
|
+
case "cancelled":
|
|
14
|
+
case "unknown":
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
function classifyFromStatusAndMessage(status, message) {
|
|
19
|
+
const lowerMessage = message.toLowerCase();
|
|
20
|
+
if (status) {
|
|
21
|
+
if (status === 429) return "rate_limit";
|
|
22
|
+
if (status === 401 || status === 403) return "auth";
|
|
23
|
+
if (status === 400) {
|
|
24
|
+
if (lowerMessage.includes("context") || lowerMessage.includes("token")) {
|
|
25
|
+
return "context_overflow";
|
|
26
|
+
}
|
|
27
|
+
return "invalid_request";
|
|
28
|
+
}
|
|
29
|
+
if (status === 503 || status === 502) return "overloaded";
|
|
30
|
+
if (status >= 500) return "network";
|
|
31
|
+
}
|
|
32
|
+
if (lowerMessage.includes("rate") && lowerMessage.includes("limit")) {
|
|
33
|
+
return "rate_limit";
|
|
34
|
+
}
|
|
35
|
+
if (lowerMessage.includes("overload") || lowerMessage.includes("capacity")) {
|
|
36
|
+
return "overloaded";
|
|
37
|
+
}
|
|
38
|
+
if (lowerMessage.includes("too_many_requests")) {
|
|
39
|
+
return "rate_limit";
|
|
40
|
+
}
|
|
41
|
+
if (lowerMessage.includes("unauthorized") || lowerMessage.includes("invalid api key")) {
|
|
42
|
+
return "auth";
|
|
43
|
+
}
|
|
44
|
+
if (lowerMessage.includes("context") && lowerMessage.includes("length")) {
|
|
45
|
+
return "context_overflow";
|
|
46
|
+
}
|
|
47
|
+
if (lowerMessage.includes("content") && lowerMessage.includes("filter")) {
|
|
48
|
+
return "content_filter";
|
|
49
|
+
}
|
|
50
|
+
if (lowerMessage.includes("timeout") || lowerMessage.includes("timed out")) {
|
|
51
|
+
return "timeout";
|
|
52
|
+
}
|
|
53
|
+
if (lowerMessage.includes("network") || lowerMessage.includes("econnrefused") || lowerMessage.includes("econnreset")) {
|
|
54
|
+
return "network";
|
|
55
|
+
}
|
|
56
|
+
return "unknown";
|
|
57
|
+
}
|
|
58
|
+
function parseRetryDelay(headers) {
|
|
59
|
+
const retryAfterMs = headers["retry-after-ms"];
|
|
60
|
+
if (retryAfterMs) {
|
|
61
|
+
const parsed = parseFloat(retryAfterMs);
|
|
62
|
+
if (!Number.isNaN(parsed) && parsed > 0) {
|
|
63
|
+
return parsed;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const retryAfter = headers["retry-after"];
|
|
67
|
+
if (retryAfter) {
|
|
68
|
+
const seconds = parseFloat(retryAfter);
|
|
69
|
+
if (!Number.isNaN(seconds) && seconds > 0) {
|
|
70
|
+
return Math.ceil(seconds * 1e3);
|
|
71
|
+
}
|
|
72
|
+
const dateMs = Date.parse(retryAfter);
|
|
73
|
+
if (!Number.isNaN(dateMs)) {
|
|
74
|
+
const delayMs = dateMs - Date.now();
|
|
75
|
+
if (delayMs > 0) {
|
|
76
|
+
return Math.ceil(delayMs);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return void 0;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// src/inference/errors/extract.ts
|
|
84
|
+
function extractFromAISDKError(error) {
|
|
85
|
+
const result = {};
|
|
86
|
+
const anyError = error;
|
|
87
|
+
if (typeof anyError.status === "number") {
|
|
88
|
+
result.status = anyError.status;
|
|
89
|
+
} else if (typeof anyError.statusCode === "number") {
|
|
90
|
+
result.status = anyError.statusCode;
|
|
91
|
+
}
|
|
92
|
+
if (anyError.responseHeaders && typeof anyError.responseHeaders === "object") {
|
|
93
|
+
result.headers = anyError.responseHeaders;
|
|
94
|
+
} else if (anyError.headers && typeof anyError.headers === "object") {
|
|
95
|
+
result.headers = anyError.headers;
|
|
96
|
+
}
|
|
97
|
+
if (anyError.data && typeof anyError.data === "object") {
|
|
98
|
+
const data = anyError.data;
|
|
99
|
+
if (data.type === "error" && typeof data.error === "object") {
|
|
100
|
+
const innerError = data.error;
|
|
101
|
+
if (innerError.type === "too_many_requests") {
|
|
102
|
+
result.category = "rate_limit";
|
|
103
|
+
} else if (innerError.type === "overloaded") {
|
|
104
|
+
result.category = "overloaded";
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
if (typeof data.isRetryable === "boolean" && !data.isRetryable && !result.category) {
|
|
108
|
+
result.category = "invalid_request";
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
return result;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// src/inference/errors/llm-error.ts
|
|
115
|
+
var LLMError = class _LLMError extends Error {
|
|
116
|
+
category;
|
|
117
|
+
status;
|
|
118
|
+
headers;
|
|
119
|
+
provider;
|
|
120
|
+
model;
|
|
121
|
+
isRetryable;
|
|
122
|
+
retryDelayMs;
|
|
123
|
+
constructor(options) {
|
|
124
|
+
super(options.message, { cause: options.cause });
|
|
125
|
+
this.name = "LLMError";
|
|
126
|
+
this.status = options.status;
|
|
127
|
+
this.headers = options.headers;
|
|
128
|
+
this.provider = options.provider;
|
|
129
|
+
this.model = options.model;
|
|
130
|
+
this.category = options.category ?? classifyFromStatusAndMessage(
|
|
131
|
+
options.status,
|
|
132
|
+
options.message
|
|
133
|
+
);
|
|
134
|
+
this.isRetryable = isRetryableCategory(this.category);
|
|
135
|
+
this.retryDelayMs = this.headers ? parseRetryDelay(this.headers) : void 0;
|
|
136
|
+
}
|
|
137
|
+
static from(error, context) {
|
|
138
|
+
if (error instanceof _LLMError) {
|
|
139
|
+
return error;
|
|
140
|
+
}
|
|
141
|
+
if (error instanceof Error) {
|
|
142
|
+
if (error.name === "AbortError" || error.message.includes("abort")) {
|
|
143
|
+
return new _LLMError({
|
|
144
|
+
message: error.message,
|
|
145
|
+
category: "cancelled",
|
|
146
|
+
cause: error,
|
|
147
|
+
...context
|
|
148
|
+
});
|
|
149
|
+
}
|
|
150
|
+
return new _LLMError({
|
|
151
|
+
message: error.message,
|
|
152
|
+
cause: error,
|
|
153
|
+
...extractFromAISDKError(error),
|
|
154
|
+
...context
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
return new _LLMError({
|
|
158
|
+
message: String(error),
|
|
159
|
+
category: "unknown",
|
|
160
|
+
...context
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
get description() {
|
|
164
|
+
const parts = [this.message];
|
|
165
|
+
if (this.provider) parts.unshift(`[${this.provider}]`);
|
|
166
|
+
if (this.status) parts.push(`(HTTP ${this.status})`);
|
|
167
|
+
if (this.isRetryable && this.retryDelayMs) {
|
|
168
|
+
parts.push(`retry in ${Math.ceil(this.retryDelayMs / 1e3)}s`);
|
|
169
|
+
}
|
|
170
|
+
return parts.join(" ");
|
|
171
|
+
}
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// src/inference/errors/utils.ts
|
|
175
|
+
function isRetryable(error) {
|
|
176
|
+
if (error instanceof LLMError) {
|
|
177
|
+
return error.isRetryable;
|
|
178
|
+
}
|
|
179
|
+
return LLMError.from(error).isRetryable;
|
|
180
|
+
}
|
|
181
|
+
function getRetryDelay(error) {
|
|
182
|
+
if (error instanceof LLMError) {
|
|
183
|
+
return error.isRetryable ? error.retryDelayMs : void 0;
|
|
184
|
+
}
|
|
185
|
+
const llmError = LLMError.from(error);
|
|
186
|
+
return llmError.isRetryable ? llmError.retryDelayMs : void 0;
|
|
187
|
+
}
|
|
188
|
+
function getErrorCategory(error) {
|
|
189
|
+
if (error instanceof LLMError) {
|
|
190
|
+
return error.category;
|
|
191
|
+
}
|
|
192
|
+
return LLMError.from(error).category;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export {
|
|
196
|
+
isRetryableCategory,
|
|
197
|
+
parseRetryDelay,
|
|
198
|
+
LLMError,
|
|
199
|
+
isRetryable,
|
|
200
|
+
getRetryDelay,
|
|
201
|
+
getErrorCategory
|
|
202
|
+
};
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
// src/safety/risk.ts
|
|
2
|
+
var DEFAULT_TOOL_RISKS = {
|
|
3
|
+
read: "safe",
|
|
4
|
+
read_file: "safe",
|
|
5
|
+
grep: "safe",
|
|
6
|
+
glob: "safe",
|
|
7
|
+
list_dir: "safe",
|
|
8
|
+
plan: "safe",
|
|
9
|
+
invoke_agent: "safe",
|
|
10
|
+
wait_agent: "safe",
|
|
11
|
+
close_agent: "safe",
|
|
12
|
+
skill: "safe",
|
|
13
|
+
skill_resource: "safe",
|
|
14
|
+
write: "moderate",
|
|
15
|
+
write_file: "moderate",
|
|
16
|
+
edit: "moderate",
|
|
17
|
+
edit_file: "moderate",
|
|
18
|
+
create_file: "moderate",
|
|
19
|
+
bash: "dangerous",
|
|
20
|
+
shell: "dangerous",
|
|
21
|
+
delete_file: "dangerous",
|
|
22
|
+
remove: "dangerous"
|
|
23
|
+
};
|
|
24
|
+
function getToolRisk(tool, customRisks) {
|
|
25
|
+
if (customRisks?.[tool]) {
|
|
26
|
+
return customRisks[tool];
|
|
27
|
+
}
|
|
28
|
+
if (DEFAULT_TOOL_RISKS[tool]) {
|
|
29
|
+
return DEFAULT_TOOL_RISKS[tool];
|
|
30
|
+
}
|
|
31
|
+
return "moderate";
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// src/safety/errors.ts
|
|
35
|
+
var ApprovalDeniedError = class extends Error {
|
|
36
|
+
constructor(tool, args, message) {
|
|
37
|
+
super(message || `Operation denied: ${tool}`);
|
|
38
|
+
this.tool = tool;
|
|
39
|
+
this.args = args;
|
|
40
|
+
this.name = "ApprovalDeniedError";
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
var ApprovalTimeoutError = class extends Error {
|
|
44
|
+
constructor(tool, timeoutMs) {
|
|
45
|
+
super(`Approval timeout after ${timeoutMs}ms for: ${tool}`);
|
|
46
|
+
this.tool = tool;
|
|
47
|
+
this.timeoutMs = timeoutMs;
|
|
48
|
+
this.name = "ApprovalTimeoutError";
|
|
49
|
+
}
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
// src/safety/patterns.ts
|
|
53
|
+
function matchApprovalPattern(pattern, value) {
|
|
54
|
+
if (pattern.length > 500) return false;
|
|
55
|
+
const p = pattern.toLowerCase();
|
|
56
|
+
const v = value.toLowerCase();
|
|
57
|
+
let pi = 0;
|
|
58
|
+
let vi = 0;
|
|
59
|
+
let starPi = -1;
|
|
60
|
+
let starVi = -1;
|
|
61
|
+
while (vi < v.length) {
|
|
62
|
+
if (pi < p.length && (p[pi] === "?" || p[pi] === v[vi])) {
|
|
63
|
+
pi++;
|
|
64
|
+
vi++;
|
|
65
|
+
} else if (pi < p.length && p[pi] === "*") {
|
|
66
|
+
starPi = pi;
|
|
67
|
+
starVi = vi;
|
|
68
|
+
pi++;
|
|
69
|
+
} else if (starPi !== -1) {
|
|
70
|
+
pi = starPi + 1;
|
|
71
|
+
starVi++;
|
|
72
|
+
vi = starVi;
|
|
73
|
+
} else {
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
while (pi < p.length && p[pi] === "*") {
|
|
78
|
+
pi++;
|
|
79
|
+
}
|
|
80
|
+
return pi === p.length;
|
|
81
|
+
}
|
|
82
|
+
function extractApprovalPatterns(tool, args) {
|
|
83
|
+
if (!args || typeof args !== "object") {
|
|
84
|
+
return [tool];
|
|
85
|
+
}
|
|
86
|
+
const record = args;
|
|
87
|
+
if ("path" in record && typeof record.path === "string" || "filePath" in record && typeof record.filePath === "string") {
|
|
88
|
+
const path = record.path ?? record.filePath;
|
|
89
|
+
const dir = path.substring(0, path.lastIndexOf("/") + 1);
|
|
90
|
+
return [dir ? `${dir}*` : path];
|
|
91
|
+
}
|
|
92
|
+
if ("command" in record && typeof record.command === "string") {
|
|
93
|
+
const command = record.command.split(/\s+/)[0];
|
|
94
|
+
return [command];
|
|
95
|
+
}
|
|
96
|
+
if ("pattern" in record && typeof record.pattern === "string") {
|
|
97
|
+
return [record.pattern];
|
|
98
|
+
}
|
|
99
|
+
return [tool];
|
|
100
|
+
}
|
|
101
|
+
function describeApprovalOperation(tool, args) {
|
|
102
|
+
if (!args || typeof args !== "object") {
|
|
103
|
+
return `Execute ${tool}`;
|
|
104
|
+
}
|
|
105
|
+
const record = args;
|
|
106
|
+
switch (tool) {
|
|
107
|
+
case "read":
|
|
108
|
+
case "read_file":
|
|
109
|
+
return `Read file: ${record.path ?? record.filePath}`;
|
|
110
|
+
case "write":
|
|
111
|
+
case "write_file":
|
|
112
|
+
case "create_file":
|
|
113
|
+
return `Write file: ${record.path ?? record.filePath}`;
|
|
114
|
+
case "edit":
|
|
115
|
+
case "edit_file":
|
|
116
|
+
return `Edit file: ${record.path ?? record.filePath}`;
|
|
117
|
+
case "delete_file":
|
|
118
|
+
case "remove":
|
|
119
|
+
return `Delete: ${record.path}`;
|
|
120
|
+
case "bash":
|
|
121
|
+
case "shell": {
|
|
122
|
+
const command = String(record.command);
|
|
123
|
+
return `Run command: ${command.slice(0, 100)}${command.length > 100 ? "..." : ""}`;
|
|
124
|
+
}
|
|
125
|
+
case "grep":
|
|
126
|
+
return `Search for: ${record.pattern}`;
|
|
127
|
+
case "glob":
|
|
128
|
+
return `Find files: ${record.pattern}`;
|
|
129
|
+
default: {
|
|
130
|
+
const json = JSON.stringify(args);
|
|
131
|
+
const truncated = json.length > 50 ? `${json.slice(0, 50)}...` : json;
|
|
132
|
+
return `${tool}(${truncated})`;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// src/safety/handler.ts
|
|
138
|
+
function findMatchingRule(rules, tool, patterns) {
|
|
139
|
+
for (let index = rules.length - 1; index >= 0; index--) {
|
|
140
|
+
const rule = rules[index];
|
|
141
|
+
const toolMatches = rule.tool === "*" || matchApprovalPattern(rule.tool, tool);
|
|
142
|
+
const patternMatches = patterns.some(
|
|
143
|
+
(pattern) => matchApprovalPattern(rule.pattern, pattern)
|
|
144
|
+
);
|
|
145
|
+
if (toolMatches && patternMatches) {
|
|
146
|
+
return rule;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return void 0;
|
|
150
|
+
}
|
|
151
|
+
function createApprovalHandler(config = {}) {
|
|
152
|
+
const {
|
|
153
|
+
defaultAction = "ask",
|
|
154
|
+
timeout = 5 * 60 * 1e3,
|
|
155
|
+
onRequest
|
|
156
|
+
} = config;
|
|
157
|
+
let requestCounter = 0;
|
|
158
|
+
const initialRuleCount = config.rules?.length ?? 0;
|
|
159
|
+
const rules = [...config.rules ?? []];
|
|
160
|
+
const activeRequests = /* @__PURE__ */ new Set();
|
|
161
|
+
async function request(sessionId, tool, args, customRisks) {
|
|
162
|
+
const risk = getToolRisk(tool, customRisks);
|
|
163
|
+
const patterns = extractApprovalPatterns(tool, args);
|
|
164
|
+
const matchingRule = findMatchingRule(rules, tool, patterns);
|
|
165
|
+
if (matchingRule) {
|
|
166
|
+
if (matchingRule.action === "allow") {
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
throw new ApprovalDeniedError(
|
|
170
|
+
tool,
|
|
171
|
+
args,
|
|
172
|
+
`Denied by rule: ${matchingRule.pattern}`
|
|
173
|
+
);
|
|
174
|
+
}
|
|
175
|
+
if (risk === "safe" && defaultAction !== "deny") {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
if (!onRequest) {
|
|
179
|
+
if (defaultAction === "allow") {
|
|
180
|
+
return;
|
|
181
|
+
}
|
|
182
|
+
if (defaultAction === "deny") {
|
|
183
|
+
throw new ApprovalDeniedError(tool, args);
|
|
184
|
+
}
|
|
185
|
+
throw new ApprovalDeniedError(tool, args, "No approval handler configured");
|
|
186
|
+
}
|
|
187
|
+
const id = `approval-${++requestCounter}-${Date.now()}`;
|
|
188
|
+
const requestData = {
|
|
189
|
+
id,
|
|
190
|
+
sessionId,
|
|
191
|
+
tool,
|
|
192
|
+
args,
|
|
193
|
+
description: describeApprovalOperation(tool, args),
|
|
194
|
+
risk,
|
|
195
|
+
patterns,
|
|
196
|
+
timestamp: Date.now()
|
|
197
|
+
};
|
|
198
|
+
const ac = new AbortController();
|
|
199
|
+
activeRequests.add(ac);
|
|
200
|
+
let timeoutId;
|
|
201
|
+
try {
|
|
202
|
+
const action = await Promise.race([
|
|
203
|
+
onRequest(requestData),
|
|
204
|
+
new Promise((_, reject) => {
|
|
205
|
+
timeoutId = setTimeout(() => {
|
|
206
|
+
reject(new ApprovalTimeoutError(tool, timeout));
|
|
207
|
+
}, timeout);
|
|
208
|
+
ac.signal.addEventListener("abort", () => {
|
|
209
|
+
clearTimeout(timeoutId);
|
|
210
|
+
reject(new Error("Cancelled"));
|
|
211
|
+
}, { once: true });
|
|
212
|
+
})
|
|
213
|
+
]);
|
|
214
|
+
switch (action) {
|
|
215
|
+
case "allow":
|
|
216
|
+
return;
|
|
217
|
+
case "deny":
|
|
218
|
+
throw new ApprovalDeniedError(tool, args);
|
|
219
|
+
case "remember":
|
|
220
|
+
for (const pattern of patterns) {
|
|
221
|
+
rules.push({ pattern, tool, action: "allow" });
|
|
222
|
+
}
|
|
223
|
+
return;
|
|
224
|
+
}
|
|
225
|
+
} finally {
|
|
226
|
+
clearTimeout(timeoutId);
|
|
227
|
+
activeRequests.delete(ac);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
function cancelAll(_reason) {
|
|
231
|
+
for (const ac of activeRequests) {
|
|
232
|
+
ac.abort();
|
|
233
|
+
}
|
|
234
|
+
activeRequests.clear();
|
|
235
|
+
}
|
|
236
|
+
function addRule(rule) {
|
|
237
|
+
rules.push(rule);
|
|
238
|
+
}
|
|
239
|
+
function getRules() {
|
|
240
|
+
return rules;
|
|
241
|
+
}
|
|
242
|
+
function clearSessionRules() {
|
|
243
|
+
rules.splice(initialRuleCount);
|
|
244
|
+
}
|
|
245
|
+
return {
|
|
246
|
+
request,
|
|
247
|
+
cancelAll,
|
|
248
|
+
addRule,
|
|
249
|
+
getRules,
|
|
250
|
+
clearSessionRules
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
export {
|
|
255
|
+
getToolRisk,
|
|
256
|
+
ApprovalDeniedError,
|
|
257
|
+
ApprovalTimeoutError,
|
|
258
|
+
createApprovalHandler
|
|
259
|
+
};
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
// src/signal/local.ts
|
|
2
|
+
var LocalSignal = class {
|
|
3
|
+
/** type → Set<handler> for typed subscriptions */
|
|
4
|
+
typed = /* @__PURE__ */ new Map();
|
|
5
|
+
/** handlers that receive every event */
|
|
6
|
+
wildcard = /* @__PURE__ */ new Set();
|
|
7
|
+
on(type, handler) {
|
|
8
|
+
let set = this.typed.get(type);
|
|
9
|
+
if (!set) {
|
|
10
|
+
set = /* @__PURE__ */ new Set();
|
|
11
|
+
this.typed.set(type, set);
|
|
12
|
+
}
|
|
13
|
+
const wrapped = (event) => {
|
|
14
|
+
handler(event);
|
|
15
|
+
};
|
|
16
|
+
set.add(wrapped);
|
|
17
|
+
return () => {
|
|
18
|
+
set.delete(wrapped);
|
|
19
|
+
if (set.size === 0) this.typed.delete(type);
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
onAny(handler) {
|
|
23
|
+
this.wildcard.add(handler);
|
|
24
|
+
return () => {
|
|
25
|
+
this.wildcard.delete(handler);
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
emit(event) {
|
|
29
|
+
const set = this.typed.get(event.type);
|
|
30
|
+
if (set) {
|
|
31
|
+
for (const fn of set) {
|
|
32
|
+
try {
|
|
33
|
+
fn(event);
|
|
34
|
+
} catch {
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
for (const fn of this.wildcard) {
|
|
39
|
+
try {
|
|
40
|
+
fn(event);
|
|
41
|
+
} catch {
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
clear() {
|
|
46
|
+
this.typed.clear();
|
|
47
|
+
this.wildcard.clear();
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
LocalSignal
|
|
53
|
+
};
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
// src/presets/builtins.ts
|
|
2
|
+
var explore = {
|
|
3
|
+
name: "explore",
|
|
4
|
+
description: "Read-only exploration mode for understanding content",
|
|
5
|
+
allowTools: ["read*", "search*", "glob*", "grep*", "list*", "find*"],
|
|
6
|
+
denyTools: ["write*", "edit*", "delete*", "bash*", "exec*", "run*"],
|
|
7
|
+
systemPrompt: `{basePrompt}
|
|
8
|
+
|
|
9
|
+
## EXPLORATION MODE
|
|
10
|
+
|
|
11
|
+
You are in **exploration mode**. Your goal is to thoroughly understand the content.
|
|
12
|
+
|
|
13
|
+
Guidelines:
|
|
14
|
+
- **Always start with glob or grep to discover correct paths** \u2014 never assume directory structure
|
|
15
|
+
- Use search and read tools extensively to build understanding
|
|
16
|
+
- Map out structures, dependencies, and patterns
|
|
17
|
+
- Look for conventions, common patterns, and documentation
|
|
18
|
+
- DO NOT modify anything \u2014 only read and analyse
|
|
19
|
+
- Summarise findings clearly with references to specific locations
|
|
20
|
+
|
|
21
|
+
Error recovery:
|
|
22
|
+
- If a tool returns an error (ENOENT, not found, etc.), try a different path or approach
|
|
23
|
+
- Use glob with broader patterns to discover the correct location
|
|
24
|
+
- Keep going until you have a thorough answer \u2014 do not give up after one failure
|
|
25
|
+
- You have multiple steps available \u2014 use them all if needed`,
|
|
26
|
+
temperature: 0.3,
|
|
27
|
+
maxSteps: 30
|
|
28
|
+
};
|
|
29
|
+
var plan = {
|
|
30
|
+
name: "plan",
|
|
31
|
+
description: "Planning mode for analyzing tasks and creating detailed plans",
|
|
32
|
+
allowTools: ["read*", "search*", "glob*", "grep*", "list*", "find*"],
|
|
33
|
+
denyTools: ["write*", "edit*", "delete*", "bash*", "exec*", "run*"],
|
|
34
|
+
systemPrompt: `{basePrompt}
|
|
35
|
+
|
|
36
|
+
## PLANNING MODE
|
|
37
|
+
|
|
38
|
+
You are in **planning mode**. Your goal is to analyze and plan before implementation.
|
|
39
|
+
|
|
40
|
+
Guidelines:
|
|
41
|
+
- Analyse the task requirements thoroughly
|
|
42
|
+
- Research existing patterns and conventions
|
|
43
|
+
- Identify potential impacts and dependencies
|
|
44
|
+
- Create a clear, step-by-step implementation plan
|
|
45
|
+
- DO NOT implement anything \u2014 only plan and document
|
|
46
|
+
- Output a numbered list of specific, actionable steps`,
|
|
47
|
+
temperature: 0.2,
|
|
48
|
+
maxSteps: 20
|
|
49
|
+
};
|
|
50
|
+
var review = {
|
|
51
|
+
name: "review",
|
|
52
|
+
description: "Thorough review and analysis mode",
|
|
53
|
+
allowTools: ["read*", "grep*", "search*", "glob*", "list*"],
|
|
54
|
+
denyTools: ["*"],
|
|
55
|
+
systemPrompt: `{basePrompt}
|
|
56
|
+
|
|
57
|
+
## REVIEW MODE
|
|
58
|
+
|
|
59
|
+
You are in **review mode**. Your goal is to perform a thorough analysis.
|
|
60
|
+
|
|
61
|
+
Review checklist:
|
|
62
|
+
- [ ] Logic errors and edge cases
|
|
63
|
+
- [ ] Security vulnerabilities
|
|
64
|
+
- [ ] Performance issues
|
|
65
|
+
- [ ] Error handling and recovery
|
|
66
|
+
- [ ] Clarity and maintainability
|
|
67
|
+
- [ ] Coverage gaps
|
|
68
|
+
|
|
69
|
+
Guidelines:
|
|
70
|
+
- Be thorough and systematic
|
|
71
|
+
- Cite specific locations and details
|
|
72
|
+
- Explain WHY something is an issue
|
|
73
|
+
- Suggest concrete fixes
|
|
74
|
+
- Rate severity: Critical / High / Medium / Low`,
|
|
75
|
+
temperature: 0.1,
|
|
76
|
+
maxSteps: 25
|
|
77
|
+
};
|
|
78
|
+
var quick = {
|
|
79
|
+
name: "quick",
|
|
80
|
+
description: "Fast mode for simple questions and quick operations",
|
|
81
|
+
systemPrompt: `{basePrompt}
|
|
82
|
+
|
|
83
|
+
## QUICK MODE
|
|
84
|
+
|
|
85
|
+
You are in **quick mode**. Be fast and focused.
|
|
86
|
+
|
|
87
|
+
Guidelines:
|
|
88
|
+
- Answer directly without lengthy explanations
|
|
89
|
+
- Use minimal tool calls (1-3 max)
|
|
90
|
+
- If you can't answer quickly, say so
|
|
91
|
+
- Prioritize speed over thoroughness`,
|
|
92
|
+
temperature: 0,
|
|
93
|
+
maxSteps: 5
|
|
94
|
+
};
|
|
95
|
+
var careful = {
|
|
96
|
+
name: "careful",
|
|
97
|
+
description: "Extra cautious mode for sensitive operations",
|
|
98
|
+
denyTools: ["bash*", "exec*", "run*", "delete*", "remove*"],
|
|
99
|
+
systemPrompt: `{basePrompt}
|
|
100
|
+
|
|
101
|
+
## CAREFUL MODE
|
|
102
|
+
|
|
103
|
+
You are in **careful mode**. Every action must be verified.
|
|
104
|
+
|
|
105
|
+
Guidelines:
|
|
106
|
+
- Double-check before any file modifications
|
|
107
|
+
- Explain what you're about to do BEFORE doing it
|
|
108
|
+
- Prefer smaller, incremental changes
|
|
109
|
+
- Always verify changes after making them
|
|
110
|
+
- If uncertain, ask for clarification rather than guessing`,
|
|
111
|
+
temperature: 0,
|
|
112
|
+
maxSteps: 50
|
|
113
|
+
};
|
|
114
|
+
var code = {
|
|
115
|
+
name: "code",
|
|
116
|
+
description: "Full-power implementation mode for writing and modifying code",
|
|
117
|
+
systemPrompt: `{basePrompt}
|
|
118
|
+
|
|
119
|
+
## IMPLEMENTATION MODE
|
|
120
|
+
|
|
121
|
+
You are a focused **implementation agent**. Your goal is to complete the assigned task fully and correctly.
|
|
122
|
+
|
|
123
|
+
Guidelines:
|
|
124
|
+
- Read existing code first to understand context and conventions before making changes
|
|
125
|
+
- Follow the project's existing patterns, naming conventions, and style
|
|
126
|
+
- Make minimal, targeted changes \u2014 do not refactor unrelated code
|
|
127
|
+
- Verify your work: re-read modified files, run tests or lint if available
|
|
128
|
+
- If the task requires multiple files, handle them systematically one at a time
|
|
129
|
+
|
|
130
|
+
Error recovery:
|
|
131
|
+
- If a command fails, read the error output carefully and fix the root cause
|
|
132
|
+
- If a test fails, read the failure details and iterate until it passes
|
|
133
|
+
- If you cannot find a file, use glob or grep to discover the correct path
|
|
134
|
+
- Keep iterating until the task is DONE \u2014 do not stop at a partial solution
|
|
135
|
+
- You have many steps available \u2014 use them all if needed`,
|
|
136
|
+
temperature: 0,
|
|
137
|
+
maxSteps: 50
|
|
138
|
+
};
|
|
139
|
+
var watch = {
|
|
140
|
+
name: "watch",
|
|
141
|
+
description: "Process monitoring mode for running and watching long commands",
|
|
142
|
+
allowTools: ["bash*", "exec*", "run*", "read*", "grep*", "glob*", "list*", "find*"],
|
|
143
|
+
denyTools: ["write*", "edit*", "delete*", "remove*"],
|
|
144
|
+
systemPrompt: `{basePrompt}
|
|
145
|
+
|
|
146
|
+
## WATCH MODE
|
|
147
|
+
|
|
148
|
+
You are a **process monitor**. Your goal is to execute a command, observe its output, and report the result.
|
|
149
|
+
|
|
150
|
+
Guidelines:
|
|
151
|
+
- Run the command as given \u2014 do not modify or "improve" it
|
|
152
|
+
- Wait for completion and capture the full output
|
|
153
|
+
- Parse the output for success/failure status, error counts, warnings
|
|
154
|
+
- Report a clear summary: what ran, whether it passed, key details
|
|
155
|
+
- If the process fails, include the relevant error output verbatim
|
|
156
|
+
- Do NOT attempt to fix issues \u2014 only observe and report`,
|
|
157
|
+
temperature: 0,
|
|
158
|
+
maxSteps: 10,
|
|
159
|
+
reasoningLevel: "low"
|
|
160
|
+
};
|
|
161
|
+
var Presets = {
|
|
162
|
+
explore,
|
|
163
|
+
plan,
|
|
164
|
+
review,
|
|
165
|
+
quick,
|
|
166
|
+
careful,
|
|
167
|
+
code,
|
|
168
|
+
watch
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
export {
|
|
172
|
+
explore,
|
|
173
|
+
plan,
|
|
174
|
+
review,
|
|
175
|
+
quick,
|
|
176
|
+
careful,
|
|
177
|
+
code,
|
|
178
|
+
watch,
|
|
179
|
+
Presets
|
|
180
|
+
};
|