mindwire 0.1.10 → 0.1.13

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/run.d.ts CHANGED
@@ -1,7 +1,9 @@
1
1
  import type { Http } from "./http.js";
2
- import type { Event, ResultInfo, RespondInput, Run as RunData } from "./types.js";
2
+ import type { Event, ResultInfo, RespondInput, RunSnapshot, Run as RunData } from "./types.js";
3
3
  export interface StreamOptions {
4
4
  signal?: AbortSignal;
5
+ /** Resume after a snapshot/event cursor without replaying earlier output. */
6
+ after?: number;
5
7
  /**
6
8
  * Include the daemon's `{ type: "status", meta: { stream: "open" } }` sentinel that is
7
9
  * flushed the instant the stream opens (used to detect a live vs. buffered transport).
@@ -73,9 +75,9 @@ export declare class Run {
73
75
  */
74
76
  setModel(model?: string): Promise<void>;
75
77
  /**
76
- * Switch the permission mode of the live turn (e.g. `default`, `acceptEdits`, `plan`,
77
- * `bypassPermissions`). Only meaningful on a persistent (non-bypass) turn; on a one-shot turn it
78
- * is a best-effort no-op. Requires the agent's `setPermissionMode` capability.
78
+ * Switch the live permission mode using a value from the agent's settings schema.
79
+ * Resolves after the harness acknowledges the change; rejects if it cannot apply it.
80
+ * Requires `setPermissionMode`. Codex settings apply on the next turn instead.
79
81
  */
80
82
  setPermissionMode(mode: string): Promise<void>;
81
83
  /**
@@ -86,6 +88,8 @@ export declare class Run {
86
88
  children(): Promise<Run[]>;
87
89
  /** Re-fetch the run record from the daemon and update this handle. */
88
90
  refresh(): Promise<RunData>;
91
+ /** Restore current output once, then follow with `stream({ after: snapshot.sequence })`. */
92
+ snapshot(): Promise<RunSnapshot>;
89
93
  /**
90
94
  * Consume the event stream to completion. Returns the final run record and the `result`
91
95
  * event's summary (if any). Throws {@link RunFailedError} on an `error`/`cancelled` outcome
package/dist/types.d.ts CHANGED
@@ -108,6 +108,8 @@ export interface Usage {
108
108
  export interface ResultInfo {
109
109
  text?: string;
110
110
  isError?: boolean;
111
+ /** The harness stopped at the user's request; this is not an error. */
112
+ cancelled?: boolean;
111
113
  sessionId?: string;
112
114
  costUsd?: number;
113
115
  /** Per-turn token accounting, when the agent reports it. */
@@ -129,6 +131,10 @@ export interface ResultInfo {
129
131
  /** The unified stream item. Optional fields are populated per `type`. */
130
132
  export interface Event {
131
133
  type: EventType;
134
+ /** Per-run cursor. Subscribe with `stream({ after: sequence })` to receive newer events. */
135
+ sequence?: number;
136
+ /** Buffered output from before this stream connection opened. */
137
+ replay?: boolean;
132
138
  /** Text/thinking item identity. A non-delta snapshot replaces this item's earlier text. */
133
139
  itemId?: string;
134
140
  sessionId?: string;
@@ -189,6 +195,8 @@ export interface ContinuationInfo {
189
195
  export interface Action {
190
196
  id: string;
191
197
  label: string;
198
+ description?: string;
199
+ preview?: string;
192
200
  }
193
201
  export interface TodoItem {
194
202
  content: string;
@@ -198,29 +206,49 @@ export interface TodoItem {
198
206
  * A structured, self-describing request an agent surfaces mid-turn for the client to render
199
207
  * generically — and, when `needsResponse`, for the user to answer.
200
208
  */
209
+ export interface Question {
210
+ id: string;
211
+ title: string;
212
+ header?: string;
213
+ options?: Action[];
214
+ multiSelect?: boolean;
215
+ allowOther?: boolean;
216
+ isSecret?: boolean;
217
+ optional?: boolean;
218
+ }
219
+ export interface QuestionAnswer {
220
+ options?: string[];
221
+ text?: string;
222
+ }
201
223
  export interface Interaction {
202
224
  id?: string;
203
- kind: "todos" | "approval" | "choice" | "select" | "input" | "plan" | (string & {});
225
+ kind: "todos" | "approval" | "choice" | "select" | "input" | "form" | "plan" | (string & {});
204
226
  title?: string;
205
227
  detail?: string;
206
228
  /** `kind: "todos"` */
207
229
  items?: TodoItem[];
208
230
  /** `kind: "approval" | "choice" | "select" | "plan"` */
209
231
  options?: Action[];
232
+ questions?: Question[];
233
+ blocking?: boolean;
234
+ /** Whether approval feedback is accepted for all actions, or only a rejection. */
235
+ feedback?: "always" | "rejection";
210
236
  needsResponse?: boolean;
211
237
  meta?: Record<string, unknown>;
212
238
  }
213
239
  /**
214
240
  * The user's answer to a mid-turn {@link Interaction}, sent via {@link Run.respond}. `interactionId`
215
- * ties the answer to the interaction the turn paused on; `decision` is the approval verdict
216
- * (allow/deny) for a permission or plan; `text` is the free-form answer (or deny reason); `options`
217
- * carries a multi-select answer.
241
+ * ties the answer to the pending request. `decision` must be an offered action ID. For a form,
242
+ * `answers` maps every required question ID to its selected option IDs and optional feedback.
243
+ * Legacy single-question clients may send `options` and `text` at the top level. Incomplete
244
+ * answers return 400; stale or duplicate submissions return 409.
218
245
  */
219
246
  export interface RespondInput {
220
247
  interactionId?: string;
221
248
  decision?: string;
222
249
  options?: string[];
223
250
  text?: string;
251
+ answers?: Record<string, QuestionAnswer>;
224
252
  }
225
253
  /** Whether an agent provides a feature natively, needs the core to emulate it, or lacks it. */
226
254
  export type Support = "none" | "native" | "emulated";
@@ -585,6 +613,15 @@ export interface ConditionUX {
585
613
  export interface NotificationSpec {
586
614
  conditions: ConditionUX[];
587
615
  }
616
+ /** Materialized output at an exact stream cursor, shared by all agent harnesses. */
617
+ export interface RunSnapshot {
618
+ run: Run;
619
+ sequence: number;
620
+ parts: Part[];
621
+ result?: ResultInfo;
622
+ error?: string;
623
+ statusMessage?: string;
624
+ }
588
625
  /** A paired tool call (use + result) within an assistant turn. */
589
626
  export interface ToolPart {
590
627
  id?: string;
@@ -786,21 +823,28 @@ export interface SetupStatus {
786
823
  started: boolean;
787
824
  current?: string;
788
825
  steps: StepResult[];
826
+ /** The shared job's operation, including when another client started it. Older daemons omit it. */
827
+ operation?: "setup" | "update";
789
828
  }
790
829
  /** `GET /notify/config` — the token is never returned. */
791
830
  export interface NotifyConfigStatus {
792
831
  configured: boolean;
793
832
  url: string;
794
833
  channel: string;
834
+ /** Absent on older daemons, which always send raw Notification JSON. */
835
+ format?: NotifyChannelType;
836
+ hasToken?: boolean;
795
837
  }
796
838
  /** `PUT /notify/config` body. */
797
839
  export interface NotifyConfigInput {
798
840
  url: string;
799
841
  channel: string;
800
842
  token?: string;
843
+ /** "webhook" (default) sends raw Notification JSON; "push" uses title/body/data. */
844
+ format?: NotifyChannelType;
801
845
  }
802
846
  /** Delivery payload shape of a channel (selects only how the outgoing POST is framed). */
803
- export type NotifyChannelType = "webhook" | "slack" | "discord" | "telegram" | (string & {});
847
+ export type NotifyChannelType = "webhook" | "push" | "slack" | "discord" | "telegram" | (string & {});
804
848
  /**
805
849
  * `GET /notify/channels` — the masked read view of a channel. Secrets never cross the wire: the URL,
806
850
  * token, HMAC secret, and header VALUES are omitted; only their presence (and the URL host, as a
@@ -864,6 +908,10 @@ export interface NotifyChannelTestResult {
864
908
  }
865
909
  /** `GET /healthz` — the daemon's liveness probe. */
866
910
  export interface Health {
911
+ /** Workspace registry protocol version; absent on daemons predating workspace metadata. */
912
+ workspaceMetadataVersion?: number;
913
+ /** Durable project creation/clone operations; absent on older daemons. */
914
+ projectOperationsVersion?: number;
867
915
  ok: boolean;
868
916
  agent: string;
869
917
  version: string;
@@ -0,0 +1,149 @@
1
+ import type { Mindwire } from "./client.js";
2
+ /** Write-only credentials for one clone attempt. Never persisted in operation snapshots. */
3
+ export type ProjectAuth = {
4
+ kind: "token";
5
+ token: string;
6
+ username?: string;
7
+ } | {
8
+ kind: "ssh";
9
+ privateKey: string;
10
+ } | {
11
+ kind: "gh";
12
+ };
13
+ export interface ProjectRequest {
14
+ /** Stable idempotency key. Keep the same ID if the acknowledgement is lost. */
15
+ id: string;
16
+ source: "folder" | "create" | "clone";
17
+ name: string;
18
+ /** Absolute directory, or ~/... on the workspace. Clone/create require an absent destination. */
19
+ path: string;
20
+ repoUrl?: string;
21
+ branch?: string;
22
+ auth?: ProjectAuth;
23
+ }
24
+ export interface ProjectRemoveRequest {
25
+ /** Stable idempotency key for this confirmed removal. */
26
+ operationId: string;
27
+ expectedRevision: number;
28
+ }
29
+ export interface ProjectOperation extends Omit<ProjectRequest, "auth" | "source"> {
30
+ source: ProjectRequest["source"] | "delete";
31
+ expectedRevision?: number;
32
+ authKind?: ProjectAuth["kind"];
33
+ status: "queued" | "running" | "cancelling" | "succeeded" | "failed" | "cancelled" | "interrupted";
34
+ phase: string;
35
+ progress?: number;
36
+ /** Bounded, redacted output tail. */
37
+ log?: string;
38
+ error?: string;
39
+ projectId?: string;
40
+ createdAt: string;
41
+ updatedAt: string;
42
+ sequence: number;
43
+ attempt: number;
44
+ }
45
+ export declare class ProjectOperationsApi {
46
+ private readonly mw;
47
+ constructor(mw: Mindwire);
48
+ list(activeOnly?: boolean): Promise<ProjectOperation[]>;
49
+ get(id: string): Promise<ProjectOperation>;
50
+ cancel(id: string): Promise<ProjectOperation>;
51
+ retry(id: string, auth?: ProjectAuth): Promise<ProjectOperation>;
52
+ /** The first event is the current snapshot, then live changes. Reconnecting never replays old
53
+ * progress. Breaking the loop/aborting detaches the observer; cancel(id) explicitly stops work.
54
+ */
55
+ watch(id: string, opts?: {
56
+ signal?: AbortSignal;
57
+ }): AsyncGenerator<ProjectOperation>;
58
+ }
59
+ /** Stable identity and version of a record in one workspace's SQLite registry. */
60
+ export interface WorkspaceRecord {
61
+ id: string;
62
+ /** Registry identity, independent of the cloud provider's workspace ID. */
63
+ workspaceId: string;
64
+ createdAt: string;
65
+ revision: number;
66
+ }
67
+ /** A saved agent profile. Profiles using one harness share that workspace's native configuration. */
68
+ export interface WorkspaceAgent extends WorkspaceRecord {
69
+ name: string;
70
+ agentType: string;
71
+ agentTypeName?: string;
72
+ }
73
+ export interface WorkspaceProject extends WorkspaceRecord {
74
+ name: string;
75
+ path: string;
76
+ repoUrl?: string;
77
+ }
78
+ /** Chat membership; transcript content continues to come from /chats/:id/messages. */
79
+ export interface WorkspaceChat extends WorkspaceRecord {
80
+ agentId: string;
81
+ projectId: string;
82
+ title: string;
83
+ titleIsUserSet?: boolean;
84
+ sessionId?: string;
85
+ }
86
+ export type WorkspaceKind = "agents" | "projects" | "chats";
87
+ export type WorkspaceInput<T extends WorkspaceRecord> = Omit<T, "id" | "workspaceId" | "revision" | "createdAt"> & {
88
+ createdAt?: string;
89
+ };
90
+ /** Additive migration. Existing records and deletion tombstones always win over these values. */
91
+ export interface WorkspaceImport {
92
+ agents?: (WorkspaceInput<WorkspaceAgent> & {
93
+ id: string;
94
+ })[];
95
+ projects?: (WorkspaceInput<WorkspaceProject> & {
96
+ id: string;
97
+ })[];
98
+ chats?: (WorkspaceInput<WorkspaceChat> & {
99
+ id: string;
100
+ })[];
101
+ }
102
+ export interface WorkspaceSnapshot {
103
+ version: number;
104
+ workspaceId: string;
105
+ revision: number;
106
+ /** true replaces the cache for this workspace; false applies changed rows and deletions. */
107
+ full: boolean;
108
+ agents: WorkspaceAgent[];
109
+ projects: WorkspaceProject[];
110
+ chats: WorkspaceChat[];
111
+ deleted: {
112
+ kind: WorkspaceKind;
113
+ id: string;
114
+ revision: number;
115
+ }[];
116
+ }
117
+ export declare class WorkspaceCollection<T extends WorkspaceRecord> {
118
+ private readonly mw;
119
+ private readonly kind;
120
+ constructor(mw: Mindwire, kind: WorkspaceKind);
121
+ /** Create with a stable client-generated ID. For updates, supply the record's last revision. */
122
+ put(id: string, record: WorkspaceInput<T>, expectedRevision?: number): Promise<WorkspaceSnapshot>;
123
+ /** Remove membership and dependent chat links. Files and native transcripts are retained.
124
+ * Use deleteChat() for an explicit transcript purge. Running chats reject removal with 409.
125
+ */
126
+ delete(id: string, revision: number): Promise<WorkspaceSnapshot>;
127
+ }
128
+ /** Workspace metadata is shared by all harnesses; withAgent() never scopes these requests. */
129
+ export declare class WorkspaceApi {
130
+ private readonly mw;
131
+ readonly operations: ProjectOperationsApi;
132
+ readonly agents: WorkspaceCollection<WorkspaceAgent>;
133
+ readonly projects: WorkspaceCollection<WorkspaceProject>;
134
+ readonly chats: WorkspaceCollection<WorkspaceChat>;
135
+ constructor(mw: Mindwire);
136
+ snapshot(): Promise<WorkspaceSnapshot>;
137
+ /** Start an operation owned by the daemon. The same ID/payload returns the existing operation. */
138
+ createProject(request: ProjectRequest): Promise<ProjectOperation>;
139
+ /** Permanently remove the confirmed project's directory and membership.
140
+ * projects.delete() retains files. Native harness transcripts are not purged.
141
+ */
142
+ removeProjectFiles(id: string, request: ProjectRemoveRequest): Promise<ProjectOperation>;
143
+ /** Incremental reconciliation. Pass the previous identity to detect a replaced/restored workspace.
144
+ * A 409 requires fetching snapshot() again; never apply a delta to a different registry.
145
+ */
146
+ changes(since: number, workspaceId: string): Promise<WorkspaceSnapshot>;
147
+ /** Import legacy metadata before replacing a local cache. Safe to repeat after interruption. */
148
+ import(records: WorkspaceImport): Promise<WorkspaceSnapshot>;
149
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindwire",
3
- "version": "0.1.10",
3
+ "version": "0.1.13",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {