approval-box 0.1.26 → 0.1.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -60,3 +60,11 @@ AIには、利用者へ申請の話をする時は件名で伝えるよう返し
60
60
  ### 申請に画像を添える
61
61
 
62
62
  `request_decision` に `image_paths: ["/absolute/path/screenshot.png"]` を指定すると、AIの画像を本文下に添えて申請します。10件、単体20MiB、合計50MiBまで。全画像を上げてから申請と通知を確定します。最初の確認の札を付けた出し直しでも同じ画像パスを渡してください。`amend_decision.changes.image_paths` は全置換、空配列で削除です。回答添付とは別の欄です。リモートMCPは `upload_request_image` のIDを `request_attachment_ids` に渡します。
63
+
64
+ ### 読みやすい申請文
65
+
66
+ MCPは、[unai](https://github.com/kitepon/unai)の方針に沿って申請文を推敲するようAIへ伝えます。件名で判断してほしいことを示し、背景では判断に必要な理由と影響を先に説明します。各AIの口調や、承認対象・範囲・費用・危険・期限・未確認事項を保ちます。
67
+
68
+ 例:「ランタイム更新の実行可否について」より「Approval Boxの実行環境を更新してよいですか?」、背景には「セキュリティ修正を適用します。更新中は数秒使えなくなります。」のように具体的に書きます。
69
+
70
+ AIへの執筆指示のため、文章の品質を機械的に保証するものではありません。保存済みの申請・回答は書き換えません。ローカル接続ではコネクタ0.1.27へ更新し、MCPを再接続すると新しい指示を取得できます。
@@ -2,7 +2,7 @@
2
2
 
3
3
  approval-box bundles the following packages.
4
4
 
5
- ## @modelcontextprotocol/sdk@1.31.0 (MIT)
5
+ ## @modelcontextprotocol/sdk@1.32.2 (MIT)
6
6
 
7
7
  ```
8
8
  MIT License
@@ -157,7 +157,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
157
157
  SOFTWARE.
158
158
  ```
159
159
 
160
- ## fast-uri@3.1.8 (BSD-3-Clause)
160
+ ## fast-uri@3.1.9 (BSD-3-Clause)
161
161
 
162
162
  ```
163
163
  Copyright (c) 2011-2021, Gary Court until https://github.com/garycourt/uri-js/commit/a1acf730b4bba3f1097c9f52e7d9d3aba8cdcaae
@@ -257,7 +257,7 @@ The above copyright notice and this permission notice shall be included in all c
257
257
  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
258
258
  ```
259
259
 
260
- ## zod@4.6.5 (MIT)
260
+ ## zod@4.6.7 (MIT)
261
261
 
262
262
  ```
263
263
  MIT License
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
2
2
  import {
3
3
  PROFILE,
4
4
  runClaudeHookMain
5
- } from "./chunks/chunk-XTKJLDHY.mjs";
5
+ } from "./chunks/chunk-GFEMLSCW.mjs";
6
6
 
7
7
  // src/hooks/claude.ts
8
8
  await runClaudeHookMain(PROFILE);
@@ -5,7 +5,7 @@ import {
5
5
  handleCursorChannelHook,
6
6
  handleCursorHook,
7
7
  withoutBom
8
- } from "./chunks/chunk-XTKJLDHY.mjs";
8
+ } from "./chunks/chunk-GFEMLSCW.mjs";
9
9
 
10
10
  // src/cursor-binding.ts
11
11
  async function bindCursorResult(profile, raw) {
@@ -2,7 +2,7 @@ import { createRequire as __kbCreateRequire } from 'node:module'; const require
2
2
  import {
3
3
  PROFILE,
4
4
  runChannelReceiveMain
5
- } from "./chunks/chunk-XTKJLDHY.mjs";
5
+ } from "./chunks/chunk-GFEMLSCW.mjs";
6
6
 
7
7
  // src/hooks/receive.ts
8
8
  await runChannelReceiveMain(PROFILE);
@@ -734,6 +734,7 @@ __export(util_exports, {
734
734
  required: () => required,
735
735
  safeExtend: () => safeExtend,
736
736
  shallowClone: () => shallowClone,
737
+ sizeCaps: () => sizeCaps,
737
738
  slugify: () => slugify,
738
739
  stringifyPrimitive: () => stringifyPrimitive,
739
740
  toZod: () => toZod,
@@ -1253,6 +1254,18 @@ function prefixIssues(path12, issues) {
1253
1254
  function unwrapMessage(message) {
1254
1255
  return typeof message === "string" ? message : message?.message;
1255
1256
  }
1257
+ function sizeCaps(defChecks) {
1258
+ const caps = [];
1259
+ for (const ch of defChecks ?? []) {
1260
+ const d = ch._zod.def;
1261
+ if (!/_(length|size)$|_equals$/.test(d.check))
1262
+ break;
1263
+ const max = d.maximum ?? d.length ?? d.size;
1264
+ if (max >= 0)
1265
+ caps.push([max, ch]);
1266
+ }
1267
+ return caps;
1268
+ }
1256
1269
  function attachSchema(issues, start, inst) {
1257
1270
  var _a3;
1258
1271
  for (let i = start; i < issues.length; i++) {
@@ -2673,7 +2686,7 @@ ${content.join("\n")}
2673
2686
  var version = {
2674
2687
  major: 4,
2675
2688
  minor: 6,
2676
- patch: 5
2689
+ patch: 7
2677
2690
  };
2678
2691
 
2679
2692
  // ../../node_modules/zod/v4/core/schemas.js
@@ -3429,6 +3442,31 @@ var $ZodDate = /* @__PURE__ */ $constructor("$ZodDate", (inst, def) => {
3429
3442
  return payload;
3430
3443
  };
3431
3444
  });
3445
+ function capSize(inst, size) {
3446
+ const caps = sizeCaps(inst._zod.def.checks);
3447
+ if (!caps.length)
3448
+ return;
3449
+ const cap = Math.min(...caps.map((c) => c[0]));
3450
+ const parse3 = inst._zod.parse;
3451
+ inst._zod.parse = (payload, ctx) => {
3452
+ const n = size(payload.value);
3453
+ if (n > cap && !ctx?.skipChecks && ctx?.direction !== "backward") {
3454
+ for (const [max, ch] of sizeCaps(inst._zod.def.checks)) {
3455
+ if (n > max && ch._zod.def.when(payload)) {
3456
+ const start = payload.issues.length;
3457
+ ch._zod.check(payload);
3458
+ payload.issues[start].continue = false;
3459
+ attachSchema(payload.issues, start, inst);
3460
+ return payload;
3461
+ }
3462
+ }
3463
+ }
3464
+ return parse3(payload, ctx);
3465
+ };
3466
+ }
3467
+ var arraySize = (input2) => Array.isArray(input2) ? input2.length : -1;
3468
+ var mapSize = (input2) => input2 instanceof Map ? input2.size : -1;
3469
+ var setSize = (input2) => input2 instanceof Set ? input2.size : -1;
3432
3470
  function handleArrayResult(result, final, index) {
3433
3471
  if (result.issues.length) {
3434
3472
  final.issues.push(...prefixIssues(index, result.issues));
@@ -3472,6 +3510,7 @@ var $ZodArray = /* @__PURE__ */ $constructor("$ZodArray", (inst, def) => {
3472
3510
  }
3473
3511
  return payload;
3474
3512
  };
3513
+ capSize(inst, arraySize);
3475
3514
  });
3476
3515
  function handlePropertyResult(result, final, key, input2, optin, optout) {
3477
3516
  const isPresent = key in input2;
@@ -4428,6 +4467,7 @@ var $ZodMap = /* @__PURE__ */ $constructor("$ZodMap", (inst, def) => {
4428
4467
  return Promise.all(proms).then(() => payload);
4429
4468
  return payload;
4430
4469
  };
4470
+ capSize(inst, mapSize);
4431
4471
  });
4432
4472
  function handleMapResult(keyResult, valueResult, final, key, input2, inst, ctx) {
4433
4473
  if (keyResult.issues.length) {
@@ -4494,6 +4534,7 @@ var $ZodSet = /* @__PURE__ */ $constructor("$ZodSet", (inst, def) => {
4494
4534
  return Promise.all(proms).then(() => payload);
4495
4535
  return payload;
4496
4536
  };
4537
+ capSize(inst, setSize);
4497
4538
  });
4498
4539
  function handleSetResult(result, final) {
4499
4540
  if (result.issues.length) {
@@ -14024,9 +14065,15 @@ function generateNullableCheck(doc, ctx, schema, accessor, buildsValue = true) {
14024
14065
  doc.write(`}`);
14025
14066
  return outputVar;
14026
14067
  }
14068
+ function generateSizeGate(doc, schema, size) {
14069
+ for (const [max, check2] of sizeCaps(schema._zod.def.checks)) {
14070
+ doc.write(`if (${size} > ${numericOperand(max, check2._zod.def.check)}) return INVALID;`);
14071
+ }
14072
+ }
14027
14073
  function generateArrayCheck(doc, ctx, schema, accessor, buildsValue = true) {
14028
14074
  const def = schema._zod.def;
14029
14075
  doc.write(`if (!Array.isArray(${accessor})) return INVALID;`);
14076
+ generateSizeGate(doc, schema, `${accessor}.length`);
14030
14077
  const outputVar = buildsValue ? newVar(ctx) : null;
14031
14078
  const iVar = newVar(ctx);
14032
14079
  const elemVar = newVar(ctx);
@@ -14426,6 +14473,7 @@ function literalPropertyKey(ctx, key) {
14426
14473
  function generateMapCheck(doc, ctx, schema, accessor) {
14427
14474
  const def = schema._zod.def;
14428
14475
  doc.write(`if (!(${accessor} instanceof Map)) return INVALID;`);
14476
+ generateSizeGate(doc, schema, `${accessor}.size`);
14429
14477
  const outputVar = newVar(ctx);
14430
14478
  const kVar = newVar(ctx);
14431
14479
  const valVar = newVar(ctx);
@@ -14442,6 +14490,7 @@ function generateMapCheck(doc, ctx, schema, accessor) {
14442
14490
  function generateSetCheck(doc, ctx, schema, accessor) {
14443
14491
  const def = schema._zod.def;
14444
14492
  doc.write(`if (!(${accessor} instanceof Set)) return INVALID;`);
14493
+ generateSizeGate(doc, schema, `${accessor}.size`);
14445
14494
  const outputVar = newVar(ctx);
14446
14495
  const valVar = newVar(ctx);
14447
14496
  doc.write(`const ${outputVar} = new Set();`);
package/dist/cli.mjs CHANGED
@@ -57,7 +57,7 @@ import {
57
57
  waitProcessCommandLine,
58
58
  withCodexReceiver,
59
59
  withdrawFromChannel
60
- } from "./chunks/chunk-XTKJLDHY.mjs";
60
+ } from "./chunks/chunk-GFEMLSCW.mjs";
61
61
 
62
62
  // ../../node_modules/qrcode/lib/can-promise.js
63
63
  var require_can_promise = __commonJS({
@@ -7896,6 +7896,37 @@ var require_utils3 = __commonJS({
7896
7896
  }
7897
7897
  return output.join("");
7898
7898
  }
7899
+ function removeDotSegmentsRelative(path) {
7900
+ if (path === "" || path[0] === "/") {
7901
+ return removeDotSegments(path);
7902
+ }
7903
+ const segments = path.split("/");
7904
+ const last = segments.length - 1;
7905
+ const output = [];
7906
+ let trailingDirectory = false;
7907
+ for (let i = 0; i <= last; i++) {
7908
+ const segment = segments[i];
7909
+ if (segment === "." || segment === "..") {
7910
+ if (segment === "..") {
7911
+ if (output.length !== 0 && output[output.length - 1] !== "..") {
7912
+ output.pop();
7913
+ } else {
7914
+ output.push("..");
7915
+ }
7916
+ }
7917
+ trailingDirectory = i === last;
7918
+ } else {
7919
+ output.push(segment);
7920
+ }
7921
+ }
7922
+ if (trailingDirectory && output[output.length - 1] !== "..") {
7923
+ output.push("");
7924
+ }
7925
+ if (output.length === 0 || output[0] === "" || output[0].includes(":")) {
7926
+ output.unshift(".");
7927
+ }
7928
+ return output.join("/");
7929
+ }
7899
7930
  var HOST_DELIMS = { "@": "%40", "/": "%2F", "?": "%3F", "#": "%23", ":": "%3A" };
7900
7931
  var HOST_DELIM_RE = /[@/?#:]/g;
7901
7932
  var HOST_DELIM_NO_COLON_RE = /[@/?#]/g;
@@ -8156,6 +8187,7 @@ var require_utils3 = __commonJS({
8156
8187
  encodeFragment,
8157
8188
  escapePreservingEscapes,
8158
8189
  removeDotSegments,
8190
+ removeDotSegmentsRelative,
8159
8191
  isIPv4,
8160
8192
  isUUID,
8161
8193
  normalizeIPv6,
@@ -8379,16 +8411,18 @@ var require_schemes = __commonJS({
8379
8411
  var require_fast_uri = __commonJS({
8380
8412
  "../../node_modules/fast-uri/index.js"(exports, module) {
8381
8413
  "use strict";
8382
- var { normalizeIPv6, removeDotSegments, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils3();
8414
+ var { normalizeIPv6, removeDotSegments, removeDotSegmentsRelative, recomposeAuthority, normalizePercentEncoding, normalizePathEncoding, serializePathEncoding, normalizeQueryFragmentEncoding, encodeQuery, encodeFragment, reescapeHostDelimiters, isIPv4, nonSimpleDomain } = require_utils3();
8383
8415
  var { SCHEMES, getSchemeHandler } = require_schemes();
8384
8416
  var VALID_SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*$/u;
8385
8417
  var MALFORMED_SCHEME_ERROR = "URI scheme is malformed.";
8386
- function decodeValidScheme(scheme) {
8387
- const decodedScheme = unescape(String(scheme));
8388
- if (!VALID_SCHEME.test(decodedScheme)) {
8418
+ var MALFORMED_HOST_ERROR = "URI host is malformed.";
8419
+ var FORBIDDEN_DOMAIN_HOST_CHARACTER = /[\0-\x20"#/:<>?@[\\\]^`{|}\x7F]/u;
8420
+ function validateScheme(scheme) {
8421
+ const stringScheme = String(scheme);
8422
+ if (!VALID_SCHEME.test(stringScheme)) {
8389
8423
  throw new TypeError(MALFORMED_SCHEME_ERROR);
8390
8424
  }
8391
- return decodedScheme;
8425
+ return stringScheme;
8392
8426
  }
