@anthropic-ai/sdk 0.116.0 → 0.118.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/CHANGELOG.md +67 -0
- package/client.d.mts +2 -2
- package/client.d.mts.map +1 -1
- package/client.d.ts +2 -2
- package/client.d.ts.map +1 -1
- package/client.js +1 -1
- package/client.js.map +1 -1
- package/client.mjs +1 -1
- package/client.mjs.map +1 -1
- package/core/api-promise.d.mts +1 -0
- package/core/api-promise.d.mts.map +1 -1
- package/core/api-promise.d.ts +1 -0
- package/core/api-promise.d.ts.map +1 -1
- package/core/api-promise.js +7 -2
- package/core/api-promise.js.map +1 -1
- package/core/api-promise.mjs +8 -3
- package/core/api-promise.mjs.map +1 -1
- package/core/error.d.mts +1 -0
- package/core/error.d.mts.map +1 -1
- package/core/error.d.ts +1 -0
- package/core/error.d.ts.map +1 -1
- package/core/error.js +1 -0
- package/core/error.js.map +1 -1
- package/core/error.mjs +1 -0
- package/core/error.mjs.map +1 -1
- package/core/middleware.js +1 -1
- package/core/middleware.js.map +1 -1
- package/core/middleware.mjs +2 -2
- package/core/middleware.mjs.map +1 -1
- package/helpers/beta/zod.d.mts.map +1 -1
- package/helpers/beta/zod.d.ts.map +1 -1
- package/helpers/beta/zod.js +1 -2
- package/helpers/beta/zod.js.map +1 -1
- package/helpers/beta/zod.mjs +1 -2
- package/helpers/beta/zod.mjs.map +1 -1
- package/helpers/zod.d.mts.map +1 -1
- package/helpers/zod.d.ts.map +1 -1
- package/helpers/zod.js +1 -2
- package/helpers/zod.js.map +1 -1
- package/helpers/zod.mjs +1 -2
- package/helpers/zod.mjs.map +1 -1
- package/internal/parse.d.mts +2 -1
- package/internal/parse.d.mts.map +1 -1
- package/internal/parse.d.ts +2 -1
- package/internal/parse.d.ts.map +1 -1
- package/internal/parse.js +6 -6
- package/internal/parse.js.map +1 -1
- package/internal/parse.mjs +5 -5
- package/internal/parse.mjs.map +1 -1
- package/lib/BetaMessageStream.d.mts +2 -0
- package/lib/BetaMessageStream.d.mts.map +1 -1
- package/lib/BetaMessageStream.d.ts +2 -0
- package/lib/BetaMessageStream.d.ts.map +1 -1
- package/lib/BetaMessageStream.js +20 -7
- package/lib/BetaMessageStream.js.map +1 -1
- package/lib/BetaMessageStream.mjs +20 -7
- package/lib/BetaMessageStream.mjs.map +1 -1
- package/lib/MessageStream.d.mts +2 -0
- package/lib/MessageStream.d.mts.map +1 -1
- package/lib/MessageStream.d.ts +2 -0
- package/lib/MessageStream.d.ts.map +1 -1
- package/lib/MessageStream.js +17 -6
- package/lib/MessageStream.js.map +1 -1
- package/lib/MessageStream.mjs +17 -6
- package/lib/MessageStream.mjs.map +1 -1
- package/lib/environments/worker.d.mts +10 -6
- package/lib/environments/worker.d.mts.map +1 -1
- package/lib/environments/worker.d.ts +10 -6
- package/lib/environments/worker.d.ts.map +1 -1
- package/lib/environments/worker.js +51 -18
- package/lib/environments/worker.js.map +1 -1
- package/lib/environments/worker.mjs +51 -18
- package/lib/environments/worker.mjs.map +1 -1
- package/lib/tools/BetaRunnableTool.d.mts +20 -42
- package/lib/tools/BetaRunnableTool.d.mts.map +1 -1
- package/lib/tools/BetaRunnableTool.d.ts +20 -42
- package/lib/tools/BetaRunnableTool.d.ts.map +1 -1
- package/lib/tools/BetaRunnableTool.js +3 -17
- package/lib/tools/BetaRunnableTool.js.map +1 -1
- package/lib/tools/BetaRunnableTool.mjs +3 -17
- package/lib/tools/BetaRunnableTool.mjs.map +1 -1
- package/lib/tools/BetaToolRunner.d.mts.map +1 -1
- package/lib/tools/BetaToolRunner.d.ts.map +1 -1
- package/lib/tools/BetaToolRunner.js +11 -12
- package/lib/tools/BetaToolRunner.js.map +1 -1
- package/lib/tools/BetaToolRunner.mjs +11 -12
- package/lib/tools/BetaToolRunner.mjs.map +1 -1
- package/lib/tools/SessionToolRunner.d.mts +6 -0
- package/lib/tools/SessionToolRunner.d.mts.map +1 -1
- package/lib/tools/SessionToolRunner.d.ts +6 -0
- package/lib/tools/SessionToolRunner.d.ts.map +1 -1
- package/lib/tools/SessionToolRunner.js +37 -8
- package/lib/tools/SessionToolRunner.js.map +1 -1
- package/lib/tools/SessionToolRunner.mjs +38 -9
- package/lib/tools/SessionToolRunner.mjs.map +1 -1
- package/package.json +9 -15
- package/resources/beta/agents/agents.d.mts +3 -3
- package/resources/beta/agents/agents.d.ts +3 -3
- package/resources/beta/agents/agents.js +1 -1
- package/resources/beta/agents/agents.mjs +1 -1
- package/resources/beta/beta.d.mts +5 -5
- package/resources/beta/beta.d.mts.map +1 -1
- package/resources/beta/beta.d.ts +5 -5
- package/resources/beta/beta.d.ts.map +1 -1
- package/resources/beta/beta.js.map +1 -1
- package/resources/beta/beta.mjs.map +1 -1
- package/resources/beta/dreams.d.mts +48 -8
- package/resources/beta/dreams.d.mts.map +1 -1
- package/resources/beta/dreams.d.ts +48 -8
- package/resources/beta/dreams.d.ts.map +1 -1
- package/resources/beta/environments/environments.d.mts +4 -3
- package/resources/beta/environments/environments.d.mts.map +1 -1
- package/resources/beta/environments/environments.d.ts +4 -3
- package/resources/beta/environments/environments.d.ts.map +1 -1
- package/resources/beta/environments/environments.js.map +1 -1
- package/resources/beta/environments/environments.mjs.map +1 -1
- package/resources/beta/index.d.mts +2 -2
- package/resources/beta/index.d.mts.map +1 -1
- package/resources/beta/index.d.ts +2 -2
- package/resources/beta/index.d.ts.map +1 -1
- package/resources/beta/index.js.map +1 -1
- package/resources/beta/index.mjs.map +1 -1
- package/resources/beta/memory-stores/index.d.mts +1 -1
- package/resources/beta/memory-stores/index.d.mts.map +1 -1
- package/resources/beta/memory-stores/index.d.ts +1 -1
- package/resources/beta/memory-stores/index.d.ts.map +1 -1
- package/resources/beta/memory-stores/index.js.map +1 -1
- package/resources/beta/memory-stores/index.mjs.map +1 -1
- package/resources/beta/memory-stores/memory-stores.d.mts +2 -2
- package/resources/beta/memory-stores/memory-stores.d.mts.map +1 -1
- package/resources/beta/memory-stores/memory-stores.d.ts +2 -2
- package/resources/beta/memory-stores/memory-stores.d.ts.map +1 -1
- package/resources/beta/memory-stores/memory-stores.js.map +1 -1
- package/resources/beta/memory-stores/memory-stores.mjs.map +1 -1
- package/resources/beta/memory-stores/memory-versions.d.mts +17 -2
- package/resources/beta/memory-stores/memory-versions.d.mts.map +1 -1
- package/resources/beta/memory-stores/memory-versions.d.ts +17 -2
- package/resources/beta/memory-stores/memory-versions.d.ts.map +1 -1
- package/resources/beta/messages/batches.d.mts +1 -1
- package/resources/beta/messages/batches.d.ts +1 -1
- package/resources/beta/messages/batches.js +1 -1
- package/resources/beta/messages/batches.mjs +1 -1
- package/resources/beta/messages/index.d.mts +1 -1
- package/resources/beta/messages/index.d.mts.map +1 -1
- package/resources/beta/messages/index.d.ts +1 -1
- package/resources/beta/messages/index.d.ts.map +1 -1
- package/resources/beta/messages/index.js.map +1 -1
- package/resources/beta/messages/index.mjs.map +1 -1
- package/resources/beta/messages/messages.d.mts +4 -22
- package/resources/beta/messages/messages.d.mts.map +1 -1
- package/resources/beta/messages/messages.d.ts +4 -22
- package/resources/beta/messages/messages.d.ts.map +1 -1
- package/resources/beta/messages/messages.js +2 -2
- package/resources/beta/messages/messages.js.map +1 -1
- package/resources/beta/messages/messages.mjs +2 -2
- package/resources/beta/messages/messages.mjs.map +1 -1
- package/resources/beta/sessions/sessions.d.mts +1 -1
- package/resources/beta/sessions/sessions.d.ts +1 -1
- package/resources/beta/user-profiles.d.mts +37 -11
- package/resources/beta/user-profiles.d.mts.map +1 -1
- package/resources/beta/user-profiles.d.ts +37 -11
- package/resources/beta/user-profiles.d.ts.map +1 -1
- package/resources/beta/user-profiles.js +5 -5
- package/resources/beta/user-profiles.mjs +5 -5
- package/resources/index.d.mts +1 -1
- package/resources/index.d.mts.map +1 -1
- package/resources/index.d.ts +1 -1
- package/resources/index.d.ts.map +1 -1
- package/resources/index.js.map +1 -1
- package/resources/index.mjs.map +1 -1
- package/resources/messages/batches.d.mts +1 -1
- package/resources/messages/batches.d.ts +1 -1
- package/resources/messages/batches.js +1 -1
- package/resources/messages/batches.mjs +1 -1
- package/resources/messages/index.d.mts +1 -1
- package/resources/messages/index.d.mts.map +1 -1
- package/resources/messages/index.d.ts +1 -1
- package/resources/messages/index.d.ts.map +1 -1
- package/resources/messages/index.js.map +1 -1
- package/resources/messages/index.mjs.map +1 -1
- package/resources/messages/messages.d.mts +4 -22
- package/resources/messages/messages.d.mts.map +1 -1
- package/resources/messages/messages.d.ts +4 -22
- package/resources/messages/messages.d.ts.map +1 -1
- package/resources/messages/messages.js +2 -2
- package/resources/messages/messages.js.map +1 -1
- package/resources/messages/messages.mjs +2 -2
- package/resources/messages/messages.mjs.map +1 -1
- package/src/client.ts +1 -3
- package/src/core/api-promise.ts +14 -4
- package/src/core/error.ts +2 -0
- package/src/core/middleware.ts +2 -2
- package/src/helpers/beta/zod.ts +1 -3
- package/src/helpers/zod.ts +1 -3
- package/src/internal/parse.ts +6 -6
- package/src/lib/BetaMessageStream.ts +23 -5
- package/src/lib/MessageStream.ts +19 -4
- package/src/lib/environments/worker.ts +56 -17
- package/src/lib/tools/BetaRunnableTool.ts +20 -44
- package/src/lib/tools/BetaToolRunner.ts +11 -12
- package/src/lib/tools/SessionToolRunner.ts +39 -6
- package/src/resources/beta/agents/agents.ts +3 -3
- package/src/resources/beta/beta.ts +7 -2
- package/src/resources/beta/dreams.ts +56 -7
- package/src/resources/beta/environments/environments.ts +4 -3
- package/src/resources/beta/index.ts +3 -1
- package/src/resources/beta/memory-stores/index.ts +1 -0
- package/src/resources/beta/memory-stores/memory-stores.ts +2 -0
- package/src/resources/beta/memory-stores/memory-versions.ts +21 -1
- package/src/resources/beta/messages/batches.ts +1 -1
- package/src/resources/beta/messages/index.ts +0 -1
- package/src/resources/beta/messages/messages.ts +3 -26
- package/src/resources/beta/sessions/sessions.ts +1 -1
- package/src/resources/beta/user-profiles.ts +46 -17
- package/src/resources/index.ts +0 -1
- package/src/resources/messages/batches.ts +1 -1
- package/src/resources/messages/index.ts +0 -1
- package/src/resources/messages/messages.ts +4 -27
- package/src/tools/agent-toolset/fs-util.ts +43 -23
- package/src/tools/agent-toolset/node.ts +1 -1
- package/src/tools/agent-toolset/skills.ts +127 -31
- package/src/version.ts +1 -1
- package/tools/agent-toolset/fs-util.d.mts +14 -2
- package/tools/agent-toolset/fs-util.d.mts.map +1 -1
- package/tools/agent-toolset/fs-util.d.ts +14 -2
- package/tools/agent-toolset/fs-util.d.ts.map +1 -1
- package/tools/agent-toolset/fs-util.js +46 -24
- package/tools/agent-toolset/fs-util.js.map +1 -1
- package/tools/agent-toolset/fs-util.mjs +45 -24
- package/tools/agent-toolset/fs-util.mjs.map +1 -1
- package/tools/agent-toolset/node.js +1 -1
- package/tools/agent-toolset/node.js.map +1 -1
- package/tools/agent-toolset/node.mjs +1 -1
- package/tools/agent-toolset/node.mjs.map +1 -1
- package/tools/agent-toolset/skills.d.mts +26 -3
- package/tools/agent-toolset/skills.d.mts.map +1 -1
- package/tools/agent-toolset/skills.d.ts +26 -3
- package/tools/agent-toolset/skills.d.ts.map +1 -1
- package/tools/agent-toolset/skills.js +114 -29
- package/tools/agent-toolset/skills.js.map +1 -1
- package/tools/agent-toolset/skills.mjs +113 -30
- package/tools/agent-toolset/skills.mjs.map +1 -1
- package/version.d.mts +1 -1
- package/version.d.ts +1 -1
- package/version.js +1 -1
- package/version.mjs +1 -1
|
@@ -51,7 +51,7 @@ export class Messages extends APIResource {
|
|
|
51
51
|
* const message = await client.messages.create({
|
|
52
52
|
* max_tokens: 1024,
|
|
53
53
|
* messages: [{ content: 'Hello, world', role: 'user' }],
|
|
54
|
-
* model: 'claude-opus-
|
|
54
|
+
* model: 'claude-opus-5',
|
|
55
55
|
* });
|
|
56
56
|
* ```
|
|
57
57
|
*/
|
|
@@ -86,7 +86,7 @@ export class Messages extends APIResource {
|
|
|
86
86
|
);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
-
let timeout = (this._client as any)._options.timeout as number | null;
|
|
89
|
+
let timeout = options?.timeout ?? ((this._client as any)._options.timeout as number | null);
|
|
90
90
|
if (!body.stream && timeout == null) {
|
|
91
91
|
const maxNonstreamingTokens = MODEL_NONSTREAMING_TOKENS[body.model] ?? undefined;
|
|
92
92
|
timeout = this._client.calculateNonstreamingTimeout(body.max_tokens, maxNonstreamingTokens);
|
|
@@ -181,7 +181,7 @@ export class Messages extends APIResource {
|
|
|
181
181
|
* const messageTokensCount =
|
|
182
182
|
* await client.messages.countTokens({
|
|
183
183
|
* messages: [{ content: 'Hello, world', role: 'user' }],
|
|
184
|
-
* model: 'claude-opus-
|
|
184
|
+
* model: 'claude-opus-5',
|
|
185
185
|
* });
|
|
186
186
|
* ```
|
|
187
187
|
*/
|
|
@@ -877,8 +877,7 @@ export type ContentBlockParam =
|
|
|
877
877
|
| BashCodeExecutionToolResultBlockParam
|
|
878
878
|
| TextEditorCodeExecutionToolResultBlockParam
|
|
879
879
|
| ToolSearchToolResultBlockParam
|
|
880
|
-
| ContainerUploadBlockParam
|
|
881
|
-
| MidConversationSystemBlockParam;
|
|
880
|
+
| ContainerUploadBlockParam;
|
|
882
881
|
|
|
883
882
|
export interface ContentBlockSource {
|
|
884
883
|
content: string | Array<ContentBlockSourceContent>;
|
|
@@ -1229,27 +1228,6 @@ export interface Metadata {
|
|
|
1229
1228
|
user_id?: string | null;
|
|
1230
1229
|
}
|
|
1231
1230
|
|
|
1232
|
-
/**
|
|
1233
|
-
* System instructions that appear mid-conversation.
|
|
1234
|
-
*
|
|
1235
|
-
* Use this block to provide or update system-level instructions at a specific
|
|
1236
|
-
* point in the conversation, rather than only via the top-level `system`
|
|
1237
|
-
* parameter.
|
|
1238
|
-
*/
|
|
1239
|
-
export interface MidConversationSystemBlockParam {
|
|
1240
|
-
/**
|
|
1241
|
-
* System instruction text blocks.
|
|
1242
|
-
*/
|
|
1243
|
-
content: Array<TextBlockParam>;
|
|
1244
|
-
|
|
1245
|
-
type: 'mid_conv_system';
|
|
1246
|
-
|
|
1247
|
-
/**
|
|
1248
|
-
* Create a cache control breakpoint at this content block.
|
|
1249
|
-
*/
|
|
1250
|
-
cache_control?: CacheControlEphemeral | null;
|
|
1251
|
-
}
|
|
1252
|
-
|
|
1253
1231
|
/**
|
|
1254
1232
|
* The model that will complete your prompt.
|
|
1255
1233
|
*
|
|
@@ -3690,7 +3668,6 @@ export declare namespace Messages {
|
|
|
3690
3668
|
type MessageParam as MessageParam,
|
|
3691
3669
|
type MessageTokensCount as MessageTokensCount,
|
|
3692
3670
|
type Metadata as Metadata,
|
|
3693
|
-
type MidConversationSystemBlockParam as MidConversationSystemBlockParam,
|
|
3694
3671
|
type Model as Model,
|
|
3695
3672
|
type OutputConfig as OutputConfig,
|
|
3696
3673
|
type OutputTokensDetails as OutputTokensDetails,
|
|
@@ -24,12 +24,27 @@ async function realpathOrSelf(p: string): Promise<string> {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
|
|
27
|
+
/** Matches Linux MAXSYMLINKS, the threshold at which `realpath` itself reports ELOOP. */
|
|
28
|
+
const MAX_SYMLINK_HOPS = 40;
|
|
29
|
+
|
|
30
|
+
/** The `code` of a Node system error, or `undefined` for anything else. */
|
|
31
|
+
export function errnoCode(err: unknown): string | undefined {
|
|
32
|
+
const code = (err as { code?: unknown } | null)?.code;
|
|
33
|
+
return typeof code === 'string' ? code : undefined;
|
|
34
|
+
}
|
|
35
|
+
|
|
27
36
|
/**
|
|
28
37
|
* Fully resolve `abs`: `realpath` the longest existing ancestor and re-append
|
|
29
38
|
* the rest, but never re-append a component that is itself a symlink — read the
|
|
30
39
|
* link and continue from its target instead. This handles paths being created
|
|
31
40
|
* (write/edit) without letting a symlink leaf (e.g. a dangling one pointing
|
|
32
41
|
* outside a confinement root) slip through unresolved.
|
|
42
|
+
*
|
|
43
|
+
* Returns a symlink-free path or throws an errno-carrying error (`ELOOP` for a
|
|
44
|
+
* cycle or more than {@link MAX_SYMLINK_HOPS} links, the `lstat`/`realpath`
|
|
45
|
+
* error for an unreadable component); it never returns `abs` unresolved. Only
|
|
46
|
+
* symlink hops count against the cap, so any depth of not-yet-existing
|
|
47
|
+
* directories still resolves.
|
|
33
48
|
*/
|
|
34
49
|
export async function canonicalize(abs: string): Promise<string> {
|
|
35
50
|
const tail: string[] = [];
|
|
@@ -39,28 +54,24 @@ export async function canonicalize(abs: string): Promise<string> {
|
|
|
39
54
|
let real: string;
|
|
40
55
|
try {
|
|
41
56
|
real = await fs.realpath(prefix);
|
|
42
|
-
} catch {
|
|
43
|
-
let isLink
|
|
57
|
+
} catch (realpathErr) {
|
|
58
|
+
let isLink: boolean;
|
|
44
59
|
try {
|
|
45
60
|
isLink = (await fs.lstat(prefix)).isSymbolicLink();
|
|
46
|
-
} catch {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
// have returned ELOOP — so a cycle of unresolvable links terminates.
|
|
54
|
-
if (++hops > 40) {
|
|
55
|
-
throw new ToolError(`path ${JSON.stringify(abs)} has too many levels of symbolic links`);
|
|
56
|
-
}
|
|
57
|
-
prefix = path.resolve(path.dirname(prefix), await fs.readlink(prefix));
|
|
61
|
+
} catch (lstatErr) {
|
|
62
|
+
const code = errnoCode(lstatErr);
|
|
63
|
+
if (code !== 'ENOENT' && code !== 'ENOTDIR') throw lstatErr;
|
|
64
|
+
const parent = path.dirname(prefix);
|
|
65
|
+
if (parent === prefix) throw lstatErr;
|
|
66
|
+
tail.push(path.basename(prefix));
|
|
67
|
+
prefix = parent;
|
|
58
68
|
continue;
|
|
59
69
|
}
|
|
60
|
-
|
|
61
|
-
if (
|
|
62
|
-
|
|
63
|
-
|
|
70
|
+
if (!isLink) throw realpathErr;
|
|
71
|
+
if (++hops > MAX_SYMLINK_HOPS) {
|
|
72
|
+
throw Object.assign(new Error('too many levels of symbolic links'), { code: 'ELOOP' });
|
|
73
|
+
}
|
|
74
|
+
prefix = path.resolve(path.dirname(prefix), await fs.readlink(prefix));
|
|
64
75
|
continue;
|
|
65
76
|
}
|
|
66
77
|
return tail.length ? path.join(real, ...tail.reverse()) : real;
|
|
@@ -76,6 +87,9 @@ export async function canonicalize(abs: string): Promise<string> {
|
|
|
76
87
|
* leaf, even a dangling one) is resolved before the confinement check, and the
|
|
77
88
|
* resolved path is what the caller then operates on, so a symlink inside `root`
|
|
78
89
|
* that points outside it can neither pass the check nor be followed afterwards.
|
|
90
|
+
* `..` is collapsed lexically before any symlink is followed. A path that cannot
|
|
91
|
+
* be resolved (symlink loop, unreadable component) is rejected with a
|
|
92
|
+
* `ToolError` naming `p`, never the host's absolute path.
|
|
79
93
|
*
|
|
80
94
|
* Residual TOCTOU: a component could still be swapped for a symlink between this
|
|
81
95
|
* call and the eventual `fs` operation. Closing that fully needs per-component
|
|
@@ -91,7 +105,12 @@ export async function confineToRoot(
|
|
|
91
105
|
const realRoot = await realpathOrSelf(path.resolve(root));
|
|
92
106
|
const abs = path.resolve(realRoot, p);
|
|
93
107
|
if (allowOutside) return abs;
|
|
94
|
-
|
|
108
|
+
let real: string;
|
|
109
|
+
try {
|
|
110
|
+
real = await canonicalize(abs);
|
|
111
|
+
} catch (err) {
|
|
112
|
+
throw new ToolError(fsErrorMessage(err, `path ${JSON.stringify(p)}`));
|
|
113
|
+
}
|
|
95
114
|
if (real !== realRoot && !real.startsWith(realRoot + path.sep)) {
|
|
96
115
|
throw new ToolError(`path ${JSON.stringify(p)} escapes workdir`);
|
|
97
116
|
}
|
|
@@ -124,11 +143,12 @@ export async function atomicWriteFile(targetPath: string, content: string): Prom
|
|
|
124
143
|
/**
|
|
125
144
|
* Map a thrown filesystem error to a consistent, language-independent message,
|
|
126
145
|
* so the model sees the same wording regardless of the runtime (Node's raw
|
|
127
|
-
* `ENOENT: no such file...` text would otherwise leak through).
|
|
128
|
-
*
|
|
146
|
+
* `ENOENT: no such file...` text would otherwise leak through). Codes we don't
|
|
147
|
+
* special-case render as the bare code, never Node's message, which embeds the
|
|
148
|
+
* host's absolute path.
|
|
129
149
|
*/
|
|
130
150
|
export function fsErrorMessage(err: unknown, file: string): string {
|
|
131
|
-
const code = (err
|
|
151
|
+
const code = errnoCode(err);
|
|
132
152
|
switch (code) {
|
|
133
153
|
case 'ENOENT':
|
|
134
154
|
return `${file}: no such file or directory`;
|
|
@@ -149,6 +169,6 @@ export function fsErrorMessage(err: unknown, file: string): string {
|
|
|
149
169
|
case 'ENFILE':
|
|
150
170
|
return `${file}: too many open files`;
|
|
151
171
|
default:
|
|
152
|
-
return `${file}: ${
|
|
172
|
+
return `${file}: ${code !== undefined ? `i/o error (${code})` : 'i/o error'}`;
|
|
153
173
|
}
|
|
154
174
|
}
|
|
@@ -470,7 +470,7 @@ export function betaReadTool(ctx: AgentToolContext): BetaRunnableTool {
|
|
|
470
470
|
if (e instanceof ToolError) throw e;
|
|
471
471
|
throw new ToolError(`read: ${fsErrorMessage(e, file_path)}`);
|
|
472
472
|
}
|
|
473
|
-
if (!view_range) return data;
|
|
473
|
+
if (!view_range?.length) return data;
|
|
474
474
|
if (view_range.length !== 2) throw new ToolError('read: view_range must be [start_line, end_line]');
|
|
475
475
|
const [startLine, endLine] = view_range as [number, number];
|
|
476
476
|
const lines = data.split('\n');
|
|
@@ -15,7 +15,7 @@ import { pipeline } from 'node:stream/promises';
|
|
|
15
15
|
import type { Anthropic } from '../../client';
|
|
16
16
|
import { AnthropicError } from '../../core/error';
|
|
17
17
|
import { loggerFor } from '../../internal/utils/log';
|
|
18
|
-
import { DIR_CREATE_MODE } from './fs-util';
|
|
18
|
+
import { DIR_CREATE_MODE, errnoCode } from './fs-util';
|
|
19
19
|
import type { AgentToolContext } from './node';
|
|
20
20
|
|
|
21
21
|
const execFileAsync = promisify(execFile);
|
|
@@ -115,8 +115,8 @@ export async function resolveSkillVersion(
|
|
|
115
115
|
}
|
|
116
116
|
|
|
117
117
|
/** Reject archive members that are absolute or contain a `..` component. */
|
|
118
|
-
function assertSafeMemberNames(names: string): void {
|
|
119
|
-
for (const raw of names
|
|
118
|
+
function assertSafeMemberNames(names: string[]): void {
|
|
119
|
+
for (const raw of names) {
|
|
120
120
|
const entry = raw.trim();
|
|
121
121
|
if (!entry) continue;
|
|
122
122
|
if (path.isAbsolute(entry) || entry.split(/[\\/]/).includes('..')) {
|
|
@@ -125,19 +125,77 @@ function assertSafeMemberNames(names: string): void {
|
|
|
125
125
|
}
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
const INCONSISTENT_LISTING = 'skill archive listing is inconsistent; refusing to extract';
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Type chars (first byte of each `ls`-style line from `unzip -Z` / `tar -tvf`)
|
|
132
|
+
* that denote a regular file or directory. `zipinfo` prints `?` for entries
|
|
133
|
+
* with no Unix type bits, which `unzip` extracts as regular files; GNU tar
|
|
134
|
+
* prints `C` for contiguous files. Everything else — `l` symlink, `h`
|
|
135
|
+
* hardlink, `b`/`c` device, `p` fifo, `s` socket, unknown tar types — is a
|
|
136
|
+
* special member.
|
|
137
|
+
*/
|
|
138
|
+
const PLAIN_TYPE_CHARS = { unzip: new Set(['-', 'd', '?']), tar: new Set(['-', 'd', 'C']) };
|
|
139
|
+
|
|
140
|
+
function listingLines(listing: string): string[] {
|
|
141
|
+
const lines = listing.split('\n');
|
|
142
|
+
if (lines[lines.length - 1] === '') lines.pop();
|
|
143
|
+
return lines;
|
|
144
|
+
}
|
|
145
|
+
|
|
128
146
|
/**
|
|
129
|
-
*
|
|
130
|
-
*
|
|
131
|
-
*
|
|
132
|
-
* `
|
|
133
|
-
*
|
|
147
|
+
* A special member is excluded by handing its listed name back to the CLI as
|
|
148
|
+
* a pattern, so the name must be byte-identical to what is stored. `tar`,
|
|
149
|
+
* `bsdtar` and `unzip` print bytes they cannot show literally as `\ooo`, `^X`
|
|
150
|
+
* or `#U` escapes, or as raw non-ASCII; any such name cannot be excluded
|
|
151
|
+
* reliably. A leading `-` would let `unzip` parse the pattern as an option.
|
|
134
152
|
*/
|
|
135
|
-
function
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
153
|
+
function canExcludeVerbatim(cmd: 'unzip' | 'tar', name: string): boolean {
|
|
154
|
+
return /^[\x20-\x7E]+$/.test(name) && !/[\\^#]/.test(name) && !(cmd === 'unzip' && name.startsWith('-'));
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Pair an archive's name listing (`unzip -Z1` / `tar -tf`) with its typed
|
|
159
|
+
* listing (`unzip -Z --h --t` / `tar -tvf`) and split the members into plain
|
|
160
|
+
* (regular file or directory) and special (everything else). Special members
|
|
161
|
+
* are excluded from extraction rather than rejected; the archive is refused
|
|
162
|
+
* only when the two listings disagree in length or a special member's name
|
|
163
|
+
* cannot be passed back to the CLI verbatim (see {@link canExcludeVerbatim}).
|
|
164
|
+
*/
|
|
165
|
+
export function classifyArchiveListing(
|
|
166
|
+
cmd: 'unzip' | 'tar',
|
|
167
|
+
names: string,
|
|
168
|
+
typed: string,
|
|
169
|
+
): { plain: string[]; special: string[] } {
|
|
170
|
+
const nameLines = listingLines(names);
|
|
171
|
+
const typedLines = listingLines(typed);
|
|
172
|
+
if (nameLines.length !== typedLines.length) throw new AnthropicError(INCONSISTENT_LISTING);
|
|
173
|
+
const plain: string[] = [];
|
|
174
|
+
const special: string[] = [];
|
|
175
|
+
nameLines.forEach((name, i) => {
|
|
176
|
+
if (PLAIN_TYPE_CHARS[cmd].has(typedLines[i]!.charAt(0))) {
|
|
177
|
+
plain.push(name);
|
|
178
|
+
return;
|
|
140
179
|
}
|
|
180
|
+
if (!canExcludeVerbatim(cmd, name)) {
|
|
181
|
+
throw new AnthropicError(
|
|
182
|
+
`refusing to extract archive: cannot safely exclude member ${JSON.stringify(name)}`,
|
|
183
|
+
);
|
|
184
|
+
}
|
|
185
|
+
special.push(name);
|
|
186
|
+
});
|
|
187
|
+
return { plain, special };
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Walk `dir` with `lstat` semantics and reject anything that is not a regular
|
|
192
|
+
* file or directory. Never follows a link and never descends into anything
|
|
193
|
+
* but a real directory.
|
|
194
|
+
*/
|
|
195
|
+
export async function assertOnlyPlainEntries(dir: string): Promise<void> {
|
|
196
|
+
for (const entry of await fs.readdir(dir, { withFileTypes: true })) {
|
|
197
|
+
if (entry.isDirectory()) await assertOnlyPlainEntries(path.join(dir, entry.name));
|
|
198
|
+
else if (!entry.isFile()) throw new AnthropicError(INCONSISTENT_LISTING);
|
|
141
199
|
}
|
|
142
200
|
}
|
|
143
201
|
|
|
@@ -152,7 +210,7 @@ async function runArchiveTool(cmd: 'unzip' | 'tar', args: string[]): Promise<str
|
|
|
152
210
|
const { stdout } = await execFileAsync(cmd, args);
|
|
153
211
|
return stdout;
|
|
154
212
|
} catch (e) {
|
|
155
|
-
if (
|
|
213
|
+
if (errnoCode(e) === 'ENOENT') {
|
|
156
214
|
throw new AnthropicError(
|
|
157
215
|
`skill extraction requires the \`${cmd}\` command, but it was not found on PATH`,
|
|
158
216
|
);
|
|
@@ -162,17 +220,17 @@ async function runArchiveTool(cmd: 'unzip' | 'tar', args: string[]): Promise<str
|
|
|
162
220
|
}
|
|
163
221
|
|
|
164
222
|
/**
|
|
165
|
-
* The single top-level directory shared by every entry in
|
|
166
|
-
*
|
|
167
|
-
*
|
|
168
|
-
*
|
|
169
|
-
*
|
|
170
|
-
*
|
|
223
|
+
* The single top-level directory shared by every entry in an archive listing,
|
|
224
|
+
* or `''` if entries don't all live under one common directory. Skill bundles
|
|
225
|
+
* are packaged wrapped in one directory named after the skill (e.g.
|
|
226
|
+
* `pdf/SKILL.md`, `pdf/scripts/...`); the extractor strips it so contents land
|
|
227
|
+
* directly in the skill's dir instead of a redundant nested `<skill>/<skill>/`
|
|
228
|
+
* level. A flat or multi-root archive yields `''`.
|
|
171
229
|
*/
|
|
172
|
-
function archiveTopDir(
|
|
230
|
+
function archiveTopDir(names: string[]): string {
|
|
173
231
|
let top: string | undefined;
|
|
174
232
|
let nested = false;
|
|
175
|
-
for (const raw of
|
|
233
|
+
for (const raw of names) {
|
|
176
234
|
// Drop `.` / empty segments so a `./pdf/...`-style listing (e.g. from
|
|
177
235
|
// `tar -C dir .`) is treated the same as `pdf/...`.
|
|
178
236
|
const parts = raw
|
|
@@ -195,9 +253,14 @@ function archiveTopDir(listing: string): string {
|
|
|
195
253
|
* to `unzip`/`tar` — consistent with the rest of the toolset, which already
|
|
196
254
|
* invokes `bash` and `rg`. Both `unzip` and `tar` must be available on `PATH`; a
|
|
197
255
|
* missing binary surfaces as a clear error (see {@link runArchiveTool}). Refuses
|
|
198
|
-
* any member that would escape `dest` (zip-slip / tar-slip)
|
|
199
|
-
*
|
|
200
|
-
*
|
|
256
|
+
* any member that would escape `dest` (zip-slip / tar-slip): skill archives
|
|
257
|
+
* come from the API, but skills can be third-party. Members that are not a
|
|
258
|
+
* regular file or directory (symlink, hardlink, device, fifo) are excluded
|
|
259
|
+
* from extraction rather than rejected; an archive whose special members
|
|
260
|
+
* cannot be excluded reliably is refused (see {@link classifyArchiveListing}).
|
|
261
|
+
* `tar` matches exclusions unanchored, so a plain member sharing a special
|
|
262
|
+
* member's name may be dropped too. The staging tree is verified to hold only
|
|
263
|
+
* regular files and directories before anything is promoted into `dest`.
|
|
201
264
|
*
|
|
202
265
|
* The skill bundle's single wrapper directory is stripped: the archive is
|
|
203
266
|
* extracted into a staging dir and the wrapper's contents are promoted into
|
|
@@ -215,6 +278,7 @@ export async function extractSkillArchive(resp: Response, dest: string): Promise
|
|
|
215
278
|
fssync.createWriteStream(tmp),
|
|
216
279
|
);
|
|
217
280
|
const stage = path.join(path.dirname(dest), `.skill-stage-${process.pid}-${Date.now()}`);
|
|
281
|
+
const excludeFile = path.join(path.dirname(dest), `.skill-exclude-${process.pid}-${Date.now()}`);
|
|
218
282
|
try {
|
|
219
283
|
// Sniff the first bytes: zip archives start with "PK\x03\x04"; treat
|
|
220
284
|
// anything else as a tar.* archive (`tar -xf` autodetects gzip/bzip2/xz).
|
|
@@ -224,25 +288,57 @@ export async function extractSkillArchive(resp: Response, dest: string): Promise
|
|
|
224
288
|
const archiveCmd = isZip ? 'unzip' : 'tar';
|
|
225
289
|
// List first, validate, then extract — `tar`/`unzip` will happily write a
|
|
226
290
|
// `../` member (or follow a symlink member) outside `-C`/`-d` otherwise.
|
|
227
|
-
const
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
291
|
+
const names = await runArchiveTool(archiveCmd, isZip ? ['-Z1', tmp] : ['-tf', tmp]);
|
|
292
|
+
const typed = await runArchiveTool(archiveCmd, isZip ? ['-Z', '--h', '--t', tmp] : ['-tvf', tmp]);
|
|
293
|
+
const { plain, special } = classifyArchiveListing(archiveCmd, names, typed);
|
|
294
|
+
assertSafeMemberNames([...plain, ...special]);
|
|
295
|
+
const top = archiveTopDir(plain);
|
|
231
296
|
await fs.mkdir(stage, { recursive: true, mode: DIR_CREATE_MODE });
|
|
232
|
-
|
|
297
|
+
// `unzip` exits non-zero when every member is excluded, so only run the
|
|
298
|
+
// extractor when there is something to extract.
|
|
299
|
+
if (plain.length > 0) {
|
|
300
|
+
await runArchiveTool(archiveCmd, await extractArgs(archiveCmd, tmp, stage, special, excludeFile));
|
|
301
|
+
}
|
|
302
|
+
await assertOnlyPlainEntries(stage);
|
|
233
303
|
// Promote the wrapper's contents (or the staged tree itself, if the
|
|
234
304
|
// archive wasn't wrapped) into the already-created empty `dest`. `stage`
|
|
235
305
|
// is a sibling of `dest`, so each rename stays on one filesystem.
|
|
236
306
|
const srcRoot = top ? path.join(stage, top) : stage;
|
|
237
|
-
|
|
307
|
+
const entries = await fs.readdir(srcRoot).catch((e: unknown) => {
|
|
308
|
+
throw errnoCode(e) === 'ENOENT' ? new AnthropicError(INCONSISTENT_LISTING) : e;
|
|
309
|
+
});
|
|
310
|
+
for (const entry of entries) {
|
|
238
311
|
await fs.rename(path.join(srcRoot, entry), path.join(dest, entry));
|
|
239
312
|
}
|
|
240
313
|
} finally {
|
|
241
314
|
await fs.rm(tmp, { force: true });
|
|
315
|
+
await fs.rm(excludeFile, { force: true });
|
|
242
316
|
await fs.rm(stage, { recursive: true, force: true });
|
|
243
317
|
}
|
|
244
318
|
}
|
|
245
319
|
|
|
320
|
+
/**
|
|
321
|
+
* Arguments that extract `archive` into `stage` while excluding every member
|
|
322
|
+
* in `special`. Names are glob-escaped because both CLIs treat exclusions as
|
|
323
|
+
* patterns; `tar` reads them from `excludeFile`, `unzip` takes them after
|
|
324
|
+
* `-x`, which must follow `-d` so no pattern is parsed as an option.
|
|
325
|
+
*/
|
|
326
|
+
async function extractArgs(
|
|
327
|
+
cmd: 'unzip' | 'tar',
|
|
328
|
+
archive: string,
|
|
329
|
+
stage: string,
|
|
330
|
+
special: string[],
|
|
331
|
+
excludeFile: string,
|
|
332
|
+
): Promise<string[]> {
|
|
333
|
+
const patterns = special.map((name) => name.replace(/[*?[\\]/g, '\\$&'));
|
|
334
|
+
if (cmd === 'unzip') {
|
|
335
|
+
return ['-oq', archive, '-d', stage, ...(patterns.length > 0 ? ['-x', ...patterns] : [])];
|
|
336
|
+
}
|
|
337
|
+
if (patterns.length === 0) return ['-xf', archive, '-C', stage];
|
|
338
|
+
await fs.writeFile(excludeFile, patterns.join('\n') + '\n', { flag: 'wx', mode: 0o600 });
|
|
339
|
+
return ['-xf', archive, '-C', stage, '-X', excludeFile];
|
|
340
|
+
}
|
|
341
|
+
|
|
246
342
|
/** Read the first `n` bytes of `file`. */
|
|
247
343
|
async function readHead(file: string, n: number): Promise<Buffer> {
|
|
248
344
|
const handle = await fs.open(file, 'r');
|
package/src/version.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const VERSION = '0.
|
|
1
|
+
export const VERSION = '0.118.0'; // x-release-please-version
|
|
@@ -8,12 +8,20 @@
|
|
|
8
8
|
export declare const DIR_CREATE_MODE = 493;
|
|
9
9
|
/** Mode for files the file tools create. */
|
|
10
10
|
export declare const FILE_CREATE_MODE = 420;
|
|
11
|
+
/** The `code` of a Node system error, or `undefined` for anything else. */
|
|
12
|
+
export declare function errnoCode(err: unknown): string | undefined;
|
|
11
13
|
/**
|
|
12
14
|
* Fully resolve `abs`: `realpath` the longest existing ancestor and re-append
|
|
13
15
|
* the rest, but never re-append a component that is itself a symlink — read the
|
|
14
16
|
* link and continue from its target instead. This handles paths being created
|
|
15
17
|
* (write/edit) without letting a symlink leaf (e.g. a dangling one pointing
|
|
16
18
|
* outside a confinement root) slip through unresolved.
|
|
19
|
+
*
|
|
20
|
+
* Returns a symlink-free path or throws an errno-carrying error (`ELOOP` for a
|
|
21
|
+
* cycle or more than {@link MAX_SYMLINK_HOPS} links, the `lstat`/`realpath`
|
|
22
|
+
* error for an unreadable component); it never returns `abs` unresolved. Only
|
|
23
|
+
* symlink hops count against the cap, so any depth of not-yet-existing
|
|
24
|
+
* directories still resolves.
|
|
17
25
|
*/
|
|
18
26
|
export declare function canonicalize(abs: string): Promise<string>;
|
|
19
27
|
/**
|
|
@@ -25,6 +33,9 @@ export declare function canonicalize(abs: string): Promise<string>;
|
|
|
25
33
|
* leaf, even a dangling one) is resolved before the confinement check, and the
|
|
26
34
|
* resolved path is what the caller then operates on, so a symlink inside `root`
|
|
27
35
|
* that points outside it can neither pass the check nor be followed afterwards.
|
|
36
|
+
* `..` is collapsed lexically before any symlink is followed. A path that cannot
|
|
37
|
+
* be resolved (symlink loop, unreadable component) is rejected with a
|
|
38
|
+
* `ToolError` naming `p`, never the host's absolute path.
|
|
28
39
|
*
|
|
29
40
|
* Residual TOCTOU: a component could still be swapped for a symlink between this
|
|
30
41
|
* call and the eventual `fs` operation. Closing that fully needs per-component
|
|
@@ -43,8 +54,9 @@ export declare function atomicWriteFile(targetPath: string, content: string): Pr
|
|
|
43
54
|
/**
|
|
44
55
|
* Map a thrown filesystem error to a consistent, language-independent message,
|
|
45
56
|
* so the model sees the same wording regardless of the runtime (Node's raw
|
|
46
|
-
* `ENOENT: no such file...` text would otherwise leak through).
|
|
47
|
-
*
|
|
57
|
+
* `ENOENT: no such file...` text would otherwise leak through). Codes we don't
|
|
58
|
+
* special-case render as the bare code, never Node's message, which embeds the
|
|
59
|
+
* host's absolute path.
|
|
48
60
|
*/
|
|
49
61
|
export declare function fsErrorMessage(err: unknown, file: string): string;
|
|
50
62
|
//# sourceMappingURL=fs-util.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-util.d.mts","sourceRoot":"","sources":["../../src/tools/agent-toolset/fs-util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,uFAAuF;AACvF,eAAO,MAAM,eAAe,MAAQ,CAAC;AACrC,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,MAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"fs-util.d.mts","sourceRoot":"","sources":["../../src/tools/agent-toolset/fs-util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,uFAAuF;AACvF,eAAO,MAAM,eAAe,MAAQ,CAAC;AACrC,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,MAAQ,CAAC;AActC,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBxF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBjE"}
|
|
@@ -8,12 +8,20 @@
|
|
|
8
8
|
export declare const DIR_CREATE_MODE = 493;
|
|
9
9
|
/** Mode for files the file tools create. */
|
|
10
10
|
export declare const FILE_CREATE_MODE = 420;
|
|
11
|
+
/** The `code` of a Node system error, or `undefined` for anything else. */
|
|
12
|
+
export declare function errnoCode(err: unknown): string | undefined;
|
|
11
13
|
/**
|
|
12
14
|
* Fully resolve `abs`: `realpath` the longest existing ancestor and re-append
|
|
13
15
|
* the rest, but never re-append a component that is itself a symlink — read the
|
|
14
16
|
* link and continue from its target instead. This handles paths being created
|
|
15
17
|
* (write/edit) without letting a symlink leaf (e.g. a dangling one pointing
|
|
16
18
|
* outside a confinement root) slip through unresolved.
|
|
19
|
+
*
|
|
20
|
+
* Returns a symlink-free path or throws an errno-carrying error (`ELOOP` for a
|
|
21
|
+
* cycle or more than {@link MAX_SYMLINK_HOPS} links, the `lstat`/`realpath`
|
|
22
|
+
* error for an unreadable component); it never returns `abs` unresolved. Only
|
|
23
|
+
* symlink hops count against the cap, so any depth of not-yet-existing
|
|
24
|
+
* directories still resolves.
|
|
17
25
|
*/
|
|
18
26
|
export declare function canonicalize(abs: string): Promise<string>;
|
|
19
27
|
/**
|
|
@@ -25,6 +33,9 @@ export declare function canonicalize(abs: string): Promise<string>;
|
|
|
25
33
|
* leaf, even a dangling one) is resolved before the confinement check, and the
|
|
26
34
|
* resolved path is what the caller then operates on, so a symlink inside `root`
|
|
27
35
|
* that points outside it can neither pass the check nor be followed afterwards.
|
|
36
|
+
* `..` is collapsed lexically before any symlink is followed. A path that cannot
|
|
37
|
+
* be resolved (symlink loop, unreadable component) is rejected with a
|
|
38
|
+
* `ToolError` naming `p`, never the host's absolute path.
|
|
28
39
|
*
|
|
29
40
|
* Residual TOCTOU: a component could still be swapped for a symlink between this
|
|
30
41
|
* call and the eventual `fs` operation. Closing that fully needs per-component
|
|
@@ -43,8 +54,9 @@ export declare function atomicWriteFile(targetPath: string, content: string): Pr
|
|
|
43
54
|
/**
|
|
44
55
|
* Map a thrown filesystem error to a consistent, language-independent message,
|
|
45
56
|
* so the model sees the same wording regardless of the runtime (Node's raw
|
|
46
|
-
* `ENOENT: no such file...` text would otherwise leak through).
|
|
47
|
-
*
|
|
57
|
+
* `ENOENT: no such file...` text would otherwise leak through). Codes we don't
|
|
58
|
+
* special-case render as the bare code, never Node's message, which embeds the
|
|
59
|
+
* host's absolute path.
|
|
48
60
|
*/
|
|
49
61
|
export declare function fsErrorMessage(err: unknown, file: string): string;
|
|
50
62
|
//# sourceMappingURL=fs-util.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fs-util.d.ts","sourceRoot":"","sources":["../../src/tools/agent-toolset/fs-util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,uFAAuF;AACvF,eAAO,MAAM,eAAe,MAAQ,CAAC;AACrC,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,MAAQ,CAAC;
|
|
1
|
+
{"version":3,"file":"fs-util.d.ts","sourceRoot":"","sources":["../../src/tools/agent-toolset/fs-util.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAOH,uFAAuF;AACvF,eAAO,MAAM,eAAe,MAAQ,CAAC;AACrC,4CAA4C;AAC5C,eAAO,MAAM,gBAAgB,MAAQ,CAAC;AActC,2EAA2E;AAC3E,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAG1D;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CA8B/D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAsB,aAAa,CACjC,IAAI,EAAE,MAAM,EACZ,CAAC,EAAE,MAAM,EACT,IAAI,CAAC,EAAE;IAAE,YAAY,CAAC,EAAE,OAAO,CAAA;CAAE,GAChC,OAAO,CAAC,MAAM,CAAC,CAejB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAgBxF;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAwBjE"}
|