pikiloom 0.4.26 → 0.4.28

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 (156) hide show
  1. package/dashboard/dist/assets/{AgentTab-BNJ73P0m.js → AgentTab-DtjuI8NU.js} +1 -1
  2. package/dashboard/dist/assets/ConnectionModal-BIx6a5o1.js +1 -0
  3. package/dashboard/dist/assets/{DirBrowser-D-GT-G-w.js → DirBrowser-BINh_7NB.js} +1 -1
  4. package/dashboard/dist/assets/{ExtensionsTab-BrJMulJR.js → ExtensionsTab-CHpd147b.js} +1 -1
  5. package/dashboard/dist/assets/{IMAccessTab-auPnx468.js → IMAccessTab-C4DbGxbG.js} +1 -1
  6. package/dashboard/dist/assets/{Modal-lYfO9m-I.js → Modal-D_PUi-5O.js} +1 -1
  7. package/dashboard/dist/assets/{Modals-PRdWOIY9.js → Modals-BahDEMqf.js} +1 -1
  8. package/dashboard/dist/assets/{Select-BhbU-rll.js → Select-Cp5VXb_2.js} +1 -1
  9. package/dashboard/dist/assets/SessionPanel-DZVNXptx.js +1 -0
  10. package/dashboard/dist/assets/SystemTab-CLznS31f.js +1 -0
  11. package/dashboard/dist/assets/index-CLGovkkw.js +3 -0
  12. package/dashboard/dist/assets/index-CXIN3nTr.css +1 -0
  13. package/dashboard/dist/assets/index-DcYOI6rL.js +23 -0
  14. package/dashboard/dist/assets/{shared-C5uXvhZJ.js → shared-C8DCTJ44.js} +1 -1
  15. package/dashboard/dist/index.html +2 -2
  16. package/dist/agent/acp-client.js +0 -59
  17. package/dist/agent/artifacts.js +1 -38
  18. package/dist/agent/auto-update.js +2 -78
  19. package/dist/agent/await-resume.js +0 -20
  20. package/dist/agent/cli/auth.js +3 -51
  21. package/dist/agent/cli/catalog.js +0 -3
  22. package/dist/agent/cli/detector.js +1 -19
  23. package/dist/agent/cli/index.js +0 -3
  24. package/dist/agent/cli/registry.js +0 -25
  25. package/dist/agent/driver.js +0 -14
  26. package/dist/agent/drivers/claude-tui.js +2 -769
  27. package/dist/agent/drivers/claude.js +12 -631
  28. package/dist/agent/drivers/codex.js +11 -162
  29. package/dist/agent/drivers/gemini.js +6 -114
  30. package/dist/agent/drivers/hermes.js +0 -128
  31. package/dist/agent/goal.js +0 -45
  32. package/dist/agent/handover.js +1 -46
  33. package/dist/agent/images.js +7 -133
  34. package/dist/agent/index.js +1 -29
  35. package/dist/agent/mcp/bridge.js +1 -197
  36. package/dist/agent/mcp/extensions.js +5 -84
  37. package/dist/agent/mcp/oauth.js +2 -69
  38. package/dist/agent/mcp/registry.js +2 -33
  39. package/dist/agent/mcp/session-server.js +2 -45
  40. package/dist/agent/mcp/tools/ask-user.js +0 -6
  41. package/dist/agent/mcp/tools/await-resume.js +0 -15
  42. package/dist/agent/mcp/tools/goal.js +0 -25
  43. package/dist/agent/mcp/tools/types.js +0 -5
  44. package/dist/agent/mcp/tools/workspace.js +0 -23
  45. package/dist/agent/npm.js +0 -14
  46. package/dist/agent/session.js +86 -196
  47. package/dist/agent/skill-installer.js +3 -70
  48. package/dist/agent/skills.js +0 -43
  49. package/dist/agent/stream.js +5 -148
  50. package/dist/agent/types.js +0 -12
  51. package/dist/agent/utils.js +2 -120
  52. package/dist/bot/bot.js +3 -468
  53. package/dist/bot/command-ui.js +0 -45
  54. package/dist/bot/commands.js +0 -51
  55. package/dist/bot/headless-bot.js +0 -21
  56. package/dist/bot/host.js +1 -5
  57. package/dist/bot/human-loop.js +0 -8
  58. package/dist/bot/menu.js +0 -3
  59. package/dist/bot/orchestration.js +0 -3
  60. package/dist/bot/render-shared.js +0 -63
  61. package/dist/bot/session-hub.js +14 -92
  62. package/dist/bot/session-status.js +1 -5
  63. package/dist/bot/streaming.js +0 -53
  64. package/dist/browser-profile.js +0 -51
  65. package/dist/browser-supervisor.js +0 -75
  66. package/dist/catalog/cli-tools.js +0 -53
  67. package/dist/catalog/index.js +0 -18
  68. package/dist/catalog/local-models.js +0 -18
  69. package/dist/catalog/mcp-servers.js +0 -35
  70. package/dist/catalog/skill-repos.js +0 -32
  71. package/dist/channels/base.js +0 -19
  72. package/dist/channels/dingtalk/bot.js +0 -3
  73. package/dist/channels/dingtalk/channel.js +0 -33
  74. package/dist/channels/discord/bot.js +0 -7
  75. package/dist/channels/discord/channel.js +0 -22
  76. package/dist/channels/feishu/bot.js +0 -71
  77. package/dist/channels/feishu/channel.js +0 -78
  78. package/dist/channels/feishu/markdown.js +0 -5
  79. package/dist/channels/feishu/render.js +0 -45
  80. package/dist/channels/health.js +0 -46
  81. package/dist/channels/slack/bot.js +0 -7
  82. package/dist/channels/slack/channel.js +1 -27
  83. package/dist/channels/states.js +0 -3
  84. package/dist/channels/telegram/bot.js +0 -60
  85. package/dist/channels/telegram/channel.js +2 -99
  86. package/dist/channels/telegram/directory.js +0 -3
  87. package/dist/channels/telegram/live-preview.js +0 -8
  88. package/dist/channels/telegram/render.js +0 -30
  89. package/dist/channels/wecom/bot.js +0 -3
  90. package/dist/channels/wecom/channel.js +0 -58
  91. package/dist/channels/weixin/api.js +0 -9
  92. package/dist/channels/weixin/bot.js +0 -88
  93. package/dist/channels/weixin/channel.js +0 -6
  94. package/dist/cli/autostart.js +1 -44
  95. package/dist/cli/channel-supervisor.js +1 -59
  96. package/dist/cli/channels.js +0 -6
  97. package/dist/cli/main.js +1 -145
  98. package/dist/cli/onboarding.js +0 -6
  99. package/dist/cli/run.js +0 -11
  100. package/dist/cli/setup-wizard.js +0 -3
  101. package/dist/core/config/runtime-config.js +0 -38
  102. package/dist/core/config/user-config.js +0 -63
  103. package/dist/core/config/validation.js +0 -9
  104. package/dist/core/constants.js +0 -268
  105. package/dist/core/git.js +0 -31
  106. package/dist/core/legacy-compat.js +1 -28
  107. package/dist/core/logging.js +0 -3
  108. package/dist/core/platform.js +0 -28
  109. package/dist/core/process-control.js +0 -8
  110. package/dist/core/secrets/index.js +0 -17
  111. package/dist/core/secrets/inline-seal.js +0 -7
  112. package/dist/core/secrets/ref.js +0 -19
  113. package/dist/core/secrets/resolver.js +0 -8
  114. package/dist/core/secrets/store.js +1 -12
  115. package/dist/core/utils.js +1 -37
  116. package/dist/core/version.js +0 -3
  117. package/dist/dashboard/platform.js +1 -35
  118. package/dist/dashboard/routes/agents.js +2 -71
  119. package/dist/dashboard/routes/cli.js +0 -27
  120. package/dist/dashboard/routes/config.js +0 -54
  121. package/dist/dashboard/routes/extensions.js +0 -132
  122. package/dist/dashboard/routes/local-models.js +0 -68
  123. package/dist/dashboard/routes/models.js +0 -46
  124. package/dist/dashboard/routes/sessions.js +0 -100
  125. package/dist/dashboard/runtime.js +1 -58
  126. package/dist/dashboard/server.js +0 -49
  127. package/dist/dashboard/session-control.js +2 -69
  128. package/dist/model/catalog.js +1 -17
  129. package/dist/model/index.js +0 -15
  130. package/dist/model/injector.js +1 -181
  131. package/dist/model/provider-models.js +1 -48
  132. package/dist/model/responses-bridge.js +3 -45
  133. package/dist/model/store.js +0 -17
  134. package/dist/model/types.js +0 -12
  135. package/dist/model/validation.js +1 -18
  136. package/dist/pikichannel/adapter-pikiloom.js +0 -31
  137. package/dist/pikichannel/code.js +0 -12
  138. package/dist/pikichannel/codec.js +0 -14
  139. package/dist/pikichannel/host.js +4 -33
  140. package/dist/pikichannel/protocol.js +0 -52
  141. package/dist/pikichannel/rendezvous-broker.js +5 -26
  142. package/dist/pikichannel/rendezvous-host.js +3 -16
  143. package/dist/pikichannel/server.js +6 -55
  144. package/dist/pikichannel/transport.js +0 -25
  145. package/dist/pikichannel/transports/webrtc-host.js +0 -18
  146. package/dist/pikichannel/transports/webrtc-shared.js +4 -34
  147. package/dist/pikichannel/transports/websocket-host.js +1 -14
  148. package/dist/pikichannel/turn.js +2 -69
  149. package/dist/pikichannel/web/sdk.js +14 -71
  150. package/package.json +1 -1
  151. package/dashboard/dist/assets/ConnectionModal-Dt05H2f9.js +0 -1
  152. package/dashboard/dist/assets/SessionPanel-_0dLWvEb.js +0 -1
  153. package/dashboard/dist/assets/SystemTab-CN_QrRKt.js +0 -1
  154. package/dashboard/dist/assets/index-CP3LYJR2.js +0 -23
  155. package/dashboard/dist/assets/index-C_neLnaO.js +0 -3
  156. package/dashboard/dist/assets/index-CyCspgtc.css +0 -1
