@agent-builder-lab/eve-kit 0.2.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 +5 -2
- package/dist/channel.js +15 -4
- package/dist/{chunk-3IQOFBSQ.js → chunk-I5XIFBNJ.js} +1 -1
- package/dist/chunk-Z56XW2U4.js +33 -0
- package/dist/index.js +56 -29
- package/dist/mcp.d.ts +27 -1
- package/dist/mcp.js +13 -0
- 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.
|
|
@@ -28,6 +28,9 @@ interface LabChannelOptions extends Omit<EveChannelInput, "auth"> {
|
|
|
28
28
|
* para os atributos do auth do turno (`labAccount`), onde `labAuthorization()` confere cada
|
|
29
29
|
* tool call, e também sai do contexto que o modelo vê: a identidade vem do harness, nunca do
|
|
30
30
|
* texto.
|
|
31
|
+
* - Quando o pedido traz o modo do MCP da formação (`clientContext.labMcp`, o botão do lab), os
|
|
32
|
+
* ataques vão para os atributos do auth do turno (`labMcp`) e saem do contexto do modelo:
|
|
33
|
+
* `labMcpAtaquesOf(ctx)` (de `@agent-builder-lab/eve-kit/mcp`) lê na ferramenta.
|
|
31
34
|
*
|
|
32
35
|
* Em produção (`eve start`, Vercel) o acesso local não autentica nada e o canal se comporta como
|
|
33
36
|
* o padrão com os autenticadores que você passar.
|
package/dist/channel.js
CHANGED
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LAB_MCP_ATTRIBUTE,
|
|
3
|
+
LAB_MCP_CONTEXT_KEY,
|
|
4
|
+
labMcpAtaquesFromContext
|
|
5
|
+
} from "./chunk-Z56XW2U4.js";
|
|
1
6
|
import {
|
|
2
7
|
LAB_ACCOUNT_ATTRIBUTE,
|
|
3
8
|
LAB_ACCOUNT_CONTEXT_KEY,
|
|
@@ -8,7 +13,7 @@ import {
|
|
|
8
13
|
LAB_FORK_CONTEXT_KEY,
|
|
9
14
|
fetchForkPlan,
|
|
10
15
|
forkIdFromContext
|
|
11
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-I5XIFBNJ.js";
|
|
12
17
|
|
|
13
18
|
// src/channel.ts
|
|
14
19
|
import { localDev } from "eve/channels/auth";
|
|
@@ -31,11 +36,13 @@ function labOnMessage(options) {
|
|
|
31
36
|
const context = ctx.eve.clientContext;
|
|
32
37
|
const forkId = forkIdFromContext(context);
|
|
33
38
|
const account = labAccountFromContext(context);
|
|
34
|
-
|
|
39
|
+
const mcpAtaques = labMcpAtaquesFromContext(context);
|
|
40
|
+
if (!forkId && !account && mcpAtaques === void 0 && !hasLabKeys(context)) return base;
|
|
35
41
|
const plan = forkId ? await fetchForkPlan(forkId, options.connectorUrl) : void 0;
|
|
36
42
|
const attributes = {
|
|
37
43
|
...forkId ? { [LAB_FORK_ATTRIBUTE]: forkId } : {},
|
|
38
|
-
...account ? { [LAB_ACCOUNT_ATTRIBUTE]: JSON.stringify(account) } : {}
|
|
44
|
+
...account ? { [LAB_ACCOUNT_ATTRIBUTE]: JSON.stringify(account) } : {},
|
|
45
|
+
...mcpAtaques !== void 0 ? { [LAB_MCP_ATTRIBUTE]: JSON.stringify({ ataques: mcpAtaques }) } : {}
|
|
39
46
|
};
|
|
40
47
|
return {
|
|
41
48
|
...base,
|
|
@@ -68,7 +75,11 @@ function isLoopback(request) {
|
|
|
68
75
|
const host = new URL(request.url).hostname.replace(/^\[|\]$/g, "");
|
|
69
76
|
return host === "127.0.0.1" || host === "localhost" || host === "::1";
|
|
70
77
|
}
|
|
71
|
-
var LAB_KEYS = [
|
|
78
|
+
var LAB_KEYS = [
|
|
79
|
+
LAB_FORK_CONTEXT_KEY,
|
|
80
|
+
LAB_ACCOUNT_CONTEXT_KEY,
|
|
81
|
+
LAB_MCP_CONTEXT_KEY
|
|
82
|
+
];
|
|
72
83
|
function hasLabKeys(context) {
|
|
73
84
|
if (!context || typeof context !== "object" || Array.isArray(context)) return false;
|
|
74
85
|
return LAB_KEYS.some((key) => key in context);
|
|
@@ -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);
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// src/lab-mcp.ts
|
|
2
|
+
var LAB_MCP_CONTEXT_KEY = "labMcp";
|
|
3
|
+
var LAB_MCP_ATTRIBUTE = "labMcp";
|
|
4
|
+
var ATAQUES_VALIDOS = /^[a-z_@, ]{0,200}$/;
|
|
5
|
+
function labMcpAtaquesFromContext(context) {
|
|
6
|
+
if (!context || typeof context !== "object" || Array.isArray(context)) return void 0;
|
|
7
|
+
const value = context[LAB_MCP_CONTEXT_KEY];
|
|
8
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return void 0;
|
|
9
|
+
const v = value;
|
|
10
|
+
if (v.v !== 1 || typeof v.ataques !== "string") return void 0;
|
|
11
|
+
return ATAQUES_VALIDOS.test(v.ataques) ? v.ataques : void 0;
|
|
12
|
+
}
|
|
13
|
+
function labMcpAtaquesFromAuth(auth) {
|
|
14
|
+
const raw = auth?.attributes?.[LAB_MCP_ATTRIBUTE];
|
|
15
|
+
if (typeof raw !== "string") return void 0;
|
|
16
|
+
try {
|
|
17
|
+
const ataques = JSON.parse(raw)?.ataques;
|
|
18
|
+
return typeof ataques === "string" && ATAQUES_VALIDOS.test(ataques) ? ataques : void 0;
|
|
19
|
+
} catch {
|
|
20
|
+
return void 0;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
function labMcpAtaquesOf(ctx) {
|
|
24
|
+
return labMcpAtaquesFromAuth(ctx.session.auth.current);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export {
|
|
28
|
+
LAB_MCP_CONTEXT_KEY,
|
|
29
|
+
LAB_MCP_ATTRIBUTE,
|
|
30
|
+
labMcpAtaquesFromContext,
|
|
31
|
+
labMcpAtaquesFromAuth,
|
|
32
|
+
labMcpAtaquesOf
|
|
33
|
+
};
|
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/mcp.d.ts
CHANGED
|
@@ -1,5 +1,31 @@
|
|
|
1
1
|
import { ApprovalPolicy } from 'eve/tools/approval';
|
|
2
2
|
|
|
3
|
+
/** Chave do `clientContext` com o modo do MCP do turno. */
|
|
4
|
+
declare const LAB_MCP_CONTEXT_KEY = "labMcp";
|
|
5
|
+
/** Atributo do auth do turno com os ataques, em JSON (`{"ataques":"injecao"}`), para as ferramentas lerem. */
|
|
6
|
+
declare const LAB_MCP_ATTRIBUTE = "labMcp";
|
|
7
|
+
/**
|
|
8
|
+
* Os ataques que o lab mandou no `clientContext` do pedido: "" para o modo limpo, "injecao",
|
|
9
|
+
* "todos"… Undefined quando o pedido não traz o modo ou ele vem fora do formato.
|
|
10
|
+
*/
|
|
11
|
+
declare function labMcpAtaquesFromContext(context: unknown): string | undefined;
|
|
12
|
+
type AuthLike = {
|
|
13
|
+
readonly attributes?: Readonly<Record<string, string | readonly string[]>>;
|
|
14
|
+
};
|
|
15
|
+
/** Os ataques guardados nos atributos de um auth (o `labChannel()` grava). */
|
|
16
|
+
declare function labMcpAtaquesFromAuth(auth: AuthLike | null | undefined): string | undefined;
|
|
17
|
+
/**
|
|
18
|
+
* Os ataques do MCP escolhidos no lab para este turno, para usar dentro de uma ferramenta:
|
|
19
|
+
* `labMcpAtaquesOf(ctx)`. "" é o modo limpo; undefined, sem escolha (vale a URL do agente).
|
|
20
|
+
*/
|
|
21
|
+
declare function labMcpAtaquesOf(ctx: {
|
|
22
|
+
readonly session: {
|
|
23
|
+
readonly auth: {
|
|
24
|
+
readonly current: AuthLike | null;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
}): string | undefined;
|
|
28
|
+
|
|
3
29
|
interface ClienteMcp {
|
|
4
30
|
chamar(nome: string, argumentos: Record<string, unknown>, signal?: AbortSignal): Promise<unknown>;
|
|
5
31
|
listar(signal?: AbortSignal): Promise<Array<{
|
|
@@ -84,4 +110,4 @@ declare function aprovarEntradaExterna<TInput = Record<string, unknown>>(opcoes?
|
|
|
84
110
|
readonly next?: ApprovalPolicy<TInput>;
|
|
85
111
|
}): ApprovalPolicy<TInput>;
|
|
86
112
|
|
|
87
|
-
export { type AchadoNoResultado, type ClienteMcp, type OpcoesDaFerramentaMcp, type OpcoesDeVarredura, type OpcoesDoCliente, type ResultadoDaVarredura, type ResultadoExterno, type SinalDeAtaque, aprovarEntradaExterna, chamarMcpVarrido, clienteMcpHttp, varrerResultado };
|
|
113
|
+
export { type AchadoNoResultado, type ClienteMcp, LAB_MCP_ATTRIBUTE, LAB_MCP_CONTEXT_KEY, type OpcoesDaFerramentaMcp, type OpcoesDeVarredura, type OpcoesDoCliente, type ResultadoDaVarredura, type ResultadoExterno, type SinalDeAtaque, aprovarEntradaExterna, chamarMcpVarrido, clienteMcpHttp, labMcpAtaquesFromAuth, labMcpAtaquesFromContext, labMcpAtaquesOf, varrerResultado };
|
package/dist/mcp.js
CHANGED
|
@@ -1,3 +1,11 @@
|
|
|
1
|
+
import {
|
|
2
|
+
LAB_MCP_ATTRIBUTE,
|
|
3
|
+
LAB_MCP_CONTEXT_KEY,
|
|
4
|
+
labMcpAtaquesFromAuth,
|
|
5
|
+
labMcpAtaquesFromContext,
|
|
6
|
+
labMcpAtaquesOf
|
|
7
|
+
} from "./chunk-Z56XW2U4.js";
|
|
8
|
+
|
|
1
9
|
// src/mcp-client.ts
|
|
2
10
|
var PROTOCOLO = "2025-06-18";
|
|
3
11
|
var ErroMcp = class extends Error {
|
|
@@ -270,8 +278,13 @@ function aprovarEntradaExterna(opcoes = {}) {
|
|
|
270
278
|
};
|
|
271
279
|
}
|
|
272
280
|
export {
|
|
281
|
+
LAB_MCP_ATTRIBUTE,
|
|
282
|
+
LAB_MCP_CONTEXT_KEY,
|
|
273
283
|
aprovarEntradaExterna,
|
|
274
284
|
chamarMcpVarrido,
|
|
275
285
|
clienteMcpHttp,
|
|
286
|
+
labMcpAtaquesFromAuth,
|
|
287
|
+
labMcpAtaquesFromContext,
|
|
288
|
+
labMcpAtaquesOf,
|
|
276
289
|
varrerResultado
|
|
277
290
|
};
|
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",
|