8393
8427
  function normalize(uri, options) {
8394
8428
  if (typeof uri === "string") {
@@ -8425,6 +8459,9 @@ var require_fast_uri = __commonJS({
8425
8459
  const resolvedSchemeHandler = getSchemeHandler(options && options.scheme || resolved.scheme);
8426
8460
  const resolvedHost = resolved.host;
8427
8461
  const resolvedHostIsIP = resolvedHost !== void 0 && resolvedHost !== "" && (isIPv4(resolvedHost) || normalizeIPv6(resolvedHost).isIPV6);
8462
+ if (hasForbiddenDomainHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP)) {
8463
+ throw new Error(MALFORMED_HOST_ERROR);
8464
+ }
8428
8465
  canonicalizeHost(resolved, options || {}, resolvedSchemeHandler, resolvedHostIsIP);
8429
8466
  const encodedASCIIHost = resolvedHost && resolvedHost.indexOf("%") !== -1 && !new RegExp("\\P{ASCII}", "u").test(resolvedHost);
8430
8467
  if (resolved.error && !encodedASCIIHost) {
@@ -8466,14 +8503,15 @@ var require_fast_uri = __commonJS({
8466
8503
  if (relative.path[0] === "/") {
8467
8504
  target.path = removeDotSegments(relative.path);
8468
8505
  } else {
8469
- if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
8506
+ const baseHasAuthority = base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0;
8507
+ if (baseHasAuthority && !base.path) {
8470
8508
  target.path = "/" + relative.path;
8471
8509
  } else if (!base.path) {
8472
8510
  target.path = relative.path;
8473
8511
  } else {
8474
8512
  target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative.path;
8475
8513
  }
8476
- target.path = removeDotSegments(target.path);
8514
+ target.path = base.scheme === void 0 && !baseHasAuthority && target.path[0] !== "/" ? removeDotSegmentsRelative(target.path) : removeDotSegments(target.path);
8477
8515
  }
8478
8516
  target.query = relative.query;
8479
8517
  }
@@ -8511,12 +8549,13 @@ var require_fast_uri = __commonJS({
8511
8549
  const options = Object.assign({}, opts);
8512
8550
  const uriTokens = [];
8513
8551
  if (component.scheme) {
8514
- component.scheme = decodeValidScheme(component.scheme);
8552
+ component.scheme = validateScheme(component.scheme);
8515
8553
  }
8516
8554
  const schemeHandler = getSchemeHandler(options.scheme || component.scheme);
8517
8555
  if (schemeHandler && schemeHandler.serialize) schemeHandler.serialize(component, options);
8518
8556
  const hasAuthority = component.userinfo !== void 0 || component.host !== void 0 || component.port !== void 0;
8519
- const pathNoScheme = !options.skipEscape && component.scheme === void 0 && !hasAuthority;
8557
+ const schemelessReference = (component.scheme === void 0 || options.reference === "suffix") && !hasAuthority;
8558
+ const pathNoScheme = !options.skipEscape && schemelessReference;
8520
8559
  if (component.path !== void 0) {
8521
8560
  if (!options.skipEscape) {
8522
8561
  component.path = serializePathEncoding(component.path, pathNoScheme);
@@ -8525,7 +8564,7 @@ var require_fast_uri = __commonJS({
8525
8564
  }
8526
8565
  }
8527
8566
  if (options.reference !== "suffix" && component.scheme) {
8528
- component.scheme = decodeValidScheme(component.scheme);
8567
+ component.scheme = validateScheme(component.scheme);
8529
8568
  uriTokens.push(component.scheme, ":");
8530
8569
  }
8531
8570
  const authority = recomposeAuthority(component);
@@ -8541,9 +8580,9 @@ var require_fast_uri = __commonJS({
8541
8580
  if (component.path !== void 0) {
8542
8581
  let s = component.path;
8543
8582
  if (!options.absolutePath && (!schemeHandler || !schemeHandler.absolutePath)) {
8544
- s = removeDotSegments(s);
8583
+ s = schemelessReference && s[0] !== "/" ? removeDotSegmentsRelative(s) : removeDotSegments(s);
8545
8584
  }
8546
- if (pathNoScheme) {
8585
+ if (schemelessReference) {
8547
8586
  s = serializePathEncoding(s, true);
8548
8587
  }
8549
8588
  if (authority === void 0 && s[0] === "/" && s[1] === "/") {
@@ -8590,16 +8629,34 @@ var require_fast_uri = __commonJS({
8590
8629
  return hasMalformedPercentEncoding(matches[3]) || host !== void 0 && !isIPLiteral(host) && hasMalformedPercentEncoding(host) || hasMalformedPercentEncoding(matches[6]) || hasMalformedPercentEncoding(matches[7]) || hasMalformedPercentEncoding(matches[8]);
8591
8630
  }
8592
8631
  function canonicalizeHost(parsed, options, schemeHandler, isIP) {
8632
+ if (hasForbiddenDomainHost(parsed, options, schemeHandler, isIP)) {
8633
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
8634
+ return true;
8635
+ }
8593
8636
  if (!options.unicodeSupport && (!schemeHandler || !schemeHandler.unicodeSupport) && parsed.host && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && isIP === false && nonSimpleDomain(parsed.host)) {
8637
+ let url;
8594
8638
  try {
8595
- parsed.host = new URL("http://" + parsed.host).hostname;
8639
+ url = new URL("http://" + parsed.host);
8596
8640
  } catch (e) {
8597
8641
  parsed.error = parsed.error || "Host's domain name can not be converted to ASCII: " + e;
8598
8642
  return true;
8599
8643
  }
8644
+ if (!isHostOnlyURL(url)) {
8645
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
8646
+ return true;
8647
+ }
8648
+ parsed.host = url.hostname;
8600
8649
  }
8601
8650
  return false;
8602
8651
  }
8652
+ function hasForbiddenDomainHost(parsed, options, schemeHandler, isIP) {
8653
+ return Boolean(
8654
+ parsed.host && isIP === false && !isIPLiteral(parsed.host) && (options.domainHost || schemeHandler && schemeHandler.domainHost) && FORBIDDEN_DOMAIN_HOST_CHARACTER.test(parsed.host)
8655
+ );
8656
+ }
8657
+ function isHostOnlyURL(url) {
8658
+ return url.username === "" && url.password === "" && url.port === "" && url.pathname === "/" && url.search === "" && url.hash === "" && url.hostname !== "";
8659
+ }
8603
8660
  function parseWithStatus(uri, opts) {
8604
8661
  const options = Object.assign({}, opts);
8605
8662
  const parsed = {
@@ -8654,9 +8711,8 @@ var require_fast_uri = __commonJS({
8654
8711
  parsed.query = matches[7];
8655
8712
  parsed.fragment = matches[8];
8656
8713
  if (parsed.scheme !== void 0) {
8657
- const decodedScheme = unescape(parsed.scheme);
8658
- if (VALID_SCHEME.test(decodedScheme)) {
8659
- parsed.scheme = decodedScheme.toLowerCase();
8714
+ if (VALID_SCHEME.test(parsed.scheme)) {
8715
+ parsed.scheme = parsed.scheme.toLowerCase();
8660
8716
  } else {
8661
8717
  parsed.error = parsed.error || MALFORMED_SCHEME_ERROR;
8662
8718
  malformedScheme = true;
@@ -8684,7 +8740,7 @@ var require_fast_uri = __commonJS({
8684
8740
  malformedIPLiteral = hasIPLiteralBracket && (!bracketedIPLiteral || ipv6result.error === true);
8685
8741
  parsed.host = isIP ? ipv6result.host : ipv6result.host.toLowerCase();
8686
8742
  if (malformedIPLiteral) {
8687
- parsed.error = parsed.error || "URI host is malformed.";
8743
+ parsed.error = parsed.error || MALFORMED_HOST_ERROR;
8688
8744
  malformedAuthorityOrPort = true;
8689
8745
  }
8690
8746
  } else {
@@ -8712,7 +8768,7 @@ var require_fast_uri = __commonJS({
8712
8768
  if (!isIP) {
8713
8769
  host = normalizePercentEncoding(host.toLowerCase());
8714
8770
  }
8715
- parsed.host = reescapeHostDelimiters(host, isIP);
8771
+ parsed.host = isIP || options.scheme !== "null" ? reescapeHostDelimiters(host, isIP) : host;
8716
8772
  }
8717
8773
  if (!schemeHandler || schemeHandler && !schemeHandler.skipNormalize) {
8718
8774
  if (parsed.path) {
@@ -14154,6 +14210,9 @@ var Protocol = class {
14154
14210
  this.setRequestHandler(GetTaskPayloadRequestSchema, async (request, extra) => {
14155
14211
  const handleTaskResult = async () => {
14156
14212
  const taskId = request.params.taskId;
14213
+ if (!await this._taskStore.getTask(taskId, extra.sessionId)) {
14214
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14215
+ }
14157
14216
  if (this._taskMessageQueue) {
14158
14217
  let queuedMessage;
14159
14218
  while (queuedMessage = await this._taskMessageQueue.dequeue(taskId, extra.sessionId)) {
@@ -14184,12 +14243,12 @@ var Protocol = class {
14184
14243
  throw new McpError(ErrorCode.InvalidParams, `Task not found: ${taskId}`);
14185
14244
  }
14186
14245
  if (!isTerminal(task.status)) {
14187
- await this._waitForTaskUpdate(taskId, extra.signal);
14246
+ await this._waitForTaskUpdate(taskId, extra.signal, extra.sessionId);
14188
14247
  return await handleTaskResult();
14189
14248
  }
14190
14249
  if (isTerminal(task.status)) {
14191
14250
  const result = await this._taskStore.getTaskResult(taskId, extra.sessionId);
14192
- this._clearTaskQueue(taskId);
14251
+ this._clearTaskQueue(taskId, extra.sessionId);
14193
14252
  return {
14194
14253
  ...result,
14195
14254
  _meta: {
@@ -14226,7 +14285,7 @@ var Protocol = class {
14226
14285
  throw new McpError(ErrorCode.InvalidParams, `Cannot cancel task in terminal status: ${task.status}`);
14227
14286
  }
14228
14287
  await this._taskStore.updateTaskStatus(request.params.taskId, "cancelled", "Client cancelled task execution.", extra.sessionId);
14229
- this._clearTaskQueue(request.params.taskId);
14288
+ this._clearTaskQueue(request.params.taskId, extra.sessionId);
14230
14289
  const cancelledTask = await this._taskStore.getTask(request.params.taskId, extra.sessionId);
14231
14290
  if (!cancelledTask) {
14232
14291
  throw new McpError(ErrorCode.InvalidParams, `Task not found after cancellation: ${request.params.taskId}`);
@@ -14354,6 +14413,19 @@ var Protocol = class {
14354
14413
  const handler = this._requestHandlers.get(request.method) ?? this.fallbackRequestHandler;
14355
14414
  const capturedTransport = this._transport;
14356
14415
  const relatedTaskId = request.params?._meta?.[RELATED_TASK_META_KEY]?.taskId;
14416
+ const sessionId = capturedTransport?.sessionId;
14417
+ const store = this._taskStore;
14418
+ let relatedTaskFound = true;
14419
+ let relatedTaskLookup;
14420
+ if (relatedTaskId && store && this._taskMessageQueue && sessionId !== void 0) {
14421
+ relatedTaskFound = false;
14422
+ relatedTaskLookup = (async () => {
14423
+ if (!await store.getTask(relatedTaskId, sessionId)) {
14424
+ throw new McpError(ErrorCode.InvalidParams, `Task not found: ${relatedTaskId}`);
14425
+ }
14426
+ relatedTaskFound = true;
14427
+ })();
14428
+ }
14357
14429
  if (handler === void 0) {
14358
14430
  const errorResponse = {
14359
14431
  jsonrpc: "2.0",
@@ -14363,7 +14435,10 @@ var Protocol = class {
14363
14435
  message: "Method not found"
14364
14436
  }
14365
14437
  };
14366
- if (relatedTaskId && this._taskMessageQueue) {
14438
+ if (relatedTaskId && relatedTaskLookup) {
14439
+ const queuedError = { type: "error", message: errorResponse, timestamp: Date.now() };
14440
+ relatedTaskLookup.then(() => this._enqueueTaskMessage(relatedTaskId, queuedError, sessionId), () => capturedTransport?.send(errorResponse)).catch((error) => this._onerror(new Error(`Failed to send an error response: ${error}`)));
14441
+ } else if (relatedTaskId && this._taskMessageQueue) {
14367
14442
  this._enqueueTaskMessage(relatedTaskId, {
14368
14443
  type: "error",
14369
14444
  message: errorResponse,
@@ -14414,7 +14489,10 @@ var Protocol = class {
14414
14489
  closeSSEStream: extra?.closeSSEStream,
14415
14490
  closeStandaloneSSEStream: extra?.closeStandaloneSSEStream
14416
14491
  };
14417
- Promise.resolve().then(() => {
14492
+ (relatedTaskLookup ?? Promise.resolve()).then(() => {
14493
+ if (relatedTaskLookup && abortController.signal.aborted) {
14494
+ throw new McpError(ErrorCode.ConnectionClosed, "Request was cancelled");
14495
+ }
14418
14496
  if (taskCreationParams) {
14419
14497
  this.assertTaskHandlerCapability(request.method);
14420
14498
  }
@@ -14449,7 +14527,7 @@ var Protocol = class {
14449
14527
  ...error["data"] !== void 0 && { data: error["data"] }
14450
14528
  }
14451
14529
  };
14452
- if (relatedTaskId && this._taskMessageQueue) {
14530
+ if (relatedTaskId && this._taskMessageQueue && relatedTaskFound) {
14453
14531
  await this._enqueueTaskMessage(relatedTaskId, {
14454
14532
  type: "error",
14455
14533
  message: errorResponse,
@@ -14929,7 +15007,7 @@ var Protocol = class {
14929
15007
  throw new Error("Cannot enqueue task message: taskStore and taskMessageQueue are not configured");
14930
15008
  }
14931
15009
  const maxQueueSize = this._options?.maxTaskQueueSize;
14932
- await this._taskMessageQueue.enqueue(taskId, message, sessionId, maxQueueSize);
15010
+ await this._taskMessageQueue.enqueue(taskId, message, sessionId ?? this._transport?.sessionId, maxQueueSize);
14933
15011
  }
14934
15012
  /**
14935
15013
  * Clears the message queue for a task and rejects any pending request resolvers.
@@ -14958,12 +15036,13 @@ var Protocol = class {
14958
15036
  * Uses polling to check for updates at the task's configured poll interval.
14959
15037
  * @param taskId The task ID to wait for
14960
15038
  * @param signal Abort signal to cancel the wait
15039
+ * @param sessionId Session of the request that waits, passed to the task store
14961
15040
  * @returns Promise that resolves when an update occurs or rejects if aborted
14962
15041
  */
14963
- async _waitForTaskUpdate(taskId, signal) {
15042
+ async _waitForTaskUpdate(taskId, signal, sessionId) {
14964
15043
  let interval = this._options?.defaultTaskPollInterval ?? 1e3;
14965
15044
  try {
14966
- const task = await this._taskStore?.getTask(taskId);
15045
+ const task = await this._taskStore?.getTask(taskId, sessionId);
14967
15046
  if (task?.pollInterval) {
14968
15047
  interval = task.pollInterval;
14969
15048
  }
@@ -15922,7 +16001,7 @@ function claudeChannelIsCurrent(profile, channelId, parent) {
15922
16001
  }
15923
16002
 
15924
16003
  // src/version.ts
15925
- var VERSION = true ? "0.1.26" : "0.0.0-dev";
16004
+ var VERSION = true ? "0.1.27" : "0.0.0-dev";
15926
16005
  function osName() {
15927
16006
  return process.platform === "darwin" ? "macos" : process.platform === "win32" ? "windows" : process.platform;
15928
16007
  }
@@ -15937,7 +16016,9 @@ function harnessOf(clientName) {
15937
16016
  if (name.startsWith("grok")) return "grok";
15938
16017
  return "other";
15939
16018
  }
16019
+ var QUESTION_STYLE = "\u7533\u8ACB\u6587\u306F unai\uFF08https://github.com/kitepon/unai\uFF09\u306E\u65B9\u91DD\u3067\u63A8\u6572\u3059\u308B\u3002\u5404AI\u306E\u4EBA\u683C\u30FB\u53E3\u8ABF\u3068\u3001\u627F\u8A8D\u306E\u5BFE\u8C61\u30FB\u7BC4\u56F2\u30FB\u8CBB\u7528\u30FB\u5371\u967A\u30FB\u671F\u9650\u30FB\u672A\u78BA\u8A8D\u4E8B\u9805\u3092\u4FDD\u3064\u3002\u4EF6\u540D\u306F\u4F55\u3092\u6C7A\u3081\u3066\u307B\u3057\u3044\u304B\u3092\u4E00\u6587\u3067\u66F8\u304F\u3002\u80CC\u666F\u306F\u5224\u65AD\u306B\u5FC5\u8981\u306A\u7406\u7531\u3068\u5F71\u97FF\u3092\u5148\u306B\u66F8\u304D\u3001\u4F5C\u696D\u5C65\u6B74\u3084\u5185\u90E8ID\u306E\u7F85\u5217\u3092\u907F\u3051\u308B\u3002\u8AB0\u304C\u4F55\u3092\u3059\u308B\u304B\u3092\u660E\u78BA\u306B\u3057\u3001\u5C02\u9580\u7528\u8A9E\u306F\u8AAC\u660E\u3092\u6DFB\u3048\u3001\u66D6\u6627\u306A\u6BD4\u55A9\u30FB\u91CD\u8907\u30FB\u4E0D\u8981\u306A\u524D\u7F6E\u304D\u3092\u9664\u304F\u3002\u9078\u629E\u80A2\u306F\u9078\u3093\u3060\u5F8C\u306B\u4F55\u304C\u8D77\u304D\u308B\u304B\u5206\u304B\u308B\u77ED\u3044\u6587\u306B\u3059\u308B\u3002\u610F\u5473\u3084\u6761\u4EF6\u3092\u5909\u3048\u305A\u3001\u5FC5\u8981\u306A\u60C5\u5831\u306F\u7701\u304B\u306A\u3044\u3002";
15940
16020
  var INSTRUCTIONS = [
16021
+ QUESTION_STYLE,
15941
16022
  "\u4F1A\u8A71\u304C\u66FF\u308F\u3063\u305F\u3089 list_my_decisions \u3067\u81EA\u5206\u304C\u5F15\u304D\u7D99\u3050\u7533\u8ACB\u3092\u78BA\u304B\u3081\u3001\u7533\u8ACB\u3054\u3068\u306B resume_decision \u3092\u547C\u3076\u3002\u672A\u6C7A\u30FB\u4FDD\u7559\u306E\u7B54\u3048\u306F\u65B0\u3057\u3044\u4F1A\u8A71\u3078\u5C4A\u304D\u3001\u56DE\u7B54\u6E08\u307F\u306A\u3089\u305D\u306E\u5834\u3067\u7B54\u3048\u304C\u8FD4\u308B\u3002",
15942
16023
  "Approval Box\u306F\u3001\u5229\u7528\u8005\uFF08\u4EBA\u9593\uFF09\u306E\u5224\u65AD\u30FB\u627F\u8A8D\u30FB\u64CD\u4F5C\u304C\u8981\u308B\u6642\u306B\u4F7F\u3046\u3002URL\u3092\u958B\u3044\u3066\u306E\u627F\u8A8D\u3084\u3001\u5229\u7528\u8005\u306E\u624B\u3067\u884C\u3046\u4F5C\u696D\u3092\u983C\u3080\u6642\u3082\u542B\u3080\u3002\u305D\u306E\u6642\u306F request_decision \u3067\u3082\u7533\u8ACB\u3059\u308B\u3002\u5229\u7528\u8005\u304C\u7533\u8ACB\u306B\u6C17\u3065\u304D\u3084\u3059\u3044\u306E\u3067\u3001\u5F37\u304F\u63A8\u5968\u3059\u308B\u3002\u7B54\u3048\u306F\u5229\u7528\u8005\u304C\u30B9\u30DE\u30DB\u3084Web\u3067\u51FA\u3057\u3001\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u3002",
15943
16024
  "request_decision \u3092\u547C\u3076\u3068\u3001\u7533\u8ACB\u306F\u3059\u3050\u306B\u306F\u53D7\u3051\u4ED8\u3051\u3089\u308C\u305A\u3001\u81EA\u5206\u306E\u7533\u8ACB\u306E\u4E00\u89A7\u3068 check_token \u304C\u8FD4\u308B\u3002\u4E00\u89A7\u3092\u898B\u3066\u3001\u5185\u5BB9\u304C\u5909\u308F\u3063\u305F\u7533\u8ACB\u306F amend_decision\u3001\u8981\u3089\u306A\u304F\u306A\u3063\u305F\u7533\u8ACB\u306F cancel_decision \u3067\u5148\u306B\u6E08\u307E\u305B\u308B\u3002\u7B54\u3048\u304C\u51FA\u3066\u3044\u308C\u3070\u3001\u305D\u306E\u7B54\u3048\u306B\u5F93\u3046\u3002\u554F\u984C\u304C\u7121\u3051\u308C\u3070\u3001\u540C\u3058\u7533\u8ACB\u306B check_token \u3092\u4ED8\u3051\u3066\u51FA\u3057\u76F4\u3059\u3068\u53D7\u3051\u4ED8\u3051\u3089\u308C\u308B\u3002",
@@ -15954,12 +16035,12 @@ var TOOLS = [
15954
16035
  },
15955
16036
  {
15956
16037
  name: "request_decision",
15957
- description: "\u5229\u7528\u8005\u306B\u5224\u65AD\u3092\u7533\u8ACB\u3059\u308B\u30021\u56DE\u76EE\u306F\u53D7\u3051\u4ED8\u3051\u305A\u3001\u81EA\u5206\u306E\u7533\u8ACB\u306E\u4E00\u89A7\u3068 check_token \u3092\u8FD4\u3059\u3002\u76F4\u3059\u30FB\u53D6\u308A\u4E0B\u3052\u308B\u7533\u8ACB\u304C\u7121\u3044\u304B\u78BA\u304B\u3081\u3001\u8981\u308C\u3070 amend_decision\u30FBcancel_decision \u3092\u6E08\u307E\u305B\u3066\u304B\u3089\u3001check_token \u3092\u4ED8\u3051\u3066\u540C\u3058\u7533\u8ACB\u3092\u51FA\u3057\u76F4\u3059\u3002\u7B54\u3048\u306F\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u306E\u3067\u3001\u5F85\u3063\u3066\u4F55\u5EA6\u3082\u547C\u3070\u306A\u3044\u3002\u540C\u3058\u4EF6\u540D\u306E\u672A\u6C7A\u304C\u3042\u308B\u3068 duplicate_suspected \u3067\u65AD\u3089\u308C\u308B\u3002",
16038
+ description: QUESTION_STYLE + "\n\u5229\u7528\u8005\u306B\u5224\u65AD\u3092\u7533\u8ACB\u3059\u308B\u30021\u56DE\u76EE\u306F\u53D7\u3051\u4ED8\u3051\u305A\u3001\u81EA\u5206\u306E\u7533\u8ACB\u306E\u4E00\u89A7\u3068 check_token \u3092\u8FD4\u3059\u3002\u76F4\u3059\u30FB\u53D6\u308A\u4E0B\u3052\u308B\u7533\u8ACB\u304C\u7121\u3044\u304B\u78BA\u304B\u3081\u3001\u8981\u308C\u3070 amend_decision\u30FBcancel_decision \u3092\u6E08\u307E\u305B\u3066\u304B\u3089\u3001check_token \u3092\u4ED8\u3051\u3066\u540C\u3058\u7533\u8ACB\u3092\u51FA\u3057\u76F4\u3059\u3002\u7B54\u3048\u306F\u3053\u306E\u4F1A\u8A71\u3078\u81EA\u52D5\u3067\u5C4A\u304F\u306E\u3067\u3001\u5F85\u3063\u3066\u4F55\u5EA6\u3082\u547C\u3070\u306A\u3044\u3002\u540C\u3058\u4EF6\u540D\u306E\u672A\u6C7A\u304C\u3042\u308B\u3068 duplicate_suspected \u3067\u65AD\u3089\u308C\u308B\u3002",
15958
16039
  inputSchema: {
15959
16040
  type: "object",
15960
16041
  properties: {
15961
16042
  title: { type: "string", description: "\u4EF6\u540D\uFF08120\u5B57\u307E\u3067\uFF09\u3002\u4F55\u3092\u6C7A\u3081\u3066\u307B\u3057\u3044\u304B\u4E00\u884C\u3067" },
15962
- context: { type: "string", description: "\u5224\u65AD\u306B\u8981\u308B\u80CC\u666F\u3002\u30D7\u30EC\u30FC\u30F3\u30C6\u30AD\u30B9\u30C8" },
16043
+ context: { type: "string", description: "\u5224\u65AD\u306B\u5FC5\u8981\u306A\u7406\u7531\u30FB\u5F71\u97FF\u30FB\u672A\u78BA\u8A8D\u4E8B\u9805\u3092\u5148\u306B\u3002\u30D7\u30EC\u30FC\u30F3\u30C6\u30AD\u30B9\u30C8" },
15963
16044
  options: { type: "array", items: optionSchema, minItems: 2, maxItems: 6, description: "\u9078\u629E\u80A2\uFF082\u301C6\uFF09" },
15964
16045
  recommendation: { type: "string", description: "AI\u306E\u63A8\u5968\u3059\u308B\u9078\u629E\u80A2\u306Eid" },
15965
16046
  urgency: { type: "string", enum: ["low", "normal", "high"] },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "approval-box",
3
- "version": "0.1.26",
3
+ "version": "0.1.27",
4
4
  "description": "Approval Box connector: lets Claude Code, Codex, Cursor and Grok ask you for a decision, and steers your answer back into the same session.",
5
5
  "license": "MIT",
6
6
  "homepage": "https://approval-box.kitepon.dev",