@agent-compose/sdk 0.8.4 → 0.8.6
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 +213 -189
- package/dist/agent/agent-context.d.ts +9 -1
- package/dist/agent/agent-loop.d.ts +14 -6
- package/dist/agent/perf-sampler.d.ts +27 -2
- package/dist/agent/run-agent.d.ts +1 -1
- package/dist/client.d.ts +250 -59
- package/dist/directives.d.ts +14 -0
- package/dist/display.d.ts +7 -0
- package/dist/errors.d.ts +1 -1
- package/dist/generated/agentc-commands.d.ts +34 -0
- package/dist/index.d.ts +13 -11
- package/dist/index.js +1692 -194
- package/dist/request-context/request-context.d.ts +1 -1
- package/dist/runtimes/_cli-agent.d.ts +278 -58
- package/dist/runtimes/claude-code.d.ts +90 -1
- package/dist/runtimes/claude.d.ts +1 -1
- package/dist/runtimes/codex.d.ts +94 -6
- package/dist/runtimes/codex.mid-turn-hook.test.d.ts +10 -0
- package/dist/runtimes/openai-desktop.d.ts +50 -0
- package/dist/runtimes/openai-desktop.js +1689 -211
- package/dist/runtimes/openai-desktop.test.d.ts +20 -0
- package/dist/runtimes/opencode.d.ts +48 -11
- package/dist/runtimes/opencode.test.d.ts +14 -0
- package/dist/runtimes/tool-pulse.test.d.ts +17 -0
- package/dist/sandbox/baked-clis.d.ts +75 -0
- package/dist/sandbox/devbox.d.ts +5 -5
- package/dist/sandbox/exec-stream.d.ts +1 -2
- package/dist/sandbox/network-policy.d.ts +23 -5
- package/dist/sandbox/registry.d.ts +12 -0
- package/dist/sandbox/sizes.d.ts +11 -5
- package/dist/sandbox.d.ts +5 -3
- package/dist/step-invocation/protocol.d.ts +3 -4
- package/dist/step-invocation/server.d.ts +2 -2
- package/dist/step-invocation/types.d.ts +2 -2
- package/dist/types/api-conversations.d.ts +513 -27
- package/dist/types/api-factory.d.ts +183 -3
- package/dist/types/api-projects.d.ts +480 -0
- package/dist/types/api-runs.d.ts +8 -0
- package/dist/types/api-scopes.d.ts +32 -3
- package/dist/types/conversation-stream.d.ts +27 -1
- package/dist/types/execution-context.d.ts +1 -1
- package/dist/types/protocol.d.ts +182 -2
- package/dist/types/runtime.d.ts +80 -2
- package/dist/types/workflow-metadata.d.ts +2 -4
- package/dist/types/workflow-plan.d.ts +1 -3
- package/dist/utils/bundler.d.ts +23 -0
- package/dist/workflow-steps/observability.d.ts +2 -3
- package/dist/workflow-steps/runner.d.ts +5 -8
- package/dist/workflow-steps/types.d.ts +8 -10
- package/dist/workflow-steps/workflow.d.ts +2 -1
- package/dist/workflows/engine.d.ts +3 -5
- package/dist/workflows/invoke-child.d.ts +2 -2
- package/package.json +2 -2
- package/src/agent/agent-context.ts +193 -116
- package/src/agent/agent-loop.ts +16 -9
- package/src/agent/desktop-open.ts +13 -1
- package/src/agent/perf-sampler.ts +54 -3
- package/src/agent/run-agent.ts +1 -1
- package/src/client.ts +418 -80
- package/src/directives.ts +21 -1
- package/src/display.ts +12 -0
- package/src/errors.ts +1 -0
- package/src/generated/agentc-commands.ts +571 -0
- package/src/index.ts +65 -18
- package/src/pause/pause-core.ts +2 -1
- package/src/request-context/request-context.ts +1 -1
- package/src/runtimes/_cli-agent.ts +607 -132
- package/src/runtimes/claude-code.ts +427 -20
- package/src/runtimes/claude.ts +1 -1
- package/src/runtimes/codex.ts +188 -19
- package/src/runtimes/openai-desktop.ts +82 -19
- package/src/runtimes/opencode.ts +195 -26
- package/src/sandbox/baked-clis.ts +86 -0
- package/src/sandbox/devbox.ts +5 -5
- package/src/sandbox/exec-stream.ts +1 -2
- package/src/sandbox/network-policy.ts +51 -7
- package/src/sandbox/providers/e2b.ts +63 -19
- package/src/sandbox/providers/vercel.ts +6 -6
- package/src/sandbox/registry.ts +19 -1
- package/src/sandbox/sizes.ts +11 -5
- package/src/sandbox.ts +9 -2
- package/src/step-invocation/invoker.ts +2 -6
- package/src/step-invocation/protocol.ts +3 -4
- package/src/step-invocation/server.ts +2 -2
- package/src/types/api-conversations.ts +424 -29
- package/src/types/api-factory.ts +189 -3
- package/src/types/api-projects.ts +443 -0
- package/src/types/api-runs.ts +5 -0
- package/src/types/api-scopes.ts +32 -3
- package/src/types/conversation-stream.ts +29 -1
- package/src/types/execution-context.ts +1 -1
- package/src/types/protocol.ts +180 -2
- package/src/types/runtime.ts +71 -2
- package/src/types/sandbox-environment.ts +1 -2
- package/src/types/workflow-metadata.ts +2 -4
- package/src/types/workflow-plan.ts +1 -3
- package/src/utils/bundler.ts +88 -19
- package/src/workflow-steps/observability.ts +2 -3
- package/src/workflow-steps/runner.ts +5 -8
- package/src/workflow-steps/types.ts +8 -10
- package/src/workflow-steps/workflow.ts +2 -1
- package/src/workflows/engine.ts +3 -5
- package/src/workflows/invoke-child.ts +2 -2
- package/dist/pause/__tests__/errors.test.d.ts +0 -1
- package/dist/pause/__tests__/wrappers.test.d.ts +0 -1
- package/dist/step-invocation/__tests__/protocol.test.d.ts +0 -1
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
|
|
10
10
|
import type { ConversationAgentPresence } from "./conversation-stream.js";
|
|
11
11
|
import type { ConversationMemberRole } from "./api-scopes.js";
|
|
12
|
+
import type { ProjectRole } from "./api-projects.js";
|
|
12
13
|
import type { SandboxSize } from "../sandbox/sizes.js";
|
|
13
14
|
import type { SandboxNetworkPolicy } from "../sandbox/network-policy.js";
|
|
14
15
|
|
|
@@ -46,6 +47,9 @@ export interface Mention {
|
|
|
46
47
|
contextUrl: string | null;
|
|
47
48
|
text: string;
|
|
48
49
|
runId: string | null;
|
|
50
|
+
/** The chat message the ping came from (conversation pings from a send
|
|
51
|
+
* or an edit); null otherwise. */
|
|
52
|
+
messageId: string | null;
|
|
49
53
|
seenAt: string | null;
|
|
50
54
|
resolvedAt: string | null;
|
|
51
55
|
createdAt: string;
|
|
@@ -89,10 +93,36 @@ export interface ConversationRow {
|
|
|
89
93
|
* `model: "default"` passes through to the agent's own model. */
|
|
90
94
|
agentConfig: { model: string; effort: string; instructions: string };
|
|
91
95
|
createdAt: string;
|
|
96
|
+
/** The ROW's write time — every write bumps it, invisible background
|
|
97
|
+
* rows included. Recency people see is `lastMessageAt`. */
|
|
92
98
|
updatedAt: string;
|
|
93
|
-
/** Per-viewer unread
|
|
94
|
-
* callers; key callers see 0. */
|
|
99
|
+
/** Per-viewer unread room messages — present on the list wire for
|
|
100
|
+
* session callers; key callers see 0. */
|
|
95
101
|
unreadCount?: number;
|
|
102
|
+
/** Per-viewer unread replies in the channel threads the viewer follows
|
|
103
|
+
* (wrote the root or a reply) — read only by opening the thread.
|
|
104
|
+
* List wire; key callers see 0. */
|
|
105
|
+
threadUnreadCount?: number;
|
|
106
|
+
/** When the conversation last had something a person can SEE (a
|
|
107
|
+
* message that renders, room or thread) — "last active" and the rail's
|
|
108
|
+
* order. Null when nothing visible is recent. List wire. */
|
|
109
|
+
lastMessageAt?: string | null;
|
|
110
|
+
/** The projects holding this chat that the caller can see — a member
|
|
111
|
+
* row, or a team-public project (role `read`) — each with the object
|
|
112
|
+
* row that files it. Empty for a chat in no visible project; a private
|
|
113
|
+
* project the caller is outside is never named. List wire. */
|
|
114
|
+
projects?: ConversationProject[];
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/** A project a chat is filed in, as the caller may see it: the project,
|
|
118
|
+
* the caller's role there (a member row's, or a public project's `read`
|
|
119
|
+
* floor) and the object row that files the chat — the id a
|
|
120
|
+
* `removeProjectObject` of that filing takes. */
|
|
121
|
+
export interface ConversationProject {
|
|
122
|
+
id: string;
|
|
123
|
+
name: string;
|
|
124
|
+
role: ProjectRole;
|
|
125
|
+
objectId: string;
|
|
96
126
|
}
|
|
97
127
|
|
|
98
128
|
/** Agent-author identity decoration (mirrors the server's `agentAuthor`
|
|
@@ -108,6 +138,9 @@ export interface ConversationAgentAuthor {
|
|
|
108
138
|
avatarSeed: string;
|
|
109
139
|
ownerUserId: string | null;
|
|
110
140
|
ownerName: string | null;
|
|
141
|
+
/** True when this agent IS Ivy (a user's assistant or a shared chat's
|
|
142
|
+
* resident): render Ivy's one mark, never `avatarSeed`. */
|
|
143
|
+
ivy: boolean;
|
|
111
144
|
}
|
|
112
145
|
|
|
113
146
|
export interface ConversationMessageRow {
|
|
@@ -134,6 +167,11 @@ export interface ConversationMessageRow {
|
|
|
134
167
|
* (absent on older servers). */
|
|
135
168
|
editedAt?: string | null;
|
|
136
169
|
createdAt: string;
|
|
170
|
+
/** When the row's words first landed, on a reply row its turn opened
|
|
171
|
+
* before it had any; null for a row sent with its words. Read state
|
|
172
|
+
* dates a message by the later of this and `createdAt`: a reply that
|
|
173
|
+
* lands after a read is new. Absent on older servers. */
|
|
174
|
+
publishedAt?: string | null;
|
|
137
175
|
/** Thread-root facepile (≤3) — present only on roots with replies. */
|
|
138
176
|
replyAuthors?: Array<{ kind: string; id: string | null }>;
|
|
139
177
|
/** Set on a channel message an ATTACHED SESSION posted (ADR-0057 Seam 4)
|
|
@@ -371,6 +409,37 @@ export interface ConversationThread {
|
|
|
371
409
|
root: ConversationMessageRow;
|
|
372
410
|
/** Oldest→newest; the root is not repeated. */
|
|
373
411
|
messages: ConversationMessageRow[];
|
|
412
|
+
/** The viewer's thread read cursor before this visit (ISO) — the
|
|
413
|
+
* panel's "new replies" divider; null when they never read it. */
|
|
414
|
+
viewerLastReadAt: string | null;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
/** GET /conversations/unread — every chat with something unread for the
|
|
418
|
+
* caller (the sidebar, project rollups and space totals read this one
|
|
419
|
+
* summary). Session callers only; keys get an empty list. */
|
|
420
|
+
export interface ConversationUnreadSummary {
|
|
421
|
+
conversations: Array<{ conversationId: string; unreadCount: number; threadUnreadCount: number }>;
|
|
422
|
+
/** A server bound cut the list. */
|
|
423
|
+
truncated: boolean;
|
|
424
|
+
}
|
|
425
|
+
|
|
426
|
+
/** GET /conversations/:id/unread-threads — one channel's threads with
|
|
427
|
+
* unread replies for the caller, in transcript order. */
|
|
428
|
+
export interface ConversationUnreadThreads {
|
|
429
|
+
threads: Array<{ rootId: string; unreadCount: number }>;
|
|
430
|
+
truncated: boolean;
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/** POST /conversations/:id/read — what the caller SAW (`through` the newest
|
|
434
|
+
* message they had in view), or the explicit wholesale read (`all`). */
|
|
435
|
+
export type ConversationReadInput = { through: string } | { all: true };
|
|
436
|
+
|
|
437
|
+
export interface ConversationReadResult {
|
|
438
|
+
ok: true;
|
|
439
|
+
/** The thread the read moved; null = the room. */
|
|
440
|
+
threadRootId: string | null;
|
|
441
|
+
/** That place's cursor after the read (ISO). */
|
|
442
|
+
readAt: string;
|
|
374
443
|
}
|
|
375
444
|
|
|
376
445
|
/** One live dev preview on a cloud session (ADR-0052 §4). The directory row
|
|
@@ -396,13 +465,24 @@ export interface SessionPreview {
|
|
|
396
465
|
url: string | null;
|
|
397
466
|
createdAt: string;
|
|
398
467
|
lastSeenAt: string;
|
|
468
|
+
/** The hosting session (a chat's list spans the sessions attached to the
|
|
469
|
+
* chat; a session's own list names itself) and its liveness: `live` =
|
|
470
|
+
* the machine runs now, `parked` = suspended (an open wakes it), `gone`
|
|
471
|
+
* = the machine was reclaimed. */
|
|
472
|
+
sessionId: string;
|
|
473
|
+
sessionTitle: string | null;
|
|
474
|
+
sessionState: "live" | "parked" | "gone";
|
|
399
475
|
}
|
|
400
476
|
|
|
401
477
|
/** Result of opening a dev preview (`POST /conversations/:id/preview`). */
|
|
402
478
|
export interface PreviewOpened {
|
|
403
479
|
preview: SessionPreview;
|
|
404
|
-
/** The member-gated
|
|
405
|
-
|
|
480
|
+
/** The member-gated preview URL to open in a browser (never the raw host),
|
|
481
|
+
* minted for the PERSON who opened it. `null` when the opener is the
|
|
482
|
+
* session's own machine key (`agentc preview open` inside the sandbox):
|
|
483
|
+
* a machine gets no link; every person who looks mints their own from
|
|
484
|
+
* the live previews list (the card, the chat's Previews chip). */
|
|
485
|
+
url: string | null;
|
|
406
486
|
}
|
|
407
487
|
|
|
408
488
|
/** Input for `openPreview`. */
|
|
@@ -430,6 +510,164 @@ export interface BackgroundWorkHeld {
|
|
|
430
510
|
leaseUntil: string;
|
|
431
511
|
}
|
|
432
512
|
|
|
513
|
+
/** One background CHILD declared beside the busy lease (task #63): a
|
|
514
|
+
* detached process, by pid, with its durable journal/log file — what lets
|
|
515
|
+
* the platform VERIFY the work (`/proc/<pid>` + journal mtime) and
|
|
516
|
+
* reattach it after a park instead of losing it. */
|
|
517
|
+
export interface BackgroundWorkChildDecl {
|
|
518
|
+
pid: number;
|
|
519
|
+
/** Absolute guest-side path to the child's own durable output/journal
|
|
520
|
+
* file — its mtime is the progress evidence. */
|
|
521
|
+
journalPath?: string;
|
|
522
|
+
label?: string;
|
|
523
|
+
}
|
|
524
|
+
|
|
525
|
+
// ── Session waits (owner ruling 2026-09-23: no watch runs inside a session
|
|
526
|
+
// sandbox; the worker declares what it waits for and the platform senses it,
|
|
527
|
+
// `POST/GET/DELETE /sessions/:id/waits`) ──────────────────────────────────────
|
|
528
|
+
|
|
529
|
+
export type SessionWaitKind = "mail" | "time" | "need" | "github" | "webhook" | "schedule";
|
|
530
|
+
export type SessionWaitState = "open" | "satisfied" | "expired" | "cancelled";
|
|
531
|
+
|
|
532
|
+
/** What a session asks to be woken for. A mail wait names a sender (a full
|
|
533
|
+
* address or "@domain") with an optional subject regex and ONE deadline
|
|
534
|
+
* form (`forMs` from now, or an ISO `until`; default a day); a time wait
|
|
535
|
+
* names its instant, which is also its deadline. */
|
|
536
|
+
export type CreateSessionWaitInput =
|
|
537
|
+
| { kind: "mail"; from: string; subject?: string; forMs?: number; until?: string; label?: string }
|
|
538
|
+
| { kind: "time"; at: string; label?: string }
|
|
539
|
+
// STANDING waits (owner 2026-09-27): open across fires; every fire tells
|
|
540
|
+
// the session's thread agent and wakes the session while it is alive.
|
|
541
|
+
| { kind: "github"; repo: string; events?: Array<"workflow_run" | "check_run" | "check_suite" | "status" | "release" | "tag">; branches?: string[]; conclusions?: string[]; label: string; cooldownMinutes?: number; forDays?: number; forHours?: number }
|
|
542
|
+
| { kind: "webhook"; label: string; cooldownMinutes?: number; forDays?: number; forHours?: number }
|
|
543
|
+
| {
|
|
544
|
+
kind: "schedule"; cron?: string; everyMinutes?: number; timezone: string; label: string;
|
|
545
|
+
/** The wait's lifetime (one of the two). A plain schedule more often
|
|
546
|
+
* than hourly is armed with one, or with `noEndReason`. */
|
|
547
|
+
forDays?: number; forHours?: number; noEndReason?: string;
|
|
548
|
+
/** A SCRIPTED CHECK: the workspace's own registered workflow each tick
|
|
549
|
+
* runs instead of waking anyone, the input every run gets, the vault
|
|
550
|
+
* keys it reads (from the grants of the chat it is armed from, or of
|
|
551
|
+
* that chat's project), the person's message it answers, and a per-run
|
|
552
|
+
* model allowance when it must call a small model. Its first run is
|
|
553
|
+
* reviewed by the thread's agent before its schedule starts; then only
|
|
554
|
+
* what a run reports as needing attention (`attention: { summary,
|
|
555
|
+
* evidence }`), a run that measured nothing (no `measured`), or once a
|
|
556
|
+
* failure reaches the thread's agent. */
|
|
557
|
+
workflow?: string; input?: Record<string, unknown>; credentials?: string[]; askedIn?: string; modelBudgetUsd?: number;
|
|
558
|
+
};
|
|
559
|
+
|
|
560
|
+
/** How one scripted check run came out, as its wait records it. `breach`:
|
|
561
|
+
* it reported no attention and measured nothing (missing data is
|
|
562
|
+
* attention, never all clear). */
|
|
563
|
+
export interface SessionWaitCheckResult {
|
|
564
|
+
runId: string | null;
|
|
565
|
+
at: string;
|
|
566
|
+
result: "clear" | "attention" | "breach" | "failed" | "not_run";
|
|
567
|
+
summary: string;
|
|
568
|
+
/** What the run reported it measured (`measured` in its output). */
|
|
569
|
+
measured?: unknown;
|
|
570
|
+
digest?: string;
|
|
571
|
+
inARow?: number;
|
|
572
|
+
/** Whether it reached the thread's agent. */
|
|
573
|
+
woke: boolean;
|
|
574
|
+
}
|
|
575
|
+
|
|
576
|
+
/** One review the thread agent recorded of a scripted check. */
|
|
577
|
+
export interface SessionWaitCheckReview {
|
|
578
|
+
at: string;
|
|
579
|
+
findings: string;
|
|
580
|
+
/** The registered version it reviewed (a content hash). */
|
|
581
|
+
version: string | null;
|
|
582
|
+
confirmed?: boolean;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
/** A scripted check as its wait carries it. */
|
|
586
|
+
export interface SessionWaitCheck {
|
|
587
|
+
/** proving: its first run awaits the thread agent's review; live: it runs
|
|
588
|
+
* on its schedule. */
|
|
589
|
+
state: "proving" | "live" | null;
|
|
590
|
+
version: string | null;
|
|
591
|
+
/** The run going now. */
|
|
592
|
+
runId: string | null;
|
|
593
|
+
lastResult: SessionWaitCheckResult | null;
|
|
594
|
+
/** The agent's reviews of it, newest first (the last 20). */
|
|
595
|
+
reviews: SessionWaitCheckReview[];
|
|
596
|
+
nextReviewAt: string | null;
|
|
597
|
+
}
|
|
598
|
+
|
|
599
|
+
/** One declared wait as the server renders it. */
|
|
600
|
+
export interface SessionWait {
|
|
601
|
+
object: "session_wait";
|
|
602
|
+
id: string;
|
|
603
|
+
kind: SessionWaitKind;
|
|
604
|
+
/** mail: { from, subject? }; time: { instant }. */
|
|
605
|
+
spec: Record<string, unknown>;
|
|
606
|
+
label: string | null;
|
|
607
|
+
/** ISO deadline (a time wait's instant); a standing wait's lifetime, or
|
|
608
|
+
* null when it lives until cancelled. */
|
|
609
|
+
until: string | null;
|
|
610
|
+
state: SessionWaitState;
|
|
611
|
+
/** What settled it: the mail's from, subject and Gmail message id; the
|
|
612
|
+
* instant; or the deadline that passed. Null while open or cancelled. */
|
|
613
|
+
satisfiedBy: Record<string, unknown> | null;
|
|
614
|
+
createdAt: string;
|
|
615
|
+
updatedAt: string;
|
|
616
|
+
/** Standing waits only: how often it fired, when last, and a schedule's
|
|
617
|
+
* next instant. */
|
|
618
|
+
fireCount?: number;
|
|
619
|
+
lastFiredAt?: string | null;
|
|
620
|
+
nextFireAt?: string | null;
|
|
621
|
+
/** A webhook wait: the URL a monitoring tool POSTs to, and how to use it. */
|
|
622
|
+
webhookUrl?: string | null;
|
|
623
|
+
instructions?: string;
|
|
624
|
+
/** A scripted check: where it stands, its run going now, how the latest
|
|
625
|
+
* one came out, and the agent's reviews of it. */
|
|
626
|
+
check?: SessionWaitCheck;
|
|
627
|
+
}
|
|
628
|
+
|
|
629
|
+
/** The 201 of a declared wait: the row plus the one sentence the worker
|
|
630
|
+
* acts on ("the platform wakes this session when it arrives"). */
|
|
631
|
+
export interface SessionWaitCreated extends SessionWait {
|
|
632
|
+
message: string;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
export interface SessionWaitList {
|
|
636
|
+
object: "list";
|
|
637
|
+
waits: SessionWait[];
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
/** Outcome of requesting one machine size up
|
|
641
|
+
* (`POST /conversations/:id/machine/request-upsize` — task #110, the
|
|
642
|
+
* auto-resize policy's agent door). The platform arbitrates: within the
|
|
643
|
+
* team's daily cap the upsize is auto-granted (and lands immediately when
|
|
644
|
+
* no turn/background work holds the machine); past it a human approval
|
|
645
|
+
* card is posted. Wire shape mirrors
|
|
646
|
+
* server/src/sandbox/session-auto-resize.ts `UpsizeRequestOutcome`. */
|
|
647
|
+
export interface MachineUpsizeOutcome {
|
|
648
|
+
/** "executed" (landed now), "granted" (lands when the work settles),
|
|
649
|
+
* "pending_approval" (a card awaits the owner). Refusals arrive as HTTP
|
|
650
|
+
* errors carrying `code`. */
|
|
651
|
+
outcome: "executed" | "granted" | "pending_approval";
|
|
652
|
+
/** The size the grant/card names (e.g. "4vcpu-8gb"). */
|
|
653
|
+
size: string;
|
|
654
|
+
approvalId: string;
|
|
655
|
+
/** One human-readable line the CLI can print verbatim. */
|
|
656
|
+
message: string;
|
|
657
|
+
}
|
|
658
|
+
|
|
659
|
+
/** The session's background-work status
|
|
660
|
+
* (`GET /conversations/:id/background-work`). */
|
|
661
|
+
export interface BackgroundWorkStatus {
|
|
662
|
+
/** ISO deadline of the live lease, or null (no lease held). */
|
|
663
|
+
leaseUntil: string | null;
|
|
664
|
+
/** The declared children (each with its server-stamped `declaredAt`). */
|
|
665
|
+
children: Array<BackgroundWorkChildDecl & { declaredAt: string }>;
|
|
666
|
+
/** Non-null when a mid-work park froze declared children and the session
|
|
667
|
+
* still owes its conversation a status report (ISO park instant). */
|
|
668
|
+
frozenAt: string | null;
|
|
669
|
+
}
|
|
670
|
+
|
|
433
671
|
// ── Session branch proposals (ADR-0053) ─────────────────────────────────────
|
|
434
672
|
// Every cloud session works on its own factory-drive branch; the whole branch
|
|
435
673
|
// is the unit of review, like a PR. Wire shapes mirror
|
|
@@ -511,11 +749,9 @@ export interface SessionChangeSet {
|
|
|
511
749
|
* (hard cap 2; a manual re-review resets it). */
|
|
512
750
|
reviewAutoFollowup?: boolean;
|
|
513
751
|
reviewAutoRounds?: number;
|
|
514
|
-
/** The
|
|
515
|
-
* older servers; default
|
|
516
|
-
|
|
517
|
-
* from main headlessly. Toggled via `setSessionAutoRebase`. */
|
|
518
|
-
autoRebaseFromMain?: boolean;
|
|
752
|
+
/** The session's selectable cap on automatic follow-up rounds (additive
|
|
753
|
+
* — absent on older servers; default 2, range 1..5). */
|
|
754
|
+
reviewAutoRoundsMax?: number;
|
|
519
755
|
/** STRUCTURED review suggestions beside the notes (additive — absent on
|
|
520
756
|
* older servers): individually actionable {id, path, title, rationale,
|
|
521
757
|
* patch} entries the review session wrote back, status-stamped
|
|
@@ -538,6 +774,36 @@ export interface SessionChangeSet {
|
|
|
538
774
|
reviewDocuments?: SessionReviewDocument[];
|
|
539
775
|
}
|
|
540
776
|
|
|
777
|
+
/** The one fact keeping a session branch's version of a file off main
|
|
778
|
+
* (`SessionFilePlane.why`): an open conflict on the session's branch (one
|
|
779
|
+
* conflicting path holds every file on it), an open merge card, the
|
|
780
|
+
* session's merge gate, a linked repository's folder — or none of those,
|
|
781
|
+
* the session simply has not landed it yet. */
|
|
782
|
+
export type SessionFileHold = "in_progress" | "conflict" | "awaiting_approval" | "merge_gated" | "linked_repo";
|
|
783
|
+
|
|
784
|
+
/** Where ONE path's current version lives (`GET /conversations/:id/changes/file`),
|
|
785
|
+
* decided when a link to it is opened: `main` when the main drive holds the
|
|
786
|
+
* session branch's version (landed, or never changed on the branch), else
|
|
787
|
+
* `branch` with `why` naming what keeps it off main. `change`, `why` and
|
|
788
|
+
* `approvalId` are null and `conflictPaths` empty on the main plane. */
|
|
789
|
+
export interface SessionFilePlane {
|
|
790
|
+
object: "session_file_plane";
|
|
791
|
+
conversationId: string;
|
|
792
|
+
path: string;
|
|
793
|
+
plane: "main" | "branch";
|
|
794
|
+
branch: string | null;
|
|
795
|
+
change: "add" | "modify" | null;
|
|
796
|
+
why: SessionFileHold | null;
|
|
797
|
+
/** The open merge card waiting on this session's branch, if any. */
|
|
798
|
+
approvalId: string | null;
|
|
799
|
+
/** `why: "conflict"`: the session's open conflicts, oldest first, capped
|
|
800
|
+
* — the path itself when it is one of them, else what holds it. */
|
|
801
|
+
conflictPaths: string[];
|
|
802
|
+
/** The session the link named: its title, its status, and whether the
|
|
803
|
+
* platform lands its drive work on main as it goes (a thread's worker). */
|
|
804
|
+
session: { title: string | null; status: string; worker: boolean };
|
|
805
|
+
}
|
|
806
|
+
|
|
541
807
|
/** One reviewer's published review document
|
|
542
808
|
* (`SessionChangeSet.reviewDocuments`). `stale` compares the head this
|
|
543
809
|
* document was published against with the served diff. */
|
|
@@ -793,14 +1059,6 @@ export interface SessionRebaseReport {
|
|
|
793
1059
|
foldSkipped?: boolean;
|
|
794
1060
|
}
|
|
795
1061
|
|
|
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
|
-
|
|
804
1062
|
/** The sender's page stamp (HUD bar sends) — persisted server-side, never
|
|
805
1063
|
* echoed back on the wire. Mirrors the server's `PageContext` schema. */
|
|
806
1064
|
export interface ConversationPageContext {
|
|
@@ -849,6 +1107,9 @@ export interface SendConversationMessageResult {
|
|
|
849
1107
|
* private channel pings members only; a DM pings only the pair) —
|
|
850
1108
|
* present only when non-empty. Absent on older servers. */
|
|
851
1109
|
unnotifiedMentions?: UnnotifiedMention[];
|
|
1110
|
+
/** This send made the sender a member of the public chat (posting
|
|
1111
|
+
* joins). Present only when it happened; absent on older servers. */
|
|
1112
|
+
joined?: true;
|
|
852
1113
|
}
|
|
853
1114
|
|
|
854
1115
|
/** Response of the presence heartbeat (ADR-0037 §6): a fresh agent-liveness
|
|
@@ -878,11 +1139,35 @@ export interface ChannelSessionStatus {
|
|
|
878
1139
|
unreadCount: number;
|
|
879
1140
|
/** An agent ask is awaiting a human answer (bounded transcript scan). */
|
|
880
1141
|
awaiting: boolean;
|
|
881
|
-
/** The most recent agent-authored message contains an error part
|
|
1142
|
+
/** The most recent agent-authored message contains an error part and the
|
|
1143
|
+
* newest turn was not stopped (a stop is not a failure). */
|
|
882
1144
|
lastTurnFailed: boolean;
|
|
1145
|
+
/** The newest turn ended by a stop: someone stopped it on purpose (a
|
|
1146
|
+
* person, Ivy, the session's thread agent, the platform enforcing one of
|
|
1147
|
+
* those). */
|
|
1148
|
+
lastTurnStopped: boolean;
|
|
883
1149
|
lastAgentMessageAt: string | null;
|
|
884
1150
|
}
|
|
885
1151
|
|
|
1152
|
+
/** A chat worker's chip facts (owner 2026-09-28) — set only when the
|
|
1153
|
+
* session is one of this chat's workers. Never viewer-scoped. */
|
|
1154
|
+
export interface ChannelWorkerFacts {
|
|
1155
|
+
/** The chat message the worker was started under; null = no anchor. */
|
|
1156
|
+
originMessageId: string | null;
|
|
1157
|
+
/** The model stamped at birth; null = the runtime's own default. */
|
|
1158
|
+
model: string | null;
|
|
1159
|
+
/** The worker's session has ended. */
|
|
1160
|
+
ended: boolean;
|
|
1161
|
+
/** Parked on an open question to its thread agent (work unfinished). */
|
|
1162
|
+
parked: boolean;
|
|
1163
|
+
/** Its one-line status ("Reading the Fly logs"), when that text was set
|
|
1164
|
+
* (ISO) and how old it was when read (`ageSec`: a live turn whose words
|
|
1165
|
+
* are old has produced nothing since), while the turn the line describes
|
|
1166
|
+
* is running; null otherwise. Live updates ride the channel's
|
|
1167
|
+
* `session_status` frames. */
|
|
1168
|
+
statusLine: { text: string; at: string; ageSec: number } | null;
|
|
1169
|
+
}
|
|
1170
|
+
|
|
886
1171
|
/** One session attached to a channel, as listed by
|
|
887
1172
|
* `GET /conversations/:channelId/sessions` (newest attach first). */
|
|
888
1173
|
export interface ChannelSessionRow {
|
|
@@ -900,6 +1185,8 @@ export interface ChannelSessionRow {
|
|
|
900
1185
|
attachedAt: string;
|
|
901
1186
|
/** Who attached it (provenance only); null when the user is gone. */
|
|
902
1187
|
addedBy: string | null;
|
|
1188
|
+
/** Set ⇔ the session is one of this chat's workers. */
|
|
1189
|
+
worker: ChannelWorkerFacts | null;
|
|
903
1190
|
status: ChannelSessionStatus;
|
|
904
1191
|
}
|
|
905
1192
|
|
|
@@ -908,17 +1195,6 @@ export interface ChannelSessionsResponse {
|
|
|
908
1195
|
sessions: ChannelSessionRow[];
|
|
909
1196
|
}
|
|
910
1197
|
|
|
911
|
-
/** Result of posting into a channel AS a session
|
|
912
|
-
* (`POST /conversations/:channelId/session-messages`, ADR-0057 Seam 4).
|
|
913
|
-
* The post never triggers any turn — it is a report, not an address. */
|
|
914
|
-
export interface SessionChannelMessagePosted {
|
|
915
|
-
messageId: string;
|
|
916
|
-
/** Where the post landed: the thread root it replied under (by default,
|
|
917
|
-
* the message that last addressed the session from that channel), or
|
|
918
|
-
* null for a room post. Absent on older servers. */
|
|
919
|
-
threadRootId?: string | null;
|
|
920
|
-
}
|
|
921
|
-
|
|
922
1198
|
/** Result of `POST /session-messages` — one session's agent messaging
|
|
923
1199
|
* ANOTHER session's conversation (`agentc session message @alias`). Unlike
|
|
924
1200
|
* a channel post, this DOES wake the target's turn machinery: `turn` is
|
|
@@ -1004,3 +1280,122 @@ export interface StreamConversationOptions {
|
|
|
1004
1280
|
lastEventId?: number;
|
|
1005
1281
|
signal?: AbortSignal;
|
|
1006
1282
|
}
|
|
1283
|
+
|
|
1284
|
+
/** Shared chat creation includes its own Ivy unless explicitly disabled.
|
|
1285
|
+
* A chat is named for its topic: `title` is required (the server refuses
|
|
1286
|
+
* a shared chat without one — a conversation with people and no name is
|
|
1287
|
+
* a direct message, which people start themselves in the dashboard). */
|
|
1288
|
+
export interface CreateChatInput {
|
|
1289
|
+
title: string;
|
|
1290
|
+
visibility: "shared";
|
|
1291
|
+
access?: "public" | "private";
|
|
1292
|
+
memberIds?: string[];
|
|
1293
|
+
includeIvy?: boolean;
|
|
1294
|
+
}
|
|
1295
|
+
export interface ChannelIvyState {
|
|
1296
|
+
projects: Array<{ id: string; name: string }>;
|
|
1297
|
+
agent: AgentListRow | null;
|
|
1298
|
+
enabled: boolean; agentId: string | null; canManage: boolean;
|
|
1299
|
+
}
|
|
1300
|
+
/** Where a GitHub grant lives: the whole workspace, one project, or one
|
|
1301
|
+
* private chat. */
|
|
1302
|
+
export type IvyConnectionScope = "workspace" | "project" | "chat";
|
|
1303
|
+
/** A GitHub App installation's repositories granted to one scope. `scope`
|
|
1304
|
+
* says where it lives, `projectId` or `chatId` which one, and `scopeName`
|
|
1305
|
+
* that project's name or chat's title (null for the workspace). */
|
|
1306
|
+
export interface IvyConnection {
|
|
1307
|
+
id: string; teamId: string; scope: IvyConnectionScope; projectId: string | null; chatId: string | null; scopeName: string | null;
|
|
1308
|
+
provider: "github"; installationId: string;
|
|
1309
|
+
accountLogin: string; repositories: string[];
|
|
1310
|
+
/** ADR-0065 capabilities on the connection: allowWrites = issues
|
|
1311
|
+
* (create, update, comment), allowCodeWrites = code (push branches, open
|
|
1312
|
+
* pull requests). Every connection reads its repositories. */
|
|
1313
|
+
allowWrites: boolean; allowCodeWrites: boolean; configuredBy: string | null;
|
|
1314
|
+
/** The name of the person who granted it (last shared or changed); null
|
|
1315
|
+
* when they are gone or unnamed. */
|
|
1316
|
+
configuredByName: string | null;
|
|
1317
|
+
updatedAt: string;
|
|
1318
|
+
}
|
|
1319
|
+
/** An inherited grant of a project the caller does not read: the fact that
|
|
1320
|
+
* a project they are not in grants something here, nothing more. */
|
|
1321
|
+
export interface HiddenIvyConnection { id: string; provider: "github"; scope: "project"; hidden: true }
|
|
1322
|
+
/** One scope's listing: its own grants, the ones it inherits (a project
|
|
1323
|
+
* the workspace's; a chat the workspace's and each project it is in),
|
|
1324
|
+
* whether the caller may remove and add here (canManage), whether the
|
|
1325
|
+
* scope takes a new grant now at all (addable: a chat's only while it is
|
|
1326
|
+
* private), and who can grant here when the caller cannot. */
|
|
1327
|
+
export interface IvyConnectionsView {
|
|
1328
|
+
own: IvyConnection[];
|
|
1329
|
+
inherited: Array<IvyConnection | HiddenIvyConnection>;
|
|
1330
|
+
canManage: boolean;
|
|
1331
|
+
addable: boolean;
|
|
1332
|
+
granters: string[];
|
|
1333
|
+
/** The TEAM CONNECTIONS of this scope (owner 2026-10-01): the
|
|
1334
|
+
* workspace's own, and what a project or chat inherits from the
|
|
1335
|
+
* workspace. Absent on an older server. */
|
|
1336
|
+
workspaceConnections?: WorkspaceConnectionsScopeView;
|
|
1337
|
+
/** The listing is a PAGE (`limit`, `cursor` on the request): its rows are
|
|
1338
|
+
* one bounded read in scope order, and `nextCursor` opens the next page;
|
|
1339
|
+
* null at the end. */
|
|
1340
|
+
nextCursor: string | null;
|
|
1341
|
+
}
|
|
1342
|
+
/** One page of a scope listing: `cursor` is the previous page's
|
|
1343
|
+
* `nextCursor`; `limit` (1..200, 50 by default) its size. */
|
|
1344
|
+
export interface ListingPage { cursor?: string; limit?: number }
|
|
1345
|
+
/** Where a team connection is shared, as the caller may read it: a
|
|
1346
|
+
* project they are not in and a chat they do not read keep their ids and
|
|
1347
|
+
* lose their names. */
|
|
1348
|
+
export type WorkspaceConnectionAudienceEntry =
|
|
1349
|
+
| { scope: "workspace" }
|
|
1350
|
+
| { scope: "project"; projectId: string; name: string | null }
|
|
1351
|
+
| { scope: "chat"; chatId: string; title: string | null };
|
|
1352
|
+
/** A TEAM-OWNED connection of a tool (Linear first): a dedicated account's
|
|
1353
|
+
* pasted key or the provider's app installed as itself, with the admin's
|
|
1354
|
+
* label, the provider's capability keys it enables, and who it is shared
|
|
1355
|
+
* with. Never a credential. */
|
|
1356
|
+
export interface WorkspaceConnection {
|
|
1357
|
+
id: string; provider: string; providerName: string; kind: "api_key" | "oauth_app";
|
|
1358
|
+
label: string; accountLabel: string | null;
|
|
1359
|
+
capabilities: string[]; capabilityLabels: string[];
|
|
1360
|
+
status: "active" | "revoked" | "reauth_required";
|
|
1361
|
+
projectShareable: boolean; addedByName: string | null;
|
|
1362
|
+
audience: WorkspaceConnectionAudienceEntry[]; apiHosts: string[]; updatedAt: string;
|
|
1363
|
+
}
|
|
1364
|
+
export interface WorkspaceConnectionsScopeView {
|
|
1365
|
+
own: WorkspaceConnection[];
|
|
1366
|
+
inherited: WorkspaceConnection[];
|
|
1367
|
+
shareable: WorkspaceConnection[];
|
|
1368
|
+
canShare: boolean;
|
|
1369
|
+
}
|
|
1370
|
+
/** One picked Google Drive item of a share: a file, or a folder with
|
|
1371
|
+
* everything inside it. */
|
|
1372
|
+
export interface DriveShareItem { id: string; kind: "file" | "folder"; name: string; mimeType: string | null }
|
|
1373
|
+
/** A person's own Drive folders and files shared read-only into one scope
|
|
1374
|
+
* (owner 2026-10-01), read by Ivy there through the sharer's own account.
|
|
1375
|
+
* `account` is that Google address on the caller's OWN shares only; every
|
|
1376
|
+
* other row carries null and reads as "<Name>'s Drive". `sharedBy.email`
|
|
1377
|
+
* (the sharer's sign-in address, not their Google one) rides only while
|
|
1378
|
+
* the sharer shares the workspace with the viewer, for the label rule's
|
|
1379
|
+
* fail-safe when they have no name. `standing` says whether it still
|
|
1380
|
+
* reaches the scope today (the sharer is still in it and their Google
|
|
1381
|
+
* account still works). */
|
|
1382
|
+
export interface DriveShare {
|
|
1383
|
+
id: string; scope: IvyConnectionScope; projectId: string | null; chatId: string | null; scopeName: string | null;
|
|
1384
|
+
provider: string; sharedBy: { id: string; name: string | null; email: string | null }; account: string | null;
|
|
1385
|
+
items: DriveShareItem[];
|
|
1386
|
+
standing: boolean; standingReason: "sharer_left_scope" | "google_disconnected" | null;
|
|
1387
|
+
createdAt: string; canRemove: boolean;
|
|
1388
|
+
}
|
|
1389
|
+
/** An inherited share of a project the caller does not read: the fact that
|
|
1390
|
+
* a project they are not in shares something here, nothing more. */
|
|
1391
|
+
export interface HiddenDriveShare { id: string; provider: string; scope: "project"; hidden: true }
|
|
1392
|
+
/** One scope's Drive shares: its own, the ones it inherits, whether the
|
|
1393
|
+
* caller may share here, and the Google account they would share from. */
|
|
1394
|
+
export interface DriveSharesView {
|
|
1395
|
+
own: DriveShare[];
|
|
1396
|
+
inherited: Array<DriveShare | HiddenDriveShare>;
|
|
1397
|
+
mayShare: boolean;
|
|
1398
|
+
google: { grantId: string; account: string | null } | null;
|
|
1399
|
+
/** A page, as IvyConnectionsView: `nextCursor` opens the next one. */
|
|
1400
|
+
nextCursor: string | null;
|
|
1401
|
+
}
|