@vecteur/cli 0.4.3 → 0.5.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/package.json +1 -1
- package/src/client.js +3 -2
- package/src/contract.js +7 -251
- package/src/format.js +22 -22
- package/src/mcp.js +2 -2
package/package.json
CHANGED
package/src/client.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { createHash, randomUUID } from "node:crypto";
|
|
2
2
|
|
|
3
3
|
import {
|
|
4
|
-
ARTIFACT_MEDIA_TYPES, EVENT_KINDS, OWNER_CONTRACT_IDENTITY, validateAdmitted,
|
|
4
|
+
ARTIFACT_MEDIA_TYPES, EVENT_KINDS, OWNER_CONTRACT_IDENTITY, RETIRED_EVENT_KINDS, validateAdmitted,
|
|
5
5
|
validateCustomerCostProjection, validateDeviceAuthorization, validateLimitDenial,
|
|
6
6
|
validatePatCreated, validateProject, validateRunAck, validateAccount, validateQuotaDenial,
|
|
7
7
|
RECOVERY_ACTIONS,
|
|
@@ -171,7 +171,8 @@ function exactObject(value, fields, code) {
|
|
|
171
171
|
export function validateEvent(value, runId, expectedSeq) {
|
|
172
172
|
exactObject(value, ["run_id", "seq", "kind", "payload"], "event_invalid");
|
|
173
173
|
if (value.run_id !== runId || !Number.isInteger(value.seq) || value.seq !== expectedSeq ||
|
|
174
|
-
!EVENT_KINDS.includes(value.kind) ||
|
|
174
|
+
!(EVENT_KINDS.includes(value.kind) || RETIRED_EVENT_KINDS.includes(value.kind)) ||
|
|
175
|
+
!value.payload || typeof value.payload !== "object" ||
|
|
175
176
|
Array.isArray(value.payload)) {
|
|
176
177
|
throw new CliError("event_sequence_invalid", `Expected event sequence ${expectedSeq}`);
|
|
177
178
|
}
|
package/src/contract.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
// GENERATED by scripts/gen-contract.mjs from owner TypeScript projections.
|
|
2
|
-
export const OWNER_CONTRACT_IDENTITY = "api-sha256:
|
|
2
|
+
export const OWNER_CONTRACT_IDENTITY = "api-sha256:0c052b44526d01d46a674d63ecd1bf8c0abf790e9b1bb9ba674c3e1f7acb9219;run-wire-sha256:30cae1b53b6142917e0f633d1f8edcbbe4d8eded0397cef91200dfddffd701d4";
|
|
3
3
|
export const RECOVERY_ACTIONS = Object.freeze({"delete_project":{"label":"Delete a project","href":"/projects"},"upgrade_plan":{"label":"Upgrade your plan","href":"/dashboard/billing"},"wait_for_reset":{"label":"Wait until the UTC reset","href":null}});
|
|
4
|
-
export const EVENT_KINDS = Object.freeze(["source","step_started","step_finished","
|
|
5
|
-
export const
|
|
6
|
-
export const
|
|
7
|
-
export const
|
|
4
|
+
export const EVENT_KINDS = Object.freeze(["source","step_started","step_finished","tool_call","tool_result","synthesis","artifact","terminal","heartbeat","assistant_delta","knowledge_binding","engineering_projection","provider_attempt","clarification"]);
|
|
5
|
+
export const RETIRED_EVENT_KINDS = Object.freeze(["context_frame","cta","step_label"]);
|
|
6
|
+
export const TERMINAL_FIELDS = Object.freeze(["answer","defect","deliverable_asked","evidence_dag","instruction_source","intent","missing_input_need","missing_inputs","provider_retry_offer","recovery","refusal_unfounded","state","steps","unmet_wanted"]);
|
|
7
|
+
export const ARTIFACT_MEDIA_TYPES = Object.freeze({"binary":"application/octet-stream","code":"text/plain","csv":"text/csv","docx":"application/vnd.openxmlformats-officedocument.wordprocessingml.document","drive":"application/vnd.google-drive","html":"text/html","jpeg":"image/jpeg","json":"application/json","md":"text/markdown","pdf":"application/pdf","png":"image/png","svg":"image/svg+xml","xlsx":"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"});
|
|
8
|
+
export const TERMINAL_RECOVERY_DECLARATIONS = Object.freeze({"artifact_publication_missing":[["start_run",["project_id"]]],"artifact_store_unavailable":[["start_run",["project_id"]]],"budget_exhausted":[["start_run",["project_id"]]],"cancelled":[["start_run",["project_id"]]],"cause_unrecorded":[["start_run",["project_id"]]],"clarification_custody_invalid":[["start_run",["project_id"]]],"clarification_custody_lost":[["start_run",["project_id"]]],"clarification_resume_invalid":[["start_run",["project_id"]]],"clarification_unpersisted":[["start_run",["project_id"]]],"context_unselected":[["start_run",["project_id"]]],"credential_class_disclosure":[["start_run",["project_id"]]],"deliverable_missing":[["start_run",["project_id"]]],"design_state_missing":[["start_run",["project_id"]]],"evidence_admission_invalid":[["start_run",["project_id"]]],"evidence_artifact_invalid":[["start_run",["project_id"]]],"evidence_artifact_unbound":[["start_run",["project_id"]]],"evidence_binding_unresolved":[["start_run",["project_id"]]],"evidence_context_invalid":[["start_run",["project_id"]]],"evidence_extract_unreached":[["start_run",["project_id"]]],"evidence_missing":[["start_run",["project_id"]]],"evidence_owner_receipt_mismatch":[["start_run",["project_id"]]],"evidence_owner_receipt_missing":[["start_run",["project_id"]]],"evidence_payload_invalid":[["start_run",["project_id"]]],"evidence_reached_invalid":[["start_run",["project_id"]]],"evidence_replay_invalid":[["start_run",["project_id"]]],"evidence_run_mismatch":[["start_run",["project_id"]]],"evidence_seal_collision":[["start_run",["project_id"]]],"evidence_selected_unreached":[["start_run",["project_id"]]],"execution_route_invalid":[["start_run",["project_id"]]],"executor_root_invalid":[["start_run",["project_id"]]],"extraction_offer_invalid":[["start_run",["project_id"]]],"extraction_offer_tampered":[["start_run",["project_id"]]],"fact_support_unread":[["start_run",["project_id"]]],"harness_arm_invalid":[["start_run",["project_id"]]],"harness_event_unmapped":[["start_run",["project_id"]]],"harness_exited":[["start_run",["project_id"]]],"harness_mapping_failed":[["start_run",["project_id"]]],"harness_session_invalid":[["start_run",["project_id"]]],"harness_session_missing":[["start_run",["project_id"]]],"harness_timeout":[["start_run",["project_id"]]],"infeasible_physics":[["start_run",["project_id"]]],"lab_denied":[["start_run",["project_id"]]],"lab_failed":[["start_run",["project_id"]]],"lab_not_reproduced":[["start_run",["project_id"]]],"lease_interval_invalid":[["start_run",["project_id"]]],"ledger_malformed":[["start_run",["project_id"]]],"max_tokens":[["start_run",["project_id"]]],"no_facts":[["start_run",["project_id"]]],"not_a_decision_i_can_make":[["start_run",["project_id"]]],"out_of_physics":[["start_run",["project_id"]]],"profile_eligibility_changed":[["start_run",["project_id"]]],"prompt_provenance_unavailable":[["start_run",["project_id"]]],"provider_budget_exhausted":[["start_run",["project_id"]]],"provider_budget_missing":[["start_run",["project_id"]]],"provider_budget_unavailable":[["start_run",["project_id"]]],"provider_relay_absent":[["start_run",["project_id"]]],"provider_route_control_invalid":[["start_run",["project_id"]]],"provider_route_exhausted":[["start_run",["project_id"]],["retry_run",["source_run_id","offer_id","generation"]]],"provider_route_failure_unobserved":[["start_run",["project_id"]]],"provider_route_reconciliation_invalid":[["start_run",["project_id"]]],"provider_route_restart_terminal":[["start_run",["project_id"]]],"provider_training_opted_in":[["start_run",["project_id"]]],"publish_seal_missing":[["start_run",["project_id"]]],"refusal_unfounded":[["start_run",["project_id"]]],"replay_capture_digest_mismatch":[["start_run",["project_id"]]],"replay_capture_invalid":[["start_run",["project_id"]]],"replay_config_incomplete":[["start_run",["project_id"]]],"replay_failed":[["start_run",["project_id"]]],"replay_no_requests":[["start_run",["project_id"]]],"replay_patch_invalid":[["start_run",["project_id"]]],"replay_plugin_absent":[["start_run",["project_id"]]],"replay_provider_socket":[["start_run",["project_id"]]],"replay_receipt_invalid":[["start_run",["project_id"]]],"replay_receipt_owner_chown":[["start_run",["project_id"]]],"replay_receipt_owner_incomplete":[["start_run",["project_id"]]],"replay_receipt_owner_invalid":[["start_run",["project_id"]]],"replay_request_observation_count":[["start_run",["project_id"]]],"replay_request_observation_invalid":[["start_run",["project_id"]]],"replay_request_observation_missing":[["start_run",["project_id"]]],"replay_request_owner_chown":[["start_run",["project_id"]]],"replay_socket_observation_invalid":[["start_run",["project_id"]]],"replay_socket_observation_missing":[["start_run",["project_id"]]],"replay_socket_owner_chown":[["start_run",["project_id"]]],"row_budget":[["start_run",["project_id"]]],"run_database_capability_refused":[["start_run",["project_id"]]],"runtime_unavailable":[["start_run",["project_id"]]],"sealed_contract_violated":[["start_run",["project_id"]]],"sealed_file_missing":[["start_run",["project_id"]]],"seat_patch_absent":[["start_run",["project_id"]]],"seat_patch_drift":[["start_run",["project_id"]]],"selection_admission_invalid":[["start_run",["project_id"]]],"selection_context_invalid":[["start_run",["project_id"]]],"selection_receipt_conflict":[["start_run",["project_id"]]],"selection_receipt_invalid":[["start_run",["project_id"]]],"selection_receipt_missing":[["start_run",["project_id"]]],"selection_required":[["start_run",["project_id"]]],"state_corrupt":[["start_run",["project_id"]]],"state_file_invalid":[["start_run",["project_id"]]],"state_invalid":[["start_run",["project_id"]]],"state_payload_overflow":[["start_run",["project_id"]]],"state_unencodable":[["start_run",["project_id"]]],"state_version_unknown":[["start_run",["project_id"]]],"unreceipted_numbers":[["start_run",["project_id"]]],"usage_egress_mismatch":[["start_run",["project_id"]]],"wall_budget":[["start_run",["project_id"]]],"wanted_not_computed":[["start_run",["project_id"]]]});
|
|
8
9
|
export const ORIGIN_KINDS = Object.freeze(["user","hypothesis","derived","knowledge","file","catalog","default"]);
|
|
9
10
|
export const ORIGIN_WORD = Object.freeze({"user":"your brief","hypothesis":"assumed","derived":"derived","knowledge":"Vecteur knowledge","file":"your file","catalog":"catalogue","default":"default","unattributed":"unstated"});
|
|
10
11
|
const shape=(v,r,o=[])=>!!v&&typeof v==="object"&&!Array.isArray(v)&&r.every(k=>Object.hasOwn(v,k))&&Object.keys(v).every(k=>r.includes(k)||o.includes(k));
|
|
@@ -26,7 +27,7 @@ const ownerCostScope=v=>shape(v,["type","id"],[])&&((v.type==="organization"||v.
|
|
|
26
27
|
const ownerCostBindingScope=v=>shape(v,["kind","scope"],[])&&((v.kind==="platform_tier"||v.kind==="restriction"||v.kind==="unlimited"))&&(ownerCostScope(v.scope));
|
|
27
28
|
const ownerCustomerCostDisplay=v=>shape(v,["currency","used","scope_used","limit","remaining"],[])&&((v.currency==="EUR"||v.currency==="USD"))&&((typeof v.used==="string"||v.used===null))&&((typeof v.scope_used==="string"||v.scope_used===null))&&((typeof v.limit==="string"||v.limit===null))&&((typeof v.remaining==="string"||v.remaining===null));
|
|
28
29
|
const ownerLimitDenial=v=>shape(v,["schema","scope","binding_scope","period_start","period_end","unit","used","scope_used","limit","remaining","reset_at","coverage","display","dimension","recovery"],[])&&(v.schema==="vecteur.customer-cost-projection.v1")&&(ownerCostScope(v.scope))&&(ownerCostBindingScope(v.binding_scope))&&(Number.isFinite(v.period_start))&&(Number.isFinite(v.period_end))&&(v.unit==="customer_gross_microusd")&&((Number.isFinite(v.used)||v.used===null))&&((Number.isFinite(v.scope_used)||v.scope_used===null))&&((Number.isFinite(v.limit)||v.limit===null))&&((Number.isFinite(v.remaining)||v.remaining===null))&&(Number.isFinite(v.reset_at))&&((v.coverage==="complete"||v.coverage==="incomplete"))&&(ownerCustomerCostDisplay(v.display))&&(v.dimension==="customer_cost")&&(Array.isArray(v.recovery)&&v.recovery.every(x=>(x==="wait_for_reset"||x==="upgrade_plan")));
|
|
29
|
-
const ownerArtifact=v=>shape(v,["id","kind","cas_ref","filename"],["produced_by_step","from_input_rows","build_receipt_id","output_index"])&&(typeof v.id==="string")&&((v.kind==="docx"||v.kind==="xlsx"||v.kind==="pdf"||v.kind==="md"||v.kind==="csv"||v.kind==="html"||v.kind==="code"||v.kind==="drive"))&&(ownerCasRef(v.cas_ref))&&(typeof v.filename==="string")&&(v.produced_by_step===undefined||(typeof v.produced_by_step==="string"||v.produced_by_step===null))&&(v.from_input_rows===undefined||(Array.isArray(v.from_input_rows)&&v.from_input_rows.every(x=>typeof x==="string")||v.from_input_rows===null))&&(v.build_receipt_id===undefined||(typeof v.build_receipt_id==="string"||v.build_receipt_id===null))&&(v.output_index===undefined||(Number.isFinite(v.output_index)||v.output_index===null));
|
|
30
|
+
const ownerArtifact=v=>shape(v,["id","kind","cas_ref","filename"],["produced_by_step","from_input_rows","build_receipt_id","output_index","path","revision","origin_call_id","preview","supersedes_cas_ref","execution_id"])&&(typeof v.id==="string")&&((v.kind==="docx"||v.kind==="xlsx"||v.kind==="pdf"||v.kind==="md"||v.kind==="csv"||v.kind==="html"||v.kind==="code"||v.kind==="drive"||v.kind==="png"||v.kind==="jpeg"||v.kind==="svg"||v.kind==="json"||v.kind==="binary"))&&(ownerCasRef(v.cas_ref))&&(typeof v.filename==="string")&&(v.produced_by_step===undefined||(typeof v.produced_by_step==="string"||v.produced_by_step===null))&&(v.from_input_rows===undefined||(Array.isArray(v.from_input_rows)&&v.from_input_rows.every(x=>typeof x==="string")||v.from_input_rows===null))&&(v.build_receipt_id===undefined||(typeof v.build_receipt_id==="string"||v.build_receipt_id===null))&&(v.output_index===undefined||(Number.isFinite(v.output_index)||v.output_index===null))&&(v.path===undefined||(typeof v.path==="string"||v.path===null))&&(v.revision===undefined||(Number.isFinite(v.revision)||v.revision===null))&&(v.origin_call_id===undefined||(typeof v.origin_call_id==="string"||v.origin_call_id===null))&&(v.preview===undefined||(v.preview==="text"||v.preview==="code"||v.preview==="csv"||v.preview==="table"||v.preview==="series"||v.preview==="image"||v.preview==="html"||v.preview==="docx"||v.preview==="xlsx"||v.preview==="pdf"||v.preview==="binary"||v.preview===null))&&(v.supersedes_cas_ref===undefined||(ownerCasRef(v.supersedes_cas_ref)||v.supersedes_cas_ref===null))&&(v.execution_id===undefined||(typeof v.execution_id==="string"||v.execution_id===null));
|
|
30
31
|
const ownerCasRef=v=>typeof v==="string";
|
|
31
32
|
const ownerSynthesis=v=>shape(v,["answer","core","terminal"],[])&&(typeof v.answer==="string")&&(v.core!==null&&typeof v.core==="object"&&!Array.isArray(v.core)&&Object.values(v.core).every(x=>true))&&((v.terminal==="ok"||v.terminal==="partial"||v.terminal==="blocked"||v.terminal==="refused"||v.terminal==="infeasible_physics"||v.terminal==="capability_gap"));
|
|
32
33
|
export const validateAccount=v=>ownerAccount(v)&&[v.id,v.email,v.display_name,v.org_id].every(text)&&v.workspaces.every(w=>[w.id,w.org_id,w.name].every(text))&&integer(v.entitlements.active_projects.current)&&v.entitlements.active_projects.current>=0&&(v.entitlements.active_projects.maximum===null||(integer(v.entitlements.active_projects.maximum)&&v.entitlements.active_projects.maximum>=0));
|
|
@@ -45,248 +46,3 @@ const usage=(v)=>exact(v,["coverage","provider_id","model_id","observed_at","bil
|
|
|
45
46
|
export const validateAdmitted=(v)=>shape(v,["run_id","state_hash","result_hash","requested_route_id","profile","terminal","usage","events"],["duration_seconds"])&&[v.run_id,v.state_hash,v.result_hash,v.requested_route_id,v.profile].every(text)&&["ok","partial","blocked","refused","infeasible_physics","capability_gap"].includes(v.terminal)&&usage(v.usage)&&Array.isArray(v.events)&&(v.duration_seconds===undefined||v.duration_seconds===null||(integer(v.duration_seconds)&&v.duration_seconds>=0));
|
|
46
47
|
export const validatePatCreated=(v)=>exact(v,["id","name","token","prefix","project_id","scopes","created_at","expires_at"])&&[v.id,v.name,v.token,v.prefix].every(text)&&(v.project_id===null||text(v.project_id))&&Array.isArray(v.scopes)&&v.scopes.every(s=>["project:read","project:execute"].includes(s))&&integer(v.created_at)&&integer(v.expires_at);
|
|
47
48
|
export const validateDeviceAuthorization=(v)=>exact(v,["device_code","user_code","verification_uri","verification_uri_complete","expires_at","interval"])&&[v.device_code,v.user_code,v.verification_uri,v.verification_uri_complete].every(text)&&integer(v.expires_at)&&integer(v.interval)&&v.interval>=0;
|
|
48
|
-
// --- frontend/src/run/tasks.ts, transpiled: the task projection the canvas and this door share ---
|
|
49
|
-
export function stepVerb(step) {
|
|
50
|
-
return (step.method?.verb ?? '').replace(/^mcp__[a-z0-9]+__/i, '');
|
|
51
|
-
}
|
|
52
|
-
const PROGRAM_ROW = /^call_(\d+)_steps$/;
|
|
53
|
-
export function programNodes(step) {
|
|
54
|
-
if (stepVerb(step) !== 'run_program')
|
|
55
|
-
return null;
|
|
56
|
-
const nodes = [];
|
|
57
|
-
for (const row of step.inputs ?? []) {
|
|
58
|
-
if (!PROGRAM_ROW.test(row.name) || !Array.isArray(row.value))
|
|
59
|
-
continue;
|
|
60
|
-
for (const entry of row.value) {
|
|
61
|
-
if (!entry || typeof entry !== 'object' || Array.isArray(entry))
|
|
62
|
-
return null;
|
|
63
|
-
const { bind, verb } = entry;
|
|
64
|
-
if (typeof bind !== 'string' || typeof verb !== 'string' || !verb)
|
|
65
|
-
return null;
|
|
66
|
-
nodes.push({ bind, verb });
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return nodes.length ? nodes : null;
|
|
70
|
-
}
|
|
71
|
-
export function attemptState(step) {
|
|
72
|
-
const produced = (step.outputs ?? []).length > 0;
|
|
73
|
-
if (!produced && (step.refusals ?? []).length > 0)
|
|
74
|
-
return 'refused';
|
|
75
|
-
return produced ? 'computed' : 'open';
|
|
76
|
-
}
|
|
77
|
-
function attemptOf(step) {
|
|
78
|
-
const state = attemptState(step);
|
|
79
|
-
return { step, state, code: state === 'refused' ? (step.refusals?.[0]?.code ?? 'refused') : null };
|
|
80
|
-
}
|
|
81
|
-
export function taskGroups(steps) {
|
|
82
|
-
const tasks = [];
|
|
83
|
-
let open = null;
|
|
84
|
-
for (const step of steps) {
|
|
85
|
-
const verb = stepVerb(step);
|
|
86
|
-
if (verb === 'thinking')
|
|
87
|
-
continue;
|
|
88
|
-
const nodes = programNodes(step);
|
|
89
|
-
const verbs = nodes ? [...new Set(nodes.map((node) => node.verb))] : [];
|
|
90
|
-
if (nodes && open && verbs.some((verb) => open.verbs.includes(verb))) {
|
|
91
|
-
const attempt = attemptOf(step);
|
|
92
|
-
open.attempts.push(attempt);
|
|
93
|
-
if (attempt.state === 'refused')
|
|
94
|
-
open.refused.push(attempt);
|
|
95
|
-
for (const verb of verbs)
|
|
96
|
-
if (!open.verbs.includes(verb))
|
|
97
|
-
open.verbs.push(verb);
|
|
98
|
-
open.state = attempt.state;
|
|
99
|
-
if (attempt.state === 'computed')
|
|
100
|
-
open = null;
|
|
101
|
-
continue;
|
|
102
|
-
}
|
|
103
|
-
const attempt = attemptOf(step);
|
|
104
|
-
const task = {
|
|
105
|
-
id: step.id, program: nodes !== null, verbs,
|
|
106
|
-
attempts: [attempt], refused: attempt.state === 'refused' ? [attempt] : [],
|
|
107
|
-
state: attempt.state,
|
|
108
|
-
};
|
|
109
|
-
tasks.push(task);
|
|
110
|
-
if (nodes)
|
|
111
|
-
open = attempt.state === 'computed' ? null : task;
|
|
112
|
-
else if (verb !== 'phys_search')
|
|
113
|
-
open = null;
|
|
114
|
-
}
|
|
115
|
-
return tasks;
|
|
116
|
-
}
|
|
117
|
-
const INTENT_ROW = /^call_(\d+)_intent$/;
|
|
118
|
-
const MISSION_ROW = /^call_(\d+)_(intent|hoisted_requirements|unmet_wanted)$/;
|
|
119
|
-
const UNMET_ROW = /^call_(\d+)_unmet_wanted$/;
|
|
120
|
-
const HOISTED_ROW = /^call_(\d+)_hoisted_requirements$/;
|
|
121
|
-
export function isIntentRow(name) {
|
|
122
|
-
return MISSION_ROW.test(name);
|
|
123
|
-
}
|
|
124
|
-
const words = (value) => (Array.isArray(value) ? value.filter((item) => typeof item === 'string' && item.trim() !== '').map((item) => item.trim()) : []);
|
|
125
|
-
function asThresholds(value) {
|
|
126
|
-
if (!Array.isArray(value))
|
|
127
|
-
return [];
|
|
128
|
-
const out = [];
|
|
129
|
-
for (const row of value) {
|
|
130
|
-
if (!row || typeof row !== 'object' || Array.isArray(row))
|
|
131
|
-
continue;
|
|
132
|
-
const { quantity, comparator, limit, unit, quote } = row;
|
|
133
|
-
if (typeof quantity !== 'string' || typeof comparator !== 'string' || typeof limit !== 'number' || typeof quote !== 'string')
|
|
134
|
-
continue;
|
|
135
|
-
out.push({ quantity, comparator, limit, unit: typeof unit === 'string' ? unit : '', quote });
|
|
136
|
-
}
|
|
137
|
-
return out;
|
|
138
|
-
}
|
|
139
|
-
export function stepIntent(step) {
|
|
140
|
-
let found = null;
|
|
141
|
-
for (const row of step.inputs ?? []) {
|
|
142
|
-
if (!INTENT_ROW.test(row.name))
|
|
143
|
-
continue;
|
|
144
|
-
const value = row.value;
|
|
145
|
-
if (typeof value === 'string') {
|
|
146
|
-
found = { title: value.trim(), rationale: '', wanted: [], thresholds: [] };
|
|
147
|
-
continue;
|
|
148
|
-
}
|
|
149
|
-
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
150
|
-
continue;
|
|
151
|
-
const { title, rationale, wanted, thresholds } = value;
|
|
152
|
-
found = {
|
|
153
|
-
title: typeof title === 'string' ? title.trim() : '',
|
|
154
|
-
rationale: typeof rationale === 'string' ? rationale.trim() : '',
|
|
155
|
-
wanted: words(wanted),
|
|
156
|
-
thresholds: asThresholds(thresholds),
|
|
157
|
-
};
|
|
158
|
-
}
|
|
159
|
-
return found;
|
|
160
|
-
}
|
|
161
|
-
export function hoistedRequirements(step) {
|
|
162
|
-
const out = [];
|
|
163
|
-
for (const row of step.inputs ?? []) {
|
|
164
|
-
if (!HOISTED_ROW.test(row.name) || !Array.isArray(row.value))
|
|
165
|
-
continue;
|
|
166
|
-
for (const entry of row.value) {
|
|
167
|
-
if (!entry || typeof entry !== 'object' || Array.isArray(entry))
|
|
168
|
-
continue;
|
|
169
|
-
const { quantity, comparator, limit, unit } = entry;
|
|
170
|
-
if (typeof quantity !== 'string' || typeof comparator !== 'string' || typeof limit !== 'number')
|
|
171
|
-
continue;
|
|
172
|
-
out.push({ quantity: quantity.replace(/^\$/, ''), comparator, limit, unit: typeof unit === 'string' ? unit : '' });
|
|
173
|
-
}
|
|
174
|
-
}
|
|
175
|
-
return out;
|
|
176
|
-
}
|
|
177
|
-
export function hoistedQuotes(step) {
|
|
178
|
-
const quotes = new Map();
|
|
179
|
-
const thresholds = stepIntent(step)?.thresholds ?? [];
|
|
180
|
-
for (const row of hoistedRequirements(step)) {
|
|
181
|
-
const matches = thresholds.filter((threshold) => (threshold.comparator === row.comparator && threshold.limit === row.limit && threshold.unit === row.unit));
|
|
182
|
-
if (matches.length === 1)
|
|
183
|
-
quotes.set(row.quantity, matches[0].quote);
|
|
184
|
-
}
|
|
185
|
-
return quotes;
|
|
186
|
-
}
|
|
187
|
-
export function unmetWanted(step) {
|
|
188
|
-
let found = [];
|
|
189
|
-
for (const row of step.outputs ?? []) {
|
|
190
|
-
if (!row || typeof row !== 'object')
|
|
191
|
-
continue;
|
|
192
|
-
const { name, value } = row;
|
|
193
|
-
if (typeof name === 'string' && UNMET_ROW.test(name))
|
|
194
|
-
found = words(value);
|
|
195
|
-
}
|
|
196
|
-
return found;
|
|
197
|
-
}
|
|
198
|
-
const sameWords = (left, right) => {
|
|
199
|
-
const norm = (value) => value.replace(/[.!?]+$/u, '').replace(/\s+/g, ' ').trim().toLowerCase();
|
|
200
|
-
const a = norm(left);
|
|
201
|
-
return Boolean(a) && a === norm(right);
|
|
202
|
-
};
|
|
203
|
-
export function intentTitle(step) {
|
|
204
|
-
const recorded = (step.title ?? '').trim();
|
|
205
|
-
const intent = stepIntent(step);
|
|
206
|
-
return recorded && intent && sameWords(recorded, intent.title) ? recorded : '';
|
|
207
|
-
}
|
|
208
|
-
export const ENGINEERING_VERBS = {
|
|
209
|
-
analyze_acquisition_contact_latency: 'Acquisition-to-contact latency',
|
|
210
|
-
analyze_eclipse_profile: 'Eclipse profile',
|
|
211
|
-
close_link: 'Link closure',
|
|
212
|
-
resolve_payload: 'Image resolution',
|
|
213
|
-
resolve_utc_interval: 'Time window',
|
|
214
|
-
sample_projection: 'Sampled projection',
|
|
215
|
-
select_propulsion: 'Propulsion selection',
|
|
216
|
-
size_access: 'Coverage and revisit',
|
|
217
|
-
size_annual_power: 'Annual power',
|
|
218
|
-
size_burn_sequence: 'Burn sequence',
|
|
219
|
-
size_delta_v_budget: 'Delta-v budget',
|
|
220
|
-
size_drag_makeup: 'Drag make-up',
|
|
221
|
-
size_ground_contacts: 'Ground contacts',
|
|
222
|
-
size_hohmann_transfer: 'Hohmann transfer',
|
|
223
|
-
size_hybrid_transfer: 'Hybrid transfer',
|
|
224
|
-
size_in_view: 'Satellites in view',
|
|
225
|
-
size_orbit: 'Orbit geometry',
|
|
226
|
-
size_phase_duration: 'Phasing duration',
|
|
227
|
-
size_platform: 'Platform sizing',
|
|
228
|
-
size_pnt_geometry: 'Navigation geometry',
|
|
229
|
-
size_power: 'Power system',
|
|
230
|
-
size_propellant: 'Propellant',
|
|
231
|
-
size_raan_change: 'Plane change',
|
|
232
|
-
size_repeat_orbit: 'Repeat orbit',
|
|
233
|
-
size_station_keeping: 'Station keeping',
|
|
234
|
-
size_topology: 'Topology search',
|
|
235
|
-
size_transfer: 'Orbit transfer',
|
|
236
|
-
};
|
|
237
|
-
export function engineeringVerbLabel(verb) {
|
|
238
|
-
return ENGINEERING_VERBS[verb] ?? verb.replace(/^size_/, '').replaceAll('_', ' ')
|
|
239
|
-
.replace(/^./, (letter) => letter.toUpperCase());
|
|
240
|
-
}
|
|
241
|
-
export function taskTitle(task) {
|
|
242
|
-
for (let index = task.attempts.length - 1; index >= 0; index -= 1) {
|
|
243
|
-
const attempt = task.attempts[index];
|
|
244
|
-
if (attempt.state !== 'computed')
|
|
245
|
-
continue;
|
|
246
|
-
const title = intentTitle(attempt.step);
|
|
247
|
-
if (title)
|
|
248
|
-
return title;
|
|
249
|
-
}
|
|
250
|
-
return task.verbs.map(engineeringVerbLabel).join(' · ');
|
|
251
|
-
}
|
|
252
|
-
export function taskRationale(task) {
|
|
253
|
-
for (let index = task.attempts.length - 1; index >= 0; index -= 1) {
|
|
254
|
-
const rationale = stepIntent(task.attempts[index].step)?.rationale ?? '';
|
|
255
|
-
if (rationale)
|
|
256
|
-
return rationale;
|
|
257
|
-
}
|
|
258
|
-
return '';
|
|
259
|
-
}
|
|
260
|
-
export const REFUSAL_WORDS = {
|
|
261
|
-
support_mismatch: 'sources',
|
|
262
|
-
unit_error: 'units',
|
|
263
|
-
authoring_defect: 'program',
|
|
264
|
-
owner_refusal: 'bound',
|
|
265
|
-
INVALID_TOOL_OUTPUT: 'output',
|
|
266
|
-
missing_knowledge_dependency: 'knowledge',
|
|
267
|
-
capability_gap: 'capability',
|
|
268
|
-
budget: 'budget',
|
|
269
|
-
missing_input: 'input',
|
|
270
|
-
};
|
|
271
|
-
export function taskStateWord(task) {
|
|
272
|
-
if (task.state === 'open')
|
|
273
|
-
return 'no result';
|
|
274
|
-
if (task.state !== 'refused')
|
|
275
|
-
return task.state;
|
|
276
|
-
const word = REFUSAL_WORDS[task.attempts[task.attempts.length - 1]?.code ?? ''];
|
|
277
|
-
return word ? `refused — ${word}` : 'refused';
|
|
278
|
-
}
|
|
279
|
-
export function taskUnmet(task) {
|
|
280
|
-
if (task.state !== 'computed')
|
|
281
|
-
return [];
|
|
282
|
-
return unmetWanted(task.attempts[task.attempts.length - 1].step);
|
|
283
|
-
}
|
|
284
|
-
export function taskMeta(task) {
|
|
285
|
-
const count = task.attempts.length;
|
|
286
|
-
const unmet = taskUnmet(task).length;
|
|
287
|
-
return [
|
|
288
|
-
taskStateWord(task),
|
|
289
|
-
count > 1 ? `${count} attempts` : '',
|
|
290
|
-
unmet ? `${unmet} still to compute` : '',
|
|
291
|
-
].filter(Boolean).join(' · ');
|
|
292
|
-
}
|
package/src/format.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ORIGIN_KINDS, ORIGIN_WORD, TERMINAL_FIELDS, TERMINAL_RECOVERY_DECLARATIONS,
|
|
3
|
-
|
|
3
|
+
validateArtifact, validateSynthesis,
|
|
4
4
|
} from "./contract.js";
|
|
5
5
|
import { CliError } from "./errors.js";
|
|
6
6
|
|
|
@@ -64,8 +64,7 @@ export function originWord(origin) {
|
|
|
64
64
|
/** `name = value unit (origin word, ref)` — one line per input, in wire order. */
|
|
65
65
|
export function inputLines(inputs) {
|
|
66
66
|
if (!Array.isArray(inputs)) return [];
|
|
67
|
-
|
|
68
|
-
return inputs.filter((row) => !isIntentRow(String(row?.name ?? ""))).map((row) => {
|
|
67
|
+
return inputs.map((row) => {
|
|
69
68
|
const unit = typeof row?.unit === "string" && row.unit ? ` ${row.unit}` : "";
|
|
70
69
|
const word = originWord(row?.origin);
|
|
71
70
|
// The REF is what makes the word actionable — "your file" is a category, "your file
|
|
@@ -78,24 +77,29 @@ export function inputLines(inputs) {
|
|
|
78
77
|
}
|
|
79
78
|
|
|
80
79
|
/**
|
|
81
|
-
*
|
|
80
|
+
* ONE ROW PER INTENT, SPOKEN BY THIS DOOR TOO (RunWire v2, CONTRACTS.md S1).
|
|
82
81
|
*
|
|
83
|
-
* The
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
* asked for: one line per task, its verbs as the title, what it is and how many attempts it
|
|
87
|
-
* took. Binding receipts (`binding-*`) are the workspace register's rows, not work.
|
|
82
|
+
* The rows are the `step_finished` facts keyed by `step_id`: the finding as the title, the
|
|
83
|
+
* outcome word, the attempt count and the `RESULT:` line the program printed. Tool calls stay
|
|
84
|
+
* folded; this door prints the plan, not the process.
|
|
88
85
|
*/
|
|
86
|
+
/** The budget that closed a partial row (`step_finished.cause`), in the reader's words — the same
|
|
87
|
+
* words the workbench's row meta uses (`StepRow.vue`). */
|
|
88
|
+
const CAUSE_WORD = Object.freeze({
|
|
89
|
+
row_budget: "stopped at its budget", wall_budget: "stopped at the turn's time limit",
|
|
90
|
+
});
|
|
91
|
+
|
|
89
92
|
export function taskLines(events) {
|
|
90
|
-
|
|
93
|
+
return events.flatMap((event) => {
|
|
91
94
|
if (event?.kind !== "step_finished") return [];
|
|
92
|
-
const
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
const row = event.payload;
|
|
96
|
+
if (!row || typeof row !== "object" || typeof row.step_id !== "string") return [];
|
|
97
|
+
const attempts = Number.isInteger(row.attempts) && row.attempts > 0
|
|
98
|
+
? ` · ${row.attempts} ${row.attempts === 1 ? "attempt" : "attempts"}` : "";
|
|
99
|
+
const result = typeof row.result_line === "string" && row.result_line.trim()
|
|
100
|
+
? `\n ${plainLine(row.result_line)}` : "";
|
|
101
|
+
const outcome = CAUSE_WORD[row.cause] ?? row.status;
|
|
102
|
+
return [` ${plainLine(`${row.title} — ${outcome}${attempts}`)}${result}`];
|
|
99
103
|
});
|
|
100
104
|
}
|
|
101
105
|
|
|
@@ -192,7 +196,7 @@ export function humanRun(value, { projectId, cost } = {}) {
|
|
|
192
196
|
const tasks = taskLines(value.events);
|
|
193
197
|
const lines = [];
|
|
194
198
|
if (terminal.answer !== undefined) lines.push(terminal.answer, "");
|
|
195
|
-
if (tasks.length) lines.push("
|
|
199
|
+
if (tasks.length) lines.push("Steps:", ...tasks, "");
|
|
196
200
|
if (origins.length) lines.push("Inputs and origins:", ...origins, "");
|
|
197
201
|
if (artifacts.length) {
|
|
198
202
|
lines.push("Artifacts:");
|
|
@@ -241,10 +245,6 @@ export function progress(event) {
|
|
|
241
245
|
const title = plainLine(event.payload?.title ?? "");
|
|
242
246
|
return title.trim() ? `Starting: ${title}\n` : "Starting\n";
|
|
243
247
|
}
|
|
244
|
-
if (event?.kind === "step_label") {
|
|
245
|
-
const label = plainLine(event.payload?.label ?? "");
|
|
246
|
-
return label.trim() ? `Working: ${label}\n` : "";
|
|
247
|
-
}
|
|
248
248
|
if (event?.kind === "artifact") {
|
|
249
249
|
return `File ready: ${plainLine(event.payload.filename)}\n`;
|
|
250
250
|
}
|
package/src/mcp.js
CHANGED
|
@@ -3,7 +3,7 @@ import { serveStdio } from "@modelcontextprotocol/server/stdio";
|
|
|
3
3
|
import * as z from "zod/v4";
|
|
4
4
|
|
|
5
5
|
import { CliError, VecteurClient, redact } from "./client.js";
|
|
6
|
-
import { EVENT_KINDS } from "./contract.js";
|
|
6
|
+
import { EVENT_KINDS, RETIRED_EVENT_KINDS } from "./contract.js";
|
|
7
7
|
import { canonicalJson } from "./format.js";
|
|
8
8
|
|
|
9
9
|
const projectInput = z.object({ project_id: z.string().min(1) }).strict();
|
|
@@ -12,7 +12,7 @@ const submitInput = z.object({
|
|
|
12
12
|
ask: z.string().min(1),
|
|
13
13
|
}).strict();
|
|
14
14
|
const runInput = z.object({ run_id: z.string().min(1) }).strict();
|
|
15
|
-
const eventKind = z.enum(EVENT_KINDS);
|
|
15
|
+
const eventKind = z.enum([...EVENT_KINDS, ...RETIRED_EVENT_KINDS]);
|
|
16
16
|
const eventOutput = z.object({
|
|
17
17
|
run_id: z.string().min(1), seq: z.number().int().safe().nonnegative(),
|
|
18
18
|
kind: eventKind,
|