toolroll 0.9.27 → 0.9.29
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 +28 -0
- package/dist/agentconfig.js +71 -3
- package/dist/browser/workspace.js +3 -3
- package/dist/build-review.js +3 -2
- package/dist/builder.js +10 -8
- package/dist/chat-actions.js +7 -4
- package/dist/chat-flow.js +10 -6
- package/dist/converse.js +3 -2
- package/dist/coordinator-proposals.js +2 -2
- package/dist/decision.d.ts +3 -3
- package/dist/decision.js +4 -3
- package/dist/desktop-update.d.ts +1 -1
- package/dist/evidence.js +1 -1
- package/dist/flow-actions.d.ts +1 -0
- package/dist/flow-actions.js +6 -7
- package/dist/flow-code.d.ts +3 -2
- package/dist/flow-code.js +6 -4
- package/dist/flow-draft.d.ts +10 -4
- package/dist/flow-draft.js +19 -8
- package/dist/flow-engine.d.ts +0 -3
- package/dist/flow-engine.js +17 -10
- package/dist/flow-people.d.ts +0 -1
- package/dist/flow-people.js +9 -1
- package/dist/flow-send.js +3 -2
- package/dist/flow-steps.js +33 -10
- package/dist/flows.d.ts +23 -8
- package/dist/flows.js +106 -52
- package/dist/guides.js +1 -1
- package/dist/lead-context.d.ts +3 -9
- package/dist/lead-context.js +21 -5
- package/dist/lead-status.js +17 -12
- package/dist/mate-doors.js +8 -2
- package/dist/mate-tools.js +27 -10
- package/dist/mate.js +13 -2
- package/dist/needs-you.d.ts +2 -2
- package/dist/needs-you.js +3 -0
- package/dist/operate.d.ts +3 -0
- package/dist/operate.js +144 -9
- package/dist/phase-routing.d.ts +86 -5
- package/dist/phase-routing.js +229 -17
- package/dist/process-liveness.d.ts +1 -0
- package/dist/process-liveness.js +5 -0
- package/dist/project-skills.d.ts +10 -0
- package/dist/proposal.d.ts +10 -2
- package/dist/proposal.js +25 -10
- package/dist/recipe-ui.js +2 -1
- package/dist/scout-report.d.ts +10 -4
- package/dist/scout-report.js +23 -6
- package/dist/scout.d.ts +2 -0
- package/dist/scout.js +83 -10
- package/dist/serve.js +71 -15
- package/dist/setup-guide.d.ts +2 -2
- package/dist/store.d.ts +72 -8
- package/dist/store.js +230 -29
- package/dist/task-sizing.d.ts +78 -0
- package/dist/task-sizing.js +228 -0
- package/dist/task-text.d.ts +4 -4
- package/dist/task-text.js +10 -6
- package/dist/teammate-work.js +31 -7
- package/dist/teammates.d.ts +20 -1
- package/dist/teammates.js +18 -5
- package/dist/teams-chat.d.ts +4 -1
- package/dist/teams-chat.js +17 -6
- package/dist/telegram-flow.js +6 -2
- package/dist/test-temp.js +1 -1
- package/dist/text-limits.d.ts +67 -0
- package/dist/text-limits.js +73 -0
- package/dist/tier-report.d.ts +44 -0
- package/dist/tier-report.js +71 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,33 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.9.29 — 2026-10-04
|
|
4
|
+
|
|
5
|
+
- **Tasks filed from the command line get sized too.** `task scope` now sizes
|
|
6
|
+
the task from its goal before the plan is sealed, so work the lead files
|
|
7
|
+
gets the same fast-or-strong model choice as work filed in the console.
|
|
8
|
+
- **A reused process ID no longer blocks finishing a release.** Once
|
|
9
|
+
Toolroll has recorded that a process exited, a new program taking its
|
|
10
|
+
number doesn't count as the old one. Leftover process records close when the
|
|
11
|
+
run ends, and a wait that clears by itself says so instead of asking you to
|
|
12
|
+
confirm.
|
|
13
|
+
- **Status shows each task once.** A task that is building appears only under
|
|
14
|
+
Building, an approved plan no longer reads as waiting for review, and risky
|
|
15
|
+
routes say "Risky" instead of "routine".
|
|
16
|
+
|
|
17
|
+
## 0.9.28 — 2026-10-04
|
|
18
|
+
|
|
19
|
+
- **Each task gets the right model.** When a task is filed, a fast
|
|
20
|
+
classifier on your own subscription sizes it as small, medium or large and
|
|
21
|
+
flags risky work. Small changes build on a fast model with no plan. Large or
|
|
22
|
+
risky ones get your strong models for planning and building. The choice is
|
|
23
|
+
sealed into the plan you approve, with the reason, and you can override it.
|
|
24
|
+
Where a tier has both Claude and Codex, it picks the one with more of its
|
|
25
|
+
plan left. `toolroll spend` shows what each tier took.
|
|
26
|
+
- **Nothing gets cut off.** Task goals hold 8,000 characters (up from 2,000),
|
|
27
|
+
notes 4,000 (up from 500) and flow instructions 8,000. Agents are told each
|
|
28
|
+
limit before they write and get one chance to shorten. Anything still over
|
|
29
|
+
is kept whole and linked. Chat messages split instead of cutting.
|
|
30
|
+
|
|
3
31
|
## 0.9.27 — 2026-10-04
|
|
4
32
|
|
|
5
33
|
- **Integrations show their real logos.** Every integration has its own mark
|
package/dist/agentconfig.js
CHANGED
|
@@ -234,6 +234,39 @@ export function resolveScopeChain(store, repo, ref, flags, baseAuthMode) {
|
|
|
234
234
|
}
|
|
235
235
|
const PHASE_NOUN = { plan: "planner", build: "builder", repair: "repair", review: "reviewer" };
|
|
236
236
|
export function resolveRouteCandidates(store, repo, pins = {}) {
|
|
237
|
+
// The LIGHT tier (v2): the operator's named fast builder, project over
|
|
238
|
+
// installation, never inherited and never inferred. Only the build phase
|
|
239
|
+
// has one: a small change makes no plan, and repairs resume the builder.
|
|
240
|
+
const lightOf = (phase) => {
|
|
241
|
+
const project = repo === null ? null : store.phaseTierConfig(repo, phase, "light");
|
|
242
|
+
const row = project ?? store.phaseTierConfig(INSTALLATION_SCOPE, phase, "light");
|
|
243
|
+
if (row === null)
|
|
244
|
+
return { ok: true, light: null };
|
|
245
|
+
const source = project !== null ? "project (light)" : "installation (light)";
|
|
246
|
+
if (!isProviderId(row.provider) || row.model === null || row.model === "") {
|
|
247
|
+
return { ok: false, problem: `the ${source} ${PHASE_NOUN[phase]} names ${row.provider}${row.model === null || row.model === "" ? " with no model" : ` · ${row.model}`} — a light agent is an exact pair: \`config set ${phase} --tier light --provider … --model …\`, or \`--clear\` it` };
|
|
248
|
+
}
|
|
249
|
+
const valid = validateSpec({ provider: row.provider, model: row.model });
|
|
250
|
+
if (!valid.ok)
|
|
251
|
+
return { ok: false, problem: `the ${source} ${PHASE_NOUN[phase]}: ${valid.problem}` };
|
|
252
|
+
return { ok: true, light: { provider: row.provider, model: row.model, source } };
|
|
253
|
+
};
|
|
254
|
+
// Alternates (v2): one more candidate per provider on a tier, project over installation.
|
|
255
|
+
const alternatesOf = (phase, tier) => {
|
|
256
|
+
const project = repo === null ? [] : store.phaseTierAlternates(repo, phase, tier);
|
|
257
|
+
const rows = project.length > 0 ? project : store.phaseTierAlternates(INSTALLATION_SCOPE, phase, tier);
|
|
258
|
+
const source = `${project.length > 0 ? "project" : "installation"} (${tier}, also)`;
|
|
259
|
+
const alternates = [];
|
|
260
|
+
for (const row of rows) {
|
|
261
|
+
if (!isProviderId(row.provider))
|
|
262
|
+
return { ok: false, problem: `the ${source} ${PHASE_NOUN[phase]} names unknown provider ${row.provider} — \`config clear ${phase} --also --provider ${row.provider}\`` };
|
|
263
|
+
const valid = validateSpec({ provider: row.provider, model: row.model });
|
|
264
|
+
if (!valid.ok)
|
|
265
|
+
return { ok: false, problem: `the ${source} ${PHASE_NOUN[phase]}: ${valid.problem}` };
|
|
266
|
+
alternates.push({ provider: row.provider, model: row.model, source });
|
|
267
|
+
}
|
|
268
|
+
return { ok: true, alternates };
|
|
269
|
+
};
|
|
237
270
|
const strongOf = (phase) => {
|
|
238
271
|
const strongProject = repo === null ? null : store.phaseTierConfig(repo, phase, "strong");
|
|
239
272
|
const strongInstallation = store.phaseTierConfig(INSTALLATION_SCOPE, phase, "strong");
|
|
@@ -284,7 +317,34 @@ export function resolveRouteCandidates(store, repo, pins = {}) {
|
|
|
284
317
|
return { ok: false, phase, problem: routine.problem };
|
|
285
318
|
if (!strong.ok)
|
|
286
319
|
return { ok: false, phase, problem: strong.problem };
|
|
287
|
-
|
|
320
|
+
const light = phase === "build" ? lightOf(phase) : { ok: true, light: null };
|
|
321
|
+
if (!light.ok)
|
|
322
|
+
return { ok: false, phase, problem: light.problem };
|
|
323
|
+
if (phase === "review") {
|
|
324
|
+
out.review = { routine: routine.routine, strong: strong.strong };
|
|
325
|
+
continue;
|
|
326
|
+
}
|
|
327
|
+
// A tier's candidates on other providers (`--also`), one per provider.
|
|
328
|
+
const alternates = {};
|
|
329
|
+
let primary = { light: light.light, strong: strong.strong };
|
|
330
|
+
for (const tier of (phase === "build" ? ["light", "routine", "strong"] : ["routine", "strong"])) {
|
|
331
|
+
const read = alternatesOf(phase, tier);
|
|
332
|
+
if (!read.ok)
|
|
333
|
+
return { ok: false, phase, problem: read.problem };
|
|
334
|
+
const own = tier === "routine" ? routine.routine : primary[tier];
|
|
335
|
+
// With no candidate of its own, a tier's first alternate stands as it.
|
|
336
|
+
const list = own === null ? read.alternates.slice(1) : read.alternates.filter(one => one.provider !== own.provider);
|
|
337
|
+
if (own === null && read.alternates[0] !== undefined)
|
|
338
|
+
primary = { ...primary, [tier]: read.alternates[0] };
|
|
339
|
+
if (list.length > 0)
|
|
340
|
+
alternates[tier] = list;
|
|
341
|
+
}
|
|
342
|
+
out[phase] = {
|
|
343
|
+
routine: routine.routine,
|
|
344
|
+
strong: primary.strong,
|
|
345
|
+
...(primary.light === null ? {} : { light: primary.light }),
|
|
346
|
+
...(Object.keys(alternates).length === 0 ? {} : { alternates }),
|
|
347
|
+
};
|
|
288
348
|
}
|
|
289
349
|
// Repair: the configured row is optional (inherit is the law when none
|
|
290
350
|
// exists), but a row that EXISTS must be exact — a provider the policy
|
|
@@ -364,6 +424,8 @@ export function routeOfTask(store, taskId, ref, now) {
|
|
|
364
424
|
candidates: candidates.candidates,
|
|
365
425
|
overrides,
|
|
366
426
|
pins: { plan: planPin.pin, build: buildPin.pin },
|
|
427
|
+
size: ref?.sizing ?? null,
|
|
428
|
+
headroom: store.planHeadroom(now),
|
|
367
429
|
});
|
|
368
430
|
return { kind: "route", route, source: "live" };
|
|
369
431
|
}
|
|
@@ -424,9 +486,15 @@ export function agentChoicesFor(store, repo, route) {
|
|
|
424
486
|
const buildProvider = route === null ? candidates.candidates.build.routine.provider : legOf(route, "build").provider;
|
|
425
487
|
const configuredFor = (phase) => {
|
|
426
488
|
const tiers = candidates.candidates[phase];
|
|
489
|
+
const everyOf = (one) => [
|
|
490
|
+
one.light ?? null,
|
|
491
|
+
one.routine,
|
|
492
|
+
one.strong,
|
|
493
|
+
...Object.values(one.alternates ?? {}).flatMap(list => [...(list ?? [])]),
|
|
494
|
+
];
|
|
427
495
|
const own = phase === "repair"
|
|
428
|
-
? [tiers.routine, tiers.strong, candidates.candidates.build
|
|
429
|
-
: [tiers.routine, tiers.strong];
|
|
496
|
+
? [tiers.routine, tiers.strong, ...everyOf(candidates.candidates.build)]
|
|
497
|
+
: phase === "review" ? [tiers.routine, tiers.strong] : everyOf(candidates.candidates[phase]);
|
|
430
498
|
const out = [];
|
|
431
499
|
for (const one of own) {
|
|
432
500
|
if (one === null || out.some(seen => sameSpec(seen, one)))
|