@cmgmyr/hive 1.9.1 → 1.10.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/README.md +1 -0
- package/claude-plugin/README.md +4 -0
- package/claude-plugin/crew/.claude-plugin/plugin.json +1 -0
- package/claude-plugin/crew/hooks/hooks.json +1 -0
- package/claude-plugin/crew/hooks/register.tsx +82 -0
- package/claude-plugin/crew/model.mjs +139 -0
- package/claude-plugin/crew/types/index.d.ts +18 -0
- package/dist/build-info.json +1 -1
- package/dist/cli.js +53 -21
- package/dist/crew.js +507 -0
- package/dist/dashboard.js +179 -156
- package/dist/db.js +1 -0
- package/dist/heldLabel.js +17 -0
- package/dist/leadState.js +8 -1
- package/dist/portfolio.js +8 -5
- package/dist/projectYml.js +14 -0
- package/dist/queenDashboard.js +30 -13
- package/dist/spawn.js +47 -18
- package/dist/tmux.js +9 -6
- package/dist/tools/agents.js +68 -37
- package/dist/transcript.js +135 -2
- package/package.json +1 -1
package/dist/transcript.js
CHANGED
|
@@ -35,6 +35,9 @@ function usageTokens(record) {
|
|
|
35
35
|
return tokenNumber(sum) && sum > 0 ? sum : null;
|
|
36
36
|
}
|
|
37
37
|
function tailRecords(path) {
|
|
38
|
+
return tailRead(path).records;
|
|
39
|
+
}
|
|
40
|
+
function tailRead(path) {
|
|
38
41
|
let fd;
|
|
39
42
|
try {
|
|
40
43
|
fd = openSync(path, "r");
|
|
@@ -54,10 +57,10 @@ function tailRecords(path) {
|
|
|
54
57
|
}
|
|
55
58
|
catch { }
|
|
56
59
|
}
|
|
57
|
-
return records;
|
|
60
|
+
return { records, clipped: start > 0 };
|
|
58
61
|
}
|
|
59
62
|
catch {
|
|
60
|
-
return [];
|
|
63
|
+
return { records: [], clipped: false };
|
|
61
64
|
}
|
|
62
65
|
finally {
|
|
63
66
|
if (fd !== undefined)
|
|
@@ -124,3 +127,133 @@ export function readContextTokens(cwd, sessionId, explicitPath = "") {
|
|
|
124
127
|
return null;
|
|
125
128
|
return claudeTokens(tailRecords(transcriptPath(cwd, sessionId, explicitPath)));
|
|
126
129
|
}
|
|
130
|
+
export const RECENT_TOOL_CALLS = 8;
|
|
131
|
+
export const SKILL_TOOL = "Skill";
|
|
132
|
+
export function lastComponent(name) {
|
|
133
|
+
return name.split(/__|[.:/]/).filter(Boolean).pop() ?? name;
|
|
134
|
+
}
|
|
135
|
+
function timestamp(record) {
|
|
136
|
+
return typeof record.timestamp === "string" && record.timestamp !== "" ? record.timestamp : null;
|
|
137
|
+
}
|
|
138
|
+
function reviewMarker(texts, at, skills) {
|
|
139
|
+
for (const skill of skills) {
|
|
140
|
+
const invocation = new RegExp(`^\\s*\\$${skill.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}(?![\\w-])`, "m");
|
|
141
|
+
if (texts.some((text) => typeof text === "string" && invocation.test(text))) {
|
|
142
|
+
return [{ name: SKILL_TOOL, input: { skill }, at }];
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
function claudeToolCalls(record, options) {
|
|
148
|
+
if (record.type !== "assistant")
|
|
149
|
+
return [];
|
|
150
|
+
const content = object(record.message)?.content;
|
|
151
|
+
if (!Array.isArray(content))
|
|
152
|
+
return [];
|
|
153
|
+
const at = timestamp(record);
|
|
154
|
+
const calls = [];
|
|
155
|
+
for (const part of content) {
|
|
156
|
+
const block = object(part);
|
|
157
|
+
if (!block)
|
|
158
|
+
continue;
|
|
159
|
+
if (block.type === "tool_use" && typeof block.name === "string") {
|
|
160
|
+
calls.push({ name: block.name, input: object(block.input) ?? {}, at });
|
|
161
|
+
}
|
|
162
|
+
else if (block.type === "text") {
|
|
163
|
+
calls.push(...reviewMarker([block.text], at, options.reviewSkills ?? []));
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
return calls;
|
|
167
|
+
}
|
|
168
|
+
function stringLiteral(text) {
|
|
169
|
+
const quote = text[0];
|
|
170
|
+
if (quote !== '"' && quote !== "'")
|
|
171
|
+
return null;
|
|
172
|
+
const json = quote === '"' ? text : `"${text.slice(1, -1).replace(/\\'/g, "'").replace(/(\\.)|"/g, (m, esc) => esc ?? '\\"')}"`;
|
|
173
|
+
try {
|
|
174
|
+
const value = JSON.parse(json);
|
|
175
|
+
return typeof value === "string" ? value : null;
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
function execInnerCalls(source, at) {
|
|
182
|
+
const marks = [...source.matchAll(/\btools\.([A-Za-z_]\w*)\s*\(/g)];
|
|
183
|
+
if (marks.length === 0)
|
|
184
|
+
return null;
|
|
185
|
+
const calls = [];
|
|
186
|
+
marks.forEach((mark, i) => {
|
|
187
|
+
const name = lastComponent(mark[1]);
|
|
188
|
+
if (name === "write_stdin")
|
|
189
|
+
return;
|
|
190
|
+
if (name === "exec_command") {
|
|
191
|
+
const span = source.slice(mark.index + mark[0].length, marks[i + 1]?.index ?? source.length);
|
|
192
|
+
const cmd = /["']?\bcmd["']?\s*:\s*("(?:[^"\\]|\\.)*"|'(?:[^'\\]|\\.)*')/.exec(span);
|
|
193
|
+
const command = cmd ? stringLiteral(cmd[1]) : null;
|
|
194
|
+
if (command !== null)
|
|
195
|
+
calls.push({ name: "Bash", input: { command }, at });
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
calls.push({ name, input: {}, at });
|
|
199
|
+
});
|
|
200
|
+
return calls;
|
|
201
|
+
}
|
|
202
|
+
function codexToolCalls(record, options) {
|
|
203
|
+
const payload = object(record.payload);
|
|
204
|
+
if (record.type !== "response_item" || !payload)
|
|
205
|
+
return [];
|
|
206
|
+
const at = timestamp(record);
|
|
207
|
+
if (payload.type === "message") {
|
|
208
|
+
if (payload.role !== "assistant" || !Array.isArray(payload.content))
|
|
209
|
+
return [];
|
|
210
|
+
return reviewMarker(payload.content.map((part) => object(part)?.text), at, options.reviewSkills ?? []);
|
|
211
|
+
}
|
|
212
|
+
if (typeof payload.name !== "string")
|
|
213
|
+
return [];
|
|
214
|
+
const name = lastComponent(payload.name);
|
|
215
|
+
if (payload.type === "custom_tool_call") {
|
|
216
|
+
if (name === "exec" && typeof payload.input === "string") {
|
|
217
|
+
const inner = execInnerCalls(payload.input, at);
|
|
218
|
+
if (inner)
|
|
219
|
+
return inner;
|
|
220
|
+
}
|
|
221
|
+
return [{ name, input: typeof payload.input === "string" ? { input: payload.input } : {}, at }];
|
|
222
|
+
}
|
|
223
|
+
if (payload.type !== "function_call")
|
|
224
|
+
return [];
|
|
225
|
+
if (name === "write_stdin" || name === "sleep")
|
|
226
|
+
return [];
|
|
227
|
+
let args = {};
|
|
228
|
+
if (typeof payload.arguments === "string") {
|
|
229
|
+
try {
|
|
230
|
+
args = object(JSON.parse(payload.arguments)) ?? {};
|
|
231
|
+
}
|
|
232
|
+
catch { }
|
|
233
|
+
}
|
|
234
|
+
if (name === "exec_command")
|
|
235
|
+
return typeof args.cmd === "string" ? [{ name: "Bash", input: { command: args.cmd }, at }] : [];
|
|
236
|
+
return [{ name, input: args, at }];
|
|
237
|
+
}
|
|
238
|
+
export function readRecentToolCalls(kind, worker, options = {}) {
|
|
239
|
+
const path = worker.transcript_path || (kind === "claude" && worker.session_id
|
|
240
|
+
? join(transcriptDir(worker.cwd), `${worker.session_id}.jsonl`) : "");
|
|
241
|
+
if (!path)
|
|
242
|
+
return { calls: [], truncated: false };
|
|
243
|
+
const { records, clipped } = tailRead(path);
|
|
244
|
+
const newestFirst = [];
|
|
245
|
+
let capped = false;
|
|
246
|
+
for (const record of records) {
|
|
247
|
+
const calls = (kind === "claude" ? claudeToolCalls : codexToolCalls)(record, options);
|
|
248
|
+
for (let i = calls.length - 1; i >= 0; i--) {
|
|
249
|
+
if (newestFirst.length === RECENT_TOOL_CALLS) {
|
|
250
|
+
capped = true;
|
|
251
|
+
break;
|
|
252
|
+
}
|
|
253
|
+
newestFirst.push(calls[i]);
|
|
254
|
+
}
|
|
255
|
+
if (capped)
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
return { calls: newestFirst.reverse(), truncated: clipped || capped };
|
|
259
|
+
}
|
package/package.json
CHANGED