@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
package/src/core/api-promise.ts
CHANGED
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
type APIResponseProps,
|
|
8
8
|
type WithRequestID,
|
|
9
9
|
defaultParseResponse,
|
|
10
|
-
|
|
10
|
+
addResponseIDs,
|
|
11
11
|
} from '../internal/parse';
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -37,7 +37,7 @@ export class APIPromise<T> extends Promise<WithRequestID<T>> {
|
|
|
37
37
|
|
|
38
38
|
_thenUnwrap<U>(transform: (data: T, props: APIResponseProps) => U): APIPromise<U> {
|
|
39
39
|
return new APIPromise(this.#client, this.responsePromise, async (client, props) =>
|
|
40
|
-
|
|
40
|
+
addResponseIDs(transform(await this.parseResponse(client, props), props), props.response),
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
|
|
@@ -68,9 +68,19 @@ export class APIPromise<T> extends Promise<WithRequestID<T>> {
|
|
|
68
68
|
* Try setting `"moduleResolution": "NodeNext"` or add `"lib": ["DOM"]`
|
|
69
69
|
* to your `tsconfig.json`.
|
|
70
70
|
*/
|
|
71
|
-
async withResponse(): Promise<{
|
|
71
|
+
async withResponse(): Promise<{
|
|
72
|
+
data: T;
|
|
73
|
+
response: Response;
|
|
74
|
+
request_id: string | null | undefined;
|
|
75
|
+
workspace_id: string | null | undefined;
|
|
76
|
+
}> {
|
|
72
77
|
const [data, response] = await Promise.all([this.parse(), this.asResponse()]);
|
|
73
|
-
return {
|
|
78
|
+
return {
|
|
79
|
+
data,
|
|
80
|
+
response,
|
|
81
|
+
request_id: response.headers.get('request-id'),
|
|
82
|
+
workspace_id: response.headers.get('anthropic-workspace-id'),
|
|
83
|
+
};
|
|
74
84
|
}
|
|
75
85
|
|
|
76
86
|
private parse(): Promise<WithRequestID<T>> {
|
package/src/core/error.ts
CHANGED
|
@@ -18,6 +18,7 @@ export class APIError<
|
|
|
18
18
|
readonly error: TError;
|
|
19
19
|
|
|
20
20
|
readonly requestID: string | null | undefined;
|
|
21
|
+
readonly workspaceID: string | null | undefined;
|
|
21
22
|
|
|
22
23
|
/** The `error.type` from the API response body, e.g. `"rate_limit_error"` */
|
|
23
24
|
readonly type: ErrorType | null;
|
|
@@ -33,6 +34,7 @@ export class APIError<
|
|
|
33
34
|
this.status = status;
|
|
34
35
|
this.headers = headers;
|
|
35
36
|
this.requestID = headers?.get('request-id');
|
|
37
|
+
this.workspaceID = headers?.get('anthropic-workspace-id');
|
|
36
38
|
this.error = error;
|
|
37
39
|
this.type = type ?? null;
|
|
38
40
|
}
|
package/src/core/middleware.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { BaseAnthropic } from '../client';
|
|
2
2
|
import type { Fetch } from '../internal/builtin-types';
|
|
3
3
|
import { castToError, isAbortError } from '../internal/errors';
|
|
4
|
-
import {
|
|
4
|
+
import { addResponseIDs } from '../internal/parse';
|
|
5
5
|
import type { FinalRequestOptions } from '../internal/request-options';
|
|
6
6
|
import { defaultLogger, loggerFor, type Logger } from '../internal/utils/log';
|
|
7
7
|
import type { APIRequest } from './api';
|
|
@@ -299,7 +299,7 @@ async function parseMiddlewareResponse(
|
|
|
299
299
|
// if there is no content we can't do anything
|
|
300
300
|
return undefined;
|
|
301
301
|
}
|
|
302
|
-
return
|
|
302
|
+
return addResponseIDs(await response.clone().json(), response);
|
|
303
303
|
}
|
|
304
304
|
|
|
305
305
|
return await response.clone().text();
|
package/src/helpers/beta/zod.ts
CHANGED
|
@@ -16,9 +16,7 @@ import { BetaToolResultContentBlockParam } from '../../resources/beta';
|
|
|
16
16
|
export function betaZodOutputFormat<ZodInput extends z.ZodType>(
|
|
17
17
|
zodObject: ZodInput,
|
|
18
18
|
): AutoParseableBetaOutputFormat<z.infer<ZodInput>> {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
jsonSchema = transformJSONSchema(jsonSchema);
|
|
19
|
+
const jsonSchema = transformJSONSchema(z.toJSONSchema(zodObject, { reused: 'ref' }));
|
|
22
20
|
|
|
23
21
|
return {
|
|
24
22
|
type: 'json_schema',
|
package/src/helpers/zod.ts
CHANGED
|
@@ -15,9 +15,7 @@ import { AutoParseableOutputFormat } from '../lib/parser';
|
|
|
15
15
|
export function zodOutputFormat<ZodInput extends z.ZodType>(
|
|
16
16
|
zodObject: ZodInput,
|
|
17
17
|
): AutoParseableOutputFormat<z.infer<ZodInput>> {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
jsonSchema = transformJSONSchema(jsonSchema);
|
|
18
|
+
const jsonSchema = transformJSONSchema(z.toJSONSchema(zodObject, { reused: 'ref' }));
|
|
21
19
|
|
|
22
20
|
return {
|
|
23
21
|
type: 'json_schema',
|
package/src/internal/parse.ts
CHANGED
|
@@ -51,7 +51,7 @@ export async function defaultParseResponse<T>(
|
|
|
51
51
|
}
|
|
52
52
|
|
|
53
53
|
const json = await response.json();
|
|
54
|
-
return
|
|
54
|
+
return addResponseIDs(json as T, response);
|
|
55
55
|
}
|
|
56
56
|
|
|
57
57
|
const text = await response.text();
|
|
@@ -80,16 +80,16 @@ export async function defaultParseResponse<T>(
|
|
|
80
80
|
|
|
81
81
|
export type WithRequestID<T> =
|
|
82
82
|
T extends Array<any> | Response | AbstractPage<any> ? T
|
|
83
|
-
: T extends Record<string, any> ? T & { _request_id?: string | null }
|
|
83
|
+
: T extends Record<string, any> ? T & { _request_id?: string | null; _workspace_id?: string | null }
|
|
84
84
|
: T;
|
|
85
85
|
|
|
86
|
-
export function
|
|
86
|
+
export function addResponseIDs<T>(value: T, response: Response): WithRequestID<T> {
|
|
87
87
|
if (!value || typeof value !== 'object' || Array.isArray(value)) {
|
|
88
88
|
return value as WithRequestID<T>;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
return Object.
|
|
92
|
-
value: response.headers.get('request-id'),
|
|
93
|
-
enumerable: false,
|
|
91
|
+
return Object.defineProperties(value, {
|
|
92
|
+
_request_id: { value: response.headers.get('request-id'), enumerable: false },
|
|
93
|
+
_workspace_id: { value: response.headers.get('anthropic-workspace-id'), enumerable: false },
|
|
94
94
|
}) as WithRequestID<T>;
|
|
95
95
|
}
|
|
@@ -74,6 +74,7 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
74
74
|
#catchingPromiseCreated = false;
|
|
75
75
|
#response: Response | null | undefined;
|
|
76
76
|
#request_id: string | null | undefined;
|
|
77
|
+
#workspace_id: string | null | undefined;
|
|
77
78
|
#logger: Logger;
|
|
78
79
|
|
|
79
80
|
constructor(params: MessageCreateParamsBase | null, opts?: { logger?: Logger | undefined }) {
|
|
@@ -106,6 +107,10 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
106
107
|
return this.#request_id;
|
|
107
108
|
}
|
|
108
109
|
|
|
110
|
+
get workspace_id(): string | null | undefined {
|
|
111
|
+
return this.#workspace_id;
|
|
112
|
+
}
|
|
113
|
+
|
|
109
114
|
/**
|
|
110
115
|
* Returns the `MessageStream` data, the raw `Response` instance and the ID of the request,
|
|
111
116
|
* returned vie the `request-id` header which is useful for debugging requests and resporting
|
|
@@ -120,6 +125,7 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
120
125
|
data: BetaMessageStream<ParsedT>;
|
|
121
126
|
response: Response;
|
|
122
127
|
request_id: string | null | undefined;
|
|
128
|
+
workspace_id: string | null | undefined;
|
|
123
129
|
}> {
|
|
124
130
|
this.#catchingPromiseCreated = true;
|
|
125
131
|
|
|
@@ -132,6 +138,7 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
132
138
|
data: this,
|
|
133
139
|
response,
|
|
134
140
|
request_id: response.headers.get('request-id'),
|
|
141
|
+
workspace_id: response.headers.get('anthropic-workspace-id'),
|
|
135
142
|
};
|
|
136
143
|
}
|
|
137
144
|
|
|
@@ -223,6 +230,7 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
223
230
|
if (this.ended) return;
|
|
224
231
|
this.#response = response;
|
|
225
232
|
this.#request_id = response?.headers.get('request-id');
|
|
233
|
+
this.#workspace_id = response?.headers.get('anthropic-workspace-id');
|
|
226
234
|
this.#resolveConnectedPromise(response);
|
|
227
235
|
this._emit('connect');
|
|
228
236
|
}
|
|
@@ -581,15 +589,21 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
581
589
|
case 'message_stop':
|
|
582
590
|
return snapshot;
|
|
583
591
|
case 'message_delta':
|
|
584
|
-
snapshot.container = event.delta.container;
|
|
585
592
|
snapshot.stop_reason = event.delta.stop_reason;
|
|
586
593
|
snapshot.stop_sequence = event.delta.stop_sequence;
|
|
587
|
-
|
|
588
|
-
snapshot.stop_details = event.delta.stop_details;
|
|
589
|
-
}
|
|
594
|
+
snapshot.stop_details = event.delta.stop_details;
|
|
590
595
|
snapshot.usage.output_tokens = event.usage.output_tokens;
|
|
591
|
-
snapshot.context_management = event.context_management;
|
|
592
596
|
|
|
597
|
+
if (event.delta.container != null) {
|
|
598
|
+
snapshot.container = event.delta.container;
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
if (event.context_management != null) {
|
|
602
|
+
snapshot.context_management = event.context_management;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// The remaining usage counters are cumulative whole-message totals that are
|
|
606
|
+
// omitted when they don't apply, so overwrite when present and never add.
|
|
593
607
|
if (event.usage.input_tokens != null) {
|
|
594
608
|
snapshot.usage.input_tokens = event.usage.input_tokens;
|
|
595
609
|
}
|
|
@@ -614,6 +628,10 @@ export class BetaMessageStream<ParsedT = null> implements AsyncIterable<BetaMess
|
|
|
614
628
|
snapshot.usage.fallback_credit = event.usage.fallback_credit;
|
|
615
629
|
}
|
|
616
630
|
|
|
631
|
+
if (event.usage.output_tokens_details != null) {
|
|
632
|
+
snapshot.usage.output_tokens_details = event.usage.output_tokens_details;
|
|
633
|
+
}
|
|
634
|
+
|
|
617
635
|
return snapshot;
|
|
618
636
|
case 'content_block_start':
|
|
619
637
|
snapshot.content.push(event.content_block);
|
package/src/lib/MessageStream.ts
CHANGED
|
@@ -73,6 +73,7 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
73
73
|
#catchingPromiseCreated = false;
|
|
74
74
|
#response: Response | null | undefined;
|
|
75
75
|
#request_id: string | null | undefined;
|
|
76
|
+
#workspace_id: string | null | undefined;
|
|
76
77
|
#logger: Logger;
|
|
77
78
|
|
|
78
79
|
constructor(params: MessageCreateParamsBase | null, opts?: { logger?: Logger | undefined }) {
|
|
@@ -105,6 +106,10 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
105
106
|
return this.#request_id;
|
|
106
107
|
}
|
|
107
108
|
|
|
109
|
+
get workspace_id(): string | null | undefined {
|
|
110
|
+
return this.#workspace_id;
|
|
111
|
+
}
|
|
112
|
+
|
|
108
113
|
/**
|
|
109
114
|
* Returns the `MessageStream` data, the raw `Response` instance and the ID of the request,
|
|
110
115
|
* returned vie the `request-id` header which is useful for debugging requests and resporting
|
|
@@ -119,6 +124,7 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
119
124
|
data: MessageStream<ParsedT>;
|
|
120
125
|
response: Response;
|
|
121
126
|
request_id: string | null | undefined;
|
|
127
|
+
workspace_id: string | null | undefined;
|
|
122
128
|
}> {
|
|
123
129
|
this.#catchingPromiseCreated = true;
|
|
124
130
|
|
|
@@ -131,6 +137,7 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
131
137
|
data: this,
|
|
132
138
|
response,
|
|
133
139
|
request_id: response.headers.get('request-id'),
|
|
140
|
+
workspace_id: response.headers.get('anthropic-workspace-id'),
|
|
134
141
|
};
|
|
135
142
|
}
|
|
136
143
|
|
|
@@ -222,6 +229,7 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
222
229
|
if (this.ended) return;
|
|
223
230
|
this.#response = response;
|
|
224
231
|
this.#request_id = response?.headers.get('request-id');
|
|
232
|
+
this.#workspace_id = response?.headers.get('anthropic-workspace-id');
|
|
225
233
|
this.#resolveConnectedPromise(response);
|
|
226
234
|
this._emit('connect');
|
|
227
235
|
}
|
|
@@ -575,12 +583,15 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
575
583
|
case 'message_delta':
|
|
576
584
|
snapshot.stop_reason = event.delta.stop_reason;
|
|
577
585
|
snapshot.stop_sequence = event.delta.stop_sequence;
|
|
578
|
-
|
|
579
|
-
snapshot.stop_details = event.delta.stop_details;
|
|
580
|
-
}
|
|
586
|
+
snapshot.stop_details = event.delta.stop_details;
|
|
581
587
|
snapshot.usage.output_tokens = event.usage.output_tokens;
|
|
582
588
|
|
|
583
|
-
|
|
589
|
+
if (event.delta.container != null) {
|
|
590
|
+
snapshot.container = event.delta.container;
|
|
591
|
+
}
|
|
592
|
+
|
|
593
|
+
// The remaining usage counters are cumulative whole-message totals that are
|
|
594
|
+
// omitted when they don't apply, so overwrite when present and never add.
|
|
584
595
|
if (event.usage.input_tokens != null) {
|
|
585
596
|
snapshot.usage.input_tokens = event.usage.input_tokens;
|
|
586
597
|
}
|
|
@@ -597,6 +608,10 @@ export class MessageStream<ParsedT = null> implements AsyncIterable<MessageStrea
|
|
|
597
608
|
snapshot.usage.server_tool_use = event.usage.server_tool_use;
|
|
598
609
|
}
|
|
599
610
|
|
|
611
|
+
if (event.usage.output_tokens_details != null) {
|
|
612
|
+
snapshot.usage.output_tokens_details = event.usage.output_tokens_details;
|
|
613
|
+
}
|
|
614
|
+
|
|
600
615
|
return snapshot;
|
|
601
616
|
case 'content_block_start':
|
|
602
617
|
snapshot.content.push({ ...event.content_block });
|
|
@@ -21,6 +21,7 @@ import { copyClientForHelper } from '../helper-client';
|
|
|
21
21
|
import type { AgentToolContext } from '../../tools/agent-toolset/node';
|
|
22
22
|
|
|
23
23
|
const HEARTBEAT_DEFAULT_MS = 30_000;
|
|
24
|
+
const HEARTBEAT_TTL_DEFAULT_MS = 90_000;
|
|
24
25
|
const NO_HEARTBEAT_SENTINEL = 'NO_HEARTBEAT';
|
|
25
26
|
|
|
26
27
|
/**
|
|
@@ -51,6 +52,10 @@ export interface EnvironmentWorkerOptions {
|
|
|
51
52
|
* Tools to expose to each claimed session. Defaults to
|
|
52
53
|
* `betaAgentToolset20260401(ctx)` (the standard `agent_toolset_20260401` set
|
|
53
54
|
* bound to the per-session {@link AgentToolContext}).
|
|
55
|
+
*
|
|
56
|
+
* A `run` that blocks the event loop synchronously also stalls the lease
|
|
57
|
+
* heartbeat, and the worker can lose the lease; keep tools non-blocking (see
|
|
58
|
+
* {@link BetaRunnableTool.run}).
|
|
54
59
|
*/
|
|
55
60
|
tools?: EnvironmentWorkerTools;
|
|
56
61
|
/** Base directory for the per-session {@link AgentToolContext}. Defaults to `process.cwd()`. */
|
|
@@ -109,10 +114,10 @@ type ClaimedWork = Pick<BetaSelfHostedWork, 'id' | 'environment_id' | 'data'>;
|
|
|
109
114
|
* For each claimed `session` work item it: builds the per-session
|
|
110
115
|
* {@link AgentToolContext}, downloads the session agent's skills
|
|
111
116
|
* (`setupSkills`), then runs a {@link SessionToolRunner} for the session
|
|
112
|
-
*
|
|
113
|
-
* the work item, cleans up the downloaded skills, and loops to the
|
|
114
|
-
* lease heartbeat reports `state === "stopping"` / a lost lease
|
|
115
|
-
* by aborting the session runner.
|
|
117
|
+
* while heartbeating the work-item lease on the same event loop; on exit it
|
|
118
|
+
* force-stops the work item, cleans up the downloaded skills, and loops to the
|
|
119
|
+
* next one. The lease heartbeat reports `state === "stopping"` / a lost lease
|
|
120
|
+
* back into the run by aborting the session runner.
|
|
116
121
|
*
|
|
117
122
|
* Use {@link EnvironmentWorker.handleItem} if you already hold a claimed work
|
|
118
123
|
* item (e.g. a `worker poll --on-work` script handed one to a fresh process) and
|
|
@@ -195,8 +200,8 @@ export class EnvironmentWorker {
|
|
|
195
200
|
* per-session {@link AgentToolContext} (workdir from this worker's options),
|
|
196
201
|
* download the session agent's skills (`setupSkills`), run a
|
|
197
202
|
* {@link SessionToolRunner} for the session while heartbeating the work-item
|
|
198
|
-
* lease
|
|
199
|
-
*
|
|
203
|
+
* lease, and force-stop the work item on exit (whether the runner finishes
|
|
204
|
+
* normally, throws, or the heartbeat loop signals shutdown).
|
|
200
205
|
*
|
|
201
206
|
* Use this when something else does the claiming — e.g. a `worker poll
|
|
202
207
|
* --on-work` script that hands an already-claimed item to a fresh process. The
|
|
@@ -292,19 +297,26 @@ export class EnvironmentWorker {
|
|
|
292
297
|
const ctrl = new AbortController();
|
|
293
298
|
const detachExternal = linkAbort(externalSignal, ctrl);
|
|
294
299
|
|
|
295
|
-
|
|
300
|
+
// Inert until iterated below.
|
|
301
|
+
const runner = new SessionToolRunner(sessionId, {
|
|
302
|
+
client: sessionClient,
|
|
303
|
+
tools,
|
|
304
|
+
...(this.maxIdleMs !== undefined ? { maxIdleMs: this.maxIdleMs } : {}),
|
|
305
|
+
...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
|
|
306
|
+
signal: ctrl.signal,
|
|
307
|
+
});
|
|
308
|
+
|
|
309
|
+
// Each heartbeat reports the lease TTL the server is enforcing; it becomes
|
|
310
|
+
// the runner's tool-result send retry window so a send keeps retrying
|
|
311
|
+
// exactly as long as the lease could still be live.
|
|
312
|
+
const heartbeatPromise = heartbeatLoop(sessionClient, work, ctrl, log, this.requestOptions, (ttlMs) =>
|
|
313
|
+
runner._setSendRetryWindow(ttlMs),
|
|
314
|
+
).catch((e) => {
|
|
296
315
|
if (!ctrl.signal.aborted) log.error('heartbeat loop failed', { work_id: work.id, error: String(e) });
|
|
297
316
|
ctrl.abort();
|
|
298
317
|
});
|
|
299
318
|
|
|
300
319
|
try {
|
|
301
|
-
const runner = new SessionToolRunner(sessionId, {
|
|
302
|
-
client: sessionClient,
|
|
303
|
-
tools,
|
|
304
|
-
...(this.maxIdleMs !== undefined ? { maxIdleMs: this.maxIdleMs } : {}),
|
|
305
|
-
...(this.requestOptions !== undefined ? { requestOptions: this.requestOptions } : {}),
|
|
306
|
-
signal: ctrl.signal,
|
|
307
|
-
});
|
|
308
320
|
for await (const _ of runner) {
|
|
309
321
|
// Drive the runner to completion; per-call observability is not part
|
|
310
322
|
// of this composition's surface — use `SessionToolRunner` directly
|
|
@@ -348,7 +360,10 @@ async function forceStop(
|
|
|
348
360
|
/**
|
|
349
361
|
* Keep the work-item lease alive while a session is being served. Aborts `ctrl`
|
|
350
362
|
* when the control plane reports the work is `stopping`/`stopped`, when the
|
|
351
|
-
* lease is no longer extended,
|
|
363
|
+
* lease is no longer extended, on a permanent heartbeat failure, or when no
|
|
364
|
+
* heartbeat has succeeded for longer than the lease ttl (the lease is assumed
|
|
365
|
+
* lost). Each heartbeat call is cut off after the current beat interval so a
|
|
366
|
+
* hung request cannot outlive the lease it is meant to renew.
|
|
352
367
|
*/
|
|
353
368
|
async function heartbeatLoop(
|
|
354
369
|
client: Anthropic,
|
|
@@ -356,19 +371,31 @@ async function heartbeatLoop(
|
|
|
356
371
|
ctrl: AbortController,
|
|
357
372
|
logger: Logger,
|
|
358
373
|
requestOptions?: BetaToolRunnerRequestOptions,
|
|
374
|
+
/** Called with the server-reported lease TTL after every successful beat. */
|
|
375
|
+
onLeaseTtl?: (ttlMs: number) => void,
|
|
359
376
|
): Promise<void> {
|
|
360
377
|
let intervalMs = HEARTBEAT_DEFAULT_MS;
|
|
378
|
+
let ttlMs = HEARTBEAT_TTL_DEFAULT_MS;
|
|
379
|
+
let lastSuccessMs = Date.now();
|
|
361
380
|
let last = NO_HEARTBEAT_SENTINEL;
|
|
362
381
|
const beat = async (): Promise<void> => {
|
|
382
|
+
// Not the request `timeout` option: the core client retries timeouts, so
|
|
383
|
+
// it would not bound the call as a whole.
|
|
384
|
+
const beatCtrl = new AbortController();
|
|
385
|
+
const detach = linkAbort(ctrl.signal, beatCtrl);
|
|
386
|
+
const cutoff = setTimeout(() => beatCtrl.abort(), intervalMs);
|
|
363
387
|
try {
|
|
364
388
|
const resp = await client.beta.environments.work.heartbeat(
|
|
365
389
|
work.id,
|
|
366
390
|
{ environment_id: work.environment_id, expected_last_heartbeat: last },
|
|
367
|
-
{ ...requestOptions, headers: buildHeaders([requestOptions?.headers]), signal:
|
|
391
|
+
{ ...requestOptions, headers: buildHeaders([requestOptions?.headers]), signal: beatCtrl.signal },
|
|
368
392
|
);
|
|
393
|
+
lastSuccessMs = Date.now();
|
|
369
394
|
last = resp.last_heartbeat;
|
|
370
395
|
if (resp.ttl_seconds > 0) {
|
|
371
|
-
|
|
396
|
+
ttlMs = resp.ttl_seconds * 1000;
|
|
397
|
+
intervalMs = Math.max(1_000, Math.min(ttlMs / 2, HEARTBEAT_DEFAULT_MS));
|
|
398
|
+
onLeaseTtl?.(ttlMs);
|
|
372
399
|
}
|
|
373
400
|
if (resp.state === 'stopping' || resp.state === 'stopped') {
|
|
374
401
|
logger.info('heartbeat signals shutdown', { work_id: work.id, state: resp.state });
|
|
@@ -387,7 +414,19 @@ async function heartbeatLoop(
|
|
|
387
414
|
ctrl.abort();
|
|
388
415
|
throw e;
|
|
389
416
|
}
|
|
417
|
+
if (Date.now() - lastSuccessMs > ttlMs) {
|
|
418
|
+
logger.error('lease assumed lost: no successful heartbeat in ttl', {
|
|
419
|
+
work_id: work.id,
|
|
420
|
+
ttl_ms: ttlMs,
|
|
421
|
+
error: String(e),
|
|
422
|
+
});
|
|
423
|
+
ctrl.abort();
|
|
424
|
+
return;
|
|
425
|
+
}
|
|
390
426
|
logger.warn('transient heartbeat failure', { work_id: work.id, error: String(e) });
|
|
427
|
+
} finally {
|
|
428
|
+
clearTimeout(cutoff);
|
|
429
|
+
detach();
|
|
391
430
|
}
|
|
392
431
|
};
|
|
393
432
|
|
|
@@ -22,10 +22,7 @@ import { ToolError } from './ToolError';
|
|
|
22
22
|
|
|
23
23
|
export type Promisable<T> = T | Promise<T>;
|
|
24
24
|
|
|
25
|
-
/**
|
|
26
|
-
* Tool types that can be implemented on the client.
|
|
27
|
-
* Excludes server-side tools like code execution, web search, and MCP toolsets.
|
|
28
|
-
*/
|
|
25
|
+
/** Tools that run on the client. Server-side tools (code execution, web search, MCP toolsets) are not included. */
|
|
29
26
|
export type BetaClientRunnableToolType =
|
|
30
27
|
| BetaTool
|
|
31
28
|
| BetaMemoryTool20250818
|
|
@@ -40,15 +37,9 @@ export type BetaClientRunnableToolType =
|
|
|
40
37
|
| BetaToolTextEditor20250728;
|
|
41
38
|
|
|
42
39
|
/**
|
|
43
|
-
* The tool
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
* - from `client.beta.sessions.events.toolRunner`, the `agent.tool_use` /
|
|
47
|
-
* `agent.custom_tool_use` session event.
|
|
48
|
-
*
|
|
49
|
-
* The shapes overlap on the common fields (`id`, `name`, `input`), so code that
|
|
50
|
-
* only reads those works without narrowing; narrow on the shape (e.g. `'type' in
|
|
51
|
-
* x`) when you need surface-specific properties.
|
|
40
|
+
* The tool call being served: a Messages `tool_use` block, or a session
|
|
41
|
+
* `agent.tool_use` / `agent.custom_tool_use` event. All three carry `id`,
|
|
42
|
+
* `name` and `input`.
|
|
52
43
|
*/
|
|
53
44
|
export type BetaToolUse =
|
|
54
45
|
| BetaToolUseBlock
|
|
@@ -56,65 +47,50 @@ export type BetaToolUse =
|
|
|
56
47
|
| BetaManagedAgentsAgentCustomToolUseEvent;
|
|
57
48
|
|
|
58
49
|
export type BetaToolRunContext = {
|
|
59
|
-
/** The tool-use that triggered this run. See {@link BetaToolUse}. */
|
|
60
50
|
toolUse: BetaToolUse;
|
|
51
|
+
/** @deprecated Use `toolUse`. */
|
|
52
|
+
toolUseBlock: BetaToolUse;
|
|
61
53
|
/**
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
* name — which is why it was renamed.
|
|
54
|
+
* Aborted when the runner is aborted or, in the session runner, when the
|
|
55
|
+
* per-tool timeout fires. The runner still waits for `run` to return, so
|
|
56
|
+
* check it in long-running work.
|
|
66
57
|
*/
|
|
67
|
-
toolUseBlock: BetaToolUse;
|
|
68
58
|
signal?: AbortSignal | null | undefined;
|
|
69
59
|
};
|
|
70
60
|
|
|
71
|
-
|
|
72
|
-
// that will be called by `toolRunner()` helpers
|
|
61
|
+
/** A tool definition plus the `run` and `parse` the tool runners call. */
|
|
73
62
|
export type BetaRunnableTool<Input = any> = BetaClientRunnableToolType & {
|
|
63
|
+
/**
|
|
64
|
+
* Runs on the event loop: a body that blocks synchronously stalls the runner
|
|
65
|
+
* and, in an `EnvironmentWorker`, the lease heartbeat. Await async work or
|
|
66
|
+
* move it to a worker thread.
|
|
67
|
+
*/
|
|
74
68
|
run: (
|
|
75
69
|
args: Input,
|
|
76
70
|
context?: BetaToolRunContext,
|
|
77
71
|
) => Promisable<string | Array<BetaToolResultContentBlockParam>>;
|
|
78
72
|
parse: (content: unknown) => Input;
|
|
79
|
-
/**
|
|
80
|
-
* Optional cleanup hook for tools that hold process-level resources (e.g. a
|
|
81
|
-
* persistent shell). `SessionToolRunner` (`client.beta.sessions.events.toolRunner`)
|
|
82
|
-
* calls it once when iteration ends.
|
|
83
|
-
*/
|
|
73
|
+
/** Called once by the session runner when it stops. Release held resources here (e.g. a shell). */
|
|
84
74
|
close?: () => Promisable<void>;
|
|
85
75
|
};
|
|
86
76
|
|
|
87
|
-
/**
|
|
88
|
-
* Resolve the registry key for a tool — the name the model addresses it by.
|
|
89
|
-
* MCP toolsets are keyed on `mcp_server_name`; every other tool on `name`.
|
|
90
|
-
* Shared so the tool-name lookup is identical across `toolRunner()` surfaces.
|
|
91
|
-
*/
|
|
77
|
+
/** The name the model calls a tool by: `mcp_server_name` for MCP toolsets, `name` for everything else. */
|
|
92
78
|
export function toolName(tool: BetaToolUnion | BetaRunnableTool): string {
|
|
93
79
|
return 'name' in tool ? tool.name : tool.mcp_server_name;
|
|
94
80
|
}
|
|
95
81
|
|
|
96
|
-
/**
|
|
97
|
-
* Format a thrown value into tool-result content: a {@link ToolError} carries
|
|
98
|
-
* its own structured content, anything else becomes an `Error: <message>`
|
|
99
|
-
* string. Shared so every `toolRunner()` surface reports tool failures the
|
|
100
|
-
* same way to the model.
|
|
101
|
-
*/
|
|
82
|
+
/** Tool-result content for a thrown value: a {@link ToolError}'s own content, otherwise `Error: <message>`. */
|
|
102
83
|
export function toolErrorContent(e: unknown): string | Array<BetaToolResultContentBlockParam> {
|
|
103
84
|
return e instanceof ToolError ? e.content : `Error: ${e instanceof Error ? e.message : String(e)}`;
|
|
104
85
|
}
|
|
105
86
|
|
|
106
|
-
/**
|
|
87
|
+
/** What a tool run produced, and whether it failed. */
|
|
107
88
|
export interface RunnableToolOutcome {
|
|
108
89
|
content: string | Array<BetaToolResultContentBlockParam>;
|
|
109
90
|
isError: boolean;
|
|
110
91
|
}
|
|
111
92
|
|
|
112
|
-
/**
|
|
113
|
-
* Run a {@link BetaRunnableTool} end-to-end: parse the raw input, invoke `run`,
|
|
114
|
-
* and format any thrown value via {@link toolErrorContent}. Shared so the
|
|
115
|
-
* parse → run → catch → format pipeline is identical across `toolRunner()`
|
|
116
|
-
* surfaces.
|
|
117
|
-
*/
|
|
93
|
+
/** Parse the input, run the tool, and turn anything thrown into an error result. */
|
|
118
94
|
export async function runRunnableTool(
|
|
119
95
|
tool: BetaRunnableTool,
|
|
120
96
|
rawInput: unknown,
|
|
@@ -222,6 +222,17 @@ export class BetaToolRunner<Stream extends boolean> {
|
|
|
222
222
|
const message = await this.#message;
|
|
223
223
|
this.#state.params.messages.push({ role: message.role, content: message.content });
|
|
224
224
|
|
|
225
|
+
// Container-bound server tools reject a follow-up request that omits the container the
|
|
226
|
+
// previous turn ran in, so carry its id forward unless the caller pinned one themselves.
|
|
227
|
+
const { container } = this.#state.params;
|
|
228
|
+
if (message.container) {
|
|
229
|
+
if (container == null) {
|
|
230
|
+
this.#state.params.container = message.container.id;
|
|
231
|
+
} else if (typeof container === 'object' && container.id == null) {
|
|
232
|
+
this.#state.params.container = { ...container, id: message.container.id };
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
|
|
225
236
|
// Refusal-terminated turns are terminal: the refusal may have cut a tool_use off
|
|
226
237
|
// with partial input, so executing this turn's tools would fire side effects the
|
|
227
238
|
// model never confirmed — and once middleware strips the refusal turn, their
|
|
@@ -567,18 +578,6 @@ function applyToolChange(block: BetaContentBlockParam, available: Set<string>):
|
|
|
567
578
|
case 'tool_addition':
|
|
568
579
|
applyToolReference(block, available);
|
|
569
580
|
break;
|
|
570
|
-
case 'mid_conv_system':
|
|
571
|
-
// A `mid_conv_system` block's content is limited by the API schema to
|
|
572
|
-
// text / tool_addition / tool_removal, so we walk exactly one level — no recursion.
|
|
573
|
-
for (const inner of block.content) {
|
|
574
|
-
if (inner.type === 'tool_removal' || inner.type === 'tool_addition') {
|
|
575
|
-
applyToolReference(inner, available);
|
|
576
|
-
}
|
|
577
|
-
}
|
|
578
|
-
break;
|
|
579
|
-
default:
|
|
580
|
-
// Other and unknown/newer block types leave the set untouched (forward compatibility).
|
|
581
|
-
break;
|
|
582
581
|
}
|
|
583
582
|
}
|
|
584
583
|
|