@tablation/crew 0.29.0 → 0.30.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/cli.js +38 -10
- package/package.json +1 -1
- package/prompts/default/personas/common.md +2 -2
- package/prompts/default/personas/lane-design.md +9 -6
- package/prompts/default/personas/lane-pair.md +2 -1
- package/prompts/default/personas/lane-qa.md +1 -1
- package/prompts/dev-qa/personas/common.md +2 -2
- package/prompts/dev-qa/personas/lane-pair.md +2 -1
- package/prompts/dev-qa/personas/lane-qa.md +1 -1
package/dist/cli.js
CHANGED
|
@@ -200,11 +200,11 @@ function extractResult(line) {
|
|
|
200
200
|
return {
|
|
201
201
|
sessionId: obj.session_id,
|
|
202
202
|
numTurns: obj.num_turns,
|
|
203
|
-
|
|
203
|
+
costUsd: obj.total_cost_usd,
|
|
204
204
|
inputTokens: obj.usage?.input_tokens,
|
|
205
205
|
outputTokens: obj.usage?.output_tokens,
|
|
206
206
|
cacheReadTokens: obj.usage?.cache_read_input_tokens,
|
|
207
|
-
|
|
207
|
+
cacheWriteTokens: obj.usage?.cache_creation_input_tokens
|
|
208
208
|
};
|
|
209
209
|
}
|
|
210
210
|
|
|
@@ -376,6 +376,7 @@ var claudeAdapter = {
|
|
|
376
376
|
...spec.env
|
|
377
377
|
};
|
|
378
378
|
},
|
|
379
|
+
provider: () => "anthropic",
|
|
379
380
|
unsetEnv: BILLING_VARS_TO_UNSET,
|
|
380
381
|
mapStreamLine,
|
|
381
382
|
extractResult,
|
|
@@ -6131,6 +6132,13 @@ function renderEnvironment(i) {
|
|
|
6131
6132
|
}
|
|
6132
6133
|
|
|
6133
6134
|
// src/agent-log.ts
|
|
6135
|
+
var AgentLogHttpError = class extends Error {
|
|
6136
|
+
status;
|
|
6137
|
+
constructor(message, status2) {
|
|
6138
|
+
super(message);
|
|
6139
|
+
this.status = status2;
|
|
6140
|
+
}
|
|
6141
|
+
};
|
|
6134
6142
|
async function post(target, path, body) {
|
|
6135
6143
|
const url = `${target.baseUrl.replace(/\/+$/, "")}/api/workspaces/${target.workspaceId}${path}`;
|
|
6136
6144
|
const res = await fetch(url, {
|
|
@@ -6143,11 +6151,11 @@ async function post(target, path, body) {
|
|
|
6143
6151
|
},
|
|
6144
6152
|
body: JSON.stringify(body)
|
|
6145
6153
|
});
|
|
6146
|
-
if (!res.ok) throw new
|
|
6154
|
+
if (!res.ok) throw new AgentLogHttpError(`${path}: ${res.status} ${res.statusText}`, res.status);
|
|
6147
6155
|
return await res.json();
|
|
6148
6156
|
}
|
|
6149
6157
|
async function reportAgentRun(target, run2) {
|
|
6150
|
-
const
|
|
6158
|
+
const body = {
|
|
6151
6159
|
agentId: target.agentId,
|
|
6152
6160
|
ticketReference: run2.ticketReference,
|
|
6153
6161
|
outcome: run2.outcome,
|
|
@@ -6163,7 +6171,14 @@ async function reportAgentRun(target, run2) {
|
|
|
6163
6171
|
costUsd: run2.costUsd,
|
|
6164
6172
|
promptVersion: run2.promptVersion,
|
|
6165
6173
|
promptSha: run2.promptSha
|
|
6166
|
-
}
|
|
6174
|
+
};
|
|
6175
|
+
let entry;
|
|
6176
|
+
try {
|
|
6177
|
+
entry = await post(target, "/agents/log", { ...body, harness: run2.harness, provider: run2.provider });
|
|
6178
|
+
} catch (e) {
|
|
6179
|
+
if (!(e instanceof AgentLogHttpError) || e.status !== 400 || !run2.harness && !run2.provider) throw e;
|
|
6180
|
+
entry = await post(target, "/agents/log", body);
|
|
6181
|
+
}
|
|
6167
6182
|
for (const cycle of run2.cycles) {
|
|
6168
6183
|
await post(target, `/agents/log/${entry.id}/cycles`, {
|
|
6169
6184
|
cycleIndex: cycle.cycleIndex,
|
|
@@ -6212,6 +6227,7 @@ var TicketAttributionTracker = class {
|
|
|
6212
6227
|
// src/agent.ts
|
|
6213
6228
|
var DIGEST_MAX_AGE_SECONDS = 600;
|
|
6214
6229
|
var LEGACY_TOOLCHAIN_HARNESS = "claude";
|
|
6230
|
+
var LEGACY_TOOLCHAIN_PROVIDER = "anthropic";
|
|
6215
6231
|
function scrubbedEnv(env = process.env, harness = LEGACY_TOOLCHAIN_HARNESS) {
|
|
6216
6232
|
const out = { ...env };
|
|
6217
6233
|
for (const v of adapterFor(harness).unsetEnv) delete out[v];
|
|
@@ -6288,6 +6304,7 @@ function planAgentRun(o) {
|
|
|
6288
6304
|
args: invocation.args,
|
|
6289
6305
|
toolchain: toolchain.name,
|
|
6290
6306
|
harness: toolchain.harness,
|
|
6307
|
+
provider: adapter.provider(toolchain),
|
|
6291
6308
|
resolution: { toolchain: seat.toolchainWhy, model: seat.modelWhy },
|
|
6292
6309
|
warnings: seat.warnings,
|
|
6293
6310
|
prompt,
|
|
@@ -6440,6 +6457,11 @@ function spawnAgent(plan, emit) {
|
|
|
6440
6457
|
await Promise.all([endSink(rawSink), endSink(eventsSink)]);
|
|
6441
6458
|
if (spawnFailed) return;
|
|
6442
6459
|
const attributedTicket = attribution.winner(plan.ticket);
|
|
6460
|
+
const identity = {
|
|
6461
|
+
toolchain: plan.toolchain ?? LEGACY_TOOLCHAIN_HARNESS,
|
|
6462
|
+
harness: adapter.harness,
|
|
6463
|
+
provider: plan.provider ?? LEGACY_TOOLCHAIN_PROVIDER
|
|
6464
|
+
};
|
|
6443
6465
|
try {
|
|
6444
6466
|
writeFileSync4(`${plan.streamPath}.meta.json`, JSON.stringify({
|
|
6445
6467
|
route: plan.route,
|
|
@@ -6449,9 +6471,10 @@ function spawnAgent(plan, emit) {
|
|
|
6449
6471
|
startedAt,
|
|
6450
6472
|
exitCode: code ?? 1,
|
|
6451
6473
|
model: plan.model,
|
|
6474
|
+
...identity,
|
|
6452
6475
|
sessionId: result?.sessionId ?? null,
|
|
6453
6476
|
numTurns: result?.numTurns ?? null,
|
|
6454
|
-
totalCostUsd: result?.
|
|
6477
|
+
totalCostUsd: result?.costUsd ?? null
|
|
6455
6478
|
}));
|
|
6456
6479
|
} catch {
|
|
6457
6480
|
}
|
|
@@ -6460,9 +6483,10 @@ function spawnAgent(plan, emit) {
|
|
|
6460
6483
|
data: {
|
|
6461
6484
|
ms: ms2,
|
|
6462
6485
|
code: code ?? 1,
|
|
6486
|
+
...identity,
|
|
6463
6487
|
...result?.sessionId ? { sessionId: result.sessionId } : {},
|
|
6464
6488
|
...result?.numTurns !== void 0 ? { numTurns: result.numTurns } : {},
|
|
6465
|
-
...result?.
|
|
6489
|
+
...result?.costUsd !== void 0 ? { totalCostUsd: result.costUsd } : {}
|
|
6466
6490
|
}
|
|
6467
6491
|
});
|
|
6468
6492
|
if (plan.agentLog) {
|
|
@@ -6477,8 +6501,10 @@ function spawnAgent(plan, emit) {
|
|
|
6477
6501
|
tokensIn: result?.inputTokens,
|
|
6478
6502
|
tokensOut: result?.outputTokens,
|
|
6479
6503
|
cacheReadTokens: result?.cacheReadTokens,
|
|
6480
|
-
cacheWriteTokens: result?.
|
|
6481
|
-
costUsd: result?.
|
|
6504
|
+
cacheWriteTokens: result?.cacheWriteTokens,
|
|
6505
|
+
costUsd: result?.costUsd,
|
|
6506
|
+
harness: identity.harness,
|
|
6507
|
+
provider: identity.provider,
|
|
6482
6508
|
promptVersion: plan.promptVersion,
|
|
6483
6509
|
promptSha: plan.promptSha
|
|
6484
6510
|
});
|
|
@@ -12697,7 +12723,7 @@ ${changed2.map((c) => ` - ${c}
|
|
|
12697
12723
|
}
|
|
12698
12724
|
for (const e of entries) {
|
|
12699
12725
|
process.stdout.write(
|
|
12700
|
-
`${e.id} ${e.started_at ?? "?"} ${e.outcome ?? "?"}${e.ticket_reference ? ` ${e.ticket_reference}` : ""}${e.model ? ` ${e.model}` : ""}
|
|
12726
|
+
`${e.id} ${e.started_at ?? "?"} ${e.outcome ?? "?"}${e.ticket_reference ? ` ${e.ticket_reference}` : ""}${e.model ? ` ${e.model}` : ""}${e.harness || e.provider ? ` (${[e.harness, e.provider].filter(Boolean).join(" \xB7 ")})` : ""}
|
|
12701
12727
|
`
|
|
12702
12728
|
);
|
|
12703
12729
|
}
|
|
@@ -12713,6 +12739,8 @@ finished: ${entry.finished_at ?? "?"}
|
|
|
12713
12739
|
outcome: ${entry.outcome ?? "?"}
|
|
12714
12740
|
ticket: ${entry.ticket_reference ?? "(none)"}
|
|
12715
12741
|
model: ${entry.model ?? "?"}
|
|
12742
|
+
harness: ${entry.harness ?? "?"}
|
|
12743
|
+
provider: ${entry.provider ?? "?"}
|
|
12716
12744
|
`
|
|
12717
12745
|
);
|
|
12718
12746
|
if (flag("prompt")) {
|
package/package.json
CHANGED
|
@@ -131,7 +131,7 @@ Don't reopen it, don't re-verify it, don't merge it.
|
|
|
131
131
|
**A ticket assigned to any row the roster lists as a hold is an active
|
|
132
132
|
hold: skip it entirely, do not read its worktree, do not `cd` into it, do
|
|
133
133
|
not touch its branch.** That is a person, directly or through an
|
|
134
|
-
interactive
|
|
134
|
+
interactive session, actively iterating on it right now; assignee_id
|
|
135
135
|
is the live hand-off signal, checked *before* anything else in this step.
|
|
136
136
|
This is not the same thing as "nothing new to act on" below — an
|
|
137
137
|
actively-held ticket isn't yours to evaluate at all this run. **A held
|
|
@@ -483,7 +483,7 @@ if `report_type` is either of those.
|
|
|
483
483
|
See `CHANGELOG.md`'s own "How this file is maintained" header for the
|
|
484
484
|
full mechanics of how the release phase turns these into the entry.
|
|
485
485
|
**User-facing documentation.** If the repository's own instructions (its
|
|
486
|
-
CLAUDE.md or equivalent) name a user-facing documentation location, a
|
|
486
|
+
CLAUDE.md, AGENTS.md, GEMINI.md or equivalent) name a user-facing documentation location, a
|
|
487
487
|
change to a user-facing surface updates the relevant documentation there
|
|
488
488
|
**in the same commit as the change**. If the repository names no such
|
|
489
489
|
location, this rule is a no-op — never invent a docs location of your own.
|
|
@@ -44,10 +44,13 @@ stopping for this run, do the following instead:
|
|
|
44
44
|
- **3.4a — Design before pixels.** Work the surface out per the designer
|
|
45
45
|
brief: read the components already rendering that area, settle the
|
|
46
46
|
interaction model in words (default / empty / loading / error / narrow
|
|
47
|
-
width / keyboard path / destructive path), then make it visual.
|
|
48
|
-
`design` skill
|
|
47
|
+
width / keyboard path / destructive path), then make it visual. If your harness provides a
|
|
48
|
+
`design` skill and a canvas (Claude Code's `Skill` and `Artifact` tools),
|
|
49
|
+
load the skill for anything with real layout to settle — a new screen,
|
|
49
50
|
panel, or flow, or a redesign; skip the canvas for a single-component
|
|
50
|
-
tweak and mock it statically instead.
|
|
51
|
+
tweak and mock it statically instead. Without them (Codex, Gemini and
|
|
52
|
+
other harnesses), work in the edit profile: no canvas, mock statically
|
|
53
|
+
and rely on the PNG in 3.4b. If it genuinely helps to try an
|
|
51
54
|
interaction out in code first — a real worktree, in whatever stack this
|
|
52
55
|
repo actually uses — that's fine as a spike to inform the comp, but it is
|
|
53
56
|
scratch work: it never gets committed as the fix, and this ticket never
|
|
@@ -60,9 +63,9 @@ stopping for this run, do the following instead:
|
|
|
60
63
|
repo's own front-end stack, then upload it with the recipe under
|
|
61
64
|
"Attaching a file to a comment" in the Environment section. The PNG
|
|
62
65
|
upload is a required part of a finished design pass; a text wireframe
|
|
63
|
-
alone does not satisfy this step. If a canvas Artifact published
|
|
64
|
-
its URL in the comment body too, but never *only* the URL — the
|
|
65
|
-
|
|
66
|
+
alone does not satisfy this step. If a canvas Artifact published (only where your harness provides
|
|
67
|
+
one), include its URL in the comment body too, but never *only* the URL — the canvas
|
|
68
|
+
is optional, the PNG is not. If the upload itself fails, post the
|
|
66
69
|
HTTP status and response body in the comment rather than a sentence
|
|
67
70
|
saying uploads are impossible.
|
|
68
71
|
- **3.4c — Hand it to the operator, always, one of two ways.** Every design
|
|
@@ -20,7 +20,8 @@ interactive session editing files there does too, and it has no cycle
|
|
|
20
20
|
boundary to make the collision visible until something breaks. If you
|
|
21
21
|
already edited a tracked file directly in the primary checkout before
|
|
22
22
|
realizing this, stash it, create the worktree, and re-apply the stash there
|
|
23
|
-
— don't just leave the change on `main`. Read your own project's
|
|
23
|
+
— don't just leave the change on `main`. Read your own project's agent
|
|
24
|
+
instructions file (CLAUDE.md, AGENTS.md, GEMINI.md or equivalent)
|
|
24
25
|
and any repo-specific instructions the person has already given you in this
|
|
25
26
|
conversation; where they conflict with the general conventions below, they
|
|
26
27
|
win.
|
|
@@ -111,7 +111,7 @@ human review, so "probably fine" is not a pass.
|
|
|
111
111
|
comment. Red text in a run that exits 0 with every test passing is not a
|
|
112
112
|
failure.
|
|
113
113
|
7. **Check the documentation, when the repository names a place for it.** If
|
|
114
|
-
the repository's own instructions (its CLAUDE.md or equivalent) name a
|
|
114
|
+
the repository's own instructions (its CLAUDE.md, AGENTS.md, GEMINI.md or equivalent) name a
|
|
115
115
|
user-facing documentation location, a ticket that changes a user-facing
|
|
116
116
|
surface must come with a matching update there, in the same branch.
|
|
117
117
|
Missing or stale docs are a reason to bounce the ticket back to the dev
|
|
@@ -129,7 +129,7 @@ Don't reopen it, don't re-verify it, don't merge it.
|
|
|
129
129
|
**A ticket assigned to any row the roster lists as a hold is an active
|
|
130
130
|
hold: skip it entirely, do not read its worktree, do not `cd` into it, do
|
|
131
131
|
not touch its branch.** That is a person, directly or through an
|
|
132
|
-
interactive
|
|
132
|
+
interactive session, actively iterating on it right now; assignee_id
|
|
133
133
|
is the live hand-off signal, checked *before* anything else in this step.
|
|
134
134
|
This is not the same thing as "nothing new to act on" below — an
|
|
135
135
|
actively-held ticket isn't yours to evaluate at all this run. **A held
|
|
@@ -465,7 +465,7 @@ if `report_type` is either of those.
|
|
|
465
465
|
See `CHANGELOG.md`'s own "How this file is maintained" header for the
|
|
466
466
|
full mechanics of how the release phase turns these into the entry.
|
|
467
467
|
**User-facing documentation.** If the repository's own instructions (its
|
|
468
|
-
CLAUDE.md or equivalent) name a user-facing documentation location, a
|
|
468
|
+
CLAUDE.md, AGENTS.md, GEMINI.md or equivalent) name a user-facing documentation location, a
|
|
469
469
|
change to a user-facing surface updates the relevant documentation there
|
|
470
470
|
**in the same commit as the change**. If the repository names no such
|
|
471
471
|
location, this rule is a no-op — never invent a docs location of your own.
|
|
@@ -20,7 +20,8 @@ interactive session editing files there does too, and it has no cycle
|
|
|
20
20
|
boundary to make the collision visible until something breaks. If you
|
|
21
21
|
already edited a tracked file directly in the primary checkout before
|
|
22
22
|
realizing this, stash it, create the worktree, and re-apply the stash there
|
|
23
|
-
— don't just leave the change on `main`. Read your own project's
|
|
23
|
+
— don't just leave the change on `main`. Read your own project's agent
|
|
24
|
+
instructions file (CLAUDE.md, AGENTS.md, GEMINI.md or equivalent)
|
|
24
25
|
and any repo-specific instructions the person has already given you in this
|
|
25
26
|
conversation; where they conflict with the general conventions below, they
|
|
26
27
|
win.
|
|
@@ -98,7 +98,7 @@ human review, so "probably fine" is not a pass.
|
|
|
98
98
|
the ticket untouched; an undecided ticket at `qa` just gets re-picked
|
|
99
99
|
next cycle and re-run from scratch.
|
|
100
100
|
7. **Check the documentation, when the repository names a place for it.** If
|
|
101
|
-
the repository's own instructions (its CLAUDE.md or equivalent) name a
|
|
101
|
+
the repository's own instructions (its CLAUDE.md, AGENTS.md, GEMINI.md or equivalent) name a
|
|
102
102
|
user-facing documentation location, a ticket that changes a user-facing
|
|
103
103
|
surface must come with a matching update there, in the same branch.
|
|
104
104
|
Missing or stale docs are a reason to bounce the ticket back to the dev
|