@skylandnpm/octopus-proxy 0.1.73 → 0.1.74

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.
@@ -11070,6 +11070,7 @@ var OpenCodeAdapter = class {
11070
11070
  terminalOutput = /* @__PURE__ */ new Map();
11071
11071
  permissionEvents = /* @__PURE__ */ new Map();
11072
11072
  resolving = /* @__PURE__ */ new Set();
11073
+ approveAll = /* @__PURE__ */ new Set();
11073
11074
  config;
11074
11075
  media;
11075
11076
  async request(project, method, path, body, signal) {
@@ -11128,6 +11129,7 @@ var OpenCodeAdapter = class {
11128
11129
  { id: "ask", label: "\u8BF7\u6C42\u6279\u51C6", description: "\u6BCF\u6B21\u4F7F\u7528\u5DE5\u5177\u524D\u8BF7\u6C42\u6279\u51C6" },
11129
11130
  { id: "full", label: "\u5B8C\u5168\u8BBF\u95EE", description: "\u81EA\u52A8\u5141\u8BB8\u5DE5\u5177\u64CD\u4F5C\uFF1B\u4ECD\u9075\u5B88\u4E3B\u673A\u548C\u5DE5\u5177\u81EA\u8EAB\u7684\u8BBF\u95EE\u9650\u5236" }
11130
11131
  ] };
11132
+ if (id && ["sessions.prompt", "sessions.command", "sessions.shell", "sessions.abort", "sessions.delete"].includes(op)) this.approveAll.delete(`${project}\0${id}`);
11131
11133
  if (op === "sessions.prompt") return this.prompt(project, id, p, base, session?.model);
11132
11134
  if (op === "sessions.command" || op === "sessions.shell") {
11133
11135
  await this.switchSelection(project, base, p);
@@ -11262,7 +11264,7 @@ var OpenCodeAdapter = class {
11262
11264
  entries = [...this.permissionEvents.get(project)?.values() ?? []].filter((entry) => !session || entry.sessionID === session);
11263
11265
  if (!entries.length) throw error;
11264
11266
  }
11265
- return (Array.isArray(entries) ? entries : []).map((entry) => ({ ...entry, permission: entry.action, patterns: entry.resources ?? [], replies: ["once", "always", "reject"] }));
11267
+ return (Array.isArray(entries) ? entries : []).map((entry) => ({ ...entry, permission: entry.action, patterns: entry.resources ?? [], replies: ["once", "always", "all", "reject"] }));
11266
11268
  }
11267
11269
  trackPermission(project, type, data) {
11268
11270
  if (typeof data?.sessionID !== "string" || !SESSION_ID.test(data.sessionID)) return;
@@ -11272,6 +11274,12 @@ var OpenCodeAdapter = class {
11272
11274
  if (!pending) this.permissionEvents.set(project, pending = /* @__PURE__ */ new Map());
11273
11275
  pending.set(data.id, data);
11274
11276
  if (pending.size > 256) pending.delete(pending.keys().next().value);
11277
+ if (this.approveAll.has(`${project}\0${data.sessionID}`)) {
11278
+ void this.resolveInteraction(project, data.sessionID, "permissions.reply", { requestId: data.id, reply: "once" }).catch(() => {
11279
+ });
11280
+ }
11281
+ } else if (type === "session.idle" || type === "session.status" && data.status?.type === "idle") {
11282
+ this.approveAll.delete(`${project}\0${data.sessionID}`);
11275
11283
  } else if (type === "permission.replied") {
11276
11284
  const pending = this.permissionEvents.get(project);
11277
11285
  if (pending?.get(data.requestID)?.sessionID === data.sessionID) pending.delete(data.requestID);
@@ -11296,7 +11304,14 @@ var OpenCodeAdapter = class {
11296
11304
  if (kind !== "permission" || !session) await this.session(project, item.sessionID);
11297
11305
  const base = `/api/session/${encodeURIComponent(item.sessionID)}/${kind}/${requestId}`;
11298
11306
  if (kind === "permission") {
11299
- const decision = payload.reply === "deny" ? "reject" : payload.reply;
11307
+ if (payload.reply === "all") {
11308
+ this.approveAll.add(`${project}\0${item.sessionID}`);
11309
+ for (const other of pending) if (other.sessionID === item.sessionID && other.id !== item.id) {
11310
+ await this.data(project, "POST", `/api/session/${encodeURIComponent(item.sessionID)}/permission/${this.identifier(other.id)}/reply`, { decision: "once" });
11311
+ this.permissionEvents.get(project)?.delete(other.id);
11312
+ }
11313
+ }
11314
+ const decision = payload.reply === "all" ? "once" : payload.reply === "deny" ? "reject" : payload.reply;
11300
11315
  const result = await this.data(project, "POST", `${base}/reply`, { decision, ...payload.message ? { message: payload.message } : {} });
11301
11316
  this.permissionEvents.get(project)?.delete(String(payload.requestId));
11302
11317
  return result;
@@ -11420,6 +11435,7 @@ var OpenCodeAdapter = class {
11420
11435
  this.streams.get(project)?.abort();
11421
11436
  this.streams.delete(project);
11422
11437
  this.permissionEvents.delete(project);
11438
+ for (const key of this.approveAll) if (key.startsWith(`${project}\0`)) this.approveAll.delete(key);
11423
11439
  for (const [key, terminal] of this.terminals) {
11424
11440
  if (!key.startsWith(`${project}:`)) continue;
11425
11441
  terminal.close();
@@ -11481,6 +11497,7 @@ var OpenCodeAdapter = class {
11481
11497
  close() {
11482
11498
  this.auth.close();
11483
11499
  this.permissionEvents.clear();
11500
+ this.approveAll.clear();
11484
11501
  for (const controller of this.streams.values()) controller.abort();
11485
11502
  for (const terminal of this.terminals.values()) terminal.close();
11486
11503
  }
@@ -12316,6 +12333,7 @@ var CodexAdapter = class {
12316
12333
  media;
12317
12334
  liveTurns = /* @__PURE__ */ new Map();
12318
12335
  approvals = /* @__PURE__ */ new Map();
12336
+ approveAll = /* @__PURE__ */ new Set();
12319
12337
  inputs = /* @__PURE__ */ new Map();
12320
12338
  activeTurns = /* @__PURE__ */ new Map();
12321
12339
  loadedThreads = /* @__PURE__ */ new Map();
@@ -12356,13 +12374,17 @@ var CodexAdapter = class {
12356
12374
  this.trackNotification(project, method, params);
12357
12375
  if (method === "turn/completed") {
12358
12376
  const detail = params ?? {};
12359
- if (detail.threadId && this.activeTurns.get(detail.threadId) === detail.turn?.id) this.activeTurns.delete(detail.threadId);
12377
+ if (detail.threadId && this.activeTurns.get(detail.threadId) === detail.turn?.id) {
12378
+ this.activeTurns.delete(detail.threadId);
12379
+ this.approveAll.delete(`${project}\0${detail.threadId}`);
12380
+ }
12360
12381
  }
12361
12382
  this.emit(project, method, params);
12362
12383
  },
12363
12384
  onServerRequest: (id, method, params, respond) => this.onServerRequest(project, id, method, params, respond),
12364
12385
  onClose: () => {
12365
12386
  this.loadedThreads.delete(project);
12387
+ for (const key of this.approveAll) if (key.startsWith(`${project}\0`)) this.approveAll.delete(key);
12366
12388
  for (const key of this.liveTurns.keys()) if (key.startsWith(`${project}\0`)) this.liveTurns.delete(key);
12367
12389
  for (const [key, entry] of this.approvals) if (entry.project === project) this.approvals.delete(key);
12368
12390
  for (const [key, entry] of this.inputs) if (entry.project === project) this.inputs.delete(key);
@@ -12380,7 +12402,12 @@ var CodexAdapter = class {
12380
12402
  const requestId = randomUUID13();
12381
12403
  const threadId = String(detail.threadId ?? "");
12382
12404
  if (["item/permissions/requestApproval", "item/commandExecution/requestApproval", "item/fileChange/requestApproval"].includes(method)) {
12383
- this.approvals.set(requestId, { project, method, requestId, threadId, detail, respond });
12405
+ const entry = { project, method, requestId, threadId, detail, respond };
12406
+ if (this.approveAll.has(`${project}\0${threadId}`)) {
12407
+ respond(this.approvalResponse(entry, "once"));
12408
+ return;
12409
+ }
12410
+ this.approvals.set(requestId, entry);
12384
12411
  this.emit(project, "permission.request", { requestId, threadId });
12385
12412
  return;
12386
12413
  }
@@ -12611,6 +12638,7 @@ var CodexAdapter = class {
12611
12638
  for (const approval of this.approvals.values()) approval.respond(this.approvalResponse(approval, "reject"));
12612
12639
  for (const input of this.inputs.values()) input.respond({ answers: {} });
12613
12640
  this.approvals.clear();
12641
+ this.approveAll.clear();
12614
12642
  this.inputs.clear();
12615
12643
  this.liveTurns.clear();
12616
12644
  }
@@ -12737,6 +12765,7 @@ var CodexAdapter = class {
12737
12765
  }
12738
12766
  if (lines.length) input.push({ type: "text", text: lines.join("\n") });
12739
12767
  if (!input.length) throw new Error("Message or attachments required");
12768
+ this.approveAll.delete(`${project}\0${id}`);
12740
12769
  const selectedModel = p.model;
12741
12770
  const model = selectedModel?.providerID === "codex" && typeof selectedModel.modelID === "string" ? selectedModel.modelID : void 0;
12742
12771
  const effort = selectedReasoningLevel(p, "effort");
@@ -12746,6 +12775,7 @@ var CodexAdapter = class {
12746
12775
  }
12747
12776
  if (op === "sessions.abort") {
12748
12777
  if (!id) throw new Error("Session required");
12778
+ this.approveAll.delete(`${project}\0${id}`);
12749
12779
  await this.session(project, id);
12750
12780
  let turnId = this.activeTurns.get(id);
12751
12781
  if (!turnId) {
@@ -12770,15 +12800,23 @@ var CodexAdapter = class {
12770
12800
  permission: entry.detail.type ?? (entry.method.includes("fileChange") ? "\u6587\u4EF6\u4FEE\u6539" : entry.detail.permissions ? "\u6269\u5C55\u6743\u9650" : "\u547D\u4EE4\u6267\u884C"),
12771
12801
  patterns: [entry.detail.command ?? entry.detail.commandDraft ?? entry.detail.path ?? entry.detail.grantRoot ?? ""],
12772
12802
  metadata: entry.detail,
12773
- replies: ["once", "always", "reject"],
12774
- alwaysLabel: "\u672C\u4F1A\u8BDD\u5141\u8BB8"
12803
+ replies: ["once", "always", "all", "reject"],
12804
+ alwaysLabel: "\u5141\u8BB8\u7C7B\u4F3C\u8BF7\u6C42"
12775
12805
  }));
12776
12806
  }
12777
12807
  if (op === "permissions.reply") {
12778
12808
  const entry = this.approvals.get(String(p.requestId));
12779
12809
  if (!entry || entry.project !== project) throw new Error("Request is no longer pending in this project");
12780
12810
  if (id && id !== entry.threadId) throw new Error("Request belongs to another session");
12781
- if (!["accept", "allow", "yes", "once", "approve", "true", "always", "reject"].includes(String(p.reply))) throw new Error("Invalid permission reply");
12811
+ if (!["accept", "allow", "yes", "once", "approve", "true", "always", "all", "reject"].includes(String(p.reply))) throw new Error("Invalid permission reply");
12812
+ if (p.reply === "all") {
12813
+ this.approveAll.add(`${project}\0${entry.threadId}`);
12814
+ for (const [key, pending] of this.approvals) if (pending.project === project && pending.threadId === entry.threadId) {
12815
+ this.approvals.delete(key);
12816
+ pending.respond(this.approvalResponse(pending, "once"));
12817
+ }
12818
+ return { ok: true };
12819
+ }
12782
12820
  entry.respond(this.approvalResponse(entry, String(p.reply)));
12783
12821
  this.approvals.delete(String(p.requestId));
12784
12822
  return { ok: true };
@@ -12841,6 +12879,7 @@ var ZcodeAdapter = class {
12841
12879
  auth = new AuthFlows();
12842
12880
  media;
12843
12881
  permissions = /* @__PURE__ */ new Map();
12882
+ approveAll = /* @__PURE__ */ new Set();
12844
12883
  inputs = /* @__PURE__ */ new Map();
12845
12884
  subscribed = /* @__PURE__ */ new Set();
12846
12885
  resuming = /* @__PURE__ */ new Map();
@@ -12855,6 +12894,7 @@ var ZcodeAdapter = class {
12855
12894
  },
12856
12895
  onServerRequest: (id, method, params, respond, respondError) => this.onServerRequest(project, id, method, params, respond, respondError),
12857
12896
  onClose: () => {
12897
+ for (const key of this.approveAll) if (key.startsWith(`${project}\0`)) this.approveAll.delete(key);
12858
12898
  for (const key of this.subscribed) if (key.startsWith(`${project}\0`)) this.subscribed.delete(key);
12859
12899
  for (const [key, entry] of this.permissions) if (entry.project === project) this.permissions.delete(key);
12860
12900
  for (const [key, entry] of this.inputs) if (entry.project === project) this.inputs.delete(key);
@@ -12873,6 +12913,10 @@ var ZcodeAdapter = class {
12873
12913
  return;
12874
12914
  }
12875
12915
  if (method === "interaction/requestPermission" || method === "permission.request") {
12916
+ if (this.approveAll.has(`${project}\0${sessionId}`)) {
12917
+ respond({ decision: "allow" });
12918
+ return;
12919
+ }
12876
12920
  this.permissions.set(requestId, { project, requestId, sessionId, detail, respond });
12877
12921
  this.emit(project, "permission.request", { sessionID: sessionId, requestId });
12878
12922
  return;
@@ -12998,6 +13042,7 @@ var ZcodeAdapter = class {
12998
13042
  for (const entry of this.permissions.values()) entry.respond({ decision: "deny" });
12999
13043
  for (const entry of this.inputs.values()) entry.respond({ action: "decline" });
13000
13044
  this.permissions.clear();
13045
+ this.approveAll.clear();
13001
13046
  this.inputs.clear();
13002
13047
  }
13003
13048
  async dispatch(command) {
@@ -13118,10 +13163,16 @@ var ZcodeAdapter = class {
13118
13163
  const level = selectedReasoningLevel(p, "thoughtLevel");
13119
13164
  await rpc.request("session/setThoughtLevel", { sessionId: id, thoughtLevel: level });
13120
13165
  }
13121
- return await rpc.request("session/send", { sessionId: id, content: lines.join("\n") });
13166
+ this.approveAll.delete(`${project}\0${id}`);
13167
+ try {
13168
+ return await rpc.request("session/send", { sessionId: id, content: lines.join("\n") });
13169
+ } finally {
13170
+ this.approveAll.delete(`${project}\0${id}`);
13171
+ }
13122
13172
  }
13123
13173
  if (op === "sessions.abort") {
13124
13174
  if (!id) throw new Error("Session required");
13175
+ this.approveAll.delete(`${project}\0${id}`);
13125
13176
  return await rpc.request("session/stop", { sessionId: id });
13126
13177
  }
13127
13178
  if (op === "sessions.delete") {
@@ -13136,15 +13187,23 @@ var ZcodeAdapter = class {
13136
13187
  permission: entry.detail.type ?? entry.detail.toolName ?? "\u64CD\u4F5C\u786E\u8BA4",
13137
13188
  patterns: [entry.detail.command ?? entry.detail.pattern ?? ""],
13138
13189
  metadata: entry.detail,
13139
- replies: this.alwaysResponse(entry) ? ["once", "always", "reject"] : ["once", "reject"],
13140
- alwaysLabel: "\u6309\u8BF7\u6C42\u8303\u56F4\u5141\u8BB8"
13190
+ replies: this.alwaysResponse(entry) ? ["once", "always", "all", "reject"] : ["once", "all", "reject"],
13191
+ alwaysLabel: "\u5141\u8BB8\u7C7B\u4F3C\u8BF7\u6C42"
13141
13192
  }));
13142
13193
  }
13143
13194
  if (op === "permissions.reply") {
13144
13195
  const entry = this.permissions.get(String(p.requestId));
13145
13196
  if (!entry || entry.project !== project) throw new Error("Request is no longer pending in this project");
13146
13197
  if (id && id !== entry.sessionId) throw new Error("Request belongs to another session");
13147
- if (!["accept", "once", "always", "reject"].includes(String(p.reply))) throw new Error("Invalid permission reply");
13198
+ if (!["accept", "once", "always", "all", "reject"].includes(String(p.reply))) throw new Error("Invalid permission reply");
13199
+ if (p.reply === "all") {
13200
+ this.approveAll.add(`${project}\0${entry.sessionId}`);
13201
+ for (const [key, pending] of this.permissions) if (pending.project === project && pending.sessionId === entry.sessionId) {
13202
+ this.permissions.delete(key);
13203
+ pending.respond({ decision: "allow" });
13204
+ }
13205
+ return { ok: true };
13206
+ }
13148
13207
  const always = p.reply === "always" ? this.alwaysResponse(entry) : void 0;
13149
13208
  if (p.reply === "always" && !always) throw new Error("Persistent approval is not offered by this request");
13150
13209
  entry.respond(always ?? { decision: p.reply === "reject" ? "deny" : "allow" });
@@ -13244,6 +13303,7 @@ var PiAdapter = class {
13244
13303
  partials = /* @__PURE__ */ new Map();
13245
13304
  active = /* @__PURE__ */ new Set();
13246
13305
  questions = /* @__PURE__ */ new Map();
13306
+ approveAll = /* @__PURE__ */ new Set();
13247
13307
  mutations = /* @__PURE__ */ new Map();
13248
13308
  deleting = /* @__PURE__ */ new Set();
13249
13309
  reconfiguring = /* @__PURE__ */ new Set();
@@ -13287,7 +13347,10 @@ var PiAdapter = class {
13287
13347
  calls.set(detail.toolCallId, progress);
13288
13348
  this.toolProgress.set(key, calls);
13289
13349
  }
13290
- if (type === "agent_settled") this.active.delete(key);
13350
+ if (type === "agent_settled") {
13351
+ this.active.delete(key);
13352
+ this.approveAll.delete(key);
13353
+ }
13291
13354
  if (type === "message_update") this.partials.set(key, detail.message);
13292
13355
  if (type === "message_end" || type === "agent_end" || type === "agent_settled") this.partials.delete(key);
13293
13356
  if (type === "extension_ui_request") {
@@ -13298,6 +13361,7 @@ var PiAdapter = class {
13298
13361
  this.emit(project, event, { ...detail, sessionID: id });
13299
13362
  },
13300
13363
  onClose: () => {
13364
+ this.approveAll.delete(this.key(project, id));
13301
13365
  this.partials.delete(this.key(project, id));
13302
13366
  this.active.delete(this.key(project, id));
13303
13367
  this.clearQuestions(project, id);
@@ -13311,6 +13375,10 @@ var PiAdapter = class {
13311
13375
  void this.rpc(project, sessionId).then((rpc) => {
13312
13376
  if (rpc.exited) return;
13313
13377
  const question = { id, project, sessionId, detail, rpc };
13378
+ if (this.isPermission(question) && this.approveAll.has(this.key(project, sessionId))) {
13379
+ rpc.notify("extension_ui_response", { id: detail.id, confirmed: true });
13380
+ return;
13381
+ }
13314
13382
  if (typeof detail.timeout === "number" && detail.timeout > 0) {
13315
13383
  question.timer = setTimeout(() => {
13316
13384
  this.questions.delete(id);
@@ -13339,6 +13407,7 @@ var PiAdapter = class {
13339
13407
  if (!question.rpc.exited) question.rpc.notify("extension_ui_response", { id: question.detail.id, cancelled: true });
13340
13408
  }
13341
13409
  this.questions.clear();
13410
+ this.approveAll.clear();
13342
13411
  this.partials.clear();
13343
13412
  this.active.clear();
13344
13413
  this.toolProgress.clear();
@@ -13440,13 +13509,22 @@ var PiAdapter = class {
13440
13509
  sessionID: q.sessionId,
13441
13510
  permission: "Pi \u5DE5\u5177\u64CD\u4F5C",
13442
13511
  patterns: [q.detail.message ?? ""],
13443
- replies: ["once", "reject"]
13512
+ replies: ["once", "all", "reject"]
13444
13513
  }));
13445
13514
  }
13446
13515
  if (op === "permissions.reply") {
13447
13516
  const question = this.questions.get(String(p.requestId));
13448
13517
  if (!question || !this.isPermission(question) || question.project !== project || id && id !== question.sessionId) throw new Error("Request is no longer pending in this session");
13449
- if (p.reply !== "once" && p.reply !== "reject") throw new Error("Invalid permission reply");
13518
+ if (p.reply !== "once" && p.reply !== "all" && p.reply !== "reject") throw new Error("Invalid permission reply");
13519
+ if (p.reply === "all") {
13520
+ this.approveAll.add(this.key(project, question.sessionId));
13521
+ for (const [key, pending] of this.questions) if (pending.project === project && pending.sessionId === question.sessionId && this.isPermission(pending)) {
13522
+ clearTimeout(pending.timer);
13523
+ this.questions.delete(key);
13524
+ pending.rpc.notify("extension_ui_response", { id: pending.detail.id, confirmed: true });
13525
+ }
13526
+ return { ok: true };
13527
+ }
13450
13528
  question.rpc.notify("extension_ui_response", { id: question.detail.id, confirmed: p.reply === "once" });
13451
13529
  clearTimeout(question.timer);
13452
13530
  this.questions.delete(question.id);
@@ -13509,6 +13587,7 @@ var PiAdapter = class {
13509
13587
  return this.media.messages(project, id, this.messages(messages, this.key(project, id)));
13510
13588
  }
13511
13589
  if (op === "sessions.abort") {
13590
+ this.approveAll.delete(this.key(project, id));
13512
13591
  this.clearQuestions(project, id);
13513
13592
  await rpc.request("clear_queue");
13514
13593
  await rpc.request("abort");
@@ -13544,6 +13623,7 @@ var PiAdapter = class {
13544
13623
  const level = selectedReasoningLevel(p, "level");
13545
13624
  if (model && typeof model.providerID === "string" && typeof model.modelID === "string") await rpc.request("set_model", { provider: model.providerID, modelId: model.modelID });
13546
13625
  if (level) await rpc.request("set_thinking_level", { level });
13626
+ this.approveAll.delete(this.key(project, id));
13547
13627
  const result = await rpc.request("prompt", { message: lines.join("\n"), ...images.length ? { images } : {} });
13548
13628
  session.time.updated = Date.now();
13549
13629
  if (session.title === "\u65B0\u4EFB\u52A1" && typeof p.text === "string" && p.text.trim()) session.title = p.text.trim().slice(0, 100);
package/dist/cli.js CHANGED
@@ -35,7 +35,7 @@ import {
35
35
  supportedPlatform,
36
36
  systemdUnitPath,
37
37
  toolSearchDirs
38
- } from "./chunk-SSY3TLHA.js";
38
+ } from "./chunk-JUUJGAHF.js";
39
39
  import {
40
40
  DESKTOP_PERMISSION_GUIDANCE,
41
41
  PlatformDesktop,
package/dist/main.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  ConfigError,
4
4
  runDaemon
5
- } from "./chunk-SSY3TLHA.js";
5
+ } from "./chunk-JUUJGAHF.js";
6
6
  import "./chunk-OTKNRBZ7.js";
7
7
 
8
8
  // src/main.ts
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@skylandnpm/octopus-proxy",
3
- "version": "0.1.73",
3
+ "version": "0.1.74",
4
4
  "type": "module",
5
5
  "description": "Octopus host proxy: OpenCode, Codex, ZCode and Pi adapters with service installer CLI",
6
6
  "bin": {