toolroll 0.9.54 → 0.9.56
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 +19 -0
- package/README.md +29 -12
- package/dist/action-ledger.d.ts +2 -4
- package/dist/action-ledger.js +2 -10
- package/dist/agent-onboard.js +4 -1
- package/dist/approval-policy.d.ts +5 -5
- package/dist/approval-policy.js +4 -4
- package/dist/approval-rules-ui.d.ts +3 -2
- package/dist/approval-rules-ui.js +17 -22
- package/dist/assignment-ui.d.ts +3 -2
- package/dist/assignment-ui.js +4 -11
- package/dist/backup-ui.d.ts +2 -1
- package/dist/backup-ui.js +16 -27
- package/dist/brand-mark.d.ts +3 -2
- package/dist/brand-mark.js +4 -4
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +25 -25
- package/dist/browser-shell.d.ts +2 -1
- package/dist/browser-shell.js +9 -9
- package/dist/browser-workspace.d.ts +14 -15
- package/dist/browser-workspace.js +0 -3
- 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 +27 -34
- 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-polish.d.ts +5 -4
- package/dist/chat-polish.js +9 -10
- package/dist/chat-rooms.js +3 -3
- package/dist/chat-warmth.d.ts +2 -2
- package/dist/check-levels-ui.d.ts +2 -1
- package/dist/check-levels-ui.js +26 -53
- package/dist/cli.d.ts +3 -1
- package/dist/cli.js +15 -10
- package/dist/coding-shipping-ui.d.ts +2 -1
- package/dist/coding-shipping-ui.js +6 -6
- package/dist/coding-ui.d.ts +3 -1
- package/dist/coding-ui.js +30 -29
- 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/cli.d.ts +1 -3
- package/dist/contracts/console-api.d.ts +7 -7
- package/dist/contracts/console-api.js +13 -12
- 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/health.d.ts +1 -3
- 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/control-ui.d.ts +5 -4
- package/dist/control-ui.js +9 -34
- 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/credentials-ui.d.ts +5 -4
- package/dist/credentials-ui.js +23 -24
- package/dist/demo-chat.d.ts +3 -3
- package/dist/demo-chat.js +29 -76
- 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/discord-settings.d.ts +3 -2
- package/dist/discord-settings.js +17 -42
- package/dist/dispatch.d.ts +1 -1
- package/dist/dispatch.js +1 -1
- package/dist/envelope.js +10 -1
- package/dist/evidence-pack.d.ts +2 -1
- package/dist/evidence-pack.js +45 -49
- package/dist/export-ui.d.ts +7 -2
- package/dist/export-ui.js +4 -10
- package/dist/export.js +7 -7
- package/dist/flow-engine.d.ts +2 -2
- package/dist/flow-engine.js +21 -21
- package/dist/flow-gallery-ui.d.ts +4 -3
- package/dist/flow-gallery-ui.js +28 -43
- package/dist/flow-insights.d.ts +1 -1
- package/dist/flow-share.js +13 -8
- package/dist/flow-starters-ui.d.ts +2 -1
- package/dist/flow-starters-ui.js +12 -15
- package/dist/flow-steps.d.ts +5 -5
- package/dist/flow-steps.js +19 -19
- package/dist/flow-triggers.d.ts +2 -1
- package/dist/flow-triggers.js +17 -15
- package/dist/flows-cli.js +1 -1
- package/dist/flows-ui.d.ts +4 -3
- package/dist/flows-ui.js +38 -49
- package/dist/flows.js +21 -20
- package/dist/guides.js +112 -6
- package/dist/html.d.ts +76 -0
- package/dist/html.js +173 -0
- package/dist/integrations-ui.d.ts +2 -1
- package/dist/integrations-ui.js +19 -23
- package/dist/invoke.js +1 -1
- package/dist/kits-ui.d.ts +5 -4
- package/dist/kits-ui.js +22 -24
- package/dist/kits.d.ts +12 -12
- package/dist/kits.js +31 -31
- package/dist/knowledge-ui.d.ts +6 -5
- package/dist/knowledge-ui.js +26 -25
- 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 +12 -2
- package/dist/lead-context.js +15 -17
- 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/{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/ledger-view.d.ts +2 -1
- package/dist/ledger-view.js +27 -29
- package/dist/limits-ui.d.ts +3 -2
- package/dist/limits-ui.js +8 -8
- package/dist/live-bus.d.ts +50 -8
- package/dist/live-bus.js +133 -50
- package/dist/mcp-connect.d.ts +1 -1
- package/dist/mcp-connect.js +3 -3
- package/dist/mcp-core.js +1 -1
- package/dist/mcp-oauth.js +35 -36
- package/dist/memory-pass.d.ts +2 -2
- package/dist/memory-pass.js +7 -7
- package/dist/models-ui.d.ts +2 -1
- package/dist/models-ui.js +25 -35
- package/dist/monitoring-ui.d.ts +4 -3
- package/dist/monitoring-ui.js +13 -26
- package/dist/notification-rows.d.ts +2 -2
- package/dist/openrouter-models.d.ts +2 -1
- package/dist/openrouter-models.js +5 -9
- package/dist/operate.d.ts +3 -3
- package/dist/operate.js +46 -41
- package/dist/people-audit-ui.d.ts +2 -1
- package/dist/people-audit-ui.js +13 -13
- package/dist/policy-ui.d.ts +3 -2
- package/dist/policy-ui.js +17 -23
- 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.d.ts +4 -3
- package/dist/project-delete-ui.js +16 -28
- 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/pull-request-ui.d.ts +2 -1
- package/dist/pull-request-ui.js +17 -32
- package/dist/recipe-ui.d.ts +8 -7
- package/dist/recipe-ui.js +39 -32
- package/dist/release-adapters.d.ts +60 -0
- package/dist/release-adapters.js +435 -0
- package/dist/release-cli.d.ts +24 -0
- package/dist/release-cli.js +181 -0
- package/dist/release-gate.d.ts +80 -0
- package/dist/release-gate.js +150 -0
- package/dist/release-links.d.ts +29 -0
- package/dist/release-links.js +102 -0
- package/dist/release.d.ts +331 -0
- package/dist/release.js +550 -0
- package/dist/reply-shape.d.ts +2 -1
- package/dist/reply-shape.js +5 -5
- package/dist/repository-context-ui.d.ts +2 -1
- package/dist/repository-context-ui.js +2 -7
- package/dist/request-budget-ui.d.ts +2 -1
- package/dist/request-budget-ui.js +16 -16
- package/dist/result-review.d.ts +2 -3
- package/dist/result-review.js +3 -9
- package/dist/retention-ui.d.ts +7 -1
- package/dist/retention-ui.js +7 -11
- 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.d.ts +11 -2
- package/dist/serve.js +105 -99
- package/dist/server/chat.d.ts +7 -10
- package/dist/server/chat.js +984 -1021
- package/dist/server/chrome.d.ts +291 -0
- package/dist/server/chrome.js +747 -0
- package/dist/server/console.css +2819 -0
- package/dist/server/flows.d.ts +2 -6
- package/dist/server/flows.js +854 -773
- package/dist/server/guards.d.ts +1 -1
- package/dist/server/guards.js +8 -5
- package/dist/server/handler-context.d.ts +1 -1
- package/dist/server/handler-context.js +1 -1
- package/dist/server/handler-registry.d.ts +8 -6
- package/dist/server/handler-registry.js +14 -2
- package/dist/server/http.d.ts +274 -0
- package/dist/server/http.js +239 -0
- package/dist/server/live.d.ts +34 -0
- package/dist/server/live.js +309 -0
- package/dist/server/pages.d.ts +2 -6
- package/dist/server/pages.js +808 -789
- package/dist/server/people-tokens.d.ts +1 -6
- package/dist/server/people-tokens.js +581 -573
- package/dist/server/remote.d.ts +4 -7
- package/dist/server/remote.js +39 -70
- package/dist/server/render-chat.d.ts +402 -0
- package/dist/server/render-chat.js +927 -0
- package/dist/server/render-pages.d.ts +535 -0
- package/dist/server/render-pages.js +1277 -0
- package/dist/server/render-people.d.ts +32 -0
- package/dist/server/render-people.js +121 -0
- package/dist/server/render-results.d.ts +744 -0
- package/dist/server/render-results.js +2237 -0
- package/dist/server/render-settings.d.ts +154 -0
- package/dist/server/render-settings.js +580 -0
- package/dist/server/render-tasks.d.ts +632 -0
- package/dist/server/render-tasks.js +2345 -0
- package/dist/server/request-context.d.ts +46 -0
- package/dist/server/request-context.js +17 -0
- package/dist/server/route-table.d.ts +25 -3
- package/dist/server/route-table.js +167 -77
- package/dist/server/runtime.d.ts +28 -20
- package/dist/server/runtime.js +7 -1
- package/dist/server/session.d.ts +138 -0
- package/dist/server/session.js +94 -0
- package/dist/server/settings.d.ts +1 -5
- package/dist/server/settings.js +2186 -2121
- package/dist/server/task-views.d.ts +11 -4
- package/dist/server/task-views.js +26 -22
- package/dist/server/tasks.d.ts +9 -9
- package/dist/server/tasks.js +1489 -1420
- package/dist/server-telemetry.d.ts +4 -3
- package/dist/server-telemetry.js +4 -8
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills-ui.d.ts +4 -3
- package/dist/skills-ui.js +14 -17
- package/dist/skills.d.ts +1 -1
- package/dist/skills.js +2 -1
- package/dist/slack-chat.d.ts +2 -2
- package/dist/slack-chat.js +6 -6
- package/dist/slack-settings.d.ts +3 -2
- package/dist/slack-settings.js +17 -42
- package/dist/spend-ui.d.ts +5 -4
- package/dist/spend-ui.js +17 -40
- package/dist/spend.d.ts +14 -14
- package/dist/spend.js +31 -31
- package/dist/sso-ui.d.ts +3 -2
- package/dist/sso-ui.js +26 -27
- package/dist/storage-ui.d.ts +2 -1
- package/dist/storage-ui.js +14 -33
- package/dist/store-baseline.d.ts +19 -0
- package/dist/store-baseline.js +2873 -0
- package/dist/store.d.ts +197 -249
- package/dist/store.js +747 -3084
- 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/subagents-ui.js +137 -0
- 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 +20 -33
- package/dist/task-composer.d.ts +2 -1
- package/dist/task-composer.js +7 -7
- package/dist/task-status.d.ts +4 -3
- package/dist/task-status.js +15 -16
- package/dist/team-cli.d.ts +1 -0
- package/dist/team-cli.js +14 -2
- package/dist/team-http.d.ts +5 -9
- package/dist/team-http.js +5 -63
- package/dist/team-leads.js +13 -13
- package/dist/team-runtime.d.ts +2 -2
- package/dist/team-runtime.js +8 -8
- package/dist/team-ui.d.ts +2 -1
- package/dist/team-ui.js +2 -5
- package/dist/teams-chat.js +6 -6
- package/dist/teams-settings.d.ts +3 -2
- package/dist/teams-settings.js +20 -31
- 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-settings.d.ts +3 -2
- package/dist/telegram-settings.js +14 -25
- package/dist/telegram-status.js +1 -1
- 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 +9 -30
- package/dist/text-limits.d.ts +18 -18
- package/dist/text-limits.js +18 -18
- package/dist/toolroll-update-ui.d.ts +3 -2
- package/dist/toolroll-update-ui.js +35 -39
- package/dist/toolroll-update.d.ts +8 -0
- package/dist/toolroll-update.js +45 -8
- package/dist/tools-ui.d.ts +5 -2
- package/dist/tools-ui.js +31 -31
- package/dist/when-html.d.ts +11 -3
- package/dist/when-html.js +5 -6
- package/dist/workspace-ui.d.ts +4 -2
- package/dist/workspace-ui.js +10 -10
- package/package.json +1 -2
- package/dist/server/shared.d.ts +0 -3151
- package/dist/server/shared.js +0 -12001
- package/dist/teammate-admin.d.ts +0 -53
- package/dist/teammates-ui.d.ts +0 -20
- package/dist/teammates-ui.js +0 -166
|
@@ -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/control-ui.d.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
/** Shared setup views over the existing project configuration and approval doors. */
|
|
2
|
+
import { type Html } from "./html.js";
|
|
2
3
|
import type { ProviderId } from "./provider.js";
|
|
3
4
|
import type { ProviderConnection } from "./provider-connection.js";
|
|
4
5
|
import { type ModelChoice } from "./setup-guide.js";
|
|
5
6
|
import type { SetupInputs } from "./control-setup.js";
|
|
6
7
|
import { type OpenRouterModels } from "./openrouter-models.js";
|
|
7
|
-
export declare function hiddenFields(values: Record<string, string>): string;
|
|
8
8
|
export declare function connectionWords(connection: ProviderConnection): string;
|
|
9
|
-
export declare function connectionHtml(provider: ProviderId, connection: ProviderConnection, task?: string):
|
|
9
|
+
export declare function connectionHtml(provider: ProviderId, connection: ProviderConnection, task?: string): Html;
|
|
10
10
|
export declare function controlSetupHtml(data: {
|
|
11
11
|
repo: string;
|
|
12
12
|
csrf: string;
|
|
@@ -25,5 +25,6 @@ export declare function controlSetupHtml(data: {
|
|
|
25
25
|
installed: boolean;
|
|
26
26
|
message?: string;
|
|
27
27
|
};
|
|
28
|
-
}):
|
|
29
|
-
|
|
28
|
+
}): Html;
|
|
29
|
+
/** `fields` may still carry the session's csrf (a caller's habit): postForm writes the one CSRF field. */
|
|
30
|
+
export declare function setupPreviewHtml(inputs: SetupInputs, fields: Record<string, string>): Html;
|
package/dist/control-ui.js
CHANGED
|
@@ -1,9 +1,7 @@
|
|
|
1
|
+
/** Shared setup views over the existing project configuration and approval doors. */
|
|
2
|
+
import { html, joinHtml, postForm } from "./html.js";
|
|
1
3
|
import { ASSISTANTS } from "./setup-guide.js";
|
|
2
4
|
import { openRouterPicker } from "./openrouter-models.js";
|
|
3
|
-
const escape = (value) => value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
4
|
-
export function hiddenFields(values) {
|
|
5
|
-
return Object.entries(values).map(([name, value]) => `<input type="hidden" name="${escape(name)}" value="${escape(value)}">`).join("");
|
|
6
|
-
}
|
|
7
5
|
export function connectionWords(connection) {
|
|
8
6
|
return {
|
|
9
7
|
connected: "Connected", "signed-out": "Not signed in", "not-installed": "CLI not installed",
|
|
@@ -12,42 +10,19 @@ export function connectionWords(connection) {
|
|
|
12
10
|
}
|
|
13
11
|
export function connectionHtml(provider, connection, task = "") {
|
|
14
12
|
const query = new URLSearchParams({ provider, ...(task ? { task } : {}) });
|
|
15
|
-
return `<div class="card assistant-account"><p><strong>${
|
|
16
|
-
`<p class="meta">${[connection.email, connection.plan, connection.method].filter(Boolean).map(one => escape(one)).join(" · ")}</p>` +
|
|
17
|
-
`<p class="meta">Checked ${escape(new Date(connection.checkedAt).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", timeZoneName: "short" }))} on the computer running this console. Sign-in does not prove model access or remaining quota.</p>` +
|
|
18
|
-
`<a class="button-link" href="/control/connection?${escape(query.toString())}">${connection.state === "connected" ? "Manage connection" : "Connect account"}</a> · ` +
|
|
19
|
-
`<a href="/control?${escape(query.toString())}&check-connection=1">Check again</a></div>`;
|
|
13
|
+
return html `<div class="card assistant-account"><p><strong>${ASSISTANTS[provider].name} · ${connectionWords(connection)}</strong></p><p class="meta">${[connection.email, connection.plan, connection.method].filter(Boolean).join(" · ")}</p><p class="meta">Checked ${new Date(connection.checkedAt).toLocaleTimeString("en-US", { hour: "numeric", minute: "2-digit", timeZoneName: "short" })} on the computer running this console. Sign-in does not prove model access or remaining quota.</p><a class="button-link" href="/control/connection?${query.toString()}">${connection.state === "connected" ? "Manage connection" : "Connect account"}</a> · <a href="/control?${query.toString()}&check-connection=1">Check again</a></div>`;
|
|
20
14
|
}
|
|
21
15
|
export function controlSetupHtml(data) {
|
|
22
16
|
const { provider, inputs, task = "" } = data;
|
|
23
17
|
const query = new URLSearchParams({ provider, ...(task ? { task } : {}) });
|
|
24
18
|
const model = data.catalog !== null
|
|
25
19
|
? openRouterPicker(data.catalog, inputs.model || null, `/control?${query}&refresh-models=1`)
|
|
26
|
-
: `<label>Model<input type="text" name="model" value="${
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
`<p class="meta">Choose the default builder for new tasks and the preparation command for this project.</p>` +
|
|
30
|
-
`<nav class="assistant-picker row" aria-label="Choose provider">${Object.keys(ASSISTANTS).map(id => `<a class="button-link" href="/control?${escape(new URLSearchParams({ provider: id, ...(task ? { task } : {}) }).toString())}"${id === provider ? ' aria-current="page"' : ""}>${ASSISTANTS[id].name}</a>`).join(" ")}</nav>` +
|
|
31
|
-
connectionHtml(provider, data.connection, task) +
|
|
32
|
-
`<form method="post" action="/control/setup-preview" class="card">${hiddenFields({ csrf: data.csrf, repo: data.repo, provider, task })}` + model +
|
|
33
|
-
`<details class="setup-advanced"><summary>Project preparation</summary>` +
|
|
34
|
-
(data.preparation === null ? "" : `<p class="meta">Suggested from ${escape(data.preparation.evidence)}: ${escape(data.preparation.label)} — <code>${escape(data.preparation.command)}</code>. Review before approving.</p>`) +
|
|
35
|
-
`<label>Preparation command<textarea name="command" rows="2" maxlength="2000">${escape(inputs.command)}</textarea></label>` +
|
|
36
|
-
`<label>Preparation timeout in seconds<input name="seconds" type="number" min="1" max="3600" value="${escape(inputs.seconds)}" required></label>` +
|
|
37
|
-
`<p class="meta">Preparation applies to subsequent runs, including already approved tasks. Saving setup does not execute it.</p></details>` +
|
|
38
|
-
`<button type="submit">Review project setup</button></form>` +
|
|
39
|
-
`<section class="card"><h2>Agent instructions</h2>` +
|
|
40
|
-
(data.instructions.message ? `<p>${escape(data.instructions.message)}</p>` : data.instructions.installed ? `<p>Toolroll instructions are installed.</p>` :
|
|
41
|
-
`<p>Give the agent the project's Toolroll handoff instructions.</p><form method="post" action="/control/instructions-preview">${hiddenFields({ csrf: data.csrf, repo: data.repo })}<button>Review instructions</button></form>`) +
|
|
42
|
-
`</section><p><a href="/fleet">Configure planning, repair, and review agents</a> · <a href="/tasks/new">Describe a task</a></p>`;
|
|
20
|
+
: html `<label>Model<input type="text" name="model" value="${inputs.model}" list="setup-models" required autocomplete="off" placeholder="Exact model id or supported alias"></label><datalist id="setup-models">${data.models.map(one => html `<option value="${one.value}">${one.label}</option>`)}</datalist>`;
|
|
21
|
+
return html `<h1>Project setup</h1><p>${data.repo}</p><p class="meta">Choose the default builder for new tasks and the preparation command for this project.</p><nav class="assistant-picker row" aria-label="Choose provider">${joinHtml(Object.keys(ASSISTANTS).map(id => html `<a class="button-link" href="/control?${new URLSearchParams({ provider: id, ...(task ? { task } : {}) }).toString()}"${id === provider ? html ` aria-current="page"` : ""}>${ASSISTANTS[id].name}</a>`), " ")}</nav>${connectionHtml(provider, data.connection, task)}${postForm("/control/setup-preview", html `${model}<details class="setup-advanced"><summary>Project preparation</summary>${data.preparation === null ? "" : html `<p class="meta">Suggested from ${data.preparation.evidence}: ${data.preparation.label} — <code>${data.preparation.command}</code>. Review before approving.</p>`}<label>Preparation command<textarea name="command" rows="2" maxlength="2000">${inputs.command}</textarea></label><label>Preparation timeout in seconds<input name="seconds" type="number" min="1" max="3600" value="${inputs.seconds}" required></label><p class="meta">Preparation applies to subsequent runs, including already approved tasks. Saving setup does not execute it.</p></details><button type="submit">Review project setup</button>`, { attrs: { class: "card" }, hidden: { repo: data.repo, provider, task } })}<section class="card"><h2>Agent instructions</h2>${data.instructions.message ? html `<p>${data.instructions.message}</p>` : data.instructions.installed ? html `<p>Toolroll instructions are installed.</p>` :
|
|
22
|
+
html `<p>Give the agent the project's Toolroll handoff instructions.</p>${postForm("/control/instructions-preview", html `<button>Review instructions</button>`, { hidden: { repo: data.repo } })}`}</section><p><a href="/fleet">Configure planning, repair, and review agents</a> · <a href="/tasks/new">Describe a task</a></p>`;
|
|
43
23
|
}
|
|
24
|
+
/** `fields` may still carry the session's csrf (a caller's habit): postForm writes the one CSRF field. */
|
|
44
25
|
export function setupPreviewHtml(inputs, fields) {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
`<p><strong>Preparation:</strong></p><pre class="recap">${escape(inputs.command || "No preparation command")}</pre>` +
|
|
48
|
-
`<p>Preparation timeout: ${escape(inputs.seconds)} seconds.</p>` +
|
|
49
|
-
`<p>The builder default applies to new tasks. Preparation applies to subsequent runs, including already approved tasks. Existing signed task settings and verification rules remain in force.</p>` +
|
|
50
|
-
`<form method="post" action="/control/setup-approve">${hiddenFields({ ...fields, ...inputs })}` +
|
|
51
|
-
`<label>Your password<input type="password" name="token" autocomplete="current-password" required></label>` +
|
|
52
|
-
`<button>Approve project setup</button></form></div>`;
|
|
26
|
+
const { csrf: _csrf, ...rest } = fields;
|
|
27
|
+
return html `<h1>Approve project setup</h1><div class="card"><p>${fields.repo ?? ""}</p><p><strong>Builder:</strong> ${inputs.provider} · ${inputs.model}</p><p><strong>Preparation:</strong></p><pre class="recap">${inputs.command || "No preparation command"}</pre><p>Preparation timeout: ${inputs.seconds} seconds.</p><p>The builder default applies to new tasks. Preparation applies to subsequent runs, including already approved tasks. Existing signed task settings and verification rules remain in force.</p>${postForm("/control/setup-approve", html `<label>Your password<input type="password" name="token" autocomplete="current-password" required></label><button>Approve project setup</button>`, { hidden: { ...rest, ...inputs } })}</div>`;
|
|
53
28
|
}
|
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
|
package/dist/credentials-ui.d.ts
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
* can see and end everyone's.
|
|
5
5
|
*/
|
|
6
6
|
import type { ApiTokenRow, WebSessionRow } from "./store.js";
|
|
7
|
+
import { type Html } from "./html.js";
|
|
7
8
|
export declare const CREDENTIALS_CSS: string;
|
|
8
9
|
/** "Chrome on macOS", from a user agent, for a person to recognise a session. */
|
|
9
10
|
export declare function deviceWords(agent: string | null): string;
|
|
@@ -19,12 +20,12 @@ export type CredentialsView = {
|
|
|
19
20
|
/** Request limits (request-budget-ui.ts): words for each token's line, and the operator's disclosure. */
|
|
20
21
|
limits?: {
|
|
21
22
|
note: (token: ApiTokenRow) => string;
|
|
22
|
-
section:
|
|
23
|
+
section: Html;
|
|
23
24
|
};
|
|
24
25
|
};
|
|
25
|
-
export declare function credentialsHtml(view: CredentialsView,
|
|
26
|
+
export declare function credentialsHtml(view: CredentialsView, notice: {
|
|
26
27
|
said?: string | null;
|
|
27
28
|
problem?: string | null;
|
|
28
|
-
}):
|
|
29
|
+
}): Html;
|
|
29
30
|
/** The token, once: a focused page with no script. */
|
|
30
|
-
export declare function tokenShownHtml(name: string, token: string, access: "read" | "act", expiresAt: string):
|
|
31
|
+
export declare function tokenShownHtml(name: string, token: string, access: "read" | "act", expiresAt: string): Html;
|
package/dist/credentials-ui.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { daysLeft, expiryNoticeDue, TOKEN_DAYS, tokenLive } from "./api-tokens.js";
|
|
2
2
|
import { projectName } from "./project.js";
|
|
3
|
-
|
|
3
|
+
import { html, postForm } from "./html.js";
|
|
4
4
|
export const CREDENTIALS_CSS = `.credentials{max-width:820px;min-width:0}.credentials .card{padding:14px 16px;margin:12px 0}.credentials h2{font-size:1.05rem;margin:0 0 8px}` +
|
|
5
5
|
`.credentials .rows{display:grid;gap:0;border:1px solid var(--so-line);border-radius:10px;overflow:hidden}.credentials .row-item{display:flex;align-items:center;justify-content:space-between;gap:12px;padding:10px 14px;border-bottom:1px solid var(--so-line)}` +
|
|
6
6
|
`.credentials .row-item:last-child{border-bottom:0}.credentials .row-item p{margin:0}.credentials .row-item .meta{font-size:.85rem}.credentials form{margin:0}.credentials button{min-height:40px;white-space:nowrap}` +
|
|
@@ -22,39 +22,38 @@ const when = (value, now) => {
|
|
|
22
22
|
const minutes = Math.round((now - at) / 60_000);
|
|
23
23
|
return minutes < 1 ? "just now" : minutes < 60 ? `${minutes} min ago` : minutes < 60 * 24 ? `${Math.round(minutes / 60)} h ago` : new Date(at).toISOString().slice(0, 10);
|
|
24
24
|
};
|
|
25
|
-
export function credentialsHtml(view,
|
|
26
|
-
const
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
`${one.here ? "" : post({ action: "end-session", session: one.idHash }, "Sign out")}</div>`).join("")}</div>`;
|
|
25
|
+
export function credentialsHtml(view, notice) {
|
|
26
|
+
const post = (fields, label, style = "secondary") => postForm("/settings/sessions", html `<button class="${style}">${label}</button>`, { hidden: { ...fields, ...(view.everyone ? { everyone: "1" } : {}) } });
|
|
27
|
+
const note = notice.problem ? html `<p class="problem" role="alert">${notice.problem}</p>` : notice.said ? html `<p role="status">${notice.said}</p>` : "";
|
|
28
|
+
const toggle = view.canSeeEveryone ? html `<p class="meta"><a href="/settings/sessions${view.everyone ? "" : "?everyone=1"}">${view.everyone ? "Show only mine" : "Show everyone's"}</a></p>` : "";
|
|
29
|
+
const sessions = view.sessions.length === 0 ? html `<p class="meta">No one else is signed in.</p>` : html `<div class="rows">${view.sessions.map(one => html `<div class="row-item" data-session="${one.idHash.slice(0, 12)}"><div><p>${view.everyone ? html `<strong>${one.account}</strong> · ` : ""}${deviceWords(one.agent)}${one.here ? html `<span class="badge-here">This browser</span>` : ""}</p>\
|
|
30
|
+
<p class="meta">${one.ssoAt === null ? "Password" : "Identity provider"} · ${one.address ?? "unknown address"} · active ${when(one.lastSeen, view.now)} · signed in ${when(one.createdAt, view.now)}</p></div>\
|
|
31
|
+
${one.here ? "" : post({ action: "end-session", session: one.idHash }, "Sign out")}</div>`)}</div>`;
|
|
33
32
|
const others = view.sessions.filter(one => !one.here && one.account === view.who).length;
|
|
34
33
|
const endOthers = others > 0 && !view.everyone ? post({ action: "end-others" }, `Sign out everywhere else (${others})`) : "";
|
|
35
34
|
const live = view.tokens.filter(one => tokenLive(one, view.now));
|
|
36
35
|
// v111: its projects, and one state: when it stops (soon, said once and marked) or, once replaced, when it ends.
|
|
37
36
|
const ends = (one) => {
|
|
38
37
|
if (one.replacedBy !== null && one.overlapUntil !== null)
|
|
39
|
-
return `<span class="soon">Replaced · stops ${
|
|
38
|
+
return html `<span class="soon">Replaced · stops ${one.overlapUntil.slice(11, 16)} UTC</span>`;
|
|
40
39
|
if (expiryNoticeDue(one, view.now) === null)
|
|
41
|
-
return `Expires ${
|
|
40
|
+
return html `Expires ${one.expiresAt.slice(0, 10)}`;
|
|
42
41
|
const days = daysLeft(one.expiresAt, view.now);
|
|
43
|
-
return `<span class="soon">Expires ${days <= 1 ? "within a day" : `in ${days} days`}</span>`;
|
|
42
|
+
return html `<span class="soon">Expires ${days <= 1 ? "within a day" : `in ${days} days`}</span>`;
|
|
44
43
|
};
|
|
45
|
-
const scope = (one) => one.projects === null ? "All projects" : one.projects.length === 0 ? "No projects" : one.projects.map(repo =>
|
|
46
|
-
const tokens = live.length === 0 ? `<p class="meta">No API tokens.</p>` : `<div class="rows">${live.map(one => `<div class="row-item" data-token="${
|
|
47
|
-
|
|
48
|
-
const create = `<details class="card"><summary>New API token</summary
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
return `<section class="credentials">${note}${toggle}<h2>Signed in</h2>${sessions}${endOthers}<h2 style="margin-top:1.5rem">API tokens</h2
|
|
54
|
-
|
|
44
|
+
const scope = (one) => one.projects === null ? "All projects" : one.projects.length === 0 ? "No projects" : one.projects.map(repo => projectName(repo)).join(", ");
|
|
45
|
+
const tokens = live.length === 0 ? html `<p class="meta">No API tokens.</p>` : html `<div class="rows">${live.map(one => html `<div class="row-item" data-token="${one.id}"><div><p>${view.everyone ? html `<strong>${one.account}</strong> · ` : ""}${one.name} · ${one.access === "act" ? "Can act" : "Read only"}</p>\
|
|
46
|
+
<p class="meta">${scope(one)} · ${ends(one)} · last used ${when(one.lastUsedAt, view.now)}${view.limits === undefined ? "" : ` · ${view.limits.note(one)}`}</p></div>${post({ action: "revoke-token", token: one.id }, "Revoke")}</div>`)}</div>`;
|
|
47
|
+
const create = html `<details class="card"><summary>New API token</summary>${postForm("/settings/sessions", html `\
|
|
48
|
+
<label>Name<input type="text" name="name" maxlength="60" required placeholder="for example: CI"></label>\
|
|
49
|
+
<label>It can<select name="access"><option value="read">Read (tasks, results, the ledger)</option><option value="act">Act as you (file and manage work; never approve)</option></select></label>\
|
|
50
|
+
<label>Expires in<select name="days">${TOKEN_DAYS.map(days => html `<option value="${days}"${days === 90 ? " selected" : ""}>${days} days</option>`)}</select></label>\
|
|
51
|
+
<label>Your Toolroll password<input type="password" name="password" autocomplete="current-password" required></label><button>Make the token</button>`, { attrs: { class: "create" }, hidden: { action: "create-token" } })}</details>`;
|
|
52
|
+
return html `<section class="credentials">${note}${toggle}<h2>Signed in</h2>${sessions}${endOthers}<h2 style="margin-top:1.5rem">API tokens</h2>\
|
|
53
|
+
<p class="meta">For scripts and CI: send <code>Authorization: Bearer <token></code>. A token can't approve anything.</p>${tokens}${view.everyone ? "" : create}${view.limits?.section ?? ""}</section>`;
|
|
55
54
|
}
|
|
56
55
|
/** The token, once: a focused page with no script. */
|
|
57
56
|
export function tokenShownHtml(name, token, access, expiresAt) {
|
|
58
|
-
return `<h1>${
|
|
59
|
-
|
|
57
|
+
return html `<h1>${name}</h1><div class="card"><p>Your API token, shown once. Only a hash is kept, so copy it now.</p><p class="mono secret-value">${token}</p>\
|
|
58
|
+
<p class="meta">${access === "act" ? "It acts as you (never approves)" : "It reads"} until ${expiresAt.slice(0, 10)}. Revoke it any time on Sessions & tokens.</p></div><p class="meta"><a href="/settings/sessions">Back to Sessions & tokens</a></p>`;
|
|
60
59
|
}
|
package/dist/demo-chat.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type Html } from "./html.js";
|
|
1
2
|
import type { DemoExchange } from "./demo.js";
|
|
2
3
|
/** What a finished exchange's stored result holds, read back from its evidence. */
|
|
3
4
|
export type DemoResultView = {
|
|
@@ -17,14 +18,13 @@ export type DemoResultView = {
|
|
|
17
18
|
taskHref: string;
|
|
18
19
|
};
|
|
19
20
|
/** The conversation itself; the live script swaps this region in place. */
|
|
20
|
-
export declare function demoThreadHtml(exchanges: readonly DemoExchange[],
|
|
21
|
+
export declare function demoThreadHtml(exchanges: readonly DemoExchange[], resultOf: (exchange: DemoExchange) => DemoResultView | null): Html;
|
|
21
22
|
export declare function demoChatHtml(input: {
|
|
22
23
|
exchanges: readonly DemoExchange[];
|
|
23
|
-
csrf: string;
|
|
24
24
|
version: number;
|
|
25
25
|
problem: string | null;
|
|
26
26
|
resultOf: (exchange: DemoExchange) => DemoResultView | null;
|
|
27
|
-
}):
|
|
27
|
+
}): Html;
|
|
28
28
|
/**
|
|
29
29
|
* Keeps a running build live: polls while one is working and swaps the
|
|
30
30
|
* thread in place, unless the visitor is typing inside it. Enter sends.
|