@@ -1,37 +1,7 @@
1
- /**
2
- * pikichannel-sdk.js — the reference browser client SDK (vanilla ESM, zero deps).
3
- *
4
- * This is the embeddable client: drop it into any web app (or wrap it in a
5
- * WebView for mobile) and you get a live, bidirectional agent session over
6
- * either transport. It mirrors the L2 protocol in src/pikichannel/protocol.ts —
7
- * keep the message `type` literals in lockstep with that file.
8
- *
9
- * Layering mirrors the host:
10
- * - Transport (L1): WsTransport | RtcTransport — both expose connect/send and
11
- * onopen/onmessage/onclose. The client is blind to which one it holds.
12
- * - Client (L2): PikichannelClient — speaks the protocol, keeps a reactive
13
- * `sessions` store, exposes prompt/stop/steer/interact, and emits events.
14
- *
15
- * Public surface:
16
- * const c = new Pikichannel.Client({ transport: 'websocket' | 'webrtc' })
17
- * c.on('status'|'welcome'|'session'|'sessions'|'accepted'|'error', cb)
18
- * await c.connect(); c.subscribeAll();
19
- * c.prompt({ prompt, sessionKey?, agent?, model?, effort? })
20
- * c.stop(key) / c.steer(taskId) / c.recall(taskId) / c.interact(promptId, action, value)
21
- * c.sessions // Map<sessionKey, UniversalSnapshot>
22
- * c.stats() // { transport, state, rtt, framesIn, framesOut, bytesIn, bytesOut }
23
- */
24
-
25
1
  export const PROTOCOL_VERSION = 1;
26
2
 
27
- // The browser keeps plain STUN (no secrets). Relay fallback rides the host's
28
- // TURN: the host (answerer) trickles its Cloudflare relay candidate, which the
29
- // browser reaches outbound — so no browser-side TURN credential is needed.
30
3
  const ICE_SERVERS = [{ urls: 'stun:stun.l.google.com:19302' }, { urls: 'stun:stun.cloudflare.com:3478' }];
31
4
 
