toolroll 0.9.55 → 0.9.57
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 +18 -0
- package/README.md +24 -8
- package/dist/action-ledger.d.ts +2 -4
- package/dist/action-ledger.js +2 -10
- package/dist/approval-policy.d.ts +5 -5
- package/dist/approval-policy.js +4 -4
- package/dist/approval-rules-ui.js +2 -2
- package/dist/assignment-adapters.d.ts +5 -0
- package/dist/assignment.d.ts +24 -3
- package/dist/assignment.js +36 -10
- package/dist/browser/workspace.js +5 -5
- package/dist/browser-workspace.d.ts +12 -12
- package/dist/browser-workspace.js +1 -1
- package/dist/budget-alerts.js +3 -3
- package/dist/chat-actions.d.ts +23 -18
- package/dist/chat-actions.js +110 -88
- package/dist/chat-ask.d.ts +2 -2
- package/dist/chat-ask.js +5 -5
- package/dist/chat-channel.d.ts +15 -15
- package/dist/chat-channel.js +20 -20
- package/dist/chat-controls.d.ts +0 -4
- package/dist/chat-controls.js +0 -1
- package/dist/chat-core.js +1 -1
- package/dist/chat-delivery-state.js +2 -2
- package/dist/chat-delivery.d.ts +2 -2
- package/dist/chat-delivery.js +30 -37
- package/dist/chat-flow.js +3 -3
- package/dist/chat-messages.d.ts +1 -1
- package/dist/chat-messages.js +4 -4
- package/dist/chat-migration.d.ts +1 -1
- package/dist/chat-migration.js +11 -11
- package/dist/chat-rooms.js +3 -3
- package/dist/chat-voice.js +1 -1
- package/dist/chat-warmth.d.ts +2 -2
- package/dist/check-levels.d.ts +3 -0
- package/dist/check-levels.js +5 -0
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +6 -7
- package/dist/contracts/chat-actions.d.ts +32 -27
- package/dist/contracts/chat-actions.js +29 -11
- package/dist/contracts/chat-content.d.ts +1 -1
- package/dist/contracts/chat-content.js +1 -1
- package/dist/contracts/chat-tables.js +4 -4
- package/dist/contracts/console-api.d.ts +6 -6
- package/dist/contracts/console-api.js +7 -7
- package/dist/contracts/flow-propose.d.ts +3 -3
- package/dist/contracts/flow.d.ts +132 -125
- package/dist/contracts/flow.js +27 -12
- package/dist/contracts/lead-context.d.ts +1 -1
- package/dist/contracts/lead-context.js +2 -2
- package/dist/contracts/lead-tools.d.ts +20 -18
- package/dist/contracts/lead-tools.js +15 -15
- package/dist/contracts/stage-output.d.ts +1 -1
- package/dist/contracts/stage-output.js +1 -1
- package/dist/contracts/store-json.d.ts +23 -22
- package/dist/contracts/store-json.js +17 -17
- package/dist/contracts/{teammate-turn.d.ts → subagent-turn.d.ts} +5 -5
- package/dist/contracts/{teammate-turn.js → subagent-turn.js} +7 -7
- package/dist/converse.d.ts +23 -23
- package/dist/converse.js +28 -28
- package/dist/coordinator-proposals.d.ts +2 -2
- package/dist/coordinator-proposals.js +1 -1
- package/dist/coordinator.js +1 -1
- package/dist/deprecations.d.ts +12 -0
- package/dist/deprecations.js +20 -0
- package/dist/desktop-update-gate.js +8 -4
- package/dist/desktop-update.js +6 -1
- package/dist/discord-chat.js +6 -6
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/dispose.js +0 -5
- package/dist/envelope.js +0 -1
- package/dist/export-ui.js +1 -1
- package/dist/export.js +7 -7
- package/dist/flow-engine.d.ts +2 -2
- package/dist/flow-engine.js +21 -21
- package/dist/flow-insights.d.ts +1 -1
- package/dist/flow-share.js +13 -8
- package/dist/flow-steps.d.ts +5 -5
- package/dist/flow-steps.js +19 -19
- package/dist/flow-triggers.d.ts +1 -1
- package/dist/flow-triggers.js +1 -1
- package/dist/flows-cli.js +1 -1
- package/dist/flows-ui.js +20 -20
- package/dist/flows.js +19 -19
- package/dist/guides.js +4 -3
- package/dist/invoke.js +1 -1
- package/dist/kits-ui.js +5 -5
- package/dist/kits.d.ts +12 -12
- package/dist/kits.js +31 -31
- package/dist/{mate-cli.d.ts → lead-cli.d.ts} +11 -11
- package/dist/{mate-cli.js → lead-cli.js} +38 -38
- package/dist/lead-commitments.js +4 -4
- package/dist/lead-context.d.ts +2 -2
- package/dist/lead-context.js +9 -9
- package/dist/{mate-contract.d.ts → lead-contract.d.ts} +3 -3
- package/dist/{mate-contract.js → lead-contract.js} +7 -6
- package/dist/{mate-doors.d.ts → lead-doors.d.ts} +6 -6
- package/dist/{mate-doors.js → lead-doors.js} +24 -24
- package/dist/lead-follow.d.ts +5 -5
- package/dist/lead-follow.js +9 -9
- package/dist/lead-people.d.ts +5 -5
- package/dist/lead-people.js +14 -14
- package/dist/{mate-progress.d.ts → lead-progress.d.ts} +9 -9
- package/dist/{mate-progress.js → lead-progress.js} +3 -3
- package/dist/lead-status.d.ts +1 -1
- package/dist/lead-status.js +2 -2
- package/dist/{mate-tools.d.ts → lead-tools.d.ts} +19 -19
- package/dist/{mate-tools.js → lead-tools.js} +109 -101
- package/dist/{mate.d.ts → lead.d.ts} +27 -27
- package/dist/{mate.js → lead.js} +102 -102
- package/dist/limits-ui.d.ts +1 -1
- package/dist/limits-ui.js +1 -1
- package/dist/mcp-connect.d.ts +1 -1
- package/dist/mcp-connect.js +3 -3
- package/dist/mcp-core.js +1 -1
- package/dist/memory-pass.d.ts +2 -2
- package/dist/memory-pass.js +7 -7
- package/dist/notification-rows.d.ts +2 -2
- package/dist/operate.d.ts +3 -3
- package/dist/operate.js +52 -42
- package/dist/policy.d.ts +1 -1
- package/dist/principal.d.ts +1 -1
- package/dist/principal.js +2 -2
- package/dist/project-delete-ui.js +1 -1
- package/dist/project-delete.d.ts +1 -1
- package/dist/project-delete.js +26 -26
- package/dist/project-memory.js +1 -1
- package/dist/project-tools.d.ts +1 -1
- package/dist/project-tools.js +1 -1
- package/dist/proof.d.ts +9 -0
- package/dist/proof.js +12 -0
- package/dist/recipe-ui.js +1 -1
- package/dist/release-coverage.d.ts +16 -0
- package/dist/release-coverage.js +92 -0
- package/dist/retention.js +4 -4
- package/dist/scope.d.ts +2 -2
- package/dist/scout-report.d.ts +1 -1
- package/dist/scout-report.js +1 -1
- package/dist/serve.js +40 -45
- package/dist/server/chat.d.ts +4 -4
- package/dist/server/chat.js +105 -103
- package/dist/server/chrome.js +3 -3
- package/dist/server/flows.js +69 -62
- package/dist/server/guards.js +3 -3
- package/dist/server/http.d.ts +3 -3
- package/dist/server/http.js +1 -1
- package/dist/server/live.js +6 -6
- package/dist/server/people-tokens.js +1 -1
- package/dist/server/remote.js +12 -10
- package/dist/server/render-chat.d.ts +30 -30
- package/dist/server/render-chat.js +33 -33
- package/dist/server/render-pages.js +2 -2
- package/dist/server/render-results.d.ts +4 -1
- package/dist/server/render-results.js +23 -9
- package/dist/server/render-settings.d.ts +7 -0
- package/dist/server/render-settings.js +3 -0
- package/dist/server/route-table.js +9 -7
- package/dist/server/runtime.d.ts +13 -13
- package/dist/server/settings.js +14 -13
- package/dist/server/tasks.js +34 -30
- package/dist/setup-guide.d.ts +2 -2
- package/dist/slack-chat.d.ts +2 -2
- package/dist/slack-chat.js +6 -6
- package/dist/spend-ui.d.ts +3 -3
- package/dist/spend-ui.js +9 -9
- package/dist/spend.d.ts +14 -14
- package/dist/spend.js +31 -31
- package/dist/store-baseline.d.ts +19 -0
- package/dist/store-baseline.js +2873 -0
- package/dist/store.d.ts +200 -254
- package/dist/store.js +830 -3152
- package/dist/subagent-admin.d.ts +53 -0
- package/dist/{teammate-admin.js → subagent-admin.js} +37 -37
- package/dist/{teammate-desk.d.ts → subagent-desk.d.ts} +22 -23
- package/dist/{teammate-desk.js → subagent-desk.js} +26 -35
- package/dist/{teammate-memory.d.ts → subagent-memory.d.ts} +17 -17
- package/dist/{teammate-memory.js → subagent-memory.js} +41 -41
- package/dist/{teammate-question.d.ts → subagent-question.d.ts} +6 -6
- package/dist/{teammate-question.js → subagent-question.js} +17 -17
- package/dist/{teammate-tools.d.ts → subagent-tools.d.ts} +18 -18
- package/dist/{teammate-tools.js → subagent-tools.js} +36 -36
- package/dist/{teammate-week.d.ts → subagent-week.d.ts} +10 -10
- package/dist/{teammate-week.js → subagent-week.js} +23 -23
- package/dist/{teammate-work.d.ts → subagent-work.d.ts} +21 -21
- package/dist/{teammate-work.js → subagent-work.js} +50 -50
- package/dist/subagents-ui.d.ts +22 -0
- package/dist/{teammates-ui.js → subagents-ui.js} +45 -45
- package/dist/{teammates.d.ts → subagents.d.ts} +11 -11
- package/dist/{teammates.js → subagents.js} +21 -21
- package/dist/subscription-chat.d.ts +13 -13
- package/dist/subscription-chat.js +19 -19
- package/dist/surface.d.ts +19 -2
- package/dist/surface.js +7 -31
- package/dist/task-outcome-cli.js +3 -1
- package/dist/task-status.d.ts +59 -7
- package/dist/task-status.js +132 -16
- package/dist/team-cli.d.ts +1 -0
- package/dist/team-cli.js +14 -2
- package/dist/team-leads.js +13 -13
- package/dist/team-runtime.d.ts +2 -2
- package/dist/team-runtime.js +9 -9
- package/dist/teams-chat.js +6 -6
- package/dist/telegram-flow.d.ts +3 -3
- package/dist/telegram-flow.js +3 -3
- package/dist/{telegram-mate.d.ts → telegram-lead.d.ts} +5 -5
- package/dist/{telegram-mate.js → telegram-lead.js} +27 -27
- package/dist/telegram-status.d.ts +11 -4
- package/dist/telegram-status.js +18 -11
- package/dist/telegram-team.d.ts +1 -1
- package/dist/telegram-team.js +5 -5
- package/dist/telegram.d.ts +1 -1
- package/dist/telegram.js +13 -34
- package/dist/text-limits.d.ts +18 -18
- package/dist/text-limits.js +18 -18
- package/dist/toolroll-update.d.ts +8 -0
- package/dist/toolroll-update.js +45 -8
- package/dist/work-index.d.ts +6 -1
- package/dist/work-index.js +50 -8
- package/dist/workspace-ui.js +2 -1
- package/package.json +1 -2
- package/dist/teammate-admin.d.ts +0 -53
- package/dist/teammates-ui.d.ts +0 -21
|
@@ -1,21 +1,21 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* A
|
|
2
|
+
* A subagent's turn (subagents.ts): one schema for the JSON Schema Claude answers in (`--json-schema`) and the reader
|
|
3
3
|
* that takes the answer back. One flat object with every field (a root union is refused by the API); fields a turn
|
|
4
4
|
* does not use are "" (or [] for options).
|
|
5
5
|
*
|
|
6
6
|
* The text limits (TURN_LIMITS, from TEXT_LIMITS) are deliberately not in the schema: the CLI refuses an answer a few
|
|
7
7
|
* characters over one whole, so they are checked after parsing and an answer over one is asked once to shorten
|
|
8
|
-
* (
|
|
8
|
+
* (subagent-work.ts), then kept whole. What the zone allows — which actions, which answers, a note for a send-back, a
|
|
9
9
|
* question for an ask, a tool for a tool call — is checked after parsing too (`readTurn`), by path.
|
|
10
10
|
*
|
|
11
11
|
* A turn is kept as the step's decision (`flow_step_run.decision_json`) as it was read, so a saved one is this shape.
|
|
12
12
|
*/
|
|
13
13
|
import { z } from "zod";
|
|
14
14
|
import { parseContract, toModelSchema } from "./contract.js";
|
|
15
|
-
/** What a
|
|
15
|
+
/** What a subagent may do on one turn. A decision zone: approve, send back, or hand it to a person. A work zone: pick
|
|
16
16
|
* where it goes, ask its person, or say it can't. v94: "use_tool" asks for one tool call. */
|
|
17
17
|
export const TURN_ACTIONS = ["approve", "send_back", "hand_off", "route", "ask", "cant", "use_tool"];
|
|
18
|
-
export const
|
|
18
|
+
export const subagentTurnSchema = z.object({
|
|
19
19
|
action: z.enum(TURN_ACTIONS),
|
|
20
20
|
/** route: one of the zone's answers, exactly as written. */
|
|
21
21
|
answer: z.string(),
|
|
@@ -35,17 +35,17 @@ export const teammateTurnSchema = z.object({
|
|
|
35
35
|
remember: z.string(),
|
|
36
36
|
});
|
|
37
37
|
/** What Claude's `--json-schema` is for a turn: the turn schema, exactly. */
|
|
38
|
-
export const TURN_MODEL_SCHEMA = toModelSchema(
|
|
38
|
+
export const TURN_MODEL_SCHEMA = toModelSchema(subagentTurnSchema);
|
|
39
39
|
/** Older and plain-text turns default absent or non-text fields to "", and keep only string options. */
|
|
40
40
|
export function readTurnAnswer(value) {
|
|
41
41
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
42
42
|
const body = { ...value };
|
|
43
|
-
for (const key of Object.keys(
|
|
43
|
+
for (const key of Object.keys(subagentTurnSchema.shape)) {
|
|
44
44
|
if (key !== "action" && key !== "options" && typeof body[key] !== "string")
|
|
45
45
|
body[key] = "";
|
|
46
46
|
}
|
|
47
47
|
body["options"] = Array.isArray(body["options"]) ? body["options"].filter(one => typeof one === "string") : [];
|
|
48
48
|
value = body;
|
|
49
49
|
}
|
|
50
|
-
return parseContract(
|
|
50
|
+
return parseContract(subagentTurnSchema, value);
|
|
51
51
|
}
|
package/dist/converse.d.ts
CHANGED
|
@@ -142,15 +142,15 @@ export type ProviderAnswer = {
|
|
|
142
142
|
* ruling 14): a negative, fractional, or absurd usage is a malformed reply,
|
|
143
143
|
* never a discount on the pinned settlement. */
|
|
144
144
|
export declare function tokenCount(value: number): boolean;
|
|
145
|
-
export declare const
|
|
146
|
-
export declare const
|
|
145
|
+
export declare const LEAD_MAX_STEPS = 8;
|
|
146
|
+
export declare const LEAD_MAX_CALLS_PER_STEP = 4;
|
|
147
147
|
/** A tool result, measured AS EMBEDDED — the JSON-encoded string, escapes included. */
|
|
148
|
-
export declare const
|
|
148
|
+
export declare const LEAD_TOOL_RESULT_CAP_BYTES = 16384;
|
|
149
149
|
/** A tool call, measured as the serialized `{id, name, args}` — the id counts. */
|
|
150
|
-
export declare const
|
|
151
|
-
export declare const
|
|
150
|
+
export declare const LEAD_TOOL_CALL_CAP_BYTES = 2048;
|
|
151
|
+
export declare const LEAD_TOOL_CALL_ID_CAP_BYTES = 64;
|
|
152
152
|
/** One step's assistant text; over it the reply is malformed (review finding 7). */
|
|
153
|
-
export declare const
|
|
153
|
+
export declare const LEAD_STEP_TEXT_CAP_BYTES = 8192;
|
|
154
154
|
/**
|
|
155
155
|
* The triangular worst case (mate arc, ruling 6; slice-1 review finding 7):
|
|
156
156
|
* request s carries the base prompt plus every earlier step's calls,
|
|
@@ -160,7 +160,7 @@ export declare const MATE_STEP_TEXT_CAP_BYTES = 8192;
|
|
|
160
160
|
* body), so each is budgeted at twice its cap — escaping at most doubles
|
|
161
161
|
* a string. Each step may answer with the full output allowance.
|
|
162
162
|
*/
|
|
163
|
-
export declare function
|
|
163
|
+
export declare function leadWorstCaseForPrice(price: ModelPrice, baseBytes: number, caps?: {
|
|
164
164
|
steps?: number;
|
|
165
165
|
callsPerStep?: number;
|
|
166
166
|
resultCap?: number;
|
|
@@ -169,32 +169,32 @@ export declare function mateWorstCaseForPrice(price: ModelPrice, baseBytes: numb
|
|
|
169
169
|
}): number;
|
|
170
170
|
/** The bytes a tool result costs on the wire: its JSON string form. */
|
|
171
171
|
export declare function embeddedBytes(text: string): number;
|
|
172
|
-
export type
|
|
172
|
+
export type LeadToolSchema = {
|
|
173
173
|
name: string;
|
|
174
174
|
description: string;
|
|
175
175
|
inputSchema: Record<string, unknown>;
|
|
176
176
|
};
|
|
177
|
-
export type
|
|
177
|
+
export type LeadToolCall = {
|
|
178
178
|
id: string;
|
|
179
179
|
name: string;
|
|
180
180
|
args: Record<string, unknown>;
|
|
181
181
|
};
|
|
182
182
|
/** A provider answer with tool calls allowed: text, calls, usage. */
|
|
183
|
-
export type
|
|
183
|
+
export type LeadProviderAnswer = {
|
|
184
184
|
text: string;
|
|
185
|
-
calls:
|
|
185
|
+
calls: LeadToolCall[];
|
|
186
186
|
tokensIn: number;
|
|
187
187
|
tokensOut: number;
|
|
188
188
|
reportedCostMicrousd: number | null;
|
|
189
189
|
};
|
|
190
|
-
/** One message of the
|
|
191
|
-
export type
|
|
190
|
+
/** One message of the lead's own history, provider-neutral. */
|
|
191
|
+
export type LeadHistoryMessage = {
|
|
192
192
|
role: "operator";
|
|
193
193
|
text: string;
|
|
194
194
|
} | {
|
|
195
195
|
role: "assistant";
|
|
196
196
|
text: string;
|
|
197
|
-
calls:
|
|
197
|
+
calls: LeadToolCall[];
|
|
198
198
|
} | {
|
|
199
199
|
role: "tool";
|
|
200
200
|
callId: string;
|
|
@@ -207,36 +207,36 @@ export type MateHistoryMessage = {
|
|
|
207
207
|
* most M per answer, each argument object under the call cap), and
|
|
208
208
|
* anything else about the shape is malformed.
|
|
209
209
|
*/
|
|
210
|
-
export declare function
|
|
210
|
+
export declare function parseLeadProviderWrapper(provider: DirectChatProviderId, bytes: Buffer): {
|
|
211
211
|
ok: true;
|
|
212
|
-
answer:
|
|
212
|
+
answer: LeadProviderAnswer;
|
|
213
213
|
} | {
|
|
214
214
|
ok: false;
|
|
215
215
|
problem: string;
|
|
216
216
|
};
|
|
217
|
-
/** The
|
|
217
|
+
/** The lead's request: system contract, the data document as the first
|
|
218
218
|
* operator message, the history in provider-native shape, the tools. */
|
|
219
|
-
export declare function
|
|
219
|
+
export declare function composeLeadRequest(args: {
|
|
220
220
|
provider: DirectChatProviderId;
|
|
221
221
|
model: string;
|
|
222
222
|
key: string;
|
|
223
223
|
system: string;
|
|
224
224
|
dataDocument: string;
|
|
225
|
-
history: readonly
|
|
226
|
-
tools: readonly
|
|
225
|
+
history: readonly LeadHistoryMessage[];
|
|
226
|
+
tools: readonly LeadToolSchema[];
|
|
227
227
|
}): {
|
|
228
228
|
url: string;
|
|
229
229
|
headers: Record<string, string>;
|
|
230
230
|
body: string;
|
|
231
231
|
};
|
|
232
|
-
/** The
|
|
233
|
-
export declare function
|
|
232
|
+
/** The lead's network call: the same transport posture as fleet chat's, the tool-capable parser at the end. */
|
|
233
|
+
export declare function performLeadRequest(request: {
|
|
234
234
|
url: string;
|
|
235
235
|
headers: Record<string, string>;
|
|
236
236
|
body: string;
|
|
237
237
|
}, provider: DirectChatProviderId, signal: AbortSignal, fetcher?: typeof fetch): Promise<{
|
|
238
238
|
ok: true;
|
|
239
|
-
answer:
|
|
239
|
+
answer: LeadProviderAnswer;
|
|
240
240
|
} | {
|
|
241
241
|
ok: false;
|
|
242
242
|
problem: string;
|
package/dist/converse.js
CHANGED
|
@@ -357,16 +357,16 @@ export function parseAssistantEnvelope(text) {
|
|
|
357
357
|
export function tokenCount(value) {
|
|
358
358
|
return Number.isSafeInteger(value) && value >= 0 && value <= 1_000_000_000;
|
|
359
359
|
}
|
|
360
|
-
// ---------------------------------------------------------------- the
|
|
361
|
-
export const
|
|
362
|
-
export const
|
|
360
|
+
// ---------------------------------------------------------------- the lead
|
|
361
|
+
export const LEAD_MAX_STEPS = 8;
|
|
362
|
+
export const LEAD_MAX_CALLS_PER_STEP = 4;
|
|
363
363
|
/** A tool result, measured AS EMBEDDED — the JSON-encoded string, escapes included. */
|
|
364
|
-
export const
|
|
364
|
+
export const LEAD_TOOL_RESULT_CAP_BYTES = 16_384;
|
|
365
365
|
/** A tool call, measured as the serialized `{id, name, args}` — the id counts. */
|
|
366
|
-
export const
|
|
367
|
-
export const
|
|
366
|
+
export const LEAD_TOOL_CALL_CAP_BYTES = 2_048;
|
|
367
|
+
export const LEAD_TOOL_CALL_ID_CAP_BYTES = 64;
|
|
368
368
|
/** One step's assistant text; over it the reply is malformed (review finding 7). */
|
|
369
|
-
export const
|
|
369
|
+
export const LEAD_STEP_TEXT_CAP_BYTES = 8_192;
|
|
370
370
|
/**
|
|
371
371
|
* The triangular worst case (mate arc, ruling 6; slice-1 review finding 7):
|
|
372
372
|
* request s carries the base prompt plus every earlier step's calls,
|
|
@@ -376,12 +376,12 @@ export const MATE_STEP_TEXT_CAP_BYTES = 8_192;
|
|
|
376
376
|
* body), so each is budgeted at twice its cap — escaping at most doubles
|
|
377
377
|
* a string. Each step may answer with the full output allowance.
|
|
378
378
|
*/
|
|
379
|
-
export function
|
|
380
|
-
const S = caps.steps ??
|
|
381
|
-
const M = caps.callsPerStep ??
|
|
382
|
-
const R = caps.resultCap ??
|
|
383
|
-
const C = caps.callCap ??
|
|
384
|
-
const T = caps.textCap ??
|
|
379
|
+
export function leadWorstCaseForPrice(price, baseBytes, caps = {}) {
|
|
380
|
+
const S = caps.steps ?? LEAD_MAX_STEPS;
|
|
381
|
+
const M = caps.callsPerStep ?? LEAD_MAX_CALLS_PER_STEP;
|
|
382
|
+
const R = caps.resultCap ?? LEAD_TOOL_RESULT_CAP_BYTES;
|
|
383
|
+
const C = caps.callCap ?? LEAD_TOOL_CALL_CAP_BYTES;
|
|
384
|
+
const T = caps.textCap ?? LEAD_STEP_TEXT_CAP_BYTES;
|
|
385
385
|
const tokens = (bytes) => Math.ceil(bytes / 3);
|
|
386
386
|
let input = 0;
|
|
387
387
|
for (let s = 1; s <= S; s++) {
|
|
@@ -399,7 +399,7 @@ export function embeddedBytes(text) {
|
|
|
399
399
|
* most M per answer, each argument object under the call cap), and
|
|
400
400
|
* anything else about the shape is malformed.
|
|
401
401
|
*/
|
|
402
|
-
export function
|
|
402
|
+
export function parseLeadProviderWrapper(provider, bytes) {
|
|
403
403
|
const parsed = strictJsonParse(bytes, WRAPPER_CAP_BYTES, 14);
|
|
404
404
|
if (!parsed.ok)
|
|
405
405
|
return { ok: false, problem: parsed.problem };
|
|
@@ -408,9 +408,9 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
408
408
|
return { ok: false, problem: "not-an-object" };
|
|
409
409
|
const readArgs = (raw) => {
|
|
410
410
|
const text = typeof raw === "string" ? raw : JSON.stringify(raw ?? null);
|
|
411
|
-
if (Buffer.byteLength(text, "utf8") >
|
|
411
|
+
if (Buffer.byteLength(text, "utf8") > LEAD_TOOL_CALL_CAP_BYTES)
|
|
412
412
|
return null;
|
|
413
|
-
const inner = strictJsonParse(Buffer.from(text, "utf8"),
|
|
413
|
+
const inner = strictJsonParse(Buffer.from(text, "utf8"), LEAD_TOOL_CALL_CAP_BYTES, 6);
|
|
414
414
|
if (!inner.ok || typeof inner.value !== "object" || inner.value === null || Array.isArray(inner.value))
|
|
415
415
|
return null;
|
|
416
416
|
return inner.value;
|
|
@@ -418,7 +418,7 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
418
418
|
// A call is bounded WHOLE (finding 7): the id is repeated in the assistant
|
|
419
419
|
// block and the result, so it is capped and counted inside the call cap.
|
|
420
420
|
const readCall = (id, name, rawArgs) => {
|
|
421
|
-
if (typeof id !== "string" || id === "" || Buffer.byteLength(id, "utf8") >
|
|
421
|
+
if (typeof id !== "string" || id === "" || Buffer.byteLength(id, "utf8") > LEAD_TOOL_CALL_ID_CAP_BYTES)
|
|
422
422
|
return null;
|
|
423
423
|
if (typeof name !== "string" || name === "" || name.length > 64)
|
|
424
424
|
return null;
|
|
@@ -426,7 +426,7 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
426
426
|
if (args === null)
|
|
427
427
|
return null;
|
|
428
428
|
const call = { id, name, args };
|
|
429
|
-
if (Buffer.byteLength(JSON.stringify(call), "utf8") >
|
|
429
|
+
if (Buffer.byteLength(JSON.stringify(call), "utf8") > LEAD_TOOL_CALL_CAP_BYTES)
|
|
430
430
|
return null;
|
|
431
431
|
return call;
|
|
432
432
|
};
|
|
@@ -447,7 +447,7 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
447
447
|
if (body["type"] !== "message")
|
|
448
448
|
return { ok: false, problem: "wrong-type" };
|
|
449
449
|
const content = body["content"];
|
|
450
|
-
if (!Array.isArray(content) || content.length === 0 || content.length >
|
|
450
|
+
if (!Array.isArray(content) || content.length === 0 || content.length > LEAD_MAX_CALLS_PER_STEP + 1)
|
|
451
451
|
return { ok: false, problem: "bad-content" };
|
|
452
452
|
let text = "";
|
|
453
453
|
const calls = [];
|
|
@@ -468,9 +468,9 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
468
468
|
return { ok: false, problem: "bad-block" };
|
|
469
469
|
}
|
|
470
470
|
}
|
|
471
|
-
if (calls.length >
|
|
471
|
+
if (calls.length > LEAD_MAX_CALLS_PER_STEP)
|
|
472
472
|
return { ok: false, problem: "too-many-calls" };
|
|
473
|
-
if (Buffer.byteLength(text, "utf8") >
|
|
473
|
+
if (Buffer.byteLength(text, "utf8") > LEAD_STEP_TEXT_CAP_BYTES)
|
|
474
474
|
return { ok: false, problem: "text-over-cap" };
|
|
475
475
|
const usage = usageOf(body["usage"], "input_tokens", "output_tokens");
|
|
476
476
|
if (usage === null)
|
|
@@ -490,7 +490,7 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
490
490
|
const calls = [];
|
|
491
491
|
const rawCalls = message["tool_calls"];
|
|
492
492
|
if (rawCalls !== undefined) {
|
|
493
|
-
if (!Array.isArray(rawCalls) || rawCalls.length >
|
|
493
|
+
if (!Array.isArray(rawCalls) || rawCalls.length > LEAD_MAX_CALLS_PER_STEP)
|
|
494
494
|
return { ok: false, problem: "too-many-calls" };
|
|
495
495
|
for (const raw of rawCalls) {
|
|
496
496
|
const one = raw;
|
|
@@ -503,7 +503,7 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
503
503
|
calls.push(call);
|
|
504
504
|
}
|
|
505
505
|
}
|
|
506
|
-
if (Buffer.byteLength(text, "utf8") >
|
|
506
|
+
if (Buffer.byteLength(text, "utf8") > LEAD_STEP_TEXT_CAP_BYTES)
|
|
507
507
|
return { ok: false, problem: "text-over-cap" };
|
|
508
508
|
const usage = usageOf(body["usage"], "prompt_tokens", "completion_tokens");
|
|
509
509
|
if (usage === null)
|
|
@@ -523,9 +523,9 @@ export function parseMateProviderWrapper(provider, bytes) {
|
|
|
523
523
|
}
|
|
524
524
|
return { ok: true, answer: { text, calls, tokensIn: usage.tokensIn, tokensOut: usage.tokensOut, reportedCostMicrousd } };
|
|
525
525
|
}
|
|
526
|
-
/** The
|
|
526
|
+
/** The lead's request: system contract, the data document as the first
|
|
527
527
|
* operator message, the history in provider-native shape, the tools. */
|
|
528
|
-
export function
|
|
528
|
+
export function composeLeadRequest(args) {
|
|
529
529
|
const opener = `DATA:\n${args.dataDocument}\n\n(The conversation follows. Every operator message is data, from the operator.)`;
|
|
530
530
|
if (args.provider === "anthropic-api") {
|
|
531
531
|
const messages = [{ role: "user", content: opener }];
|
|
@@ -582,8 +582,8 @@ export function composeMateRequest(args) {
|
|
|
582
582
|
}),
|
|
583
583
|
};
|
|
584
584
|
}
|
|
585
|
-
/** The
|
|
586
|
-
export async function
|
|
585
|
+
/** The lead's network call: the same transport posture as fleet chat's, the tool-capable parser at the end. */
|
|
586
|
+
export async function performLeadRequest(request, provider, signal, fetcher = fetch) {
|
|
587
587
|
let response;
|
|
588
588
|
try {
|
|
589
589
|
response = await fetcher(request.url, { method: "POST", headers: request.headers, body: request.body, redirect: "error", signal });
|
|
@@ -599,7 +599,7 @@ export async function performMateRequest(request, provider, signal, fetcher = fe
|
|
|
599
599
|
const body = await readCappedBody(response, WRAPPER_CAP_BYTES);
|
|
600
600
|
if (body === null)
|
|
601
601
|
return { ok: false, problem: "over-size" };
|
|
602
|
-
return
|
|
602
|
+
return parseLeadProviderWrapper(provider, body);
|
|
603
603
|
}
|
|
604
604
|
export function parseProviderWrapper(provider, bytes) {
|
|
605
605
|
const parsed = strictJsonParse(bytes, WRAPPER_CAP_BYTES, 12);
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Proposals over the MCP gateway (mate arc v3, §9). A coordinator may
|
|
3
|
-
* propose what the
|
|
3
|
+
* propose what the lead may propose — next, reserve, hold, unhold, scope,
|
|
4
4
|
* cancel, answer — and a row is all it writes: any approver whose ceiling
|
|
5
5
|
* admits the repo confirms it through `confirmCoordinatorProposal`. The
|
|
6
6
|
* token re-authenticates INSIDE the transaction (the session's `who` is a
|
|
7
7
|
* courtesy, exactly as for filing); the proposal counts against the
|
|
8
8
|
* credential's hourly filing rate and a per-credential pending cap; the
|
|
9
|
-
* payload carries the same CAS material the
|
|
9
|
+
* payload carries the same CAS material the lead's does, so a stale row
|
|
10
10
|
* refuses at the door in the same words.
|
|
11
11
|
*/
|
|
12
12
|
import type { CoordinatorProposalKind, Store } from "./store.js";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { TASK_TEXT_LIMITS, validateScopeText } from "./task-text.js";
|
|
2
2
|
import { authenticateCoordinator } from "./coordinator.js";
|
|
3
|
-
import { decisionOver, honestText, readTouches, readAcceptanceArg } from "./
|
|
3
|
+
import { decisionOver, honestText, readTouches, readAcceptanceArg } from "./lead-tools.js";
|
|
4
4
|
export const PER_CID_PENDING_PROPOSALS = 20;
|
|
5
5
|
const TASK_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
6
6
|
/** The coordinator's proposal as a row; the shape of `args` is the MCP tool's. */
|
package/dist/coordinator.js
CHANGED
|
@@ -18,7 +18,7 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
18
18
|
import { canonicalRepos } from "./runner.js";
|
|
19
19
|
import { fileTaskProposal } from "./proposal.js";
|
|
20
20
|
import { describeScope } from "./scope.js";
|
|
21
|
-
import { reportSummaryFor } from "./
|
|
21
|
+
import { reportSummaryFor } from "./lead-tools.js";
|
|
22
22
|
import { taskWorkSummaryOf } from "./work-summary.js";
|
|
23
23
|
import { assignmentOf, assignmentBrief } from "./assignment.js";
|
|
24
24
|
/** Module-private: the ONLY maker, reachable only through the token
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
|
|
3
|
+
* member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
|
|
4
|
+
* coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
|
|
5
|
+
* hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
|
|
6
|
+
* `--json` answer stays one envelope. Their code goes in the next minor release.
|
|
7
|
+
*/
|
|
8
|
+
export type Deprecated = "team" | "session";
|
|
9
|
+
/** The one line a deprecated command prints on stderr: what it is, when it goes, and what to use instead. */
|
|
10
|
+
export declare function deprecationWarning(command: string, kind: Deprecated): string;
|
|
11
|
+
/** What a deprecated console page or API says about itself. */
|
|
12
|
+
export declare const DEPRECATED_PAGE: Record<Deprecated, string>;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* D5 (schema v117): one AI concept, the lead. The central team service (`connect`, the central `lead list|create|update|
|
|
3
|
+
* member|transfer`, `conversation …`, and `chat`/`brief` with --lead, --conversation or a saved profile) and native
|
|
4
|
+
* coding sessions (`session …`) are deprecated. For this release they still work exactly as before, but they are
|
|
5
|
+
* hidden from help, the command contract and the console, and each run says so once on stderr — never on stdout, so a
|
|
6
|
+
* `--json` answer stays one envelope. Their code goes in the next minor release.
|
|
7
|
+
*/
|
|
8
|
+
const NEXT_STEP = {
|
|
9
|
+
team: "Talk to your lead with `toolroll chat`.",
|
|
10
|
+
session: "Queue work with `toolroll task add`.",
|
|
11
|
+
};
|
|
12
|
+
/** The one line a deprecated command prints on stderr: what it is, when it goes, and what to use instead. */
|
|
13
|
+
export function deprecationWarning(command, kind) {
|
|
14
|
+
return `Warning: \`toolroll ${command}\` is deprecated and will be removed in the next minor release. ${NEXT_STEP[kind]}`;
|
|
15
|
+
}
|
|
16
|
+
/** What a deprecated console page or API says about itself. */
|
|
17
|
+
export const DEPRECATED_PAGE = {
|
|
18
|
+
team: "Team chat is deprecated and will be removed in the next minor release. Your lead in Chat does the same work.",
|
|
19
|
+
session: "Coding sessions are deprecated and will be removed in the next minor release. Queue work as a task instead.",
|
|
20
|
+
};
|
|
@@ -9,10 +9,14 @@ const statements = (id, frozen = false) => {
|
|
|
9
9
|
`CREATE TRIGGER ${prefix}claim BEFORE INSERT ON claim BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
10
10
|
`CREATE TRIGGER ${prefix}mate BEFORE INSERT ON mate_turn BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
11
11
|
`CREATE TRIGGER ${prefix}run BEFORE INSERT ON run ${frozen ? "" : "WHEN NEW.parent_run IS NULL AND NOT EXISTS (SELECT 1 FROM claim WHERE lease_id=NEW.lease_id AND released_at IS NULL) "}BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
12
|
-
// An already-owned
|
|
12
|
+
// An already-owned lead turn may finish its remaining provider steps.
|
|
13
13
|
`CREATE TRIGGER ${prefix}chat BEFORE INSERT ON chat_turn ${frozen ? "" : "WHEN NEW.mate_turn IS NULL "}BEGIN SELECT RAISE(ABORT, '${UPDATE_PAUSED} [${id}]'); END`,
|
|
14
14
|
];
|
|
15
15
|
};
|
|
16
|
+
/** A gate statement as SQLite may keep it: a table RENAME re-quotes names, and a later build may name the lead's turns
|
|
17
|
+
* lead_turn (D5). This build's updater lifts a gate it made under either name. */
|
|
18
|
+
const same = (sql) => sql.replace(/"([A-Za-z_][A-Za-z0-9_]*)"/g, "$1").replace(/\b(?:mate|lead)_turn\b/g, "mate_turn");
|
|
19
|
+
const owns = (wanted, sql) => wanted.map(same).includes(same(String(sql)));
|
|
16
20
|
/** SQLite enforces the gate even for a CLI racing an old in-memory snapshot.
|
|
17
21
|
* Existing leases, replies, heartbeats and task data remain writable. */
|
|
18
22
|
export function installUpdateGate(db, id) {
|
|
@@ -20,7 +24,7 @@ export function installUpdateGate(db, id) {
|
|
|
20
24
|
db.exec("BEGIN IMMEDIATE");
|
|
21
25
|
try {
|
|
22
26
|
const existing = rows(db);
|
|
23
|
-
if (existing.length > 0 && (existing.length !== wanted.length || existing.some(row => ![...wanted, ...statements(id, true)]
|
|
27
|
+
if (existing.length > 0 && (existing.length !== wanted.length || existing.some(row => !owns([...wanted, ...statements(id, true)], row.sql))))
|
|
24
28
|
throw Error("Another or unrecognized update owns admission. Recover that update first.");
|
|
25
29
|
if (existing.length === 0)
|
|
26
30
|
for (const statement of wanted)
|
|
@@ -38,7 +42,7 @@ export function removeUpdateGate(db, id) {
|
|
|
38
42
|
db.exec("BEGIN IMMEDIATE");
|
|
39
43
|
try {
|
|
40
44
|
const existing = rows(db);
|
|
41
|
-
if (existing.some(row => !wanted
|
|
45
|
+
if (existing.some(row => !owns(wanted, row.sql)))
|
|
42
46
|
throw Error("This update does not own the admission pause. Nothing was cleared.");
|
|
43
47
|
removeCodingUpdateGate(db, id);
|
|
44
48
|
for (const row of existing)
|
|
@@ -53,7 +57,7 @@ export function removeUpdateGate(db, id) {
|
|
|
53
57
|
export function updateAdmissionPaused(db) { return rows(db).length > 0; }
|
|
54
58
|
export function updateGateOwned(db, id) {
|
|
55
59
|
const wanted = [...statements(id), ...statements(id, true)], existing = rows(db);
|
|
56
|
-
return existing.length === statements(id).length && existing.every(row => wanted
|
|
60
|
+
return existing.length === statements(id).length && existing.every(row => owns(wanted, row.sql));
|
|
57
61
|
}
|
|
58
62
|
export function activeUpdateWork(db) {
|
|
59
63
|
const count = (sql) => Number(db.prepare(sql).get()?.n ?? 0);
|
package/dist/desktop-update.js
CHANGED
|
@@ -8,6 +8,7 @@ import { readDesktopConfig, desktopServiceCommand, desktopServiceDefinition, ver
|
|
|
8
8
|
import { daemonStatus } from "./daemon.js";
|
|
9
9
|
import { run } from "./exec.js";
|
|
10
10
|
import { readSchemaVersion, SCHEMA_VERSION, Store } from "./store.js";
|
|
11
|
+
import { BASELINE_SCHEMA_VERSION } from "./store-baseline.js";
|
|
11
12
|
import { activeUpdateWork, freezeUpdateGate, installUpdateGate, removeUpdateGate, updateAdmissionPaused } from "./desktop-update-gate.js";
|
|
12
13
|
import { currentDesktopAccess } from "./desktop-access.js";
|
|
13
14
|
import { assertCodingUpdateStopped, backupCodingCatalog, codingCatalogExists, releaseStaleCodingOwner } from "./coding-update.js";
|
|
@@ -125,6 +126,8 @@ function connect(file, readOnly = false, accepts = currentSchemaOnly) {
|
|
|
125
126
|
const schema = readSchemaVersion(db);
|
|
126
127
|
if (!schema.ok || !accepts(schema.version)) {
|
|
127
128
|
db.close();
|
|
129
|
+
if (schema.ok && schema.version !== null && Math.abs(schema.version) < BASELINE_SCHEMA_VERSION)
|
|
130
|
+
throw Error(`This database is schema v${Math.abs(schema.version)}, older than v${BASELINE_SCHEMA_VERSION}: update through 0.9.x first (Toolroll 0.9.54 brings it up to date). The installed app is unchanged.`);
|
|
128
131
|
throw Error("This update needs the current database schema. Use the separate verified migration procedure; the installed app is unchanged.");
|
|
129
132
|
}
|
|
130
133
|
return db;
|
|
@@ -474,7 +477,9 @@ function assertConfig(j) {
|
|
|
474
477
|
}
|
|
475
478
|
function snapshot(db) {
|
|
476
479
|
const result = {};
|
|
477
|
-
|
|
480
|
+
// The lead's messages were mate_message before v117 (D5); a desktop update never migrates, so read whichever is here.
|
|
481
|
+
const messages = db.prepare("SELECT 1 FROM sqlite_master WHERE type = 'table' AND name = 'lead_message'").get() === undefined ? "mate_message" : "lead_message";
|
|
482
|
+
for (const table of ["task", "task_scope", "approver", "run", "artifact", messages, "project"]) {
|
|
478
483
|
const rows = db.prepare(`SELECT * FROM "${table}" ORDER BY rowid`).all();
|
|
479
484
|
result[table] = rows;
|
|
480
485
|
}
|
package/dist/discord-chat.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Discord messages and buttons transport the shared assistant's saved actions. */
|
|
2
|
-
import { chatQuestionButtons } from "./
|
|
2
|
+
import { chatQuestionButtons } from "./subagent-question.js";
|
|
3
3
|
import { chatAskButtons } from "./chat-ask.js";
|
|
4
4
|
import { chatFlowButtons } from "./chat-flow.js";
|
|
5
5
|
import { refuseResultShots, resultShotsPruned, shotWaitsUntil } from "./result-shots.js";
|
|
@@ -10,7 +10,7 @@ import { readChatPart } from "./contracts/chat-content.js";
|
|
|
10
10
|
import { readDiscordButtonToken, readDiscordComponentInteraction } from "./contracts/discord-callback.js";
|
|
11
11
|
import { processChatEvent, planChatNotifications, channelAccess, chatObject as object, planRoomMessages, } from "./chat-delivery.js";
|
|
12
12
|
import { chatResultHref } from "./chat-controls.js";
|
|
13
|
-
import {
|
|
13
|
+
import { LEAD_MESSAGE_MAX_CHARS } from "./lead.js";
|
|
14
14
|
import { discordPlain, renderReply } from "./reply-shape.js";
|
|
15
15
|
import { WARM_EMOJI } from "./chat-warmth.js";
|
|
16
16
|
import { proposalPreview, proposalLink, proposalOutcomeText, armedCardText, armedYesLabel, } from "./chat-channel.js";
|
|
@@ -61,7 +61,7 @@ export function receiveDiscord(state, identity, type, raw, now) {
|
|
|
61
61
|
payload = pair
|
|
62
62
|
? { hash: chatHash(pair[1]) }
|
|
63
63
|
: {
|
|
64
|
-
text: body.content.slice(0,
|
|
64
|
+
text: body.content.slice(0, LEAD_MESSAGE_MAX_CHARS + 1),
|
|
65
65
|
originalLength: body.content.length,
|
|
66
66
|
...(Array.isArray(body.attachments) && body.attachments.length
|
|
67
67
|
? {
|
|
@@ -200,7 +200,7 @@ export async function deliverDiscordPart(options) {
|
|
|
200
200
|
return true;
|
|
201
201
|
}
|
|
202
202
|
try {
|
|
203
|
-
const session = event.session === null ? null : store.
|
|
203
|
+
const session = event.session === null ? null : store.getLeadSession(event.session), repos = await channelAccess(shared, binding, session?.ceilingDigest);
|
|
204
204
|
if (event.kind === "notice" && options.canNotify?.() === false)
|
|
205
205
|
return false;
|
|
206
206
|
const content = partContent(row.payload);
|
|
@@ -241,7 +241,7 @@ export async function deliverDiscordPart(options) {
|
|
|
241
241
|
});
|
|
242
242
|
}
|
|
243
243
|
if (content.proposal) {
|
|
244
|
-
const proposal = store.
|
|
244
|
+
const proposal = store.getLeadProposal(content.proposal);
|
|
245
245
|
if (!proposal)
|
|
246
246
|
text = "This proposal is unavailable.";
|
|
247
247
|
else if (proposal.state !== "pending")
|
|
@@ -294,7 +294,7 @@ export async function deliverDiscordPart(options) {
|
|
|
294
294
|
custom_id: `so_${one.token}`,
|
|
295
295
|
}))
|
|
296
296
|
: []),
|
|
297
|
-
// A
|
|
297
|
+
// A subagent's question (v93): its options, then "Answer in words".
|
|
298
298
|
...(content.question
|
|
299
299
|
? chatQuestionButtons(state, row.id, now).map((one) => ({
|
|
300
300
|
type: 2,
|
package/dist/dispatch.d.ts
CHANGED
|
@@ -98,5 +98,5 @@ export declare function missingCapability(store: Store, taskRef: number, dispatc
|
|
|
98
98
|
export declare function diagnoseTaskDispatch(store: Store, taskId: string, now: Date, readableRepos?: readonly string[] | null): DispatchDiagnosis | null;
|
|
99
99
|
export declare function diagnosisIsDispatchable(diagnosis: DispatchDiagnosis | null): boolean;
|
|
100
100
|
/** Attach the same lifecycle answer to the bounded fleet snapshot used by
|
|
101
|
-
* both direct chat and the long-running
|
|
101
|
+
* both direct chat and the long-running lead. */
|
|
102
102
|
export declare function withDispatchDiagnoses(store: Store, snapshot: ChatSnapshot, now: Date): ChatSnapshot;
|
package/dist/dispatch.js
CHANGED
|
@@ -330,7 +330,7 @@ export function diagnosisIsDispatchable(diagnosis) {
|
|
|
330
330
|
return diagnosis?.code === "ready" || diagnosis?.code === "planning-ready" || diagnosis?.code === "scouting-ready";
|
|
331
331
|
}
|
|
332
332
|
/** Attach the same lifecycle answer to the bounded fleet snapshot used by
|
|
333
|
-
* both direct chat and the long-running
|
|
333
|
+
* both direct chat and the long-running lead. */
|
|
334
334
|
export function withDispatchDiagnoses(store, snapshot, now) {
|
|
335
335
|
return {
|
|
336
336
|
...snapshot,
|
package/dist/dispose.js
CHANGED
|
@@ -707,10 +707,6 @@ export function maybeTriggerRepair(store, repo, evidenceRoot, sourceRunId, verdi
|
|
|
707
707
|
};
|
|
708
708
|
const briefBytes = Buffer.from(JSON.stringify(draftBrief, null, 2), "utf8");
|
|
709
709
|
const key = writeEvidenceFile(evidenceRoot, sourceRunId, `repair-brief-${sourceRunId}-${attempt}.json`, briefBytes);
|
|
710
|
-
// Suffixes survive truncation (the CI-repair rule, verbatim): the prefix
|
|
711
|
-
// gives way, the identity-bearing tail never does.
|
|
712
|
-
const suffix = observation ? `-evidence-${attempt}` : `-fix-${attempt}`;
|
|
713
|
-
const draftId = `${rootTask.slice(0, 64 - suffix.length)}${suffix}`;
|
|
714
710
|
// The draft files through the ONE revision boundary: the source's goal,
|
|
715
711
|
// exclusions, touches, rubric, risk, quality, posture, budget, overrides
|
|
716
712
|
// and pins are read from the SOURCE ROWS inside the seal — the scope
|
|
@@ -719,7 +715,6 @@ export function maybeTriggerRepair(store, repo, evidenceRoot, sourceRunId, verdi
|
|
|
719
715
|
source: { task: ref.externalId, run: sourceRunId, scopeDigest: scope.digest },
|
|
720
716
|
brief: { evidenceRoot, key, sha256: createHash("sha256").update(briefBytes).digest("hex"), bytes: briefBytes.length, capture: "machine-authored repair brief (exit 0)" },
|
|
721
717
|
child: {
|
|
722
|
-
id: draftId,
|
|
723
718
|
title: observation ? `Collect missing evidence for ${ref.externalId}` : verification === undefined ? `repair ${ref.externalId}: ${unresolved.length} criteri${unresolved.length === 1 ? "on" : "a"} unmet` : `Fix failed checks for ${ref.externalId}`,
|
|
724
719
|
repair: observation ? `Collect only the missing observations for ${unresolved.join(", ")}. Keep the saved candidate unchanged. The machine runs supported focused test observations and reuses its intact passing gate; a fresh review assesses the added evidence.` : verification === undefined ? `repair exactly the unmet criteria named below; a comment cannot widen the scope. Unmet: ${unresolved.join(", ")}.` : "Diagnose the saved failed project check and repair within the original scope. Preserve the acceptance criteria and verification command; the revision brief binds the exact failure evidence.",
|
|
725
720
|
},
|
package/dist/envelope.js
CHANGED
|
@@ -28,7 +28,6 @@ export const CAPABILITIES = [
|
|
|
28
28
|
"output-file", // -o <file> writes the same envelope to a file
|
|
29
29
|
"command-schema/1", // contract --commands dumps the declared command guide
|
|
30
30
|
"skill-guides/1", // skills list / skills get serve version-matched guides
|
|
31
|
-
"session-client/1", // typed operator transport; query the service for actual availability
|
|
32
31
|
];
|
|
33
32
|
/**
|
|
34
33
|
* DOCUMENTED reasons — the curated vocabulary the command guide's
|
package/dist/export-ui.js
CHANGED
|
@@ -7,5 +7,5 @@ export const EXPORT_CSS = `.data-export{max-width:720px;min-width:0}.data-export
|
|
|
7
7
|
`.data-export input[type=password]{width:100%;max-width:360px;box-sizing:border-box}.data-export button[type=submit]{margin-top:14px;min-height:44px;white-space:nowrap}`;
|
|
8
8
|
export function dataExportHtml(notice) {
|
|
9
9
|
const note = notice.problem ? html `<p class="problem" role="alert">${notice.problem}</p>` : "";
|
|
10
|
-
return html `<section class="data-export">${note}<p>Everything Toolroll knows, as one .zip: projects, tasks, runs and cost, the action ledger, evidence packs, chats, flows,
|
|
10
|
+
return html `<section class="data-export">${note}<p>Everything Toolroll knows, as one .zip: projects, tasks, runs and cost, the action ledger, evidence packs, chats, flows, subagents and settings. Passwords, keys and tokens are never included.</p>${postForm("/settings/data", html `<label>Your Toolroll password<input type="password" name="password" autocomplete="current-password" required></label><button type="submit">Download export</button>`)}<p class="meta">The same export from the command line: <code>toolroll export --out <path> [--zip]</code></p></section>`;
|
|
11
11
|
}
|
package/dist/export.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
* Full export (v105): everything Toolroll knows, for an instance
|
|
3
3
|
* operator to take away — every table of the database as JSON Lines, grouped
|
|
4
4
|
* by what it's about (projects, tasks, runs, the ledger, chats, flows,
|
|
5
|
-
*
|
|
5
|
+
* subagents, people, settings), an evidence pack per task, the settings kept
|
|
6
6
|
* in files beside the database, a README explaining the layout, and a
|
|
7
7
|
* manifest with each file's SHA-256. One folder, or the same files in a .zip.
|
|
8
8
|
*
|
|
@@ -35,14 +35,14 @@ const DERIVED_TABLE = /^(sqlite_|memory_search)/;
|
|
|
35
35
|
const SECRET_COLUMNS = new Set([
|
|
36
36
|
"api_token.secret_hash", "lead_credential.secret_hash", "approver.credential_hash", "coordinator_credential.credential_hash", "runner.credential_hash", "invite.token_hash",
|
|
37
37
|
"flow_trigger.hook_hash", "push_subscription.endpoint", "push_subscription.p256dh", "push_subscription.auth",
|
|
38
|
-
"chat_turn.credential_key", "
|
|
38
|
+
"chat_turn.credential_key", "lead_session.credential_key", "mate_turn.credential_key", "chat_runtime.push_url", "workflow_preview.token",
|
|
39
39
|
"quota.credential_fp", "oauth_grant.renew_hash", "oauth_client.source_hash",
|
|
40
40
|
]);
|
|
41
41
|
/** A column named like this holds a secret unless it is reviewed below; an unreviewed one is dropped. */
|
|
42
42
|
const SECRET_NAME = /hash|secret|token|passw|cookie|csrf|credential|p256dh|^auth$|key|nonce|endpoint|url/i;
|
|
43
43
|
/** Reviewed: named like a secret, but it isn't one (a seal, a digest, a lookup name, an address with no key). */
|
|
44
44
|
const REVIEWED_COLUMNS = new Set([
|
|
45
|
-
"artifact.key", "budget.scope_key", "
|
|
45
|
+
"artifact.key", "budget.scope_key", "lead_thread.scope_key", "diff_comment.source_key", "chat_meta.key",
|
|
46
46
|
"flow_trigger_event.key", "installation_fact.key", "mcp_idempotency.key", "memory_gap.key", "mutation.idempotency_key", "notification.dedupe_key",
|
|
47
47
|
"service_cursor.key", "ledger_checkpoint.hash", "ledger_seal.hash", "merge_intent.grant_terms_hash", "plan_revision.parent_hash",
|
|
48
48
|
"publication.body_hash", "publication.pr_url", "team_message.payload_hash", "team_request.payload_hash", "backend_grant.credential_scope",
|
|
@@ -53,9 +53,9 @@ const USAGE_COLUMN = /(^|_)tokens(_|$)|output_tokens/;
|
|
|
53
53
|
export function categoryOf(table) {
|
|
54
54
|
const rules = [
|
|
55
55
|
[/^(action_ledger|ledger_seal|ledger_checkpoint|sync_ledger)$/, "ledger"],
|
|
56
|
-
[/^
|
|
56
|
+
[/^subagent/, "subagents"],
|
|
57
57
|
[/^(flow|workflow_)/, "flows"],
|
|
58
|
-
[/^(chat_|
|
|
58
|
+
[/^(chat_|lead_|team_|notification|push_)/, "chats"],
|
|
59
59
|
[/^(approver|api_token|lead_credential|invite|sso_identity|coordinator_|oauth_)/, "people"],
|
|
60
60
|
[/^(run|artifact|claim|worktree$|execution_slot|criterion_review|diff_comment|proof_|review_request|repair_chain|incident|publication$|merge_|side_spend|knowledge_snapshot|learning_snapshot|skill_snapshot)/, "runs"],
|
|
61
61
|
[/^(task|hold$|plan_|scope_|tool_seal|decision|external_|skill_test)/, "tasks"],
|
|
@@ -214,9 +214,9 @@ Everything this installation knew on ${now.toISOString().slice(0, 16).replace("T
|
|
|
214
214
|
- \`runs/\`: agent runs with usage and cost (\`run\`, \`run_spend\`), their records of artifacts, proofs, reviews and publications.
|
|
215
215
|
- \`ledger/\`: the action ledger (\`action_ledger\`), each entry's seal (\`ledger_seal\`) and the checkpoints (\`ledger_checkpoint\`).
|
|
216
216
|
- \`evidence-packs/\`: one JSON file per task: who asked, the exact terms and who approved them, runs and cost, checks, completion and its ledger entries.
|
|
217
|
-
- \`chats/\`: conversations with the lead and
|
|
217
|
+
- \`chats/\`: conversations with the lead and subagents, and Telegram, Slack, Discord and Teams messages and notifications.
|
|
218
218
|
- \`flows/\`: flows, their cards, scripts and triggers (schedules included) and saved recipes.
|
|
219
|
-
- \`
|
|
219
|
+
- \`subagents/\`: subagents, their versions, memory, tools and turns.
|
|
220
220
|
- \`people/\`: accounts, API token names and invitations (no passwords or tokens).
|
|
221
221
|
- \`settings/\`: models, budgets, spend and permission defaults, provider readings; \`files.json\` holds the settings kept in files.
|
|
222
222
|
- \`other/\`: everything else the database keeps (workers, leases, queues).
|