@agent-compose/sdk 0.8.2 → 0.8.3
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/dist/agent/__tests__/perf-sampler.test.d.ts +10 -0
- package/dist/agent/agent-context.d.ts +1 -1
- package/dist/agent/agent-loop.d.ts +5 -1
- package/dist/agent/desktop-open.d.ts +184 -0
- package/dist/agent/perf-sampler.d.ts +99 -0
- package/dist/agent/services-manifest.d.ts +88 -0
- package/dist/agent/services-restore.d.ts +58 -0
- package/dist/client.d.ts +164 -8
- package/dist/display.d.ts +17 -0
- package/dist/index.d.ts +13 -4
- package/dist/index.js +1374 -51
- package/dist/runtimes/_cli-agent.d.ts +347 -2
- package/dist/runtimes/claude-code.d.ts +12 -0
- package/dist/runtimes/codex.d.ts +8 -0
- package/dist/runtimes/openai-desktop.js +1312 -51
- package/dist/runtimes/session-env.test.d.ts +14 -0
- package/dist/types/api-conversations.d.ts +309 -1
- package/dist/types/api-factory.d.ts +115 -10
- package/dist/types/api-runs.d.ts +21 -0
- package/dist/types/protocol.d.ts +32 -1
- package/dist/types/runtime.d.ts +120 -0
- package/package.json +1 -1
- package/src/agent/agent-context.ts +100 -11
- package/src/agent/agent-loop.ts +10 -3
- package/src/agent/desktop-open.ts +418 -0
- package/src/agent/perf-sampler.ts +202 -0
- package/src/agent/services-manifest.ts +356 -0
- package/src/agent/services-restore.ts +195 -0
- package/src/client.ts +328 -12
- package/src/display.ts +44 -1
- package/src/index.ts +63 -1
- package/src/runtimes/_cli-agent.ts +891 -35
- package/src/runtimes/claude-code.ts +187 -12
- package/src/runtimes/codex.ts +58 -1
- package/src/sandbox/providers/local.ts +16 -4
- package/src/types/api-conversations.ts +307 -3
- package/src/types/api-factory.ts +118 -10
- package/src/types/api-runs.ts +23 -0
- package/src/types/protocol.ts +30 -1
- package/src/types/runtime.ts +122 -0
|
@@ -95,10 +95,36 @@ export interface ConversationRow {
|
|
|
95
95
|
unreadCount?: number;
|
|
96
96
|
}
|
|
97
97
|
|
|
98
|
+
/** Agent-author identity decoration (mirrors the server's `agentAuthor`
|
|
99
|
+
* on message rows and stream payloads): rows authored by a user's agent
|
|
100
|
+
* that is not the conversation's resident agent — the assistant's
|
|
101
|
+
* delegated sends, review briefs, and PEER-SESSION messages
|
|
102
|
+
* (`sourceChannel: 'session'`). The persona `name` is the author label;
|
|
103
|
+
* `avatarSeed` is the agent's own generated orb; the owner names WHOSE
|
|
104
|
+
* agent it is. */
|
|
105
|
+
export interface ConversationAgentAuthor {
|
|
106
|
+
agentId: string;
|
|
107
|
+
name: string;
|
|
108
|
+
avatarSeed: string;
|
|
109
|
+
ownerUserId: string | null;
|
|
110
|
+
ownerName: string | null;
|
|
111
|
+
}
|
|
112
|
+
|
|
98
113
|
export interface ConversationMessageRow {
|
|
99
114
|
id: string;
|
|
100
115
|
authorKind: string;
|
|
101
116
|
authorId: string | null;
|
|
117
|
+
/** The author's display name, resolved server-side — a HUMAN author's
|
|
118
|
+
* display name, or an attributable AGENT author's persona name (see
|
|
119
|
+
* `agentAuthor`). Null for resident-agent/system rows; absent on older
|
|
120
|
+
* servers. */
|
|
121
|
+
authorLabel?: string | null;
|
|
122
|
+
/** Sender identity for foreign-agent and peer-session rows — render the
|
|
123
|
+
* persona name + its avatarSeed FIRST, before any session/runtime
|
|
124
|
+
* fallback (the one resolution order; streamed and settled renders are
|
|
125
|
+
* identical). Null/absent on resident-agent, session channel-post, and
|
|
126
|
+
* older-server rows. */
|
|
127
|
+
agentAuthor?: ConversationAgentAuthor | null;
|
|
102
128
|
parts: ConversationMessagePart[];
|
|
103
129
|
threadRootId: string | null;
|
|
104
130
|
reactions: Record<string, string[]>;
|
|
@@ -115,6 +141,12 @@ export interface ConversationMessageRow {
|
|
|
115
141
|
* rows to the session (title + runtime mark), never a resident agent.
|
|
116
142
|
* Null once the session is deleted; absent on older servers. */
|
|
117
143
|
sourceSessionId?: string | null;
|
|
144
|
+
/** THE ORIGIN SURFACE (ADR-0073 §6.5): the ingress the row arrived over —
|
|
145
|
+
* 'sms' / 'phone' / 'voice' on inbound user rows, 'assistant' on
|
|
146
|
+
* delegated sends, 'session' on peer session→session messages (whose
|
|
147
|
+
* author identity rides `agentAuthor`). Null/absent = an ordinary
|
|
148
|
+
* in-app send or an older server. */
|
|
149
|
+
sourceChannel?: "sms" | "phone" | "voice" | "assistant" | "session" | null;
|
|
118
150
|
/** Set on a session-transcript row RELAYED from a channel mention
|
|
119
151
|
* (ADR-0057 Seam 3) — the channel it arrived from. Null once the
|
|
120
152
|
* channel is deleted; absent on older servers. */
|
|
@@ -133,9 +165,44 @@ export interface ConversationsPage {
|
|
|
133
165
|
/** Sessions page — each row additionally carries its resident
|
|
134
166
|
* executor substrate (ADR-0037 §8): `"cloud"` = persistent server-side
|
|
135
167
|
* sandbox (pickers render the ☁ marker), `"local"` = bridge daemon,
|
|
136
|
-
* null = no durable session record yet
|
|
168
|
+
* null = no durable session record yet — and, on diff-review spawns,
|
|
169
|
+
* `reviewOf`: the session this row was born to REVIEW (id + its current
|
|
170
|
+
* alias/title; a deleted reviewed conversation degrades to a bare id
|
|
171
|
+
* ref). Null/absent for ordinary sessions and older servers. */
|
|
137
172
|
export interface SessionsPage {
|
|
138
|
-
conversations: Array<ConversationRow & {
|
|
173
|
+
conversations: Array<ConversationRow & {
|
|
174
|
+
sessionExecutor: "local" | "cloud" | null;
|
|
175
|
+
reviewOf?: { conversationId: string; alias: string | null; title: string | null; head?: string | null } | null;
|
|
176
|
+
}>;
|
|
177
|
+
next_cursor: string | null;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/** One 15-minute sandbox perf rollup bucket from
|
|
181
|
+
* GET /conversations/:id/perf-history (session_perf_rollups). Null
|
|
182
|
+
* utilization fields = the guest never reported that resource in the
|
|
183
|
+
* bucket — never zero-filled. */
|
|
184
|
+
export interface SessionPerfBucket {
|
|
185
|
+
/** Start of the bucket, ISO 8601. */
|
|
186
|
+
bucket_start: string;
|
|
187
|
+
/** Guest samples folded into the bucket (turn + sweep lanes). */
|
|
188
|
+
samples: number;
|
|
189
|
+
cpu_busy_p50: number | null;
|
|
190
|
+
cpu_busy_p95: number | null;
|
|
191
|
+
mem_used_p50: number | null;
|
|
192
|
+
mem_used_p95: number | null;
|
|
193
|
+
disk_used_p95: number | null;
|
|
194
|
+
load1_max: number | null;
|
|
195
|
+
/** Seconds within the bucket any resource sat ≥90% (capped at 900). */
|
|
196
|
+
saturated_seconds: number;
|
|
197
|
+
vcpu: number | null;
|
|
198
|
+
provider: string;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/** Newest-first, keyset-paginated (house list envelope). */
|
|
202
|
+
export interface SessionPerfHistoryPage {
|
|
203
|
+
object: "list";
|
|
204
|
+
data: SessionPerfBucket[];
|
|
205
|
+
has_more: boolean;
|
|
139
206
|
next_cursor: string | null;
|
|
140
207
|
}
|
|
141
208
|
|
|
@@ -165,6 +232,10 @@ export interface ConversationDetail {
|
|
|
165
232
|
* with a drive branch and a resolvable factory; null/absent = main
|
|
166
233
|
* only (read loosely — older servers omit it). */
|
|
167
234
|
sessionDrive?: { factorySlug: string; branch: string } | null;
|
|
235
|
+
/** THE REVIEWER MARKER (diff-review spawns): non-null ⇒ this session was
|
|
236
|
+
* born to review that conversation's diff. Null for ordinary sessions;
|
|
237
|
+
* absent on older servers (read loosely). */
|
|
238
|
+
sessionReviewOf?: string | null;
|
|
168
239
|
viewerLastReadAt: string | null;
|
|
169
240
|
/** The caller's role in this conversation (ADR-0045) — drives client
|
|
170
241
|
* affordances only; the server remains the authority on every action.
|
|
@@ -181,6 +252,11 @@ export interface ConversationDetail {
|
|
|
181
252
|
* `messages`. Seed the stream's first `Last-Event-ID` from it instead of
|
|
182
253
|
* 0 (0 replays the entire history). Absent on older servers. */
|
|
183
254
|
streamCursor?: number;
|
|
255
|
+
/** Windowed hydrate (2026-08-17): `messages` is the NEWEST window
|
|
256
|
+
* (default 50; `limit` caps at 200). Non-null = older transcript
|
|
257
|
+
* exists — page it with `GET /conversations/:id/messages?before=` +
|
|
258
|
+
* this opaque cursor. Absent on older servers. */
|
|
259
|
+
olderCursor?: string | null;
|
|
184
260
|
messages: ConversationMessageRow[];
|
|
185
261
|
}
|
|
186
262
|
|
|
@@ -391,6 +467,13 @@ export interface SessionChangeSet {
|
|
|
391
467
|
truncated: boolean;
|
|
392
468
|
/** Open `factory_file_conflicts` rows from this session's prior merges. */
|
|
393
469
|
openConflicts: number;
|
|
470
|
+
/** Graph plane only (additive — absent elsewhere): the opaque cursor for
|
|
471
|
+
* the NEXT page of `changes` — pass it back as `after` on
|
|
472
|
+
* `getSessionChanges`. Null = last page. */
|
|
473
|
+
nextAfter?: string | null;
|
|
474
|
+
/** The serving plane (additive): `"graph"` when the change set is served
|
|
475
|
+
* from the commit graph (paginated, head-anchored); absent = legacy. */
|
|
476
|
+
plane?: "graph";
|
|
394
477
|
/** MERGE GATE (merge-gate spec, additive — absent on older servers):
|
|
395
478
|
* null = ungated. Present: whether THIS caller's merge lands directly
|
|
396
479
|
* (`canMerge` — an owner or named approver) or stages a kind='merge'
|
|
@@ -417,6 +500,22 @@ export interface SessionChangeSet {
|
|
|
417
500
|
reviewEnabled?: boolean;
|
|
418
501
|
reviewSessionConversationId?: string | null;
|
|
419
502
|
reviewSessionActive?: boolean;
|
|
503
|
+
/** BOUND (additive): the bound review session — the FOLLOW-UP LOOP's
|
|
504
|
+
* driver — exists and is not ended (a parked reviewer between turns is
|
|
505
|
+
* bound but not active). Not publish rights: every reviewer of the
|
|
506
|
+
* diff owns its own document; concurrent reviewers are first-class,
|
|
507
|
+
* bounded at spawn (`reviewer_cap`). */
|
|
508
|
+
reviewSessionBound?: boolean;
|
|
509
|
+
/** The AUTOMATIC follow-up loop (additive): armed (default true) + how
|
|
510
|
+
* many automatic rounds ran since the last human-triggered review
|
|
511
|
+
* (hard cap 2; a manual re-review resets it). */
|
|
512
|
+
reviewAutoFollowup?: boolean;
|
|
513
|
+
reviewAutoRounds?: number;
|
|
514
|
+
/** The OPT-IN main-advance auto-rebase reflex (additive — absent on
|
|
515
|
+
* older servers; default OFF): armed ⇒ when main moves and a preflight
|
|
516
|
+
* proves the fold clean, the platform rebases this session's branch
|
|
517
|
+
* from main headlessly. Toggled via `setSessionAutoRebase`. */
|
|
518
|
+
autoRebaseFromMain?: boolean;
|
|
420
519
|
/** STRUCTURED review suggestions beside the notes (additive — absent on
|
|
421
520
|
* older servers): individually actionable {id, path, title, rationale,
|
|
422
521
|
* patch} entries the review session wrote back, status-stamped
|
|
@@ -429,6 +528,34 @@ export interface SessionChangeSet {
|
|
|
429
528
|
* (`mergeable` false, merge 409s `fork_branch_unmergeable`), and it is
|
|
430
529
|
* refused as a review target (409 `review_of_review`). */
|
|
431
530
|
reviewOfConversationId?: string | null;
|
|
531
|
+
/** PER-REVIEWER review documents (additive — absent on older servers;
|
|
532
|
+
* owner ask 2026-08-22): EVERY reviewer's published document for this
|
|
533
|
+
* diff, newest publish first — parallel reviewers each own one. The
|
|
534
|
+
* flat `reviewNotes`/`reviewSuggestions` above are derived aggregates
|
|
535
|
+
* (the primary document's notes; the reviewer-stamped union); this is
|
|
536
|
+
* the grouped truth the review panel renders. Page 1 only — cursor
|
|
537
|
+
* pages serve an empty array. */
|
|
538
|
+
reviewDocuments?: SessionReviewDocument[];
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/** One reviewer's published review document
|
|
542
|
+
* (`SessionChangeSet.reviewDocuments`). `stale` compares the head this
|
|
543
|
+
* document was published against with the served diff. */
|
|
544
|
+
export interface SessionReviewDocument {
|
|
545
|
+
reviewerConversationId: string;
|
|
546
|
+
/** The reviewer session's @alias / title, when its conversation still
|
|
547
|
+
* exists (a deleted reviewer degrades to the bare id). */
|
|
548
|
+
reviewerAlias: string | null;
|
|
549
|
+
reviewerTitle: string | null;
|
|
550
|
+
notes: string;
|
|
551
|
+
suggestions: ReviewSuggestion[];
|
|
552
|
+
/** ISO timestamp of this document's last publish. */
|
|
553
|
+
publishedAt: string;
|
|
554
|
+
/** The diff head published against (null = pre-stamp reviewer). */
|
|
555
|
+
signature: string | null;
|
|
556
|
+
/** Display form of `signature` ("head cd741f27"). */
|
|
557
|
+
headShort: string | null;
|
|
558
|
+
stale: boolean;
|
|
432
559
|
}
|
|
433
560
|
|
|
434
561
|
/** One STRUCTURED, individually actionable suggestion a review session
|
|
@@ -449,6 +576,48 @@ export interface ReviewSuggestion {
|
|
|
449
576
|
* the session branch), `"rejected"`, or `"stale"` (an accept found the
|
|
450
577
|
* file drifted since review; nothing was written). */
|
|
451
578
|
status: "proposed" | "accepted" | "rejected" | "stale";
|
|
579
|
+
/** REVIEWER IDENTITY (additive — present on the flat
|
|
580
|
+
* `SessionChangeSet.reviewSuggestions` union; owner ask 2026-08-22):
|
|
581
|
+
* which reviewer's document this entry came from. Ids are unique only
|
|
582
|
+
* PER REVIEWER — the decide-one route takes `reviewerConversationId`
|
|
583
|
+
* when two reviewers reused an id (409 `ambiguous_suggestion`
|
|
584
|
+
* otherwise). */
|
|
585
|
+
reviewerConversationId?: string;
|
|
586
|
+
reviewerAlias?: string | null;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
/** One suggestion in the review write-back (`publishReviewNotes` /
|
|
590
|
+
* `agentc review publish`): `ReviewSuggestion` minus `status` — the server
|
|
591
|
+
* stamps every stored entry `"proposed"`, so a reviewer can never claim
|
|
592
|
+
* acceptance. `path` must name a file in the change set (refused
|
|
593
|
+
* otherwise). */
|
|
594
|
+
export interface ReviewSuggestionInput {
|
|
595
|
+
id: string;
|
|
596
|
+
path: string;
|
|
597
|
+
title: string;
|
|
598
|
+
rationale: string;
|
|
599
|
+
patch: string;
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/** `POST /conversations/:id/review-notes` — the review session publishing
|
|
603
|
+
* its whole review document (full replace: notes AND suggestions
|
|
604
|
+
* together). Gated to the bound review session's own toolbelt key. */
|
|
605
|
+
export interface ReviewNotesPublished {
|
|
606
|
+
ok: true;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
/** `POST /conversations/:id/review-git-credential` — one fresh short-lived
|
|
610
|
+
* credential for the review git remote, minted per git operation by the
|
|
611
|
+
* sandbox's credential helper (`agentc review git-credential`). Gated to
|
|
612
|
+
* the review session's own toolbelt key; never stored, never reused. */
|
|
613
|
+
export interface ReviewGitCredential {
|
|
614
|
+
/** The stable, credential-free remote URL (`https://host/git/<disk>`). */
|
|
615
|
+
url: string;
|
|
616
|
+
username: string;
|
|
617
|
+
password: string;
|
|
618
|
+
/** ISO timestamp the credential expires — informational (the helper
|
|
619
|
+
* mints anew per operation). */
|
|
620
|
+
expiresAt: string;
|
|
452
621
|
}
|
|
453
622
|
|
|
454
623
|
/** `POST /conversations/:id/changes/suggestions/:suggestionId/decide` —
|
|
@@ -459,6 +628,9 @@ export interface ReviewSuggestionDecision {
|
|
|
459
628
|
conversationId: string;
|
|
460
629
|
id: string;
|
|
461
630
|
status: ReviewSuggestion["status"];
|
|
631
|
+
/** PER-REVIEWER documents (additive): whose document the decided
|
|
632
|
+
* suggestion lives in — null on older servers / legacy ids. */
|
|
633
|
+
reviewerConversationId?: string | null;
|
|
462
634
|
}
|
|
463
635
|
|
|
464
636
|
/** `POST /conversations/:id/changes/suggestions/decide-all` — every stored
|
|
@@ -466,7 +638,7 @@ export interface ReviewSuggestionDecision {
|
|
|
466
638
|
export interface ReviewSuggestionDecisions {
|
|
467
639
|
object: "review_suggestion_decisions";
|
|
468
640
|
conversationId: string;
|
|
469
|
-
results: Array<{ id: string; status: ReviewSuggestion["status"] }>;
|
|
641
|
+
results: Array<{ id: string; status: ReviewSuggestion["status"]; reviewerConversationId?: string | null }>;
|
|
470
642
|
}
|
|
471
643
|
|
|
472
644
|
/** `GET /conversations/:id/changes/stats` — the changes chip's aggregate
|
|
@@ -554,6 +726,81 @@ export interface SessionDiscardReport {
|
|
|
554
726
|
discarded: true;
|
|
555
727
|
}
|
|
556
728
|
|
|
729
|
+
/** One row of the conflict preflight (`GET /conversations/:id/changes/preflight`)
|
|
730
|
+
* — the branch-side change decorated with the REAL merge's own per-file
|
|
731
|
+
* disposition, computed report-only: `fastForward` lands as-is (main
|
|
732
|
+
* untouched at the path), `skip` is already-equal on both sides,
|
|
733
|
+
* `conflict` would 409 the merge today. `autoMerge` is the legacy plane's
|
|
734
|
+
* clean-diff3 class — never emitted on the graph plane. */
|
|
735
|
+
export interface SessionPreflightFileRow {
|
|
736
|
+
path: string;
|
|
737
|
+
kind: "add" | "modify" | "delete";
|
|
738
|
+
disposition: "fastForward" | "autoMerge" | "conflict" | "skip";
|
|
739
|
+
/** Set on `conflict` rows only. */
|
|
740
|
+
conflictReason: "same_region" | "binary" | "delete_vs_edit" | null;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
/** `GET /conversations/:id/changes/preflight` — see conflicts AHEAD of the
|
|
744
|
+
* merge: report-only, no writes, no locks. `unavailable` = no cheap head
|
|
745
|
+
* anchors (legacy plane, unbranched) or the classification faulted — the
|
|
746
|
+
* caller degrades honestly, never fake zeros. `pending` = a cold compute
|
|
747
|
+
* outlived the first-response deadline; poll again to collect it. */
|
|
748
|
+
export type SessionChangePreflight =
|
|
749
|
+
| { object: "session_change_preflight"; conversationId: string; state: "unavailable" }
|
|
750
|
+
| {
|
|
751
|
+
object: "session_change_preflight"; conversationId: string; state: "pending";
|
|
752
|
+
base: string; oursHead: string; theirsHead: string;
|
|
753
|
+
}
|
|
754
|
+
| {
|
|
755
|
+
object: "session_change_preflight"; conversationId: string; state: "ok";
|
|
756
|
+
branch: string;
|
|
757
|
+
base: string;
|
|
758
|
+
/** main's head — the exact commit the dispositions were computed against. */
|
|
759
|
+
oursHead: string;
|
|
760
|
+
/** the session branch's head. */
|
|
761
|
+
theirsHead: string;
|
|
762
|
+
files: SessionPreflightFileRow[];
|
|
763
|
+
conflictCount: number;
|
|
764
|
+
/** Page caps hit — dispositions cover a floor, honestly. */
|
|
765
|
+
truncated: boolean;
|
|
766
|
+
};
|
|
767
|
+
|
|
768
|
+
/** Result of `POST /conversations/:id/changes/rebase` — current main
|
|
769
|
+
* folded INTO the session branch (the reverse merge; main untouched).
|
|
770
|
+
* `rebased` advanced the branch by one merge commit (`rebaseCommit`)
|
|
771
|
+
* and future diffs/merges use the new base. `rebased_with_conflicts`
|
|
772
|
+
* folded the clean remainder (`foldCommit`, null when nothing folded) and
|
|
773
|
+
* KEPT the branch's version for `conflictPaths` — each is recorded as a
|
|
774
|
+
* conflict row and the session was told in-conversation to reconcile. */
|
|
775
|
+
export interface SessionRebaseReport {
|
|
776
|
+
object: "session_rebase_report";
|
|
777
|
+
conversationId: string;
|
|
778
|
+
branch: string;
|
|
779
|
+
outcome: "noop" | "rebased" | "rebased_with_conflicts";
|
|
780
|
+
/** main's head at rebase — the branch's new effective base on a clean
|
|
781
|
+
* rebase. */
|
|
782
|
+
mainHead: string;
|
|
783
|
+
rebaseCommit?: string;
|
|
784
|
+
foldCommit?: string | null;
|
|
785
|
+
folded?: { added: number; modified: number; deleted: number; skipped: number };
|
|
786
|
+
baselineAdvanced?: boolean;
|
|
787
|
+
/** Capped at 100 on the wire; `conflictCount` is the true total. */
|
|
788
|
+
conflictPaths?: string[];
|
|
789
|
+
conflictCount?: number;
|
|
790
|
+
conflictsTruncated?: boolean;
|
|
791
|
+
/** True when the gateway truncated its conflict list — the fold was
|
|
792
|
+
* skipped whole (an unlisted conflicted path must never be overwritten). */
|
|
793
|
+
foldSkipped?: boolean;
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
/** Result of `POST /conversations/:id/changes/autorebase` — the opt-in
|
|
797
|
+
* main-advance auto-rebase reflex's new state. */
|
|
798
|
+
export interface SessionAutoRebaseState {
|
|
799
|
+
object: "session_autorebase";
|
|
800
|
+
conversationId: string;
|
|
801
|
+
autoRebaseFromMain: boolean;
|
|
802
|
+
}
|
|
803
|
+
|
|
557
804
|
/** The sender's page stamp (HUD bar sends) — persisted server-side, never
|
|
558
805
|
* echoed back on the wire. Mirrors the server's `PageContext` schema. */
|
|
559
806
|
export interface ConversationPageContext {
|
|
@@ -672,6 +919,63 @@ export interface SessionChannelMessagePosted {
|
|
|
672
919
|
threadRootId?: string | null;
|
|
673
920
|
}
|
|
674
921
|
|
|
922
|
+
/** Result of `POST /session-messages` — one session's agent messaging
|
|
923
|
+
* ANOTHER session's conversation (`agentc session message @alias`). Unlike
|
|
924
|
+
* a channel post, this DOES wake the target's turn machinery: `turn` is
|
|
925
|
+
* the server's verdict ('started' | 'queued' | 'parked' — the agent-to-
|
|
926
|
+
* agent exchange damper landed the message without waking anyone). */
|
|
927
|
+
export interface SessionDirectMessageSent {
|
|
928
|
+
object: "session_message";
|
|
929
|
+
messageId: string;
|
|
930
|
+
target: { conversationId: string; alias: string | null; title: string | null };
|
|
931
|
+
turn: "started" | "queued" | "parked";
|
|
932
|
+
/** Honest posture line — delivery is not completion. */
|
|
933
|
+
note: string;
|
|
934
|
+
}
|
|
935
|
+
|
|
936
|
+
/** One branch claim, as the claim/release routes serialize it. */
|
|
937
|
+
export interface BranchClaimInfo {
|
|
938
|
+
id: string;
|
|
939
|
+
branch: string;
|
|
940
|
+
targetConversationId: string;
|
|
941
|
+
holderConversationId: string;
|
|
942
|
+
targetLabel: string;
|
|
943
|
+
holderLabel: string;
|
|
944
|
+
reason: string | null;
|
|
945
|
+
claimedAt: string;
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
/** Result of `POST /session-branch-claims` — write authority over the
|
|
949
|
+
* target session's drive branch transferred to the calling session, plus
|
|
950
|
+
* the mount material the CLI uses to FUSE-mount the branch in-guest. */
|
|
951
|
+
export interface BranchClaimGranted {
|
|
952
|
+
object: "branch_claim";
|
|
953
|
+
claim: BranchClaimInfo;
|
|
954
|
+
/** True = the caller already held this claim (re-mint / re-mount path). */
|
|
955
|
+
reclaimedOwn: boolean;
|
|
956
|
+
branch: string;
|
|
957
|
+
token: string;
|
|
958
|
+
gatewayWsUrl: string;
|
|
959
|
+
expiresAtS: number;
|
|
960
|
+
diskId: string;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
/** Result of `POST /session-branch-claims/release` (and the human reclaim
|
|
964
|
+
* door) — the claims this call closed. */
|
|
965
|
+
export interface BranchClaimsReleased {
|
|
966
|
+
object: "branch_claim.release";
|
|
967
|
+
released: BranchClaimInfo[];
|
|
968
|
+
}
|
|
969
|
+
|
|
970
|
+
/** `GET /conversations/:id/branch-claim` — one session's claim state: the
|
|
971
|
+
* live claim ON its branch (null = writable there), and the claims it
|
|
972
|
+
* HOLDS on other sessions' branches. */
|
|
973
|
+
export interface BranchClaimState {
|
|
974
|
+
object: "branch_claim.state";
|
|
975
|
+
claimedBy: BranchClaimInfo | null;
|
|
976
|
+
holds: BranchClaimInfo[];
|
|
977
|
+
}
|
|
978
|
+
|
|
675
979
|
/** One agent on the team, as listed by `GET /api/v1/agents`. Bridge-runtime
|
|
676
980
|
* rows additionally carry live presence (`online`, from the daemon's
|
|
677
981
|
* heartbeat within the server's TTL) and the hosting machine's label. */
|
package/src/types/api-factory.ts
CHANGED
|
@@ -192,6 +192,48 @@ export interface FactoryFileSearchResult {
|
|
|
192
192
|
folders_truncated?: boolean;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
// ── Factory-file listing (`GET /files` — live index or browse-at-head) ─────
|
|
196
|
+
|
|
197
|
+
/** One file row of `GET /factories/:slug/files` — the flat recursive
|
|
198
|
+
* listing. Same row shape live and at a pinned head; rows arrive
|
|
199
|
+
* camelCase on the wire (mirrors `FactoryFileSearchRow`). */
|
|
200
|
+
export interface FactoryFileListRow {
|
|
201
|
+
id: string;
|
|
202
|
+
path: string;
|
|
203
|
+
sizeBytes: number;
|
|
204
|
+
contentType: string | null;
|
|
205
|
+
contentHash: string;
|
|
206
|
+
deletedAt: string | null;
|
|
207
|
+
createdAt: string;
|
|
208
|
+
updatedAt: string;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
export interface ListFactoryFilesOptions {
|
|
212
|
+
factorySlug?: string;
|
|
213
|
+
/** Only paths under this prefix. */
|
|
214
|
+
prefix?: string;
|
|
215
|
+
/** Path cursor from a prior page's `nextCursor`. */
|
|
216
|
+
cursor?: string;
|
|
217
|
+
limit?: number;
|
|
218
|
+
/** List AS OF a drive branch (e.g. a session's `session-<uuid>`). */
|
|
219
|
+
branch?: string;
|
|
220
|
+
/** Browse-at-head: a retained 64-hex commit of the MAIN drive (or, with
|
|
221
|
+
* `branch`, a pin of that graph branch). The server answers 410
|
|
222
|
+
* `at_unavailable` for a garbage-collected/unknown head. */
|
|
223
|
+
at?: string;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/** One page of `GET /factories/:slug/files`. */
|
|
227
|
+
export interface FactoryFileListPage {
|
|
228
|
+
data: FactoryFileListRow[];
|
|
229
|
+
hasMore: boolean;
|
|
230
|
+
/** Pass as `cursor` to fetch the next page; null on the last page. */
|
|
231
|
+
nextCursor: string | null;
|
|
232
|
+
/** The pinned head this page was read at — non-null exactly when the
|
|
233
|
+
* request carried `at`. `committedAt` is RFC3339 or null (unknown). */
|
|
234
|
+
at: { head: string; committedAt: string | null } | null;
|
|
235
|
+
}
|
|
236
|
+
|
|
195
237
|
export interface FactoryFileWriteResult {
|
|
196
238
|
path: string;
|
|
197
239
|
contentHash: string;
|
|
@@ -237,6 +279,28 @@ export interface FactoryRow {
|
|
|
237
279
|
updatedAt: string;
|
|
238
280
|
}
|
|
239
281
|
|
|
282
|
+
/** GET /factories/:slug/perf-summary — team-level sandbox perf aggregates
|
|
283
|
+
* over a window (session_perf_rollups). Aggregate-only by design: sessions
|
|
284
|
+
* are member-gated, so no conversation ids appear here; per-session detail
|
|
285
|
+
* is the member-gated perf-history surface. */
|
|
286
|
+
export interface FactoryPerfSummary {
|
|
287
|
+
/** The aggregated window, ISO 8601. */
|
|
288
|
+
from: string;
|
|
289
|
+
to: string;
|
|
290
|
+
/** Distinct sessions with any rollup bucket in the window. */
|
|
291
|
+
sessions: number;
|
|
292
|
+
/** Rollup buckets (15-min) in the window. */
|
|
293
|
+
buckets: number;
|
|
294
|
+
/** Guest samples folded into those buckets. */
|
|
295
|
+
samples: number;
|
|
296
|
+
cpu_busy_p95_max: number | null;
|
|
297
|
+
mem_used_p95_max: number | null;
|
|
298
|
+
disk_used_p95_max: number | null;
|
|
299
|
+
load1_max: number | null;
|
|
300
|
+
/** Total seconds any session sat ≥90% on a resource, summed. */
|
|
301
|
+
saturated_seconds: number;
|
|
302
|
+
}
|
|
303
|
+
|
|
240
304
|
export interface CreateFactoryInput {
|
|
241
305
|
slug: string;
|
|
242
306
|
name: string;
|
|
@@ -285,6 +349,48 @@ export interface SecretListEntry {
|
|
|
285
349
|
updatedAt: string;
|
|
286
350
|
}
|
|
287
351
|
|
|
352
|
+
/** One SESSION secret on the wire (metadata only — values are write-only).
|
|
353
|
+
* `kind` 'value' = a session-own secret; 'factory' = an attachment by name
|
|
354
|
+
* to the session factory's secret tier. `ownerUserId` is the user who set
|
|
355
|
+
* it — only the owner or a team admin may replace/remove it. */
|
|
356
|
+
export interface SessionSecretEntry {
|
|
357
|
+
secretKey: string;
|
|
358
|
+
kind: "value" | "factory";
|
|
359
|
+
ownerUserId: string;
|
|
360
|
+
/** Delivery mode (vault v2): 'injected' = the session env file;
|
|
361
|
+
* 'brokered' = an egress-ruleset header — the value never enters the
|
|
362
|
+
* sandbox (call the host WITHOUT auth headers; the platform adds them). */
|
|
363
|
+
delivery: "injected" | "brokered";
|
|
364
|
+
/** Brokered entries: the API host the header rides on. */
|
|
365
|
+
brokerHost: string | null;
|
|
366
|
+
/** Non-null = an ephemeral use-and-scrub copy, and when its TTL lapses. */
|
|
367
|
+
ephemeralExpiresAt: string | null;
|
|
368
|
+
createdAt: string;
|
|
369
|
+
updatedAt: string;
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
/** One entry of a session-secret set: a literal value, or a factory
|
|
373
|
+
* attachment by name (`source: "factory"`). */
|
|
374
|
+
export type SessionSecretInput =
|
|
375
|
+
| { key: string; value: string }
|
|
376
|
+
| { key: string; source: "factory" };
|
|
377
|
+
|
|
378
|
+
/** A freshly minted vault link (session secret request). `url` is the
|
|
379
|
+
* single-use page a session writer opens to provide the named values. */
|
|
380
|
+
export interface SessionSecretRequestCreated {
|
|
381
|
+
requestId: string;
|
|
382
|
+
url: string;
|
|
383
|
+
expiresAt: string;
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
/** A vault link's polled status. */
|
|
387
|
+
export interface SessionSecretRequestStatus {
|
|
388
|
+
requestId: string;
|
|
389
|
+
status: "pending" | "fulfilled" | "cancelled" | "expired";
|
|
390
|
+
keys: string[];
|
|
391
|
+
expiresAt: string;
|
|
392
|
+
}
|
|
393
|
+
|
|
288
394
|
export interface CreateApiKeyInput {
|
|
289
395
|
name?: string;
|
|
290
396
|
scopes?: string[];
|
|
@@ -355,9 +461,9 @@ export interface UsageResponse {
|
|
|
355
461
|
|
|
356
462
|
/** One drive-directory ⇄ GitHub-repo link (`/factories/:slug/repo-links`).
|
|
357
463
|
* Multi-branch model: ONE link row per (repo, branch); sibling branches
|
|
358
|
-
* of a repo occupy sibling `base@<branch>` placements.
|
|
359
|
-
*
|
|
360
|
-
*
|
|
464
|
+
* of a repo occupy sibling `base@<branch>` placements. Event delivery is
|
|
465
|
+
* app-level (the platform GitHub App's own webhook) or polling — there
|
|
466
|
+
* is no per-repo webhook setup (retired 2026-08-18). */
|
|
361
467
|
export interface DriveRepoLink {
|
|
362
468
|
id: string;
|
|
363
469
|
factoryId: string;
|
|
@@ -372,11 +478,13 @@ export interface DriveRepoLink {
|
|
|
372
478
|
connectorGrantId: string | null;
|
|
373
479
|
/** v1 links are always 'write' (the round trip is the feature). */
|
|
374
480
|
access: "read" | "write";
|
|
375
|
-
/**
|
|
376
|
-
*
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
481
|
+
/** HOW events reach this link. "app": the platform GitHub App's own
|
|
482
|
+
* registered webhook delivers every installed repo's events (zero
|
|
483
|
+
* per-repo setup). "polling": no app webhook configured — the sweep
|
|
484
|
+
* alone. */
|
|
485
|
+
eventDelivery: "app" | "polling";
|
|
486
|
+
/** When an app-signed GitHub delivery last PROVED event delivery
|
|
487
|
+
* reaches this link; null = unproven. */
|
|
380
488
|
webhookVerifiedAt: string | null;
|
|
381
489
|
/** Two-way sync: drive edits under the prefix push back to the tracked
|
|
382
490
|
* branch. ON by default for new links. */
|
|
@@ -400,8 +508,8 @@ export interface DriveRepoLink {
|
|
|
400
508
|
|
|
401
509
|
/** Input for `POST /factories/:slug/repo-links`. Requires the drive to be
|
|
402
510
|
* graph-authoritative (ADR-0058 Phase 4 promoted) — 409 otherwise.
|
|
403
|
-
*
|
|
404
|
-
*
|
|
511
|
+
* At most one of `followAllBranches` / `trackedBranches`; omitting BOTH
|
|
512
|
+
* is the follow-all default. Follow-all links EVERY
|
|
405
513
|
* branch — default branch primary at the plain `dirPrefix` — and keeps
|
|
406
514
|
* following live (new branches auto-link on push, deleted branches
|
|
407
515
|
* auto-unlink; capped at 100 branches). Explicit `trackedBranches`:
|
package/src/types/api-runs.ts
CHANGED
|
@@ -281,6 +281,29 @@ export interface RunFundingResponse {
|
|
|
281
281
|
};
|
|
282
282
|
}
|
|
283
283
|
|
|
284
|
+
/** One step's attested platform token totals — `GET
|
|
285
|
+
* /workflows/:id/step-usage`. Derived server-side from the spend ledger
|
|
286
|
+
* by step time window (steps run serially, so every gateway call falls in
|
|
287
|
+
* exactly one). Steps with no ledger rows are absent from the list. */
|
|
288
|
+
export interface RunStepUsage {
|
|
289
|
+
stepIndex: number;
|
|
290
|
+
costUsd: number;
|
|
291
|
+
promptTokens: number;
|
|
292
|
+
completionTokens: number;
|
|
293
|
+
cacheReadTokens: number;
|
|
294
|
+
cacheCreationTokens: number;
|
|
295
|
+
calls: number;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
/** `GET /workflows/:id/step-usage`. Empty `steps` is an honest answer: a
|
|
299
|
+
* legacy run with no ledger rows, or a run funded outside the platform
|
|
300
|
+
* lane (that money is never metered — ADR-0048). */
|
|
301
|
+
export interface RunStepUsageResponse {
|
|
302
|
+
object: "run.step_usage";
|
|
303
|
+
runId: string;
|
|
304
|
+
steps: RunStepUsage[];
|
|
305
|
+
}
|
|
306
|
+
|
|
284
307
|
/** One row from the factory runs list (`GET /factories/:slug/runs`) — the
|
|
285
308
|
* summary shape, a strict subset of what the route returns. */
|
|
286
309
|
export interface RunListEntry {
|
package/src/types/protocol.ts
CHANGED
|
@@ -119,6 +119,34 @@ export interface AgentMessagePlan extends AgentMessageBase {
|
|
|
119
119
|
}[];
|
|
120
120
|
}
|
|
121
121
|
|
|
122
|
+
/** A harness `<task-notification>` announcing a BACKGROUND task stopped —
|
|
123
|
+
* an async Agent spawn finishing, a background command exiting, a workflow
|
|
124
|
+
* completing. claude-code injects these as user-role text blocks; the
|
|
125
|
+
* normaliser parses them into structure so downstream can complete the
|
|
126
|
+
* spawning call's card (status, final report, usage) instead of dropping
|
|
127
|
+
* the only completion evidence a background subagent ever emits. Internal
|
|
128
|
+
* plumbing in the raw block (output-file paths, resume hints) is
|
|
129
|
+
* deliberately NOT forwarded — renderers must never see it. Additive
|
|
130
|
+
* kind: existing producers never emit it. */
|
|
131
|
+
export interface AgentMessageTaskNotification extends AgentMessageBase {
|
|
132
|
+
type: "task_notification";
|
|
133
|
+
/** The harness's background task id (`<task-id>`). */
|
|
134
|
+
taskId: string;
|
|
135
|
+
/** The SPAWNING tool_use id (`<tool-use-id>`) when the notification names
|
|
136
|
+
* one — the correlation key back to the Agent/Task call. */
|
|
137
|
+
toolUseId?: string;
|
|
138
|
+
/** Terminal status word — "completed" | "failed" | "stopped" | "killed"
|
|
139
|
+
* (verbatim from the harness; "finished" when the block carried none). */
|
|
140
|
+
status: string;
|
|
141
|
+
/** One-line what-happened ("Agent \"…\" finished"), collapsed + clamped. */
|
|
142
|
+
summary: string;
|
|
143
|
+
/** The task's final report (`<result>`), entity-unescaped and clamped.
|
|
144
|
+
* Absent when the notification carried none. */
|
|
145
|
+
report?: string;
|
|
146
|
+
/** The completion's usage block, when carried. */
|
|
147
|
+
usage?: { tokens?: number; toolUses?: number; durationMs?: number };
|
|
148
|
+
}
|
|
149
|
+
|
|
122
150
|
export type AgentMessage =
|
|
123
151
|
| AgentMessageInit
|
|
124
152
|
| AgentMessageText
|
|
@@ -130,7 +158,8 @@ export type AgentMessage =
|
|
|
130
158
|
| AgentMessageError
|
|
131
159
|
| AgentMessageUsage
|
|
132
160
|
| AgentMessageUsageDelta
|
|
133
|
-
| AgentMessagePlan
|
|
161
|
+
| AgentMessagePlan
|
|
162
|
+
| AgentMessageTaskNotification;
|
|
134
163
|
|
|
135
164
|
/** Status block the agent emits to signal iteration completion or blockers. */
|
|
136
165
|
export interface AgentStatus {
|