toolroll 0.9.67 → 0.9.68
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 +36 -0
- package/dist/acp-client.js +1 -3
- package/dist/agent-board.d.ts +0 -1
- package/dist/agent-board.js +0 -1
- package/dist/agent-fence.js +3 -0
- package/dist/browser/workspace.css +1 -1
- package/dist/browser/workspace.js +31 -29
- package/dist/builder.js +3 -26
- package/dist/canonical-json.d.ts +14 -0
- package/dist/canonical-json.js +36 -0
- package/dist/chat-actions.js +1 -2
- package/dist/chat-admission.d.ts +19 -0
- package/dist/chat-admission.js +22 -0
- package/dist/chat-channel.js +1 -1
- package/dist/chat-delivery.js +0 -1
- package/dist/chat-follow.d.ts +17 -0
- package/dist/chat-follow.js +32 -0
- package/dist/chat-messages.js +0 -1
- package/dist/chat-settings-page.d.ts +23 -0
- package/dist/chat-settings-page.js +41 -0
- package/dist/claim.js +3 -6
- package/dist/claude-print.d.ts +12 -0
- package/dist/claude-print.js +34 -0
- package/dist/cli-http.d.ts +0 -7
- package/dist/cli-http.js +0 -21
- package/dist/cli.d.ts +3 -10
- package/dist/cli.js +15 -24
- package/dist/coding-provider.js +2 -1
- package/dist/coding-workspace.js +1 -1
- package/dist/{team-cli.d.ts → connect-cli.d.ts} +5 -9
- package/dist/connect-cli.js +331 -0
- package/dist/containment.d.ts +0 -2
- package/dist/containment.js +2 -6
- package/dist/contracts/chat-actions.d.ts +0 -1
- package/dist/contracts/chat-content.d.ts +0 -4
- package/dist/contracts/chat-content.js +0 -2
- package/dist/contracts/chat-tables.d.ts +0 -1
- package/dist/contracts/cli.d.ts +0 -62
- package/dist/contracts/cli.js +0 -4
- package/dist/contracts/coding-workspace.js +1 -1
- package/dist/contracts/contract.js +1 -1
- package/dist/contracts/flow-card.d.ts +0 -1
- package/dist/contracts/flow-propose.d.ts +0 -1
- package/dist/contracts/flow-send.js +1 -1
- package/dist/contracts/gateway-tools.d.ts +0 -1
- package/dist/contracts/integration-metadata.js +1 -1
- package/dist/contracts/lead-tools.d.ts +0 -1
- package/dist/contracts/memory-pass.d.ts +0 -1
- package/dist/contracts/memory-pass.js +1 -1
- package/dist/contracts/plan.js +1 -1
- package/dist/contracts/project-knowledge.js +1 -1
- package/dist/contracts/project-skills.d.ts +0 -1
- package/dist/contracts/proof.js +1 -1
- package/dist/contracts/recipes.js +1 -1
- package/dist/contracts/scope.js +1 -1
- package/dist/contracts/scout-report.js +1 -1
- package/dist/contracts/teams-callback.d.ts +0 -1
- package/dist/converse.d.ts +0 -6
- package/dist/converse.js +0 -19
- package/dist/daemon.js +3 -2
- package/dist/decision.d.ts +1 -3
- package/dist/deprecations.d.ts +12 -4
- package/dist/deprecations.js +27 -4
- package/dist/desktop-update-recovery.js +1 -1
- package/dist/desktop-update.js +3 -2
- package/dist/discord-chat.js +4 -15
- package/dist/discord-settings.d.ts +2 -6
- package/dist/discord-settings.js +10 -38
- package/dist/discord.js +12 -23
- package/dist/evidence.d.ts +0 -1
- package/dist/evidence.js +0 -3
- package/dist/exec.d.ts +0 -9
- package/dist/exec.js +3 -81
- package/dist/flow-actions.js +0 -3
- package/dist/flow-draft.d.ts +1 -3
- package/dist/flow-draft.js +15 -28
- package/dist/flow-scripts.d.ts +1 -8
- package/dist/flow-scripts.js +0 -13
- package/dist/flow-send.js +1 -1
- package/dist/flow-share.d.ts +0 -2
- package/dist/flow-share.js +1 -6
- package/dist/flow-steps.js +1 -1
- package/dist/flow-triggers.d.ts +0 -1
- package/dist/flow-triggers.js +1 -2
- package/dist/flow-unattended.js +1 -12
- package/dist/flows.js +1 -1
- package/dist/health-cli.d.ts +2 -2
- package/dist/health-cli.js +1 -1
- package/dist/invoke.d.ts +0 -3
- package/dist/invoke.js +5 -3
- package/dist/is-record.d.ts +2 -0
- package/dist/is-record.js +2 -0
- package/dist/lead-doors.d.ts +1 -5
- package/dist/lead-doors.js +0 -4
- package/dist/lead-tools.js +3 -6
- package/dist/live-detail.d.ts +0 -1
- package/dist/live-detail.js +0 -6
- package/dist/live-terminal.js +2 -1
- package/dist/live.d.ts +0 -1
- package/dist/live.js +1 -2
- package/dist/mcp-core.js +0 -2
- package/dist/memory-pass.js +1 -1
- package/dist/model-catalog.js +1 -1
- package/dist/modes.js +1 -12
- package/dist/operate.js +383 -750
- package/dist/password-bearer.d.ts +0 -2
- package/dist/password-bearer.js +0 -4
- package/dist/peek-cli.js +2 -1
- package/dist/peek.d.ts +2 -26
- package/dist/peek.js +2 -168
- package/dist/phase-routing.d.ts +0 -4
- package/dist/phase-routing.js +2 -21
- package/dist/planner-source.d.ts +2 -1
- package/dist/planner-source.js +2 -12
- package/dist/planner.js +2 -14
- package/dist/process-tree.d.ts +0 -2
- package/dist/process-tree.js +0 -10
- package/dist/project-delete.d.ts +0 -2
- package/dist/project-delete.js +1 -3
- package/dist/project-learning.d.ts +0 -14
- package/dist/project-skills.d.ts +0 -1
- package/dist/project-skills.js +0 -14
- package/dist/project-tools.js +2 -10
- package/dist/provider.d.ts +0 -17
- package/dist/provider.js +0 -26
- package/dist/pulls.d.ts +0 -2
- package/dist/pulls.js +0 -9
- package/dist/release-adapters.d.ts +3 -0
- package/dist/release-adapters.js +15 -5
- package/dist/remote-exec.d.ts +3 -2
- package/dist/remote-exec.js +3 -2
- package/dist/repos.d.ts +0 -5
- package/dist/repos.js +2 -10
- package/dist/repository-context.d.ts +0 -2
- package/dist/repository-context.js +0 -4
- package/dist/restart-certification.d.ts +0 -2
- package/dist/restart-certification.js +1 -5
- package/dist/result-follow-ups.d.ts +1 -4
- package/dist/result-follow-ups.js +1 -6
- package/dist/result-review.d.ts +0 -2
- package/dist/result-review.js +0 -2
- package/dist/retention.d.ts +0 -1
- package/dist/retention.js +0 -1
- package/dist/review-context.d.ts +0 -1
- package/dist/review-context.js +1 -12
- package/dist/reviewer.d.ts +0 -16
- package/dist/reviewer.js +0 -18
- package/dist/run-closeout.js +2 -1
- package/dist/scope.js +1 -13
- package/dist/scout-browser.js +2 -1
- package/dist/serve.js +2 -2
- package/dist/server/console.css +5 -133
- package/dist/server/flows.js +2 -2
- package/dist/server/http.d.ts +2 -0
- package/dist/server/http.js +5 -0
- package/dist/server/pages.js +2 -2
- package/dist/server/people-tokens.js +3 -4
- package/dist/server/remote.js +1 -6
- package/dist/server/render-chat.d.ts +9 -2
- package/dist/server/render-chat.js +53 -7
- package/dist/server/render-results.d.ts +0 -6
- package/dist/server/render-results.js +3 -9
- package/dist/server/render-tasks.js +4 -5
- package/dist/server/route-table.d.ts +0 -4
- package/dist/server/route-table.js +0 -6
- package/dist/server/settings.js +23 -23
- package/dist/server/task-views.js +1 -1
- package/dist/server/tasks.js +3 -3
- package/dist/setup-guide.d.ts +2 -2
- package/dist/skills.d.ts +0 -6
- package/dist/skills.js +0 -8
- package/dist/slack-chat.d.ts +1 -7
- package/dist/slack-chat.js +5 -18
- package/dist/slack-settings.d.ts +2 -6
- package/dist/slack-settings.js +10 -38
- package/dist/slack.js +12 -23
- package/dist/sleep.d.ts +2 -0
- package/dist/sleep.js +2 -0
- package/dist/store.d.ts +0 -73
- package/dist/store.js +3 -177
- package/dist/structured-output.d.ts +0 -1
- package/dist/structured-output.js +0 -1
- package/dist/subagent-work.d.ts +0 -2
- package/dist/subagent-work.js +0 -2
- package/dist/subagents.d.ts +1 -3
- package/dist/subagents.js +20 -33
- package/dist/subscription-chat.d.ts +1 -3
- package/dist/subscription-chat.js +2 -3
- package/dist/task-sizing.d.ts +1 -4
- package/dist/task-sizing.js +3 -10
- package/dist/teams-chat.js +4 -11
- package/dist/teams.js +12 -19
- package/dist/telegram-lead.js +2 -2
- package/dist/telegram.js +1 -1
- package/dist/token-notices.d.ts +0 -11
- package/dist/token-notices.js +1 -5
- package/dist/tool-secret-store.d.ts +0 -3
- package/dist/tool-secret-store.js +2 -11
- package/dist/toolroll-update.d.ts +0 -2
- package/dist/toolroll-update.js +2 -2
- package/dist/verification-evidence.d.ts +0 -1
- package/dist/verification-evidence.js +0 -1
- package/dist/webhooks.d.ts +0 -1
- package/dist/webhooks.js +0 -1
- package/dist/workspace-ui.d.ts +0 -8
- package/dist/workspace-ui.js +1 -6
- package/package.json +1 -1
- package/dist/contracts/native-census.d.ts +0 -42
- package/dist/contracts/native-census.js +0 -36
- package/dist/process-recovery-anchor.d.ts +0 -75
- package/dist/process-recovery-anchor.js +0 -188
- package/dist/process-recovery-coalition.d.ts +0 -25
- package/dist/process-recovery-coalition.js +0 -105
- package/dist/process-recovery-eligibility.d.ts +0 -179
- package/dist/process-recovery-eligibility.js +0 -174
- package/dist/process-recovery-native.d.ts +0 -161
- package/dist/process-recovery-native.js +0 -595
- package/dist/process-recovery-provenance.d.ts +0 -163
- package/dist/process-recovery-provenance.js +0 -292
- package/dist/process-recovery-services.d.ts +0 -56
- package/dist/process-recovery-services.js +0 -191
- package/dist/process-recovery-settlement.d.ts +0 -32
- package/dist/process-recovery-settlement.js +0 -133
- package/dist/process-recovery.d.ts +0 -41
- package/dist/process-recovery.js +0 -91
- package/dist/session-brief.d.ts +0 -8
- package/dist/session-brief.js +0 -24
- package/dist/session-cli.d.ts +0 -42
- package/dist/session-cli.js +0 -271
- package/dist/session-contract.d.ts +0 -183
- package/dist/session-contract.js +0 -122
- package/dist/session-remote.d.ts +0 -19
- package/dist/session-remote.js +0 -86
- package/dist/session-service.d.ts +0 -22
- package/dist/session-service.js +0 -157
- package/dist/team-cli.js +0 -692
package/dist/sleep.d.ts
ADDED
package/dist/sleep.js
ADDED
package/dist/store.d.ts
CHANGED
|
@@ -415,8 +415,6 @@ type CancellationTransition = {
|
|
|
415
415
|
changed: false;
|
|
416
416
|
reason: CancellationRefusal;
|
|
417
417
|
};
|
|
418
|
-
/** States from which no further work is dispatched. */
|
|
419
|
-
export declare const TERMINAL_STATES: readonly TaskState[];
|
|
420
418
|
export type Task = {
|
|
421
419
|
id: string;
|
|
422
420
|
title: string;
|
|
@@ -486,18 +484,6 @@ export type TaskRef = {
|
|
|
486
484
|
/** Recorded, not asserted: what the grant's selector is checked against. */
|
|
487
485
|
origin: TaskOrigin;
|
|
488
486
|
};
|
|
489
|
-
/** A standing order: a pre-approved template whose instances build unattended. */
|
|
490
|
-
export type ExecutionSlot = {
|
|
491
|
-
id: number;
|
|
492
|
-
runner: string;
|
|
493
|
-
state: "reserved" | "running" | "released";
|
|
494
|
-
run: number | null;
|
|
495
|
-
incarnation: string | null;
|
|
496
|
-
processGroup: number | null;
|
|
497
|
-
reservedAt: string;
|
|
498
|
-
runningAt: string | null;
|
|
499
|
-
releasedAt: string | null;
|
|
500
|
-
};
|
|
501
487
|
/** Chat providers are direct API adapters — a DISJOINT type from the build
|
|
502
488
|
* harness providers, by design (Codex v3 review, change 1). */
|
|
503
489
|
export type DirectChatProviderId = "anthropic-api" | "openrouter-api";
|
|
@@ -999,8 +985,6 @@ export type Capability = {
|
|
|
999
985
|
lastResult: string | null;
|
|
1000
986
|
expiresAt: string | null;
|
|
1001
987
|
};
|
|
1002
|
-
/** `kind:name`, the unambiguous way a requirement names a capability. */
|
|
1003
|
-
export declare function capabilityKey(capability: Pick<Capability, "kind" | "name">): string;
|
|
1004
988
|
/** Parse `kind:name`; a bare name is refused rather than guessed at. */
|
|
1005
989
|
export declare function parseCapabilityKey(key: string): {
|
|
1006
990
|
kind: Capability["kind"];
|
|
@@ -2297,7 +2281,6 @@ export declare class Store {
|
|
|
2297
2281
|
mirrorAllowsCompletion(taskId: string): boolean;
|
|
2298
2282
|
/** Whether a stored acquire mutation exists — the replay marker's fact. */
|
|
2299
2283
|
hasMutationRecord(mutation: Mutation): boolean;
|
|
2300
|
-
enqueueExternalIntent(mirror: string, kind: "comment" | "transition" | "close", body: string | null, now: Date): void;
|
|
2301
2284
|
pendingExternalIntents(limit?: number): {
|
|
2302
2285
|
id: number;
|
|
2303
2286
|
mirror: string;
|
|
@@ -4053,24 +4036,6 @@ export declare class Store {
|
|
|
4053
4036
|
liveClaimByLease(leaseId: string, now: Date): {
|
|
4054
4037
|
leaseId: string;
|
|
4055
4038
|
} | null;
|
|
4056
|
-
reserveExecutionSlots(runner: string, count: number, now: Date): number[];
|
|
4057
|
-
/** reserved → running happens in the stamp-before-spawn moment, carrying
|
|
4058
|
-
* the process group so recovery can ask the OS before freeing capacity. */
|
|
4059
|
-
markSlotRunning(id: number, facts: {
|
|
4060
|
-
run: number;
|
|
4061
|
-
incarnation?: string | null;
|
|
4062
|
-
processGroup?: number | null;
|
|
4063
|
-
}, now: Date): boolean;
|
|
4064
|
-
/** A correction process replaces the exited provider in the same open
|
|
4065
|
-
* root attempt. It may refresh only that attempt's exact occupied slot. */
|
|
4066
|
-
refreshSlotProcess(id: number, facts: {
|
|
4067
|
-
run: number;
|
|
4068
|
-
incarnation?: string | null;
|
|
4069
|
-
processGroup: number;
|
|
4070
|
-
}): boolean;
|
|
4071
|
-
releaseExecutionSlot(id: number, now: Date): boolean;
|
|
4072
|
-
liveSlotCount(runner: string): number;
|
|
4073
|
-
getExecutionSlot(id: number): ExecutionSlot | null;
|
|
4074
4039
|
/** Minted from a POST, never a GET. Bounded per approver; expired rows
|
|
4075
4040
|
* are swept rather than accumulating. */
|
|
4076
4041
|
mintCeremonyNonce(spec: {
|
|
@@ -4868,22 +4833,6 @@ export declare class Store {
|
|
|
4868
4833
|
listTasksScoped(repo: string | null, state: TaskState | undefined, limit: number, selectedId: string | null): (Task & {
|
|
4869
4834
|
repo: string | null;
|
|
4870
4835
|
})[];
|
|
4871
|
-
/**
|
|
4872
|
-
* The Work destination's one bounded page (workspace package 1 query):
|
|
4873
|
-
* the newest tasks the viewer may see, with the viewer's already-proved
|
|
4874
|
-
* admission bound BEFORE the ordering and the limit — never a wider
|
|
4875
|
-
* read post-filtered in the caller. `admitted` is the resolved
|
|
4876
|
-
* permitted repo set: `null` means unrestricted (every placed row),
|
|
4877
|
-
* `[]` means no placed project is permitted (no placed row at all).
|
|
4878
|
-
* `includeUnplaced` says whether NULL-repo rows belong to this viewer;
|
|
4879
|
-
* an account restricted to projects never sees them, so they must not
|
|
4880
|
-
* spend its page. Every predicate is a bound parameter; the limit is
|
|
4881
|
-
* clamped here, not trusted from the caller. Read-only; the legacy
|
|
4882
|
-
* `listTasksScoped` is untouched.
|
|
4883
|
-
*/
|
|
4884
|
-
listWorkTasksAdmitted(admitted: readonly string[] | null, includeUnplaced: boolean, limit: number): (Task & {
|
|
4885
|
-
repo: string | null;
|
|
4886
|
-
})[];
|
|
4887
4836
|
/** Newest first, because the question is almost always "what just happened". */
|
|
4888
4837
|
runsFor(taskRef: number): Run[];
|
|
4889
4838
|
/**
|
|
@@ -5309,7 +5258,6 @@ export declare class Store {
|
|
|
5309
5258
|
run: number;
|
|
5310
5259
|
kind: Incident["kind"];
|
|
5311
5260
|
}, now: Date): number;
|
|
5312
|
-
incidentForRun(run: number): Incident | null;
|
|
5313
5261
|
/** Unresolved, task attached, oldest first. No time window: these do not age out. */
|
|
5314
5262
|
openIncidents(repo?: string | null): (Incident & {
|
|
5315
5263
|
taskId: string;
|
|
@@ -5516,9 +5464,6 @@ export declare class Store {
|
|
|
5516
5464
|
claimMergeIntent(id: number, by: string, leaseMs: number, now: Date): {
|
|
5517
5465
|
generation: number;
|
|
5518
5466
|
} | null;
|
|
5519
|
-
/** Renew the lease AND re-prove the generation in one CAS — the last
|
|
5520
|
-
* gate before the external call; a failed re-proof aborts the attempt. */
|
|
5521
|
-
renewMergeClaim(id: number, generation: number, leaseMs: number, now: Date): boolean;
|
|
5522
5467
|
/** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
|
|
5523
5468
|
* state it believes it owns, and a terminal row is never overwritten —
|
|
5524
5469
|
* a stale claim owner cannot un-merge what the observer already settled,
|
|
@@ -5583,12 +5528,6 @@ export declare class Store {
|
|
|
5583
5528
|
lastError: string | null;
|
|
5584
5529
|
firingDeadline: string | null;
|
|
5585
5530
|
} | null;
|
|
5586
|
-
latestObservation(githubRepo: string, prNumber: number): {
|
|
5587
|
-
headSha: string;
|
|
5588
|
-
state: string;
|
|
5589
|
-
observedAt: string;
|
|
5590
|
-
generation: number;
|
|
5591
|
-
} | null;
|
|
5592
5531
|
/** Revocation is immediate: intents not yet pushed die with the grant. */
|
|
5593
5532
|
revokePublicationGrant(repo: string, by: string, now: Date): boolean;
|
|
5594
5533
|
publicationGrantFor(repo: string): PublicationGrant | null;
|
|
@@ -6408,7 +6347,6 @@ export declare class Store {
|
|
|
6408
6347
|
recentLeadTurns(approver: string, limit?: number): LeadTurn[];
|
|
6409
6348
|
getLeadTurn(id: number): LeadTurn | null;
|
|
6410
6349
|
liveLeadTurnFor(approver: string): LeadTurn | null;
|
|
6411
|
-
leadStepsOf(leadTurn: number): ChatTurn[];
|
|
6412
6350
|
/** Remember a project was opened. Upsert keeps added_at; recency always moves.
|
|
6413
6351
|
* A project added for the first time starts on Quick checks. */
|
|
6414
6352
|
upsertProject(path: string, name: string, now: Date, admission?: {
|
|
@@ -6469,17 +6407,6 @@ export declare class Store {
|
|
|
6469
6407
|
repo: string | null;
|
|
6470
6408
|
blockerRepo: string | null;
|
|
6471
6409
|
}[];
|
|
6472
|
-
/**
|
|
6473
|
-
* Active work only, running first — the Work tab's page. Terminal history
|
|
6474
|
-
* belongs to Done and the build ledger, never to this list.
|
|
6475
|
-
*/
|
|
6476
|
-
listActiveWorkScoped(repo: string | null, now: Date, limit?: number): (Task & {
|
|
6477
|
-
repo: string | null;
|
|
6478
|
-
approved: boolean;
|
|
6479
|
-
held: boolean;
|
|
6480
|
-
buildingBy: string | null;
|
|
6481
|
-
strikes: number;
|
|
6482
|
-
})[];
|
|
6483
6410
|
/**
|
|
6484
6411
|
* Completed work, one row per done task with its final accepted run and
|
|
6485
6412
|
* any publication attached — never composed from separate task and PR
|
package/dist/store.js
CHANGED
|
@@ -68,13 +68,13 @@ import { containerEmptiness } from "./container-state.js";
|
|
|
68
68
|
import { hasDisguisedText, hasForbiddenControls, validateNote } from "./decision.js";
|
|
69
69
|
import { parseReviewContext, reviewContextCustodyProblem } from "./review-context.js";
|
|
70
70
|
import { foldReview, manualReviewOnly } from "./proof.js";
|
|
71
|
-
import { approvalOf, digestOf, canonicalProfileJson, chainFromJson, profileDigestOf, profileFromJson, scopeAuthorityOf, routeParityProblem, parseAcceptanceCriteria, exactAcceptance, exactStringList, exactSafeIntegerOrNull
|
|
71
|
+
import { approvalOf, digestOf, canonicalProfileJson, chainFromJson, profileDigestOf, profileFromJson, scopeAuthorityOf, routeParityProblem, parseAcceptanceCriteria, exactAcceptance, exactStringList, exactSafeIntegerOrNull } from "./scope.js";
|
|
72
72
|
import { resolveScopeProfile, resolveRouteCandidates, exactPinOf, routeOfTask, agentChoicesFor } from "./agentconfig.js";
|
|
73
|
-
import { canonicalOverridesJson, canonicalRouteJson,
|
|
73
|
+
import { canonicalOverridesJson, canonicalRouteJson, isRiskLevel, isTaskSize, headroomFrom, makesNoPlan, legOf, overridesFromJson, phaseOfRole, recommendRoute, routeDigestOf, routeFromJson, routeProblems, routeStampProblem, ROUTE_ERA, PROVIDER_ID_LIST, } from "./phase-routing.js";
|
|
74
74
|
import { readAuthModeStrict } from "./keys.js";
|
|
75
75
|
import { modeDigestOf, modeTermsFromJson } from "./modes.js";
|
|
76
76
|
import { readVerifiedArtifact } from "./evidence.js";
|
|
77
|
-
import {
|
|
77
|
+
import {} from "./provider.js";
|
|
78
78
|
import { authenticate as runnerAuthenticate } from "./runner.js";
|
|
79
79
|
import { stampNewProjectLevel } from "./check-levels.js";
|
|
80
80
|
import { parseCheckProgressSnapshot } from "./check-progress.js";
|
|
@@ -1177,8 +1177,6 @@ CREATE INDEX IF NOT EXISTS sso_identity_account ON sso_identity (account);
|
|
|
1177
1177
|
*/
|
|
1178
1178
|
/** The backend name the built-in store registers itself under. */
|
|
1179
1179
|
export const BUILT_IN = "built-in";
|
|
1180
|
-
/** States from which no further work is dispatched. */
|
|
1181
|
-
export const TERMINAL_STATES = ["done", "failed", "cancelled"];
|
|
1182
1180
|
export const LEAD_THREAD = { kind: "lead" };
|
|
1183
1181
|
/** A lead_message row as a LeadMessage. */
|
|
1184
1182
|
function readLeadMessageRow(row) {
|
|
@@ -1298,10 +1296,6 @@ function readFlowReceipt(row) {
|
|
|
1298
1296
|
const optional = (key) => row[key] === null || row[key] === undefined ? null : String(row[key]);
|
|
1299
1297
|
return { state, card, note: optional("note"), at: String(row["at"]), acceptedAt: optional("accepted_at"), itemJson: optional("item_json") };
|
|
1300
1298
|
}
|
|
1301
|
-
/** `kind:name`, the unambiguous way a requirement names a capability. */
|
|
1302
|
-
export function capabilityKey(capability) {
|
|
1303
|
-
return `${capability.kind}:${capability.name}`;
|
|
1304
|
-
}
|
|
1305
1299
|
/** Parse `kind:name`; a bare name is refused rather than guessed at. */
|
|
1306
1300
|
export function parseCapabilityKey(key) {
|
|
1307
1301
|
const split = key.indexOf(":");
|
|
@@ -6413,11 +6407,6 @@ export class Store {
|
|
|
6413
6407
|
.get(mutation.idempotencyKey);
|
|
6414
6408
|
return row !== undefined;
|
|
6415
6409
|
}
|
|
6416
|
-
enqueueExternalIntent(mirror, kind, body, now) {
|
|
6417
|
-
this.db
|
|
6418
|
-
.prepare("INSERT INTO external_intent (mirror, kind, body, created_at) VALUES (?, ?, ?, ?)")
|
|
6419
|
-
.run(mirror, kind, body, now.toISOString());
|
|
6420
|
-
}
|
|
6421
6410
|
pendingExternalIntents(limit = 50) {
|
|
6422
6411
|
return this.db
|
|
6423
6412
|
.prepare("SELECT id, mirror, kind, body, attempts FROM external_intent WHERE state = 'pending' ORDER BY id LIMIT ?")
|
|
@@ -11423,54 +11412,6 @@ export class Store {
|
|
|
11423
11412
|
return row === undefined ? null : { leaseId: String(row["lease_id"]) };
|
|
11424
11413
|
}
|
|
11425
11414
|
// ---- worker-process slots (v14, finding 26) ----------------------------
|
|
11426
|
-
reserveExecutionSlots(runner, count, now) {
|
|
11427
|
-
return this.transact(() => {
|
|
11428
|
-
const ids = [];
|
|
11429
|
-
for (let index = 0; index < count; index++) {
|
|
11430
|
-
const inserted = this.db
|
|
11431
|
-
.prepare("INSERT INTO execution_slot (runner, reserved_at) VALUES (?, ?)")
|
|
11432
|
-
.run(runner, now.toISOString());
|
|
11433
|
-
ids.push(Number(inserted.lastInsertRowid));
|
|
11434
|
-
}
|
|
11435
|
-
return ids;
|
|
11436
|
-
});
|
|
11437
|
-
}
|
|
11438
|
-
/** reserved → running happens in the stamp-before-spawn moment, carrying
|
|
11439
|
-
* the process group so recovery can ask the OS before freeing capacity. */
|
|
11440
|
-
markSlotRunning(id, facts, now) {
|
|
11441
|
-
const changed = this.db
|
|
11442
|
-
.prepare(`UPDATE execution_slot SET state = 'running', run = ?, incarnation = ?, process_group = ?, running_at = ?
|
|
11443
|
-
WHERE id = ? AND state = 'reserved'`)
|
|
11444
|
-
.run(facts.run, facts.incarnation ?? null, facts.processGroup ?? null, now.toISOString(), id);
|
|
11445
|
-
return Number(changed.changes) === 1;
|
|
11446
|
-
}
|
|
11447
|
-
/** A correction process replaces the exited provider in the same open
|
|
11448
|
-
* root attempt. It may refresh only that attempt's exact occupied slot. */
|
|
11449
|
-
refreshSlotProcess(id, facts) {
|
|
11450
|
-
if (!Number.isInteger(facts.processGroup) || facts.processGroup <= 0)
|
|
11451
|
-
return false;
|
|
11452
|
-
const changed = this.db.prepare(`UPDATE execution_slot SET process_group = ?
|
|
11453
|
-
WHERE id = ? AND state = 'running' AND run = ? AND incarnation IS ?
|
|
11454
|
-
AND EXISTS (SELECT 1 FROM run WHERE id = ? AND outcome IS NULL)`)
|
|
11455
|
-
.run(facts.processGroup, id, facts.run, facts.incarnation ?? null, facts.run);
|
|
11456
|
-
return Number(changed.changes) === 1;
|
|
11457
|
-
}
|
|
11458
|
-
releaseExecutionSlot(id, now) {
|
|
11459
|
-
const changed = this.db
|
|
11460
|
-
.prepare("UPDATE execution_slot SET state = 'released', released_at = ? WHERE id = ? AND state IN ('reserved','running')")
|
|
11461
|
-
.run(now.toISOString(), id);
|
|
11462
|
-
return Number(changed.changes) === 1;
|
|
11463
|
-
}
|
|
11464
|
-
liveSlotCount(runner) {
|
|
11465
|
-
const row = this.db
|
|
11466
|
-
.prepare("SELECT COUNT(*) AS n FROM execution_slot WHERE runner = ? AND state IN ('reserved','running')")
|
|
11467
|
-
.get(runner);
|
|
11468
|
-
return Number(row?.["n"] ?? 0);
|
|
11469
|
-
}
|
|
11470
|
-
getExecutionSlot(id) {
|
|
11471
|
-
const row = this.db.prepare("SELECT * FROM execution_slot WHERE id = ?").get(id);
|
|
11472
|
-
return row === undefined ? null : readExecutionSlot(row);
|
|
11473
|
-
}
|
|
11474
11415
|
// ---- durable ceremony nonces (v14, findings 21/30) ---------------------
|
|
11475
11416
|
/** Minted from a POST, never a GET. Bounded per approver; expired rows
|
|
11476
11417
|
* are swept rather than accumulating. */
|
|
@@ -13528,40 +13469,6 @@ export class Store {
|
|
|
13528
13469
|
repo: row["task_repo"] === null ? null : String(row["task_repo"]),
|
|
13529
13470
|
}));
|
|
13530
13471
|
}
|
|
13531
|
-
/**
|
|
13532
|
-
* The Work destination's one bounded page (workspace package 1 query):
|
|
13533
|
-
* the newest tasks the viewer may see, with the viewer's already-proved
|
|
13534
|
-
* admission bound BEFORE the ordering and the limit — never a wider
|
|
13535
|
-
* read post-filtered in the caller. `admitted` is the resolved
|
|
13536
|
-
* permitted repo set: `null` means unrestricted (every placed row),
|
|
13537
|
-
* `[]` means no placed project is permitted (no placed row at all).
|
|
13538
|
-
* `includeUnplaced` says whether NULL-repo rows belong to this viewer;
|
|
13539
|
-
* an account restricted to projects never sees them, so they must not
|
|
13540
|
-
* spend its page. Every predicate is a bound parameter; the limit is
|
|
13541
|
-
* clamped here, not trusted from the caller. Read-only; the legacy
|
|
13542
|
-
* `listTasksScoped` is untouched.
|
|
13543
|
-
*/
|
|
13544
|
-
listWorkTasksAdmitted(admitted, includeUnplaced, limit) {
|
|
13545
|
-
const page = Math.max(1, Math.min(Math.floor(limit), 500));
|
|
13546
|
-
// SQLite accepts an empty IN list, so an empty admission binds as
|
|
13547
|
-
// "no placed row" without any special SQL shape.
|
|
13548
|
-
const rows = this.db
|
|
13549
|
-
.prepare(`SELECT task.*, task_ref.repo AS task_repo FROM task
|
|
13550
|
-
JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
|
|
13551
|
-
WHERE ((task_ref.repo IS NULL AND ? = 1)
|
|
13552
|
-
OR (task_ref.repo IS NOT NULL AND (? = 1 OR task_ref.repo IN (${(admitted ?? []).map(() => "?").join(",")}))))
|
|
13553
|
-
ORDER BY task.created_at DESC, task.id DESC LIMIT ?`)
|
|
13554
|
-
.all(BUILT_IN, includeUnplaced ? 1 : 0, admitted === null ? 1 : 0, ...(admitted ?? []), page);
|
|
13555
|
-
return rows.map(row => ({
|
|
13556
|
-
id: String(row["id"]),
|
|
13557
|
-
title: String(row["title"]),
|
|
13558
|
-
state: String(row["state"]),
|
|
13559
|
-
createdAt: String(row["created_at"]),
|
|
13560
|
-
updatedAt: String(row["updated_at"]),
|
|
13561
|
-
priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
|
|
13562
|
-
repo: row["task_repo"] === null ? null : String(row["task_repo"]),
|
|
13563
|
-
}));
|
|
13564
|
-
}
|
|
13565
13472
|
/** Newest first, because the question is almost always "what just happened". */
|
|
13566
13473
|
runsFor(taskRef) {
|
|
13567
13474
|
return this.db
|
|
@@ -14507,10 +14414,6 @@ export class Store {
|
|
|
14507
14414
|
.run(incident.run, incident.kind, now.toISOString());
|
|
14508
14415
|
return Number(inserted.lastInsertRowid);
|
|
14509
14416
|
}
|
|
14510
|
-
incidentForRun(run) {
|
|
14511
|
-
const row = this.db.prepare("SELECT * FROM incident WHERE run = ?").get(run);
|
|
14512
|
-
return row === undefined ? null : readIncident(row);
|
|
14513
|
-
}
|
|
14514
14417
|
/** Unresolved, task attached, oldest first. No time window: these do not age out. */
|
|
14515
14418
|
openIncidents(repo = null) {
|
|
14516
14419
|
return this.db
|
|
@@ -14872,14 +14775,6 @@ export class Store {
|
|
|
14872
14775
|
return Number(changes) === 1 ? { generation } : null;
|
|
14873
14776
|
});
|
|
14874
14777
|
}
|
|
14875
|
-
/** Renew the lease AND re-prove the generation in one CAS — the last
|
|
14876
|
-
* gate before the external call; a failed re-proof aborts the attempt. */
|
|
14877
|
-
renewMergeClaim(id, generation, leaseMs, now) {
|
|
14878
|
-
const { changes } = this.db
|
|
14879
|
-
.prepare("UPDATE merge_intent SET claimed_until = ? WHERE id = ? AND state = 'claimed' AND generation = ?")
|
|
14880
|
-
.run(new Date(now.getTime() + leaseMs).toISOString(), id, generation);
|
|
14881
|
-
return Number(changes) === 1;
|
|
14882
|
-
}
|
|
14883
14778
|
/** STATE-SPECIFIC and TERMINALLY MONOTONIC (E1): the writer names the
|
|
14884
14779
|
* state it believes it owns, and a terminal row is never overwritten —
|
|
14885
14780
|
* a stale claim owner cannot un-merge what the observer already settled,
|
|
@@ -15029,14 +14924,6 @@ export class Store {
|
|
|
15029
14924
|
firingDeadline: row["firing_deadline"] === null ? null : String(row["firing_deadline"]),
|
|
15030
14925
|
};
|
|
15031
14926
|
}
|
|
15032
|
-
latestObservation(githubRepo, prNumber) {
|
|
15033
|
-
const row = this.db
|
|
15034
|
-
.prepare("SELECT head_sha, state, observed_at, generation FROM ci_observation WHERE github_repo = ? AND pr_number = ?")
|
|
15035
|
-
.get(githubRepo, prNumber);
|
|
15036
|
-
return row === undefined || String(row["observed_at"]) === ""
|
|
15037
|
-
? null
|
|
15038
|
-
: { headSha: String(row["head_sha"]), state: String(row["state"]), observedAt: String(row["observed_at"]), generation: Number(row["generation"]) };
|
|
15039
|
-
}
|
|
15040
14927
|
/** Revocation is immediate: intents not yet pushed die with the grant. */
|
|
15041
14928
|
revokePublicationGrant(repo, by, now) {
|
|
15042
14929
|
const { changes } = this.db
|
|
@@ -16635,9 +16522,6 @@ export class Store {
|
|
|
16635
16522
|
const row = this.db.prepare("SELECT * FROM mate_turn WHERE approver = ? AND state IN ('queued','running') ORDER BY id DESC LIMIT 1").get(approver);
|
|
16636
16523
|
return row === undefined ? null : readLeadTurn(row);
|
|
16637
16524
|
}
|
|
16638
|
-
leadStepsOf(leadTurn) {
|
|
16639
|
-
return this.db.prepare("SELECT * FROM chat_turn WHERE mate_turn = ? ORDER BY id ASC").all(leadTurn).map(readChatTurn);
|
|
16640
|
-
}
|
|
16641
16525
|
// ---- projects ------------------------------------------------------------
|
|
16642
16526
|
/** Remember a project was opened. Upsert keeps added_at; recency always moves.
|
|
16643
16527
|
* A project added for the first time starts on Quick checks. */
|
|
@@ -16808,50 +16692,6 @@ export class Store {
|
|
|
16808
16692
|
blockerRepo: row["blocker_repo"] === null || row["blocker_repo"] === undefined ? null : String(row["blocker_repo"]),
|
|
16809
16693
|
}));
|
|
16810
16694
|
}
|
|
16811
|
-
/**
|
|
16812
|
-
* Active work only, running first — the Work tab's page. Terminal history
|
|
16813
|
-
* belongs to Done and the build ledger, never to this list.
|
|
16814
|
-
*/
|
|
16815
|
-
listActiveWorkScoped(repo, now, limit = 50) {
|
|
16816
|
-
const page = Math.max(1, Math.min(Math.floor(limit), 100));
|
|
16817
|
-
return this.db
|
|
16818
|
-
.prepare(`SELECT task.*, task_ref.repo AS task_repo, task_ref.strikes AS ref_strikes,
|
|
16819
|
-
EXISTS (
|
|
16820
|
-
SELECT 1 FROM task_scope
|
|
16821
|
-
WHERE task_scope.task_id = task.id AND task_scope.approved_digest = task_scope.digest
|
|
16822
|
-
AND task_scope.approved_at IS NOT NULL
|
|
16823
|
-
) AS approved,
|
|
16824
|
-
EXISTS (
|
|
16825
|
-
SELECT 1 FROM hold
|
|
16826
|
-
WHERE hold.task_ref = task_ref.id AND (hold.until IS NULL OR hold.until > ?)
|
|
16827
|
-
) AS held,
|
|
16828
|
-
(SELECT claim.runner FROM claim
|
|
16829
|
-
WHERE claim.task_ref = task_ref.id AND claim.released_at IS NULL AND claim.expires_at > ?
|
|
16830
|
-
AND claim.lease_generation = (
|
|
16831
|
-
SELECT MAX(newest.lease_generation) FROM claim AS newest
|
|
16832
|
-
WHERE newest.task_ref = claim.task_ref)
|
|
16833
|
-
LIMIT 1) AS building_by
|
|
16834
|
-
FROM task
|
|
16835
|
-
JOIN task_ref ON task_ref.backend = ? AND task_ref.external_id = task.id
|
|
16836
|
-
WHERE task.state IN ('running','queued')
|
|
16837
|
-
AND (? IS NULL OR task_ref.repo IS NULL OR task_ref.repo = ?)
|
|
16838
|
-
ORDER BY CASE task.state WHEN 'running' THEN 0 ELSE 1 END, task.updated_at DESC, task.id DESC
|
|
16839
|
-
LIMIT ?`)
|
|
16840
|
-
.all(now.toISOString(), now.toISOString(), BUILT_IN, repo, repo, page)
|
|
16841
|
-
.map(row => ({
|
|
16842
|
-
id: String(row["id"]),
|
|
16843
|
-
title: String(row["title"]),
|
|
16844
|
-
state: String(row["state"]),
|
|
16845
|
-
createdAt: String(row["created_at"]),
|
|
16846
|
-
updatedAt: String(row["updated_at"]),
|
|
16847
|
-
priority: row["priority"] === null || row["priority"] === undefined ? 0 : Number(row["priority"]),
|
|
16848
|
-
repo: row["task_repo"] === null ? null : String(row["task_repo"]),
|
|
16849
|
-
approved: Number(row["approved"]) === 1,
|
|
16850
|
-
held: Number(row["held"]) === 1,
|
|
16851
|
-
buildingBy: row["building_by"] === null ? null : String(row["building_by"]),
|
|
16852
|
-
strikes: Number(row["ref_strikes"]),
|
|
16853
|
-
}));
|
|
16854
|
-
}
|
|
16855
16695
|
/**
|
|
16856
16696
|
* Completed work, one row per done task with its final accepted run and
|
|
16857
16697
|
* any publication attached — never composed from separate task and PR
|
|
@@ -19544,20 +19384,6 @@ function readTaskRef(row) {
|
|
|
19544
19384
|
origin: String(row["origin"]) === "ours" ? "ours" : "theirs",
|
|
19545
19385
|
};
|
|
19546
19386
|
}
|
|
19547
|
-
function readExecutionSlot(row) {
|
|
19548
|
-
const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
|
|
19549
|
-
return {
|
|
19550
|
-
id: Number(row["id"]),
|
|
19551
|
-
runner: String(row["runner"]),
|
|
19552
|
-
state: String(row["state"]),
|
|
19553
|
-
run: row["run"] === null ? null : Number(row["run"]),
|
|
19554
|
-
incarnation: maybe("incarnation"),
|
|
19555
|
-
processGroup: row["process_group"] === null ? null : Number(row["process_group"]),
|
|
19556
|
-
reservedAt: String(row["reserved_at"]),
|
|
19557
|
-
runningAt: maybe("running_at"),
|
|
19558
|
-
releasedAt: maybe("released_at"),
|
|
19559
|
-
};
|
|
19560
|
-
}
|
|
19561
19387
|
function readChatTurn(row) {
|
|
19562
19388
|
const maybe = (key) => (row[key] === null || row[key] === undefined ? null : String(row[key]));
|
|
19563
19389
|
const maybeN = (key) => (row[key] === null || row[key] === undefined ? null : Number(row[key]));
|
|
@@ -20,7 +20,6 @@ export declare const REVIEW_OUTPUT_LIMITS: {
|
|
|
20
20
|
readonly path: 300;
|
|
21
21
|
};
|
|
22
22
|
export declare const REVIEW_NOTE_CODE_POINTS: number;
|
|
23
|
-
export declare const REVIEW_NOTE_GUIDANCE: string;
|
|
24
23
|
export type StructuredNormalization = {
|
|
25
24
|
text: string;
|
|
26
25
|
changed: boolean;
|
|
@@ -16,7 +16,6 @@ export const STRUCTURED_REPAIR_TIMEOUT_MS = 5 * 60_000;
|
|
|
16
16
|
* notes concise without imposing a second, stricter transport contract. */
|
|
17
17
|
export const REVIEW_OUTPUT_LIMITS = { comments: 40, criteria: 12, note: TEXT_LIMITS.reviewNote, path: TEXT_LIMITS.reviewPath };
|
|
18
18
|
export const REVIEW_NOTE_CODE_POINTS = Math.floor(REVIEW_OUTPUT_LIMITS.note / 2);
|
|
19
|
-
export const REVIEW_NOTE_GUIDANCE = `Keep each comment and criterion note to one concise finding and its evidence. Aim for ${REVIEW_NOTE_CODE_POINTS} characters or fewer; the hard limit is ${REVIEW_OUTPUT_LIMITS.note} UTF-16 units. Preserve the conclusion and any needed provenance; omit repeated rubric text.`;
|
|
20
19
|
/** Strip only unambiguous, whole-payload wrappers. */
|
|
21
20
|
export function normalizeStructuredJson(raw) {
|
|
22
21
|
let text = raw;
|
package/dist/subagent-work.d.ts
CHANGED
package/dist/subagent-work.js
CHANGED
|
@@ -304,5 +304,3 @@ export function answerSubagentQuestion(store, id, answer, now) {
|
|
|
304
304
|
return { ok: true, said: question.toolCall === null ? "Answered. It picks the card up again now." : choice?.id === APPROVE ? "Approved. The call is made now, exactly as shown." : "It won't make that call. It picks the card up again now." };
|
|
305
305
|
});
|
|
306
306
|
}
|
|
307
|
-
/** A card's link, for messages about it. */
|
|
308
|
-
export const subagentCardHref = (flow, card) => flowCardHref(flow, card);
|
package/dist/subagents.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { type CommandRunner } from "./claude-print.js";
|
|
2
2
|
import type { ContractResult } from "./contracts/contract.js";
|
|
3
3
|
import { type TurnAnswer } from "./contracts/subagent-turn.js";
|
|
4
4
|
import { type Overrun } from "./text-limits.js";
|
|
@@ -13,7 +13,6 @@ export type Soul = {
|
|
|
13
13
|
};
|
|
14
14
|
/** A handle from a name: "Maya" → "maya". */
|
|
15
15
|
export declare const handleOf: (name: string) => string;
|
|
16
|
-
export declare const isHandle: (value: unknown) => value is string;
|
|
17
16
|
/** A soul file read: its name and role (front matter) and its sections. */
|
|
18
17
|
export declare function parseSoul(text: string): {
|
|
19
18
|
ok: true;
|
|
@@ -139,7 +138,6 @@ export type TurnReply = ({
|
|
|
139
138
|
/** Runs one turn; injectable so tests never spend a subscription turn. */
|
|
140
139
|
export type TurnRunner = (request: TurnRequest) => Promise<TurnReply>;
|
|
141
140
|
export declare const TURN_TIMEOUT_MS = 180000;
|
|
142
|
-
type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
|
|
143
141
|
/** The production runner: Claude through this computer's sign-in, answering in the turn schema (TURN_MODEL_SCHEMA), with no tools, no MCP servers and no repository. */
|
|
144
142
|
export declare function claudeTurnRunner(runner?: CommandRunner): TurnRunner;
|
|
145
143
|
/** How a subagent is named to people: "Maya · Support". */
|
package/dist/subagents.js
CHANGED
|
@@ -17,21 +17,17 @@
|
|
|
17
17
|
* spending — those stay with people (or a signed hands-off mode).
|
|
18
18
|
*/
|
|
19
19
|
import { Buffer } from "node:buffer";
|
|
20
|
-
import { mkdtempSync, rmSync } from "node:fs";
|
|
21
|
-
import { tmpdir } from "node:os";
|
|
22
|
-
import { join } from "node:path";
|
|
23
20
|
import { strictJsonParse } from "./converse.js";
|
|
24
21
|
import { scanForSecrets } from "./evidence.js";
|
|
25
22
|
import { run } from "./exec.js";
|
|
23
|
+
import { CLAUDE_NO_TOOLS_ARGS, CLAUDE_SIGNED_OUT, claudeJsonBody, claudeModelArgs, inScratchDir } from "./claude-print.js";
|
|
26
24
|
import { ALL_CREDENTIAL_ENV } from "./provider.js";
|
|
27
25
|
import { readTurnAnswer, TURN_MODEL_SCHEMA } from "./contracts/subagent-turn.js";
|
|
28
26
|
import { LIMITS } from "./decision.js";
|
|
29
27
|
import { overruns, TEXT_LIMITS } from "./text-limits.js";
|
|
30
28
|
export const SOUL_CHARS = 12_000;
|
|
31
|
-
const HANDLE = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
32
29
|
/** A handle from a name: "Maya" → "maya". */
|
|
33
30
|
export const handleOf = (name) => name.toLowerCase().normalize("NFKD").replace(/[^a-z0-9]+/g, "-").replace(/^-+|-+$/g, "").slice(0, 32) || "subagent";
|
|
34
|
-
export const isHandle = (value) => typeof value === "string" && HANDLE.test(value);
|
|
35
31
|
/** A soul file read: its name and role (front matter) and its sections. */
|
|
36
32
|
export function parseSoul(text) {
|
|
37
33
|
const normal = text.replace(/\r\n?/g, "\n").trim();
|
|
@@ -220,36 +216,27 @@ export function readTurn(value, context) {
|
|
|
220
216
|
export const TURN_TIMEOUT_MS = 180_000;
|
|
221
217
|
/** The production runner: Claude through this computer's sign-in, answering in the turn schema (TURN_MODEL_SCHEMA), with no tools, no MCP servers and no repository. */
|
|
222
218
|
export function claudeTurnRunner(runner = run) {
|
|
223
|
-
return async (
|
|
224
|
-
const dir = mkdtempSync(join(tmpdir(), "standing-orders-subagent-"));
|
|
219
|
+
return request => inScratchDir("standing-orders-subagent-", async (dir) => {
|
|
225
220
|
const started = Date.now();
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
const body = parsed.ok && typeof parsed.value === "object" && parsed.value !== null && !Array.isArray(parsed.value) ? parsed.value : null;
|
|
238
|
-
if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success") {
|
|
239
|
-
const why = typeof body?.["subtype"] === "string" && body["subtype"] !== "success" ? ` (${String(body["subtype"]).replace(/_/g, " ").slice(0, 60)})` : result.code !== 0 ? ` (exit ${result.code})` : "";
|
|
240
|
-
return { ok: false, said: /not logged in|login|authenticat/i.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : `Claude couldn't decide${why}.` };
|
|
241
|
-
}
|
|
242
|
-
const cost = costOf(body);
|
|
243
|
-
if (body["structured_output"] !== undefined && body["structured_output"] !== null)
|
|
244
|
-
return { ok: true, value: body["structured_output"], ms: Date.now() - started, ...cost };
|
|
245
|
-
const text = typeof body["result"] === "string" ? body["result"].trim().replace(/^```(?:json)?\n?|\n?```$/g, "") : "";
|
|
246
|
-
const inner = strictJsonParse(Buffer.from(text, "utf8"), 64 * 1024, 8);
|
|
247
|
-
return inner.ok ? { ok: true, value: inner.value, ms: Date.now() - started, ...cost } : { ok: false, said: "Claude's answer wasn't a decision.", ...cost };
|
|
221
|
+
const result = await runner("claude", [
|
|
222
|
+
"-p", "--output-format", "json", "--json-schema", JSON.stringify(TURN_MODEL_SCHEMA), ...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
|
|
223
|
+
], { cwd: dir, stdin: request.prompt, timeoutMs: request.timeoutMs, maxBuffer: 512 * 1024, omitEnv: ALL_CREDENTIAL_ENV, processGroup: true });
|
|
224
|
+
if (result.notFound)
|
|
225
|
+
return { ok: false, said: "Claude isn't installed on this computer." };
|
|
226
|
+
if (result.timedOut)
|
|
227
|
+
return { ok: false, said: "Claude took too long to decide." };
|
|
228
|
+
const body = claudeJsonBody(result.stdout, 512 * 1024);
|
|
229
|
+
if (result.code !== 0 || body === null || body["is_error"] === true || body["subtype"] !== "success") {
|
|
230
|
+
const why = typeof body?.["subtype"] === "string" && body["subtype"] !== "success" ? ` (${String(body["subtype"]).replace(/_/g, " ").slice(0, 60)})` : result.code !== 0 ? ` (exit ${result.code})` : "";
|
|
231
|
+
return { ok: false, said: CLAUDE_SIGNED_OUT.test(`${result.stdout}${result.stderr}`) ? "Claude isn't signed in on this computer." : `Claude couldn't decide${why}.` };
|
|
248
232
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
233
|
+
const cost = costOf(body);
|
|
234
|
+
if (body["structured_output"] !== undefined && body["structured_output"] !== null)
|
|
235
|
+
return { ok: true, value: body["structured_output"], ms: Date.now() - started, ...cost };
|
|
236
|
+
const text = typeof body["result"] === "string" ? body["result"].trim().replace(/^```(?:json)?\n?|\n?```$/g, "") : "";
|
|
237
|
+
const inner = strictJsonParse(Buffer.from(text, "utf8"), 64 * 1024, 8);
|
|
238
|
+
return inner.ok ? { ok: true, value: inner.value, ms: Date.now() - started, ...cost } : { ok: false, said: "Claude's answer wasn't a decision.", ...cost };
|
|
239
|
+
});
|
|
253
240
|
}
|
|
254
241
|
/** What the CLI says a turn cost, and its tokens (cache reads and writes count as input). */
|
|
255
242
|
function costOf(body) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type LeadHistoryMessage, type LeadProviderAnswer, type LeadToolSchema } from "./converse.js";
|
|
2
|
-
import {
|
|
2
|
+
import { type CommandRunner } from "./claude-print.js";
|
|
3
3
|
import type { SubscriptionChatProviderId } from "./store.js";
|
|
4
4
|
export type SubscriptionLeadRequest = {
|
|
5
5
|
provider: SubscriptionChatProviderId;
|
|
@@ -27,7 +27,6 @@ export type SubscriptionLeadRunner = (request: SubscriptionLeadRequest) => Promi
|
|
|
27
27
|
ok: false;
|
|
28
28
|
problem: string;
|
|
29
29
|
}>;
|
|
30
|
-
type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
|
|
31
30
|
/** The model-visible request. Tool results are already redacted by leadView. */
|
|
32
31
|
export declare function composeSubscriptionLeadPrompt(request: Omit<SubscriptionLeadRequest, "provider" | "model" | "timeoutMs" | "signal">): string;
|
|
33
32
|
/** Strictly turn the harness's structured output into the provider-neutral answer. */
|
|
@@ -49,4 +48,3 @@ export declare function performSubscriptionLeadRequest(request: SubscriptionLead
|
|
|
49
48
|
ok: false;
|
|
50
49
|
problem: string;
|
|
51
50
|
}>;
|
|
52
|
-
export {};
|
|
@@ -16,6 +16,7 @@ import { tmpdir } from "node:os";
|
|
|
16
16
|
import { join } from "node:path";
|
|
17
17
|
import { LEAD_MAX_CALLS_PER_STEP, LEAD_STEP_TEXT_CAP_BYTES, LEAD_TOOL_CALL_CAP_BYTES, LEAD_TOOL_CALL_ID_CAP_BYTES, strictJsonParse, tokenCount, } from "./converse.js";
|
|
18
18
|
import { run } from "./exec.js";
|
|
19
|
+
import { CLAUDE_NO_TOOLS_ARGS, claudeModelArgs } from "./claude-print.js";
|
|
19
20
|
import { claudeStreamReader } from "./lead-progress.js";
|
|
20
21
|
import { ALL_CREDENTIAL_ENV } from "./provider.js";
|
|
21
22
|
import { claudeLimitsOf, noteLimits } from "./provider-limits.js";
|
|
@@ -215,9 +216,7 @@ export async function performSubscriptionLeadRequest(request, runner = run) {
|
|
|
215
216
|
// Streaming (someone is watching): the same answer, delivered as
|
|
216
217
|
// events whose final `result` line is the whole structured reply.
|
|
217
218
|
"-p", ...(streaming ? ["--output-format", "stream-json", "--verbose", "--include-partial-messages"] : ["--output-format", "json"]), "--json-schema", JSON.stringify(schema),
|
|
218
|
-
|
|
219
|
-
"--permission-prompts", "none", "--strict-mcp-config", "--mcp-config", '{"mcpServers":{}}',
|
|
220
|
-
...(request.model === "default" ? [] : ["--model", request.model]),
|
|
219
|
+
...CLAUDE_NO_TOOLS_ARGS, ...claudeModelArgs(request.model),
|
|
221
220
|
];
|
|
222
221
|
}
|
|
223
222
|
const result = await runner(command, args, {
|
package/dist/task-sizing.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type SizeAnswer } from "./contracts/task-sizing.js";
|
|
2
|
-
import {
|
|
2
|
+
import { type CommandRunner } from "./claude-print.js";
|
|
3
3
|
import { type TaskSizing } from "./phase-routing.js";
|
|
4
4
|
import type { Store } from "./store.js";
|
|
5
5
|
/** The classifier's whole budget, from asking to answer. */
|
|
@@ -24,7 +24,6 @@ export declare function planningSignals(input: SizingInput): boolean;
|
|
|
24
24
|
export declare function heuristicSizing(input: SizingInput, why?: string | null): TaskSizing;
|
|
25
25
|
/** What the classifier reads: the task as data, bounded, keys blanked. */
|
|
26
26
|
export declare function sizingText(input: SizingInput): string;
|
|
27
|
-
type CommandRunner = (file: string, args: readonly string[], options: Parameters<typeof run>[2]) => Promise<ExecResult>;
|
|
28
27
|
/** A small Claude model on this computer's sign-in: no tools, no MCP servers, no repository, credential keys stripped.
|
|
29
28
|
* The abort ends it: a late answer never keeps a command (or its process) waiting. */
|
|
30
29
|
export declare function claudeSizer(runner?: CommandRunner, model?: string, budgetMs?: number): Sizer;
|
|
@@ -41,8 +40,6 @@ export declare function classifyTask(input: SizingInput, sizer: Sizer | null, bu
|
|
|
41
40
|
/** Install the process's classifier for filings (the CLI, the console, the worker); returns how to remove it. Unset,
|
|
42
41
|
* filings keep the description's size — tests never spend a turn. */
|
|
43
42
|
export declare function installFilingSizer(sizer: Sizer, budgetMs?: number): () => void;
|
|
44
|
-
/** Whether filings in this process are classified. */
|
|
45
|
-
export declare function filingSizerInstalled(): boolean;
|
|
46
43
|
/**
|
|
47
44
|
* After a filing: ask the classifier (within the budget) and apply its size
|
|
48
45
|
* to the still-unapproved task. Runs in the background; the filing already
|