agency-lang 0.0.80 → 0.0.82
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/lib/backends/agencyGenerator.js +4 -2
- package/dist/lib/backends/typescriptGenerator.d.ts +11 -0
- package/dist/lib/backends/typescriptGenerator.js +43 -0
- package/dist/lib/parsers/importStatement.js +18 -1
- package/dist/lib/parsers/importStatement.test.js +64 -4
- package/dist/lib/runtime/errors.d.ts +7 -0
- package/dist/lib/runtime/errors.js +12 -0
- package/dist/lib/runtime/index.d.ts +1 -0
- package/dist/lib/runtime/index.js +1 -0
- package/dist/lib/runtime/prompt.d.ts +1 -0
- package/dist/lib/runtime/prompt.js +42 -3
- package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/functionDefinition.js +7 -0
- package/dist/lib/templates/backends/typescriptGenerator/imports.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/imports.js +1 -0
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.d.ts +1 -1
- package/dist/lib/templates/backends/typescriptGenerator/promptFunction.js +3 -1
- package/dist/lib/types/importStatement.d.ts +1 -0
- package/package.json +2 -2
|
@@ -390,8 +390,10 @@ export class AgencyGenerator extends BaseGenerator {
|
|
|
390
390
|
}
|
|
391
391
|
processImportNameType(node) {
|
|
392
392
|
switch (node.type) {
|
|
393
|
-
case "namedImport":
|
|
394
|
-
|
|
393
|
+
case "namedImport": {
|
|
394
|
+
const names = node.importedNames.map((name) => node.safeNames?.includes(name) ? `safe ${name}` : name);
|
|
395
|
+
return `{ ${names.join(", ")} }`;
|
|
396
|
+
}
|
|
395
397
|
case "namespaceImport":
|
|
396
398
|
return `* as ${node.importedNames}`;
|
|
397
399
|
case "defaultImport":
|
|
@@ -24,6 +24,8 @@ export declare class TypeScriptGenerator extends BaseGenerator {
|
|
|
24
24
|
protected isInsideGraphNode: boolean;
|
|
25
25
|
private parallelThreadVars;
|
|
26
26
|
private loopVars;
|
|
27
|
+
protected safeFunctions: Record<string, boolean>;
|
|
28
|
+
protected importedFunctions: Record<string, boolean>;
|
|
27
29
|
constructor(args?: {
|
|
28
30
|
config?: AgencyConfig;
|
|
29
31
|
});
|
|
@@ -104,6 +106,15 @@ export declare class TypeScriptGenerator extends BaseGenerator {
|
|
|
104
106
|
private agencyFileToDefaultImportName;
|
|
105
107
|
protected preprocess(): string;
|
|
106
108
|
protected postprocess(): string;
|
|
109
|
+
/**
|
|
110
|
+
* Check if a function name refers to an impure imported function
|
|
111
|
+
* (imported from TS, not marked safe).
|
|
112
|
+
*/
|
|
113
|
+
protected isImpureImportedFunction(functionName: string): boolean;
|
|
114
|
+
/**
|
|
115
|
+
* Check if an AST node (or its children) contains a call to an impure imported function.
|
|
116
|
+
*/
|
|
117
|
+
protected containsImpureCall(node: AgencyNode): boolean;
|
|
107
118
|
protected processBodyAsParts(body: AgencyNode[]): string[];
|
|
108
119
|
protected processKeyword(node: Keyword): string;
|
|
109
120
|
protected scopetoString(scope: ScopeType, varName?: string): string;
|
|
@@ -34,6 +34,8 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
34
34
|
isInsideGraphNode = false;
|
|
35
35
|
parallelThreadVars = {};
|
|
36
36
|
loopVars = [];
|
|
37
|
+
safeFunctions = {};
|
|
38
|
+
importedFunctions = {};
|
|
37
39
|
constructor(args = {}) {
|
|
38
40
|
super(args);
|
|
39
41
|
}
|
|
@@ -629,6 +631,19 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
629
631
|
});
|
|
630
632
|
}
|
|
631
633
|
processImportStatement(node) {
|
|
634
|
+
// Track safe and imported functions from named imports
|
|
635
|
+
for (const nameType of node.importedNames) {
|
|
636
|
+
if (nameType.type === "namedImport") {
|
|
637
|
+
for (const name of nameType.importedNames) {
|
|
638
|
+
this.importedFunctions[name] = true;
|
|
639
|
+
}
|
|
640
|
+
if (nameType.safeNames) {
|
|
641
|
+
for (const safeName of nameType.safeNames) {
|
|
642
|
+
this.safeFunctions[safeName] = true;
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
}
|
|
646
|
+
}
|
|
632
647
|
const importedNames = node.importedNames.map((name) => this.processImportNameType(name));
|
|
633
648
|
return `import ${importedNames.join(", ")} from "${node.modulePath.replace(/\.agency$/, ".js")}";`;
|
|
634
649
|
}
|
|
@@ -918,6 +933,30 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
918
933
|
lines.push("export default graph;");
|
|
919
934
|
return lines.join("\n");
|
|
920
935
|
}
|
|
936
|
+
/**
|
|
937
|
+
* Check if a function name refers to an impure imported function
|
|
938
|
+
* (imported from TS, not marked safe).
|
|
939
|
+
*/
|
|
940
|
+
isImpureImportedFunction(functionName) {
|
|
941
|
+
return (!!this.importedFunctions[functionName] &&
|
|
942
|
+
!this.safeFunctions[functionName]);
|
|
943
|
+
}
|
|
944
|
+
/**
|
|
945
|
+
* Check if an AST node (or its children) contains a call to an impure imported function.
|
|
946
|
+
*/
|
|
947
|
+
containsImpureCall(node) {
|
|
948
|
+
if (node.type === "functionCall") {
|
|
949
|
+
if (this.isImpureImportedFunction(node.functionName)) {
|
|
950
|
+
return true;
|
|
951
|
+
}
|
|
952
|
+
}
|
|
953
|
+
if (node.type === "assignment" && node.value) {
|
|
954
|
+
if (this.containsImpureCall(node.value)) {
|
|
955
|
+
return true;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
return false;
|
|
959
|
+
}
|
|
921
960
|
/* This generates the body of a node or function separated into multiple parts.
|
|
922
961
|
You can think of a part as roughly corresponding to a single statement
|
|
923
962
|
(although some statements don't need their own parts, such as a newlines or type definitions).
|
|
@@ -934,6 +973,10 @@ export class TypeScriptGenerator extends BaseGenerator {
|
|
|
934
973
|
if (!TYPES_THAT_DONT_TRIGGER_NEW_PART.includes(stmt.type)) {
|
|
935
974
|
parts.push([]);
|
|
936
975
|
}
|
|
976
|
+
// Inject __self.__retryable = false before impure imported function calls
|
|
977
|
+
if (this.containsImpureCall(stmt)) {
|
|
978
|
+
parts[parts.length - 1].push("__self.__retryable = false;\n");
|
|
979
|
+
}
|
|
937
980
|
parts[parts.length - 1].push(this.processStatement(stmt));
|
|
938
981
|
}
|
|
939
982
|
const bodyCode = [];
|
|
@@ -7,7 +7,24 @@ const singleQuotedPath = seqC(char("'"), capture(many1Till(char("'")), "path"),
|
|
|
7
7
|
const quotedPath = map(or(doubleQuotedPath, singleQuotedPath), (res) => res.path);
|
|
8
8
|
export const importNodeStatmentParser = trace("importNodeStatement", seqC(set("type", "importNodeStatement"), str("import"), spaces, or(str("nodes"), str("node")), captureCaptures(parseError("expected a statement of the form `import nodes { x, y } from 'filename.agency'`", spaces, char("{"), optionalSpaces, capture(sepBy1(comma, many1WithJoin(alphanum)), "importedNodes"), optionalSpaces, char("}"), spaces, str("from"), spaces, capture(quotedPath, "agencyFile"), optionalSemicolon, optional(newline)))));
|
|
9
9
|
export const importToolStatmentParser = trace("importToolStatement", seqC(set("type", "importToolStatement"), str("import"), spaces, or(str("tools"), str("tool")), captureCaptures(parseError("expected a statement of the form `import tools { x, y } from 'filename.agency'`", spaces, char("{"), optionalSpaces, capture(sepBy1(comma, many1WithJoin(alphanum)), "importedTools"), optionalSpaces, char("}"), spaces, str("from"), spaces, capture(quotedPath, "agencyFile"), optionalSemicolon, optional(newline)))));
|
|
10
|
-
const
|
|
10
|
+
const safeNameItem = or(map(seqC(str("safe "), capture(many1WithJoin(alphanum), "name")), (r) => ({
|
|
11
|
+
name: r.name,
|
|
12
|
+
isSafe: true,
|
|
13
|
+
})), map(seqC(capture(many1WithJoin(alphanum), "name")), (r) => ({
|
|
14
|
+
name: r.name,
|
|
15
|
+
isSafe: false,
|
|
16
|
+
})));
|
|
17
|
+
const namedImportParser = trace("namedImportParser", map(seqC(char("{"), optionalSpaces, capture(sepBy1(comma, safeNameItem), "items"), optionalSpaces, char("}")), (result) => {
|
|
18
|
+
const importedNames = [];
|
|
19
|
+
const safeNames = [];
|
|
20
|
+
for (const item of result.items) {
|
|
21
|
+
importedNames.push(item.name);
|
|
22
|
+
if (item.isSafe) {
|
|
23
|
+
safeNames.push(item.name);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return { type: "namedImport", importedNames, safeNames };
|
|
27
|
+
}));
|
|
11
28
|
const namespaceImportParser = trace("namespaceImportParser", seqC(many1Till(spaces), spaces, str("as"), spaces, capture(many1WithJoin(alphanum), "importedNames"), set("type", "namespaceImport")));
|
|
12
29
|
const defaultImportParser = trace("defaultImportParser", seqC(capture(many1WithJoin(alphanum), "importedNames"), set("type", "defaultImport")));
|
|
13
30
|
const importNameTypeParser = sepBy(comma, or(namedImportParser, namespaceImportParser, defaultImportParser));
|
|
@@ -20,7 +20,9 @@ describe("importStatmentParser", () => {
|
|
|
20
20
|
if (result.success) {
|
|
21
21
|
expect(result.result).toEqual({
|
|
22
22
|
type: "importStatement",
|
|
23
|
-
importedNames: [
|
|
23
|
+
importedNames: [
|
|
24
|
+
{ type: "namedImport", importedNames: ["foo"], safeNames: [] },
|
|
25
|
+
],
|
|
24
26
|
modulePath: "./foo.ts",
|
|
25
27
|
});
|
|
26
28
|
}
|
|
@@ -34,7 +36,7 @@ describe("importStatmentParser", () => {
|
|
|
34
36
|
type: "importStatement",
|
|
35
37
|
importedNames: [
|
|
36
38
|
{ type: "defaultImport", importedNames: "foo" },
|
|
37
|
-
{ type: "namedImport", importedNames: ["bar"] },
|
|
39
|
+
{ type: "namedImport", importedNames: ["bar"], safeNames: [] },
|
|
38
40
|
],
|
|
39
41
|
modulePath: "./foo.ts",
|
|
40
42
|
});
|
|
@@ -85,7 +87,9 @@ describe("importStatmentParser", () => {
|
|
|
85
87
|
if (result.success) {
|
|
86
88
|
expect(result.result).toEqual({
|
|
87
89
|
type: "importStatement",
|
|
88
|
-
importedNames: [
|
|
90
|
+
importedNames: [
|
|
91
|
+
{ type: "namedImport", importedNames: ["foo"], safeNames: [] },
|
|
92
|
+
],
|
|
89
93
|
modulePath: "./foo.agency",
|
|
90
94
|
});
|
|
91
95
|
}
|
|
@@ -105,12 +109,68 @@ describe("importStatmentParser", () => {
|
|
|
105
109
|
expect(result.result).toEqual({
|
|
106
110
|
type: "importStatement",
|
|
107
111
|
importedNames: [
|
|
108
|
-
{
|
|
112
|
+
{
|
|
113
|
+
type: "namedImport",
|
|
114
|
+
importedNames: ["foo", "bar", "baz"],
|
|
115
|
+
safeNames: [],
|
|
116
|
+
},
|
|
109
117
|
],
|
|
110
118
|
modulePath: "myModule",
|
|
111
119
|
});
|
|
112
120
|
}
|
|
113
121
|
});
|
|
122
|
+
// Safe imports
|
|
123
|
+
it('should parse: import { safe foo, bar } from "./tools.js"', () => {
|
|
124
|
+
const result = importStatmentParser('import { safe foo, bar } from "./tools.js"');
|
|
125
|
+
expect(result.success).toBe(true);
|
|
126
|
+
if (result.success) {
|
|
127
|
+
expect(result.result).toEqual({
|
|
128
|
+
type: "importStatement",
|
|
129
|
+
importedNames: [
|
|
130
|
+
{
|
|
131
|
+
type: "namedImport",
|
|
132
|
+
importedNames: ["foo", "bar"],
|
|
133
|
+
safeNames: ["foo"],
|
|
134
|
+
},
|
|
135
|
+
],
|
|
136
|
+
modulePath: "./tools.js",
|
|
137
|
+
});
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
it('should parse: import { safe foo, safe bar, baz } from "./tools.js"', () => {
|
|
141
|
+
const result = importStatmentParser('import { safe foo, safe bar, baz } from "./tools.js"');
|
|
142
|
+
expect(result.success).toBe(true);
|
|
143
|
+
if (result.success) {
|
|
144
|
+
expect(result.result).toEqual({
|
|
145
|
+
type: "importStatement",
|
|
146
|
+
importedNames: [
|
|
147
|
+
{
|
|
148
|
+
type: "namedImport",
|
|
149
|
+
importedNames: ["foo", "bar", "baz"],
|
|
150
|
+
safeNames: ["foo", "bar"],
|
|
151
|
+
},
|
|
152
|
+
],
|
|
153
|
+
modulePath: "./tools.js",
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
it('should parse: import { safe foo } from "./tools.js"', () => {
|
|
158
|
+
const result = importStatmentParser('import { safe foo } from "./tools.js"');
|
|
159
|
+
expect(result.success).toBe(true);
|
|
160
|
+
if (result.success) {
|
|
161
|
+
expect(result.result).toEqual({
|
|
162
|
+
type: "importStatement",
|
|
163
|
+
importedNames: [
|
|
164
|
+
{
|
|
165
|
+
type: "namedImport",
|
|
166
|
+
importedNames: ["foo"],
|
|
167
|
+
safeNames: ["foo"],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
modulePath: "./tools.js",
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
});
|
|
114
174
|
// With semicolons
|
|
115
175
|
it('should parse imports with semicolons', () => {
|
|
116
176
|
const result = importStatmentParser('import foo from "./foo.ts";');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export class ToolCallError extends Error {
|
|
2
|
+
retryable;
|
|
3
|
+
originalError;
|
|
4
|
+
constructor(error, opts) {
|
|
5
|
+
super(error instanceof Error ? error.message : String(error));
|
|
6
|
+
this.originalError = error;
|
|
7
|
+
this.retryable = opts.retryable;
|
|
8
|
+
if (error instanceof Error && error.stack) {
|
|
9
|
+
this.stack = error.stack;
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
@@ -13,4 +13,5 @@ export { interrupt, isInterrupt, respondToInterrupt, approveInterrupt, rejectInt
|
|
|
13
13
|
export { isGenerator, handleStreamingResponse } from "./streaming.js";
|
|
14
14
|
export { runPrompt } from "./prompt.js";
|
|
15
15
|
export type { ToolHandler } from "./prompt.js";
|
|
16
|
+
export { ToolCallError } from "./errors.js";
|
|
16
17
|
export { setupNode, setupFunction, runNode } from "./node.js";
|
|
@@ -9,4 +9,5 @@ export { readSkillTool, readSkillToolParams, printTool, printToolParams, printJS
|
|
|
9
9
|
export { interrupt, isInterrupt, respondToInterrupt, approveInterrupt, rejectInterrupt, modifyInterrupt, resolveInterrupt, resumeFromState, } from "./interrupts.js";
|
|
10
10
|
export { isGenerator, handleStreamingResponse } from "./streaming.js";
|
|
11
11
|
export { runPrompt } from "./prompt.js";
|
|
12
|
+
export { ToolCallError } from "./errors.js";
|
|
12
13
|
export { setupNode, setupFunction, runNode } from "./node.js";
|
|
@@ -5,6 +5,7 @@ import { updateTokenStats, extractResponse } from "./utils.js";
|
|
|
5
5
|
import { callHook } from "./hooks.js";
|
|
6
6
|
import { handleStreamingResponse } from "./streaming.js";
|
|
7
7
|
import { ThreadStore } from "./state/threadStore.js";
|
|
8
|
+
import { ToolCallError } from "./errors.js";
|
|
8
9
|
async function _runPrompt({ ctx, messages, tools, prompt, responseFormat, stream, clientConfig, }) {
|
|
9
10
|
const startTime = performance.now();
|
|
10
11
|
const startHookResult = await callHook({
|
|
@@ -92,7 +93,7 @@ async function _runPrompt({ ctx, messages, tools, prompt, responseFormat, stream
|
|
|
92
93
|
}
|
|
93
94
|
return { messages, toolCalls };
|
|
94
95
|
}
|
|
95
|
-
async function executeToolCalls({ toolCalls, toolHandlers, messages, ctx, clientConfig, interruptData, }) {
|
|
96
|
+
async function executeToolCalls({ toolCalls, toolHandlers, messages, ctx, clientConfig, interruptData, removedTools, toolErrorCounts, }) {
|
|
96
97
|
for (const toolCall of toolCalls) {
|
|
97
98
|
const handler = toolHandlers.find((h) => h.name === toolCall.name);
|
|
98
99
|
if (!handler) {
|
|
@@ -141,7 +142,35 @@ async function executeToolCalls({ toolCalls, toolHandlers, messages, ctx, client
|
|
|
141
142
|
isToolCall: true,
|
|
142
143
|
});
|
|
143
144
|
const toolCallStartTime = performance.now();
|
|
144
|
-
|
|
145
|
+
try {
|
|
146
|
+
result = await handler.execute(...params);
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
const retryable = error instanceof ToolCallError ? error.retryable : false;
|
|
150
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
151
|
+
toolErrorCounts[handler.name] = (toolErrorCounts[handler.name] || 0) + 1;
|
|
152
|
+
if (retryable && toolErrorCounts[handler.name] < 5) {
|
|
153
|
+
messages.push(smoltalk.toolMessage(`Error: ${errorMessage}. You may retry this tool call with corrected arguments.`, {
|
|
154
|
+
tool_call_id: toolCall.id,
|
|
155
|
+
name: toolCall.name,
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
else if (retryable) {
|
|
159
|
+
messages.push(smoltalk.toolMessage(`Error: ${errorMessage}. This tool has failed too many times and can no longer be called.`, {
|
|
160
|
+
tool_call_id: toolCall.id,
|
|
161
|
+
name: toolCall.name,
|
|
162
|
+
}));
|
|
163
|
+
removedTools.push(handler.name);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
messages.push(smoltalk.toolMessage(`Error: ${errorMessage}. This tool failed after performing side effects and cannot be retried.`, {
|
|
167
|
+
tool_call_id: toolCall.id,
|
|
168
|
+
name: toolCall.name,
|
|
169
|
+
}));
|
|
170
|
+
removedTools.push(handler.name);
|
|
171
|
+
}
|
|
172
|
+
continue;
|
|
173
|
+
}
|
|
145
174
|
result =
|
|
146
175
|
result || `${handler.name} ran successfully but did not return a value`;
|
|
147
176
|
const toolCallEndTime = performance.now();
|
|
@@ -183,7 +212,9 @@ async function executeToolCalls({ toolCalls, toolHandlers, messages, ctx, client
|
|
|
183
212
|
return { isInterrupt: false, messages };
|
|
184
213
|
}
|
|
185
214
|
export async function runPrompt(args) {
|
|
186
|
-
const { ctx, prompt, responseFormat,
|
|
215
|
+
const { ctx, prompt, responseFormat, stream = false, maxToolCallRounds = 10, removedTools = [], } = args;
|
|
216
|
+
let tools = (args.tools || []).filter((t) => !removedTools.includes(t.name));
|
|
217
|
+
let toolHandlers = (args.toolHandlers || []).filter((h) => !removedTools.includes(h.name));
|
|
187
218
|
const clientConfig = ctx.getSmoltalkConfig(args.clientConfig || {});
|
|
188
219
|
// console.log(color.magenta(JSON.stringify(clientConfig, null, 2)) + "\n");
|
|
189
220
|
/* in order, either:
|
|
@@ -228,6 +259,7 @@ export async function runPrompt(args) {
|
|
|
228
259
|
toolCalls = [args.interruptData.toolCall];
|
|
229
260
|
}
|
|
230
261
|
// Handle tool calls
|
|
262
|
+
const toolErrorCounts = {};
|
|
231
263
|
let toolCallRound = 0;
|
|
232
264
|
while (toolCalls.length > 0) {
|
|
233
265
|
if (toolCallRound++ >= maxToolCallRounds) {
|
|
@@ -240,8 +272,15 @@ export async function runPrompt(args) {
|
|
|
240
272
|
ctx,
|
|
241
273
|
clientConfig,
|
|
242
274
|
interruptData: args.interruptData,
|
|
275
|
+
removedTools,
|
|
276
|
+
toolErrorCounts,
|
|
243
277
|
});
|
|
244
278
|
messages = executeToolCallsResult.messages;
|
|
279
|
+
// Filter out tools that failed after side effects
|
|
280
|
+
if (removedTools.length > 0) {
|
|
281
|
+
tools = tools.filter((t) => !removedTools.includes(t.name));
|
|
282
|
+
toolHandlers = toolHandlers.filter((h) => !removedTools.includes(h.name));
|
|
283
|
+
}
|
|
245
284
|
if (executeToolCallsResult.isInterrupt) {
|
|
246
285
|
const { interrupt } = executeToolCallsResult;
|
|
247
286
|
ctx.statelogClient.debug(`Tool call interrupted execution.`, {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "\nexport async function {{{functionName:string}}}({{{paramList:string}}}__state: InternalFunctionState | undefined = undefined) {\n const { stack: __stack, step: __step, self: __self, threads: __threads } =\n setupFunction({ state: __state });\n\n // __state will be undefined if this function is\n // being called as a tool by an llm\n const __ctx = __state?.ctx || __globalCtx;\n const statelogClient = __ctx.statelogClient;\n const __graph = __ctx.graph;\n const __funcStartTime = performance.now();\n await callHook({ callbacks: __ctx.callbacks, name: \"onFunctionStart\", data: { functionName: \"{{{functionName}}}\", args: {{{argsObject:string}}}, isBuiltin: false } });\n\n // put all args on the state stack\n {{{paramAssignments:string}}}\n\n {{{functionBody}}}\n\n await callHook({ callbacks: __ctx.callbacks, name: \"onFunctionEnd\", data: { functionName: \"{{{functionName}}}\", timeTaken: performance.now() - __funcStartTime } });\n}\n";
|
|
1
|
+
export declare const template = "\nexport async function {{{functionName:string}}}({{{paramList:string}}}__state: InternalFunctionState | undefined = undefined) {\n const { stack: __stack, step: __step, self: __self, threads: __threads } =\n setupFunction({ state: __state });\n\n // __state will be undefined if this function is\n // being called as a tool by an llm\n const __ctx = __state?.ctx || __globalCtx;\n const statelogClient = __ctx.statelogClient;\n const __graph = __ctx.graph;\n const __funcStartTime = performance.now();\n await callHook({ callbacks: __ctx.callbacks, name: \"onFunctionStart\", data: { functionName: \"{{{functionName}}}\", args: {{{argsObject:string}}}, isBuiltin: false } });\n\n // put all args on the state stack\n {{{paramAssignments:string}}}\n\n __self.__retryable = __self.__retryable ?? true;\n\n try {\n {{{functionBody}}}\n } catch (__error) {\n if (__error instanceof ToolCallError) throw __error;\n throw new ToolCallError(__error, { retryable: __self.__retryable });\n }\n\n await callHook({ callbacks: __ctx.callbacks, name: \"onFunctionEnd\", data: { functionName: \"{{{functionName}}}\", timeTaken: performance.now() - __funcStartTime } });\n}\n";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
functionName: string;
|
|
4
4
|
paramList: string;
|
|
@@ -18,7 +18,14 @@ export async function {{{functionName:string}}}({{{paramList:string}}}__state: I
|
|
|
18
18
|
// put all args on the state stack
|
|
19
19
|
{{{paramAssignments:string}}}
|
|
20
20
|
|
|
21
|
+
__self.__retryable = __self.__retryable ?? true;
|
|
22
|
+
|
|
23
|
+
try {
|
|
21
24
|
{{{functionBody}}}
|
|
25
|
+
} catch (__error) {
|
|
26
|
+
if (__error instanceof ToolCallError) throw __error;
|
|
27
|
+
throw new ToolCallError(__error, { retryable: __self.__retryable });
|
|
28
|
+
}
|
|
22
29
|
|
|
23
30
|
await callHook({ callbacks: __ctx.callbacks, name: "onFunctionEnd", data: { functionName: "{{{functionName}}}", timeTaken: performance.now() - __funcStartTime } });
|
|
24
31
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "import { fileURLToPath } from \"url\";\nimport process from \"process\";\nimport { readFileSync, writeFileSync } from \"fs\";\nimport { z } from \"zod\";\nimport { goToNode, color, nanoid, registerProvider, registerTextModel } from \"agency-lang\";\nimport * as smoltalk from \"agency-lang\";\nimport path from \"path\";\nimport type { GraphState, InternalFunctionState, Interrupt } from \"agency-lang/runtime\";\nimport {\n RuntimeContext, MessageThread, ThreadStore,\n setupNode, setupFunction, runNode, runPrompt, callHook,\n interrupt, isInterrupt,\n respondToInterrupt as _respondToInterrupt,\n approveInterrupt as _approveInterrupt,\n rejectInterrupt as _rejectInterrupt,\n resolveInterrupt as _resolveInterrupt,\n modifyInterrupt as _modifyInterrupt,\n resumeFromState as _resumeFromState,\n deepClone as __deepClone,\n not, eq, neq, lt, lte, gt, gte, and, or,\n head, tail, empty,\n builtinFetch as _builtinFetch,\n builtinFetchJSON as _builtinFetchJSON,\n builtinInput as _builtinInput,\n builtinRead as _builtinReadRaw,\n builtinWrite as _builtinWriteRaw,\n builtinReadImage as _builtinReadImageRaw,\n builtinSleep as _builtinSleep,\n builtinRound as _builtinRound,\n printJSON as _printJSON,\n print as _print,\n readSkill as _readSkillRaw,\n readSkillTool as __readSkillTool,\n readSkillToolParams as __readSkillToolParams,\n printTool as __printTool,\n printToolParams as __printToolParams,\n printJSONTool as __printJSONTool,\n printJSONToolParams as __printJSONToolParams,\n inputTool as __inputTool,\n inputToolParams as __inputToolParams,\n readTool as __readTool,\n readToolParams as __readToolParams,\n readImageTool as __readImageTool,\n readImageToolParams as __readImageToolParams,\n writeTool as __writeTool,\n writeToolParams as __writeToolParams,\n fetchTool as __fetchTool,\n fetchToolParams as __fetchToolParams,\n fetchJSONTool as __fetchJSONTool,\n fetchJSONToolParams as __fetchJSONToolParams,\n fetchJsonTool as __fetchJsonTool,\n fetchJsonToolParams as __fetchJsonToolParams,\n sleepTool as __sleepTool,\n sleepToolParams as __sleepToolParams,\n roundTool as __roundTool,\n roundToolParams as __roundToolParams,\n} from \"agency-lang/runtime\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst __cwd = process.cwd();\n\nconst __globalCtx = new RuntimeContext({\n statelogConfig: {\n host: \"{{{logHost:string}}}\",\n {{#hasApiKey}}\n apiKey: \"{{{logApiKey?:string}}}\",\n {{/hasApiKey}}\n {{^hasApiKey}}\n apiKey: process.env.STATELOG_API_KEY || \"\",\n {{/hasApiKey}}\n projectId: \"{{{logProjectId:string}}}\",\n debugMode: {{{logDebugMode:boolean}}},\n },\n smoltalkDefaults: {\n {{#hasOpenAiApiKey}}\n openAiApiKey: \"{{{clientOpenAiApiKey?:string}}}\",\n {{/hasOpenAiApiKey}}\n {{^hasOpenAiApiKey}}\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n {{/hasOpenAiApiKey}}\n {{#hasGoogleApiKey}}\n googleApiKey: \"{{{clientGoogleApiKey?:string}}}\",\n {{/hasGoogleApiKey}}\n {{^hasGoogleApiKey}}\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n {{/hasGoogleApiKey}}\n model: \"{{{clientDefaultModel:string}}}\",\n logLevel: \"{{{clientLogLevel:string}}}\",\n statelog: { \n host: \"{{{clientStatelogHost:string}}}\",\n projectId: \"{{{clientStatelogProjectId:string}}}\",\n apiKey: process.env.STATELOG_SMOLTALK_API_KEY || \"\",\n traceId: nanoid()\n }\n },\n dirname: __dirname,\n});\nconst graph = __globalCtx.graph;\n\n// Path-dependent builtin wrappers\nfunction _builtinRead(filename: string): string {\n return _builtinReadRaw({ filename, dirname: __dirname });\n}\nfunction _builtinWrite(filename: string, content: string): void {\n _builtinWriteRaw({ filename, content, dirname: __dirname });\n}\nfunction _builtinReadImage(filename: string): string {\n return _builtinReadImageRaw({ filename, dirname: __dirname });\n}\nexport function readSkill({filepath}: {filepath: string}): string {\n return _readSkillRaw({ filepath, dirname: __dirname });\n}\n\n// Interrupt re-exports bound to this module's context\nexport { interrupt, isInterrupt };\nexport const respondToInterrupt = (i: Interrupt, r: any, m?: any) => _respondToInterrupt({ ctx: __globalCtx, interrupt: i, interruptResponse: r, metadata: m });\nexport const approveInterrupt = (i: Interrupt, m?: any) => _approveInterrupt({ ctx: __globalCtx, interrupt: i, metadata: m });\nexport const rejectInterrupt = (i: Interrupt, m?: any) => _rejectInterrupt({ ctx: __globalCtx, interrupt: i, metadata: m });\nexport const modifyInterrupt = (i: Interrupt, a: any, m?: any) => _modifyInterrupt({ ctx: __globalCtx, interrupt: i, newArguments: a, metadata: m });\nexport const resolveInterrupt = (i: Interrupt, v: any, m?: any) => _resolveInterrupt({ ctx: __globalCtx, interrupt: i, value: v, metadata: m });";
|
|
1
|
+
export declare const template = "import { fileURLToPath } from \"url\";\nimport process from \"process\";\nimport { readFileSync, writeFileSync } from \"fs\";\nimport { z } from \"zod\";\nimport { goToNode, color, nanoid, registerProvider, registerTextModel } from \"agency-lang\";\nimport * as smoltalk from \"agency-lang\";\nimport path from \"path\";\nimport type { GraphState, InternalFunctionState, Interrupt } from \"agency-lang/runtime\";\nimport {\n RuntimeContext, MessageThread, ThreadStore,\n setupNode, setupFunction, runNode, runPrompt, callHook,\n interrupt, isInterrupt,\n respondToInterrupt as _respondToInterrupt,\n approveInterrupt as _approveInterrupt,\n rejectInterrupt as _rejectInterrupt,\n resolveInterrupt as _resolveInterrupt,\n modifyInterrupt as _modifyInterrupt,\n resumeFromState as _resumeFromState,\n ToolCallError,\n deepClone as __deepClone,\n not, eq, neq, lt, lte, gt, gte, and, or,\n head, tail, empty,\n builtinFetch as _builtinFetch,\n builtinFetchJSON as _builtinFetchJSON,\n builtinInput as _builtinInput,\n builtinRead as _builtinReadRaw,\n builtinWrite as _builtinWriteRaw,\n builtinReadImage as _builtinReadImageRaw,\n builtinSleep as _builtinSleep,\n builtinRound as _builtinRound,\n printJSON as _printJSON,\n print as _print,\n readSkill as _readSkillRaw,\n readSkillTool as __readSkillTool,\n readSkillToolParams as __readSkillToolParams,\n printTool as __printTool,\n printToolParams as __printToolParams,\n printJSONTool as __printJSONTool,\n printJSONToolParams as __printJSONToolParams,\n inputTool as __inputTool,\n inputToolParams as __inputToolParams,\n readTool as __readTool,\n readToolParams as __readToolParams,\n readImageTool as __readImageTool,\n readImageToolParams as __readImageToolParams,\n writeTool as __writeTool,\n writeToolParams as __writeToolParams,\n fetchTool as __fetchTool,\n fetchToolParams as __fetchToolParams,\n fetchJSONTool as __fetchJSONTool,\n fetchJSONToolParams as __fetchJSONToolParams,\n fetchJsonTool as __fetchJsonTool,\n fetchJsonToolParams as __fetchJsonToolParams,\n sleepTool as __sleepTool,\n sleepToolParams as __sleepToolParams,\n roundTool as __roundTool,\n roundToolParams as __roundToolParams,\n} from \"agency-lang/runtime\";\n\nconst __filename = fileURLToPath(import.meta.url);\nconst __dirname = path.dirname(__filename);\nconst __cwd = process.cwd();\n\nconst __globalCtx = new RuntimeContext({\n statelogConfig: {\n host: \"{{{logHost:string}}}\",\n {{#hasApiKey}}\n apiKey: \"{{{logApiKey?:string}}}\",\n {{/hasApiKey}}\n {{^hasApiKey}}\n apiKey: process.env.STATELOG_API_KEY || \"\",\n {{/hasApiKey}}\n projectId: \"{{{logProjectId:string}}}\",\n debugMode: {{{logDebugMode:boolean}}},\n },\n smoltalkDefaults: {\n {{#hasOpenAiApiKey}}\n openAiApiKey: \"{{{clientOpenAiApiKey?:string}}}\",\n {{/hasOpenAiApiKey}}\n {{^hasOpenAiApiKey}}\n openAiApiKey: process.env.OPENAI_API_KEY || \"\",\n {{/hasOpenAiApiKey}}\n {{#hasGoogleApiKey}}\n googleApiKey: \"{{{clientGoogleApiKey?:string}}}\",\n {{/hasGoogleApiKey}}\n {{^hasGoogleApiKey}}\n googleApiKey: process.env.GEMINI_API_KEY || \"\",\n {{/hasGoogleApiKey}}\n model: \"{{{clientDefaultModel:string}}}\",\n logLevel: \"{{{clientLogLevel:string}}}\",\n statelog: { \n host: \"{{{clientStatelogHost:string}}}\",\n projectId: \"{{{clientStatelogProjectId:string}}}\",\n apiKey: process.env.STATELOG_SMOLTALK_API_KEY || \"\",\n traceId: nanoid()\n }\n },\n dirname: __dirname,\n});\nconst graph = __globalCtx.graph;\n\n// Path-dependent builtin wrappers\nfunction _builtinRead(filename: string): string {\n return _builtinReadRaw({ filename, dirname: __dirname });\n}\nfunction _builtinWrite(filename: string, content: string): void {\n _builtinWriteRaw({ filename, content, dirname: __dirname });\n}\nfunction _builtinReadImage(filename: string): string {\n return _builtinReadImageRaw({ filename, dirname: __dirname });\n}\nexport function readSkill({filepath}: {filepath: string}): string {\n return _readSkillRaw({ filepath, dirname: __dirname });\n}\n\n// Interrupt re-exports bound to this module's context\nexport { interrupt, isInterrupt };\nexport const respondToInterrupt = (i: Interrupt, r: any, m?: any) => _respondToInterrupt({ ctx: __globalCtx, interrupt: i, interruptResponse: r, metadata: m });\nexport const approveInterrupt = (i: Interrupt, m?: any) => _approveInterrupt({ ctx: __globalCtx, interrupt: i, metadata: m });\nexport const rejectInterrupt = (i: Interrupt, m?: any) => _rejectInterrupt({ ctx: __globalCtx, interrupt: i, metadata: m });\nexport const modifyInterrupt = (i: Interrupt, a: any, m?: any) => _modifyInterrupt({ ctx: __globalCtx, interrupt: i, newArguments: a, metadata: m });\nexport const resolveInterrupt = (i: Interrupt, v: any, m?: any) => _resolveInterrupt({ ctx: __globalCtx, interrupt: i, value: v, metadata: m });";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
logHost: string;
|
|
4
4
|
hasApiKey: boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export declare const template = "\nasync function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<any> {\n return runPrompt({\n ctx: __ctx,\n prompt: {{{promptCode:string}}},\n messages: __metadata?.messages || new MessageThread(),\n {{#hasResponseFormat}}\n responseFormat: z.object({\n response: {{{zodSchema:string}}}\n }),\n {{/hasResponseFormat}}\n tools: {{{tools}}},\n toolHandlers: [{{{toolHandlers:string}}}],\n clientConfig: {{{clientConfig:string}}},\n stream: {{{isStreaming:boolean}}},\n maxToolCallRounds: {{{maxToolCallRounds:number}}},\n interruptData: __state?.interruptData
|
|
1
|
+
export declare const template = "\nasync function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<any> {\n __self.__removedTools = __self.__removedTools || [];\n return runPrompt({\n ctx: __ctx,\n prompt: {{{promptCode:string}}},\n messages: __metadata?.messages || new MessageThread(),\n {{#hasResponseFormat}}\n responseFormat: z.object({\n response: {{{zodSchema:string}}}\n }),\n {{/hasResponseFormat}}\n tools: {{{tools}}},\n toolHandlers: [{{{toolHandlers:string}}}],\n clientConfig: {{{clientConfig:string}}},\n stream: {{{isStreaming:boolean}}},\n maxToolCallRounds: {{{maxToolCallRounds:number}}},\n interruptData: __state?.interruptData,\n removedTools: __self.__removedTools,\n });\n}\n\n{{#isAsync}}\n__self.{{{variableName:string}}} = _{{{variableName:string}}}({{{funcCallParams:string}}});\n{{/isAsync}}\n\n{{^isAsync}}\n__self.{{{variableName:string}}} = await _{{{variableName:string}}}({{{funcCallParams:string}}});\n\n// return early from node if this is an interrupt\nif (isInterrupt(__self.{{{variableName:string}}})) {\n {{#nodeContext}}\n return { messages: __threads, data: __self.{{{variableName:string}}} };\n {{/nodeContext}}\n {{^nodeContext}}\n return __self.{{{variableName:string}}};\n {{/nodeContext}}\n}\n{{/isAsync}}";
|
|
2
2
|
export type TemplateType = {
|
|
3
3
|
variableName: string;
|
|
4
4
|
argsStr: string;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { apply } from "typestache";
|
|
5
5
|
export const template = `
|
|
6
6
|
async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<any> {
|
|
7
|
+
__self.__removedTools = __self.__removedTools || [];
|
|
7
8
|
return runPrompt({
|
|
8
9
|
ctx: __ctx,
|
|
9
10
|
prompt: {{{promptCode:string}}},
|
|
@@ -18,7 +19,8 @@ async function _{{{variableName:string}}}({{{argsStr:string}}}): Promise<any> {
|
|
|
18
19
|
clientConfig: {{{clientConfig:string}}},
|
|
19
20
|
stream: {{{isStreaming:boolean}}},
|
|
20
21
|
maxToolCallRounds: {{{maxToolCallRounds:number}}},
|
|
21
|
-
interruptData: __state?.interruptData
|
|
22
|
+
interruptData: __state?.interruptData,
|
|
23
|
+
removedTools: __self.__removedTools,
|
|
22
24
|
});
|
|
23
25
|
}
|
|
24
26
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agency-lang",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.82",
|
|
4
4
|
"description": "The Agency language",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"nanoid": "^5.1.6",
|
|
68
68
|
"ora": "^9.3.0",
|
|
69
69
|
"prompts": "^2.4.2",
|
|
70
|
-
"smoltalk": "^0.0.
|
|
70
|
+
"smoltalk": "^0.0.64",
|
|
71
71
|
"tarsec": "^0.1.8",
|
|
72
72
|
"termcolors": "github:egonSchiele/termcolors",
|
|
73
73
|
"typestache": "^0.4.4",
|