@economic/agents 3.0.0 → 3.0.1
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/index.d.mts +63 -63
- package/dist/index.mjs +155 -58
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -341,6 +341,61 @@ type Tool<Context extends Record<string, unknown> = Record<string, unknown>, INP
|
|
|
341
341
|
executeTask?: ExecuteTask<Context, INPUT, NoInfer<OUTPUT> & TaskValue>;
|
|
342
342
|
};
|
|
343
343
|
export declare function tool<Context extends Record<string, unknown> = Record<string, unknown>, INPUT extends JSONValue | unknown | never = any, OUTPUT extends JSONValue | unknown | never = any>(definition: Tool<Context, INPUT, OUTPUT>): Tool<Context, INPUT, OUTPUT>;
|
|
344
|
+
/** Tool execution options plus the additional context supplied by native Think actions. */
|
|
345
|
+
type ActionContext<Context extends Record<string, unknown> = Record<string, unknown>> = ToolExecutionOptions<Context> & ActionContext$1 & {
|
|
346
|
+
/** The action's resolved domain key, or its tool-call fallback when none was declared. */
|
|
347
|
+
idempotencyKey: string;
|
|
348
|
+
};
|
|
349
|
+
type Action<Context extends Record<string, unknown> = Record<string, unknown>, Input = any, Output = any> = Omit<ActionConfig<FlexibleSchema<Input>, Output>, "approval" | "execute" | "idempotencyKey" | "inputSchema" | "permissions"> & {
|
|
350
|
+
description: string;
|
|
351
|
+
inputSchema: FlexibleSchema<Input>;
|
|
352
|
+
approval?: ActionApprovalPolicy<Input>;
|
|
353
|
+
idempotencyKey?: ActionIdempotencyKey<Input>;
|
|
354
|
+
permissions?: ActionPermissionSpec<Input>;
|
|
355
|
+
authorize?: (ctx?: Context) => boolean;
|
|
356
|
+
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
357
|
+
execute(input: Input, ctx: ActionContext<Context>): Promise<Output> | Output;
|
|
358
|
+
};
|
|
359
|
+
type RegisteredAction<Context extends Record<string, unknown> = Record<string, unknown>, InputSchema extends FlexibleSchema = FlexibleSchema, Output = unknown> = Action$1<InputSchema, Output> & {
|
|
360
|
+
authorize?: (ctx?: Context) => boolean;
|
|
361
|
+
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
362
|
+
};
|
|
363
|
+
/** A native Think action with the SDK's standard authorization policy. */
|
|
364
|
+
export declare function action<Context extends Record<string, unknown> = Record<string, unknown>, Input = any, Output = any>(definition: Action<Context, Input, Output>): RegisteredAction<Context, FlexibleSchema<Input>, Output>;
|
|
365
|
+
interface SkillDefinition<Context extends Record<string, unknown>> {
|
|
366
|
+
name: string;
|
|
367
|
+
description: string;
|
|
368
|
+
instructions: string;
|
|
369
|
+
tools?: Record<string, Tool<Context>>;
|
|
370
|
+
actions?: Record<string, RegisteredAction<Context, any, any>>;
|
|
371
|
+
authorize?: (ctx?: Context) => boolean;
|
|
372
|
+
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* When the skill is active:
|
|
376
|
+
* - `"auto"`: once the model starts it, when it's relevant. The default.
|
|
377
|
+
* - `"always"`: on every turn, without being started.
|
|
378
|
+
* - `"manual"`: once the user starts it with its `command`. It's hidden from
|
|
379
|
+
* the model, which can't start it itself.
|
|
380
|
+
*/
|
|
381
|
+
type SkillActivation = "auto" | "always" | "manual";
|
|
382
|
+
type Skill<Context extends Record<string, unknown> = Record<string, unknown>> = SkillDefinition<Context> & ({
|
|
383
|
+
activation?: "auto" | "always";
|
|
384
|
+
/** Lets the user start the skill from chat with `/command`. */
|
|
385
|
+
command?: string;
|
|
386
|
+
} | {
|
|
387
|
+
activation: "manual";
|
|
388
|
+
command: string;
|
|
389
|
+
});
|
|
390
|
+
interface SkillSource<Context extends Record<string, unknown> = Record<string, unknown>> extends SkillSource$1 {
|
|
391
|
+
command?: string;
|
|
392
|
+
activation?: SkillActivation;
|
|
393
|
+
tools?: Record<string, Tool<Context>>;
|
|
394
|
+
actions?: Record<string, RegisteredAction<Context, any, any>>;
|
|
395
|
+
authorize?: (ctx?: Context | undefined) => boolean;
|
|
396
|
+
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
397
|
+
}
|
|
398
|
+
export declare function skill<Context extends Record<string, unknown> = Record<string, unknown>>(definition: Skill<Context>): SkillSource<Context>;
|
|
344
399
|
interface SpanIds {
|
|
345
400
|
traceId: string;
|
|
346
401
|
spanId: string;
|
|
@@ -463,6 +518,7 @@ declare class Tracing {
|
|
|
463
518
|
type MessagePart = UIMessage["parts"][number];
|
|
464
519
|
interface TurnInspection<RequestContext extends Record<string, unknown> = Record<string, unknown>, UserContext extends Record<string, unknown> = Record<string, unknown>> {
|
|
465
520
|
messages?: ModelMessage[];
|
|
521
|
+
continuation?: boolean;
|
|
466
522
|
requestContext?: RequestContext;
|
|
467
523
|
userContext?: UserContext;
|
|
468
524
|
}
|
|
@@ -479,6 +535,8 @@ type CurrentTurnState<RequestContext extends Record<string, unknown>, UserContex
|
|
|
479
535
|
context?: ToolContext<RequestContext, UserContext>;
|
|
480
536
|
inputTools: ToolSet;
|
|
481
537
|
preparedTools: ToolSet;
|
|
538
|
+
activeSkillNames: Set<string>;
|
|
539
|
+
skillSourcesByName?: Promise<Map<string, SkillSource>>;
|
|
482
540
|
unavailableSkillIds: Set<string>;
|
|
483
541
|
skillsSystemBlock: string;
|
|
484
542
|
visibleSkillNames: string[];
|
|
@@ -655,7 +713,7 @@ export declare abstract class Agent<RequestContext extends Record<string, unknow
|
|
|
655
713
|
workspaceTools: boolean;
|
|
656
714
|
sendReasoning: boolean;
|
|
657
715
|
getSkillScriptRunner(): skills.SkillScriptRunner | null;
|
|
658
|
-
protected pruneTurnMessages(messages: ModelMessage[]): ModelMessage[];
|
|
716
|
+
protected pruneTurnMessages(messages: ModelMessage[], continuation?: boolean): ModelMessage[];
|
|
659
717
|
private _prepareTools;
|
|
660
718
|
private _renderSkillsSystemBlock;
|
|
661
719
|
/**
|
|
@@ -666,7 +724,6 @@ export declare abstract class Agent<RequestContext extends Record<string, unknow
|
|
|
666
724
|
private _filterSkillHelperTools;
|
|
667
725
|
private _filterActivateSkillTool;
|
|
668
726
|
private _skillSources?;
|
|
669
|
-
private _skillSourcesByName?;
|
|
670
727
|
private _getUnauthorizedReason;
|
|
671
728
|
private _getSkillSources;
|
|
672
729
|
/** Each skill's source, by the skill's name. A source can hold several skills. */
|
|
@@ -703,12 +760,10 @@ export declare abstract class Agent<RequestContext extends Record<string, unknow
|
|
|
703
760
|
private _withTurnContextFallback;
|
|
704
761
|
/** The current turn's tool context, for every tool prepared for the turn. */
|
|
705
762
|
private _toolsContext;
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
private _activeSkillName;
|
|
711
|
-
private _getLastActivatedSkillName;
|
|
763
|
+
private _skillTurnStart;
|
|
764
|
+
private _activeSkillNamesForTurn;
|
|
765
|
+
private _activatedSkillNames;
|
|
766
|
+
private _getActivatedSkillNames;
|
|
712
767
|
/**
|
|
713
768
|
* The caller's identity, user context and credentials, kept until the
|
|
714
769
|
* token expires so turns after hibernation, and scheduled turns, can still
|
|
@@ -796,61 +851,6 @@ type MessageFeedback = {
|
|
|
796
851
|
created_at: number;
|
|
797
852
|
updated_at: number;
|
|
798
853
|
};
|
|
799
|
-
/** Tool execution options plus the additional context supplied by native Think actions. */
|
|
800
|
-
type ActionContext<Context extends Record<string, unknown> = Record<string, unknown>> = ToolExecutionOptions<Context> & ActionContext$1 & {
|
|
801
|
-
/** The action's resolved domain key, or its tool-call fallback when none was declared. */
|
|
802
|
-
idempotencyKey: string;
|
|
803
|
-
};
|
|
804
|
-
type Action<Context extends Record<string, unknown> = Record<string, unknown>, Input = any, Output = any> = Omit<ActionConfig<FlexibleSchema<Input>, Output>, "approval" | "execute" | "idempotencyKey" | "inputSchema" | "permissions"> & {
|
|
805
|
-
description: string;
|
|
806
|
-
inputSchema: FlexibleSchema<Input>;
|
|
807
|
-
approval?: ActionApprovalPolicy<Input>;
|
|
808
|
-
idempotencyKey?: ActionIdempotencyKey<Input>;
|
|
809
|
-
permissions?: ActionPermissionSpec<Input>;
|
|
810
|
-
authorize?: (ctx?: Context) => boolean;
|
|
811
|
-
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
812
|
-
execute(input: Input, ctx: ActionContext<Context>): Promise<Output> | Output;
|
|
813
|
-
};
|
|
814
|
-
type RegisteredAction<Context extends Record<string, unknown> = Record<string, unknown>, InputSchema extends FlexibleSchema = FlexibleSchema, Output = unknown> = Action$1<InputSchema, Output> & {
|
|
815
|
-
authorize?: (ctx?: Context) => boolean;
|
|
816
|
-
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
817
|
-
};
|
|
818
|
-
/** A native Think action with the SDK's standard authorization policy. */
|
|
819
|
-
export declare function action<Context extends Record<string, unknown> = Record<string, unknown>, Input = any, Output = any>(definition: Action<Context, Input, Output>): RegisteredAction<Context, FlexibleSchema<Input>, Output>;
|
|
820
|
-
interface SkillDefinition<Context extends Record<string, unknown>> {
|
|
821
|
-
name: string;
|
|
822
|
-
description: string;
|
|
823
|
-
instructions: string;
|
|
824
|
-
tools?: Record<string, Tool<Context>>;
|
|
825
|
-
actions?: Record<string, RegisteredAction<Context, any, any>>;
|
|
826
|
-
authorize?: (ctx?: Context) => boolean;
|
|
827
|
-
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
828
|
-
}
|
|
829
|
-
/**
|
|
830
|
-
* When the skill is active:
|
|
831
|
-
* - `"auto"`: once the model starts it, when it's relevant. The default.
|
|
832
|
-
* - `"always"`: on every turn, without being started.
|
|
833
|
-
* - `"manual"`: once the user starts it with its `command`. It's hidden from
|
|
834
|
-
* the model, which can't start it itself.
|
|
835
|
-
*/
|
|
836
|
-
type SkillActivation = "auto" | "always" | "manual";
|
|
837
|
-
type Skill<Context extends Record<string, unknown> = Record<string, unknown>> = SkillDefinition<Context> & ({
|
|
838
|
-
activation?: "auto" | "always";
|
|
839
|
-
/** Lets the user start the skill from chat with `/command`. */
|
|
840
|
-
command?: string;
|
|
841
|
-
} | {
|
|
842
|
-
activation: "manual";
|
|
843
|
-
command: string;
|
|
844
|
-
});
|
|
845
|
-
interface SkillSource<Context extends Record<string, unknown> = Record<string, unknown>> extends SkillSource$1 {
|
|
846
|
-
command?: string;
|
|
847
|
-
activation?: SkillActivation;
|
|
848
|
-
tools?: Record<string, Tool<Context>>;
|
|
849
|
-
actions?: Record<string, RegisteredAction<Context, any, any>>;
|
|
850
|
-
authorize?: (ctx?: Context | undefined) => boolean;
|
|
851
|
-
onUnauthorized?: UnauthorizedPolicy<Context>;
|
|
852
|
-
}
|
|
853
|
-
export declare function skill<Context extends Record<string, unknown> = Record<string, unknown>>(definition: Skill<Context>): SkillSource<Context>;
|
|
854
854
|
interface InvocableSkill {
|
|
855
855
|
/** Slash command without the leading `/`. */
|
|
856
856
|
command: string;
|
package/dist/index.mjs
CHANGED
|
@@ -2180,6 +2180,7 @@ var Agent = class Agent extends Think {
|
|
|
2180
2180
|
_turn = {
|
|
2181
2181
|
inputTools: {},
|
|
2182
2182
|
preparedTools: {},
|
|
2183
|
+
activeSkillNames: /* @__PURE__ */ new Set(),
|
|
2183
2184
|
unavailableSkillIds: /* @__PURE__ */ new Set(),
|
|
2184
2185
|
skillsSystemBlock: "",
|
|
2185
2186
|
visibleSkillNames: [],
|
|
@@ -2206,14 +2207,15 @@ var Agent = class Agent extends Think {
|
|
|
2206
2207
|
*/
|
|
2207
2208
|
async beforeTurn(ctx) {
|
|
2208
2209
|
await this._inspection;
|
|
2210
|
+
this._turn.skillSourcesByName = void 0;
|
|
2209
2211
|
this._turn.context = this.createToolContextForCurrentTurn(ctx.body);
|
|
2210
2212
|
const config = await this.getAgentConfig(this._turn.context);
|
|
2211
2213
|
if (config.inputSchema && !ctx.continuation) this._refuseUnexpectedInput(config.inputSchema);
|
|
2212
2214
|
this.tracing.turnStarted(ctx.messages, ctx.continuation);
|
|
2213
2215
|
this.registerInstanceActivity();
|
|
2214
|
-
|
|
2216
|
+
this._turn.activeSkillNames = await this._activeSkillNamesForTurn(ctx.messages, ctx.continuation);
|
|
2215
2217
|
this._turn.inputTools = ctx.tools;
|
|
2216
|
-
const { tools, activeTools } = await this._prepareTools(ctx.tools,
|
|
2218
|
+
const { tools, activeTools } = await this._prepareTools(ctx.tools, this._turn.activeSkillNames, true);
|
|
2217
2219
|
const baseSystem = await this.context.refreshSystemPrompt();
|
|
2218
2220
|
this._turn.baseSystem = [baseSystem, this._turn.skillsSystemBlock].filter(Boolean).join("\n\n");
|
|
2219
2221
|
const turnTracing = await this.tracing.turn(this._turn.context ?? {}, this.messages);
|
|
@@ -2231,7 +2233,7 @@ var Agent = class Agent extends Think {
|
|
|
2231
2233
|
...config.outputSchema && { output: Output.object({ schema: config.outputSchema }) },
|
|
2232
2234
|
system: this._turn.baseSystem,
|
|
2233
2235
|
model: this.getModel(this._turn.context),
|
|
2234
|
-
messages: this.pruneTurnMessages(ctx.messages),
|
|
2236
|
+
messages: this.pruneTurnMessages(ctx.messages, ctx.continuation),
|
|
2235
2237
|
tools: this._withTurnContextFallback(this._withTaskToolExecution(tools)),
|
|
2236
2238
|
activeTools,
|
|
2237
2239
|
experimental_transform: buildSourcesTransform(),
|
|
@@ -2263,10 +2265,11 @@ var Agent = class Agent extends Think {
|
|
|
2263
2265
|
* @returns The step config.
|
|
2264
2266
|
*/
|
|
2265
2267
|
async beforeStep(ctx) {
|
|
2266
|
-
const
|
|
2268
|
+
const activatedSkillNames = await this._activatedSkillNames(ctx.steps);
|
|
2267
2269
|
const toolsContext = this._toolsContext();
|
|
2268
|
-
if (
|
|
2269
|
-
const
|
|
2270
|
+
if (activatedSkillNames.length === 0) return { toolsContext };
|
|
2271
|
+
for (const name of activatedSkillNames) this._turn.activeSkillNames.add(name);
|
|
2272
|
+
const { activeTools } = await this._prepareTools(this._turn.inputTools, this._turn.activeSkillNames);
|
|
2270
2273
|
return {
|
|
2271
2274
|
activeTools,
|
|
2272
2275
|
system: this._turn.baseSystem,
|
|
@@ -2280,6 +2283,10 @@ var Agent = class Agent extends Think {
|
|
|
2280
2283
|
async beforeToolCall(ctx) {
|
|
2281
2284
|
const toolCtx = this._turn.context ?? {};
|
|
2282
2285
|
const skill = await this._skillOfCall(ctx.toolName, ctx.input);
|
|
2286
|
+
if (SKILL_TOOL_NAMES.has(ctx.toolName) && !skill) return {
|
|
2287
|
+
action: "block",
|
|
2288
|
+
reason: GENERIC_UNAVAILABLE_TOOL_GUIDANCE
|
|
2289
|
+
};
|
|
2283
2290
|
if (skill?.authorize?.(toolCtx) === false) return {
|
|
2284
2291
|
action: "block",
|
|
2285
2292
|
reason: this._getUnauthorizedReason(skill.onUnauthorized, toolCtx) ?? "Say naturally that you don't have that capability, then stop. Do not mention tools, apologize, invent a reason or remedy, or offer further help."
|
|
@@ -2563,6 +2570,7 @@ var Agent = class Agent extends Think {
|
|
|
2563
2570
|
},
|
|
2564
2571
|
inputTools: {},
|
|
2565
2572
|
preparedTools: {},
|
|
2573
|
+
activeSkillNames: /* @__PURE__ */ new Set(),
|
|
2566
2574
|
unavailableSkillIds: /* @__PURE__ */ new Set(),
|
|
2567
2575
|
skillsSystemBlock: "",
|
|
2568
2576
|
visibleSkillNames: [],
|
|
@@ -2583,7 +2591,8 @@ var Agent = class Agent extends Think {
|
|
|
2583
2591
|
...frameworkTools
|
|
2584
2592
|
};
|
|
2585
2593
|
this._turn.inputTools = inputTools;
|
|
2586
|
-
|
|
2594
|
+
this._turn.activeSkillNames = await this._activeSkillNamesForTurn(messages, input.continuation);
|
|
2595
|
+
const { tools, activeTools } = await this._prepareTools(inputTools, this._turn.activeSkillNames, true);
|
|
2587
2596
|
const baseSystem = await this.context.refreshSystemPrompt();
|
|
2588
2597
|
this._turn.baseSystem = [baseSystem, this._turn.skillsSystemBlock].filter(Boolean).join("\n\n");
|
|
2589
2598
|
const snapshotContext = this._turn.context;
|
|
@@ -2592,7 +2601,7 @@ var Agent = class Agent extends Think {
|
|
|
2592
2601
|
tools: withFallbackToolContext(this._withTaskToolExecution(tools), () => snapshotContext),
|
|
2593
2602
|
activeTools,
|
|
2594
2603
|
frameworkToolNames: Object.keys(frameworkTools),
|
|
2595
|
-
messages: this.pruneTurnMessages(messages)
|
|
2604
|
+
messages: this.pruneTurnMessages(messages, input.continuation)
|
|
2596
2605
|
};
|
|
2597
2606
|
} finally {
|
|
2598
2607
|
this._turn = previousTurn;
|
|
@@ -2610,19 +2619,21 @@ var Agent = class Agent extends Think {
|
|
|
2610
2619
|
if (!("LOADER" in this.env)) return null;
|
|
2611
2620
|
return skills.runner({ loader: this.env.LOADER });
|
|
2612
2621
|
}
|
|
2613
|
-
pruneTurnMessages(messages) {
|
|
2622
|
+
pruneTurnMessages(messages, continuation = false) {
|
|
2623
|
+
const turnStart = this._skillTurnStart(messages, continuation);
|
|
2624
|
+
const retainedSkillMessages = Math.max(5, messages.length - turnStart);
|
|
2614
2625
|
return pruneMessages({
|
|
2615
2626
|
messages,
|
|
2616
2627
|
toolCalls: [{
|
|
2617
2628
|
type: "before-last-2-messages",
|
|
2618
2629
|
tools: []
|
|
2619
2630
|
}, {
|
|
2620
|
-
type:
|
|
2631
|
+
type: `before-last-${retainedSkillMessages}-messages`,
|
|
2621
2632
|
tools: ["activate_skill"]
|
|
2622
2633
|
}]
|
|
2623
2634
|
});
|
|
2624
2635
|
}
|
|
2625
|
-
async _prepareTools(inputTools,
|
|
2636
|
+
async _prepareTools(inputTools, activeSkillNames, updateSkillsSystemBlock = false) {
|
|
2626
2637
|
const ctx = this._turn.context;
|
|
2627
2638
|
const tools = {};
|
|
2628
2639
|
const activeTools = [];
|
|
@@ -2720,8 +2731,16 @@ var Agent = class Agent extends Think {
|
|
|
2720
2731
|
this._turn.authorizedSkillNames = /* @__PURE__ */ new Set([...catalog.authorizedSkillNames, ...await skillNames(manualSkillSources)]);
|
|
2721
2732
|
}
|
|
2722
2733
|
this._filterActivateSkillTool(tools, activeTools, this._turn.visibleSkillNames);
|
|
2723
|
-
const
|
|
2724
|
-
if (
|
|
2734
|
+
const activeSources = /* @__PURE__ */ new Set();
|
|
2735
|
+
if (activeSkillNames.size > 0) {
|
|
2736
|
+
const sourcesByName = await this._getSkillSourcesByName();
|
|
2737
|
+
for (const name of activeSkillNames) {
|
|
2738
|
+
const source = sourcesByName.get(name);
|
|
2739
|
+
if (source) activeSources.add(source);
|
|
2740
|
+
}
|
|
2741
|
+
}
|
|
2742
|
+
for (const activeSkill of skillSources) {
|
|
2743
|
+
if (!activeSources.has(activeSkill) || skillAuthorization.get(activeSkill) === false) continue;
|
|
2725
2744
|
const activeSkillTools = Object.entries(activeSkill.tools ?? {});
|
|
2726
2745
|
for (const [registrationName, definition] of Object.entries(activeSkill.actions ?? {})) {
|
|
2727
2746
|
const name = actionToolName(registrationName, definition);
|
|
@@ -2730,7 +2749,7 @@ var Agent = class Agent extends Think {
|
|
|
2730
2749
|
}
|
|
2731
2750
|
for (const [name, tool] of activeSkillTools) if (configureTool(name, tool, actionsByToolName.get(name) ?? tool)) activeTools.push(name);
|
|
2732
2751
|
}
|
|
2733
|
-
if (!hasAlwaysActiveSkill) this._filterSkillHelperTools(activeTools,
|
|
2752
|
+
if (!hasAlwaysActiveSkill) this._filterSkillHelperTools(activeTools, activeSkillNames);
|
|
2734
2753
|
this._turn.preparedTools = tools;
|
|
2735
2754
|
return {
|
|
2736
2755
|
tools,
|
|
@@ -2777,8 +2796,8 @@ var Agent = class Agent extends Think {
|
|
|
2777
2796
|
provider: { get: async () => source.authorize?.(this._turn.context) !== false && !this._turn.unavailableSkillIds.has(source.id) ? (await source.load(name))?.body.trim() ?? "" : "" }
|
|
2778
2797
|
}))))).flat();
|
|
2779
2798
|
}
|
|
2780
|
-
_filterSkillHelperTools(activeTools,
|
|
2781
|
-
|
|
2799
|
+
_filterSkillHelperTools(activeTools, activeSkillNames) {
|
|
2800
|
+
for (const name of activeSkillNames) if (this._turn.authorizedSkillNames.has(name)) return;
|
|
2782
2801
|
for (const name of SKILL_HELPER_TOOL_NAMES) {
|
|
2783
2802
|
const index = activeTools.indexOf(name);
|
|
2784
2803
|
if (index !== -1) activeTools.splice(index, 1);
|
|
@@ -2806,7 +2825,6 @@ var Agent = class Agent extends Think {
|
|
|
2806
2825
|
};
|
|
2807
2826
|
}
|
|
2808
2827
|
_skillSources;
|
|
2809
|
-
_skillSourcesByName;
|
|
2810
2828
|
_getUnauthorizedReason(policy, ctx) {
|
|
2811
2829
|
return typeof policy === "function" ? policy(ctx) : policy;
|
|
2812
2830
|
}
|
|
@@ -2815,9 +2833,14 @@ var Agent = class Agent extends Think {
|
|
|
2815
2833
|
}
|
|
2816
2834
|
/** Each skill's source, by the skill's name. A source can hold several skills. */
|
|
2817
2835
|
_getSkillSourcesByName() {
|
|
2818
|
-
return this.
|
|
2836
|
+
return this._turn.skillSourcesByName ??= this._getSkillSources().then(async (sources) => {
|
|
2819
2837
|
const byName = /* @__PURE__ */ new Map();
|
|
2820
|
-
for (const source of sources)
|
|
2838
|
+
for (const source of sources) try {
|
|
2839
|
+
for (const descriptor of await source.list()) if (!byName.has(descriptor.name)) byName.set(descriptor.name, source);
|
|
2840
|
+
} catch (error) {
|
|
2841
|
+
console.warn(`[Agent] Failed to resolve skill source "${source.id}"`, error);
|
|
2842
|
+
break;
|
|
2843
|
+
}
|
|
2821
2844
|
return byName;
|
|
2822
2845
|
});
|
|
2823
2846
|
}
|
|
@@ -2864,36 +2887,63 @@ var Agent = class Agent extends Think {
|
|
|
2864
2887
|
const context = this._turn.context ?? {};
|
|
2865
2888
|
return Object.fromEntries(Object.keys(this._turn.preparedTools).map((name) => [name, context]));
|
|
2866
2889
|
}
|
|
2867
|
-
|
|
2868
|
-
|
|
2869
|
-
|
|
2870
|
-
|
|
2871
|
-
|
|
2872
|
-
const manual = await skillNames((await this._getSkillSources()).filter((source) => source.activation === "manual"));
|
|
2873
|
-
return this._getLastActivatedSkillName(items, new Set(manual));
|
|
2874
|
-
}
|
|
2875
|
-
_getLastActivatedSkillName(items = [], manualSkillNames) {
|
|
2876
|
-
for (let index = items.length - 1; index >= 0; index--) {
|
|
2877
|
-
const item = items[index];
|
|
2878
|
-
if (!item || typeof item !== "object") continue;
|
|
2879
|
-
const record = item;
|
|
2880
|
-
const input = record.input;
|
|
2881
|
-
if ((record.toolName === "activate_skill" || record.type === "tool-activate_skill") && input && typeof input === "object") {
|
|
2882
|
-
const { name } = input;
|
|
2883
|
-
if (typeof name === "string" && (!manualSkillNames.has(name) || String(record.toolCallId).startsWith("skill-command-"))) return name;
|
|
2890
|
+
_skillTurnStart(messages, continuation) {
|
|
2891
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
2892
|
+
if (messages[index].role !== "user") continue;
|
|
2893
|
+
if (continuation && index === messages.length - 1) {
|
|
2894
|
+
if (this.messages.at(-1)?.role !== "user") continue;
|
|
2884
2895
|
}
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
|
|
2888
|
-
|
|
2889
|
-
|
|
2890
|
-
|
|
2891
|
-
|
|
2892
|
-
|
|
2893
|
-
|
|
2896
|
+
return index + 1;
|
|
2897
|
+
}
|
|
2898
|
+
return 0;
|
|
2899
|
+
}
|
|
2900
|
+
async _activeSkillNamesForTurn(messages, continuation = false) {
|
|
2901
|
+
const turnStart = this._skillTurnStart(messages, continuation);
|
|
2902
|
+
const previousSkills = await this._activatedSkillNames(messages.slice(0, turnStart));
|
|
2903
|
+
const currentSkills = await this._activatedSkillNames(messages.slice(turnStart));
|
|
2904
|
+
const previousSkill = previousSkills.at(-1);
|
|
2905
|
+
return new Set(previousSkill ? [previousSkill, ...currentSkills] : currentSkills);
|
|
2906
|
+
}
|
|
2907
|
+
async _activatedSkillNames(items) {
|
|
2908
|
+
const manual = await skillNames((await this._getSkillSources()).filter((source) => source.activation === "manual"));
|
|
2909
|
+
return this._getActivatedSkillNames(items, new Set(manual));
|
|
2910
|
+
}
|
|
2911
|
+
_getActivatedSkillNames(items, manualSkillNames) {
|
|
2912
|
+
const calls = /* @__PURE__ */ new Map();
|
|
2913
|
+
const outputs = /* @__PURE__ */ new Map();
|
|
2914
|
+
const collect = (entries) => {
|
|
2915
|
+
for (const item of entries) {
|
|
2916
|
+
if (!item || typeof item !== "object") continue;
|
|
2917
|
+
const record = item;
|
|
2918
|
+
const { type, toolCallId, input } = record;
|
|
2919
|
+
const uiActivation = type === "tool-activate_skill";
|
|
2920
|
+
if (typeof toolCallId === "string" && (uiActivation || record.toolName === "activate_skill")) {
|
|
2921
|
+
if ((type === "tool-call" || uiActivation) && input && typeof input === "object") {
|
|
2922
|
+
const { name } = input;
|
|
2923
|
+
if (typeof name === "string" && !calls.has(toolCallId)) calls.set(toolCallId, name);
|
|
2924
|
+
}
|
|
2925
|
+
if (type === "tool-result" && !record.preliminary || uiActivation && record.state === "output-available") outputs.set(toolCallId, record.output);
|
|
2926
|
+
}
|
|
2927
|
+
for (const key of [
|
|
2928
|
+
"content",
|
|
2929
|
+
"parts",
|
|
2930
|
+
"toolCalls",
|
|
2931
|
+
"toolResults"
|
|
2932
|
+
]) {
|
|
2933
|
+
const nestedItems = record[key];
|
|
2934
|
+
if (Array.isArray(nestedItems)) collect(nestedItems);
|
|
2894
2935
|
}
|
|
2895
2936
|
}
|
|
2937
|
+
};
|
|
2938
|
+
collect(items);
|
|
2939
|
+
const names = [];
|
|
2940
|
+
for (const [toolCallId, name] of calls) {
|
|
2941
|
+
if (manualSkillNames.has(name) && !toolCallId.startsWith("skill-command-")) continue;
|
|
2942
|
+
let output = outputs.get(toolCallId);
|
|
2943
|
+
if (output && typeof output === "object" && "type" in output && output.type === "text") output = "value" in output ? output.value : void 0;
|
|
2944
|
+
if (typeof output === "string" && output.startsWith(`<skill_content name="${name}"`)) names.push(name);
|
|
2896
2945
|
}
|
|
2946
|
+
return names;
|
|
2897
2947
|
}
|
|
2898
2948
|
/**
|
|
2899
2949
|
* The caller's identity, user context and credentials, kept until the
|
|
@@ -3618,22 +3668,20 @@ var Assistant = class extends Agent$1 {
|
|
|
3618
3668
|
};
|
|
3619
3669
|
const COMPACTION_MAX_OUTPUT_TOKENS = 2e3;
|
|
3620
3670
|
const COMPACTION_HEAD_MESSAGES = 2;
|
|
3671
|
+
const COMPACTION_TAIL_MESSAGES = 1;
|
|
3621
3672
|
const COMPACTION_MESSAGE_CHARS = 2e4;
|
|
3622
3673
|
const MODEL_COMPACTION_MESSAGE_ID = "compaction_model_context";
|
|
3623
|
-
/**
|
|
3624
|
-
* Summarizes everything between the first two messages and the newest one, so
|
|
3625
|
-
* a single large answer is compacted before the prompt that follows it.
|
|
3626
|
-
*/
|
|
3674
|
+
/** Summarizes older content while retaining the latest request and active skill exchanges. */
|
|
3627
3675
|
const createCompactFn = (model) => async (messages) => {
|
|
3628
|
-
const
|
|
3629
|
-
const previous =
|
|
3630
|
-
const
|
|
3631
|
-
const first =
|
|
3632
|
-
const last =
|
|
3676
|
+
const { compacted } = partitionCompactionRange(messages, COMPACTION_HEAD_MESSAGES, messages.length - COMPACTION_TAIL_MESSAGES - 1);
|
|
3677
|
+
const previous = compacted.find((message) => message.id === MODEL_COMPACTION_MESSAGE_ID);
|
|
3678
|
+
const candidates = compacted.filter((message) => message.id !== MODEL_COMPACTION_MESSAGE_ID);
|
|
3679
|
+
const first = candidates[0];
|
|
3680
|
+
const last = candidates.at(-1);
|
|
3633
3681
|
if (!first || !last) return null;
|
|
3634
3682
|
const { text } = await generateText({
|
|
3635
3683
|
model,
|
|
3636
|
-
prompt: summaryPrompt(
|
|
3684
|
+
prompt: summaryPrompt(candidates, previous),
|
|
3637
3685
|
maxOutputTokens: COMPACTION_MAX_OUTPUT_TOKENS
|
|
3638
3686
|
});
|
|
3639
3687
|
if (!text.trim()) return null;
|
|
@@ -3718,6 +3766,40 @@ function migrateSessionCompaction(sql) {
|
|
|
3718
3766
|
sql`DELETE FROM cf_agents_session_compactions WHERE session_id = ''`;
|
|
3719
3767
|
return true;
|
|
3720
3768
|
}
|
|
3769
|
+
function partitionCompactionRange(messages, from, to) {
|
|
3770
|
+
const turnStart = messages.findLastIndex((message) => message.role === "user");
|
|
3771
|
+
const retained = [];
|
|
3772
|
+
const compacted = [];
|
|
3773
|
+
for (let index = from; index <= to; index++) {
|
|
3774
|
+
const message = messages[index];
|
|
3775
|
+
if (index === turnStart) {
|
|
3776
|
+
retained.push(message);
|
|
3777
|
+
continue;
|
|
3778
|
+
}
|
|
3779
|
+
const retainedParts = [];
|
|
3780
|
+
const compactedParts = [];
|
|
3781
|
+
for (const part of message.parts) if (part.type === "step-start") retainedParts.push(part);
|
|
3782
|
+
else if (index > turnStart && message.role === "assistant" && retainTurnToolPart(part)) retainedParts.push(part);
|
|
3783
|
+
else compactedParts.push(part);
|
|
3784
|
+
if (retainedParts.some((part) => part.type !== "step-start")) retained.push({
|
|
3785
|
+
...message,
|
|
3786
|
+
parts: retainedParts
|
|
3787
|
+
});
|
|
3788
|
+
if (compactedParts.length > 0) compacted.push({
|
|
3789
|
+
...message,
|
|
3790
|
+
parts: compactedParts
|
|
3791
|
+
});
|
|
3792
|
+
}
|
|
3793
|
+
return {
|
|
3794
|
+
retained,
|
|
3795
|
+
compacted
|
|
3796
|
+
};
|
|
3797
|
+
}
|
|
3798
|
+
function retainTurnToolPart(part) {
|
|
3799
|
+
if (!isToolUIPart(part)) return false;
|
|
3800
|
+
if (getToolName(part) === "activate_skill" || part.approval) return true;
|
|
3801
|
+
return part.state === "input-streaming" || part.state === "input-available" || part.state === "output-available" && part.preliminary === true;
|
|
3802
|
+
}
|
|
3721
3803
|
function applyModelCompaction(messages, state) {
|
|
3722
3804
|
const fromIndex = messages.findIndex((message) => message.id === state.fromMessageId);
|
|
3723
3805
|
const toIndex = messages.findIndex((message) => message.id === state.toMessageId);
|
|
@@ -3732,6 +3814,7 @@ function applyModelCompaction(messages, state) {
|
|
|
3732
3814
|
text: state.summary
|
|
3733
3815
|
}]
|
|
3734
3816
|
},
|
|
3817
|
+
...partitionCompactionRange(messages, fromIndex, toIndex).retained,
|
|
3735
3818
|
...messages.slice(toIndex + 1)
|
|
3736
3819
|
];
|
|
3737
3820
|
}
|
|
@@ -3756,10 +3839,23 @@ async function prepareModelHistory(messages, existingState, compact, systemPromp
|
|
|
3756
3839
|
state,
|
|
3757
3840
|
stateChanged
|
|
3758
3841
|
};
|
|
3842
|
+
let fromIndex = messages.findIndex((message) => message.id === result.fromMessageId);
|
|
3843
|
+
let toIndex = messages.findIndex((message) => message.id === result.toMessageId);
|
|
3844
|
+
if (fromIndex === -1 || toIndex < fromIndex) return {
|
|
3845
|
+
messages: projected,
|
|
3846
|
+
state,
|
|
3847
|
+
stateChanged
|
|
3848
|
+
};
|
|
3849
|
+
if (state) {
|
|
3850
|
+
const previousStart = messages.findIndex((message) => message.id === state.fromMessageId);
|
|
3851
|
+
const previousEnd = messages.findIndex((message) => message.id === state.toMessageId);
|
|
3852
|
+
fromIndex = Math.min(previousStart, fromIndex);
|
|
3853
|
+
toIndex = Math.max(previousEnd, toIndex);
|
|
3854
|
+
}
|
|
3759
3855
|
const nextState = {
|
|
3760
3856
|
summary: result.summary,
|
|
3761
|
-
fromMessageId:
|
|
3762
|
-
toMessageId:
|
|
3857
|
+
fromMessageId: messages[fromIndex].id,
|
|
3858
|
+
toMessageId: messages[toIndex].id
|
|
3763
3859
|
};
|
|
3764
3860
|
const nextProjection = applyModelCompaction(messages, nextState);
|
|
3765
3861
|
if (!nextProjection) return {
|
|
@@ -3797,6 +3893,7 @@ async function withModelCompaction(modelMessages, transcript, state, tools) {
|
|
|
3797
3893
|
text: state.summary
|
|
3798
3894
|
}]
|
|
3799
3895
|
},
|
|
3896
|
+
...await convert(partitionCompactionRange(transcript, from, to).retained),
|
|
3800
3897
|
...modelMessages.slice((await convert(transcript.slice(0, to + 1))).length)
|
|
3801
3898
|
];
|
|
3802
3899
|
}
|
|
@@ -4098,7 +4195,7 @@ var ChatAgent = class extends Agent {
|
|
|
4098
4195
|
const messages = await withModelCompaction(ctx.messages, this.messages, prepared.state, tools);
|
|
4099
4196
|
if (messages) return {
|
|
4100
4197
|
...config,
|
|
4101
|
-
messages: this.pruneTurnMessages([...messages, ...skillInvocation?.messages ?? []])
|
|
4198
|
+
messages: this.pruneTurnMessages([...messages, ...skillInvocation?.messages ?? []], ctx.continuation)
|
|
4102
4199
|
};
|
|
4103
4200
|
}
|
|
4104
4201
|
} catch (error) {
|