mindwire 0.1.25 → 0.1.27

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/client.d.ts CHANGED
@@ -7,7 +7,7 @@ import { ExecutionApi } from "./execution.js";
7
7
  import { ComputerApi } from "./computer.js";
8
8
  import { type Target } from "./target/index.js";
9
9
  import type { EnsureEvent } from "./target/host.js";
10
- import type { AgentInfo, AuthMethod, AuthState, AuthStatus, Catalog, ChatSummary, CustomProvider, DeleteResult, DoctorReport, Health, MCPServer, MemoryDoc, MemoryScope, Message, ModelInfo, Notification, NotifyChannel, NotifyChannelInput, NotifyChannelTestResult, NotifyConfigInput, NotifyConfigStatus, NotifyRule, NotifyRuleInput, ProcessFrame, PromptTemplate, ResolveOptions, SetupStatus, HarnessSoftware, Stats, Subagent, TurnOptions } from "./types.js";
10
+ import type { AgentInfo, AuthMethod, AuthState, AuthStatus, Catalog, ChatSummary, CustomProvider, DeleteResult, DoctorReport, Health, MCPServer, MemoryDoc, MemoryScope, Message, MessagePage, ModelInfo, Notification, NotifyChannel, NotifyChannelInput, NotifyChannelTestResult, NotifyConfigInput, NotifyConfigStatus, NotifyRule, NotifyRuleInput, ProcessFrame, PromptTemplate, ResolveOptions, SetupStatus, HarnessSoftware, Stats, Subagent, TurnOptions } from "./types.js";
11
11
  export interface MindwireOptions {
12
12
  /**
13
13
  * Default agent type for agent-scoped calls (e.g. `"claude-code"`). When omitted, the daemon
@@ -148,8 +148,15 @@ export declare class Mindwire {
148
148
  getConfig(scoped?: AgentScoped): Promise<Record<string, string>>;
149
149
  /** `PUT /config` — merge recognized (non-secret) setting keys. Unknown keys are ignored server-side. */
150
150
  setConfig(values: Record<string, string>, scoped?: AgentScoped): Promise<void>;
151
- /** `GET /chats` — recorded chats (newest first), shared across agents. */
152
- chats(): Promise<ChatSummary[]>;
151
+ /** Native project conversations and drafts, newest first, shared across agents.
152
+ * `cwd` matches an exact directory; `projectId` selects saved membership.
153
+ * `refresh` bypasses the daemon's short native metadata cache.
154
+ */
155
+ chats(options?: {
156
+ cwd?: string;
157
+ projectId?: string;
158
+ refresh?: boolean;
159
+ }): Promise<ChatSummary[]>;
153
160
  /**
154
161
  * `PUT /chats/{id}` — rename a chat. The user title wins over the agent's native auto-title in
155
162
  * every listing; an empty title clears the rename (reverting to the native/derived title).
@@ -181,6 +188,16 @@ export declare class Mindwire {
181
188
  limit?: number;
182
189
  before?: string;
183
190
  }): Promise<Message[]>;
191
+ /**
192
+ * Byte-budgeted history (default 1 MiB). Whole messages are retained, including
193
+ * up to two newest messages even when oversized. Older services return their
194
+ * bounded array, normalized here without a probe or duplicate request.
195
+ */
196
+ messagePage(chatId: string, opts?: AgentScoped & {
197
+ limit?: number;
198
+ before?: string;
199
+ maxBytes?: number;
200
+ }): Promise<MessagePage>;
184
201
  /** `GET /chats/{id}/run` — the latest run for a chat (reattach anchor), or `null` if none yet. */
185
202
  latestRun(chatId: string): Promise<Run | null>;
186
203
  /**
@@ -193,6 +210,8 @@ export declare class Mindwire {
193
210
  * clearer entry point for that. The returned {@link Run} is then the parent of the run tree.
194
211
  */
195
212
  turn(input: {
213
+ /** Keep this ID when retrying an unacknowledged turn. Requires turnRequestVersion >= 1. */
214
+ requestId?: string;
196
215
  chatId: string;
197
216
  message: string;
198
217
  cwd?: string;
@@ -214,6 +233,7 @@ export declare class Mindwire {
214
233
  * {@link ApiError} (409) if a turn is already running for the chat.
215
234
  */
216
235
  resolve(input: {
236
+ requestId?: string;
217
237
  chatId: string;
218
238
  message: string;
219
239
  cwd?: string;
@@ -0,0 +1,22 @@
1
+ import type { ComputerReconnectCode, ComputerDevice, ComputerInfo } from "../computer.js";
2
+ export type ConnectionAction = "resume" | "reconnect" | "pair";
3
+ export declare function connectionAction(value: string | undefined): ConnectionAction | undefined;
4
+ /** Noninteractive runs never unexpectedly create a new invitation for a paired computer. */
5
+ export declare function chooseConnectionAction(options: {
6
+ requested?: ConnectionAction;
7
+ devices: ComputerDevice[];
8
+ question?: (prompt: string) => Promise<string>;
9
+ }): Promise<ConnectionAction>;
10
+ /** Ask once; preserve existing opt-outs. Scripts must opt in with --startup. */
11
+ export declare function chooseStartupAction(options: {
12
+ state: {
13
+ enabled: boolean;
14
+ running?: boolean;
15
+ kind?: string;
16
+ };
17
+ startup?: boolean;
18
+ noStartup?: boolean;
19
+ question?: (prompt: string) => Promise<string>;
20
+ }): Promise<boolean | undefined>;
21
+ export declare function reconnectCode(info: ComputerInfo, name: string, now?: Date): ComputerReconnectCode;
22
+ export declare function deviceSummary(devices: ComputerDevice[]): string;
@@ -0,0 +1,3 @@
1
+ export declare function recoveryDelay(failures: number): number;
2
+ /** Own process lifecycle separately from any mobile view or pairing command. */
3
+ export declare function superviseComputer(directory: string): Promise<void>;
@@ -1,6 +1,7 @@
1
1
  import { Mindwire } from "../client.js";
2
2
  import type { ComputerRoute } from "../computer.js";
3
- import { type RelayOptions } from "./relay.js";
3
+ import type { RelayOptions } from "./relay.js";
4
+ import { type ProcessState } from "./process.js";
4
5
  export interface ComputerConfig {
5
6
  daemonBin?: string;
6
7
  version?: string;
@@ -11,6 +12,13 @@ export interface ComputerConfig {
11
12
  websocketPort: number;
12
13
  relay: RelayOptions;
13
14
  }
15
+ export interface ControllerState extends ProcessState {
16
+ ready: boolean;
17
+ phase?: string;
18
+ error?: string;
19
+ recovering?: boolean;
20
+ routes?: ComputerRoute[];
21
+ }
14
22
  export declare const defaultStateDirectory: () => string;
15
23
  export declare const defaultComputerConfig: () => ComputerConfig;
16
24
  export declare function readJSON<T>(file: string): Promise<T | undefined>;
@@ -18,7 +26,9 @@ export declare function writeJSON(file: string, value: unknown): Promise<void>;
18
26
  export declare function computerClient(directory: string): Promise<Mindwire>;
19
27
  export declare function directRoutes(config: ComputerConfig, port: number): ComputerRoute[];
20
28
  /** Launch once; the daemon additionally owns an OS file lock over its identity/state. */
21
- export declare function ensureComputer(directory: string, cliPath: string, patch?: Partial<ComputerConfig>, onProgress?: (message: string) => void): Promise<Mindwire>;
22
- /** The only owner of daemon/relay processes. Closing the pairing command leaves this running. */
29
+ export declare function ensureComputer(directory: string, cliPath: string, patch?: Partial<ComputerConfig>, onProgress?: (message: string) => void, options?: {
30
+ resume?: boolean;
31
+ signal?: AbortSignal;
32
+ }): Promise<Mindwire>;
23
33
  export declare function superviseComputer(directory: string): Promise<void>;
24
34
  export declare function stopComputer(directory: string, force?: boolean): Promise<void>;
@@ -0,0 +1,11 @@
1
+ export interface ProcessLock {
2
+ close(): Promise<void>;
3
+ }
4
+ /** Serialize lock-file acquisition and stale recovery with a bakery queue. Each
5
+ * waiter owns a unique, atomically published ticket; it never removes another
6
+ * live waiter's ticket. That prevents two stale-lock cleaners deleting a newly
7
+ * acquired lock. Process birth also makes abandoned tickets safe after reboot. */
8
+ export declare function acquireProcessLock(file: string, options?: {
9
+ signal?: AbortSignal;
10
+ onWait?: () => Promise<boolean>;
11
+ }): Promise<ProcessLock | undefined>;
@@ -0,0 +1,23 @@
1
+ import { type ComputerConnectionCode } from "../computer.js";
2
+ export type PairingQRMode = "auto" | "terminal" | "browser" | "none";
3
+ type Output = Pick<NodeJS.WriteStream, "isTTY" | "columns" | "rows" | "write" | "on" | "off">;
4
+ interface DisplayOptions {
5
+ mode?: PairingQRMode;
6
+ output?: Output;
7
+ environment?: NodeJS.ProcessEnv;
8
+ openBrowser?: (url: string) => Promise<boolean>;
9
+ }
10
+ export interface PairingDisplay {
11
+ close(): void;
12
+ }
13
+ /** qrcode's small terminal renderer ignores margin/width. Render its matrix with
14
+ * a four-module quiet zone, two square QR modules per terminal character. */
15
+ export declare function createPairingQR(invitation: ComputerConnectionCode): Promise<{
16
+ lines: string[];
17
+ columns: number;
18
+ rows: number;
19
+ svg: string;
20
+ }>;
21
+ /** Display one existing invitation. Resizing never starts another service or pairing. */
22
+ export declare function showPairingInvitation(invitation: ComputerConnectionCode, options?: DisplayOptions): Promise<PairingDisplay>;
23
+ export {};
@@ -0,0 +1,26 @@
1
+ import { type ChildProcess } from "node:child_process";
2
+ export interface ProcessIdentity {
3
+ pid: number;
4
+ start: string;
5
+ }
6
+ export interface ProcessState {
7
+ pid: number;
8
+ start?: string;
9
+ }
10
+ export interface OwnedProcess {
11
+ readonly pid: number;
12
+ readonly identity?: ProcessIdentity;
13
+ alive(): boolean;
14
+ close(): Promise<void>;
15
+ }
16
+ export declare function processAlive(pid: number | undefined): boolean;
17
+ /** Include process birth, not just its reusable PID, when adopting an orphan. */
18
+ export declare function processIdentity(pid: number): Promise<ProcessIdentity | undefined>;
19
+ export declare function currentProcessIdentity(): Promise<ProcessIdentity>;
20
+ /** Old CLI records contain only a PID. New records also survive PID reuse after
21
+ * reboot, so an unrelated process cannot block recovery or receive Stop. */
22
+ export declare function processStateAlive(state: ProcessState | undefined): Promise<boolean>;
23
+ /** Launch/startup locks used plain numeric PIDs before process identities. */
24
+ export declare function readProcessState(file: string): Promise<ProcessState | undefined>;
25
+ export declare function ownChild(child: ChildProcess): Promise<OwnedProcess>;
26
+ export declare function adoptProcess(identity: ProcessIdentity): Promise<OwnedProcess | undefined>;
@@ -1,5 +1,6 @@
1
1
  import { type ChildProcess } from "node:child_process";
2
2
  import type { ComputerRoute } from "../computer.js";
3
+ import { type OwnedProcess } from "./process.js";
3
4
  export interface RelayOptions {
4
5
  kind: "none" | "cloudflare" | "ngrok" | "custom";
5
6
  /** A stable, already configured hostname; custom relays must forward WebSocket upgrades. */
@@ -9,11 +10,14 @@ export interface RelayOptions {
9
10
  export interface RelayHandle {
10
11
  route?: ComputerRoute;
11
12
  process?: ChildProcess;
12
- close(): void;
13
+ owner?: OwnedProcess;
14
+ close(): void | Promise<void>;
13
15
  }
14
16
  export declare function websocketURL(value: string): string;
15
17
  /** Both providers forward encrypted SSH bytes to one loopback WebSocket bridge. */
16
18
  export declare function startRelay(options: RelayOptions, port: number, runtime?: {
17
19
  cacheDir?: string;
18
20
  onProgress?: (message: string) => void | Promise<void>;
21
+ signal?: AbortSignal;
22
+ onSpawn?: (owner: OwnedProcess) => Promise<void>;
19
23
  }): Promise<RelayHandle>;
@@ -0,0 +1,38 @@
1
+ type Command = [string, ...string[]];
2
+ export interface StartupPlan {
3
+ kind: "launchd" | "systemd" | "task-scheduler";
4
+ name: string;
5
+ file: string;
6
+ content: string;
7
+ query: Command;
8
+ enable: Command[];
9
+ disable: Command[];
10
+ }
11
+ export interface StartupState {
12
+ enabled: boolean;
13
+ running?: boolean;
14
+ kind?: StartupPlan["kind"];
15
+ name?: string;
16
+ file?: string;
17
+ }
18
+ /** Per-user startup, with no root service, password, or copied pairing secret. */
19
+ export declare function startupPlan(options: {
20
+ directory: string;
21
+ cliPath: string;
22
+ executable?: string;
23
+ platform?: NodeJS.Platform;
24
+ home?: string;
25
+ uid?: number;
26
+ user?: string;
27
+ environmentPath?: string;
28
+ }): StartupPlan;
29
+ export declare function startupStatus(directory: string): Promise<StartupState>;
30
+ export declare function configureStartup(directory: string, cliPath: string, enabled: boolean, runtime?: {
31
+ plan?: StartupPlan;
32
+ run?: (command: Command) => Promise<void>;
33
+ verify?: () => Promise<void>;
34
+ }): Promise<StartupState>;
35
+ /** Native startup managers supervise this small guardian. It adopts an existing
36
+ * controller and honours an explicit stop; it never owns or kills user work. */
37
+ export declare function watchComputer(directory: string, cliPath: string): Promise<void>;
38
+ export {};
@@ -17,12 +17,26 @@ export interface ComputerInvitation {
17
17
  secret: string;
18
18
  expiresAt: string;
19
19
  }
20
+ /** Address refresh for an already paired phone. Contains no credential and grants no access;
21
+ * the phone must authenticate with its saved key and verify its saved host fingerprint. */
22
+ export interface ComputerReconnectCode {
23
+ version: 1;
24
+ mode: "reconnect";
25
+ computerId: string;
26
+ registryId: string;
27
+ name: string;
28
+ fingerprint: string;
29
+ routes: ComputerRoute[];
30
+ expiresAt: string;
31
+ }
32
+ export type ComputerConnectionCode = ComputerInvitation | ComputerReconnectCode;
20
33
  export interface ComputerDevice {
21
34
  id: string;
22
35
  name: string;
23
36
  publicKey: string;
24
37
  createdAt: string;
25
38
  revoked: boolean;
39
+ connected?: boolean;
26
40
  }
27
41
  export interface ComputerPairRequest {
28
42
  id: string;
@@ -41,6 +55,8 @@ export interface ComputerUpdate {
41
55
  version: string;
42
56
  updatedAt: string;
43
57
  error?: string;
58
+ /** Explicit owner restart; automatic requests omit this and wait for idle. */
59
+ force?: boolean;
44
60
  status: "idle" | "queued" | "downloading" | "waiting" | "restarting" | "complete" | "failed";
45
61
  }
46
62
  export interface ComputerInfo {
@@ -70,7 +86,11 @@ export declare class ComputerApi {
70
86
  info(): Promise<ComputerInfo>;
71
87
  setRoutes(routes: ComputerRoute[]): Promise<ComputerInfo>;
72
88
  updateStatus(): Promise<ComputerUpdate>;
73
- requestUpdate(version: string): Promise<ComputerUpdate>;
89
+ /** Automatic requests wait for idle. With serviceUpdateVersion >= 2, force
90
+ * promotes the same active request to an explicit restart without re-downloading. */
91
+ requestUpdate(version: string, options?: {
92
+ force?: boolean;
93
+ }): Promise<ComputerUpdate>;
74
94
  invite(routes: ComputerRoute[]): Promise<ComputerInvitation>;
75
95
  pairing(id: string): Promise<ComputerPairing>;
76
96
  completePairing(id: string, requestId: string): Promise<{
@@ -92,5 +112,9 @@ export declare class ComputerApi {
92
112
  ok: boolean;
93
113
  }>;
94
114
  }
115
+ /** The mobile scanner accepts raw JSON. Avoid base64 overhead in QR codes without
116
+ * dropping routes, shortening the host pin or changing the pairing protocol.
117
+ * This includes a short-lived secret; never log it to shared service logs. */
118
+ export declare function computerPairingQRData(invitation: ComputerConnectionCode): string;
95
119
  /** A URI carries an invitation, not permanent credentials. Never log it to shared service logs. */
96
- export declare function computerPairingURI(invitation: ComputerInvitation): string;
120
+ export declare function computerPairingURI(invitation: ComputerConnectionCode): string;