linkshell-cli 0.9.0 → 0.10.0

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.
Files changed (153) hide show
  1. package/README.md +11 -6
  2. package/dist/cli/src/commands/gateway.d.ts +2 -0
  3. package/dist/cli/src/commands/gateway.js +29 -0
  4. package/dist/cli/src/commands/gateway.js.map +1 -0
  5. package/dist/cli/src/commands/host.d.ts +2 -0
  6. package/dist/cli/src/commands/host.js +12 -2
  7. package/dist/cli/src/commands/host.js.map +1 -1
  8. package/dist/cli/src/commands/setup.js +4 -2
  9. package/dist/cli/src/commands/setup.js.map +1 -1
  10. package/dist/cli/src/index.js +12 -334
  11. package/dist/cli/src/index.js.map +1 -1
  12. package/dist/cli/src/utils/daemon.d.ts +0 -7
  13. package/dist/cli/src/utils/daemon.js +1 -18
  14. package/dist/cli/src/utils/daemon.js.map +1 -1
  15. package/dist/cli/tsconfig.tsbuildinfo +1 -1
  16. package/dist/gateway/src/accounts.d.ts +6 -0
  17. package/dist/gateway/src/accounts.js +32 -0
  18. package/dist/gateway/src/accounts.js.map +1 -0
  19. package/dist/gateway/src/index.d.ts +4 -0
  20. package/dist/gateway/src/index.js +5 -0
  21. package/dist/gateway/src/index.js.map +1 -0
  22. package/dist/gateway/src/main.d.ts +1 -0
  23. package/dist/gateway/src/main.js +57 -0
  24. package/dist/gateway/src/main.js.map +1 -0
  25. package/dist/gateway/src/rate-limit.d.ts +22 -0
  26. package/dist/gateway/src/rate-limit.js +66 -0
  27. package/dist/gateway/src/rate-limit.js.map +1 -0
  28. package/dist/gateway/src/relay.d.ts +84 -0
  29. package/dist/gateway/src/relay.js +434 -0
  30. package/dist/gateway/src/relay.js.map +1 -0
  31. package/dist/gateway/src/serve.d.ts +34 -0
  32. package/dist/gateway/src/serve.js +102 -0
  33. package/dist/gateway/src/serve.js.map +1 -0
  34. package/dist/gateway/src/store.d.ts +35 -0
  35. package/dist/gateway/src/store.js +109 -0
  36. package/dist/gateway/src/store.js.map +1 -0
  37. package/dist/gateway/src/subscription.d.ts +18 -0
  38. package/dist/gateway/src/subscription.js +46 -0
  39. package/dist/gateway/src/subscription.js.map +1 -0
  40. package/dist/host/src/drivers/claude/transcript.d.ts +23 -23
  41. package/dist/host/src/fs.d.ts +3 -3
  42. package/dist/host/src/input.d.ts +4 -4
  43. package/dist/host/src/terminals.d.ts +1 -1
  44. package/dist/wire/src/model.d.ts +6 -6
  45. package/dist/wire/src/relay.d.ts +8 -8
  46. package/dist/wire/src/rpc.d.ts +818 -818
  47. package/dist/wire/src/updates.d.ts +18 -18
  48. package/package.json +4 -13
  49. package/src/commands/gateway.ts +31 -0
  50. package/src/commands/host.ts +13 -2
  51. package/src/commands/setup.ts +4 -2
  52. package/src/index.ts +14 -429
  53. package/src/utils/daemon.ts +2 -27
  54. package/dist/cli/src/config.d.ts +0 -14
  55. package/dist/cli/src/config.js +0 -23
  56. package/dist/cli/src/config.js.map +0 -1
  57. package/dist/cli/src/machine-id.d.ts +0 -6
  58. package/dist/cli/src/machine-id.js +0 -50
  59. package/dist/cli/src/machine-id.js.map +0 -1
  60. package/dist/cli/src/providers.d.ts +0 -13
  61. package/dist/cli/src/providers.js +0 -77
  62. package/dist/cli/src/providers.js.map +0 -1
  63. package/dist/cli/src/runtime/acp/acp-client.d.ts +0 -128
  64. package/dist/cli/src/runtime/acp/acp-client.js +0 -430
  65. package/dist/cli/src/runtime/acp/acp-client.js.map +0 -1
  66. package/dist/cli/src/runtime/acp/agent-process-discovery.d.ts +0 -48
  67. package/dist/cli/src/runtime/acp/agent-process-discovery.js +0 -278
  68. package/dist/cli/src/runtime/acp/agent-process-discovery.js.map +0 -1
  69. package/dist/cli/src/runtime/acp/agent-session.d.ts +0 -62
  70. package/dist/cli/src/runtime/acp/agent-session.js +0 -1081
  71. package/dist/cli/src/runtime/acp/agent-session.js.map +0 -1
  72. package/dist/cli/src/runtime/acp/agent-workspace.d.ts +0 -311
  73. package/dist/cli/src/runtime/acp/agent-workspace.js +0 -6083
  74. package/dist/cli/src/runtime/acp/agent-workspace.js.map +0 -1
  75. package/dist/cli/src/runtime/acp/claude-sdk-client.d.ts +0 -121
  76. package/dist/cli/src/runtime/acp/claude-sdk-client.js +0 -1147
  77. package/dist/cli/src/runtime/acp/claude-sdk-client.js.map +0 -1
  78. package/dist/cli/src/runtime/acp/claude-stream-json-client.d.ts +0 -53
  79. package/dist/cli/src/runtime/acp/claude-stream-json-client.js +0 -552
  80. package/dist/cli/src/runtime/acp/claude-stream-json-client.js.map +0 -1
  81. package/dist/cli/src/runtime/acp/json-rpc.d.ts +0 -22
  82. package/dist/cli/src/runtime/acp/json-rpc.js +0 -160
  83. package/dist/cli/src/runtime/acp/json-rpc.js.map +0 -1
  84. package/dist/cli/src/runtime/acp/provider-resolver.d.ts +0 -16
  85. package/dist/cli/src/runtime/acp/provider-resolver.js +0 -132
  86. package/dist/cli/src/runtime/acp/provider-resolver.js.map +0 -1
  87. package/dist/cli/src/runtime/bridge-session.d.ts +0 -97
  88. package/dist/cli/src/runtime/bridge-session.js +0 -1364
  89. package/dist/cli/src/runtime/bridge-session.js.map +0 -1
  90. package/dist/cli/src/runtime/hook-command.d.ts +0 -9
  91. package/dist/cli/src/runtime/hook-command.js +0 -80
  92. package/dist/cli/src/runtime/hook-command.js.map +0 -1
  93. package/dist/cli/src/runtime/screen-fallback.d.ts +0 -22
  94. package/dist/cli/src/runtime/screen-fallback.js +0 -202
  95. package/dist/cli/src/runtime/screen-fallback.js.map +0 -1
  96. package/dist/cli/src/runtime/screen-share.d.ts +0 -34
  97. package/dist/cli/src/runtime/screen-share.js +0 -376
  98. package/dist/cli/src/runtime/screen-share.js.map +0 -1
  99. package/dist/cli/src/runtime/scrollback.d.ts +0 -11
  100. package/dist/cli/src/runtime/scrollback.js +0 -33
  101. package/dist/cli/src/runtime/scrollback.js.map +0 -1
  102. package/dist/cli/src/runtime/usage-report.d.ts +0 -34
  103. package/dist/cli/src/runtime/usage-report.js +0 -332
  104. package/dist/cli/src/runtime/usage-report.js.map +0 -1
  105. package/dist/cli/src/utils/keep-awake.d.ts +0 -6
  106. package/dist/cli/src/utils/keep-awake.js +0 -48
  107. package/dist/cli/src/utils/keep-awake.js.map +0 -1
  108. package/dist/cli/src/utils/lan-ip.d.ts +0 -9
  109. package/dist/cli/src/utils/lan-ip.js +0 -61
  110. package/dist/cli/src/utils/lan-ip.js.map +0 -1
  111. package/dist/host/src/input-helper.d.ts +0 -1
  112. package/dist/host/src/input-helper.js +0 -564
  113. package/dist/host/src/input-helper.js.map +0 -1
  114. package/dist/shared-protocol/src/index.d.ts +0 -17029
  115. package/dist/shared-protocol/src/index.js +0 -1064
  116. package/dist/shared-protocol/src/index.js.map +0 -1
  117. package/scripts/copy-web.mjs +0 -34
  118. package/src/config.ts +0 -36
  119. package/src/machine-id.ts +0 -61
  120. package/src/providers.ts +0 -97
  121. package/src/runtime/acp/acp-client.ts +0 -521
  122. package/src/runtime/acp/agent-process-discovery.ts +0 -308
  123. package/src/runtime/acp/agent-session.ts +0 -1186
  124. package/src/runtime/acp/agent-workspace.ts +0 -6590
  125. package/src/runtime/acp/claude-sdk-client.ts +0 -1221
  126. package/src/runtime/acp/claude-stream-json-client.ts +0 -633
  127. package/src/runtime/acp/json-rpc.ts +0 -184
  128. package/src/runtime/acp/provider-resolver.ts +0 -154
  129. package/src/runtime/bridge-session.ts +0 -1549
  130. package/src/runtime/hook-command.ts +0 -73
  131. package/src/runtime/screen-fallback.ts +0 -235
  132. package/src/runtime/screen-share.ts +0 -426
  133. package/src/runtime/scrollback.ts +0 -43
  134. package/src/runtime/usage-report.ts +0 -342
  135. package/src/utils/keep-awake.ts +0 -61
  136. package/src/utils/lan-ip.ts +0 -61
  137. package/web/assets/FileBrowser-wOAfY-xj.js +0 -2
  138. package/web/assets/PortPreview-Cbvv7yzA.js +0 -2
  139. package/web/assets/TerminalPanel-CTSklkct.js +0 -1
  140. package/web/assets/UsageDashboard-CJ1AsNmd.js +0 -1
  141. package/web/assets/index-BsnDaeCt.css +0 -33
  142. package/web/assets/index-q85psYZ5.js +0 -36
  143. package/web/assets/vendor-highlight-NXWAAyIv.js +0 -5
  144. package/web/assets/vendor-react-M7xG3qiw.js +0 -49
  145. package/web/assets/vendor-xterm-D15THcI4.js +0 -9
  146. package/web/index.html +0 -37
  147. package/web/logos/claude.png +0 -0
  148. package/web/logos/codex.png +0 -0
  149. package/web/logos/copilot.png +0 -0
  150. package/web/logos/gemini.png +0 -0
  151. package/web/logos/linkshell-1024.png +0 -0
  152. package/web/logos/linkshell-splash.png +0 -0
  153. package/web/logos/linkshell.png +0 -0
