@kevin5251984/guild 0.2.12
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/LICENSE +21 -0
- package/bin/guildd.mjs +20 -0
- package/cordis.yml +24 -0
- package/package.json +52 -0
- package/src/agent-file.ts +125 -0
- package/src/browser.ts +668 -0
- package/src/catalog/default-bots.ts +263 -0
- package/src/catalog/skills.ts +128 -0
- package/src/catalog/subagents.ts +70 -0
- package/src/chat-parts.ts +71 -0
- package/src/cli-args.ts +75 -0
- package/src/cli.ts +60 -0
- package/src/compact.ts +355 -0
- package/src/cordis.d.ts +40 -0
- package/src/db.ts +653 -0
- package/src/generate.ts +673 -0
- package/src/handlers.ts +1623 -0
- package/src/harness.ts +326 -0
- package/src/host-agents.ts +137 -0
- package/src/host-browse.ts +199 -0
- package/src/host-skills.ts +150 -0
- package/src/image-gen.ts +270 -0
- package/src/index.ts +12 -0
- package/src/llm.ts +993 -0
- package/src/mcp.ts +563 -0
- package/src/memory.ts +159 -0
- package/src/mention.ts +176 -0
- package/src/oauth.ts +1474 -0
- package/src/plugins/api.ts +8 -0
- package/src/plugins/chat.ts +31 -0
- package/src/plugins/harness.ts +77 -0
- package/src/plugins/llm.ts +50 -0
- package/src/plugins/mcp.ts +58 -0
- package/src/plugins/memory.ts +42 -0
- package/src/plugins/oauth.ts +47 -0
- package/src/plugins/server.ts +126 -0
- package/src/plugins/store.ts +29 -0
- package/src/plugins/tools.ts +79 -0
- package/src/public/buddy.js +432 -0
- package/src/public/chat.css +3045 -0
- package/src/public/chat.html +5834 -0
- package/src/public/favicon-16.png +0 -0
- package/src/public/favicon-16.svg +10 -0
- package/src/public/favicon-32.png +0 -0
- package/src/public/favicon.ico +0 -0
- package/src/public/favicon.svg +13 -0
- package/src/public/i18n.js +663 -0
- package/src/public/index.html +143 -0
- package/src/public/library.html +678 -0
- package/src/public/mcp-add.html +126 -0
- package/src/public/md.js +332 -0
- package/src/public/rpg/inn-street.jpg +0 -0
- package/src/public/settings.html +795 -0
- package/src/public/skills-add.html +212 -0
- package/src/public/studio.html +1181 -0
- package/src/public/style.css +1678 -0
- package/src/public/subagents-add.html +152 -0
- package/src/router.ts +978 -0
- package/src/send-budget.ts +52 -0
- package/src/server.ts +1 -0
- package/src/skill-import.ts +250 -0
- package/src/slash.ts +15 -0
- package/src/start.ts +103 -0
- package/src/store.ts +1208 -0
- package/src/subagent.ts +355 -0
- package/src/tools.ts +818 -0
- package/src/trajectory.ts +339 -0
- package/src/usage.ts +111 -0
- package/vendor/protocol/package.json +19 -0
- package/vendor/protocol/src/index.ts +159 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import type { ChatMessage } from "@guild/protocol";
|
|
2
|
+
import type { ToolTrace } from "./tools.ts";
|
|
3
|
+
|
|
4
|
+
export type TrajectoryKind =
|
|
5
|
+
| "system"
|
|
6
|
+
| "user"
|
|
7
|
+
| "context"
|
|
8
|
+
| "model"
|
|
9
|
+
| "thinking"
|
|
10
|
+
| "tool"
|
|
11
|
+
| "skill"
|
|
12
|
+
| "spawn"
|
|
13
|
+
| "assistant";
|
|
14
|
+
|
|
15
|
+
export type TrajectoryEvent = {
|
|
16
|
+
seq: number;
|
|
17
|
+
ts: string;
|
|
18
|
+
turnId: string;
|
|
19
|
+
botId?: string;
|
|
20
|
+
kind: TrajectoryKind;
|
|
21
|
+
summary: string;
|
|
22
|
+
payload?: unknown;
|
|
23
|
+
result?: string;
|
|
24
|
+
durationMs?: number;
|
|
25
|
+
isError?: boolean;
|
|
26
|
+
/** In-progress turn; not persisted. */
|
|
27
|
+
live?: boolean;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type TrajectoryDraft = Omit<TrajectoryEvent, "seq">;
|
|
31
|
+
|
|
32
|
+
const CLIP = 140;
|
|
33
|
+
const FIELD_CAP = 32_000;
|
|
34
|
+
|
|
35
|
+
export function clip(text: string, n = CLIP): string {
|
|
36
|
+
const one = String(text || "").replace(/\s+/g, " ").trim();
|
|
37
|
+
if (one.length <= n) return one;
|
|
38
|
+
return one.slice(0, n - 1) + "…";
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function recordOf(value: unknown): Record<string, unknown> | null {
|
|
42
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return null;
|
|
43
|
+
return value as Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/** Old rows logged spawn as TOOL "spawn spawn". Present them as spawn. */
|
|
47
|
+
export function promoteSpawnEvent<T extends { kind: string; summary: string; payload?: unknown }>(
|
|
48
|
+
event: T,
|
|
49
|
+
): T & { kind: TrajectoryKind; summary: string } {
|
|
50
|
+
if (event.kind === "spawn") return event as T & { kind: TrajectoryKind; summary: string };
|
|
51
|
+
const payload = recordOf(event.payload);
|
|
52
|
+
const toolName = String(payload?.name || "");
|
|
53
|
+
const looksSpawn =
|
|
54
|
+
event.kind === "tool" &&
|
|
55
|
+
(toolName === "spawn" || /^\s*spawn(\s+spawn)?\s*$/i.test(event.summary || ""));
|
|
56
|
+
if (!looksSpawn) return event as T & { kind: TrajectoryKind; summary: string };
|
|
57
|
+
const args = recordOf(payload?.args) || payload || {};
|
|
58
|
+
const agent = String(args.name || "worker").trim() || "worker";
|
|
59
|
+
const label = String(args.description || "").replace(/\s+/g, " ").trim();
|
|
60
|
+
const prompt = String(args.prompt || "").replace(/\s+/g, " ").trim();
|
|
61
|
+
return {
|
|
62
|
+
...event,
|
|
63
|
+
kind: "spawn",
|
|
64
|
+
summary: clip(
|
|
65
|
+
`${agent}${label ? " · " + label : ""}${prompt ? " — " + prompt : ""}`,
|
|
66
|
+
),
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
function cap(value: unknown): unknown {
|
|
71
|
+
if (typeof value === "string") {
|
|
72
|
+
return value.length > FIELD_CAP ? value.slice(0, FIELD_CAP) : value;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
const raw = JSON.stringify(value);
|
|
76
|
+
if (raw && raw.length > FIELD_CAP) return raw.slice(0, FIELD_CAP);
|
|
77
|
+
} catch {
|
|
78
|
+
/* ignore */
|
|
79
|
+
}
|
|
80
|
+
return value;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export function userTrajectoryEvent(
|
|
84
|
+
messageId: string,
|
|
85
|
+
body: string,
|
|
86
|
+
ts = new Date().toISOString(),
|
|
87
|
+
): TrajectoryDraft {
|
|
88
|
+
return {
|
|
89
|
+
ts,
|
|
90
|
+
turnId: messageId,
|
|
91
|
+
kind: "user",
|
|
92
|
+
summary: clip(body),
|
|
93
|
+
payload: { body },
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function turnTrajectoryEvents(input: {
|
|
98
|
+
turnId: string;
|
|
99
|
+
botId: string;
|
|
100
|
+
ts?: string;
|
|
101
|
+
system?: string;
|
|
102
|
+
channelMd?: string;
|
|
103
|
+
model?: { provider: string; model: string } | null;
|
|
104
|
+
thinking?: string;
|
|
105
|
+
traces?: ToolTrace[];
|
|
106
|
+
text: string;
|
|
107
|
+
source?: string;
|
|
108
|
+
}): TrajectoryDraft[] {
|
|
109
|
+
const ts = input.ts || new Date().toISOString();
|
|
110
|
+
const { turnId, botId } = input;
|
|
111
|
+
const events: TrajectoryDraft[] = [];
|
|
112
|
+
const modelLabel = input.model
|
|
113
|
+
? `${input.model.provider} / ${input.model.model}`
|
|
114
|
+
: input.source === "local"
|
|
115
|
+
? "local"
|
|
116
|
+
: "";
|
|
117
|
+
if (modelLabel) {
|
|
118
|
+
events.push({
|
|
119
|
+
ts,
|
|
120
|
+
turnId,
|
|
121
|
+
botId,
|
|
122
|
+
kind: "model",
|
|
123
|
+
summary: modelLabel,
|
|
124
|
+
payload: input.model ?? { source: "local" },
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
if (input.system) {
|
|
128
|
+
events.push({
|
|
129
|
+
ts,
|
|
130
|
+
turnId,
|
|
131
|
+
botId,
|
|
132
|
+
kind: "system",
|
|
133
|
+
summary: clip(input.system),
|
|
134
|
+
payload: cap(input.system),
|
|
135
|
+
});
|
|
136
|
+
}
|
|
137
|
+
if (input.channelMd?.trim()) {
|
|
138
|
+
events.push({
|
|
139
|
+
ts,
|
|
140
|
+
turnId,
|
|
141
|
+
botId,
|
|
142
|
+
kind: "context",
|
|
143
|
+
summary: "Channel.md",
|
|
144
|
+
payload: cap(input.channelMd),
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
if (input.thinking?.trim()) {
|
|
148
|
+
events.push({
|
|
149
|
+
ts,
|
|
150
|
+
turnId,
|
|
151
|
+
botId,
|
|
152
|
+
kind: "thinking",
|
|
153
|
+
summary: clip(input.thinking),
|
|
154
|
+
result: String(cap(input.thinking)),
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
for (const trace of input.traces ?? []) {
|
|
158
|
+
if (trace.name === "skill") {
|
|
159
|
+
const name = String(trace.args.name ?? "skill");
|
|
160
|
+
events.push({
|
|
161
|
+
ts,
|
|
162
|
+
turnId,
|
|
163
|
+
botId,
|
|
164
|
+
kind: "skill",
|
|
165
|
+
summary: `${name}${trace.running ? " …" : ""}`,
|
|
166
|
+
payload: cap(trace.args),
|
|
167
|
+
result: String(cap(trace.text ?? "")),
|
|
168
|
+
isError: trace.isError,
|
|
169
|
+
});
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (trace.name === "spawn" || trace.name === "read_spawn") {
|
|
173
|
+
const agent =
|
|
174
|
+
String(
|
|
175
|
+
trace.args.profile ||
|
|
176
|
+
trace.args.name ||
|
|
177
|
+
trace.args.agent ||
|
|
178
|
+
"worker",
|
|
179
|
+
).trim() || "worker";
|
|
180
|
+
const label = String(trace.args.title || trace.args.description || "")
|
|
181
|
+
.replace(/\s+/g, " ")
|
|
182
|
+
.trim();
|
|
183
|
+
const prompt = String(trace.args.prompt || trace.args.task || "")
|
|
184
|
+
.replace(/\s+/g, " ")
|
|
185
|
+
.trim();
|
|
186
|
+
const bg =
|
|
187
|
+
trace.args.background === true || trace.args.is_background === true
|
|
188
|
+
? " (bg)"
|
|
189
|
+
: "";
|
|
190
|
+
const waitId = String(trace.args.agent_id || trace.args.id || "").trim();
|
|
191
|
+
events.push({
|
|
192
|
+
ts,
|
|
193
|
+
turnId,
|
|
194
|
+
botId,
|
|
195
|
+
kind: "spawn",
|
|
196
|
+
summary: clip(
|
|
197
|
+
trace.name === "read_spawn"
|
|
198
|
+
? `read ${waitId || agent}${trace.running ? " …" : ""}`
|
|
199
|
+
: `${agent}${bg}${label ? " · " + label : ""}${prompt ? " — " + prompt : ""}${trace.running ? " …" : ""}`,
|
|
200
|
+
),
|
|
201
|
+
payload: cap(trace.args),
|
|
202
|
+
result: String(cap(trace.text ?? "")),
|
|
203
|
+
isError: trace.isError,
|
|
204
|
+
});
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
const detail =
|
|
208
|
+
trace.name === "run"
|
|
209
|
+
? String(trace.args.command ?? "")
|
|
210
|
+
: String(trace.args.path ?? trace.name);
|
|
211
|
+
events.push({
|
|
212
|
+
ts,
|
|
213
|
+
turnId,
|
|
214
|
+
botId,
|
|
215
|
+
kind: "tool",
|
|
216
|
+
summary: clip(`${trace.name} ${detail}${trace.running ? " …" : ""}`),
|
|
217
|
+
payload: cap({ name: trace.name, args: trace.args }),
|
|
218
|
+
result: String(cap(trace.text ?? "")),
|
|
219
|
+
isError: trace.isError,
|
|
220
|
+
});
|
|
221
|
+
}
|
|
222
|
+
events.push({
|
|
223
|
+
ts,
|
|
224
|
+
turnId,
|
|
225
|
+
botId,
|
|
226
|
+
kind: "assistant",
|
|
227
|
+
summary: clip(input.text),
|
|
228
|
+
result: String(cap(input.text)),
|
|
229
|
+
});
|
|
230
|
+
return events;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
export function liveTrajectoryEvents(input: {
|
|
234
|
+
botId: string;
|
|
235
|
+
thinking?: string;
|
|
236
|
+
traces?: Array<{
|
|
237
|
+
name: string;
|
|
238
|
+
args?: Record<string, unknown>;
|
|
239
|
+
text?: string;
|
|
240
|
+
isError?: boolean;
|
|
241
|
+
running?: boolean;
|
|
242
|
+
}>;
|
|
243
|
+
startedAt?: string;
|
|
244
|
+
}): TrajectoryDraft[] {
|
|
245
|
+
const traces: ToolTrace[] = (input.traces ?? []).map((tr) => ({
|
|
246
|
+
name: tr.name,
|
|
247
|
+
args: tr.args ?? {},
|
|
248
|
+
text: tr.text ?? "",
|
|
249
|
+
isError: Boolean(tr.isError),
|
|
250
|
+
running: tr.running,
|
|
251
|
+
}));
|
|
252
|
+
const events = turnTrajectoryEvents({
|
|
253
|
+
turnId: `live-${input.botId}`,
|
|
254
|
+
botId: input.botId,
|
|
255
|
+
ts: input.startedAt,
|
|
256
|
+
thinking: input.thinking,
|
|
257
|
+
traces,
|
|
258
|
+
text: "",
|
|
259
|
+
}).filter((event) => event.kind !== "assistant");
|
|
260
|
+
return events.map((event) => ({ ...event, live: true }));
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
export function synthesizeTrajectory(messages: ChatMessage[]): TrajectoryEvent[] {
|
|
264
|
+
const events: TrajectoryEvent[] = [];
|
|
265
|
+
let seq = 0;
|
|
266
|
+
for (const msg of messages) {
|
|
267
|
+
const ts = msg.createdAt;
|
|
268
|
+
const turnId = `derived-${msg.id}`;
|
|
269
|
+
if (msg.author === "you") {
|
|
270
|
+
events.push({
|
|
271
|
+
seq: seq++,
|
|
272
|
+
ts,
|
|
273
|
+
turnId,
|
|
274
|
+
kind: "user",
|
|
275
|
+
summary: clip(msg.body),
|
|
276
|
+
payload: { body: msg.body },
|
|
277
|
+
});
|
|
278
|
+
continue;
|
|
279
|
+
}
|
|
280
|
+
const parts = msg.parts?.length
|
|
281
|
+
? msg.parts
|
|
282
|
+
: [{ type: "text" as const, text: msg.body }];
|
|
283
|
+
for (const part of parts) {
|
|
284
|
+
if (part.type === "thinking") {
|
|
285
|
+
events.push({
|
|
286
|
+
seq: seq++,
|
|
287
|
+
ts,
|
|
288
|
+
turnId,
|
|
289
|
+
botId: msg.author,
|
|
290
|
+
kind: "thinking",
|
|
291
|
+
summary: clip(part.text),
|
|
292
|
+
result: part.text,
|
|
293
|
+
});
|
|
294
|
+
continue;
|
|
295
|
+
}
|
|
296
|
+
if (part.type === "skill") {
|
|
297
|
+
events.push({
|
|
298
|
+
seq: seq++,
|
|
299
|
+
ts,
|
|
300
|
+
turnId,
|
|
301
|
+
botId: msg.author,
|
|
302
|
+
kind: "skill",
|
|
303
|
+
summary: part.name,
|
|
304
|
+
payload: { name: part.name },
|
|
305
|
+
result: part.output || "",
|
|
306
|
+
});
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
if (part.type === "tool") {
|
|
310
|
+
events.push({
|
|
311
|
+
seq: seq++,
|
|
312
|
+
ts,
|
|
313
|
+
turnId,
|
|
314
|
+
botId: msg.author,
|
|
315
|
+
kind: part.name === "spawn" ? "spawn" : "tool",
|
|
316
|
+
summary: clip(
|
|
317
|
+
part.name === "spawn"
|
|
318
|
+
? part.detail || part.label || "spawn"
|
|
319
|
+
: `${part.name} ${part.detail}`,
|
|
320
|
+
),
|
|
321
|
+
payload: { name: part.name, detail: part.detail },
|
|
322
|
+
result: part.output,
|
|
323
|
+
isError: part.isError,
|
|
324
|
+
});
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
events.push({
|
|
328
|
+
seq: seq++,
|
|
329
|
+
ts,
|
|
330
|
+
turnId,
|
|
331
|
+
botId: msg.author,
|
|
332
|
+
kind: "assistant",
|
|
333
|
+
summary: clip(part.text),
|
|
334
|
+
result: part.text,
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return events;
|
|
339
|
+
}
|
package/src/usage.ts
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import type { ChatUsage } from "@guild/protocol";
|
|
2
|
+
|
|
3
|
+
export function blankUsage(): ChatUsage {
|
|
4
|
+
return {
|
|
5
|
+
input: 0,
|
|
6
|
+
output: 0,
|
|
7
|
+
cacheRead: 0,
|
|
8
|
+
cacheWrite: 0,
|
|
9
|
+
reasoning: 0,
|
|
10
|
+
totalTokens: 0,
|
|
11
|
+
costUsd: 0,
|
|
12
|
+
rounds: 0,
|
|
13
|
+
durationMs: 0,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function addUsage(acc: ChatUsage, next?: ChatUsage | null): ChatUsage {
|
|
18
|
+
if (!next) return acc;
|
|
19
|
+
acc.input = (acc.input ?? 0) + (next.input ?? 0);
|
|
20
|
+
acc.output = (acc.output ?? 0) + (next.output ?? 0);
|
|
21
|
+
acc.cacheRead = (acc.cacheRead ?? 0) + (next.cacheRead ?? 0);
|
|
22
|
+
acc.cacheWrite = (acc.cacheWrite ?? 0) + (next.cacheWrite ?? 0);
|
|
23
|
+
acc.reasoning = (acc.reasoning ?? 0) + (next.reasoning ?? 0);
|
|
24
|
+
acc.totalTokens = (acc.totalTokens ?? 0) + (next.totalTokens ?? 0);
|
|
25
|
+
acc.costUsd = (acc.costUsd ?? 0) + (next.costUsd ?? 0);
|
|
26
|
+
acc.rounds = (acc.rounds ?? 0) + (next.rounds ?? 0);
|
|
27
|
+
if (next.provider) acc.provider = next.provider;
|
|
28
|
+
if (next.model) acc.model = next.model;
|
|
29
|
+
return acc;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function fromPiUsage(usage?: {
|
|
33
|
+
input?: number;
|
|
34
|
+
output?: number;
|
|
35
|
+
cacheRead?: number;
|
|
36
|
+
cacheWrite?: number;
|
|
37
|
+
reasoning?: number;
|
|
38
|
+
totalTokens?: number;
|
|
39
|
+
cost?: { total?: number };
|
|
40
|
+
} | null): ChatUsage {
|
|
41
|
+
if (!usage) return { rounds: 1 };
|
|
42
|
+
const input = num(usage.input);
|
|
43
|
+
const output = num(usage.output);
|
|
44
|
+
const total =
|
|
45
|
+
num(usage.totalTokens) || (input || 0) + (output || 0) || undefined;
|
|
46
|
+
return {
|
|
47
|
+
input,
|
|
48
|
+
output,
|
|
49
|
+
cacheRead: num(usage.cacheRead),
|
|
50
|
+
cacheWrite: num(usage.cacheWrite),
|
|
51
|
+
reasoning: num(usage.reasoning),
|
|
52
|
+
totalTokens: total,
|
|
53
|
+
costUsd: num(usage.cost?.total),
|
|
54
|
+
rounds: 1,
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function fromOpenAiUsage(usage?: {
|
|
59
|
+
prompt_tokens?: number;
|
|
60
|
+
completion_tokens?: number;
|
|
61
|
+
total_tokens?: number;
|
|
62
|
+
prompt_tokens_details?: { cached_tokens?: number };
|
|
63
|
+
input_tokens_details?: { cached_tokens?: number };
|
|
64
|
+
} | null): ChatUsage {
|
|
65
|
+
if (!usage) return { rounds: 1 };
|
|
66
|
+
const input = num(usage.prompt_tokens);
|
|
67
|
+
const output = num(usage.completion_tokens);
|
|
68
|
+
const cacheRead =
|
|
69
|
+
num(usage.prompt_tokens_details?.cached_tokens) ??
|
|
70
|
+
num(usage.input_tokens_details?.cached_tokens);
|
|
71
|
+
return {
|
|
72
|
+
input,
|
|
73
|
+
output,
|
|
74
|
+
cacheRead,
|
|
75
|
+
totalTokens: num(usage.total_tokens) || sum(input, output),
|
|
76
|
+
rounds: 1,
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export function fromAnthropicUsage(usage?: {
|
|
81
|
+
input_tokens?: number;
|
|
82
|
+
output_tokens?: number;
|
|
83
|
+
cache_read_input_tokens?: number;
|
|
84
|
+
cache_creation_input_tokens?: number;
|
|
85
|
+
} | null): ChatUsage {
|
|
86
|
+
if (!usage) return { rounds: 1 };
|
|
87
|
+
const input = num(usage.input_tokens);
|
|
88
|
+
const output = num(usage.output_tokens);
|
|
89
|
+
return {
|
|
90
|
+
input,
|
|
91
|
+
output,
|
|
92
|
+
cacheRead: num(usage.cache_read_input_tokens),
|
|
93
|
+
cacheWrite: num(usage.cache_creation_input_tokens),
|
|
94
|
+
totalTokens: sum(input, output),
|
|
95
|
+
rounds: 1,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function withDuration(usage: ChatUsage, started: number): ChatUsage {
|
|
100
|
+
usage.durationMs = Math.max(0, Date.now() - started);
|
|
101
|
+
return usage;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function num(value: unknown): number | undefined {
|
|
105
|
+
return typeof value === "number" && Number.isFinite(value) ? value : undefined;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function sum(a?: number, b?: number): number | undefined {
|
|
109
|
+
if (a == null && b == null) return undefined;
|
|
110
|
+
return (a ?? 0) + (b ?? 0);
|
|
111
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@guild/protocol",
|
|
3
|
+
"version": "0.2.11",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"description": "Shared types for Guild (guildd).",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": "./src/index.ts"
|
|
9
|
+
},
|
|
10
|
+
"files": ["src"],
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/Jakevin/guild.git",
|
|
14
|
+
"directory": "packages/protocol"
|
|
15
|
+
},
|
|
16
|
+
"publishConfig": {
|
|
17
|
+
"access": "public"
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
export type HealthResponse = {
|
|
2
|
+
status: "ok";
|
|
3
|
+
ready: true;
|
|
4
|
+
service: "guildd";
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
export type BotStatus = "bench" | "staffed" | "running" | "retired";
|
|
8
|
+
|
|
9
|
+
export type ModelRef = { provider: string; model: string };
|
|
10
|
+
|
|
11
|
+
export type LibraryKind =
|
|
12
|
+
| "souls"
|
|
13
|
+
| "agents"
|
|
14
|
+
| "skills"
|
|
15
|
+
| "positions"
|
|
16
|
+
| "subagents";
|
|
17
|
+
|
|
18
|
+
export type LibraryItem = {
|
|
19
|
+
id: string;
|
|
20
|
+
slug: string;
|
|
21
|
+
name: string;
|
|
22
|
+
body: string;
|
|
23
|
+
description?: string;
|
|
24
|
+
tags?: string[];
|
|
25
|
+
source?: "catalog" | "user";
|
|
26
|
+
featured?: boolean;
|
|
27
|
+
createdAt: string;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type Bot = {
|
|
31
|
+
id: string;
|
|
32
|
+
handle: string;
|
|
33
|
+
name: string;
|
|
34
|
+
status: BotStatus;
|
|
35
|
+
soulId: string;
|
|
36
|
+
agentTemplateId: string;
|
|
37
|
+
skillIds: string[];
|
|
38
|
+
defaultPositionId: string;
|
|
39
|
+
oneLiner?: string;
|
|
40
|
+
/** Public /generated/… sprite. Missing → procedural tavern buddy. */
|
|
41
|
+
portrait?: string;
|
|
42
|
+
/** Chat model for this bot. Missing → guild default. */
|
|
43
|
+
model?: ModelRef | null;
|
|
44
|
+
createdAt: string;
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
/** Talent bench listing. Empty before any bots exist. */
|
|
48
|
+
export type BenchListing = Bot[];
|
|
49
|
+
|
|
50
|
+
export type RoomKind = "channel" | "dm";
|
|
51
|
+
|
|
52
|
+
export type Room = {
|
|
53
|
+
id: string;
|
|
54
|
+
kind: RoomKind;
|
|
55
|
+
name: string;
|
|
56
|
+
memberIds: string[];
|
|
57
|
+
createdAt: string;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type ChatPart =
|
|
61
|
+
| { type: "thinking"; text: string }
|
|
62
|
+
| {
|
|
63
|
+
type: "tool";
|
|
64
|
+
name: string;
|
|
65
|
+
detail: string;
|
|
66
|
+
output: string;
|
|
67
|
+
isError?: boolean;
|
|
68
|
+
/** Short UI label (DSH bash `description`). */
|
|
69
|
+
label?: string;
|
|
70
|
+
}
|
|
71
|
+
| { type: "skill"; name: string; output?: string }
|
|
72
|
+
| { type: "text"; text: string };
|
|
73
|
+
|
|
74
|
+
export type ChatAttachment = {
|
|
75
|
+
token: string;
|
|
76
|
+
title: string;
|
|
77
|
+
body: string;
|
|
78
|
+
/** Small data-URL thumbnail for hover preview. Not sent to the model. */
|
|
79
|
+
preview?: string;
|
|
80
|
+
};
|
|
81
|
+
|
|
82
|
+
/** Per-turn LLM accounting, shown in the message stats panel. */
|
|
83
|
+
export type ChatUsage = {
|
|
84
|
+
input?: number;
|
|
85
|
+
output?: number;
|
|
86
|
+
cacheRead?: number;
|
|
87
|
+
cacheWrite?: number;
|
|
88
|
+
reasoning?: number;
|
|
89
|
+
totalTokens?: number;
|
|
90
|
+
costUsd?: number;
|
|
91
|
+
rounds?: number;
|
|
92
|
+
durationMs?: number;
|
|
93
|
+
/** When this agent turn started working. */
|
|
94
|
+
startedAt?: string;
|
|
95
|
+
provider?: string;
|
|
96
|
+
model?: string;
|
|
97
|
+
estimated?: boolean;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
export type ChatMessage = {
|
|
101
|
+
id: string;
|
|
102
|
+
roomId: string;
|
|
103
|
+
author: "you" | string;
|
|
104
|
+
body: string;
|
|
105
|
+
/** DSH-style transcript rows. Missing on older messages. */
|
|
106
|
+
parts?: ChatPart[];
|
|
107
|
+
/** Parent message id when this is a reply. */
|
|
108
|
+
replyTo?: string;
|
|
109
|
+
/** Composer attachments referenced by tokens like [Image #1]. */
|
|
110
|
+
attachments?: ChatAttachment[];
|
|
111
|
+
usage?: ChatUsage;
|
|
112
|
+
createdAt: string;
|
|
113
|
+
/** When an agent turn finished. User messages omit this. */
|
|
114
|
+
finishedAt?: string;
|
|
115
|
+
/** Injected into a live turn (⌘/Ctrl+Enter), not a new user turn. */
|
|
116
|
+
steer?: boolean;
|
|
117
|
+
/** Live bot this steer was aimed at. */
|
|
118
|
+
steerBotId?: string;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
export type LlmApi =
|
|
122
|
+
| "openai-completions"
|
|
123
|
+
| "anthropic-messages"
|
|
124
|
+
| "openai-responses";
|
|
125
|
+
|
|
126
|
+
export type ModelEntry = {
|
|
127
|
+
id: string;
|
|
128
|
+
name?: string;
|
|
129
|
+
};
|
|
130
|
+
|
|
131
|
+
export type ProviderEntry = {
|
|
132
|
+
name?: string;
|
|
133
|
+
baseUrl: string;
|
|
134
|
+
api: LlmApi;
|
|
135
|
+
apiKey?: string;
|
|
136
|
+
models: ModelEntry[];
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
export type AuxRole =
|
|
140
|
+
| "vision"
|
|
141
|
+
| "web"
|
|
142
|
+
| "compression"
|
|
143
|
+
| "skills"
|
|
144
|
+
| "approval"
|
|
145
|
+
| "title"
|
|
146
|
+
| "generate"
|
|
147
|
+
| "spawn";
|
|
148
|
+
|
|
149
|
+
export type ModelsFile = {
|
|
150
|
+
default?: ModelRef | null;
|
|
151
|
+
reasoning?: "minimal" | "low" | "medium" | "high";
|
|
152
|
+
fast?: boolean;
|
|
153
|
+
aux?: Partial<Record<AuxRole, ModelRef | null>>;
|
|
154
|
+
recent?: ModelRef[];
|
|
155
|
+
providers: Record<string, ProviderEntry>;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
export const DEFAULT_GUILD_HOST = "127.0.0.1";
|
|
159
|
+
export const DEFAULT_GUILD_PORT = 7420;
|