@event4u/agent-config 9.27.0 → 9.29.0
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/.claude-plugin/marketplace.json +1 -1
- package/AGENTS.md +13 -12
- package/CHANGELOG.md +165 -0
- package/README.md +1 -1
- package/agents/templates/.ai-council.yml.example +55 -24
- package/dist/agent-src/commands/analyze/conformance.md +24 -0
- package/dist/agent-src/commands/cost/report.md +2 -2
- package/dist/agent-src/commands/team/adversarial.md +8 -7
- package/dist/agent-src/commands/team/delegate.md +13 -12
- package/dist/agent-src/commands/team/review.md +9 -8
- package/dist/agent-src/commands/team/status.md +9 -8
- package/dist/agent-src/commands/team.md +29 -19
- package/dist/agent-src/contexts/execution/auto-dispatch-classification.md +88 -2
- package/dist/agent-src/contexts/execution/auto-orchestration-activation.md +29 -21
- package/dist/agent-src/contexts/execution/host-capability-manifest.md +26 -15
- package/dist/agent-src/contexts/execution/orchestration-telemetry.md +28 -3
- package/dist/agent-src/contexts/execution/subagent-response-contract.md +54 -0
- package/dist/agent-src/contexts/execution/subagent-routing.md +13 -11
- package/dist/agent-src/contexts/execution/subagent-spawn-contract.md +25 -0
- package/dist/agent-src/contexts/execution/subagent-steering.md +6 -3
- package/dist/agent-src/rules/artifact-engagement-recording.md +4 -1
- package/dist/agent-src/rules/autonomous-execution.md +1 -1
- package/dist/agent-src/rules/brand-source-of-truth.md +33 -6
- package/dist/agent-src/rules/context-hygiene.md +3 -1
- package/dist/agent-src/rules/council-availability.md +93 -0
- package/dist/agent-src/rules/cross-source-consistency.md +3 -0
- package/dist/agent-src/rules/delegation-policy.md +38 -10
- package/dist/agent-src/rules/design-fidelity.md +3 -0
- package/dist/agent-src/rules/evaluator-independence.md +2 -1
- package/dist/agent-src/rules/external-code-graph-interop.md +2 -1
- package/dist/agent-src/rules/finance-safety-floor.md +1 -1
- package/dist/agent-src/rules/git-history-discipline.md +1 -1
- package/dist/agent-src/rules/history-discipline.md +3 -1
- package/dist/agent-src/rules/legal-safety-floor.md +1 -1
- package/dist/agent-src/rules/no-pr-progress-comments.md +3 -1
- package/dist/agent-src/rules/onboarding-gate.md +3 -1
- package/dist/agent-src/rules/roadmap-ci-steps-policy.md +4 -1
- package/dist/agent-src/rules/role-mode-adherence.md +1 -1
- package/dist/agent-src/rules/scale-discipline.md +3 -1
- package/dist/agent-src/rules/self-repair-loop.md +103 -0
- package/dist/agent-src/rules/session-canary.md +2 -1
- package/dist/agent-src/rules/settings-ask-protocol.md +8 -7
- package/dist/agent-src/rules/strategy-safety-floor.md +1 -1
- package/dist/agent-src/rules/token-budget-discipline.md +4 -2
- package/dist/agent-src/rules/tool-safety.md +5 -1
- package/dist/agent-src/skills/adversarial-review/SKILL.md +1 -1
- package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +1 -1
- package/dist/agent-src/skills/forensics-report/SKILL.md +114 -0
- package/dist/agent-src/skills/forensics-report/evals/triggers.json +17 -0
- package/dist/agent-src/skills/performance-analysis/SKILL.md +1 -1
- package/dist/agent-src/skills/persona-improvement/SKILL.md +1 -1
- package/dist/agent-src/skills/premortem/SKILL.md +30 -1
- package/dist/agent-src/skills/project-analyzer/SKILL.md +1 -1
- package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +2 -1
- package/dist/agent-src/skills/security-audit/SKILL.md +1 -1
- package/dist/agent-src/skills/sequential-thinking/SKILL.md +1 -1
- package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +1 -1
- package/dist/agent-src/skills/subagent-orchestration/SKILL.md +7 -5
- package/dist/agent-src/skills/subagent-orchestration/schemas/subagent-status.json +61 -3
- package/dist/agent-src/skills/test-case-discovery/SKILL.md +1 -1
- package/dist/agent-src/skills/universal-project-analysis/SKILL.md +1 -1
- package/dist/agent-src/templates/AGENTS.md +8 -12
- package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
- package/dist/agent-src/templates/roadmaps.md +23 -0
- package/dist/cli/registry.js +7 -0
- package/dist/cli/registry.js.map +1 -1
- package/dist/cli-delegate/chunk-66OVWGB5.js +270 -0
- package/dist/cli-delegate/{chunk-HJ6DAJHR.js → chunk-LCFJIQ4J.js} +89 -7
- package/dist/cli-delegate/{chunk-VSYT7OHO.js → chunk-LVRYBKTI.js} +31 -2
- package/dist/cli-delegate/{chunk-DVRS2KVR.js → chunk-MMXA5GY7.js} +10 -17
- package/dist/cli-delegate/{chunk-WR6GTRHJ.js → chunk-MP3JT3IU.js} +3 -3
- package/dist/cli-delegate/{chunk-3KJIMFTB.js → chunk-NZ5N2XQL.js} +467 -305
- package/dist/cli-delegate/{chunk-AIIUU73N.js → chunk-OJM3MBJM.js} +1 -1
- package/dist/cli-delegate/{chunk-BCPIOAGV.js → chunk-RCIA67XN.js} +117 -96
- package/dist/cli-delegate/chunk-REKCMYOU.js +2991 -0
- package/dist/cli-delegate/cmd_analyze_session.js +1 -1
- package/dist/cli-delegate/cmd_brand_status.js +134 -0
- package/dist/cli-delegate/cmd_conformance.js +10 -47
- package/dist/cli-delegate/cmd_converge.js +3 -3
- package/dist/cli-delegate/cmd_doctor.js +10 -6
- package/dist/cli-delegate/cmd_explain.js +80 -330
- package/dist/cli-delegate/cmd_export.js +6 -6
- package/dist/cli-delegate/cmd_fleet.js +3 -3
- package/dist/cli-delegate/cmd_handoff.js +3 -3
- package/dist/cli-delegate/cmd_mcp_available.js +433 -0
- package/dist/cli-delegate/cmd_migrate.js +3 -3
- package/dist/cli-delegate/cmd_packs_active.js +153 -0
- package/dist/cli-delegate/cmd_preflight.js +1 -1
- package/dist/cli-delegate/cmd_prune.js +6 -6
- package/dist/cli-delegate/cmd_route_audit.js +8 -8
- package/dist/cli-delegate/cmd_route_explain.js +4 -4
- package/dist/cli-delegate/cmd_settings_get.js +266 -0
- package/dist/cli-delegate/cmd_settings_migrate.js +6 -6
- package/dist/cli-delegate/cmd_settings_set.js +8 -2968
- package/dist/cli-delegate/cmd_sync.js +6 -6
- package/dist/cli-delegate/cmd_uninstall.js +6 -6
- package/dist/cli-delegate/cmd_update.js +4 -4
- package/dist/cli-delegate/cmd_upgrade.js +4 -4
- package/dist/cli-delegate/cmd_validate.js +6 -6
- package/dist/cli-delegate/cmd_versions.js +4 -4
- package/dist/discovery/deprecation-report.md +1 -1
- package/dist/discovery/discovery-manifest.json +164 -55
- package/dist/discovery/discovery-manifest.json.sha256 +1 -1
- package/dist/discovery/discovery-manifest.summary.md +4 -3
- package/dist/discovery/orphan-report.md +1 -1
- package/dist/discovery/packs.json +44 -5
- package/dist/discovery/trust-report.md +11 -11
- package/dist/discovery/workspaces.json +16 -6
- package/dist/hooks/dispatch.js +9341 -6131
- package/dist/install/install.mjs +739 -524
- package/dist/mcp/registry-manifest.json +3 -3
- package/dist/mcp/server.json +2 -2
- package/dist/mcp/server.mjs +777 -281
- package/dist/router.json +1 -1
- package/dist/scripts/_lib/agent_settings.js +134 -15
- package/dist/scripts/_lib/agent_settings.js.map +1 -1
- package/dist/scripts/condense.js +147 -2
- package/dist/scripts/condense.js.map +1 -1
- package/dist/server/schemas/settings.js +6 -7
- package/dist/server/schemas/settings.js.map +1 -1
- package/dist/shared/settingsCarveOut.js +0 -9
- package/dist/shared/settingsCarveOut.js.map +1 -1
- package/dist/shared/settingsClasses.js +11 -9
- package/dist/shared/settingsClasses.js.map +1 -1
- package/dist/ui/assets/{index-DmR0mbk4.js → index-JDAF00bC.js} +2 -2
- package/dist/ui/assets/{index-DmR0mbk4.js.map → index-JDAF00bC.js.map} +1 -1
- package/dist/ui/index.html +1 -1
- package/docs/contracts/settings-classes.md +68 -17
- package/docs/guidelines/agent-infra/memory-access.md +14 -3
- package/package.json +1 -1
- package/src/agent-src/templates/AGENTS.md +8 -12
- package/src/config/agent-settings.template.yml +52 -66
- package/src/config/budgets.yml +29 -0
- package/src/config/discovery/packs.yml +11 -0
- package/src/config/discovery/workspaces.yml +1 -1
- package/src/config/evaluator-budgets.json +4 -4
- package/src/config/gate-coverage.yml +26 -0
- package/src/config/gate-violation-baselines.json +3 -3
- package/src/scripts/_cli/cmd_brand_status.ts +174 -0
- package/src/scripts/_cli/cmd_conformance.ts +14 -42
- package/src/scripts/_cli/cmd_doctor.ts +65 -48
- package/src/scripts/_cli/cmd_mcp_available.ts +266 -0
- package/src/scripts/_cli/cmd_packs_active.ts +225 -0
- package/src/scripts/_cli/cmd_settings_get.ts +324 -0
- package/src/scripts/_dispatch.bash +57 -0
- package/src/scripts/_lib/agent_settings.ts +140 -16
- package/src/scripts/_lib/auto_dispatch.corpus.test.ts +1 -1
- package/src/scripts/_lib/auto_dispatch.ts +23 -18
- package/src/scripts/_lib/capsule_trigger.ts +124 -0
- package/src/scripts/_lib/carrier_divergence.ts +135 -0
- package/src/scripts/_lib/host_capability.ts +144 -4
- package/src/scripts/_lib/judgment_ladder.ts +382 -0
- package/src/scripts/_lib/orchestration_gate.ts +8 -0
- package/src/scripts/_lib/orchestration_record.ts +37 -0
- package/src/scripts/_lib/orchestration_savings.ts +1 -1
- package/src/scripts/_lib/prompt_shape.ts +88 -0
- package/src/scripts/_lib/review_skipped_record.ts +102 -0
- package/src/scripts/_lib/rule_layer_overlap.ts +254 -0
- package/src/scripts/_lib/self_repair.ts +489 -0
- package/src/scripts/_lib/self_repair_store.ts +128 -0
- package/src/scripts/_lib/subagent_capsule.ts +182 -0
- package/src/scripts/_lib/subagent_response.ts +19 -0
- package/src/scripts/_lib/subagent_spawn.ts +13 -0
- package/src/scripts/_lib/subagent_steering.ts +9 -4
- package/src/scripts/_lib/tier_budget_routing.ts +6 -1
- package/src/scripts/_lib/transcript_entry.ts +80 -0
- package/src/scripts/_lib/worker_budget.ts +37 -2
- package/src/scripts/ai_council/clients.ts +76 -54
- package/src/scripts/ai_council/config.ts +94 -6
- package/src/scripts/ai_council/handoff.ts +113 -0
- package/src/scripts/ai_council/modes.ts +19 -4
- package/src/scripts/ai_council/orchestrator.ts +105 -0
- package/src/scripts/ai_council/quorum.ts +84 -0
- package/src/scripts/ai_council/session.ts +44 -0
- package/src/scripts/ai_council/transport_resolver.ts +127 -1
- package/src/scripts/ai_team/availability.ts +110 -0
- package/src/scripts/ai_team/config.ts +34 -14
- package/src/scripts/ai_team/team_dispatch.ts +71 -29
- package/src/scripts/bench_critic_protocol.ts +396 -0
- package/src/scripts/check_branch_freshness.ts +255 -0
- package/src/scripts/check_council_config_location.ts +125 -1
- package/src/scripts/check_detector_corpus.ts +202 -0
- package/src/scripts/check_hook_bundle_freshness.ts +4 -1
- package/src/scripts/check_standing_rule_delivery.ts +314 -0
- package/src/scripts/condense.ts +162 -2
- package/src/scripts/config/profiles.ts +13 -3
- package/src/scripts/conformance_scan.ts +272 -24
- package/src/scripts/council_availability_hook.ts +188 -0
- package/src/scripts/council_cli.ts +527 -32
- package/src/scripts/forensics_report.ts +333 -0
- package/src/scripts/hook_manifest.yaml +107 -26
- package/src/scripts/hooks/block_no_verify.ts +39 -2
- package/src/scripts/hooks/block_unauthorized_git.ts +156 -7
- package/src/scripts/hooks/concern_registry.ts +10 -0
- package/src/scripts/hooks/delegation_nudge_hook.ts +484 -0
- package/src/scripts/hooks/end_review_nudge_hook.ts +726 -0
- package/src/scripts/hooks/orchestration_record_hook.ts +342 -0
- package/src/scripts/install.ts +151 -0
- package/src/scripts/language_mirror_hook.ts +30 -37
- package/src/scripts/lint_discovery_vocabulary.ts +2 -0
- package/src/scripts/lint_never_silent.ts +276 -0
- package/src/scripts/lint_no_activation_gates.ts +271 -0
- package/src/scripts/measure_scope_dedup.ts +19 -13
- package/src/scripts/onboarding_gate_hook.ts +40 -1
- package/src/scripts/orchestration_record.ts +12 -1
- package/src/scripts/preamble_byte_census.ts +9 -20
- package/src/scripts/rebuild_hook_bundle.ts +177 -0
- package/src/scripts/release.ts +74 -2
- package/src/scripts/report_carrier_divergence.ts +364 -0
- package/src/scripts/report_skill_activation.ts +257 -0
- package/src/scripts/report_skill_obligation_violations.ts +579 -0
- package/src/scripts/routing_doctor.ts +95 -39
- package/src/scripts/score_skill_selection.ts +19 -5
- package/src/scripts/self_repair_cli.ts +470 -0
- package/src/scripts/self_repair_hook.ts +241 -0
- package/src/scripts/team_events_spike.ts +271 -0
- package/src/scripts/team_review_gate_hook.ts +31 -9
- package/src/server/schemas/settings.ts +10 -17
- package/src/shared/settingsCarveOut.ts +0 -10
- package/src/shared/settingsClasses.ts +11 -9
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Worker-generation CHECKPOINT capsule (road-to-worker-generation-recycling, Phase 0).
|
|
3
|
+
*
|
|
4
|
+
* Pure, no-I/O. The structured state a worker emits BELOW its stop-loss
|
|
5
|
+
* watermark so a successor generation can continue the SAME task from the
|
|
6
|
+
* capsule alone — never from the transcript, never from an orchestrator-written
|
|
7
|
+
* re-brief. Today a worker that reaches `max_tokens_per_worker` is killed
|
|
8
|
+
* (`worker_budget.ts`) and its partial result returns as a `BLOCKED` envelope;
|
|
9
|
+
* there is no handoff. This is the handoff shape.
|
|
10
|
+
*
|
|
11
|
+
* TRANSCRIPT-EXCLUSION BY CONSTRUCTION: every field is a ref token, a single
|
|
12
|
+
* short line, or a count — there is NO field capable of holding a transcript,
|
|
13
|
+
* a file body, or prose at length, and the per-array caps mean a capsule cannot
|
|
14
|
+
* become one by accumulation either. This is not stylistic. A capsule that
|
|
15
|
+
* could smuggle raw context would make the successor's brief unmeasurable,
|
|
16
|
+
* which is the whole question the roadmap's claim asks. Do not add a free-form
|
|
17
|
+
* field. (Same principle as `orchestration_record.ts` for telemetry and
|
|
18
|
+
* `domain-safety-pii` § Surface 2 for logs.)
|
|
19
|
+
*
|
|
20
|
+
* Contract: `src/agent-src/contexts/execution/subagent-response-contract.md`
|
|
21
|
+
* Wire format: `src/skills/subagent-orchestration/schemas/subagent-status.json`
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Epistemic vocabulary for `assumptions[].epistemic_state` — pinned ONCE, here,
|
|
26
|
+
* to the three Evidence-Report buckets already in use for docs and discovery
|
|
27
|
+
* (`evidence-discipline.md` § Evidence Report). A capsule that graded its
|
|
28
|
+
* assumptions on a private scale would fork the vocabulary the rest of the
|
|
29
|
+
* suite reasons in, so it does not get one.
|
|
30
|
+
*
|
|
31
|
+
* - `verified` — confirmed against a real source during THIS worker generation.
|
|
32
|
+
* - `assumed` — taken as a premise, not confirmed; explicitly a hypothesis.
|
|
33
|
+
* - `gap` — known missing evidence the task needs.
|
|
34
|
+
*/
|
|
35
|
+
export const EPISTEMIC_STATES = ['verified', 'assumed', 'gap'] as const;
|
|
36
|
+
export type EpistemicState = (typeof EPISTEMIC_STATES)[number];
|
|
37
|
+
|
|
38
|
+
const EPISTEMIC: ReadonlySet<string> = new Set<string>(EPISTEMIC_STATES);
|
|
39
|
+
|
|
40
|
+
/** Max chars for a ref token (`file:line`, id, path). Mirrors the spawn contract. */
|
|
41
|
+
export const MAX_REF_CHARS = 200;
|
|
42
|
+
/** Max chars for one capsule sentence. A paragraph does not fit; that is the point. */
|
|
43
|
+
export const MAX_LINE_CHARS = 240;
|
|
44
|
+
/** Max entries per capsule array. A transcript cannot be reached by accumulation. */
|
|
45
|
+
export const MAX_ENTRIES = 40;
|
|
46
|
+
|
|
47
|
+
/** One stated premise the successor generation inherits instead of re-deriving. */
|
|
48
|
+
export interface CapsuleAssumption {
|
|
49
|
+
/** The premise, one line. */
|
|
50
|
+
statement: string;
|
|
51
|
+
/** What it rests on — a ref token (`file:line`, id, path, command). */
|
|
52
|
+
basis: string;
|
|
53
|
+
/** How well it is established. See {@link EPISTEMIC_STATES}. */
|
|
54
|
+
epistemic_state: EpistemicState;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The capsule a worker emits at its watermark. Rides as the body of a
|
|
59
|
+
* `CHECKPOINT` envelope (`subagent-status.json`).
|
|
60
|
+
*/
|
|
61
|
+
export interface WorkerCapsule {
|
|
62
|
+
/** One- or two-sentence outcome so far. */
|
|
63
|
+
summary: string;
|
|
64
|
+
/** Generation index in the chain; the first dispatch is 1. */
|
|
65
|
+
generation: number;
|
|
66
|
+
/** What is finished — ref tokens, never bodies. */
|
|
67
|
+
done: string[];
|
|
68
|
+
/** What is left, one short line each. */
|
|
69
|
+
remaining: string[];
|
|
70
|
+
/** Choices already made that the successor must not silently re-open. */
|
|
71
|
+
decisions: string[];
|
|
72
|
+
/** Known risks still open. */
|
|
73
|
+
open_risks: string[];
|
|
74
|
+
/** Files this generation touched — paths / `file:line`, never diffs. */
|
|
75
|
+
touched_files: string[];
|
|
76
|
+
/**
|
|
77
|
+
* Stated premises. Unstated assumptions are the first thing compression
|
|
78
|
+
* drops, which makes them the most likely mechanism behind a degraded
|
|
79
|
+
* capsule — the field gives the successor a target list instead of
|
|
80
|
+
* implicit premises.
|
|
81
|
+
*/
|
|
82
|
+
assumptions: CapsuleAssumption[];
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/** A single-line token no longer than `max` chars. Rejects any body-shaped value. */
|
|
86
|
+
function isShortLine(value: unknown, max: number): value is string {
|
|
87
|
+
return typeof value === 'string' && value.length > 0 && value.length <= max && !value.includes('\n');
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function checkList(
|
|
91
|
+
errors: string[],
|
|
92
|
+
field: string,
|
|
93
|
+
value: unknown,
|
|
94
|
+
max: number,
|
|
95
|
+
required: boolean,
|
|
96
|
+
): void {
|
|
97
|
+
if (value === undefined) {
|
|
98
|
+
if (required) errors.push(`${field} is required`);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (!Array.isArray(value)) {
|
|
102
|
+
errors.push(`${field} must be an array`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
if (value.length > MAX_ENTRIES) {
|
|
106
|
+
errors.push(`${field} carries ${value.length} entries (max ${MAX_ENTRIES}) — a capsule is a handoff, not a transcript`);
|
|
107
|
+
}
|
|
108
|
+
const bad = value.filter((x) => !isShortLine(x, max));
|
|
109
|
+
if (bad.length > 0) {
|
|
110
|
+
errors.push(
|
|
111
|
+
`${field} carries ${bad.length} entr${bad.length === 1 ? 'y' : 'ies'} that are not single lines of ≤ ${max} chars (refs and short lines only, never bodies)`,
|
|
112
|
+
);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Validate a capsule body. Returns the list of violations (empty = valid).
|
|
118
|
+
*
|
|
119
|
+
* The orchestrator never briefs a successor from an invalid capsule — an
|
|
120
|
+
* invalid capsule falls back to today's stop-loss behaviour, loudly.
|
|
121
|
+
*/
|
|
122
|
+
export function validateCapsule(input: unknown): string[] {
|
|
123
|
+
const errors: string[] = [];
|
|
124
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
125
|
+
return ['not an object'];
|
|
126
|
+
}
|
|
127
|
+
const c = input as Record<string, unknown>;
|
|
128
|
+
|
|
129
|
+
if (!isShortLine(c['summary'], MAX_LINE_CHARS)) {
|
|
130
|
+
errors.push(`summary must be a single line of 1–${MAX_LINE_CHARS} chars`);
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
const generation = c['generation'];
|
|
134
|
+
if (typeof generation !== 'number' || !Number.isInteger(generation) || generation < 1) {
|
|
135
|
+
errors.push('generation must be an integer ≥ 1 (the first dispatch is generation 1)');
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
checkList(errors, 'done', c['done'], MAX_REF_CHARS, true);
|
|
139
|
+
checkList(errors, 'remaining', c['remaining'], MAX_LINE_CHARS, true);
|
|
140
|
+
checkList(errors, 'decisions', c['decisions'], MAX_LINE_CHARS, false);
|
|
141
|
+
checkList(errors, 'open_risks', c['open_risks'], MAX_LINE_CHARS, false);
|
|
142
|
+
checkList(errors, 'touched_files', c['touched_files'], MAX_REF_CHARS, false);
|
|
143
|
+
|
|
144
|
+
const assumptions = c['assumptions'];
|
|
145
|
+
if (assumptions !== undefined) {
|
|
146
|
+
if (!Array.isArray(assumptions)) {
|
|
147
|
+
errors.push('assumptions must be an array');
|
|
148
|
+
} else {
|
|
149
|
+
if (assumptions.length > MAX_ENTRIES) {
|
|
150
|
+
errors.push(`assumptions carries ${assumptions.length} entries (max ${MAX_ENTRIES})`);
|
|
151
|
+
}
|
|
152
|
+
for (const [i, raw] of assumptions.entries()) {
|
|
153
|
+
errors.push(...validateAssumption(raw, `assumptions[${i}]`));
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
return errors;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Validate one `{statement, basis, epistemic_state}` triple. Exported because
|
|
163
|
+
* the worker RESULT envelope carries the same field (`subagent_response.ts`) —
|
|
164
|
+
* one shape, one validator, so the two cannot drift.
|
|
165
|
+
*/
|
|
166
|
+
export function validateAssumption(input: unknown, label = 'assumption'): string[] {
|
|
167
|
+
const errors: string[] = [];
|
|
168
|
+
if (typeof input !== 'object' || input === null || Array.isArray(input)) {
|
|
169
|
+
return [`${label} is not an object`];
|
|
170
|
+
}
|
|
171
|
+
const a = input as Record<string, unknown>;
|
|
172
|
+
if (!isShortLine(a['statement'], MAX_LINE_CHARS)) {
|
|
173
|
+
errors.push(`${label}.statement must be a single line of 1–${MAX_LINE_CHARS} chars`);
|
|
174
|
+
}
|
|
175
|
+
if (!isShortLine(a['basis'], MAX_REF_CHARS)) {
|
|
176
|
+
errors.push(`${label}.basis must be a ref token (file:line, id, path, command) of ≤ ${MAX_REF_CHARS} chars`);
|
|
177
|
+
}
|
|
178
|
+
if (typeof a['epistemic_state'] !== 'string' || !EPISTEMIC.has(a['epistemic_state'])) {
|
|
179
|
+
errors.push(`${label}.epistemic_state must be one of ${EPISTEMIC_STATES.join(' | ')}`);
|
|
180
|
+
}
|
|
181
|
+
return errors;
|
|
182
|
+
}
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* Contract: `src/agent-src/contexts/execution/subagent-response-contract.md`.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
+
import { validateAssumption, type CapsuleAssumption } from './subagent_capsule.js';
|
|
13
|
+
|
|
12
14
|
export type Confidence = 'low' | 'medium' | 'high';
|
|
13
15
|
|
|
14
16
|
export interface Finding {
|
|
@@ -25,6 +27,14 @@ export interface SubagentResponse {
|
|
|
25
27
|
risks: string[];
|
|
26
28
|
confidence: Confidence;
|
|
27
29
|
handoff: string;
|
|
30
|
+
/**
|
|
31
|
+
* Premises the worker acted on, `{statement, basis, epistemic_state}` —
|
|
32
|
+
* the same shape and the same validator as the CHECKPOINT capsule
|
|
33
|
+
* (`subagent_capsule.ts`), so the completed-result and handoff surfaces
|
|
34
|
+
* cannot drift apart. Optional: absent means not recorded, which is not
|
|
35
|
+
* the same claim as "no assumptions were made".
|
|
36
|
+
*/
|
|
37
|
+
assumptions?: CapsuleAssumption[];
|
|
28
38
|
}
|
|
29
39
|
|
|
30
40
|
const CONFIDENCE: ReadonlySet<string> = new Set<Confidence>(['low', 'medium', 'high']);
|
|
@@ -55,6 +65,15 @@ export function validateResponse(input: unknown): ValidationResult {
|
|
|
55
65
|
}
|
|
56
66
|
}
|
|
57
67
|
}
|
|
68
|
+
if (r.assumptions !== undefined) {
|
|
69
|
+
if (!Array.isArray(r.assumptions)) {
|
|
70
|
+
errors.push('assumptions must be an array of {statement, basis, epistemic_state}');
|
|
71
|
+
} else {
|
|
72
|
+
for (const [i, a] of (r.assumptions as unknown[]).entries()) {
|
|
73
|
+
errors.push(...validateAssumption(a, `assumptions[${i}]`));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
58
77
|
return { valid: errors.length === 0, errors };
|
|
59
78
|
}
|
|
60
79
|
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
|
|
14
14
|
import * as crypto from 'node:crypto';
|
|
15
15
|
|
|
16
|
+
import { CAPSULE_WATERMARK_FRACTION } from './worker_budget.js';
|
|
17
|
+
|
|
16
18
|
export type RoleMode = 'developer' | 'reviewer' | 'tester' | 'po' | 'incident' | 'planner';
|
|
17
19
|
|
|
18
20
|
const ROLE_MODES: ReadonlySet<string> = new Set<RoleMode>([
|
|
@@ -55,6 +57,12 @@ export interface SpawnBrief {
|
|
|
55
57
|
knowledge_refs: string[];
|
|
56
58
|
/** Per-worker token stop-loss; null = unset (legacy dispatch). */
|
|
57
59
|
max_tokens_per_worker: number | null;
|
|
60
|
+
/**
|
|
61
|
+
* Token count at which the worker emits a CHECKPOINT capsule — DERIVED from
|
|
62
|
+
* `max_tokens_per_worker`, never set independently, so the watermark cannot
|
|
63
|
+
* drift away from the budget it sits under. Null when no budget is set.
|
|
64
|
+
*/
|
|
65
|
+
capsule_watermark: number | null;
|
|
58
66
|
warnings: string[];
|
|
59
67
|
}
|
|
60
68
|
|
|
@@ -112,6 +120,10 @@ export function composeSpawnBrief(sel: SpawnSelection): SpawnBrief {
|
|
|
112
120
|
personas,
|
|
113
121
|
knowledge_refs,
|
|
114
122
|
max_tokens_per_worker,
|
|
123
|
+
capsule_watermark:
|
|
124
|
+
max_tokens_per_worker === null
|
|
125
|
+
? null
|
|
126
|
+
: Math.floor(max_tokens_per_worker * CAPSULE_WATERMARK_FRACTION),
|
|
115
127
|
warnings,
|
|
116
128
|
};
|
|
117
129
|
}
|
|
@@ -133,6 +145,7 @@ export function serializeSpawnPayload(brief: SpawnBrief): string {
|
|
|
133
145
|
profile: brief.profile,
|
|
134
146
|
personas: brief.personas,
|
|
135
147
|
max_tokens_per_worker: brief.max_tokens_per_worker,
|
|
148
|
+
capsule_watermark: brief.capsule_watermark,
|
|
136
149
|
});
|
|
137
150
|
const variableTail = JSON.stringify({
|
|
138
151
|
task: brief.task,
|
|
@@ -26,14 +26,19 @@ export const GUARDRAILS = {
|
|
|
26
26
|
user_override_rate: 0.3,
|
|
27
27
|
} as const;
|
|
28
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Always-on orchestration (road-to-always-on-orchestration Phase 1) removed
|
|
31
|
+
* the `enabled`/`auto` settings this state used to carry — the only
|
|
32
|
+
* surviving switch is the audited incident halt.
|
|
33
|
+
*/
|
|
29
34
|
export interface LayerState {
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
/** `emergency.orchestration_halt`. */
|
|
36
|
+
halted: boolean;
|
|
32
37
|
}
|
|
33
38
|
|
|
34
|
-
/** The kill-switch: layer is disabled
|
|
39
|
+
/** The kill-switch: layer is disabled only during an active emergency halt. */
|
|
35
40
|
export function isLayerDisabled(state: LayerState): boolean {
|
|
36
|
-
return
|
|
41
|
+
return state.halted;
|
|
37
42
|
}
|
|
38
43
|
|
|
39
44
|
/** N=3 per-target budget: halt once consecutive failed attempts reach the cap. */
|
|
@@ -43,7 +43,12 @@ export interface PickTierInputs {
|
|
|
43
43
|
adequate_tier: BudgetTier;
|
|
44
44
|
/** Per-tier budget state, complete over TIER_ORDER. */
|
|
45
45
|
budgets: Record<BudgetTier, TierBudgetState>;
|
|
46
|
-
/**
|
|
46
|
+
/**
|
|
47
|
+
* Caller-supplied switch. Formerly sourced from the `subagents.budget_routing`
|
|
48
|
+
* settings key, deleted by always-on orchestration (Phase 1) — this
|
|
49
|
+
* function has no production caller today, so the field stays as the
|
|
50
|
+
* DESIGNED input shape; a future wiring supplies its own source.
|
|
51
|
+
*/
|
|
47
52
|
routing_switch: BudgetRoutingSwitch;
|
|
48
53
|
/** Estimated cost of the dispatch (USD) for the availability check. */
|
|
49
54
|
estimated_cost_usd: number;
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One reader for a transcript entry's text — the shape half, shared.
|
|
3
|
+
*
|
|
4
|
+
* WHY THIS EXISTS, measured rather than anticipated. A Claude Code transcript
|
|
5
|
+
* carries a user entry's `message.content` in TWO shapes: a bare string, and an
|
|
6
|
+
* array of content blocks. `conformance_scan` handled both; a second reader
|
|
7
|
+
* written against the same field handled only the string, and the store says why
|
|
8
|
+
* that is fatal rather than cosmetic:
|
|
9
|
+
*
|
|
10
|
+
* user entries in one 30-session store: 1 440 string · 23 907 array
|
|
11
|
+
* injected skill bodies among them: 0 via string · 41 via array
|
|
12
|
+
*
|
|
13
|
+
* So the narrower reader saw **none** of them, and the failure was invisible:
|
|
14
|
+
* a detector whose loaded-set is empty returns no findings, which is
|
|
15
|
+
* indistinguishable from compliance. `grep` over the raw JSONL finds the marker
|
|
16
|
+
* either way — reading raw text is not evidence about the parse path, and that
|
|
17
|
+
* is the mistake this module removes the opportunity to repeat.
|
|
18
|
+
*
|
|
19
|
+
* Scope is deliberately just the shape, plus the sidechain exclusion. Semantic
|
|
20
|
+
* filters (a `<system-reminder>` is not a chat message, an injected body is not a
|
|
21
|
+
* user turn) stay with the caller that needs them: they differ per question, and
|
|
22
|
+
* folding them in here would make one module answer two.
|
|
23
|
+
*/
|
|
24
|
+
|
|
25
|
+
/** A parsed transcript line. */
|
|
26
|
+
export type TranscriptEntry = Record<string, unknown>;
|
|
27
|
+
|
|
28
|
+
function _isObject(v: unknown): v is Record<string, unknown> {
|
|
29
|
+
return typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* A subagent's own turns. Excluded by every reader in this tree: a sidechain turn
|
|
34
|
+
* did not happen in the main thread, so counting it lets a skill loaded in one
|
|
35
|
+
* context be paired with an act taken in another.
|
|
36
|
+
*/
|
|
37
|
+
export function isSidechain(entry: TranscriptEntry): boolean {
|
|
38
|
+
return entry['isSidechain'] === true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Flatten `message.content` to text, whichever shape it arrived in.
|
|
43
|
+
*
|
|
44
|
+
* Returns `''` when there is no text (a tool-result-only entry, an unparseable
|
|
45
|
+
* shape) — never `null`, so a caller cannot forget the second branch.
|
|
46
|
+
*/
|
|
47
|
+
export function entryText(entry: TranscriptEntry): string {
|
|
48
|
+
const msg = entry['message'];
|
|
49
|
+
const content = _isObject(msg) ? msg['content'] : undefined;
|
|
50
|
+
if (typeof content === 'string') {
|
|
51
|
+
return content;
|
|
52
|
+
}
|
|
53
|
+
if (!Array.isArray(content)) {
|
|
54
|
+
return '';
|
|
55
|
+
}
|
|
56
|
+
return content
|
|
57
|
+
.filter((b) => _isObject(b) && b['type'] === 'text')
|
|
58
|
+
.map((b) => String((b as Record<string, unknown>)['text'] ?? ''))
|
|
59
|
+
.join('\n');
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Tool calls in an entry, flattened to name + input. Both shapes are arrays. */
|
|
63
|
+
export function toolUses(entry: TranscriptEntry): Array<{ name: string; input: Record<string, unknown> }> {
|
|
64
|
+
const msg = entry['message'];
|
|
65
|
+
const content = _isObject(msg) ? msg['content'] : undefined;
|
|
66
|
+
if (!Array.isArray(content)) {
|
|
67
|
+
return [];
|
|
68
|
+
}
|
|
69
|
+
const out: Array<{ name: string; input: Record<string, unknown> }> = [];
|
|
70
|
+
for (const part of content) {
|
|
71
|
+
if (!_isObject(part) || part['type'] !== 'tool_use') {
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
out.push({
|
|
75
|
+
name: typeof part['name'] === 'string' ? part['name'] : '',
|
|
76
|
+
input: _isObject(part['input']) ? part['input'] : {},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
return out;
|
|
80
|
+
}
|
|
@@ -35,6 +35,24 @@ export function budgetForTier(tier: Tier, sessionTier: Exclude<Tier, 'inherit'>
|
|
|
35
35
|
return MAX_TOKENS_PER_WORKER[effective];
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
/**
|
|
39
|
+
* Fraction of the stop-loss budget at which a worker emits its CHECKPOINT
|
|
40
|
+
* capsule (road-to-worker-generation-recycling, Phase 1).
|
|
41
|
+
*
|
|
42
|
+
* The headroom IS the mechanism: a worker at 100 % of its budget cannot
|
|
43
|
+
* summarise itself, so the watermark sits below the kill line rather than on
|
|
44
|
+
* it. A start value, not a tuned one — Phase 1 measures it in shadow against a
|
|
45
|
+
* second trigger arm before anything acts on it, and `blocker:
|
|
46
|
+
* capsule-quality-near-budget` exists because a bad watermark and a bad
|
|
47
|
+
* mechanism look identical from one sample.
|
|
48
|
+
*/
|
|
49
|
+
export const CAPSULE_WATERMARK_FRACTION = 0.8;
|
|
50
|
+
|
|
51
|
+
/** Token count at which a worker of this tier emits its capsule. */
|
|
52
|
+
export function watermarkForTier(tier: Tier, sessionTier: Exclude<Tier, 'inherit'> = 'high'): number {
|
|
53
|
+
return Math.floor(budgetForTier(tier, sessionTier) * CAPSULE_WATERMARK_FRACTION);
|
|
54
|
+
}
|
|
55
|
+
|
|
38
56
|
/** Where the orchestrator should send the task after a budget hit. */
|
|
39
57
|
export type NextRung = 'primitive' | 'higher-tier-subagent' | 'in-session';
|
|
40
58
|
|
|
@@ -64,19 +82,36 @@ export interface BudgetEvaluation {
|
|
|
64
82
|
budget_hit: boolean;
|
|
65
83
|
consumed: number;
|
|
66
84
|
budget: number;
|
|
85
|
+
/** Token count at which the CHECKPOINT capsule is due (below the kill line). */
|
|
86
|
+
watermark: number;
|
|
87
|
+
/** Consumption reached the watermark but not yet the stop-loss. */
|
|
88
|
+
watermark_hit: boolean;
|
|
67
89
|
reason: string;
|
|
68
90
|
}
|
|
69
91
|
|
|
70
|
-
/**
|
|
92
|
+
/**
|
|
93
|
+
* Evaluate consumption against the worker's budget.
|
|
94
|
+
*
|
|
95
|
+
* Two lines, not one: the **watermark** (emit a capsule, still working) and the
|
|
96
|
+
* **stop-loss** (return a partial result, stop). A budget hit implies the
|
|
97
|
+
* watermark was passed, so `watermark_hit` marks the band BETWEEN them — the
|
|
98
|
+
* only window in which a capsule can still be written.
|
|
99
|
+
*/
|
|
71
100
|
export function evaluateWorkerBudget(consumed: number, budget: number): BudgetEvaluation {
|
|
72
101
|
const hit = consumed >= budget;
|
|
102
|
+
const watermark = Math.floor(budget * CAPSULE_WATERMARK_FRACTION);
|
|
103
|
+
const watermarkHit = !hit && consumed >= watermark;
|
|
73
104
|
return {
|
|
74
105
|
budget_hit: hit,
|
|
75
106
|
consumed,
|
|
76
107
|
budget,
|
|
108
|
+
watermark,
|
|
109
|
+
watermark_hit: watermarkHit,
|
|
77
110
|
reason: hit
|
|
78
111
|
? `budget hit (${consumed} >= ${budget}) — return partial result + escalation flag, stop exploring`
|
|
79
|
-
:
|
|
112
|
+
: watermarkHit
|
|
113
|
+
? `watermark reached (${consumed} >= ${watermark}) — emit a CHECKPOINT capsule while there is headroom to write one`
|
|
114
|
+
: `within budget (${consumed} < ${budget})`,
|
|
80
115
|
};
|
|
81
116
|
}
|
|
82
117
|
|
|
@@ -1052,9 +1052,12 @@ export class SubprocessError extends Error {
|
|
|
1052
1052
|
* `~/.event4u/agent-config/cli-calls.json` and resets on UTC date rollover.
|
|
1053
1053
|
*
|
|
1054
1054
|
* Subclass contract:
|
|
1055
|
-
* - `name
|
|
1056
|
-
*
|
|
1057
|
-
* `binary:` field is not set.
|
|
1055
|
+
* - `super(opts, { name, default_binary })`: `name` is the provider key
|
|
1056
|
+
* (`anthropic`, `openai`, `gemini`, …); `default_binary` is the executable
|
|
1057
|
+
* resolved via PATH when the member-level `binary:` field is not set. Both
|
|
1058
|
+
* are passed explicitly to `super()` — not read off subclass instance
|
|
1059
|
+
* fields — because a subclass's own field initializers run only AFTER this
|
|
1060
|
+
* `super()` call returns.
|
|
1058
1061
|
* - `_build_command(system_prompt, user_prompt, max_tokens)`: return the argv.
|
|
1059
1062
|
* - `_parse_output(stdout, stderr)`: return a partial `CouncilResponse`.
|
|
1060
1063
|
*
|
|
@@ -1097,8 +1100,22 @@ export abstract class CliClient extends ExternalAIClient {
|
|
|
1097
1100
|
'usage limit',
|
|
1098
1101
|
];
|
|
1099
1102
|
|
|
1100
|
-
|
|
1103
|
+
/**
|
|
1104
|
+
* `identity` carries the subclass constants (`name`, `default_binary`)
|
|
1105
|
+
* that construction validates against. They are passed explicitly rather
|
|
1106
|
+
* than read off `this.name` / `this.default_binary` because subclass
|
|
1107
|
+
* instance-field initializers (`override default_binary = 'claude'`,
|
|
1108
|
+
* declared in the subclass body) run only AFTER this `super()` call
|
|
1109
|
+
* returns — reading them here, before that happens, would always see the
|
|
1110
|
+
* base class's own field defaults (`''`), not the subclass override.
|
|
1111
|
+
*/
|
|
1112
|
+
constructor(
|
|
1113
|
+
opts: CliClientOptions & { model: string },
|
|
1114
|
+
identity: { name: string; default_binary: string },
|
|
1115
|
+
) {
|
|
1101
1116
|
super();
|
|
1117
|
+
this.name = identity.name;
|
|
1118
|
+
this.default_binary = identity.default_binary;
|
|
1102
1119
|
this.model = opts.model;
|
|
1103
1120
|
this.timeout_seconds = opts.timeout_seconds ?? DEFAULT_CLI_TIMEOUT_SECONDS;
|
|
1104
1121
|
this.max_calls_per_day = opts.max_calls_per_day ?? null;
|
|
@@ -1353,19 +1370,20 @@ export abstract class CliClient extends ExternalAIClient {
|
|
|
1353
1370
|
* collides with argv length limits.
|
|
1354
1371
|
*/
|
|
1355
1372
|
export class AnthropicCliClient extends CliClient {
|
|
1356
|
-
override name = 'anthropic';
|
|
1357
|
-
override default_binary = 'claude';
|
|
1358
1373
|
override subscription_label = 'claude-pro';
|
|
1359
1374
|
|
|
1360
1375
|
constructor(opts: CliClientOptions = {}) {
|
|
1361
|
-
super(
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1376
|
+
super(
|
|
1377
|
+
{
|
|
1378
|
+
model: opts.model ?? DEFAULT_ANTHROPIC_CLI_MODEL,
|
|
1379
|
+
binary: opts.binary,
|
|
1380
|
+
timeout_seconds: opts.timeout_seconds,
|
|
1381
|
+
max_calls_per_day: opts.max_calls_per_day,
|
|
1382
|
+
warn_at: opts.warn_at,
|
|
1383
|
+
cli_calls_path: opts.cli_calls_path,
|
|
1384
|
+
},
|
|
1385
|
+
{ name: 'anthropic', default_binary: 'claude' },
|
|
1386
|
+
);
|
|
1369
1387
|
}
|
|
1370
1388
|
|
|
1371
1389
|
protected override _build_command(
|
|
@@ -1446,8 +1464,6 @@ export class AnthropicCliClient extends CliClient {
|
|
|
1446
1464
|
* token usage in `usage.input_tokens` / `usage.output_tokens`.
|
|
1447
1465
|
*/
|
|
1448
1466
|
export class OpenAICliClient extends CliClient {
|
|
1449
|
-
override name = 'openai';
|
|
1450
|
-
override default_binary = 'codex';
|
|
1451
1467
|
override subscription_label = 'chatgpt-plus';
|
|
1452
1468
|
|
|
1453
1469
|
static override _AUTH_FAILURE_PATTERNS: readonly string[] = [
|
|
@@ -1458,14 +1474,17 @@ export class OpenAICliClient extends CliClient {
|
|
|
1458
1474
|
];
|
|
1459
1475
|
|
|
1460
1476
|
constructor(opts: CliClientOptions = {}) {
|
|
1461
|
-
super(
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1477
|
+
super(
|
|
1478
|
+
{
|
|
1479
|
+
model: opts.model ?? DEFAULT_OPENAI_CLI_MODEL,
|
|
1480
|
+
binary: opts.binary,
|
|
1481
|
+
timeout_seconds: opts.timeout_seconds,
|
|
1482
|
+
max_calls_per_day: opts.max_calls_per_day,
|
|
1483
|
+
warn_at: opts.warn_at,
|
|
1484
|
+
cli_calls_path: opts.cli_calls_path,
|
|
1485
|
+
},
|
|
1486
|
+
{ name: 'openai', default_binary: 'codex' },
|
|
1487
|
+
);
|
|
1469
1488
|
}
|
|
1470
1489
|
|
|
1471
1490
|
protected override _build_command(
|
|
@@ -1569,8 +1588,6 @@ export class OpenAICliClient extends CliClient {
|
|
|
1569
1588
|
* stdin to dodge argv limits.
|
|
1570
1589
|
*/
|
|
1571
1590
|
export class GeminiCliClient extends CliClient {
|
|
1572
|
-
override name = 'gemini';
|
|
1573
|
-
override default_binary = 'gemini';
|
|
1574
1591
|
override subscription_label = 'gemini-pro';
|
|
1575
1592
|
|
|
1576
1593
|
static override _AUTH_FAILURE_PATTERNS: readonly string[] = [
|
|
@@ -1581,14 +1598,17 @@ export class GeminiCliClient extends CliClient {
|
|
|
1581
1598
|
];
|
|
1582
1599
|
|
|
1583
1600
|
constructor(opts: CliClientOptions = {}) {
|
|
1584
|
-
super(
|
|
1585
|
-
|
|
1586
|
-
|
|
1587
|
-
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1601
|
+
super(
|
|
1602
|
+
{
|
|
1603
|
+
model: opts.model ?? DEFAULT_GEMINI_CLI_MODEL,
|
|
1604
|
+
binary: opts.binary,
|
|
1605
|
+
timeout_seconds: opts.timeout_seconds,
|
|
1606
|
+
max_calls_per_day: opts.max_calls_per_day,
|
|
1607
|
+
warn_at: opts.warn_at,
|
|
1608
|
+
cli_calls_path: opts.cli_calls_path,
|
|
1609
|
+
},
|
|
1610
|
+
{ name: 'gemini', default_binary: 'gemini' },
|
|
1611
|
+
);
|
|
1592
1612
|
}
|
|
1593
1613
|
|
|
1594
1614
|
protected override _build_command(
|
|
@@ -1686,8 +1706,6 @@ export class GeminiCliClient extends CliClient {
|
|
|
1686
1706
|
* heuristically (chars / 4) for the audit-trail.
|
|
1687
1707
|
*/
|
|
1688
1708
|
export class XAICliClient extends CliClient {
|
|
1689
|
-
override name = 'xai';
|
|
1690
|
-
override default_binary = 'grok';
|
|
1691
1709
|
override billable = true; // community CLI consumes an API key — billable applies
|
|
1692
1710
|
|
|
1693
1711
|
static override _AUTH_FAILURE_PATTERNS: readonly string[] = [
|
|
@@ -1698,14 +1716,17 @@ export class XAICliClient extends CliClient {
|
|
|
1698
1716
|
];
|
|
1699
1717
|
|
|
1700
1718
|
constructor(opts: CliClientOptions = {}) {
|
|
1701
|
-
super(
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1719
|
+
super(
|
|
1720
|
+
{
|
|
1721
|
+
model: opts.model ?? DEFAULT_XAI_MODEL,
|
|
1722
|
+
binary: opts.binary,
|
|
1723
|
+
timeout_seconds: opts.timeout_seconds,
|
|
1724
|
+
max_calls_per_day: opts.max_calls_per_day,
|
|
1725
|
+
warn_at: opts.warn_at,
|
|
1726
|
+
cli_calls_path: opts.cli_calls_path,
|
|
1727
|
+
},
|
|
1728
|
+
{ name: 'xai', default_binary: 'grok' },
|
|
1729
|
+
);
|
|
1709
1730
|
}
|
|
1710
1731
|
|
|
1711
1732
|
protected override _build_command(
|
|
@@ -1752,8 +1773,6 @@ export class XAICliClient extends CliClient {
|
|
|
1752
1773
|
* Invokes `perplexity -p <prompt>`. Output is plain text — no JSON envelope.
|
|
1753
1774
|
*/
|
|
1754
1775
|
export class PerplexityCliClient extends CliClient {
|
|
1755
|
-
override name = 'perplexity';
|
|
1756
|
-
override default_binary = 'perplexity';
|
|
1757
1776
|
override billable = true; // community CLI consumes an API key — billable applies
|
|
1758
1777
|
|
|
1759
1778
|
static override _AUTH_FAILURE_PATTERNS: readonly string[] = [
|
|
@@ -1764,14 +1783,17 @@ export class PerplexityCliClient extends CliClient {
|
|
|
1764
1783
|
];
|
|
1765
1784
|
|
|
1766
1785
|
constructor(opts: CliClientOptions = {}) {
|
|
1767
|
-
super(
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
1786
|
+
super(
|
|
1787
|
+
{
|
|
1788
|
+
model: opts.model ?? DEFAULT_PERPLEXITY_MODEL,
|
|
1789
|
+
binary: opts.binary,
|
|
1790
|
+
timeout_seconds: opts.timeout_seconds,
|
|
1791
|
+
max_calls_per_day: opts.max_calls_per_day,
|
|
1792
|
+
warn_at: opts.warn_at,
|
|
1793
|
+
cli_calls_path: opts.cli_calls_path,
|
|
1794
|
+
},
|
|
1795
|
+
{ name: 'perplexity', default_binary: 'perplexity' },
|
|
1796
|
+
);
|
|
1775
1797
|
}
|
|
1776
1798
|
|
|
1777
1799
|
protected override _build_command(
|