@@ -0,0 +1,109 @@
1
+ import { DatabaseSync } from "node:sqlite";
2
+ export class GatewayStore {
3
+ db;
4
+ constructor(path) {
5
+ this.db = new DatabaseSync(path);
6
+ this.db.exec(`
7
+ PRAGMA journal_mode = WAL;
8
+ CREATE TABLE IF NOT EXISTS peers (
9
+ id TEXT PRIMARY KEY,
10
+ role TEXT NOT NULL,
11
+ sign_key TEXT NOT NULL,
12
+ box_key TEXT NOT NULL,
13
+ name TEXT NOT NULL,
14
+ platform TEXT,
15
+ user_id TEXT,
16
+ last_seen INTEGER NOT NULL
17
+ );
18
+ CREATE INDEX IF NOT EXISTS peers_by_user ON peers (user_id);
19
+ CREATE TABLE IF NOT EXISTS links (
20
+ machine_id TEXT NOT NULL,
21
+ device_id TEXT NOT NULL,
22
+ created_at INTEGER NOT NULL,
23
+ PRIMARY KEY (machine_id, device_id)
24
+ ) WITHOUT ROWID;
25
+ CREATE INDEX IF NOT EXISTS links_by_device ON links (device_id);
26
+ `);
27
+ }
28
+ close() {
29
+ this.db.close();
30
+ }
31
+ peer(id) {
32
+ const row = this.db.prepare("SELECT * FROM peers WHERE id = ?").get(id);
33
+ return row ? toPeer(row) : undefined;
34
+ }
35
+ upsertPeer(peer) {
36
+ this.db
37
+ .prepare(`INSERT INTO peers (id, role, sign_key, box_key, name, platform, user_id, last_seen)
38
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?)
39
+ ON CONFLICT(id) DO UPDATE SET box_key = excluded.box_key, name = excluded.name,
40
+ platform = excluded.platform, user_id = excluded.user_id, last_seen = excluded.last_seen`)
41
+ .run(peer.id, peer.role, peer.signKey, peer.boxKey, peer.name, peer.platform ?? null, peer.userId ?? null, peer.lastSeen);
42
+ }
43
+ touch(id, at = Date.now()) {
44
+ this.db.prepare("UPDATE peers SET last_seen = ? WHERE id = ?").run(at, id);
45
+ }
46
+ link(machineId, deviceId, at = Date.now()) {
47
+ this.db.prepare("INSERT OR IGNORE INTO links (machine_id, device_id, created_at) VALUES (?, ?, ?)").run(machineId, deviceId, at);
48
+ }
49
+ unlink(machineId, deviceId) {
50
+ return this.db.prepare("DELETE FROM links WHERE machine_id = ? AND device_id = ?").run(machineId, deviceId).changes > 0;
51
+ }
52
+ /**
53
+ * Takes a peer off its account: the account's other peers no longer reach it, or list it. Its
54
+ * keys and pairings stay, and signing in again puts it back.
55
+ */
56
+ disown(id) {
57
+ return this.db.prepare("UPDATE peers SET user_id = NULL WHERE id = ? AND user_id IS NOT NULL").run(id).changes > 0;
58
+ }
59
+ linkedAt(machineId, deviceId) {
60
+ const row = this.db.prepare("SELECT created_at FROM links WHERE machine_id = ? AND device_id = ?").get(machineId, deviceId);
61
+ return row?.created_at;
62
+ }
63
+ /** Peers of the other role that `id` may reach: linked, or owned by the same account. */
64
+ reachable(id) {
65
+ const self = this.peer(id);
66
+ if (!self)
67
+ return [];
68
+ const other = self.role === "machine" ? "device" : "machine";
69
+ const linked = (self.role === "machine"
70
+ ? this.db.prepare("SELECT p.*, l.created_at AS paired_at FROM links l JOIN peers p ON p.id = l.device_id WHERE l.machine_id = ?").all(id)
71
+ : this.db.prepare("SELECT p.*, l.created_at AS paired_at FROM links l JOIN peers p ON p.id = l.machine_id WHERE l.device_id = ?").all(id));
72
+ const out = new Map();
73
+ for (const row of linked)
74
+ out.set(String(row.id), { peer: toPeer(row), via: "paired", pairedAt: Number(row.paired_at) });
75
+ if (self.userId) {
76
+ const owned = this.db.prepare("SELECT * FROM peers WHERE user_id = ? AND role = ?").all(self.userId, other);
77
+ for (const row of owned)
78
+ if (!out.has(String(row.id)))
79
+ out.set(String(row.id), { peer: toPeer(row), via: "account" });
80
+ }
81
+ return [...out.values()];
82
+ }
83
+ /** How `from` may reach `to`, or undefined when it may not. */
84
+ route(from, to) {
85
+ const a = this.peer(from);
86
+ const b = this.peer(to);
87
+ if (!a || !b || a.role === b.role)
88
+ return undefined;
89
+ const [machine, device] = a.role === "machine" ? [a, b] : [b, a];
90
+ if (this.linkedAt(machine.id, device.id) !== undefined)
91
+ return "paired";
92
+ if (a.userId && a.userId === b.userId)
93
+ return "account";
94
+ return undefined;
95
+ }
96
+ }
97
+ function toPeer(row) {
98
+ return {
99
+ id: String(row.id),
100
+ role: row.role,
101
+ signKey: String(row.sign_key),
102
+ boxKey: String(row.box_key),
103
+ name: String(row.name),
104
+ platform: row.platform ? String(row.platform) : undefined,
105
+ userId: row.user_id ? String(row.user_id) : undefined,
106
+ lastSeen: Number(row.last_seen),
107
+ };
108
+ }
109
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../../../../gateway/src/store.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { GatewayOptions } from "./relay.js";
2
+ export interface SubscriptionCheck {
3
+ /** "unknown": the lookup itself failed, which says nothing about the account. */
4
+ status: "active" | "inactive" | "unknown";
5
+ reason?: string;
6
+ }
7
+ export type CheckSubscription = (userId: string) => Promise<SubscriptionCheck>;
8
+ export declare function supabaseSubscriptions(supabase: {
9
+ url: string;
10
+ anonKey: string;
11
+ serviceRoleKey: string;
12
+ }): CheckSubscription;
13
+ /**
14
+ * The official gateway's rule for who may connect: a computer needs an active
15
+ * Pro account. Devices only reach computers they're paired with or share an
16
+ * account with, so they need nothing more.
17
+ */
18
+ export declare function requirePro(check: CheckSubscription, warn: (message: string) => void): NonNullable<GatewayOptions["admit"]>;
@@ -0,0 +1,46 @@
1
+ export function supabaseSubscriptions(supabase) {
2
+ return async (userId) => {
3
+ if (!supabase.url || !supabase.anonKey)
4
+ return { status: "unknown", reason: "missing_supabase_config" };
5
+ if (!supabase.serviceRoleKey)
6
+ return { status: "unknown", reason: "missing_service_role_key" };
7
+ try {
8
+ const response = await fetch(`${supabase.url}/rest/v1/profiles?id=eq.${userId}&select=plan,plan_expires_at&limit=1`, {
9
+ headers: { Authorization: `Bearer ${supabase.serviceRoleKey}`, apikey: supabase.anonKey },
10
+ signal: AbortSignal.timeout(5_000),
11
+ });
12
+ if (!response.ok)
13
+ return { status: "unknown", reason: `profile_lookup_http_${response.status}` };
14
+ const profiles = (await response.json());
15
+ const profile = profiles[0];
16
+ if (!profile)
17
+ return { status: "unknown", reason: "profile_not_found" };
18
+ const active = profile.plan === "pro" && !!profile.plan_expires_at && new Date(profile.plan_expires_at) > new Date();
19
+ return { status: active ? "active" : "inactive" };
20
+ }
21
+ catch {
22
+ return { status: "unknown", reason: "profile_lookup_failed" };
23
+ }
24
+ };
25
+ }
26
+ /**
27
+ * The official gateway's rule for who may connect: a computer needs an active
28
+ * Pro account. Devices only reach computers they're paired with or share an
29
+ * account with, so they need nothing more.
30
+ */
31
+ export function requirePro(check, warn) {
32
+ return async ({ role, userId }) => {
33
+ if (role !== "machine")
34
+ return undefined;
35
+ if (!userId)
36
+ return "官方网关需要登录 Pro 账号:在电脑上运行 linkshell login";
37
+ const subscription = await check(userId);
38
+ // A lookup failure isn't a lapsed subscription; don't lock people out over it.
39
+ if (subscription.status === "inactive")
40
+ return "官方网关需要 Pro 订阅:https://itool.tech";
41
+ if (subscription.status === "unknown")
42
+ warn(`subscription check unavailable (${subscription.reason}); admitting ${userId}`);
43
+ return undefined;
44
+ };
45
+ }
46
+ //# sourceMappingURL=subscription.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"subscription.js","sourceRoot":"","sources":["../../../../gateway/src/subscription.ts"],"names":[],"mappings":"AAcA,MAAM,UAAU,qBAAqB,CAAC,QAAkE;IACtG,OAAO,KAAK,EAAE,MAAM,EAAE,EAAE;QACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO;YAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,yBAAyB,EAAE,CAAC;QACxG,IAAI,CAAC,QAAQ,CAAC,cAAc;YAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,0BAA0B,EAAE,CAAC;QAC/F,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,QAAQ,CAAC,GAAG,2BAA2B,MAAM,sCAAsC,EAAE;gBACnH,OAAO,EAAE,EAAE,aAAa,EAAE,UAAU,QAAQ,CAAC,cAAc,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,OAAO,EAAE;gBACzF,MAAM,EAAE,WAAW,CAAC,OAAO,CAAC,KAAK,CAAC;aACnC,CAAC,CAAC;YACH,IAAI,CAAC,QAAQ,CAAC,EAAE;gBAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YACjG,MAAM,QAAQ,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuD,CAAC;YAC/F,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,CAAC,OAAO;gBAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,mBAAmB,EAAE,CAAC;YACxE,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,OAAO,CAAC,eAAe,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,eAAe,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YACrH,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC;QACpD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,uBAAuB,EAAE,CAAC;QAChE,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,UAAU,CAAC,KAAwB,EAAE,IAA+B;IAClF,OAAO,KAAK,EAAE,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE;QAChC,IAAI,IAAI,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QACzC,IAAI,CAAC,MAAM;YAAE,OAAO,wCAAwC,CAAC;QAC7D,MAAM,YAAY,GAAG,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC;QACzC,+EAA+E;QAC/E,IAAI,YAAY,CAAC,MAAM,KAAK,UAAU;YAAE,OAAO,kCAAkC,CAAC;QAClF,IAAI,YAAY,CAAC,MAAM,KAAK,SAAS;YAAE,IAAI,CAAC,mCAAmC,YAAY,CAAC,MAAM,gBAAgB,MAAM,EAAE,CAAC,CAAC;QAC5H,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;AACJ,CAAC"}
@@ -33,7 +33,6 @@ export declare function transcriptLine(raw: string, options?: {
33
33
  /** Parses a whole transcript file. */
34
34
  /** When each transcript update happened, for history import. */
35
35
  export declare const transcriptTimes: WeakMap<{
36
- sessionUpdate: "user_message_chunk";
37
36
  content: {
38
37
  type: "text";
39
38
  text: string;
@@ -43,15 +42,14 @@ export declare const transcriptTimes: WeakMap<{
43
42
  data?: string | undefined;
44
43
  uri?: string | undefined;
45
44
  } | {
46
- name: string;
47
45
  type: "resource_link";
46
+ name: string;
48
47
  uri: string;
49
48
  kind?: "agent" | "file" | "skill" | undefined;
50
49
  };
50
+ sessionUpdate: "user_message_chunk";
51
51
  messageId?: string | undefined;
52
52
  } | {
53
- sessionUpdate: "agent_message_chunk";
54
- messageId: string;
55
53
  content: {
56
54
  type: "text";
57
55
  text: string;
@@ -61,15 +59,15 @@ export declare const transcriptTimes: WeakMap<{
61
59
  data?: string | undefined;
62
60
  uri?: string | undefined;
63
61
  } | {
64
- name: string;
65
62
  type: "resource_link";
63
+ name: string;
66
64
  uri: string;
67
65
  kind?: "agent" | "file" | "skill" | undefined;
68
66
  };
67
+ sessionUpdate: "agent_message_chunk";
68
+ messageId: string;
69
69
  parentToolCallId?: string | undefined;
70
70
  } | {
71
- sessionUpdate: "agent_thought_chunk";
72
- messageId: string;
73
71
  content: {
74
72
  type: "text";
75
73
  text: string;
@@ -79,16 +77,18 @@ export declare const transcriptTimes: WeakMap<{
79
77
  data?: string | undefined;
80
78
  uri?: string | undefined;
81
79
  } | {
82
- name: string;
83
80
  type: "resource_link";
81
+ name: string;
84
82
  uri: string;
85
83
  kind?: "agent" | "file" | "skill" | undefined;
86
84
  };
85
+ sessionUpdate: "agent_thought_chunk";
86
+ messageId: string;
87
87
  parentToolCallId?: string | undefined;
88
88
  } | {
89
- status: "pending" | "in_progress" | "completed" | "failed";
89
+ status: "failed" | "pending" | "in_progress" | "completed";
90
+ kind: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other";
90
91
  title: string;
91
- kind: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other";
92
92
  toolCallId: string;
93
93
  sessionUpdate: "tool_call";
94
94
  detail?: {
@@ -98,12 +98,12 @@ export declare const transcriptTimes: WeakMap<{
98
98
  } | {
99
99
  type: "subagent";
100
100
  action: "message" | "spawn" | "wait" | "stop" | "resume" | "list";
101
- model?: string | undefined;
102
101
  task?: string | undefined;
103
102
  agentType?: string | undefined;
103
+ model?: string | undefined;
104
104
  } | {
105
- name: string;
106
105
  type: "skill";
106
+ name: string;
107
107
  description?: string | undefined;
108
108
  } | {
109
109
  type: "web_search";
@@ -132,8 +132,8 @@ export declare const transcriptTimes: WeakMap<{
132
132
  data?: string | undefined;
133
133
  uri?: string | undefined;
134
134
  } | {
135
- name: string;
136
135
  type: "resource_link";
136
+ name: string;
137
137
  uri: string;
138
138
  kind?: "agent" | "file" | "skill" | undefined;
139
139
  };
@@ -161,6 +161,8 @@ export declare const transcriptTimes: WeakMap<{
161
161
  } | {
162
162
  toolCallId: string;
163
163
  sessionUpdate: "tool_call_update";
164
+ status?: "failed" | "pending" | "in_progress" | "completed" | undefined;
165
+ title?: string | undefined;
164
166
  detail?: {
165
167
  type: "mcp";
166
168
  tool: string;
@@ -168,12 +170,12 @@ export declare const transcriptTimes: WeakMap<{
168
170
  } | {
169
171
  type: "subagent";
170
172
  action: "message" | "spawn" | "wait" | "stop" | "resume" | "list";
171
- model?: string | undefined;
172
173
  task?: string | undefined;
173
174
  agentType?: string | undefined;
175
+ model?: string | undefined;
174
176
  } | {
175
- name: string;
176
177
  type: "skill";
178
+ name: string;
177
179
  description?: string | undefined;
178
180
  } | {
179
181
  type: "web_search";
@@ -191,8 +193,6 @@ export declare const transcriptTimes: WeakMap<{
191
193
  text: string;
192
194
  more?: number | undefined;
193
195
  } | undefined;
194
- status?: "pending" | "in_progress" | "completed" | "failed" | undefined;
195
- title?: string | undefined;
196
196
  content?: ({
197
197
  type: "content";
198
198
  content: {
@@ -204,8 +204,8 @@ export declare const transcriptTimes: WeakMap<{
204
204
  data?: string | undefined;
205
205
  uri?: string | undefined;
206
206
  } | {
207
- name: string;
208
207
  type: "resource_link";
208
+ name: string;
209
209
  uri: string;
210
210
  kind?: "agent" | "file" | "skill" | undefined;
211
211
  };
@@ -259,14 +259,14 @@ export declare const transcriptTimes: WeakMap<{
259
259
  parentToolCallId?: string | undefined;
260
260
  } | {
261
261
  options: {
262
- name: string;
263
262
  values: {
264
- name: string;
265
263
  value: string;
264
+ name: string;
266
265
  description?: string | undefined;
267
266
  }[];
268
267
  id: string;
269
- category: "model" | "other" | "mode" | "effort";
268
+ name: string;
269
+ category: "mode" | "other" | "model" | "effort";
270
270
  current: string;
271
271
  }[];
272
272
  sessionUpdate: "ls_config";
@@ -283,15 +283,15 @@ export declare const transcriptTimes: WeakMap<{
283
283
  stopReason?: "error" | "end_turn" | "cancelled" | "max_tokens" | "refusal" | undefined;
284
284
  } | {
285
285
  options: {
286
+ optionId: string;
286
287
  name: string;
287
288
  kind: "allow_once" | "allow_always" | "reject_once" | "reject_always";
288
- optionId: string;
289
289
  }[];
290
290
  title: string;
291
291
  requestId: string;
292
292
  sessionUpdate: "ls_permission";
293
- detail?: string | undefined;
294
293
  toolCallId?: string | undefined;
294
+ detail?: string | undefined;
295
295
  questions?: {
296
296
  id: string;
297
297
  kind: "text" | "choice" | "choices";
@@ -4,8 +4,8 @@ export declare function listDirectory(input: {
4
4
  files?: boolean;
5
5
  }): Promise<{
6
6
  entries: {
7
- name: string;
8
7
  path: string;
8
+ name: string;
9
9
  file?: boolean | undefined;
10
10
  project?: boolean | undefined;
11
11
  size?: number | undefined;
@@ -15,8 +15,8 @@ export declare function listDirectory(input: {
15
15
  home: string;
16
16
  } | {
17
17
  entries: {
18
- name: string;
19
18
  path: string;
19
+ name: string;
20
20
  file?: boolean | undefined;
21
21
  project?: boolean | undefined;
22
22
  size?: number | undefined;
@@ -35,8 +35,8 @@ export declare function searchDirectories(input: {
35
35
  limit: number;
36
36
  }, budgetMs?: number): Promise<{
37
37
  entries: {
38
- name: string;
39
38
  path: string;
39
+ name: string;
40
40
  file?: boolean | undefined;
41
41
  project?: boolean | undefined;
42
42
  size?: number | undefined;
@@ -73,11 +73,11 @@ export declare const inputEvent: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
73
73
  t: z.ZodLiteral<"text">;
74
74
  s: z.ZodString;
75
75
  }, "strip", z.ZodTypeAny, {
76
- s: string;
77
76
  t: "text";
78
- }, {
79
77
  s: string;
78
+ }, {
80
79
  t: "text";
80
+ s: string;
81
81
  }>, z.ZodObject<{
82
82
  t: z.ZodLiteral<"prompt">;
83
83
  }, "strip", z.ZodTypeAny, {
@@ -158,11 +158,11 @@ export declare const videoSignal: z.ZodDiscriminatedUnion<"t", [z.ZodObject<{
158
158
  t: z.ZodLiteral<"rtc.answer">;
159
159
  sdp: z.ZodString;
160
160
  }, "strip", z.ZodTypeAny, {
161
- t: "rtc.answer";
162
161
  sdp: string;
163
- }, {
164
162
  t: "rtc.answer";
163
+ }, {
165
164
  sdp: string;
165
+ t: "rtc.answer";
166
166
  }>, z.ZodObject<{
167
167
  t: z.ZodLiteral<"rtc.ice">;
168
168
  candidate: z.ZodString;
@@ -36,9 +36,9 @@ export declare class TerminalManager {
36
36
  id: string;
37
37
  title: string;
38
38
  cwd: string;
39
+ createdAt: number;
39
40
  cols: number;
40
41
  rows: number;
41
- createdAt: number;
42
42
  activeAt: number;
43
43
  command?: string | undefined;
44
44
  exitCode?: number | null | undefined;
@@ -196,11 +196,11 @@ export declare const sessionActivitySchema: z.ZodObject<{
196
196
  }, "strip", z.ZodTypeAny, {
197
197
  kind: "thinking" | "responding" | "tool";
198
198
  title?: string | undefined;
199
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
199
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
200
200
  }, {
201
201
  kind: "thinking" | "responding" | "tool";
202
202
  title?: string | undefined;
203
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
203
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
204
204
  }>;
205
205
  export type SessionActivity = z.infer<typeof sessionActivitySchema>;
206
206
  /** The oldest unanswered permission request, so lists can offer approval inline. Live only. */
@@ -466,11 +466,11 @@ export declare const sessionSummarySchema: z.ZodObject<{
466
466
  }, "strip", z.ZodTypeAny, {
467
467
  kind: "thinking" | "responding" | "tool";
468
468
  title?: string | undefined;
469
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
469
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
470
470
  }, {
471
471
  kind: "thinking" | "responding" | "tool";
472
472
  title?: string | undefined;
473
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
473
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
474
474
  }>>;
475
475
  permission: z.ZodOptional<z.ZodObject<{
476
476
  requestId: z.ZodString;
@@ -655,7 +655,7 @@ export declare const sessionSummarySchema: z.ZodObject<{
655
655
  activity?: {
656
656
  kind: "thinking" | "responding" | "tool";
657
657
  title?: string | undefined;
658
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
658
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
659
659
  } | undefined;
660
660
  permission?: {
661
661
  options: {
@@ -713,7 +713,7 @@ export declare const sessionSummarySchema: z.ZodObject<{
713
713
  activity?: {
714
714
  kind: "thinking" | "responding" | "tool";
715
715
  title?: string | undefined;
716
- toolKind?: "read" | "edit" | "delete" | "move" | "search" | "execute" | "think" | "fetch" | "other" | undefined;
716
+ toolKind?: "search" | "read" | "edit" | "delete" | "move" | "execute" | "think" | "fetch" | "other" | undefined;
717
717
  } | undefined;
718
718
  permission?: {
719
719
  options: {
@@ -91,8 +91,8 @@ export declare const clientFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
91
91
  /** Account access token, when signed in. */
92
92
  token: z.ZodOptional<z.ZodString>;
93
93
  }, "strip", z.ZodTypeAny, {
94
- role: "machine" | "device";
95
94
  name: string;
95
+ role: "machine" | "device";
96
96
  t: "auth";
97
97
  identity: {
98
98
  id: string;
@@ -103,8 +103,8 @@ export declare const clientFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
103
103
  platform?: string | undefined;
104
104
  token?: string | undefined;
105
105
  }, {
106
- role: "machine" | "device";
107
106
  name: string;
107
+ role: "machine" | "device";
108
108
  t: "auth";
109
109
  identity: {
110
110
  id: string;
@@ -164,12 +164,12 @@ export declare const serverFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
164
164
  email: z.ZodOptional<z.ZodString>;
165
165
  }, "strip", z.ZodTypeAny, {
166
166
  t: "ready";
167
- email?: string | undefined;
168
167
  userId?: string | undefined;
168
+ email?: string | undefined;
169
169
  }, {
170
170
  t: "ready";
171
- email?: string | undefined;
172
171
  userId?: string | undefined;
172
+ email?: string | undefined;
173
173
  }>, z.ZodObject<{
174
174
  t: z.ZodLiteral<"res">;
175
175
  id: z.ZodNumber;
@@ -230,8 +230,8 @@ export declare const serverFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
230
230
  via: z.ZodEnum<["paired", "account"]>;
231
231
  d: z.ZodString;
232
232
  }, "strip", z.ZodTypeAny, {
233
- t: "from";
234
233
  via: "account" | "paired";
234
+ t: "from";
235
235
  d: string;
236
236
  from: {
237
237
  id: string;
@@ -239,8 +239,8 @@ export declare const serverFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
239
239
  boxKey: string;
240
240
  };
241
241
  }, {
242
- t: "from";
243
242
  via: "account" | "paired";
243
+ t: "from";
244
244
  d: string;
245
245
  from: {
246
246
  id: string;
@@ -252,13 +252,13 @@ export declare const serverFrameSchema: z.ZodDiscriminatedUnion<"t", [z.ZodObjec
252
252
  to: z.ZodString;
253
253
  reason: z.ZodString;
254
254
  }, "strip", z.ZodTypeAny, {
255
- reason: string;
256
255
  t: "undeliverable";
257
256
  to: string;
258
- }, {
259
257
  reason: string;
258
+ }, {
260
259
  t: "undeliverable";
261
260
  to: string;
261
+ reason: string;
262
262
  }>, z.ZodObject<{
263
263
  t: z.ZodLiteral<"pong">;
264
264
  }, "strip", z.ZodTypeAny, {