@neutrome/lilsdk-ts 0.2.1 → 0.2.3

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@neutrome/lilsdk-ts",
3
- "version": "0.2.1",
3
+ "version": "0.2.3",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./src/index.ts",
@@ -13,7 +13,7 @@
13
13
  "./managed": "./src/managed/index.ts"
14
14
  },
15
15
  "dependencies": {
16
- "@neutrome/lil-engine": "0.2.0"
16
+ "@neutrome/lil-engine": "0.2.1"
17
17
  },
18
18
  "devDependencies": {
19
19
  "@types/node": "^25.9.3",
@@ -37,14 +37,24 @@ export function retry(executor: Executor, options: RetryOptions = {}): Executor
37
37
  );
38
38
  },
39
39
 
40
- stream(request, ctx) {
41
- return streamBuffered(() =>
42
- runRetry(
43
- (attempt) => collect(executor.stream(request, childContext(ctx, attempt))),
44
- attempts,
45
- options,
46
- ),
47
- );
40
+ async *stream(request, ctx) {
41
+ let lastError: unknown;
42
+
43
+ for (let attempt = 1; attempt <= attempts; attempt += 1) {
44
+ try {
45
+ yield* executor.stream(request, childContext(ctx, attempt));
46
+ return;
47
+ } catch (error) {
48
+ lastError = error;
49
+ const canRetry = attempt < attempts && (await shouldContinue(error, attempt, options.shouldRetry));
50
+ if (!canRetry) {
51
+ throw error;
52
+ }
53
+ await options.onRetry?.(error, attempt);
54
+ }
55
+ }
56
+
57
+ throw lastError;
48
58
  },
49
59
  };
50
60
  }
@@ -63,14 +73,26 @@ export function fallback(executors: readonly Executor[], options: FallbackOption
63
73
  );
64
74
  },
65
75
 
66
- stream(request, ctx) {
67
- return streamBuffered(() =>
68
- runFallback(
69
- (executor, index) => collect(executor.stream(request, childContext(ctx, index + 1))),
70
- executors,
71
- options,
72
- ),
73
- );
76
+ async *stream(request, ctx) {
77
+ let lastError: unknown;
78
+
79
+ for (const [index, executor] of executors.entries()) {
80
+ try {
81
+ yield* executor.stream(request, childContext(ctx, index + 1));
82
+ return;
83
+ } catch (error) {
84
+ lastError = error;
85
+ const canFallback =
86
+ index < executors.length - 1 &&
87
+ (await shouldContinue(error, index, options.shouldFallback));
88
+ if (!canFallback) {
89
+ throw error;
90
+ }
91
+ await options.onFallback?.(error, index);
92
+ }
93
+ }
94
+
95
+ throw lastError;
74
96
  },
75
97
  };
76
98
  }
@@ -98,8 +120,9 @@ export function goal(options: GoalOptions): Executor {
98
120
  return {
99
121
  execute: executeGoal,
100
122
 
101
- stream(request, ctx) {
102
- return streamBuffered(async () => [await executeGoal(request, ctx)]);
123
+ async *stream(request, ctx) {
124
+ const result = await executeGoal(request, ctx);
125
+ yield result;
103
126
  },
104
127
  };
105
128
  }
@@ -160,20 +183,6 @@ async function shouldContinue(
160
183
  return predicate ? predicate(error, attempt) : true;
161
184
  }
162
185
 
163
- async function collect(stream: AsyncIterable<Program>): Promise<Program[]> {
164
- const chunks: Program[] = [];
165
- for await (const chunk of stream) {
166
- chunks.push(chunk);
167
- }
168
- return chunks;
169
- }
170
-
171
- async function* streamBuffered(load: () => Promise<Program[]>): AsyncIterable<Program> {
172
- for (const chunk of await load()) {
173
- yield chunk;
174
- }
175
- }
176
-
177
186
  function childContext(ctx: ExecutorContext, attempt: number): ExecutorContext {
178
187
  return {
179
188
  ...ctx,
package/src/tools.ts CHANGED
@@ -75,6 +75,7 @@ function buildCallExecutor(toolMap: Map<string, Tool>) {
75
75
  } catch {
76
76
  parsed = {};
77
77
  }
78
+ const startedMs = Date.now();
78
79
  const result = await tool.execute(parsed, ctx);
79
80
  ctx.observe(createSdkEvent({
80
81
  kind: "tool.executed",
@@ -84,6 +85,7 @@ function buildCallExecutor(toolMap: Map<string, Tool>) {
84
85
  data: {
85
86
  toolName: call.name,
86
87
  toolCallId: call.id,
88
+ durationMs: Date.now() - startedMs,
87
89
  lilText: buildToolTrace(call, result),
88
90
  },
89
91
  }));