32
- // Resolve the ws(s):// base for a target host. `host` may be a bare authority
33
- // ("192.168.1.5:3940"), a full ws(s)/http(s) URL, or empty (same origin). This
34
- // is what makes a client repointable: pass `host` to talk to a different node.
35
5
  function wsBase(host) {
36
6
  const loc = window.location;
37
7
  const proto = loc.protocol === 'https:' ? 'wss:' : 'ws:';
@@ -42,10 +12,6 @@ function wsBase(host) {
42
12
  return proto + '//' + host.replace(/\/$/, '');
43
13
  }
44
14
 
45
- // ---------------------------------------------------------------------------
46
- // L1 transports (browser side)
47
- // ---------------------------------------------------------------------------
48
-
49
15
  class WsTransport {
50
16
  constructor(base) {
51
17
  this.kind = 'websocket';
@@ -66,16 +32,12 @@ class WsTransport {
66
32
  isOpen() { return !!this.ws && this.ws.readyState === WebSocket.OPEN; }
67
33
  }
68
34
 
69
- // The browser is always the WebRTC offerer (creates the datachannel + offer).
70
- // Two signaling paths share the same PC setup:
71
- // - direct: SDP/ICE over `${base}/pikichannel/signal` (reachable host).
72
- // - rendezvous: dial a NodeID through a broker both peers reach (NAT traversal).
73
35
  class RtcTransport {
74
36
  constructor(cfg) {
75
37
  this.kind = 'webrtc';
76
38
  this.base = cfg.base;
77
- this.rendezvous = cfg.rendezvous || null; // broker ws(s):// URL
78
- this.nodeId = cfg.nodeId || null; // host NodeID to dial
39
+ this.rendezvous = cfg.rendezvous || null;
40
+ this.nodeId = cfg.nodeId || null;
79
41
  this.pc = null; this.dc = null; this.signal = null;
80
42
  this.onopen = null; this.onmessage = null; this.onclose = null; this.onerror = null;
81
43
  }
@@ -103,7 +65,6 @@ class RtcTransport {
103
65
  this.signal = signal;
104
66
 
105
67
  if (useRendezvous) {
106
- // NAT path: dial the NodeID through the broker; signaling is relayed.
107
68
  let sessionId = null;
108
69
  pc.onicecandidate = (e) => { if (e.candidate && sessionId && signal.readyState === WebSocket.OPEN) signal.send(JSON.stringify({ t: 'signal', sessionId, data: { kind: 'candidate', candidate: e.candidate.toJSON() } })); };
109
70
  signal.onopen = () => signal.send(JSON.stringify({ t: 'dial', nodeId: this.nodeId }));
@@ -123,7 +84,6 @@ class RtcTransport {
123
84
  };
124
85
  signal.onerror = () => this.onerror && this.onerror(new Error('rendezvous socket error'));
125
86
  } else {
126
- // Direct path: SDP/ICE straight to the reachable host.
127
87
  pc.onicecandidate = (e) => { if (e.candidate && signal.readyState === WebSocket.OPEN) signal.send(JSON.stringify({ kind: 'candidate', candidate: e.candidate.toJSON() })); };
128
88
  signal.onmessage = async (m) => {
129
89
  let msg; try { msg = JSON.parse(m.data); } catch (e) { return; }
@@ -152,7 +112,6 @@ function makeTransport(kind, cfg) {
152
112
  return new WsTransport(cfg.base);
153
113
  }
154
114
 
155
- // Mirror of applySnapshotPatch() in src/pikichannel/protocol.ts — keep in lockstep.
156
115
  function applyPatch(prev, patch) {
157
116
  if (patch.full) return patch.full;
158
117
  const next = prev ? Object.assign({}, prev) : { phase: 'idle', updatedAt: 0 };
@@ -162,28 +121,23 @@ function applyPatch(prev, patch) {
162
121
  return next;
163
122
  }
164
123
 
165
- // ---------------------------------------------------------------------------
166
- // L2 client
167
- // ---------------------------------------------------------------------------
168
-
169
124
  export class PikichannelClient {
170
125
  constructor(opts) {
171
126
  opts = opts || {};
172
- this.rendezvous = opts.rendezvous || null; // broker URL for NAT traversal
173
- this.nodeId = opts.nodeId || null; // host NodeID to dial via the broker
174
- // A rendezvous dial implies WebRTC (the broker only brokers P2P signaling).
127
+ this.rendezvous = opts.rendezvous || null;
128
+ this.nodeId = opts.nodeId || null;
175
129
  this.transportKind = (this.rendezvous && this.nodeId) ? 'webrtc' : (opts.transport === 'webrtc' ? 'webrtc' : 'websocket');
176
130
  this.token = opts.token || null;
177
- this.endpoint = opts.host || null; // target node authority/URL (null = same origin)
178
- this._base = wsBase(this.endpoint); // resolved ws(s):// base
131
+ this.endpoint = opts.host || null;
132
+ this._base = wsBase(this.endpoint);
179
133
  this.transport = null;
180
- this.state = 'idle'; // idle | connecting | open | closed
181
- this.host = null; // HostInfo from welcome
182
- this.sessions = new Map(); // sessionKey -> UniversalSnapshot (reconstructed from patches)
183
- this.sessionMetas = []; // SessionMeta[]
184
- this._seqs = new Map(); // sessionKey -> last applied seq (gap detection)
134
+ this.state = 'idle';
135
+ this.host = null;
136
+ this.sessions = new Map();
137
+ this.sessionMetas = [];
138
+ this._seqs = new Map();
185
139
  this._listeners = new Map();
186
- this._pending = new Map(); // request id -> {resolve,reject} (control-plane tunnel)
140
+ this._pending = new Map();
187
141
  this._reqSeq = 0;
188
142
  this._pingTimer = null;
189
143
  this._rtt = null;
@@ -191,7 +145,6 @@ export class PikichannelClient {
191
145
  this._pendingResolve = null;
192
146
  }
193
147
 
194
- // -- event emitter --
195
148
  on(type, cb) {
196
149
  let set = this._listeners.get(type);
197
150
  if (!set) { set = new Set(); this._listeners.set(type, set); }
@@ -203,7 +156,6 @@ export class PikichannelClient {
203
156
 
204
157
  _setState(state) { this.state = state; this._emit('status', this.stats()); }
205
158
 
206
- // -- lifecycle --
207
159
  connect() {
208
160
  return new Promise((resolve, reject) => {
209
161
  this._pendingResolve = resolve;
@@ -221,7 +173,6 @@ export class PikichannelClient {
221
173
  t.onmessage = (data) => this._onFrame(data);
222
174
  t.onclose = () => { this._stopPing(); this._failPending('connection closed'); this._setState('closed'); this._emit('close', null); };
223
175
  t.onerror = (err) => { this._emit('error', { message: err && err.message ? err.message : 'transport error' }); if (this._pendingResolve) { reject(err); this._pendingResolve = null; } };
224
- // resolve connect() on welcome
225
176
  const off = this.on('welcome', () => { off(); if (this._pendingResolve) { this._pendingResolve(this.host); this._pendingResolve = null; } });
226
177
  Promise.resolve(t.connect()).catch((e) => { this._emit('error', { message: e && e.message ? e.message : 'connect failed' }); reject(e); });
227
178
  });
@@ -229,7 +180,6 @@ export class PikichannelClient {
229
180
 
230
181
  disconnect() { this._stopPing(); if (this.transport) this.transport.close(); this._setState('closed'); }
231
182
 
232
- // -- outbound commands --
233
183
  subscribeAll() { this._send({ type: 'subscribe', sessionKey: '*' }); }
234
184
  subscribe(sessionKey) { this._send({ type: 'subscribe', sessionKey: sessionKey }); }
235
185
  unsubscribe(sessionKey) { this._send({ type: 'unsubscribe', sessionKey: sessionKey }); }
@@ -247,12 +197,6 @@ export class PikichannelClient {
247
197
  this._send({ type: 'interact', promptId: promptId, action: action, value: value, requestFreeform: requestFreeform });
248
198
  }
249
199
 
250
- /**
251
- * Control-plane HTTP over the channel — full management of the connected host
252
- * WITHOUT it exposing REST publicly (no CORS, rides the authenticated channel).
253
- * Only `/api/*` is allowed by the host. Resolves with a fetch-like response:
254
- * { status, ok, headers, text(), json(), base64(), bytes() }.
255
- */
256
200
  request(method, path, opts) {
257
201
  opts = opts || {};
258
202
  let body = opts.body;
@@ -271,7 +215,6 @@ export class PikichannelClient {
271
215
  this._pending.clear();
272
216
  }
273
217
 
274
- // -- inbound --
275
218
  _onFrame(data) {
276
219
  this._stats.framesIn++;
277
220
  this._stats.bytesIn += (data && data.length) ? data.length : 0;
@@ -289,8 +232,8 @@ export class PikichannelClient {
289
232
  const lastSeq = this._seqs.get(key);
290
233
  const contiguous = lastSeq === undefined || msg.seq === lastSeq + 1 || !!msg.patch.full;
291
234
  if (!msg.patch.full && (prev === null || !contiguous)) {
292
- this.getSnapshot(key); // missing baseline or seq gap → ask for a full resync
293
- break; // don't apply a delta we can't anchor
235
+ this.getSnapshot(key);
236
+ break;
294
237
  }
295
238
  const next = applyPatch(prev, msg.patch);
296
239
  this.sessions.set(key, next);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pikiloom",
3
- "version": "0.4.26",
3
+ "version": "0.4.28",
4
4
  "description": "Put the world's smartest AI agents in your pocket. Command local Claude & Gemini via IM. | 让最好用的 IM 变成你电脑上的顶级 Agent 控制台",
5
5
  "type": "module",
6
6
  "bin": {
@@ -1 +0,0 @@
1
- import{r as a,j as t}from"./react-vendor-C7Sl8SE7.js";import{u as O,d as B,O as R,P as J,c as Q,I as r,m as w,Q as q,V as E,W as D}from"./index-C_neLnaO.js";import{M as V,a as W}from"./Modal-lYfO9m-I.js";import"./router-DHISdpPk.js";function L({open:x,onClose:b}){const j=O(e=>e.locale),c=O(e=>e.toast),n=a.useMemo(()=>B(j),[j]),l=R(),[i,k]=a.useState(l?l.mode:"local"),[p,y]=a.useState(l?.host||""),[N,H]=a.useState(l?.token||""),[C,S]=a.useState(""),[o,u]=a.useState(null),[f,P]=a.useState(""),[d,z]=a.useState(""),[g,h]=a.useState(!1);a.useEffect(()=>{if(!x)return;const e=R();k(e?e.mode:"local"),y(e?.host||""),H(e?.token||""),S(""),fetch("/pikichannel/pair").then(s=>s.ok?s.json():null).then(s=>{s?.ok&&(u(s),P(s.rendezvous||""),z(s.publicHost||""))}).catch(()=>{})},[x]);const M=()=>{if(i==="local")q();else if(i==="direct"){if(!p.trim()){c(n("conn.needHost"),!1);return}E({host:p.trim(),token:N.trim()||void 0})}else{const e=D(C.trim());if(!e){c(n("conn.badCode"),!1);return}E(e)}window.location.reload()},m=o?J(d.trim()?{host:d.trim(),token:o.token}:o.registered&&o.rendezvous&&o.nodeId?{rendezvous:o.rendezvous,nodeId:o.nodeId,token:o.token}:{token:o.token}):"",T=async()=>{h(!0);try{const e=await fetch("/pikichannel/remote",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({publicHost:d.trim()})}).then(s=>s.json());e.ok&&u(s=>({...s||{},publicHost:e.publicHost||""}))}catch{}finally{h(!1)}},I=async e=>{if(e)try{await navigator.clipboard.writeText(e),c(n("conn.copied"))}catch{c(n("conn.copyFail"),!1)}},F=async e=>{if(e&&!f.trim()){c(n("conn.needRdv"),!1);return}h(!0);try{const s=await fetch("/pikichannel/remote",{method:"POST",headers:{"content-type":"application/json"},body:JSON.stringify({enabled:e,rendezvous:f.trim()})}).then(v=>v.json());s.ok?(u(v=>({...v||{},registered:!!s.registered,rendezvous:s.rendezvous||""})),c(n(e?"conn.remoteOn":"conn.remoteOff"))):c(s.error||n("conn.remoteFail"),!1)}catch{c(n("conn.remoteFail"),!1)}finally{h(!1)}},U=[{key:"local",label:n("conn.local"),hint:n("conn.localHint")},{key:"direct",label:n("conn.direct"),hint:n("conn.directHint")},{key:"remote",label:n("conn.remote"),hint:n("conn.remoteHint")}];return t.jsxs(V,{open:x,onClose:b,size:"md",children:[t.jsx(W,{title:n("conn.title"),description:n("conn.subtitle"),onClose:b}),t.jsx("div",{className:"text-[11px] font-semibold uppercase tracking-[0.16em] text-fg-5 mb-2",children:n("conn.targetTitle")}),t.jsx("div",{className:"grid grid-cols-3 gap-2",children:U.map(e=>t.jsxs("button",{onClick:()=>k(e.key),className:Q("rounded-lg border p-2.5 text-left transition-colors",i===e.key?"border-[var(--brand)] bg-[var(--surface-2)]":"border-[var(--edge-default)] hover:border-[var(--edge-strong)]"),children:[t.jsx("div",{className:"text-[13px] font-semibold text-fg",children:e.label}),t.jsx("div",{className:"mt-0.5 text-[11px] leading-snug text-fg-5",children:e.hint})]},e.key))}),t.jsxs("div",{className:"mt-3 space-y-2",children:[i==="direct"&&t.jsxs(t.Fragment,{children:[t.jsx(r,{tone:"inset",value:p,onChange:e=>y(e.target.value),placeholder:n("conn.hostPh")}),t.jsx(r,{tone:"inset",value:N,onChange:e=>H(e.target.value),placeholder:n("conn.tokenPh")})]}),i==="remote"&&t.jsx(r,{tone:"inset",value:C,onChange:e=>S(e.target.value),placeholder:n("conn.codePh")}),i==="local"&&t.jsx("div",{className:"text-[12px] text-fg-4",children:n("conn.localBody")})]}),t.jsx("div",{className:"mt-3 flex justify-end",children:t.jsx(w,{variant:"primary",size:"sm",onClick:M,children:n("conn.connect")})}),t.jsxs("div",{className:"mt-6 border-t border-edge pt-4",children:[t.jsx("div",{className:"text-[11px] font-semibold uppercase tracking-[0.16em] text-fg-5 mb-1",children:n("conn.shareTitle")}),t.jsx("div",{className:"text-[12px] text-fg-4 mb-3",children:n("conn.shareHint")}),o?t.jsxs("div",{className:"space-y-3",children:[t.jsxs("div",{className:"space-y-1",children:[t.jsx(r,{tone:"inset",value:d,onChange:e=>z(e.target.value),onBlur:T,placeholder:n("conn.publicHostPh"),disabled:g}),t.jsx("div",{className:"text-[11px] text-fg-5",children:n("conn.publicHostHint")})]}),t.jsxs("label",{className:"flex items-center gap-2 text-[13px] text-fg-2",children:[t.jsx("input",{type:"checkbox",checked:!!o.registered,disabled:g,onChange:e=>F(e.target.checked)}),n("conn.enableRemote")]}),t.jsx(r,{tone:"inset",value:f,onChange:e=>P(e.target.value),placeholder:n("conn.rdvPh"),disabled:g}),t.jsxs("div",{className:"flex items-center gap-2",children:[t.jsx(r,{tone:"inset",readOnly:!0,value:m,className:"font-mono text-[11px]"}),t.jsx(w,{variant:"outline",size:"sm",onClick:()=>I(m),children:n("conn.copyCode")})]}),m&&t.jsxs("div",{className:"flex items-center gap-3 pt-0.5",children:[t.jsx("img",{src:`/pikichannel/qr?data=${encodeURIComponent(m)}`,alt:"QR",width:116,height:116,className:"shrink-0 rounded-md bg-white p-2"}),t.jsx("div",{className:"text-[11px] leading-relaxed text-fg-5",children:n("conn.scan")})]}),t.jsx("div",{className:"text-[11px] text-fg-5",children:n("conn.shareFoot")})]}):t.jsx("div",{className:"text-[12px] text-fg-5",children:n("conn.shareUnavailable")})]})]})}export{L as ConnectionModal};
@@ -1 +0,0 @@
1
- import{r as t,j as n}from"./react-vendor-C7Sl8SE7.js";import{c as St,I as bt,S as Se,m as be,a as j,u as Ge,d as vt,g as yt,l as It,e as Tt,j as jt,f as Rt,s as wt,X as Nt}from"./index-C_neLnaO.js";import{l as Ot,n as Je,m as Et,a as Ct,b as Mt,p as Lt,s as ke,T as Pt,R as At,U as Ze,c as qt,d as et,e as Ft,L as Ht,I as Ut}from"./index-CP3LYJR2.js";import{M as rt,a as nt}from"./Modal-lYfO9m-I.js";import"./router-DHISdpPk.js";import"./Select-BhbU-rll.js";import"./DirBrowser-D-GT-G-w.js";import"./markdown-DxQYQFeH.js";import"./ExtensionsTab-BrJMulJR.js";function Dt({snapshot:d}){const[r,m]=t.useState(d.currentIndex??0),[M,R]=t.useState(""),[x,p]=t.useState(!1),[Y,k]=t.useState(null);t.useEffect(()=>{m(d.currentIndex??0),R(""),k(null)},[d.promptId,d.currentIndex]);const N=d.questions||[],v=N[r]||null,V=N.length,O=!!(v?.options&&v.options.length),f=O?!!v?.allowFreeform:!0,F=o=>{o&&(m(h=>h+1),R(""))},le=async o=>{if(!x){p(!0),k(null);try{const h=await j.interactionSelectOption(d.promptId,o);if(!h.ok){k(h.error||"Failed to submit selection.");return}F(h.advanced)}catch(h){k(h?.message||"Network error.")}finally{p(!1)}}},E=async()=>{if(x)return;const o=M.trim();if(!o&&!v?.allowEmpty){k("Please enter a response.");return}p(!0),k(null);try{const h=await j.interactionSubmitText(d.promptId,o);if(!h.ok){k(h.error||"Failed to submit answer.");return}F(h.advanced)}catch(h){k(h?.message||"Network error.")}finally{p(!1)}},g=async()=>{if(!x){p(!0),k(null);try{const o=await j.interactionSkip(d.promptId);if(!o.ok){k(o.error||"Failed to skip.");return}F(o.advanced)}catch(o){k(o?.message||"Network error.")}finally{p(!1)}}},H=async()=>{if(!x){p(!0);try{await j.interactionCancel(d.promptId)}catch{}}},G=t.useMemo(()=>{const o=[];return d.hint&&o.push(d.hint),V>1&&o.push(`Question ${r+1} of ${V}`),o.join(" · ")||void 0},[d.hint,r,V]);return n.jsxs(rt,{open:!0,onClose:H,wide:O&&(v?.options?.length||0)>3,children:[n.jsx(nt,{title:d.title||"Pikiloom needs your input",description:G,onClose:H}),v?n.jsxs("div",{className:"space-y-4",children:[n.jsxs("div",{children:[n.jsx("div",{className:"text-xs font-medium uppercase tracking-wide text-fg-5",children:v.header||"Question"}),n.jsx("div",{className:"mt-1 whitespace-pre-wrap text-sm leading-relaxed text-fg",children:v.prompt})]}),O&&n.jsx("div",{className:"grid grid-cols-1 gap-2 sm:grid-cols-2",children:(v.options||[]).map(o=>n.jsxs("button",{type:"button",disabled:x,onClick:()=>le(o.value||o.label),className:St("group rounded-lg border border-edge bg-panel-alt px-3 py-2 text-left text-sm transition","hover:border-control-border-h hover:bg-control-h hover:shadow-sm","focus:outline-none focus:ring-2 focus:ring-[var(--th-glow-a)]","disabled:cursor-not-allowed disabled:opacity-50"),children:[n.jsx("div",{className:"font-medium text-fg group-hover:text-fg",children:o.label}),o.description&&n.jsx("div",{className:"mt-0.5 text-xs leading-snug text-fg-4",children:o.description})]},o.value||o.label))}),f&&n.jsx("div",{children:n.jsx(bt,{value:M,onChange:o=>R(o.target.value),onKeyDown:o=>{o.key==="Enter"&&!o.shiftKey&&!x&&(o.preventDefault(),E())},placeholder:O?"Or type a custom answer…":"Type your answer…",disabled:x,autoFocus:!O})}),Y&&n.jsx("div",{className:"rounded-md border border-red-300/40 bg-red-500/10 px-3 py-2 text-xs text-red-600",children:Y}),n.jsxs("div",{className:"flex items-center justify-between gap-3",children:[n.jsx("div",{className:"text-xs text-fg-5",children:x?n.jsxs("span",{className:"inline-flex items-center gap-2",children:[n.jsx(Se,{})," Submitting…"]}):n.jsxs("span",{children:["Press ",n.jsx("kbd",{className:"rounded border border-edge bg-panel-alt px-1.5 py-0.5 text-[10px] uppercase",children:"Enter"})," to send"]})}),n.jsxs("div",{className:"flex items-center gap-2",children:[n.jsx(be,{variant:"ghost",size:"sm",onClick:g,disabled:x,children:"Skip"}),f&&n.jsx(be,{variant:"primary",size:"sm",onClick:E,disabled:x||!M.trim()&&!v.allowEmpty,children:"Submit"})]})]})]}):n.jsxs("div",{className:"py-6 text-center text-sm text-fg-5",children:[n.jsx(Se,{className:"mr-2 inline-block"})," Waiting for the agent…"]})]})}function Qt(d){const r=d.streaming||d.liveStreamPhase==="streaming",m=d.queuedTaskCount>0||d.pendingQueuedCount>0||d.streamPhase==="queued";return r||m}const Fe=12,tt=160,_t=96,$t=[],Bt=[],Kt=[],zt=20,X=new Map;function Wt(d,r){return`${d}:${r}`}function Xt(d,r){for(X.delete(d),X.set(d,r);X.size>zt;)X.delete(X.keys().next().value)}const sr=t.memo(function({session:r,workdir:m,active:M=!0,onSessionChange:R,initialPendingPrompt:x,initialPendingImageUrls:p,onPendingPromptConsumed:Y}){const k=Ge(e=>e.locale),N=Ge(e=>e.agentStatus?.agents?.find(s=>s.agent===r.agent)??null),v=N?.selectedEffort??null,V=N?.selectedModel??null,O=N?.byokProviderName??null,f=t.useMemo(()=>vt(k),[k]),F=yt(r.agent||""),le=It(r),E=!!x||!!(p&&p.length),[g,H]=t.useState(null),[G,o]=t.useState(!E),[h,He]=t.useState(!1),[i,L]=t.useState(null),[J,Z]=t.useState(!1),[U,ve]=t.useState(null),[st,Ue]=t.useState(0),[lt,ye]=t.useState(null),[D,ae]=t.useState([]),[at,oe]=t.useState([]),[ee,Ie]=t.useState([]),[S,ue]=t.useState(x||null),[C,ce]=t.useState(p||[]),[ot,ie]=t.useState(null),Te=t.useRef(null);Te.current=ot;const[De,Q]=t.useState([]),je=t.useRef([]);je.current=De;const te=t.useRef(null),[ut,Qe]=t.useState(null),[de,re]=t.useState(null),[ne,Re]=t.useState(""),[P,we]=t.useState(!1),ct=!!N?.capabilities?.fork,Ne=t.useRef(null),_=t.useRef(p||[]),w=t.useRef(i),_e=t.useRef(J);w.current=i,_e.current=J;const $e=t.useRef(D);$e.current=D;const Be=t.useRef(U);Be.current=U;const A=t.useRef(null),fe=t.useRef(null),$=t.useRef(!0),B=t.useRef(!1),me=t.useRef(null),Oe=t.useRef(!1),K=t.useRef(E),se=t.useRef(!1),q=t.useRef(!1),Ee=t.useRef(!1),Ce=t.useRef(!1),Ke=t.useRef({model:null,effort:null}),it=t.useCallback(e=>{Ke.current=e},[]);t.useEffect(()=>{Ee.current||!E||(Ee.current=!0,x&&!S&&ue(x),p&&p.length&&!C.length&&(ce(p),_.current=p),o(!1),Ue(e=>e+1),Y?.())},[E,Y]);const I=t.useCallback(()=>{ue(null),ce(e=>{for(const s of e)URL.revokeObjectURL(s);return[]}),_.current=[],ie(null)},[]),z=t.useCallback(()=>{Q(e=>{if(!e.length)return e;for(const s of e)for(const l of s.imageUrls)URL.revokeObjectURL(l);return[]}),te.current=null},[]),ze=t.useCallback((e,s)=>{const l=Qt({streaming:_e.current,liveStreamPhase:w.current?.phase??null,streamPhase:Be.current,queuedTaskCount:$e.current.length,pendingQueuedCount:je.current.length}),a=s||[];if(l){const u=`local-${Date.now().toString(36)}-${Math.random().toString(36).slice(2,8)}`;te.current=u,Q(c=>[...c,{localId:u,taskId:null,prompt:e||"",imageUrls:a}]);return}w.current?.phase==="done"&&L(null);for(const u of _.current)URL.revokeObjectURL(u);te.current=null,ue(e||null),ce(a),_.current=a,ie(null)},[]),dt=t.useCallback(e=>{const s=te.current;if(s){te.current=null,Q(l=>{const a=l.findIndex(c=>c.localId===s);if(a<0)return l;const u=l.slice();return u[a]={...u[a],taskId:e},u});return}ie(e)},[]),ft=t.useCallback(async()=>{if(!de)return;const e=ne.trim();if(e){we(!0);try{const s=await j.forkSession(m,r.agent||"",r.sessionId,de.atTurn,e,{});if(!s.ok||!s.sessionKey){we(!1);return}const[l,a]=s.sessionKey.split(":");re(null),Re(""),R?.({agent:l,sessionId:a,workdir:m})}finally{we(!1)}}},[de,ne,m,r.agent,r.sessionId,R]);Ne.current=ft;const ge=t.useCallback(async(e,s={})=>{try{const l=await Ot({workdir:m,agent:r.agent||"",sessionId:r.sessionId,rich:!0,turnOffset:e.turnOffset,turnLimit:e.turnLimit,lastNTurns:e.lastNTurns},{force:s.force});return l.ok?Je(l):null}catch{return null}},[m,r.agent,r.sessionId]),T=t.useCallback(async({keepOlder:e,force:s=!1,scrollToBottom:l=!1})=>{const a=r.sessionId;if(me.current===a)return!1;me.current=a;try{const u=await ge({turnOffset:0,turnLimit:Fe},{force:s});if(!u||r.sessionId!==a)return!1;if(l&&(B.current=!0),H(c=>!c||!e?u:Et(c,u)),o(!1),se.current&&(se.current=!1,I()),q.current){const c=q.current;q.current=!1;const b=c!==!0?c.taskId:null;w.current&&(c===!0||w.current.taskId===b)&&L(null)}return!0}finally{me.current===a&&(me.current=null)}},[ge,I,r.sessionId]),he=t.useCallback(async()=>{if(!g?.hasOlder||Oe.current)return;const e=A.current;e&&(fe.current={scrollHeight:e.scrollHeight,scrollTop:e.scrollTop}),Oe.current=!0,He(!0);try{const s=await ge({turnOffset:Math.max(0,g.totalTurns-g.startTurn),turnLimit:Fe});s?H(l=>l?Ct(l,s):s):fe.current=null}finally{Oe.current=!1,He(!1)}},[ge,g]),pe=t.useRef(null),W=t.useCallback(e=>{if(e?.sessionId&&e.sessionId!==r.sessionId&&(Ce.current=!0,Me.current=`${r.agent}:${e.sessionId}`,R?.({agent:r.agent||"",sessionId:e.sessionId,workdir:m})),!e){const l=pe.current;Z(!1),l==="streaming"?(se.current=!0,q.current=!0,T({keepOlder:!0,force:!0,scrollToBottom:$.current})):L(null),K.current&&l!=="streaming"?T({keepOlder:!0,force:!0}):(l==="done"&&(I(),z()),l!==null&&(K.current=!1)),ye(null),ve(null),ae([]),oe([]),Ie([]),pe.current=null;return}if(ve(e.phase),ye(e.taskId||null),ae(e.queuedTaskIds&&e.queuedTaskIds.length?e.queuedTaskIds:$t),oe(e.queuedTasks&&e.queuedTasks.length?e.queuedTasks:Bt),Ie(Array.isArray(e.interactions)&&e.interactions.length?e.interactions:Kt),e.phase==="streaming"){if(q.current&&w.current&&w.current.taskId!==null&&w.current.taskId!==(e.taskId||null)&&!(e.text||"").trim()||L({taskId:e.taskId||null,phase:"streaming",text:e.text||"",thinking:e.thinking||"",activity:e.activity,plan:e.plan??null,model:e.model??null,effort:e.effort??null,previewMeta:e.previewMeta??null,subAgents:e.previewMeta?.subAgents??null,generatingImages:e.previewMeta?.generatingImages??0,artifacts:e.artifacts??null,startedAt:typeof e.startedAt=="number"?e.startedAt:null,error:null,question:e.question??null}),Z(!0),e.taskId&&e.taskId!==Te.current){const a=je.current,u=a.findIndex(c=>c.taskId===e.taskId);if(u>=0){const c=a[u];for(const b of _.current)URL.revokeObjectURL(b);ue(c.prompt||null),ce(c.imageUrls),_.current=c.imageUrls,ie(e.taskId),Q(b=>b.filter((xt,kt)=>kt!==u))}}$.current&&(B.current=!0)}else if(e.phase==="queued")L(null),Z(!1);else if(e.phase==="done"){Z(!1),L(b=>b?{...b,phase:"done",error:e.error??null}:e.error?{taskId:e.taskId||null,phase:"done",text:"",thinking:"",activity:"",plan:null,model:e.model??null,effort:e.effort??null,previewMeta:e.previewMeta??null,subAgents:e.previewMeta?.subAgents??null,generatingImages:e.previewMeta?.generatingImages??0,artifacts:e.artifacts??null,error:e.error}:b);const l=!!e.queuedTaskIds?.length,a=w.current,u=!!a&&Mt(a),c=!!e.incomplete&&u&&!l;pe.current!=="done"&&(l||(se.current=!0),q.current=c?!1:{taskId:e.taskId||null},T({keepOlder:!0,force:!0,scrollToBottom:$.current})),l||(K.current=!1)}const s=new Set;if(e.taskId&&s.add(e.taskId),Array.isArray(e.queuedTaskIds))for(const l of e.queuedTaskIds)s.add(l);Q(l=>{let a=!1;const u=[];for(const c of l)if(!c.taskId||s.has(c.taskId))u.push(c);else{for(const b of c.imageUrls)URL.revokeObjectURL(b);a=!0}return a?u:l}),pe.current=e.phase},[I,z,T,r.sessionId,r.agent,R,m]),We=t.useRef(W);We.current=W;const Xe=t.useCallback(()=>{K.current=!0,Ue(e=>e+1)},[]),mt=t.useCallback(async e=>{try{await j.recallSessionMessage(e),Te.current===e&&I(),Q(s=>{let l=!1;const a=[];for(const u of s)if(u.taskId===e){for(const c of u.imageUrls)URL.revokeObjectURL(c);l=!0}else a.push(u);return l?a:s}),ae(s=>s.filter(l=>l!==e)),oe(s=>s.filter(l=>l.taskId!==e)),ye(s=>s===e?null:s)}catch{}},[I]),gt=t.useCallback(async e=>{try{await j.steerSession(e)}catch{}},[]),ht=t.useCallback(async()=>{try{await j.stopSession(r.agent||"",r.sessionId)}catch{}},[r.agent,r.sessionId]),xe=Wt(r.agent||"",r.sessionId);t.useEffect(()=>{if(Ce.current){Ce.current=!1;let u=!1;return T({keepOlder:!0,force:!0}).finally(()=>{u||o(!1)}),()=>{u=!0}}let e=!1;const s=Lt({workdir:m,agent:r.agent||"",sessionId:r.sessionId,rich:!0,turnOffset:0,turnLimit:Fe},{allowStale:!0}),l=E&&!Ee.current,a=s?.ok?Je(s):X.get(xe)||null;return o(l?!1:!a),H(a),L(null),Z(!1),ve(null),ae([]),oe([]),Ie([]),l||(I(),z(),K.current=!1,se.current=!1,q.current=!1),$.current=!0,B.current=!0,l||T({keepOlder:!1,force:!0}).finally(()=>{e||o(!1)}),()=>{e=!0}},[T,r.agent,r.sessionId,m,xe,I,z]),t.useEffect(()=>{g&&g.turns.length>0&&Xt(xe,g)},[xe,g]),t.useEffect(()=>{M&&T({keepOlder:!0,force:!0})},[M,T]);const Me=t.useRef(`${r.agent}:${r.sessionId}`);Me.current=`${r.agent}:${r.sessionId}`,Tt("stream-update",t.useCallback(e=>{e.key===Me.current&&W(e.snapshot??null)},[W])),t.useEffect(()=>{let e=!0;return j.getSessionStreamState(r.agent||"",r.sessionId).then(s=>{e&&We.current(s.state)}).catch(()=>{}),()=>{e=!1}},[r.agent,r.sessionId,st]),jt(t.useCallback(()=>{j.getSessionStreamState(r.agent||"",r.sessionId).then(e=>{W(e.state)}).catch(()=>{}),T({keepOlder:!0,force:!0})},[W,r.agent,r.sessionId,T])),t.useEffect(()=>{!K.current&&le!=="running"&&!J&&!i&&!U&&D.length===0&&(I(),z())},[le,J,i,U,D.length,I,z]),t.useLayoutEffect(()=>{const e=fe.current,s=A.current;!e||!s||(fe.current=null,s.scrollTop=e.scrollTop+(s.scrollHeight-e.scrollHeight))},[g?.turns.length]),t.useLayoutEffect(()=>{if(!B.current)return;const e=A.current;e&&(B.current=!1,e.scrollTop=e.scrollHeight,requestAnimationFrame(()=>{$.current&&(e.scrollTop=e.scrollHeight)}))},[g,i]),t.useLayoutEffect(()=>{if(!S)return;const e=A.current;e&&(e.scrollTop=e.scrollHeight)},[S]),t.useEffect(()=>{if(!g?.hasOlder||G||h)return;const e=A.current;e&&e.scrollHeight<=e.clientHeight+tt&&he()},[g?.hasOlder,g?.turns.length,he,G,h]);const pt=t.useCallback(()=>{const e=A.current;if(!e)return;const s=e.scrollHeight-e.scrollTop-e.clientHeight;$.current=s<=_t,e.scrollTop<=tt&&he()},[he]),Le=i?.model||r.model||V||null,Pe=Rt(r.agent||"",i?.effort||r.thinkingEffort||v||null,r.workflowEnabled??N?.workflowEnabled)||null,Ye=Le?wt(Le):null,Ae=Nt(r,{streaming:J,hasLiveStream:!!i,streamPhase:U,queuedTaskCount:D.length}),y=g?.turns||[],qe=t.useMemo(()=>{if(!C.length||!y.length)return!1;const e=y[y.length-1];return!e.user||!ke(e.user.text,S)?!1:e.user.blocks.filter(l=>l.type==="image").length<C.length},[y,S,C.length]),Ve=t.useMemo(()=>{let e=y;if(qe){const b=e[e.length-1];e=[...e.slice(0,-1),{...b,user:null}]}if(!i||!e.length)return e;const s=e[e.length-1];if(!s.assistant)return e;const l=S??(i.question||null),a=(i.text||"").trim(),u=s.assistant.text?.trim()||"";return(l!=null?ke(s.user?.text,l):!!u&&!!a&&(a.startsWith(u)||u.startsWith(a)))?[...e.slice(0,-1),{...s,assistant:null}]:e},[y,i,S,qe]);return n.jsxs("div",{className:"flex flex-col h-full overflow-hidden",children:[n.jsx("div",{ref:A,onScroll:pt,className:"flex-1 overflow-y-auto overscroll-contain",children:G&&!S&&!C.length&&!i?n.jsx("div",{className:"flex items-center justify-center py-20",children:n.jsx(Se,{className:"h-5 w-5 text-fg-4"})}):Ve.length===0&&!S&&!C.length&&!i&&!Ae?n.jsx("div",{className:"py-20 text-center text-[13px] text-fg-5",children:f("hub.noMessages")}):n.jsxs("div",{className:"max-w-[900px] mx-auto px-6 py-6 space-y-0",children:[(g?.hasOlder||h)&&n.jsxs("div",{className:"mb-4 flex items-center justify-center gap-2 text-[11px] text-fg-5",children:[h?n.jsx(Se,{className:"h-3 w-3 text-fg-5"}):n.jsx("span",{className:"h-1.5 w-1.5 rounded-full bg-fg-5/35"}),n.jsx("span",{children:f(h?"hub.loadingOlderTurns":"hub.loadOlderTurnsHint")})]}),r.migratedFrom?.kind==="fork"&&r.migratedFrom.sessionId&&n.jsxs("button",{type:"button",onClick:()=>R?.({agent:r.migratedFrom.agent||r.agent||"",sessionId:r.migratedFrom.sessionId,workdir:m}),className:"mb-4 inline-flex items-center gap-1.5 rounded-md border border-edge bg-panel-alt px-2.5 py-1 text-[11px] text-fg-5 transition hover:border-edge-h hover:text-fg-2",title:`#${r.migratedFrom.sessionId.slice(0,8)}`,children:[n.jsxs("svg",{width:"10",height:"10",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"2",children:[n.jsx("circle",{cx:"6",cy:"6",r:"2"}),n.jsx("circle",{cx:"18",cy:"6",r:"2"}),n.jsx("circle",{cx:"12",cy:"20",r:"2"}),n.jsx("path",{d:"M6 8v3a3 3 0 0 0 3 3h6a3 3 0 0 0 3-3V8"}),n.jsx("path",{d:"M12 14v4"})]}),n.jsx("span",{children:f("hub.forkBadge")}),n.jsxs("span",{className:"font-mono",children:["#",r.migratedFrom.sessionId.slice(0,8)]}),typeof r.migratedFrom.forkedAtTurn=="number"&&n.jsxs("span",{className:"text-fg-5/70",children:["· ",f("hub.forkBadgeAt").replace("{turn}",String(r.migratedFrom.forkedAtTurn+1))]})]}),Ve.map((e,s)=>{const l=(g?.startTurn||0)+s;return n.jsx(Pt,{turn:e,turnIndex:l,agent:r.agent||"",meta:F,model:Ye,effort:Pe,providerName:O,t:f,workdir:m,onResend:a=>{B.current=!0,ze(a);const u=Ke.current;j.sendSessionMessage(m,r.agent||"",r.sessionId,a,{model:u.model||Le||void 0,effort:u.effort||Pe||void 0}).then(c=>{c.ok&&Xe()}).catch(()=>{I()})},onEdit:a=>Qe(a),onFork:ct?a=>{Re(""),re({atTurn:a})}:void 0},`${g?.startTurn||0}:${s}`)}),Ae&&n.jsx("div",{className:"mb-5 animate-in",children:n.jsx(At,{detail:Ae,t:f})}),(S||C.length>0)&&(qe||!(S&&y.length>0&&ke(y[y.length-1]?.user?.text,S)))&&n.jsxs("div",{className:"session-turn",children:[n.jsx(Ze,{text:S||"",blocks:C.map(e=>({type:"image",content:e})),t:f}),!i&&n.jsx("div",{className:"mt-3 mb-5 animate-in",children:n.jsx(qt,{className:"text-fg-5"})})]}),i&&et(i)&&!S&&i.question&&!(y.length>0&&ke(y[y.length-1]?.user?.text,i.question))&&n.jsx("div",{className:"session-turn",children:n.jsx(Ze,{text:i.question,t:f})}),i&&et(i)&&n.jsxs("div",{className:"mb-6",children:[n.jsx(Ft,{agent:r.agent||"",meta:F,model:Ye,effort:Pe,providerName:O,previewMeta:i.previewMeta,liveStartedAt:i.phase==="streaming"?i.startedAt??null:null}),n.jsx(Ht,{stream:i,t:f,workdir:m})]}),n.jsx("div",{className:"h-4"})]})}),n.jsx(Ut,{session:r,workdir:m,onStreamQueued:Xe,onSendStart:ze,onSendTaskAssigned:dt,onSessionChange:R,t:f,streamPhase:U,streamTaskId:lt,queuedTaskIds:D,queuedTasks:at,pendingQueuedSends:De,onRecall:mt,onSteer:gt,onStopAll:ht,editDraft:ut,onEditDraftConsumed:()=>Qe(null),onSelectionChange:it}),de&&n.jsxs(rt,{open:!0,onClose:()=>{P||re(null)},children:[n.jsx(nt,{title:f("hub.forkPromptTitle"),description:f("hub.forkPromptHint"),onClose:()=>{P||re(null)}}),n.jsx("textarea",{autoFocus:!0,value:ne,disabled:P,onChange:e=>Re(e.target.value),onKeyDown:e=>{e.key==="Enter"&&(e.metaKey||e.ctrlKey)&&ne.trim()&&!P&&(e.preventDefault(),Ne.current?.())},placeholder:f("hub.forkPromptPlaceholder"),className:"w-full min-h-[120px] resize-y rounded-md border border-edge bg-panel-alt px-3 py-2 text-[13px] leading-relaxed text-fg outline-none focus:border-edge-h"}),n.jsxs("div",{className:"mt-4 flex items-center justify-end gap-2",children:[n.jsx(be,{variant:"ghost",disabled:P,onClick:()=>re(null),children:f("modal.cancel")}),n.jsx(be,{variant:"primary",disabled:P||!ne.trim(),onClick:()=>{Ne.current?.()},children:f(P?"hub.forkSubmitting":"hub.forkSubmit")})]})]}),M&&ee.length>0&&n.jsx(Dt,{snapshot:ee[ee.length-1]},ee[ee.length-1].promptId)]})});export{sr as SessionPanel};
@@ -1 +0,0 @@
1
- import{j as e,r as f}from"./react-vendor-C7Sl8SE7.js";import{K as N,c as C,M as F,u as x,d as G,a as $,m as w,R as z,z as g,F as L}from"./index-C_neLnaO.js";import{S as v}from"./shared-C5uXvhZJ.js";import"./router-DHISdpPk.js";function k(s){return Number.isFinite(s??NaN)?Math.max(0,Math.min(100,Number(s))):null}function S(s){return Number.isFinite(s??NaN)?Number(s).toFixed(2):null}function O(s){return s?[s.hostName||"—",s.platform,s.arch].filter(Boolean).join(" · "):""}function E(s,r){if(!s)return[];const o=s.totalMem||0,i=s.memoryUsed||o-(s.freeMem||0),t=k(s.memoryPercent||(o>0?i/o*100:0)),a=k(s.cpuUsage?.usedPercent),d=s.loadAverage||null,c=S(d?.one),p=S(d?.five),u=S(d?.fifteen),h=k(d?d.one/Math.max(s.cpuCount||1,1)*100:null),y=[{key:"cpu",label:r("sessions.cpu"),value:a!=null?`${a.toFixed(0)}%`:`${s.cpuCount} cores`,detail:[`${s.cpuCount} cores`,s.cpuModel||""].filter(Boolean),tone:a!=null&&a>=85?"warn":"ok",progressPercent:a},...c&&p&&u?[{key:"cpu-load",label:r("system.cpuLoad"),value:`1m ${c}`,detail:[`5m ${p}`,`15m ${u}`],tone:h!=null&&h>=85?"warn":"muted",progressPercent:h}]:[],{key:"memory",label:r("sessions.memory"),value:`${F(i)} / ${F(o)}`,detail:t!=null?`${t.toFixed(0)}%`:void 0,tone:t!=null&&t>=85?"warn":"ok",progressPercent:t}];if(s.disk){const m=k(parseFloat(String(s.disk.percent).replace("%","")));y.push({key:"disk",label:r("sessions.disk"),value:`${s.disk.used} / ${s.disk.total}`,detail:s.disk.percent,tone:m!=null&&m>=85?"warn":"muted",progressPercent:m})}else if(s.battery){const m=k(parseFloat(String(s.battery.percent).replace("%","")));y.push({key:"battery",label:r("sessions.battery"),value:s.battery.percent,detail:s.battery.state,tone:m!=null&&m<=20?"warn":"muted",progressPercent:m})}return y}function K(s){return s?Array.isArray(s)?s.join(" · "):s:""}function W({items:s,loading:r,className:o}){return r?e.jsx("div",{className:C("space-y-1",o),children:Array.from({length:4},(i,t)=>e.jsxs("div",{className:"grid grid-cols-[80px_auto_1fr] items-baseline gap-x-4 py-1",children:[e.jsx(N,{className:"h-3 w-12"}),e.jsx(N,{className:"h-3 w-24"}),e.jsx(N,{className:"h-3 w-28"})]},t))}):e.jsx("div",{className:C("flex flex-wrap items-baseline gap-x-5 gap-y-1.5",o),children:s.map(i=>{const t=K(i.detail);return e.jsxs("div",{className:"inline-flex items-baseline gap-1.5 whitespace-nowrap",title:t||void 0,children:[e.jsx("span",{className:"text-[10px] font-medium uppercase tracking-[0.12em] text-fg-5",children:i.label}),e.jsx("span",{className:"font-mono text-[12px] tabular-nums text-fg-2",children:i.value}),t&&e.jsxs("span",{className:"text-[11px] text-fg-5",children:["· ",t]})]},i.key)})})}const q=[{key:"screenRecording",labelKey:"perm.screenRecording",reasonZh:"用于截图与界面分析",reasonEn:"For screenshots and UI inspection",guidePathKey:"perm.pathScreenRecording",icon:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"4",y:"5.5",width:"11.5",height:"10",rx:"2.4"}),e.jsx("path",{d:"m17.5 8.4 2.7-1.5v7.2l-2.7-1.5"}),e.jsx("circle",{cx:"9.75",cy:"10.5",r:"1.1",fill:"currentColor",stroke:"none"})]})},{key:"fullDiskAccess",labelKey:"perm.fullDiskAccess",reasonZh:"访问桌面、下载等受保护目录",reasonEn:"Access to Desktop, Downloads and other protected folders",guidePathKey:"perm.pathFullDiskAccess",icon:e.jsxs("svg",{width:"18",height:"18",viewBox:"0 0 24 24",fill:"none",stroke:"currentColor",strokeWidth:"1.8",strokeLinecap:"round",strokeLinejoin:"round",children:[e.jsx("rect",{x:"6.2",y:"10.1",width:"11.6",height:"8.6",rx:"2.6"}),e.jsx("path",{d:"M9 10V7.8a3 3 0 1 1 6 0V10"}),e.jsx("circle",{cx:"12",cy:"13.5",r:"0.9",fill:"currentColor",stroke:"none"}),e.jsx("path",{d:"M12 14.6v1.8"})]})}];function B(s){return s==="zh-CN"?{introWithHost:"请在 macOS 中为 {hostApp} 开启以下权限。",intro:"请在 macOS 中开启以下权限。",status:"状态",summary:"系统位置",loading:"检查中",needsGrant:"需要授权",granted:"已授权",authorize:"授权",openSettings:"前往设置",refreshState:"刷新状态",checking:"检查中...",hostGranted:"{hostApp} 已可直接使用此权限。",hostGrantedFallback:"当前宿主应用已可直接使用此权限。",needsGrantDetail:"尚未授权,可通过右侧按钮发起系统授权。",needsSettingsDetail:"需要在系统设置中手动开启此权限。"}:{introWithHost:"Grant the following permissions to {hostApp} in macOS.",intro:"Grant the following permissions in macOS.",status:"Status",summary:"System path",loading:"Checking",needsGrant:"Needs access",granted:"Granted",authorize:"Authorize",openSettings:"Open settings",refreshState:"Refresh status",checking:"Checking...",hostGranted:"{hostApp} can use this permission now.",hostGrantedFallback:"The current host app can use this permission now.",needsGrantDetail:"Access has not been granted yet. Use the button on the right to trigger the macOS prompt.",needsSettingsDetail:"This permission needs to be enabled manually in System Settings."}}function I(){const s=x(n=>n.state),r=x(n=>n.locale),o=x(n=>n.reload),i=x(n=>n.toast),t=f.useMemo(()=>G(r),[r]),a=B(r),d=s?.permissions||{},c=s?.hostApp||null,p=!s,[u,h]=f.useState(null),y=f.useMemo(()=>q.map(n=>({...n,permission:d[n.key]})),[d]),m=f.useCallback(async n=>{if(!u){h(n);try{const l=await $.requestPermission(n);if(!l.ok){i(l.error||t("perm.requestFailed"),!1);return}l.action==="already_granted"?i(t("perm.alreadyGranted")):l.action==="prompted"?i(t("perm.promptOpened")):i(t("perm.settingsOpened")),await o()}catch(l){i(l instanceof Error?l.message:t("perm.requestFailed"),!1)}finally{h(l=>l===n?null:l)}}},[o,u,t,i]),M=f.useCallback(async()=>{await o()},[o]);return e.jsxs("div",{className:"animate-in space-y-3",children:[e.jsxs("div",{className:"flex flex-col gap-2 sm:flex-row sm:items-center sm:justify-between",children:[e.jsx("div",{className:"min-w-0 flex-1",children:e.jsx("div",{className:"text-[13px] leading-relaxed text-fg-4",children:c?a.introWithHost.replace("{hostApp}",c):a.intro})}),e.jsx(w,{variant:"outline",size:"sm",onClick:()=>{M()},children:a.refreshState})]}),e.jsx(z,{children:y.map(n=>{const l=n.permission,j=!!l?.granted,P=!!l&&l.checkable,A=p?a.loading:j?a.granted:a.needsGrant,D=p?"idle":j?"ok":"warn",b=p?a.loading:j?c?a.hostGranted.replace("{hostApp}",c):a.hostGrantedFallback:P?a.needsGrantDetail:a.needsSettingsDetail,R=p?a.checking:P?a.authorize:a.openSettings;return e.jsxs(g,{children:[e.jsx(g.Lead,{icon:n.icon,title:t(n.labelKey),subtitle:r==="zh-CN"?n.reasonZh:n.reasonEn}),e.jsx(g.Status,{children:e.jsx(L,{state:D,label:A})}),e.jsx(g.Field,{children:t(n.guidePathKey)}),e.jsx(g.Action,{children:!j&&e.jsx(w,{variant:"primary",size:"sm",disabled:p||!!u,onClick:()=>{m(n.key)},children:u===n.key?a.checking:R})}),b&&b!==A&&e.jsx(g.Description,{children:b})]},n.key)})})]})}function _({onOpenWorkdir:s}){const r=x(c=>c.state),o=x(c=>c.host),i=x(c=>c.locale),t=f.useMemo(()=>G(i),[i]),a=r?.bot?.workdir||r?.runtimeWorkdir||r?.config.workdir||"",d=O(o);return e.jsxs("div",{className:"animate-in space-y-3",children:[e.jsx(v,{className:"!p-3.5",children:e.jsxs("div",{className:"flex items-center justify-between gap-3",children:[e.jsxs("div",{className:"min-w-0",children:[e.jsx("div",{className:"flex items-baseline gap-2",children:e.jsx("span",{className:"text-[13px] font-semibold tracking-tight text-fg",children:t("config.workdir")})}),e.jsx("div",{className:"mt-0.5 break-all font-mono text-[12px] leading-relaxed text-fg-2",children:a||t("sidebar.notSet")})]}),e.jsx(w,{variant:"outline",size:"sm",onClick:s,children:t("sidebar.switchDir")})]})}),e.jsxs(v,{className:"space-y-2 !p-3.5",children:[e.jsxs("div",{className:"flex flex-wrap items-baseline justify-between gap-x-3 gap-y-0.5",children:[e.jsxs("div",{className:"flex items-baseline gap-2 min-w-0",children:[e.jsx("span",{className:"text-[13px] font-semibold tracking-tight text-fg",children:t("app.systemInfo")}),e.jsx("span",{className:"truncate text-[11px] text-fg-5",children:d||t("status.loading")})]}),e.jsxs("div",{className:"text-[11px] text-fg-5",children:[r?.version?`Pikiloom v${r.version}`:"Pikiloom",r?.nodeVersion?` · Node ${r.nodeVersion}`:""]})]}),e.jsx(W,{items:E(o,t),loading:!o})]}),e.jsxs(v,{className:"space-y-2 !p-3.5",children:[e.jsx("div",{className:"text-[13px] font-semibold tracking-tight text-fg",children:t("tab.permissions")}),e.jsx(I,{})]})]})}export{_ as SystemTab};