mindwire 0.1.11 → 0.1.14

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
@@ -75,9 +75,9 @@ export declare class Run {
75
75
  */
76
76
  setModel(model?: string): Promise<void>;
77
77
  /**
78
- * Switch the permission mode of the live turn (e.g. `default`, `acceptEdits`, `plan`,
79
- * `bypassPermissions`). Only meaningful on a persistent (non-bypass) turn; on a one-shot turn it
80
- * 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.
81
81
  */
82
82
  setPermissionMode(mode: string): Promise<void>;
83
83
  /**
@@ -0,0 +1,177 @@
1
+ import type { Mindwire } from "./client.js";
2
+ export interface SurfaceGeometry {
3
+ width: number;
4
+ height: number;
5
+ revision: number;
6
+ }
7
+ export interface SurfaceProblem {
8
+ code: string;
9
+ message: string;
10
+ }
11
+ export interface SurfaceCapabilities {
12
+ view: boolean;
13
+ capture: boolean;
14
+ pointer: boolean;
15
+ keyboard: boolean;
16
+ text: boolean;
17
+ clipboardRead: boolean;
18
+ clipboardWrite: boolean;
19
+ }
20
+ export interface SurfaceController {
21
+ sessionId: string;
22
+ actor: "user" | "agent";
23
+ name: string;
24
+ runId?: string;
25
+ chatId?: string;
26
+ generation: number;
27
+ expiresAt: string;
28
+ }
29
+ export interface SurfaceSnapshot {
30
+ id: string;
31
+ workspaceId: string;
32
+ kind: "desktop";
33
+ provider: "oblien";
34
+ version: number;
35
+ revision: number;
36
+ instanceId: string;
37
+ state: string;
38
+ observedAt?: string;
39
+ supported: boolean;
40
+ enabled: boolean;
41
+ available: boolean;
42
+ credentials: boolean;
43
+ os?: string;
44
+ capabilities: SurfaceCapabilities;
45
+ geometry?: SurfaceGeometry;
46
+ controller?: SurfaceController;
47
+ authorizationExpiresAt?: string;
48
+ error?: SurfaceProblem;
49
+ }
50
+ /** Write-only, desktop-only, expiring provider grant. Never pass a user's session JWT. */
51
+ export interface SurfaceBinding {
52
+ registryId: string;
53
+ workspaceId: string;
54
+ gatewayToken?: string;
55
+ connection: {
56
+ expires_at: string;
57
+ ssh: {
58
+ host: string;
59
+ port: number;
60
+ username: string;
61
+ password: string;
62
+ host_key_fingerprint: string;
63
+ };
64
+ vnc: {
65
+ host: string;
66
+ port: number;
67
+ authentication: "none";
68
+ };
69
+ };
70
+ }
71
+ export interface SurfaceSession {
72
+ id: string;
73
+ surfaceId: string;
74
+ actor: "user" | "agent";
75
+ name: string;
76
+ chatId?: string;
77
+ runId?: string;
78
+ mode: "view" | "control";
79
+ createdAt: string;
80
+ controller?: SurfaceController;
81
+ }
82
+ export interface SurfaceOpenRequest {
83
+ requestId: string;
84
+ name?: string;
85
+ mode: "view" | "control";
86
+ }
87
+ export interface SurfaceControlRequest {
88
+ action: "acquire" | "takeover" | "release" | "renew";
89
+ generation?: number;
90
+ }
91
+ export interface SurfaceAction {
92
+ kind: "pointer" | "click" | "drag" | "scroll" | "key" | "text" | "clipboard_read" | "clipboard_write" | "release";
93
+ x?: number;
94
+ y?: number;
95
+ toX?: number;
96
+ toY?: number;
97
+ buttons?: number;
98
+ button?: "left" | "middle" | "right";
99
+ count?: number;
100
+ deltaX?: number;
101
+ deltaY?: number;
102
+ keys?: string[];
103
+ text?: string;
104
+ }
105
+ export interface SurfaceActionRequest {
106
+ /** Reuse this ID to inspect/recover an uncertain acknowledgement. Do not replay with a new ID. */
107
+ requestId: string;
108
+ sessionId: string;
109
+ controlGeneration: number;
110
+ frameId?: string;
111
+ geometryRevision?: number;
112
+ action: SurfaceAction;
113
+ }
114
+ export interface SurfaceReceipt {
115
+ id: string;
116
+ sessionId: string;
117
+ surfaceId: string;
118
+ kind: string;
119
+ status: "dispatching" | "dispatched" | "outcome_unknown";
120
+ createdAt: string;
121
+ error?: SurfaceProblem;
122
+ /** Transient clipboard output, not stored in the receipt. */
123
+ text?: string;
124
+ }
125
+ export interface SurfaceCapture {
126
+ id: string;
127
+ surfaceId: string;
128
+ artifactId: string;
129
+ mime: string;
130
+ geometry: SurfaceGeometry;
131
+ createdAt: string;
132
+ }
133
+ export interface ArtifactContent {
134
+ id: string;
135
+ chatId?: string;
136
+ mime: string;
137
+ bytes: number;
138
+ width: number;
139
+ height: number;
140
+ createdAt: string;
141
+ /** Base64 bytes, compatible with every existing daemon transport. */
142
+ data: string;
143
+ }
144
+ export interface SurfaceToolAction {
145
+ surfaceId: string;
146
+ operation: string;
147
+ sessionId?: string;
148
+ receiptId?: string;
149
+ status?: string;
150
+ capture?: {
151
+ id: string;
152
+ artifactId: string;
153
+ width: number;
154
+ height: number;
155
+ };
156
+ }
157
+ /** Workspace-scoped API. One controller is shared by every harness and app client. */
158
+ export declare class SurfacesApi {
159
+ private readonly mw;
160
+ constructor(mw: Mindwire);
161
+ list(): Promise<SurfaceSnapshot[]>;
162
+ status(refresh?: boolean): Promise<SurfaceSnapshot>;
163
+ bind(binding: SurfaceBinding): Promise<SurfaceSnapshot>;
164
+ open(request: SurfaceOpenRequest): Promise<SurfaceSession>;
165
+ control(id: string, request: SurfaceControlRequest): Promise<SurfaceSession>;
166
+ close(id: string): Promise<{
167
+ closed: boolean;
168
+ }>;
169
+ capture(id: string): Promise<SurfaceCapture>;
170
+ action(request: SurfaceActionRequest): Promise<SurfaceReceipt>;
171
+ receipt(id: string): Promise<SurfaceReceipt>;
172
+ artifact(id: string): Promise<ArtifactContent>;
173
+ /** Every connection starts with the current snapshot, then revisions. Never replays input. */
174
+ watch(opts?: {
175
+ signal?: AbortSignal;
176
+ }): AsyncGenerator<SurfaceSnapshot>;
177
+ }
@@ -30,9 +30,9 @@ export interface EnsureDaemonConfig {
30
30
  /** `AGENT_CWD` — working directory agents run in, inside the sandbox. */
31
31
  agentCwd: string;
32
32
  /**
33
- * Explicit path to a Linux `mindwired` to deploy (else downloaded from the matching GitHub Release).
34
- * `{arch}` is expanded to the destination architecture (`amd64` or `arm64`), allowing a development
35
- * launcher to build both artifacts without guessing the sandbox architecture in advance.
33
+ * Explicit path to a `mindwired` to deploy (else downloaded from the matching GitHub Release).
34
+ * `{os}` and `{arch}` expand to the destination (`linux`/`darwin` and `amd64`/`arm64`), allowing a
35
+ * development launcher to build artifacts without guessing the sandbox platform in advance.
36
36
  */
37
37
  daemonBin?: string;
38
38
  /** Redeploy when the running daemon's version differs from `desiredVersion`. Off by default. */
@@ -70,6 +70,8 @@ export interface EnsureEvent {
70
70
  version?: string;
71
71
  /** Target architecture the daemon was resolved for (on `upload`). */
72
72
  arch?: "amd64" | "arm64";
73
+ /** Destination operating system (on `download` / `upload`). */
74
+ platform?: "linux" | "darwin";
73
75
  /** Size of the uploaded daemon binary in bytes (on `upload`). */
74
76
  bytes?: number;
75
77
  /** Error message (on `error`). */
@@ -19,7 +19,7 @@ export interface OblienConfig {
19
19
  agentCwd?: string;
20
20
  /** Loopback port the in-workspace daemon listens on. */
21
21
  port?: number;
22
- /** Explicit local Linux `mindwired` to deploy. `{arch}` expands to the workspace architecture. */
22
+ /** Explicit local `mindwired` to deploy. `{os}`/`{arch}` expand to the workspace platform. */
23
23
  daemonBin?: string;
24
24
  /** Redeploy the daemon when the running version differs from the SDK's bundled binary. Off by default. */
25
25
  autoUpdate?: boolean;
@@ -26,7 +26,7 @@ export interface SshOptions {
26
26
  agentType?: string;
27
27
  /** `AGENT_CWD` — working directory agents run in, on the remote. Defaults to `/root`. */
28
28
  agentCwd?: string;
29
- /** Explicit path to a Linux `mindwired` to deploy (else resolved from the platform package). */
29
+ /** Explicit local `mindwired` to deploy; `{os}`/`{arch}` expand to the destination platform. Otherwise downloaded from GitHub Releases. */
30
30
  daemonBin?: string;
31
31
  /** Redeploy when the running daemon's version differs from the SDK's bundled binary. */
32
32
  autoUpdate?: boolean;
package/dist/types.d.ts CHANGED
@@ -28,6 +28,7 @@ export type ToolKind = "file_edit" | "file_read" | "shell" | "search" | "web_sea
28
28
  * apply_patch/shell).
29
29
  */
30
30
  export interface ToolAction {
31
+ surface?: import("./surfaces.js").SurfaceToolAction;
31
32
  kind: ToolKind;
32
33
  /** Short human label (e.g. the command or the path). */
33
34
  title?: string;
@@ -108,6 +109,8 @@ export interface Usage {
108
109
  export interface ResultInfo {
109
110
  text?: string;
110
111
  isError?: boolean;
112
+ /** The harness stopped at the user's request; this is not an error. */
113
+ cancelled?: boolean;
111
114
  sessionId?: string;
112
115
  costUsd?: number;
113
116
  /** Per-turn token accounting, when the agent reports it. */
@@ -193,6 +196,8 @@ export interface ContinuationInfo {
193
196
  export interface Action {
194
197
  id: string;
195
198
  label: string;
199
+ description?: string;
200
+ preview?: string;
196
201
  }
197
202
  export interface TodoItem {
198
203
  content: string;
@@ -202,29 +207,49 @@ export interface TodoItem {
202
207
  * A structured, self-describing request an agent surfaces mid-turn for the client to render
203
208
  * generically — and, when `needsResponse`, for the user to answer.
204
209
  */
210
+ export interface Question {
211
+ id: string;
212
+ title: string;
213
+ header?: string;
214
+ options?: Action[];
215
+ multiSelect?: boolean;
216
+ allowOther?: boolean;
217
+ isSecret?: boolean;
218
+ optional?: boolean;
219
+ }
220
+ export interface QuestionAnswer {
221
+ options?: string[];
222
+ text?: string;
223
+ }
205
224
  export interface Interaction {
206
225
  id?: string;
207
- kind: "todos" | "approval" | "choice" | "select" | "input" | "plan" | (string & {});
226
+ kind: "todos" | "approval" | "choice" | "select" | "input" | "form" | "plan" | (string & {});
208
227
  title?: string;
209
228
  detail?: string;
210
229
  /** `kind: "todos"` */
211
230
  items?: TodoItem[];
212
231
  /** `kind: "approval" | "choice" | "select" | "plan"` */
213
232
  options?: Action[];
233
+ questions?: Question[];
234
+ blocking?: boolean;
235
+ /** Whether approval feedback is accepted for all actions, or only a rejection. */
236
+ feedback?: "always" | "rejection";
214
237
  needsResponse?: boolean;
215
238
  meta?: Record<string, unknown>;
216
239
  }
217
240
  /**
218
241
  * The user's answer to a mid-turn {@link Interaction}, sent via {@link Run.respond}. `interactionId`
219
- * ties the answer to the interaction the turn paused on; `decision` is the approval verdict
220
- * (allow/deny) for a permission or plan; `text` is the free-form answer (or deny reason); `options`
221
- * carries a multi-select answer.
242
+ * ties the answer to the pending request. `decision` must be an offered action ID. For a form,
243
+ * `answers` maps every required question ID to its selected option IDs and optional feedback.
244
+ * Legacy single-question clients may send `options` and `text` at the top level. Incomplete
245
+ * answers return 400; stale or duplicate submissions return 409.
222
246
  */
223
247
  export interface RespondInput {
224
248
  interactionId?: string;
225
249
  decision?: string;
226
250
  options?: string[];
227
251
  text?: string;
252
+ answers?: Record<string, QuestionAnswer>;
228
253
  }
229
254
  /** Whether an agent provides a feature natively, needs the core to emulate it, or lacks it. */
230
255
  export type Support = "none" | "native" | "emulated";
@@ -497,6 +522,8 @@ export interface MCPServer {
497
522
  bearerTokenEnvVar?: string;
498
523
  /** HTTP transport: literal headers sent with each request. */
499
524
  httpHeaders?: Record<string, string>;
525
+ /** Codex's native approval behavior for this MCP server. */
526
+ defaultToolsApprovalMode?: "auto" | "prompt" | "writes" | "approve";
500
527
  }
501
528
  /**
502
529
  * One registered custom OpenAI-compatible LLM provider — a base URL + model ids an agent loads on every
@@ -799,21 +826,30 @@ export interface SetupStatus {
799
826
  started: boolean;
800
827
  current?: string;
801
828
  steps: StepResult[];
829
+ /** The shared job's operation, including when another client started it. Older daemons omit it. */
830
+ operation?: "setup" | "update";
831
+ /** Current step phase, reported by the daemon rather than inferred from elapsed time. */
832
+ stage?: "checking" | "waiting" | "installing" | "verifying" | (string & {});
802
833
  }
803
834
  /** `GET /notify/config` — the token is never returned. */
804
835
  export interface NotifyConfigStatus {
805
836
  configured: boolean;
806
837
  url: string;
807
838
  channel: string;
839
+ /** Absent on older daemons, which always send raw Notification JSON. */
840
+ format?: NotifyChannelType;
841
+ hasToken?: boolean;
808
842
  }
809
843
  /** `PUT /notify/config` body. */
810
844
  export interface NotifyConfigInput {
811
845
  url: string;
812
846
  channel: string;
813
847
  token?: string;
848
+ /** "webhook" (default) sends raw Notification JSON; "push" uses title/body/data. */
849
+ format?: NotifyChannelType;
814
850
  }
815
851
  /** Delivery payload shape of a channel (selects only how the outgoing POST is framed). */
816
- export type NotifyChannelType = "webhook" | "slack" | "discord" | "telegram" | (string & {});
852
+ export type NotifyChannelType = "webhook" | "push" | "slack" | "discord" | "telegram" | (string & {});
817
853
  /**
818
854
  * `GET /notify/channels` — the masked read view of a channel. Secrets never cross the wire: the URL,
819
855
  * token, HMAC secret, and header VALUES are omitted; only their presence (and the URL host, as a
@@ -877,6 +913,11 @@ export interface NotifyChannelTestResult {
877
913
  }
878
914
  /** `GET /healthz` — the daemon's liveness probe. */
879
915
  export interface Health {
916
+ surfaceProtocolVersion?: number;
917
+ /** Workspace registry protocol version; absent on daemons predating workspace metadata. */
918
+ workspaceMetadataVersion?: number;
919
+ /** Durable project creation/clone operations; absent on older daemons. */
920
+ projectOperationsVersion?: number;
880
921
  ok: boolean;
881
922
  agent: string;
882
923
  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.11",
3
+ "version": "0.1.14",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.js",
6
6
  "devDependencies": {