@agent-builder-lab/eve-kit 0.3.0 → 0.4.0-rc.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/channel.d.ts +2 -2
- package/dist/channel.js +1 -1
- package/dist/{chunk-3IQOFBSQ.js → chunk-I5XIFBNJ.js} +1 -1
- package/dist/index.js +56 -29
- package/dist/replay.d.ts +6 -5
- package/dist/replay.js +20 -21
- package/package.json +8 -3
package/dist/channel.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AuthFn } from 'eve/channels/auth';
|
|
2
|
-
import {
|
|
2
|
+
import { EveChannelConfig, EveChannel, EveMessageContext, EveMessageResult } from 'eve/channels/eve';
|
|
3
3
|
|
|
4
|
-
interface LabChannelOptions extends Omit<
|
|
4
|
+
interface LabChannelOptions extends Omit<EveChannelConfig, "auth"> {
|
|
5
5
|
/**
|
|
6
6
|
* Autenticadores do próprio agente, verificados antes do acesso local do lab. O acesso local
|
|
7
7
|
* (`localDev()` do eve) entra sempre por último.
|
package/dist/channel.js
CHANGED
|
@@ -37,7 +37,7 @@ async function load(forkId, base) {
|
|
|
37
37
|
});
|
|
38
38
|
} catch {
|
|
39
39
|
throw new Error(
|
|
40
|
-
`Agent Builder Lab: o conector n\xE3o respondeu em ${base}. Ele est\xE1 rodando (agent-builder-lab connect)?`
|
|
40
|
+
`Agent Builder Lab: o conector n\xE3o respondeu em ${base}. Ele est\xE1 rodando (agent-builder-lab dev ou connect)?`
|
|
41
41
|
);
|
|
42
42
|
}
|
|
43
43
|
const body = await response.json().catch(() => null);
|
package/dist/index.js
CHANGED
|
@@ -95,6 +95,26 @@ function labInstrumentation(options = {}) {
|
|
|
95
95
|
if (oldest !== void 0) sessions.delete(oldest);
|
|
96
96
|
}
|
|
97
97
|
}
|
|
98
|
+
const stepIndexes = /* @__PURE__ */ new Map();
|
|
99
|
+
function stepIndexOf(scope) {
|
|
100
|
+
const key = `${scope.sessionId}:${scope.turnId ?? ""}`;
|
|
101
|
+
let runs = stepIndexes.get(key);
|
|
102
|
+
if (!runs) {
|
|
103
|
+
runs = /* @__PURE__ */ new Map();
|
|
104
|
+
stepIndexes.delete(key);
|
|
105
|
+
stepIndexes.set(key, runs);
|
|
106
|
+
if (stepIndexes.size > MAX_SESSIONS) {
|
|
107
|
+
const oldest = stepIndexes.keys().next().value;
|
|
108
|
+
if (oldest !== void 0) stepIndexes.delete(oldest);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
let index = runs.get(scope.runId);
|
|
112
|
+
if (index === void 0) {
|
|
113
|
+
index = runs.size;
|
|
114
|
+
runs.set(scope.runId, index);
|
|
115
|
+
}
|
|
116
|
+
return index;
|
|
117
|
+
}
|
|
98
118
|
function base(idempotencyKey, scope) {
|
|
99
119
|
const info = sessions.get(scope.sessionId);
|
|
100
120
|
seq += 1;
|
|
@@ -105,9 +125,9 @@ function labInstrumentation(options = {}) {
|
|
|
105
125
|
at: (/* @__PURE__ */ new Date()).toISOString(),
|
|
106
126
|
sessionId: scope.sessionId,
|
|
107
127
|
rootSessionId: scope.rootSessionId,
|
|
108
|
-
turnId: scope.turnId,
|
|
109
|
-
stepIndex: scope
|
|
110
|
-
attemptIndex: scope.
|
|
128
|
+
turnId: scope.turnId ?? "",
|
|
129
|
+
stepIndex: stepIndexOf(scope),
|
|
130
|
+
attemptIndex: scope.attempt,
|
|
111
131
|
agentName: info?.agentName,
|
|
112
132
|
parentLineage: info?.parentLineage
|
|
113
133
|
};
|
|
@@ -142,7 +162,15 @@ function labInstrumentation(options = {}) {
|
|
|
142
162
|
}
|
|
143
163
|
});
|
|
144
164
|
},
|
|
145
|
-
"model.call.
|
|
165
|
+
"model.call.settled": (event) => {
|
|
166
|
+
if (event.outcome !== "completed") {
|
|
167
|
+
send({
|
|
168
|
+
...base(event.idempotencyKey, event.scope),
|
|
169
|
+
type: "model.call.failed",
|
|
170
|
+
error: error(event.error)
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
146
174
|
send({
|
|
147
175
|
...base(event.idempotencyKey, event.scope),
|
|
148
176
|
type: "model.call.completed",
|
|
@@ -152,42 +180,35 @@ function labInstrumentation(options = {}) {
|
|
|
152
180
|
content: event.content && [...event.content]
|
|
153
181
|
});
|
|
154
182
|
},
|
|
155
|
-
"
|
|
156
|
-
send({
|
|
157
|
-
...base(event.idempotencyKey, event.scope),
|
|
158
|
-
type: "model.call.failed",
|
|
159
|
-
error: error(event.error)
|
|
160
|
-
});
|
|
161
|
-
},
|
|
162
|
-
"tool.call.started": (event, ctx) => {
|
|
183
|
+
"call.requested": (event, ctx) => {
|
|
163
184
|
ctx.state.set({ callId: event.callId, toolName: event.toolName });
|
|
164
185
|
send({
|
|
165
186
|
...base(event.idempotencyKey, event.scope),
|
|
166
187
|
type: "tool.call.started",
|
|
167
188
|
callId: event.callId,
|
|
168
189
|
toolName: event.toolName,
|
|
169
|
-
kind: event.kind,
|
|
190
|
+
kind: toolKind(event.capability.kind),
|
|
170
191
|
input: event.input,
|
|
171
192
|
startedAtMs: event.startedAtMs
|
|
172
193
|
});
|
|
173
194
|
},
|
|
174
|
-
"
|
|
175
|
-
const started = ctx.state.get();
|
|
176
|
-
send({
|
|
177
|
-
...base(event.idempotencyKey, event.scope),
|
|
178
|
-
type: "tool.call.completed",
|
|
179
|
-
callId: started?.callId,
|
|
180
|
-
toolName: started?.toolName,
|
|
181
|
-
outcome: event.outcome,
|
|
182
|
-
// Prévias de imagem (data URLs) já chegam ao lab pelo stream do eve: aqui, só o tamanho.
|
|
183
|
-
output: withoutInlineMedia(event.output),
|
|
184
|
-
durationMs: event.durationMs,
|
|
185
|
-
completedAtMs: event.completedAtMs,
|
|
186
|
-
usage: event.usage && usage(event.usage)
|
|
187
|
-
});
|
|
188
|
-
},
|
|
189
|
-
"tool.call.failed": (event, ctx) => {
|
|
195
|
+
"call.settled": (event, ctx) => {
|
|
190
196
|
const started = ctx.state.get();
|
|
197
|
+
if (event.outcome === "completed") {
|
|
198
|
+
send({
|
|
199
|
+
...base(event.idempotencyKey, event.scope),
|
|
200
|
+
type: "tool.call.completed",
|
|
201
|
+
callId: started?.callId,
|
|
202
|
+
toolName: started?.toolName,
|
|
203
|
+
outcome: event.outcome,
|
|
204
|
+
// Prévias de imagem (data URLs) já chegam ao lab pelo stream do eve: aqui, só o tamanho.
|
|
205
|
+
output: { type: "result", output: withoutInlineMedia(event.output) },
|
|
206
|
+
durationMs: event.durationMs,
|
|
207
|
+
completedAtMs: event.completedAtMs,
|
|
208
|
+
usage: event.usage && usage(event.usage)
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
191
212
|
send({
|
|
192
213
|
...base(event.idempotencyKey, event.scope),
|
|
193
214
|
type: "tool.call.failed",
|
|
@@ -204,6 +225,12 @@ function labInstrumentation(options = {}) {
|
|
|
204
225
|
flush: () => sender.flush(2e3)
|
|
205
226
|
});
|
|
206
227
|
}
|
|
228
|
+
function toolKind(kind) {
|
|
229
|
+
if (kind === "agent") return "subagent-call";
|
|
230
|
+
if (kind === "remote-agent") return "remote-agent-call";
|
|
231
|
+
if (kind === "skill") return "load-skill";
|
|
232
|
+
return "tool-call";
|
|
233
|
+
}
|
|
207
234
|
function lineage(value) {
|
|
208
235
|
return {
|
|
209
236
|
sessionId: value.sessionId,
|
package/dist/replay.d.ts
CHANGED
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import * as eve from 'eve';
|
|
2
|
-
import { AgentStaticModelDefinition,
|
|
2
|
+
import { AgentStaticModelDefinition, AgentReasoningDefinition, AgentModelOptionsDefinition, DynamicModelContext } from 'eve';
|
|
3
3
|
|
|
4
4
|
/** O modelo de verdade: fixo ou escolhido a cada step, como num `defineDynamic`. */
|
|
5
5
|
type LabModelChoice = AgentStaticModelDefinition | {
|
|
6
6
|
model: AgentStaticModelDefinition;
|
|
7
7
|
modelContextWindowTokens?: number;
|
|
8
|
-
reasoning?:
|
|
8
|
+
reasoning?: AgentReasoningDefinition;
|
|
9
|
+
modelOptions?: AgentModelOptionsDefinition;
|
|
9
10
|
};
|
|
10
|
-
type LabModelResolver = (
|
|
11
|
+
type LabModelResolver = (ctx: DynamicModelContext) => LabModelChoice | Promise<LabModelChoice>;
|
|
11
12
|
interface LabReplayOptions {
|
|
12
13
|
/** Porta local do conector. Padrão: `LAB_CONNECTOR_URL` ou http://127.0.0.1:2100. */
|
|
13
14
|
connectorUrl?: string;
|
|
@@ -25,12 +26,12 @@ interface LabReplayOptions {
|
|
|
25
26
|
* export default defineAgent({ model: labReplayModel("anthropic/claude-sonnet-5.5") });
|
|
26
27
|
* ```
|
|
27
28
|
*
|
|
28
|
-
* Fora de um fork do lab, devolve o seu modelo em todo step. Num fork (o canal do lab marca o
|
|
29
|
+
* Fora de um fork do lab, devolve o seu modelo em todo step (ou o que a função `model(ctx)` escolher). Num fork (o canal do lab marca o
|
|
29
30
|
* turno com o id), repete os steps gravados antes da volta editada, inclusive ela, com um
|
|
30
31
|
* `mockModel`: mesmo texto, mesmas tool calls e mesmos ids. Assim as voltas anteriores saem
|
|
31
32
|
* iguais às originais e o modelo de verdade só entra depois do ponto editado. O `modelId` desses
|
|
32
33
|
* steps é `lab-replay/<modelo original>`.
|
|
33
34
|
*/
|
|
34
|
-
declare function labReplayModel(model: LabModelChoice | LabModelResolver, options?: LabReplayOptions): eve.DynamicSentinel<LabModelChoice>;
|
|
35
|
+
declare function labReplayModel(model: LabModelChoice | LabModelResolver, options?: LabReplayOptions): eve.DynamicSentinel<LabModelChoice, DynamicModelContext>;
|
|
35
36
|
|
|
36
37
|
export { type LabModelChoice, type LabModelResolver, type LabReplayOptions, labReplayModel };
|
package/dist/replay.js
CHANGED
|
@@ -2,33 +2,32 @@ import {
|
|
|
2
2
|
LAB_FORK_ATTRIBUTE,
|
|
3
3
|
REPLAY_PROVIDER,
|
|
4
4
|
fetchForkPlan
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-I5XIFBNJ.js";
|
|
6
6
|
|
|
7
7
|
// src/replay.ts
|
|
8
|
-
import {
|
|
8
|
+
import {
|
|
9
|
+
defineDynamic
|
|
10
|
+
} from "eve";
|
|
9
11
|
import { mockModel } from "eve/evals";
|
|
12
|
+
import { runs } from "eve/events";
|
|
10
13
|
function labReplayModel(model, options = {}) {
|
|
11
|
-
const real = (
|
|
12
|
-
return defineDynamic({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
modelContextWindowTokens: options.replayContextWindowTokens ?? 1e6
|
|
23
|
-
};
|
|
24
|
-
}
|
|
25
|
-
}
|
|
14
|
+
const real = (ctx) => typeof model === "function" ? model(ctx) : model;
|
|
15
|
+
return defineDynamic(async (ctx) => {
|
|
16
|
+
const forkId = ctx.session.auth.current?.attributes[LAB_FORK_ATTRIBUTE];
|
|
17
|
+
if (typeof forkId !== "string") return real(ctx);
|
|
18
|
+
const plan = await fetchForkPlan(forkId, options.connectorUrl).catch(() => void 0);
|
|
19
|
+
const step = plan?.replay?.steps[stepIndexOf(ctx)];
|
|
20
|
+
if (!step) return real(ctx);
|
|
21
|
+
return {
|
|
22
|
+
model: replayStep(step, plan?.replay?.modelId),
|
|
23
|
+
modelContextWindowTokens: options.replayContextWindowTokens ?? 1e6
|
|
24
|
+
};
|
|
26
25
|
});
|
|
27
26
|
}
|
|
28
|
-
function stepIndexOf(
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
return
|
|
27
|
+
function stepIndexOf(ctx) {
|
|
28
|
+
const turnId = ctx.turn?.id;
|
|
29
|
+
if (!turnId) return -1;
|
|
30
|
+
return runs(ctx.view, { turnId }).filter((run) => run.status === "settled").length;
|
|
32
31
|
}
|
|
33
32
|
function replayStep(step, modelId = "modelo") {
|
|
34
33
|
return mockModel({
|
package/package.json
CHANGED
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agent-builder-lab/eve-kit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0-rc.1",
|
|
4
4
|
"description": "Liga um agente eve ao Agent Builder Lab: instrumentação da janela de contexto, canal com history e stubs, replay e autorização por conta de teste.",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "git+https://github.com/vinilana/agent-builder-lab.git",
|
|
8
|
+
"directory": "packages/eve-kit"
|
|
9
|
+
},
|
|
5
10
|
"type": "module",
|
|
6
11
|
"exports": {
|
|
7
12
|
".": {
|
|
@@ -39,11 +44,11 @@
|
|
|
39
44
|
"access": "public"
|
|
40
45
|
},
|
|
41
46
|
"peerDependencies": {
|
|
42
|
-
"eve": ">=0.
|
|
47
|
+
"eve": ">=1.0.0-rc.0 <2.0.0"
|
|
43
48
|
},
|
|
44
49
|
"devDependencies": {
|
|
45
50
|
"@types/node": "24.19.2",
|
|
46
|
-
"eve": "0.
|
|
51
|
+
"eve": "1.0.0-rc.2",
|
|
47
52
|
"tsup": "8.5.1",
|
|
48
53
|
"typescript": "6.0.3",
|
|
49
54
|
"vitest": "5.0.5",
|