@volter/supercode-orchestrator 0.4.159 → 0.5.1
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/README.md +16 -5
- package/adapters/chat-sdk.mjs +4 -1
- package/adapters/rh2.mjs +18 -20
- package/agent-home.mjs +35 -0
- package/agent-profiles.mjs +53 -0
- package/agents.mjs +443 -0
- package/bin/agent-door.mjs +53 -0
- package/bin/runtime-door.mjs +23 -0
- package/bin/runtime.mjs +59 -4
- package/board/agent-declarations.mjs +29 -0
- package/board/ci.mjs +6 -1
- package/board/cli.mjs +158 -31
- package/board/dispatch.mjs +304 -124
- package/board/engine.mjs +30 -10
- package/board/event-fleet.mjs +59 -0
- package/board/event-relay.mjs +45 -0
- package/board/event-stream.mjs +104 -0
- package/board/incidents.mjs +57 -0
- package/board/published.mjs +86 -0
- package/board/runtime-door.mjs +12 -0
- package/board/store.mjs +39 -6
- package/board/tools.mjs +1 -0
- package/board/wake.mjs +17 -56
- package/board/workflow.mjs +28 -7
- package/board/workspace.mjs +18 -15
- package/commands.mjs +2 -2
- package/conversations.mjs +108 -0
- package/cron.mjs +30 -4
- package/gates.mjs +3 -2
- package/hermes-cli.mjs +19 -2
- package/index.d.ts +43 -2
- package/index.mjs +4 -0
- package/installed-apps.mjs +52 -0
- package/ir.mjs +3 -3
- package/kanban-worker.mjs +16 -6
- package/loop.mjs +211 -21
- package/mcp/bridge.mjs +13 -2
- package/mcp/tools.mjs +17 -0
- package/mcp/verbs.mjs +29 -7
- package/ontology.d.ts +246 -2
- package/operator.mjs +6 -1
- package/package.json +2 -2
- package/reducer.mjs +133 -28
- package/webhook.mjs +8 -4
package/mcp/verbs.mjs
CHANGED
|
@@ -22,6 +22,8 @@ import { compactStamp, gateFields, homeZone, nextRunAt, parseCron, payloadError,
|
|
|
22
22
|
import { applyOperator, hermesJobArgs } from '../operator.mjs';
|
|
23
23
|
import { hermesSchedule, hermesTool } from '../hermes-cli.mjs';
|
|
24
24
|
import { modelError } from '../activation.mjs';
|
|
25
|
+
import { agentRunForSession } from '../agents.mjs';
|
|
26
|
+
import { materializeAgentHome } from '../agent-home.mjs';
|
|
25
27
|
|
|
26
28
|
/**
|
|
27
29
|
* cron/jobs.py `_normalize_workdir`, transcribed: returns the absolute,
|
|
@@ -64,7 +66,9 @@ export function routedProfile(state, key) {
|
|
|
64
66
|
const profiles = Object.values(state.profiles);
|
|
65
67
|
const owner = profiles.find((p) => p.channels && p.channels[key.platform]) ?? state.profiles.default ?? profiles[0];
|
|
66
68
|
if (!owner) return null;
|
|
67
|
-
|
|
69
|
+
// a route names an agent (G1); its profile is the agent's own or the declared one's
|
|
70
|
+
const agent = resolveRoute(owner.routes, key) ?? owner.name;
|
|
71
|
+
return state.agents?.[agent]?.profile ?? (state.profiles[agent] ? agent : owner.name);
|
|
68
72
|
}
|
|
69
73
|
|
|
70
74
|
const UNIT_MINUTES = { m: 1, min: 1, mins: 1, minute: 1, minutes: 1, h: 60, hr: 60, hour: 60, hours: 60, d: 1440, day: 1440, days: 1440 };
|
|
@@ -321,10 +325,15 @@ export async function runVerb(orch, { verb, args = {}, profile: profileName, sur
|
|
|
321
325
|
case 'memory':
|
|
322
326
|
case 'skills_list':
|
|
323
327
|
case 'skill_view': {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
+
const worker=binding?.worker;
|
|
329
|
+
let home=profile.dir,scope=`profile ${profile.name}`;
|
|
330
|
+
if(verb==='memory'||verb==='session_search') {
|
|
331
|
+
const owner=worker&&agentRunForSession(state.root,[`${worker.harness}:${worker.session_id}`,`${worker.harness}:${worker.runtime_id}`]);
|
|
332
|
+
if(!owner)throw new Error(`${verb} requires the bound session's agent ownership; a profile is not an agent`);
|
|
333
|
+
home=materializeAgentHome(state.root,owner.org,owner.agent_id,profile);scope=`agent ${owner.agent_id}`;
|
|
334
|
+
}
|
|
335
|
+
const verbatim = await hermesTool(home, verb, args, { sessionId: worker?.session_id ?? null });
|
|
336
|
+
return { effects, result: { ran: `${verb} in ${scope}`, verbatim: typeof verbatim === 'string' ? verbatim : JSON.stringify(verbatim) } };
|
|
328
337
|
}
|
|
329
338
|
|
|
330
339
|
case 'session_handoff': {
|
|
@@ -333,8 +342,21 @@ export async function runVerb(orch, { verb, args = {}, profile: profileName, sur
|
|
|
333
342
|
const b = surface ? liveBinding(profile, surface) : null;
|
|
334
343
|
if (!b) throw new Error('No live session to hand off.');
|
|
335
344
|
await orch.dispatch(events.operator({ verb: 'session_handoff', profile: profile.name, args: { keyString: surface, to, note: args.note ? String(args.note) : null }, at: now }));
|
|
336
|
-
|
|
337
|
-
return { effects,
|
|
345
|
+
const record = [...(orch.state.handoffs ?? [])].reverse().find((h) => h.session === `${b.worker.harness}:${b.worker.session_id ?? ''}` && h.at === now);
|
|
346
|
+
if (record?.state !== 'pending') return { effects, error: `Cannot hand off: ${record?.error ?? 'unknown reason'}.` };
|
|
347
|
+
return { effects, result: { ran: `handed off to ${to}; the session is pending pickup`, session_id: b.worker.session_id } };
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
case 'conversation_transfer': {
|
|
351
|
+
const to = args.to ? String(args.to) : '';
|
|
352
|
+
if (!to) throw new Error('to is required');
|
|
353
|
+
const b = surface ? liveBinding(profile, surface) : null;
|
|
354
|
+
if (!b) throw new Error('No live conversation to transfer.');
|
|
355
|
+
const history = ['full', 'filtered', 'none'].includes(args.history) ? args.history : 'full';
|
|
356
|
+
await orch.dispatch(events.operator({ verb: 'conversation_transfer', profile: profile.name, args: { keyString: surface, to, reason: String(args.reason ?? ''), history, ...(history === 'filtered' ? { filter: { last: Number(args.last ?? 20) } } : {}) }, at: now }));
|
|
357
|
+
const record = [...(orch.state.transfers ?? [])].reverse().find((t) => t.at === now && t.to === to);
|
|
358
|
+
if (record?.state !== 'done') return { effects, error: `Transfer refused: ${record?.error ?? 'unknown reason'}.` };
|
|
359
|
+
return { effects, result: { ran: `transferred the conversation to ${to}`, conversation: record.conversation } };
|
|
338
360
|
}
|
|
339
361
|
|
|
340
362
|
default:
|
package/ontology.d.ts
CHANGED
|
@@ -31,6 +31,26 @@ export interface Action {
|
|
|
31
31
|
args: unknown;
|
|
32
32
|
}
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* One agent this home declares: who answers, and which profile is its template.
|
|
36
|
+
* A named profile implies its own agent of the same name; a declaration names others (several
|
|
37
|
+
* agents may share one profile) and the parent each is declared under.
|
|
38
|
+
*/
|
|
39
|
+
export interface AgentDecl {
|
|
40
|
+
/** Unique among the home's agents; a route, a speaker policy and a binding name it. */
|
|
41
|
+
name: string;
|
|
42
|
+
/** The profile it runs as (its layered template). */
|
|
43
|
+
profile: string;
|
|
44
|
+
/** A display label, not identity. */
|
|
45
|
+
label?: string | null;
|
|
46
|
+
/** The agent it is declared under, if not the home's root. */
|
|
47
|
+
parent?: string | null;
|
|
48
|
+
/** A person set on purpose as its sponsor; absent, the sponsor is inherited. */
|
|
49
|
+
sponsor?: string | null;
|
|
50
|
+
/** What a source format said about it that the IR has no field for, verbatim. */
|
|
51
|
+
residue?: Record<string, unknown>;
|
|
52
|
+
}
|
|
53
|
+
|
|
34
54
|
/** What one artifact reached on the way in or out. */
|
|
35
55
|
export interface ArtifactFidelity {
|
|
36
56
|
/** Path relative to the home the codec read or wrote. */
|
|
@@ -65,6 +85,10 @@ export interface Binding {
|
|
|
65
85
|
key: SurfaceKey;
|
|
66
86
|
/** The profile that owns it (`None` = the home's default). */
|
|
67
87
|
profile?: string | null;
|
|
88
|
+
/** The conversation it holds a session in (G1/G5); `None` where the source records none. */
|
|
89
|
+
conversation?: string | null;
|
|
90
|
+
/** The agent whose session it is; with `conversation`, its key. `None` where the source records none. */
|
|
91
|
+
agent?: string | null;
|
|
68
92
|
/** The worker session. */
|
|
69
93
|
worker: Worker;
|
|
70
94
|
/**
|
|
@@ -89,6 +113,34 @@ export interface Binding {
|
|
|
89
113
|
residue?: Residue;
|
|
90
114
|
}
|
|
91
115
|
|
|
116
|
+
/**
|
|
117
|
+
* A per-action gate on a profile's agents: a start or resume over it is refused, with the reason,
|
|
118
|
+
* and the refusal is told to the manager and the sponsor. It never pauses or ends anything itself.
|
|
119
|
+
*/
|
|
120
|
+
export interface Budget {
|
|
121
|
+
/** The window. */
|
|
122
|
+
period: BudgetPeriod;
|
|
123
|
+
/** The bound. */
|
|
124
|
+
limit: BudgetLimit;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/** What a budget bounds. */
|
|
128
|
+
export interface BudgetLimit {
|
|
129
|
+
/** Total tokens. */
|
|
130
|
+
tokens?: number | null;
|
|
131
|
+
/** Total cost. */
|
|
132
|
+
cost?: Cost | null;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** A budget's window. */
|
|
136
|
+
export type BudgetPeriod =
|
|
137
|
+
/** One run. */
|
|
138
|
+
| 'run'
|
|
139
|
+
/** A calendar day. */
|
|
140
|
+
| 'day'
|
|
141
|
+
/** A calendar month. */
|
|
142
|
+
| 'month';
|
|
143
|
+
|
|
92
144
|
/** One platform's configuration. */
|
|
93
145
|
export interface ChannelConfig {
|
|
94
146
|
/** The platform name (`telegram`, `slack`, `api_server`, …). */
|
|
@@ -101,6 +153,43 @@ export interface ChannelConfig {
|
|
|
101
153
|
extra?: Record<string, unknown>;
|
|
102
154
|
}
|
|
103
155
|
|
|
156
|
+
/** A conversation, a Resource separate from the sessions bound to it (G5, amended by M3). */
|
|
157
|
+
export interface Conversation {
|
|
158
|
+
/** Its id. */
|
|
159
|
+
id: string;
|
|
160
|
+
/** Thread or private. */
|
|
161
|
+
kind: ConversationKind;
|
|
162
|
+
/** Where a thread is shown; no profile is part of it. */
|
|
163
|
+
surface?: SurfaceKey | null;
|
|
164
|
+
/** People and agents in it. */
|
|
165
|
+
participants?: Participant[];
|
|
166
|
+
/** Who receives a line. */
|
|
167
|
+
speaker?: SpeakerPolicy;
|
|
168
|
+
/** Where its record lives. */
|
|
169
|
+
history?: HistoryRef;
|
|
170
|
+
/** The agent a completed transfer gave the conversation to; an unaddressed line goes to it. */
|
|
171
|
+
holder?: string | null;
|
|
172
|
+
/** The agent that took the last line (round robin's position). */
|
|
173
|
+
last_speaker?: string | null;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/** `thread`: a root and its replies, wherever it is shown; `private`: a harness session's own input. */
|
|
177
|
+
export type ConversationKind =
|
|
178
|
+
/** A root and its replies (a Room conversation, a chat thread, a mailbox exchange). */
|
|
179
|
+
| 'thread'
|
|
180
|
+
/** A harness session's own conversation with its owner; its history is that transcript. */
|
|
181
|
+
| 'private';
|
|
182
|
+
|
|
183
|
+
/** A cost, as the provider reported it or a rate table priced it. */
|
|
184
|
+
export interface Cost {
|
|
185
|
+
/** The amount. */
|
|
186
|
+
amount: number;
|
|
187
|
+
/** ISO currency. */
|
|
188
|
+
currency: string;
|
|
189
|
+
/** `provider` or `rate_table`. */
|
|
190
|
+
source?: string | null;
|
|
191
|
+
}
|
|
192
|
+
|
|
104
193
|
/** A transition taken once a duration has passed in the status (XState's `after`, ASL's `Wait`). */
|
|
105
194
|
export interface Delayed {
|
|
106
195
|
/** How long, in seconds (an expression). */
|
|
@@ -152,6 +241,10 @@ export type EndReason =
|
|
|
152
241
|
| 'new'
|
|
153
242
|
/** Moved to another surface. */
|
|
154
243
|
| 'handoff'
|
|
244
|
+
/** The conversation was transferred to another agent (G2). */
|
|
245
|
+
| 'transfer'
|
|
246
|
+
/** The agent left the conversation. */
|
|
247
|
+
| 'left'
|
|
155
248
|
/** The worker failed. */
|
|
156
249
|
| 'error';
|
|
157
250
|
|
|
@@ -240,9 +333,43 @@ export interface Handoff {
|
|
|
240
333
|
error?: string | null;
|
|
241
334
|
}
|
|
242
335
|
|
|
336
|
+
/** A session moving to another conversation (Hermes `/handoff`, kept by the naming rule). */
|
|
337
|
+
export interface Handoff2 {
|
|
338
|
+
/** The session (`<harness>:<id>`). */
|
|
339
|
+
session: string;
|
|
340
|
+
/** The target conversation. */
|
|
341
|
+
to: string;
|
|
342
|
+
/** Who asked. */
|
|
343
|
+
by: string;
|
|
344
|
+
/** Its progress. */
|
|
345
|
+
state: HandoffState;
|
|
346
|
+
/** Why it failed. */
|
|
347
|
+
error?: string | null;
|
|
348
|
+
/** RFC3339. */
|
|
349
|
+
at: string;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/** A handoff's progress. */
|
|
353
|
+
export type HandoffState =
|
|
354
|
+
/** Announced on the target, not yet picked up. */
|
|
355
|
+
| 'pending'
|
|
356
|
+
/** The session is bound there. */
|
|
357
|
+
| 'done'
|
|
358
|
+
/** It could not move. */
|
|
359
|
+
| 'failed';
|
|
360
|
+
|
|
243
361
|
/** Extensible identifier for a coding harness. */
|
|
244
362
|
export type HarnessId = string;
|
|
245
363
|
|
|
364
|
+
/** Where a conversation's record lives. */
|
|
365
|
+
export type HistoryRef =
|
|
366
|
+
/** The platform's own thread (a chat thread, a Room conversation). */
|
|
367
|
+
| { kind: 'platform' }
|
|
368
|
+
/** The mailbox thread. */
|
|
369
|
+
| { thread: string; kind: 'mailbox' }
|
|
370
|
+
/** A private conversation's history: its owning session's transcript. */
|
|
371
|
+
| { session: string; kind: 'transcript' };
|
|
372
|
+
|
|
246
373
|
/** One scheduled job. */
|
|
247
374
|
export interface Job {
|
|
248
375
|
/** The id (a file-name-safe token). */
|
|
@@ -270,6 +397,11 @@ export interface Job {
|
|
|
270
397
|
* the worker allows), instead of a session of its own; Hermes mirrors it into that transcript.
|
|
271
398
|
*/
|
|
272
399
|
attach_to_session?: boolean | null;
|
|
400
|
+
/**
|
|
401
|
+
* Which session a fire runs in: `main` (its agent's main session), `current` (the binding's session),
|
|
402
|
+
* `isolated` (a new one) or `session:<id>` (that one). Absent: the source's own default.
|
|
403
|
+
*/
|
|
404
|
+
session_target?: string | null;
|
|
273
405
|
/** Remaining-runs counter for `once` jobs. */
|
|
274
406
|
repeat?: Repeat | null;
|
|
275
407
|
/** Whether it fires at all. */
|
|
@@ -373,6 +505,16 @@ export interface Orchestration {
|
|
|
373
505
|
profiles: Record<string, Profile>;
|
|
374
506
|
/** O — how the home's boards are worked (`workflow.yaml` at the root; Hermes's dispatcher when there is none). */
|
|
375
507
|
workflow?: Workflow;
|
|
508
|
+
/** O — declared agents by name (§2.10); a named profile implies its own agent without one. */
|
|
509
|
+
agents?: Record<string, AgentDecl>;
|
|
510
|
+
/** O — conversations by id, separate from the sessions bound to them (G5). */
|
|
511
|
+
conversations?: Record<string, Conversation>;
|
|
512
|
+
/** O — transfers between agents, in order (G2). */
|
|
513
|
+
transfers?: Transfer[];
|
|
514
|
+
/** O — sessions moved to other conversations, in order (G2). */
|
|
515
|
+
handoffs?: Handoff2[];
|
|
516
|
+
/** O — usage per session (`<harness>:<id>`), summed per agent (G3). */
|
|
517
|
+
usage?: Record<string, SessionUsage>;
|
|
376
518
|
}
|
|
377
519
|
|
|
378
520
|
/** What is delivered. */
|
|
@@ -387,6 +529,25 @@ export interface OutboundContent {
|
|
|
387
529
|
format?: string | null;
|
|
388
530
|
}
|
|
389
531
|
|
|
532
|
+
/** A person or an agent in a conversation. */
|
|
533
|
+
export interface Participant {
|
|
534
|
+
/** An agent's name, or a person as `<platform>:<user id>` (an identity observation). */
|
|
535
|
+
principal: string;
|
|
536
|
+
/** To or CC. */
|
|
537
|
+
role: ParticipantRole;
|
|
538
|
+
/** RFC3339. */
|
|
539
|
+
since: string;
|
|
540
|
+
/** RFC3339, when it left. */
|
|
541
|
+
until?: string | null;
|
|
542
|
+
}
|
|
543
|
+
|
|
544
|
+
/** How a participant is addressed on a thread (amendment M3). */
|
|
545
|
+
export type ParticipantRole =
|
|
546
|
+
/** Addressed: expected to act. */
|
|
547
|
+
| 'to'
|
|
548
|
+
/** Copied: receives every reply. */
|
|
549
|
+
| 'cc';
|
|
550
|
+
|
|
390
551
|
/** What happens to a worker's permission prompt when no human answers. */
|
|
391
552
|
export type PermissionDefault =
|
|
392
553
|
/** Refuse after the timeout. */
|
|
@@ -459,6 +620,8 @@ export interface Profile {
|
|
|
459
620
|
fires?: Fire[];
|
|
460
621
|
/** H — `delivery_obligations`. */
|
|
461
622
|
obligations?: Obligation[];
|
|
623
|
+
/** O — per-action gates on this profile's agents (G3); they only narrow down the layers. */
|
|
624
|
+
budgets?: Budget[];
|
|
462
625
|
/** What the model does not interpret. */
|
|
463
626
|
residue?: ProfileResidue;
|
|
464
627
|
}
|
|
@@ -504,8 +667,8 @@ export interface Route {
|
|
|
504
667
|
name?: string | null;
|
|
505
668
|
/** What it matches. */
|
|
506
669
|
match: RouteMatch;
|
|
507
|
-
/** The
|
|
508
|
-
|
|
670
|
+
/** The agent that answers (G1); a named profile's own agent bears the profile's name. */
|
|
671
|
+
agent: string;
|
|
509
672
|
/** Unmodeled fields of the route, verbatim. */
|
|
510
673
|
residue?: Residue;
|
|
511
674
|
}
|
|
@@ -581,6 +744,27 @@ export type SecretRef =
|
|
|
581
744
|
/** A key in the home's own `.env` file. */
|
|
582
745
|
| { dotenv: string };
|
|
583
746
|
|
|
747
|
+
/** A session's usage, kept on the session and summed upward (session → agent → sponsor → Org). */
|
|
748
|
+
export interface SessionUsage {
|
|
749
|
+
/** The agent the session belongs to, when it has one. */
|
|
750
|
+
agent?: string | null;
|
|
751
|
+
/** The records. */
|
|
752
|
+
usage?: Usage[];
|
|
753
|
+
}
|
|
754
|
+
|
|
755
|
+
/** Which bound agents receive a line on a shared surface (G1). */
|
|
756
|
+
export type SpeakerPolicy =
|
|
757
|
+
/** Mentions pick the agent; `default` takes the rest (a Hermes or OpenClaw surface: one agent). */
|
|
758
|
+
| { default?: string | null; kind: 'addressed' }
|
|
759
|
+
/** Every bound agent gets every line. */
|
|
760
|
+
| { kind: 'all' }
|
|
761
|
+
/** Agents take lines in this order. */
|
|
762
|
+
| { order: string[]; kind: 'round_robin' }
|
|
763
|
+
/** An agent picks the next speaker (an event out and back, never a hidden model call). */
|
|
764
|
+
| { selector: string; kind: 'selector' }
|
|
765
|
+
/** The meeting's adapter decides (RH2's floor, the voice pack). */
|
|
766
|
+
| { kind: 'floor' };
|
|
767
|
+
|
|
584
768
|
/** One status a card can be in. */
|
|
585
769
|
export interface Status {
|
|
586
770
|
/**
|
|
@@ -647,6 +831,48 @@ export type Target =
|
|
|
647
831
|
/** A named surface, as `hermes send --to` spells one. */
|
|
648
832
|
| { platform: string; chat_id?: string | null; thread_id?: string | null; kind: 'explicit' };
|
|
649
833
|
|
|
834
|
+
/** One agent handing a conversation to another (OpenAI handoff, AutoGen Swarm, voice `hand_off`). */
|
|
835
|
+
export interface Transfer {
|
|
836
|
+
/** The conversation. */
|
|
837
|
+
conversation: string;
|
|
838
|
+
/** The giving agent. */
|
|
839
|
+
from: string;
|
|
840
|
+
/** The receiving agent. */
|
|
841
|
+
to: string;
|
|
842
|
+
/** Who did it (the giving agent, or whom the speaker policy allows). */
|
|
843
|
+
by: string;
|
|
844
|
+
/** Why. */
|
|
845
|
+
reason: string;
|
|
846
|
+
/** What history the receiver is given. */
|
|
847
|
+
history: TransferHistory;
|
|
848
|
+
/** For `filtered`: which part (`{"last": N}`). */
|
|
849
|
+
filter?: unknown;
|
|
850
|
+
/** Its progress. */
|
|
851
|
+
state: TransferState;
|
|
852
|
+
/** RFC3339. */
|
|
853
|
+
at: string;
|
|
854
|
+
/** Why it was refused. */
|
|
855
|
+
error?: string | null;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
/** How much of the conversation a transfer's receiver is given. */
|
|
859
|
+
export type TransferHistory =
|
|
860
|
+
/** All of it (the default). */
|
|
861
|
+
| 'full'
|
|
862
|
+
/** What the filter keeps. */
|
|
863
|
+
| 'filtered'
|
|
864
|
+
/** None. */
|
|
865
|
+
| 'none';
|
|
866
|
+
|
|
867
|
+
/** A transfer's progress. */
|
|
868
|
+
export type TransferState =
|
|
869
|
+
/** Asked, not yet applied. */
|
|
870
|
+
| 'pending'
|
|
871
|
+
/** The receiver holds the conversation. */
|
|
872
|
+
| 'done'
|
|
873
|
+
/** The receiver may not take part. */
|
|
874
|
+
| 'refused';
|
|
875
|
+
|
|
650
876
|
/** A move from the card's status on an event (or on none: `always`, `after`). */
|
|
651
877
|
export interface Transition {
|
|
652
878
|
/** Source statuses; empty applies from every status. */
|
|
@@ -689,6 +915,24 @@ export type Trigger =
|
|
|
689
915
|
/** The source does not say. */
|
|
690
916
|
| 'unknown';
|
|
691
917
|
|
|
918
|
+
/** One measured use of a model, from the harness's own records (G3). */
|
|
919
|
+
export interface Usage {
|
|
920
|
+
/** RFC3339. */
|
|
921
|
+
at: string;
|
|
922
|
+
/** The model. */
|
|
923
|
+
model: string;
|
|
924
|
+
/** Input tokens. */
|
|
925
|
+
input_tokens: number;
|
|
926
|
+
/** Output tokens. */
|
|
927
|
+
output_tokens: number;
|
|
928
|
+
/** Cache reads, when measured. */
|
|
929
|
+
cache_read_tokens?: number | null;
|
|
930
|
+
/** Cache writes, when measured. */
|
|
931
|
+
cache_write_tokens?: number | null;
|
|
932
|
+
/** Its cost, when known. */
|
|
933
|
+
cost?: Cost | null;
|
|
934
|
+
}
|
|
935
|
+
|
|
692
936
|
/** A validator: the expression must hold, else the event is refused with the message. */
|
|
693
937
|
export interface Validation {
|
|
694
938
|
/** What must hold. */
|
package/operator.mjs
CHANGED
|
@@ -43,6 +43,7 @@ export const OPERATOR_OPS = Object.freeze([
|
|
|
43
43
|
'profiles.create', 'profiles.delete',
|
|
44
44
|
'sessions.new', 'sessions.reset',
|
|
45
45
|
'access.pair_approve',
|
|
46
|
+
'agents.fork',
|
|
46
47
|
]);
|
|
47
48
|
|
|
48
49
|
/** Where a deleted profile folder is renamed to, relative to the root. */
|
|
@@ -387,10 +388,14 @@ async function run(state, profile, op, args, now, send) {
|
|
|
387
388
|
const code = String(args.code ?? '').trim();
|
|
388
389
|
if (!code) throw new Error('code is required');
|
|
389
390
|
// Hermes's pairing store holds the code; the daemon asks it, and a grant reaches the allowlist
|
|
390
|
-
await send('pair_approve', { code });
|
|
391
|
+
await send('pair_approve', { code, principal: args.principal ? String(args.principal) : null });
|
|
391
392
|
return { ran: `asked Hermes's pairing store to approve ${code} for profile ${profile.name}`, code };
|
|
392
393
|
}
|
|
393
394
|
|
|
395
|
+
case 'agents.fork':
|
|
396
|
+
// The live daemon's door performs it (mcp/bridge.mjs): it declares a child and starts its session.
|
|
397
|
+
throw new Error('agents.fork starts the child agent\'s session; it runs only through a live orchestrator daemon');
|
|
398
|
+
|
|
394
399
|
default:
|
|
395
400
|
throw new Error(`unknown operator op ${op}`);
|
|
396
401
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@volter/supercode-orchestrator",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.1",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The orchestrator runtime over the Volter Harness ontology: one typed operational model whose folder is its serialization, read and written through the harness orchestration doors (docs/ORCHESTRATOR-IR.md)",
|
|
6
6
|
"exports": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"@volter/supercode-harness-sdk": "^0.3.41",
|
|
28
28
|
"@volter/ztrack": "^2.4.21",
|
|
29
29
|
"yaml": "^2.9.0",
|
|
30
|
-
"@volter/
|
|
30
|
+
"@volter/teams": "0.2.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@chat-adapter/state-memory": "4.39.0",
|