@dogpile/sdk 0.1.0
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/CHANGELOG.md +37 -0
- package/LICENSE +16 -0
- package/README.md +842 -0
- package/dist/browser/index.d.ts +8 -0
- package/dist/browser/index.d.ts.map +1 -0
- package/dist/browser/index.js +4493 -0
- package/dist/browser/index.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/openai-compatible.d.ts +44 -0
- package/dist/providers/openai-compatible.d.ts.map +1 -0
- package/dist/providers/openai-compatible.js +305 -0
- package/dist/providers/openai-compatible.js.map +1 -0
- package/dist/runtime/broadcast.d.ts +18 -0
- package/dist/runtime/broadcast.d.ts.map +1 -0
- package/dist/runtime/broadcast.js +335 -0
- package/dist/runtime/broadcast.js.map +1 -0
- package/dist/runtime/cancellation.d.ts +6 -0
- package/dist/runtime/cancellation.d.ts.map +1 -0
- package/dist/runtime/cancellation.js +35 -0
- package/dist/runtime/cancellation.js.map +1 -0
- package/dist/runtime/coordinator.d.ts +18 -0
- package/dist/runtime/coordinator.d.ts.map +1 -0
- package/dist/runtime/coordinator.js +434 -0
- package/dist/runtime/coordinator.js.map +1 -0
- package/dist/runtime/decisions.d.ts +5 -0
- package/dist/runtime/decisions.d.ts.map +1 -0
- package/dist/runtime/decisions.js +31 -0
- package/dist/runtime/decisions.js.map +1 -0
- package/dist/runtime/defaults.d.ts +63 -0
- package/dist/runtime/defaults.d.ts.map +1 -0
- package/dist/runtime/defaults.js +426 -0
- package/dist/runtime/defaults.js.map +1 -0
- package/dist/runtime/engine.d.ts +79 -0
- package/dist/runtime/engine.d.ts.map +1 -0
- package/dist/runtime/engine.js +723 -0
- package/dist/runtime/engine.js.map +1 -0
- package/dist/runtime/model.d.ts +14 -0
- package/dist/runtime/model.d.ts.map +1 -0
- package/dist/runtime/model.js +82 -0
- package/dist/runtime/model.js.map +1 -0
- package/dist/runtime/sequential.d.ts +18 -0
- package/dist/runtime/sequential.d.ts.map +1 -0
- package/dist/runtime/sequential.js +277 -0
- package/dist/runtime/sequential.js.map +1 -0
- package/dist/runtime/shared.d.ts +18 -0
- package/dist/runtime/shared.d.ts.map +1 -0
- package/dist/runtime/shared.js +288 -0
- package/dist/runtime/shared.js.map +1 -0
- package/dist/runtime/termination.d.ts +77 -0
- package/dist/runtime/termination.d.ts.map +1 -0
- package/dist/runtime/termination.js +355 -0
- package/dist/runtime/termination.js.map +1 -0
- package/dist/runtime/tools.d.ts +314 -0
- package/dist/runtime/tools.d.ts.map +1 -0
- package/dist/runtime/tools.js +969 -0
- package/dist/runtime/tools.js.map +1 -0
- package/dist/runtime/validation.d.ts +23 -0
- package/dist/runtime/validation.d.ts.map +1 -0
- package/dist/runtime/validation.js +656 -0
- package/dist/runtime/validation.js.map +1 -0
- package/dist/types.d.ts +2434 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +81 -0
- package/dist/types.js.map +1 -0
- package/package.json +157 -0
- package/src/browser/index.ts +7 -0
- package/src/index.ts +195 -0
- package/src/providers/openai-compatible.ts +406 -0
- package/src/runtime/broadcast.test.ts +355 -0
- package/src/runtime/broadcast.ts +428 -0
- package/src/runtime/cancellation.ts +40 -0
- package/src/runtime/coordinator.test.ts +468 -0
- package/src/runtime/coordinator.ts +581 -0
- package/src/runtime/decisions.ts +38 -0
- package/src/runtime/defaults.ts +547 -0
- package/src/runtime/engine.ts +880 -0
- package/src/runtime/model.ts +117 -0
- package/src/runtime/sequential.test.ts +262 -0
- package/src/runtime/sequential.ts +357 -0
- package/src/runtime/shared.test.ts +265 -0
- package/src/runtime/shared.ts +367 -0
- package/src/runtime/termination.ts +463 -0
- package/src/runtime/tools.ts +1518 -0
- package/src/runtime/validation.ts +771 -0
- package/src/types.ts +2729 -0
|
@@ -0,0 +1,367 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
AgentSpec,
|
|
3
|
+
ConfiguredModelProvider,
|
|
4
|
+
CostSummary,
|
|
5
|
+
DogpileOptions,
|
|
6
|
+
JsonObject,
|
|
7
|
+
JsonValue,
|
|
8
|
+
ModelRequest,
|
|
9
|
+
ModelResponse,
|
|
10
|
+
ReplayTraceProtocolDecision,
|
|
11
|
+
ReplayTraceProviderCall,
|
|
12
|
+
RuntimeTool,
|
|
13
|
+
RunEvent,
|
|
14
|
+
RunResult,
|
|
15
|
+
SharedProtocolConfig,
|
|
16
|
+
TerminationCondition,
|
|
17
|
+
TerminationStopRecord,
|
|
18
|
+
Tier,
|
|
19
|
+
TranscriptEntry
|
|
20
|
+
} from "../types.js";
|
|
21
|
+
import {
|
|
22
|
+
addCost,
|
|
23
|
+
createReplayTraceBudget,
|
|
24
|
+
createReplayTraceBudgetStateChanges,
|
|
25
|
+
createReplayTraceFinalOutput,
|
|
26
|
+
createReplayTraceProtocolDecision,
|
|
27
|
+
createReplayTraceRunInputs,
|
|
28
|
+
createReplayTraceSeed,
|
|
29
|
+
createRunAccounting,
|
|
30
|
+
createRunEventLog,
|
|
31
|
+
createRunMetadata,
|
|
32
|
+
createRunUsage,
|
|
33
|
+
createTranscriptLink,
|
|
34
|
+
emptyCost
|
|
35
|
+
} from "./defaults.js";
|
|
36
|
+
import { throwIfAborted } from "./cancellation.js";
|
|
37
|
+
import { parseAgentDecision } from "./decisions.js";
|
|
38
|
+
import { generateModelTurn } from "./model.js";
|
|
39
|
+
import { evaluateTerminationStop } from "./termination.js";
|
|
40
|
+
import { createRuntimeToolExecutor, executeModelResponseToolRequests, runtimeToolAvailability } from "./tools.js";
|
|
41
|
+
|
|
42
|
+
interface SharedRunOptions {
|
|
43
|
+
readonly intent: string;
|
|
44
|
+
readonly protocol: SharedProtocolConfig;
|
|
45
|
+
readonly tier: Tier;
|
|
46
|
+
readonly model: ConfiguredModelProvider;
|
|
47
|
+
readonly agents: readonly AgentSpec[];
|
|
48
|
+
readonly tools: readonly RuntimeTool<JsonObject, JsonValue>[];
|
|
49
|
+
readonly temperature: number;
|
|
50
|
+
readonly budget?: DogpileOptions["budget"];
|
|
51
|
+
readonly seed?: string | number;
|
|
52
|
+
readonly signal?: AbortSignal;
|
|
53
|
+
readonly terminate?: TerminationCondition;
|
|
54
|
+
readonly emit?: (event: RunEvent) => void;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export async function runShared(options: SharedRunOptions): Promise<RunResult> {
|
|
58
|
+
const runId = createRunId();
|
|
59
|
+
const events: RunEvent[] = [];
|
|
60
|
+
const transcript: TranscriptEntry[] = [];
|
|
61
|
+
const protocolDecisions: ReplayTraceProtocolDecision[] = [];
|
|
62
|
+
const providerCalls: ReplayTraceProviderCall[] = [];
|
|
63
|
+
let totalCost = emptyCost();
|
|
64
|
+
const sharedState = options.protocol.organizationalMemory ?? "";
|
|
65
|
+
const maxTurns = options.protocol.maxTurns ?? options.agents.length;
|
|
66
|
+
const activeAgents = options.agents.slice(0, maxTurns);
|
|
67
|
+
const startedAtMs = nowMs();
|
|
68
|
+
let stopped = false;
|
|
69
|
+
let termination: TerminationStopRecord | undefined;
|
|
70
|
+
|
|
71
|
+
const emit = (event: RunEvent): void => {
|
|
72
|
+
events.push(event);
|
|
73
|
+
options.emit?.(event);
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
const recordProtocolDecision = (
|
|
77
|
+
event: RunEvent,
|
|
78
|
+
decisionOptions?: Parameters<typeof createReplayTraceProtocolDecision>[3]
|
|
79
|
+
): void => {
|
|
80
|
+
protocolDecisions.push(createReplayTraceProtocolDecision("shared", event, events.length - 1, decisionOptions));
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
const toolExecutor = createRuntimeToolExecutor({
|
|
84
|
+
runId,
|
|
85
|
+
protocol: "shared",
|
|
86
|
+
tier: options.tier,
|
|
87
|
+
tools: options.tools,
|
|
88
|
+
emit(event): void {
|
|
89
|
+
emit(event);
|
|
90
|
+
recordProtocolDecision(event);
|
|
91
|
+
},
|
|
92
|
+
getTrace: () => ({ events, transcript }),
|
|
93
|
+
...(options.signal !== undefined ? { abortSignal: options.signal } : {})
|
|
94
|
+
});
|
|
95
|
+
const toolAvailability = runtimeToolAvailability(toolExecutor.tools);
|
|
96
|
+
|
|
97
|
+
throwIfAborted(options.signal, options.model.id);
|
|
98
|
+
|
|
99
|
+
for (const agent of activeAgents) {
|
|
100
|
+
const event: RunEvent = {
|
|
101
|
+
type: "role-assignment",
|
|
102
|
+
runId,
|
|
103
|
+
at: new Date().toISOString(),
|
|
104
|
+
agentId: agent.id,
|
|
105
|
+
role: agent.role
|
|
106
|
+
};
|
|
107
|
+
emit(event);
|
|
108
|
+
recordProtocolDecision(event);
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
if (!stopIfNeeded()) {
|
|
112
|
+
const providerCallSlots: ReplayTraceProviderCall[] = [];
|
|
113
|
+
const turnResults = await Promise.all(
|
|
114
|
+
activeAgents.map(async (agent, index) => {
|
|
115
|
+
const turn = index + 1;
|
|
116
|
+
const input = buildSharedInput(options.intent, sharedState, turn);
|
|
117
|
+
const request: ModelRequest = {
|
|
118
|
+
temperature: options.temperature,
|
|
119
|
+
...(options.signal !== undefined ? { signal: options.signal } : {}),
|
|
120
|
+
metadata: {
|
|
121
|
+
runId,
|
|
122
|
+
protocol: "shared",
|
|
123
|
+
agentId: agent.id,
|
|
124
|
+
role: agent.role,
|
|
125
|
+
tier: options.tier,
|
|
126
|
+
turn,
|
|
127
|
+
...toolAvailability
|
|
128
|
+
},
|
|
129
|
+
messages: [
|
|
130
|
+
{
|
|
131
|
+
role: "system",
|
|
132
|
+
content: buildSystemPrompt(agent)
|
|
133
|
+
},
|
|
134
|
+
{
|
|
135
|
+
role: "user",
|
|
136
|
+
content: input
|
|
137
|
+
}
|
|
138
|
+
]
|
|
139
|
+
};
|
|
140
|
+
const response = await generateModelTurn({
|
|
141
|
+
model: options.model,
|
|
142
|
+
request,
|
|
143
|
+
runId,
|
|
144
|
+
agent,
|
|
145
|
+
input,
|
|
146
|
+
emit,
|
|
147
|
+
callId: providerCallIdFor(runId, providerCalls.length + index + 1),
|
|
148
|
+
onProviderCall(call): void {
|
|
149
|
+
providerCallSlots[index] = call;
|
|
150
|
+
}
|
|
151
|
+
});
|
|
152
|
+
const decision = parseAgentDecision(response.text);
|
|
153
|
+
const toolCalls = await executeModelResponseToolRequests({
|
|
154
|
+
response,
|
|
155
|
+
executor: toolExecutor,
|
|
156
|
+
agentId: agent.id,
|
|
157
|
+
role: agent.role,
|
|
158
|
+
turn
|
|
159
|
+
});
|
|
160
|
+
throwIfAborted(options.signal, options.model.id);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
agent,
|
|
164
|
+
turn,
|
|
165
|
+
input,
|
|
166
|
+
response,
|
|
167
|
+
decision,
|
|
168
|
+
toolCalls,
|
|
169
|
+
turnCost: responseCost(response)
|
|
170
|
+
};
|
|
171
|
+
})
|
|
172
|
+
);
|
|
173
|
+
providerCalls.push(...providerCallSlots.filter((call): call is ReplayTraceProviderCall => call !== undefined));
|
|
174
|
+
|
|
175
|
+
for (const result of turnResults) {
|
|
176
|
+
totalCost = addCost(totalCost, result.turnCost);
|
|
177
|
+
transcript.push({
|
|
178
|
+
agentId: result.agent.id,
|
|
179
|
+
role: result.agent.role,
|
|
180
|
+
input: result.input,
|
|
181
|
+
output: result.response.text,
|
|
182
|
+
...(result.decision !== undefined ? { decision: result.decision } : {}),
|
|
183
|
+
...(result.toolCalls.length > 0 ? { toolCalls: result.toolCalls } : {})
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
const event: RunEvent = {
|
|
187
|
+
type: "agent-turn",
|
|
188
|
+
runId,
|
|
189
|
+
at: new Date().toISOString(),
|
|
190
|
+
agentId: result.agent.id,
|
|
191
|
+
role: result.agent.role,
|
|
192
|
+
input: result.input,
|
|
193
|
+
output: result.response.text,
|
|
194
|
+
...(result.decision !== undefined ? { decision: result.decision } : {}),
|
|
195
|
+
cost: totalCost
|
|
196
|
+
};
|
|
197
|
+
emit(event);
|
|
198
|
+
recordProtocolDecision(event, {
|
|
199
|
+
turn: result.turn,
|
|
200
|
+
transcriptEntryCount: transcript.length
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
stopIfNeeded();
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
const output = synthesizeSharedOutput(transcript);
|
|
207
|
+
throwIfAborted(options.signal, options.model.id);
|
|
208
|
+
const final: RunEvent = {
|
|
209
|
+
type: "final",
|
|
210
|
+
runId,
|
|
211
|
+
at: new Date().toISOString(),
|
|
212
|
+
output,
|
|
213
|
+
cost: totalCost,
|
|
214
|
+
transcript: createTranscriptLink(transcript),
|
|
215
|
+
...(termination !== undefined ? { termination } : {})
|
|
216
|
+
};
|
|
217
|
+
emit(final);
|
|
218
|
+
recordProtocolDecision(final, {
|
|
219
|
+
transcriptEntryCount: transcript.length
|
|
220
|
+
});
|
|
221
|
+
const finalEvent = events.at(-1);
|
|
222
|
+
|
|
223
|
+
return {
|
|
224
|
+
output,
|
|
225
|
+
eventLog: createRunEventLog(runId, "shared", events),
|
|
226
|
+
trace: {
|
|
227
|
+
schemaVersion: "1.0",
|
|
228
|
+
runId,
|
|
229
|
+
protocol: "shared",
|
|
230
|
+
tier: options.tier,
|
|
231
|
+
modelProviderId: options.model.id,
|
|
232
|
+
agentsUsed: activeAgents,
|
|
233
|
+
inputs: createReplayTraceRunInputs({
|
|
234
|
+
intent: options.intent,
|
|
235
|
+
protocol: options.protocol,
|
|
236
|
+
tier: options.tier,
|
|
237
|
+
modelProviderId: options.model.id,
|
|
238
|
+
agents: activeAgents,
|
|
239
|
+
temperature: options.temperature
|
|
240
|
+
}),
|
|
241
|
+
budget: createReplayTraceBudget({
|
|
242
|
+
tier: options.tier,
|
|
243
|
+
...(options.budget ? { caps: options.budget } : {}),
|
|
244
|
+
...(options.terminate ? { termination: options.terminate } : {})
|
|
245
|
+
}),
|
|
246
|
+
budgetStateChanges: createReplayTraceBudgetStateChanges(events),
|
|
247
|
+
seed: createReplayTraceSeed(options.seed),
|
|
248
|
+
protocolDecisions,
|
|
249
|
+
providerCalls,
|
|
250
|
+
finalOutput: createReplayTraceFinalOutput(output, finalEvent ?? {
|
|
251
|
+
type: "final",
|
|
252
|
+
runId,
|
|
253
|
+
at: "",
|
|
254
|
+
output,
|
|
255
|
+
cost: totalCost,
|
|
256
|
+
transcript: createTranscriptLink(transcript)
|
|
257
|
+
}),
|
|
258
|
+
events,
|
|
259
|
+
transcript
|
|
260
|
+
},
|
|
261
|
+
transcript,
|
|
262
|
+
usage: createRunUsage(totalCost),
|
|
263
|
+
metadata: createRunMetadata({
|
|
264
|
+
runId,
|
|
265
|
+
protocol: "shared",
|
|
266
|
+
tier: options.tier,
|
|
267
|
+
modelProviderId: options.model.id,
|
|
268
|
+
agentsUsed: activeAgents,
|
|
269
|
+
events
|
|
270
|
+
}),
|
|
271
|
+
accounting: createRunAccounting({
|
|
272
|
+
tier: options.tier,
|
|
273
|
+
...(options.budget ? { budget: options.budget } : {}),
|
|
274
|
+
...(options.terminate ? { termination: options.terminate } : {}),
|
|
275
|
+
cost: totalCost,
|
|
276
|
+
events
|
|
277
|
+
}),
|
|
278
|
+
cost: totalCost
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
function stopIfNeeded(): boolean {
|
|
282
|
+
throwIfAborted(options.signal, options.model.id);
|
|
283
|
+
|
|
284
|
+
if (stopped || !options.terminate) {
|
|
285
|
+
return stopped;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
const stopRecord = evaluateTerminationStop(options.terminate, {
|
|
289
|
+
runId,
|
|
290
|
+
protocol: "shared",
|
|
291
|
+
tier: options.tier,
|
|
292
|
+
cost: totalCost,
|
|
293
|
+
events,
|
|
294
|
+
transcript,
|
|
295
|
+
iteration: transcript.length,
|
|
296
|
+
elapsedMs: elapsedMs(startedAtMs)
|
|
297
|
+
});
|
|
298
|
+
|
|
299
|
+
if (!stopRecord) {
|
|
300
|
+
return false;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
stopped = true;
|
|
304
|
+
termination = stopRecord;
|
|
305
|
+
if (stopRecord.reason === "budget") {
|
|
306
|
+
emitBudgetStop(stopRecord);
|
|
307
|
+
}
|
|
308
|
+
return true;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
function emitBudgetStop(record: TerminationStopRecord): void {
|
|
312
|
+
const event: RunEvent = {
|
|
313
|
+
type: "budget-stop",
|
|
314
|
+
runId,
|
|
315
|
+
at: new Date().toISOString(),
|
|
316
|
+
reason: record.budgetReason ?? "cost",
|
|
317
|
+
cost: totalCost,
|
|
318
|
+
iteration: transcript.length,
|
|
319
|
+
elapsedMs: elapsedMs(startedAtMs),
|
|
320
|
+
detail: record.detail ?? {}
|
|
321
|
+
};
|
|
322
|
+
emit(event);
|
|
323
|
+
recordProtocolDecision(event, {
|
|
324
|
+
transcriptEntryCount: transcript.length
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
function buildSystemPrompt(agent: AgentSpec): string {
|
|
330
|
+
const instruction = agent.instructions ? `\nInstructions: ${agent.instructions}` : "";
|
|
331
|
+
return `You are ${agent.id}, acting as ${agent.role} in a Shared multi-agent protocol. Read the shared state, update it with your best contribution, and preserve useful prior work.${instruction}`;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
function buildSharedInput(intent: string, sharedState: string, turn: number): string {
|
|
335
|
+
const state = sharedState ? sharedState : "(empty)";
|
|
336
|
+
return `Mission: ${intent}\nShared turn ${turn}: read the shared state and return an improved shared-state update.\n\nShared state:\n${state}`;
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
function synthesizeSharedOutput(transcript: readonly TranscriptEntry[]): string {
|
|
340
|
+
return transcript.map((entry) => `${entry.role}:${entry.agentId} => ${entry.output}`).join("\n");
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function responseCost(response: ModelResponse): CostSummary {
|
|
344
|
+
return {
|
|
345
|
+
usd: response.costUsd ?? 0,
|
|
346
|
+
inputTokens: response.usage?.inputTokens ?? 0,
|
|
347
|
+
outputTokens: response.usage?.outputTokens ?? 0,
|
|
348
|
+
totalTokens: response.usage?.totalTokens ?? 0
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
function createRunId(): string {
|
|
353
|
+
const random = globalThis.crypto?.randomUUID?.();
|
|
354
|
+
return random ?? `run-${Date.now().toString(36)}`;
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
function nowMs(): number {
|
|
358
|
+
return globalThis.performance?.now() ?? Date.now();
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
function elapsedMs(startedAtMs: number): number {
|
|
362
|
+
return Math.max(0, nowMs() - startedAtMs);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function providerCallIdFor(runId: string, oneBasedIndex: number): string {
|
|
366
|
+
return `${runId}:provider-call:${oneBasedIndex}`;
|
|
367
|
+
}
|