@tunnelbox/dsh-tunnelbox 0.1.18 → 0.1.20

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 (2) hide show
  1. package/dist/index.mjs +977 -76
  2. package/package.json +2 -2
package/dist/index.mjs CHANGED
@@ -3,10 +3,6 @@
3
3
  // src/index.ts
4
4
  import Schema from "@deepseek-ai/schemastery";
5
5
 
6
- // src/bridge.ts
7
- import { randomBytes as randomBytes2 } from "node:crypto";
8
- import { hostname } from "node:os";
9
-
10
6
  // ../core/dist/index.js
11
7
  import { randomBytes } from "crypto";
12
8
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "fs";
@@ -203,7 +199,7 @@ var zh_CN_default = {
203
199
  "install.scanHint": "\u624B\u673A\u6253\u5F00 tunnelbox App\u300C\u626B\u4E00\u626B\u914D\u5BF9\u300D\uFF0C\u626B\u63CF\u4E0A\u65B9\u4E8C\u7EF4\u7801\u5373\u53EF\u8FDE\u63A5\uFF1A",
204
200
  "pair.heading": "tunnelbox \u624B\u673A\u914D\u5BF9",
205
201
  "pair.howTo": "\u5728\u624B\u673A\u4E0A\u6253\u5F00 tunnelbox App\uFF0C\u7528\u300C\u626B\u4E00\u626B\u914D\u5BF9\u300D\u626B\u63CF\u4E0A\u65B9\u4E8C\u7EF4\u7801\uFF0C\u6216\u624B\u52A8\u8F93\u5165\u914D\u5BF9\u7801\u3002",
206
- "pair.oneTime": "\u914D\u5BF9\u7801\u4E3A\u4E00\u6B21\u6027\uFF0C\u4F7F\u7528\u540E\u5373\u5931\u6548\uFF1B\u5982\u9700\u65B0\u7801\uFF0C\u53EF\u8981\u6C42\u201C\u5237\u65B0\u914D\u5BF9\u7801\u201D\u3002",
202
+ "pair.oneTime": "\u914D\u5BF9\u7801\u4E3A\u4E00\u6B21\u6027\uFF0C\u7EA6 10 \u5206\u949F\u5185\u6709\u6548\uFF1B\u4F7F\u7528\u6216\u8FC7\u671F\u540E\u5373\u5931\u6548\uFF0C\u5982\u9700\u65B0\u7801\u53EF\u8981\u6C42\u201C\u5237\u65B0\u914D\u5BF9\u7801\u201D\u3002",
207
203
  "pair.promptBody": "\u8BF7\u5E2E\u6211\u67E5\u770B\u672C\u673A\u624B\u673A\u8FDC\u7A0B\u914D\u5BF9\u4FE1\u606F\uFF1A\u663E\u793A\u914D\u5BF9\u7801\u4E0E\u53EF\u4F9B\u626B\u7801\u7684\u4E8C\u7EF4\u7801\u3002\u4E8C\u7EF4\u7801\u8BF7\u653E\u5728\u7B49\u5BBD\u4EE3\u7801\u5757\u91CC\u5E76\u9010\u5B57\u539F\u6837\u4FDD\u7559\uFF0C\u65B9\u4FBF\u6211\u7528\u624B\u673A\u626B\u7801\u3002",
208
204
  "pair.promptDescription": "\u663E\u793A\u624B\u673A\u8FDC\u7A0B\u914D\u5BF9\u7684\u914D\u5BF9\u7801\u4E0E\u626B\u7801\u4E8C\u7EF4\u7801",
209
205
  "pair.scanIntro": "**\u626B\u4E00\u626B\u914D\u5BF9**\uFF1A\u624B\u673A\u6253\u5F00 tunnelbox App\u300C\u626B\u4E00\u626B\u914D\u5BF9\u300D\uFF0C\u626B\u63CF\u4E0B\u65B9\u4E8C\u7EF4\u7801\u5373\u53EF\u81EA\u52A8\u8FDE\u63A5\u3002",
@@ -318,7 +314,118 @@ var zh_CN_default = {
318
314
  "hermes.pairTimeout": "\u7533\u8BF7\u914D\u5BF9\u7801\u8D85\u65F6\uFF08\u4E2D\u7EE7\u672A\u54CD\u5E94\uFF09",
319
315
  "hermes.errToolPair": "tunnelbox_pair \u5931\u8D25: {err}",
320
316
  "hermes.errToolStatus": "tunnelbox_status \u5931\u8D25: {err}",
321
- "hermes.cliUsage": "\u7528\u6CD5: /tunnelbox <pair|status>\n pair \u5411\u4E2D\u7EE7\u7533\u8BF7\u624B\u673A\u914D\u5BF9\u7801\u5E76\u6253\u5370\n status \u663E\u793A\u4E2D\u7EE7/\u7ED1\u5B9A/\u8FDE\u63A5\u72B6\u6001"
317
+ "hermes.cliUsage": "\u7528\u6CD5: /tunnelbox <pair|status>\n pair \u5411\u4E2D\u7EE7\u7533\u8BF7\u624B\u673A\u914D\u5BF9\u7801\u5E76\u6253\u5370\n status \u663E\u793A\u4E2D\u7EE7/\u7ED1\u5B9A/\u8FDE\u63A5\u72B6\u6001",
318
+ "qr.validFor": "\u914D\u5BF9\u7801\u7EA6 10 \u5206\u949F\u5185\u6709\u6548\uFF0C\u8FC7\u671F\u8BF7\u5728\u7535\u8111\u7AEF\u91CD\u65B0\u83B7\u53D6\u3002",
319
+ "pair.toolDesc": "\u663E\u793A\u672C\u673A\u7684\u624B\u673A\u914D\u5BF9\u4FE1\u606F\uFF08\u914D\u5BF9\u7801\u4E0E\u53EF\u626B\u63CF\u4E8C\u7EF4\u7801\uFF09\u3002\u5F53\u7528\u6237\u8BE2\u95EE\u914D\u5BF9\u3001\u626B\u63CF\u4E8C\u7EF4\u7801\u6216\u7528\u624B\u673A\u63A7\u5236\u672C\u673A\u65F6\u8C03\u7528\u3002",
320
+ "pair.toolRefreshDesc": "\u662F\u5426\u5411\u4E2D\u7EE7\u7533\u8BF7\u65B0\u7684\u914D\u5BF9\u7801",
321
+ "state.errSaveState": "\u4FDD\u5B58\u72B6\u6001\u5931\u8D25",
322
+ "adapter.logConnected": "\u5DF2\u8FDE\u63A5\u4E2D\u7EE7 {url}",
323
+ "adapter.logDisconnected": "\u4E0E\u4E2D\u7EE7\u65AD\u5F00\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u8FDE\u2026",
324
+ "adapter.logPairCode": "\u751F\u6210\u914D\u5BF9\u7801: {code}",
325
+ "adapter.logClaimed": "\u5DF2\u7ED1\u5B9A\u5230\u624B\u673A\u8D26\u53F7\uFF0C\u4E4B\u540E\u624B\u673A\u4ECE\u300C\u6211\u7684\u7535\u8111\u300D\u76F4\u63A5\u8FDE\u63A5",
326
+ "adapter.logResetIdentity": "\u88AB\u8D26\u53F7\u89E3\u7ED1\uFF0C\u6B63\u5728\u91CD\u7F6E\u8EAB\u4EFD\u5E76\u91CD\u65B0\u751F\u6210\u914D\u5BF9\u7801\u2026",
327
+ "adapter.logUnhandledType": "\u672A\u5904\u7406\u7684\u6D88\u606F\u7C7B\u578B: {type}",
328
+ "adapter.errNoRelay": "\u672A\u914D\u7F6E\u4E2D\u7EE7\u5730\u5740\uFF1A\u6784\u5EFA\u65F6\u7528 --env \u6CE8\u5165\u9ED8\u8BA4\u503C\uFF0C\u6216\u8FD0\u884C\u65F6\u7528 TUNNELBOX_RELAY_URL \u8986\u76D6",
329
+ "adapter.errBusy": "\u8BE5\u4F1A\u8BDD\u6B63\u5728\u751F\u6210\u4E2D\uFF0C\u8BF7\u7B49\u5F85\u5B8C\u6210\u6216\u5148\u505C\u6B62",
330
+ "adapter.errBadWorkspaceEmpty": "\u7F3A\u5C11\u5DE5\u4F5C\u533A\u8DEF\u5F84",
331
+ "adapter.errBadWorkspaceNotDir": "\u8BE5\u76EE\u5F55\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528",
332
+ "adapter.errWorkspaceMissing": "\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728: {dir}",
333
+ "adapter.cmdNew": "\u65B0\u5EFA\u4F1A\u8BDD",
334
+ "adapter.cmdHelp": "\u663E\u793A\u5E2E\u52A9",
335
+ "adapter.helpText": "\u652F\u6301\u7684\u547D\u4EE4\uFF1A\n- /new \u65B0\u5EFA\u4F1A\u8BDD\n- /help \u663E\u793A\u5E2E\u52A9",
336
+ "adapter.newSessionTitle": "\u65B0\u4F1A\u8BDD",
337
+ "install.langHelpTitle": "install-local \u652F\u6301\u8BED\u8A00\uFF08--lang <tag>\uFF09\uFF1A",
338
+ "install.langHelpExample": "\u793A\u4F8B: npm run install-local -- --lang de-DE",
339
+ "install.unknownLang": '\u672A\u77E5\u8BED\u8A00 "{raw}"\uFF0C\u5DF2\u56DE\u9000 en-US\u3002\u652F\u6301\uFF1A{list}',
340
+ "hermes.errAskRequired": "question \u5FC5\u586B",
341
+ "hermes.msgPhoneUnavailable": "\u624B\u673A\u4E0D\u53EF\u7528\u6216\u672A\u5E94\u7B54\uFF1A\u8BF7\u6539\u7528\u5185\u7F6E clarify \u5728\u672C\u673A\u63D0\u95EE\uFF0C\u6216\u81EA\u884C\u5224\u65AD\u7EE7\u7EED\u3002",
342
+ "hermes.errClarifyUnavailable": "clarify \u652F\u6301\u4E0D\u53EF\u7528",
343
+ "hermes.errAskFailed": "tunnelbox_ask \u5931\u8D25: {err}",
344
+ "hermes.errClarifyFailed": "clarify \u5931\u8D25: {err}",
345
+ "bin.denied": "\u624B\u673A\u5DF2\u62D2\u7EDD",
346
+ "bin.timeout": "\u5BA1\u6279\u8D85\u65F6\uFF08fail-closed\uFF09",
347
+ "bin.reqRun": "Claude Code \u8BF7\u6C42\u6267\u884C {tool}",
348
+ "bin.pairTitle": "tunnelbox \u624B\u673A\u914D\u5BF9",
349
+ "bin.pairCodeLine": " \u914D\u5BF9\u7801: {code}",
350
+ "bin.pairHint": "\u6253\u5F00 tunnelbox App\uFF0C\u7528\u300C\u626B\u4E00\u626B\u914D\u5BF9\u300D\u626B\u63CF\u4E8C\u7EF4\u7801\uFF0C\u6216\u624B\u52A8\u8F93\u5165\u914D\u5BF9\u7801\uFF08\u4E00\u6B21\u6027\uFF09\u3002",
351
+ "bin.pairWritten": " \u914D\u5BF9\u4FE1\u606F\u5DF2\u5199\u5165: {path}",
352
+ "bin.pairRequestFailed": "\u5411\u4E2D\u7EE7\u7533\u8BF7\u914D\u5BF9\u7801\u5931\u8D25\u3002",
353
+ "bin.alreadyClaimed": "\u672C\u673A\u5DF2\u7ED1\u5B9A\u624B\u673A\u8D26\u53F7\uFF0C\u53EF\u76F4\u63A5\u5728\u624B\u673A\u300C\u6211\u7684\u7535\u8111\u300D\u91CC\u8FDE\u63A5\uFF1B\u5982\u9700\u91CD\u65B0\u914D\u5BF9\uFF0C\u8BF7\u5148\u5728\u624B\u673A\u7AEF\u89E3\u7ED1\u3002",
354
+ "bin.noRelay": "\u672A\u914D\u7F6E\u4E2D\u7EE7\u5730\u5740\uFF1A\u8BF7\u8BBE\u7F6E\u73AF\u5883\u53D8\u91CF TUNNELBOX_RELAY_URL \u540E\u91CD\u8BD5\u3002",
355
+ "bin.connectFailed": "\u65E0\u6CD5\u8FDE\u63A5\u4E2D\u7EE7\uFF1A{relay}\n\u8BF7\u8BBE\u7F6E TUNNELBOX_RELAY_URL \u6216\u5728\u5B98\u65B9-plugin \u72B6\u6001\u6587\u4EF6\u4E2D\u914D\u7F6E\u3002",
356
+ "bin.statusRelay": "\u4E2D\u7EE7: {value}",
357
+ "bin.statusAgent": "agent \u6807\u8BC6: {value}",
358
+ "bin.statusClaimed": "\u5DF2\u7ED1\u5B9A\u624B\u673A: {value}",
359
+ "bin.statusStateFile": "\u72B6\u6001\u6587\u4EF6: {value}",
360
+ "bin.statusLatest": "\u6700\u65B0\u914D\u5BF9\u4FE1\u606F\uFF1A",
361
+ "bin.usage": "\u7528\u6CD5: tunnelbox <pair|status|ask>",
362
+ "bin.usagePair": " pair \u53D6\u624B\u673A\u914D\u5BF9\u7801\u5E76\u6253\u5370",
363
+ "bin.usageStatus": " status \u663E\u793A\u4E2D\u7EE7/\u7ED1\u5B9A\u72B6\u6001",
364
+ "bin.usageAsk": " ask \u628A\u5DE5\u5177\u5BA1\u6279\u8F6C\u53D1\u5230\u624B\u673A",
365
+ "adapter.logMsgUncaught": "\u6D88\u606F\u5904\u7406\u672A\u6355\u83B7\u5F02\u5E38: {message}",
366
+ "adapter.logHandleFailed": "\u5904\u7406 {type} \u5931\u8D25: {message}",
367
+ "adapter.logPromptFailed": "session.prompt \u5931\u8D25: {message}",
368
+ "adapter.logAbortSent": "\u5DF2\u53D1\u9001\u4E2D\u6B62 (session={session})",
369
+ "adapter.errUserDenied": "\u7528\u6237\u62D2\u7EDD",
370
+ "adapter.logPendingResent": "session.pending \u8865\u53D1\u5F85\u5BA1\u6279 {count} \u6761",
371
+ "adapter.logWorkspaceSwitched": "\u5207\u6362\u5DE5\u4F5C\u533A: {path}",
372
+ "adapter.logNewSession": "\u65B0\u4F1A\u8BDD\u843D\u76D8 codexId={codexId} (alias={session})",
373
+ "adapter.logSessionError": "\u56DE\u5408\u51FA\u9519 (session={session}): {message}",
374
+ "adapter.logDshSent": "\u5DF2\u53D1\u9001\u5230 dsh (session={session})",
375
+ "adapter.logReadHistoryFailed": "\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u5931\u8D25({session}): {message}",
376
+ "adapter.logAnswererInitFailed": "\u5E94\u7B54\u5668\u521D\u59CB\u5316\u5931\u8D25: {message}",
377
+ "adapter.logRemoteMode": "\u53CC\u7AEF\u540C\u663E\u6A21\u5F0F\uFF1A\u9009\u62E9/\u5BA1\u6279\u8D70 typert \u591A\u7AEF\u5E7F\u64AD\uFF0C\u624B\u673A\u4E0E dsh web \u540C\u663E\u3001\u8C01\u7B54\u8C01\u5F97",
378
+ "adapter.logRemoteProbeFailed": "typert \u8FDC\u7A0B\u4E8B\u4EF6\u6E90\u63A2\u6D4B\u5931\u8D25\uFF0C\u56DE\u9000\u672C\u5730\u5E94\u7B54\u6A21\u5F0F: {message}",
379
+ "adapter.logLocalMode": "\u672C\u5730\u5E94\u7B54\u6A21\u5F0F\uFF1A\u9009\u62E9/\u5BA1\u6279\u7531\u624B\u673A\u4F5C\u7B54\uFF08headless\uFF0C\u65E0 dsh web \u5E7F\u64AD\uFF09",
380
+ "adapter.logRemoteStreamInterrupted": "remote events \u6D41\u4E2D\u65AD: {message}",
381
+ "adapter.logResultRejected": "$events/result \u672A\u63A5\u53D7({eventId}): {message}",
382
+ "adapter.logResultBackfillFailed": "$events/result \u56DE\u586B\u5931\u8D25({eventId}): {message}",
383
+ "adapter.logRemoteQuestion": "remote \u63D0\u95EE\u5E7F\u64AD \u2192 \u624B\u673A\u63D0\u95EE\u5361 questionID={id} (session={session})",
384
+ "adapter.errRemoteReadyFrame": "remote events \u9996\u5E27\u5F02\u5E38",
385
+ "adapter.logRemoteApproval": "remote \u5BA1\u6279\u5E7F\u64AD \u2192 \u624B\u673A\u6743\u9650\u5361 permissionID={id} (session={session})",
386
+ "adapter.logUserQuestionRoute": "user-questions \u9009\u62E9 \u2192 \u8DEF\u7531 session={session}",
387
+ "adapter.errDshQuestionEmpty": "dsh \u63D0\u95EE\u5185\u5BB9\u4E3A\u7A7A",
388
+ "adapter.errQuestionTimeout": "\u63D0\u95EE\u8D85\u65F6({seconds}s)\uFF0C\u5DF2\u53D6\u6D88",
389
+ "adapter.errQuestionCancelledAbort": "\u63D0\u95EE\u5DF2\u53D6\u6D88\uFF08agent \u4E2D\u6B62\uFF09",
390
+ "adapter.errQuestionCancelledRelay": "\u4E2D\u7EE7\u4E0D\u53EF\u8FBE\uFF0C\u63D0\u95EE\u5DF2\u53D6\u6D88",
391
+ "adapter.logQuestionToPhone": "user-questions \u9009\u62E9 \u2192 \u53D1\u9001\u5230\u624B\u673A\u63D0\u95EE\u5361 questionID={id} (session={session})",
392
+ "adapter.errQuestionUserCancelled": "\u7528\u6237\u5728\u624B\u673A\u7AEF\u53D6\u6D88/\u62D2\u7EDD\u4E86\u63D0\u95EE",
393
+ "adapter.logApprovalRequest": "\u5BA1\u6279\u8BF7\u6C42(tool={tool}) \u2192 \u53D1\u9001\u5230\u624B\u673A\u6743\u9650\u5361 permissionID={id}",
394
+ "adapter.logAgentPresetFailed": "agentPreset \u89E3\u6790\u5931\u8D25({preset})\uFF0C\u964D\u7EA7\u4E3A\u65E0 preset: {message}",
395
+ "adapter.logSessionLiveAdopted": "\u4F1A\u8BDD {session} \u5DF2\u7531\u672C\u8FDB\u7A0B\u5176\u5B83 agent \u6301\u6709\uFF08live\uFF09\uFF0C\u91C7\u7EB3\u73B0\u6709 agent \u7EE7\u7EED\u9A71\u52A8: {message}",
396
+ "adapter.logDisposeSkipped": "\u5DF2\u91C7\u7EB3\u7684\u5916\u90E8 live agent \u4E0D\u6267\u884C dispose\uFF08\u4F1A\u8BDD {session} \u7531\u539F\u6301\u6709\u8005\u7BA1\u7406\uFF09",
397
+ "adapter.logAgentCreateFailed": "\u521B\u5EFA/\u6062\u590D agent \u5931\u8D25({session}): {message}",
398
+ "adapter.errSessionBusyLive": "\u4F1A\u8BDD {session} \u6B63\u88AB\u5360\u7528\uFF08live\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5",
399
+ "adapter.errAgentsUnavailable": "agents \u670D\u52A1\u4E0D\u53EF\u7528",
400
+ "adapter.logToolReason": "dsh \u8BF7\u6C42\u6267\u884C\u5DE5\u5177 {tool}",
401
+ "adapter.logGatewayConnected": "\u5DF2\u8FDE\u63A5\u672C\u673A OpenClaw Gateway\uFF08{version}\uFF09",
402
+ "adapter.logGatewayDisconnected": "\u4E0E OpenClaw Gateway \u65AD\u5F00\uFF0C\u6B63\u5728\u7531\u5B98\u65B9\u5BA2\u6237\u7AEF\u91CD\u8FDE\u2026",
403
+ "adapter.logGatewayConnectFailed": "\u65E0\u6CD5\u8FDE\u63A5\u672C\u673A OpenClaw Gateway\uFF08\u9996\u6B21\u9700\u5728\u672C\u673A\u653E\u884C\u8BBE\u5907\uFF1A`openclaw devices list` + `openclaw devices approve <requestId>`\uFF09",
404
+ "adapter.errGatewayNoSessionKey": "Gateway \u672A\u8FD4\u56DE\u4F1A\u8BDD key",
405
+ "adapter.logDeleteSessionFailed": "\u5220\u9664\u4F1A\u8BDD\u5931\u8D25({session}): {message}\uFF08\u4ECD\u6309\u5DF2\u5220\u9664\u56DE\u6267\uFF09",
406
+ "adapter.logApprovalReplyFailed": "\u5BA1\u6279\u5E94\u7B54\u5931\u8D25({id}): {message}",
407
+ "adapter.logPendingApproval": "session.pending \u8865\u53D1\u5F85\u5BA1\u6279 {count} \u6761 (session={session})",
408
+ "adapter.workspaceDefault": "\u9ED8\u8BA4",
409
+ "adapter.cursorSessionTitle": "Cursor \u4F1A\u8BDD",
410
+ "adapter.reasonDisconnect": "\u4E2D\u7EE7\u65AD\u5F00\uFF0C\u81EA\u52A8\u62D2\u7EDD\uFF08fail-closed\uFF09",
411
+ "adapter.warnInvalidEnv": "\u5FFD\u7565\u65E0\u6548 {name}: {raw}\uFF08{list}\uFF09",
412
+ "adapter.errStartFailed": "\u542F\u52A8\u5931\u8D25:",
413
+ "adapter.msgStarted": "{name} \u9002\u914D\u5668\u5DF2\u542F\u52A8\uFF08Ctrl+C \u9000\u51FA\uFF09",
414
+ "adapter.warnCliMissing": "\u672A\u627E\u5230\u53EF\u6267\u884C\u6587\u4EF6\u300C{bin}\u300D\uFF1B\u8BF7\u5148\u5B89\u88C5\uFF08\u5982 npm i -g @openai/codex\uFF09\uFF0C\u6216\u7528 TUNNELBOX_CODEX_BIN \u6307\u5B9A\u53EF\u6267\u884C\u6587\u4EF6\u8DEF\u5F84",
415
+ "adapter.errCliNotFound": "\u672A\u627E\u5230 {name} \u53EF\u6267\u884C\u6587\u4EF6\u300C{bin}\u300D\uFF1A\u8BF7\u5B89\u88C5 Codex CLI\uFF08npm i -g @openai/codex\uFF09\u6216\u8BBE\u7F6E TUNNELBOX_CODEX_BIN",
416
+ "adapter.errSessionNotFound": "\u4F1A\u8BDD\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u5220\u9664",
417
+ "adapter.checkHeader": "tunnelbox-codex \u73AF\u5883\u81EA\u68C0",
418
+ "adapter.checkCliOk": "{name} \u53EF\u6267\u884C\u6587\u4EF6: {path}",
419
+ "adapter.checkCliMissing": "\u672A\u627E\u5230 {name} \u53EF\u6267\u884C\u6587\u4EF6\uFF08{bin}\uFF09",
420
+ "bin.yes": "\u662F",
421
+ "bin.no": "\u5426",
422
+ "adapter.errAppServerSpawn": "\u65E0\u6CD5\u542F\u52A8 codex app-server\uFF1A{message}\uFF08\u8BF7\u786E\u8BA4 Codex CLI \u652F\u6301 `codex app-server`\uFF09",
423
+ "adapter.errAppServerExit": "codex app-server \u5DF2\u9000\u51FA\uFF0C\u8FDB\u884C\u4E2D\u7684\u5BA1\u6279/\u9009\u62E9\u5DF2\u81EA\u52A8\u62D2\u7EDD",
424
+ "adapter.logUnsupportedServerRequest": "\u6682\u4E0D\u652F\u6301\u7684 app-server \u8BF7\u6C42: {method}",
425
+ "adapter.logQuestionNative": "\u9009\u62E9\u8BF7\u6C42 \u2192 \u624B\u673A\u9009\u62E9\u5361 questionID={id} (session={session})",
426
+ "adapter.logPermissionNative": "\u5BA1\u6279\u8BF7\u6C42 \u2192 \u624B\u673A\u6743\u9650\u5361 permissionID={id} (session={session})",
427
+ "adapter.checkAppServerOk": "codex app-server \u53EF\u7528",
428
+ "adapter.checkAppServerMissing": "\u5F53\u524D Codex CLI \u4E0D\u652F\u6301 `codex app-server`\uFF08\u8BF7\u5347\u7EA7 Codex CLI\uFF09"
322
429
  };
323
430
  var zh_TW_default = {
324
431
  "agent.err.createSession": "\u5EFA\u7ACB\u6703\u8A71\u5931\u6557",
@@ -369,7 +476,7 @@ var zh_TW_default = {
369
476
  "install.scanHint": "\u624B\u6A5F\u958B\u555F tunnelbox App\u300C\u6383\u63CF\u914D\u5C0D\u300D\uFF0C\u6383\u63CF\u4E0A\u65B9 QR Code \u5373\u53EF\u9023\u63A5\uFF1A",
370
477
  "pair.heading": "tunnelbox \u624B\u6A5F\u914D\u5C0D",
371
478
  "pair.howTo": "\u5728\u624B\u6A5F\u4E0A\u958B\u555F tunnelbox App\uFF0C\u7528\u300C\u6383\u63CF\u914D\u5C0D\u300D\u6383\u63CF\u4E0A\u65B9 QR Code\uFF0C\u6216\u624B\u52D5\u8F38\u5165\u914D\u5C0D\u78BC\u3002",
372
- "pair.oneTime": "\u914D\u5C0D\u78BC\u70BA\u4E00\u6B21\u6027\uFF0C\u4F7F\u7528\u5F8C\u5373\u5931\u6548\uFF1B\u5982\u9700\u65B0\u78BC\uFF0C\u53EF\u8981\u6C42\u300C\u91CD\u65B0\u6574\u7406\u914D\u5C0D\u78BC\u300D\u3002",
479
+ "pair.oneTime": "\u914D\u5C0D\u78BC\u70BA\u4E00\u6B21\u6027\uFF0C\u7D04 10 \u5206\u9418\u5167\u6709\u6548\uFF1B\u4F7F\u7528\u6216\u904E\u671F\u5F8C\u5373\u5931\u6548\uFF0C\u5982\u9700\u65B0\u78BC\u53EF\u8981\u6C42\u300C\u91CD\u65B0\u6574\u7406\u914D\u5C0D\u78BC\u300D\u3002",
373
480
  "pair.promptBody": "\u8ACB\u5E6B\u6211\u67E5\u770B\u672C\u6A5F\u624B\u6A5F\u9060\u7AEF\u914D\u5C0D\u8CC7\u8A0A\uFF1A\u986F\u793A\u914D\u5C0D\u78BC\u8207\u53EF\u4F9B\u6383\u78BC\u7684 QR Code\u3002QR Code \u8ACB\u653E\u5728\u7B49\u5BEC\u7A0B\u5F0F\u78BC\u5340\u584A\u5167\u4E26\u9010\u5B57\u539F\u6A23\u4FDD\u7559\uFF0C\u65B9\u4FBF\u6211\u7528\u624B\u6A5F\u6383\u63CF\u3002",
374
481
  "pair.promptDescription": "\u986F\u793A\u624B\u6A5F\u9060\u7AEF\u914D\u5C0D\u7684\u914D\u5C0D\u78BC\u8207\u6383\u78BC QR Code",
375
482
  "pair.scanIntro": "**\u6383\u78BC\u914D\u5C0D**\uFF1A\u624B\u6A5F\u958B\u555F tunnelbox App\u300C\u6383\u63CF\u914D\u5C0D\u300D\uFF0C\u6383\u63CF\u4E0B\u65B9 QR Code \u5373\u53EF\u81EA\u52D5\u9023\u63A5\u3002",
@@ -484,7 +591,118 @@ var zh_TW_default = {
484
591
  "hermes.pairTimeout": "\u7533\u8ACB\u914D\u5C0D\u78BC\u903E\u6642\uFF08\u4E2D\u7E7C\u672A\u56DE\u61C9\uFF09",
485
592
  "hermes.errToolPair": "tunnelbox_pair \u5931\u6557: {err}",
486
593
  "hermes.errToolStatus": "tunnelbox_status \u5931\u6557: {err}",
487
- "hermes.cliUsage": "\u7528\u6CD5: /tunnelbox <pair|status>\n pair \u5411\u4E2D\u7E7C\u7533\u8ACB\u624B\u6A5F\u914D\u5C0D\u78BC\u4E26\u5217\u5370\n status \u986F\u793A\u4E2D\u7E7C/\u7D81\u5B9A/\u9023\u7DDA\u72C0\u614B"
594
+ "hermes.cliUsage": "\u7528\u6CD5: /tunnelbox <pair|status>\n pair \u5411\u4E2D\u7E7C\u7533\u8ACB\u624B\u6A5F\u914D\u5C0D\u78BC\u4E26\u5217\u5370\n status \u986F\u793A\u4E2D\u7E7C/\u7D81\u5B9A/\u9023\u7DDA\u72C0\u614B",
595
+ "qr.validFor": "\u914D\u5C0D\u78BC\u7D04 10 \u5206\u9418\u5167\u6709\u6548\uFF0C\u904E\u671F\u8ACB\u5728\u96FB\u8166\u7AEF\u91CD\u65B0\u53D6\u5F97\u3002",
596
+ "pair.toolDesc": "\u986F\u793A\u672C\u6A5F\u7684\u624B\u6A5F\u914D\u5C0D\u8CC7\u8A0A\uFF08\u914D\u5C0D\u78BC\u8207\u53EF\u6383\u63CF QR code\uFF09\u3002\u7576\u4F7F\u7528\u8005\u8A62\u554F\u914D\u5C0D\u3001\u6383\u63CF QR code \u6216\u7528\u624B\u6A5F\u63A7\u5236\u672C\u6A5F\u6642\u547C\u53EB\u3002",
597
+ "pair.toolRefreshDesc": "\u662F\u5426\u5411\u4E2D\u7E7C\u7533\u8ACB\u65B0\u7684\u914D\u5C0D\u78BC",
598
+ "state.errSaveState": "\u5132\u5B58\u72C0\u614B\u5931\u6557",
599
+ "adapter.logConnected": "\u5DF2\u9023\u63A5\u4E2D\u7E7C {url}",
600
+ "adapter.logDisconnected": "\u8207\u4E2D\u7E7C\u65B7\u958B\uFF0C\u6B63\u5728\u81EA\u52D5\u91CD\u9023\u2026",
601
+ "adapter.logPairCode": "\u7522\u751F\u914D\u5C0D\u78BC: {code}",
602
+ "adapter.logClaimed": "\u5DF2\u7D81\u5B9A\u5230\u624B\u6A5F\u5E33\u865F\uFF0C\u4E4B\u5F8C\u624B\u6A5F\u5F9E\u300C\u6211\u7684\u96FB\u8166\u300D\u76F4\u63A5\u9023\u63A5",
603
+ "adapter.logResetIdentity": "\u88AB\u5E33\u865F\u89E3\u7D81\uFF0C\u6B63\u5728\u91CD\u8A2D\u8EAB\u5206\u4E26\u91CD\u65B0\u7522\u751F\u914D\u5C0D\u78BC\u2026",
604
+ "adapter.logUnhandledType": "\u672A\u8655\u7406\u7684\u8A0A\u606F\u985E\u578B: {type}",
605
+ "adapter.errNoRelay": "\u672A\u8A2D\u5B9A\u4E2D\u7E7C\u4F4D\u5740\uFF1A\u5EFA\u7F6E\u6642\u7528 --env \u6CE8\u5165\u9810\u8A2D\u503C\uFF0C\u6216\u57F7\u884C\u6642\u7528 TUNNELBOX_RELAY_URL \u8986\u5BEB",
606
+ "adapter.errBusy": "\u8A72\u5DE5\u4F5C\u968E\u6BB5\u6B63\u5728\u751F\u6210\u4E2D\uFF0C\u8ACB\u7B49\u5F85\u5B8C\u6210\u6216\u5148\u505C\u6B62",
607
+ "adapter.errBadWorkspaceEmpty": "\u7F3A\u5C11\u5DE5\u4F5C\u5340\u8DEF\u5F91",
608
+ "adapter.errBadWorkspaceNotDir": "\u8A72\u76EE\u9304\u4E0D\u5B58\u5728\u6216\u4E0D\u53EF\u7528",
609
+ "adapter.errWorkspaceMissing": "\u5DE5\u4F5C\u5340\u4E0D\u5B58\u5728: {dir}",
610
+ "adapter.cmdNew": "\u65B0\u5EFA\u5DE5\u4F5C\u968E\u6BB5",
611
+ "adapter.cmdHelp": "\u986F\u793A\u8AAA\u660E",
612
+ "adapter.helpText": "\u652F\u63F4\u7684\u547D\u4EE4\uFF1A\n- /new \u65B0\u5EFA\u5DE5\u4F5C\u968E\u6BB5\n- /help \u986F\u793A\u8AAA\u660E",
613
+ "adapter.newSessionTitle": "\u65B0\u5DE5\u4F5C\u968E\u6BB5",
614
+ "install.langHelpTitle": "install-local \u652F\u63F4\u8A9E\u8A00\uFF08--lang <tag>\uFF09\uFF1A",
615
+ "install.langHelpExample": "\u7BC4\u4F8B: npm run install-local -- --lang de-DE",
616
+ "install.unknownLang": '\u672A\u77E5\u8A9E\u8A00 "{raw}"\uFF0C\u5DF2\u56DE\u9000 en-US\u3002\u652F\u63F4\uFF1A{list}',
617
+ "hermes.errAskRequired": "question \u5FC5\u586B",
618
+ "hermes.msgPhoneUnavailable": "\u624B\u6A5F\u4E0D\u53EF\u7528\u6216\u672A\u56DE\u61C9\uFF1A\u8ACB\u6539\u7528\u5167\u5EFA clarify \u5728\u672C\u6A5F\u63D0\u554F\uFF0C\u6216\u81EA\u884C\u5224\u65B7\u7E7C\u7E8C\u3002",
619
+ "hermes.errClarifyUnavailable": "clarify \u652F\u63F4\u4E0D\u53EF\u7528",
620
+ "hermes.errAskFailed": "tunnelbox_ask \u5931\u6557: {err}",
621
+ "hermes.errClarifyFailed": "clarify \u5931\u6557: {err}",
622
+ "bin.denied": "\u624B\u6A5F\u5DF2\u62D2\u7D55",
623
+ "bin.timeout": "\u5BE9\u6279\u903E\u6642\uFF08fail-closed\uFF09",
624
+ "bin.reqRun": "Claude Code \u8ACB\u6C42\u57F7\u884C {tool}",
625
+ "bin.pairTitle": "tunnelbox \u624B\u6A5F\u914D\u5C0D",
626
+ "bin.pairCodeLine": " \u914D\u5C0D\u78BC: {code}",
627
+ "bin.pairHint": "\u6253\u958B tunnelbox App\uFF0C\u7528\u300C\u6383\u4E00\u6383\u914D\u5C0D\u300D\u6383\u63CF QR code\uFF0C\u6216\u624B\u52D5\u8F38\u5165\u914D\u5C0D\u78BC\uFF08\u4E00\u6B21\u6027\uFF09\u3002",
628
+ "bin.pairWritten": " \u914D\u5C0D\u8CC7\u8A0A\u5DF2\u5BEB\u5165: {path}",
629
+ "bin.pairRequestFailed": "\u5411\u4E2D\u7E7C\u7533\u8ACB\u914D\u5C0D\u78BC\u5931\u6557\u3002",
630
+ "bin.alreadyClaimed": "\u672C\u6A5F\u5DF2\u7D81\u5B9A\u624B\u6A5F\u5E33\u865F\uFF0C\u53EF\u76F4\u63A5\u5728\u624B\u6A5F\u300C\u6211\u7684\u96FB\u8166\u300D\u88E1\u9023\u63A5\uFF1B\u5982\u9700\u91CD\u65B0\u914D\u5C0D\uFF0C\u8ACB\u5148\u5728\u624B\u6A5F\u7AEF\u89E3\u7D81\u3002",
631
+ "bin.noRelay": "\u672A\u8A2D\u5B9A\u4E2D\u7E7C\u4F4D\u5740\uFF1A\u8ACB\u8A2D\u5B9A\u74B0\u5883\u8B8A\u6578 TUNNELBOX_RELAY_URL \u5F8C\u91CD\u8A66\u3002",
632
+ "bin.connectFailed": "\u7121\u6CD5\u9023\u63A5\u4E2D\u7E7C\uFF1A{relay}\n\u8ACB\u8A2D\u5B9A TUNNELBOX_RELAY_URL \u6216\u5728\u5B98\u65B9-plugin \u72C0\u614B\u6A94\u6848\u4E2D\u8A2D\u5B9A\u3002",
633
+ "bin.statusRelay": "\u4E2D\u7E7C: {value}",
634
+ "bin.statusAgent": "agent \u8B58\u5225\u78BC: {value}",
635
+ "bin.statusClaimed": "\u5DF2\u7D81\u5B9A\u624B\u6A5F: {value}",
636
+ "bin.statusStateFile": "\u72C0\u614B\u6A94\u6848: {value}",
637
+ "bin.statusLatest": "\u6700\u65B0\u914D\u5C0D\u8CC7\u8A0A\uFF1A",
638
+ "bin.usage": "\u7528\u6CD5: tunnelbox <pair|status|ask>",
639
+ "bin.usagePair": " pair \u53D6\u624B\u6A5F\u914D\u5C0D\u78BC\u4E26\u5217\u5370",
640
+ "bin.usageStatus": " status \u986F\u793A\u4E2D\u7E7C/\u7D81\u5B9A\u72C0\u614B",
641
+ "bin.usageAsk": " ask \u628A\u5DE5\u5177\u5BE9\u6279\u8F49\u767C\u5230\u624B\u6A5F",
642
+ "adapter.logMsgUncaught": "\u8A0A\u606F\u8655\u7406\u672A\u6355\u6349\u4F8B\u5916: {message}",
643
+ "adapter.logHandleFailed": "\u8655\u7406 {type} \u5931\u6557: {message}",
644
+ "adapter.logPromptFailed": "session.prompt \u5931\u6557: {message}",
645
+ "adapter.logAbortSent": "\u5DF2\u767C\u9001\u4E2D\u6B62 (session={session})",
646
+ "adapter.errUserDenied": "\u4F7F\u7528\u8005\u62D2\u7D55",
647
+ "adapter.logPendingResent": "session.pending \u88DC\u767C\u5F85\u5BE9\u6279 {count} \u689D",
648
+ "adapter.logWorkspaceSwitched": "\u5207\u63DB\u5DE5\u4F5C\u5340: {path}",
649
+ "adapter.logNewSession": "\u65B0\u5DE5\u4F5C\u968E\u6BB5\u843D\u76E4 codexId={codexId} (alias={session})",
650
+ "adapter.logSessionError": "\u56DE\u5408\u51FA\u932F (session={session}): {message}",
651
+ "adapter.logDshSent": "\u5DF2\u767C\u9001\u5230 dsh (session={session})",
652
+ "adapter.logReadHistoryFailed": "\u8B80\u53D6\u5DE5\u4F5C\u968E\u6BB5\u6B77\u53F2\u5931\u6557({session}): {message}",
653
+ "adapter.logAnswererInitFailed": "\u61C9\u7B54\u5668\u521D\u59CB\u5316\u5931\u6557: {message}",
654
+ "adapter.logRemoteMode": "\u96D9\u7AEF\u540C\u986F\u6A21\u5F0F\uFF1A\u9078\u64C7/\u5BE9\u6279\u8D70 typert \u591A\u7AEF\u5EE3\u64AD\uFF0C\u624B\u6A5F\u8207 dsh web \u540C\u986F\u3001\u8AB0\u7B54\u8AB0\u5F97",
655
+ "adapter.logRemoteProbeFailed": "typert \u9060\u7AEF\u4E8B\u4EF6\u6E90\u63A2\u6E2C\u5931\u6557\uFF0C\u56DE\u9000\u672C\u5730\u61C9\u7B54\u6A21\u5F0F: {message}",
656
+ "adapter.logLocalMode": "\u672C\u5730\u61C9\u7B54\u6A21\u5F0F\uFF1A\u9078\u64C7/\u5BE9\u6279\u7531\u624B\u6A5F\u4F5C\u7B54\uFF08headless\uFF0C\u7121 dsh web \u5EE3\u64AD\uFF09",
657
+ "adapter.logRemoteStreamInterrupted": "remote events \u4E32\u6D41\u4E2D\u65B7: {message}",
658
+ "adapter.logResultRejected": "$events/result \u672A\u63A5\u53D7({eventId}): {message}",
659
+ "adapter.logResultBackfillFailed": "$events/result \u56DE\u586B\u5931\u6557({eventId}): {message}",
660
+ "adapter.logRemoteQuestion": "remote \u63D0\u554F\u5EE3\u64AD \u2192 \u624B\u6A5F\u63D0\u554F\u5361 questionID={id} (session={session})",
661
+ "adapter.errRemoteReadyFrame": "remote events \u9996\u5E40\u7570\u5E38",
662
+ "adapter.logRemoteApproval": "remote \u5BE9\u6279\u5EE3\u64AD \u2192 \u624B\u6A5F\u6B0A\u9650\u5361 permissionID={id} (session={session})",
663
+ "adapter.logUserQuestionRoute": "user-questions \u9078\u64C7 \u2192 \u8DEF\u7531 session={session}",
664
+ "adapter.errDshQuestionEmpty": "dsh \u63D0\u554F\u5167\u5BB9\u70BA\u7A7A",
665
+ "adapter.errQuestionTimeout": "\u63D0\u554F\u903E\u6642({seconds}s)\uFF0C\u5DF2\u53D6\u6D88",
666
+ "adapter.errQuestionCancelledAbort": "\u63D0\u554F\u5DF2\u53D6\u6D88\uFF08agent \u4E2D\u6B62\uFF09",
667
+ "adapter.errQuestionCancelledRelay": "\u4E2D\u7E7C\u4E0D\u53EF\u9054\uFF0C\u63D0\u554F\u5DF2\u53D6\u6D88",
668
+ "adapter.logQuestionToPhone": "user-questions \u9078\u64C7 \u2192 \u767C\u9001\u5230\u624B\u6A5F\u63D0\u554F\u5361 questionID={id} (session={session})",
669
+ "adapter.errQuestionUserCancelled": "\u4F7F\u7528\u8005\u5728\u624B\u6A5F\u7AEF\u53D6\u6D88/\u62D2\u7D55\u4E86\u63D0\u554F",
670
+ "adapter.logApprovalRequest": "\u5BE9\u6279\u8ACB\u6C42(tool={tool}) \u2192 \u767C\u9001\u5230\u624B\u6A5F\u6B0A\u9650\u5361 permissionID={id}",
671
+ "adapter.logAgentPresetFailed": "agentPreset \u89E3\u6790\u5931\u6557({preset})\uFF0C\u964D\u7D1A\u70BA\u7121 preset: {message}",
672
+ "adapter.logSessionLiveAdopted": "\u5DE5\u4F5C\u968E\u6BB5 {session} \u5DF2\u7531\u672C\u884C\u7A0B\u5176\u5B83 agent \u6301\u6709\uFF08live\uFF09\uFF0C\u63A1\u7D0D\u73FE\u6709 agent \u7E7C\u7E8C\u9A45\u52D5: {message}",
673
+ "adapter.logDisposeSkipped": "\u5DF2\u63A1\u7D0D\u7684\u5916\u90E8 live agent \u4E0D\u57F7\u884C dispose\uFF08\u5DE5\u4F5C\u968E\u6BB5 {session} \u7531\u539F\u6301\u6709\u8005\u7BA1\u7406\uFF09",
674
+ "adapter.logAgentCreateFailed": "\u5EFA\u7ACB/\u6062\u5FA9 agent \u5931\u6557({session}): {message}",
675
+ "adapter.errSessionBusyLive": "\u5DE5\u4F5C\u968E\u6BB5 {session} \u6B63\u88AB\u4F54\u7528\uFF08live\uFF09\uFF0C\u8ACB\u7A0D\u5F8C\u91CD\u8A66",
676
+ "adapter.errAgentsUnavailable": "agents \u670D\u52D9\u4E0D\u53EF\u7528",
677
+ "adapter.logToolReason": "dsh \u8ACB\u6C42\u57F7\u884C\u5DE5\u5177 {tool}",
678
+ "adapter.logGatewayConnected": "\u5DF2\u9023\u63A5\u672C\u6A5F OpenClaw Gateway\uFF08{version}\uFF09",
679
+ "adapter.logGatewayDisconnected": "\u8207 OpenClaw Gateway \u65B7\u958B\uFF0C\u6B63\u5728\u7531\u5B98\u65B9\u5BA2\u6236\u7AEF\u91CD\u9023\u2026",
680
+ "adapter.logGatewayConnectFailed": "\u7121\u6CD5\u9023\u63A5\u672C\u6A5F OpenClaw Gateway\uFF08\u9996\u6B21\u9700\u5728\u672C\u6A5F\u653E\u884C\u88DD\u7F6E\uFF1A`openclaw devices list` + `openclaw devices approve <requestId>`\uFF09",
681
+ "adapter.errGatewayNoSessionKey": "Gateway \u672A\u8FD4\u56DE\u5DE5\u4F5C\u968E\u6BB5 key",
682
+ "adapter.logDeleteSessionFailed": "\u522A\u9664\u5DE5\u4F5C\u968E\u6BB5\u5931\u6557({session}): {message}\uFF08\u4ECD\u6309\u5DF2\u522A\u9664\u56DE\u57F7\uFF09",
683
+ "adapter.logApprovalReplyFailed": "\u5BE9\u6279\u61C9\u7B54\u5931\u6557({id}): {message}",
684
+ "adapter.logPendingApproval": "session.pending \u88DC\u767C\u5F85\u5BE9\u6279 {count} \u689D (session={session})",
685
+ "adapter.workspaceDefault": "\u9810\u8A2D",
686
+ "adapter.cursorSessionTitle": "Cursor \u5DE5\u4F5C\u968E\u6BB5",
687
+ "adapter.reasonDisconnect": "\u4E2D\u7E7C\u65B7\u958B\uFF0C\u81EA\u52D5\u62D2\u7D55\uFF08fail-closed\uFF09",
688
+ "adapter.warnInvalidEnv": "\u5FFD\u7565\u7121\u6548 {name}: {raw}\uFF08{list}\uFF09",
689
+ "adapter.errStartFailed": "\u555F\u52D5\u5931\u6557:",
690
+ "adapter.msgStarted": "{name} \u9069\u914D\u5668\u5DF2\u555F\u52D5\uFF08Ctrl+C \u9000\u51FA\uFF09",
691
+ "adapter.warnCliMissing": "\u672A\u627E\u5230\u57F7\u884C\u6A94\u300C{bin}\u300D\uFF1B\u8ACB\u5148\u5B89\u88DD\uFF08\u5982 npm i -g @openai/codex\uFF09\uFF0C\u6216\u7528 TUNNELBOX_CODEX_BIN \u6307\u5B9A\u57F7\u884C\u6A94\u8DEF\u5F91",
692
+ "adapter.errCliNotFound": "\u672A\u627E\u5230 {name} \u57F7\u884C\u6A94\u300C{bin}\u300D\uFF1A\u8ACB\u5B89\u88DD Codex CLI\uFF08npm i -g @openai/codex\uFF09\u6216\u8A2D\u5B9A TUNNELBOX_CODEX_BIN",
693
+ "adapter.errSessionNotFound": "\u6703\u8A71\u4E0D\u5B58\u5728\u6216\u5DF2\u88AB\u522A\u9664",
694
+ "adapter.checkHeader": "tunnelbox-codex \u74B0\u5883\u81EA\u6AA2",
695
+ "adapter.checkCliOk": "{name} \u57F7\u884C\u6A94: {path}",
696
+ "adapter.checkCliMissing": "\u672A\u627E\u5230 {name} \u57F7\u884C\u6A94\uFF08{bin}\uFF09",
697
+ "bin.yes": "\u662F",
698
+ "bin.no": "\u5426",
699
+ "adapter.errAppServerSpawn": "\u7121\u6CD5\u555F\u52D5 codex app-server\uFF1A{message}\uFF08\u8ACB\u78BA\u8A8D Codex CLI \u652F\u63F4 `codex app-server`\uFF09",
700
+ "adapter.errAppServerExit": "codex app-server \u5DF2\u7D50\u675F\uFF0C\u9032\u884C\u4E2D\u7684\u5BE9\u6279/\u9078\u64C7\u5DF2\u81EA\u52D5\u62D2\u7D55",
701
+ "adapter.logUnsupportedServerRequest": "\u66AB\u4E0D\u652F\u63F4\u7684 app-server \u8ACB\u6C42: {method}",
702
+ "adapter.logQuestionNative": "\u9078\u64C7\u8ACB\u6C42 \u2192 \u624B\u6A5F\u9078\u64C7\u5361 questionID={id} (session={session})",
703
+ "adapter.logPermissionNative": "\u5BE9\u6279\u8ACB\u6C42 \u2192 \u624B\u6A5F\u6B0A\u9650\u5361 permissionID={id} (session={session})",
704
+ "adapter.checkAppServerOk": "codex app-server \u53EF\u7528",
705
+ "adapter.checkAppServerMissing": "\u76EE\u524D Codex CLI \u4E0D\u652F\u63F4 `codex app-server`\uFF08\u8ACB\u5347\u7D1A Codex CLI\uFF09"
488
706
  };
489
707
  var en_US_default = {
490
708
  "agent.err.createSession": "Failed to create session",
@@ -535,7 +753,7 @@ var en_US_default = {
535
753
  "install.scanHint": "Open tunnelbox on your phone, tap \u201CScan to pair\u201D, and scan the QR code above to connect:",
536
754
  "pair.heading": "tunnelbox phone pairing",
537
755
  "pair.howTo": "Open the tunnelbox app on your phone and scan the QR code above with \u201CScan to pair\u201D, or enter the pairing code manually.",
538
- "pair.oneTime": "The pairing code is single-use and invalidates after it is claimed; ask to \u201Crefresh the pairing code\u201D for a new one.",
756
+ "pair.oneTime": "The pairing code is single-use and valid for about 10 minutes; it stops working once claimed or expired. Ask to \u201Crefresh the pairing code\u201D for a new one.",
539
757
  "pair.promptBody": "Please show this computer's phone pairing info: the pairing code and a QR code I can scan. Keep the QR code inside a monospaced code block and reproduce it character-for-character so my phone can scan it.",
540
758
  "pair.promptDescription": "Show the phone pairing code and scan-able QR code",
541
759
  "pair.scanIntro": "**Pair by scanning**: open the tunnelbox app on your phone, tap \u201CScan to pair\u201D, and scan the QR code below to connect automatically.",
@@ -650,7 +868,118 @@ var en_US_default = {
650
868
  "hermes.pairTimeout": "Timed out requesting a pairing code (relay did not respond)",
651
869
  "hermes.errToolPair": "tunnelbox_pair failed: {err}",
652
870
  "hermes.errToolStatus": "tunnelbox_status failed: {err}",
653
- "hermes.cliUsage": "Usage: /tunnelbox <pair|status>\n pair request and print a phone pairing code\n status show relay/binding/connection status"
871
+ "hermes.cliUsage": "Usage: /tunnelbox <pair|status>\n pair request and print a phone pairing code\n status show relay/binding/connection status",
872
+ "qr.validFor": "The pairing code is valid for about 10 minutes; get a new one on your computer if it expires.",
873
+ "pair.toolDesc": "Show this computer's opencode phone pairing info (pairing code and a scan-able QR code). Call when the user asks about pairing, scanning a QR code, or controlling this computer from their phone.",
874
+ "pair.toolRefreshDesc": "Whether to request a new pairing code from the relay",
875
+ "state.errSaveState": "Failed to save state",
876
+ "adapter.logConnected": "Connected to relay {url}",
877
+ "adapter.logDisconnected": "Disconnected from relay, reconnecting automatically\u2026",
878
+ "adapter.logPairCode": "Generated pairing code: {code}",
879
+ "adapter.logClaimed": "Bound to your phone account. From now on the phone connects directly from My Computers",
880
+ "adapter.logResetIdentity": "Unbound from the account; resetting identity and generating a new pairing code\u2026",
881
+ "adapter.logUnhandledType": "Unhandled message type: {type}",
882
+ "adapter.errNoRelay": "No relay URL configured: build with --env to inject a default, or override at runtime with TUNNELBOX_RELAY_URL",
883
+ "adapter.errBusy": "This session is still running; wait for it to finish or stop it first",
884
+ "adapter.errBadWorkspaceEmpty": "Missing workspace path",
885
+ "adapter.errBadWorkspaceNotDir": "Directory does not exist or is unusable",
886
+ "adapter.errWorkspaceMissing": "Workspace does not exist: {dir}",
887
+ "adapter.cmdNew": "New session",
888
+ "adapter.cmdHelp": "Show help",
889
+ "adapter.helpText": "Supported commands:\n- /new new session\n- /help show help",
890
+ "adapter.newSessionTitle": "New session",
891
+ "install.langHelpTitle": "install-local supported languages (--lang <tag>):",
892
+ "install.langHelpExample": "Example: npm run install-local -- --lang de-DE",
893
+ "install.unknownLang": 'Unknown language "{raw}", falling back to en-US. Supported: {list}',
894
+ "hermes.errAskRequired": "question is required",
895
+ "hermes.msgPhoneUnavailable": "Phone unavailable or no response: use the built-in clarify to ask locally, or decide on your own.",
896
+ "hermes.errClarifyUnavailable": "clarify support unavailable",
897
+ "hermes.errAskFailed": "tunnelbox_ask failed: {err}",
898
+ "hermes.errClarifyFailed": "clarify failed: {err}",
899
+ "bin.denied": "Rejected from your phone",
900
+ "bin.timeout": "Approval timed out (fail-closed)",
901
+ "bin.reqRun": "Claude Code requests to run {tool}",
902
+ "bin.pairTitle": "tunnelbox phone pairing",
903
+ "bin.pairCodeLine": " Pairing code: {code}",
904
+ "bin.pairHint": "Open the tunnelbox app, tap \u201CScan to pair\u201D and scan the QR code, or enter the pairing code manually (single-use).",
905
+ "bin.pairWritten": " Pairing info written to: {path}",
906
+ "bin.pairRequestFailed": "Failed to request a pairing code from the relay.",
907
+ "bin.alreadyClaimed": "This computer is already bound to a phone account; connect directly from \u201CMy Computers\u201D. To re-pair, unbind it on your phone first.",
908
+ "bin.noRelay": "No relay URL configured: set TUNNELBOX_RELAY_URL and try again.",
909
+ "bin.connectFailed": "Cannot connect to the relay: {relay}\nSet TUNNELBOX_RELAY_URL or configure it in the official-plugin state file.",
910
+ "bin.statusRelay": "Relay: {value}",
911
+ "bin.statusAgent": "Agent ID: {value}",
912
+ "bin.statusClaimed": "Phone bound: {value}",
913
+ "bin.statusStateFile": "State file: {value}",
914
+ "bin.statusLatest": "Latest pairing info:",
915
+ "bin.usage": "Usage: tunnelbox <pair|status|ask>",
916
+ "bin.usagePair": " pair request and print a phone pairing code",
917
+ "bin.usageStatus": " status show relay/binding status",
918
+ "bin.usageAsk": " ask forward a tool approval to the phone",
919
+ "adapter.logMsgUncaught": "Uncaught exception while handling message: {message}",
920
+ "adapter.logHandleFailed": "Failed to handle {type}: {message}",
921
+ "adapter.logPromptFailed": "session.prompt failed: {message}",
922
+ "adapter.logAbortSent": "Abort sent (session={session})",
923
+ "adapter.errUserDenied": "Rejected by user",
924
+ "adapter.logPendingResent": "session.pending: resent {count} pending request(s)",
925
+ "adapter.logWorkspaceSwitched": "Switched workspace: {path}",
926
+ "adapter.logNewSession": "New session persisted codexId={codexId} (alias={session})",
927
+ "adapter.logSessionError": "Turn error (session={session}): {message}",
928
+ "adapter.logDshSent": "Sent to dsh (session={session})",
929
+ "adapter.logReadHistoryFailed": "Failed to read session history ({session}): {message}",
930
+ "adapter.logAnswererInitFailed": "Answerer initialization failed: {message}",
931
+ "adapter.logRemoteMode": "Dual-display mode: selections/approvals use typert multi-client broadcast; phone and dsh web share the view, first answer wins",
932
+ "adapter.logRemoteProbeFailed": "typert remote event source probe failed; falling back to local answering mode: {message}",
933
+ "adapter.logLocalMode": "Local answering mode: selections/approvals answered by the phone (headless, no dsh web broadcast)",
934
+ "adapter.logRemoteStreamInterrupted": "remote events stream interrupted: {message}",
935
+ "adapter.logResultRejected": "$events/result not accepted ({eventId}): {message}",
936
+ "adapter.logResultBackfillFailed": "$events/result backfill failed ({eventId}): {message}",
937
+ "adapter.logRemoteQuestion": "remote question broadcast \u2192 phone question card questionID={id} (session={session})",
938
+ "adapter.errRemoteReadyFrame": "Unexpected remote events first frame",
939
+ "adapter.logRemoteApproval": "remote approval broadcast \u2192 phone permission card permissionID={id} (session={session})",
940
+ "adapter.logUserQuestionRoute": "user-questions selection \u2192 routed to session={session}",
941
+ "adapter.errDshQuestionEmpty": "dsh question content is empty",
942
+ "adapter.errQuestionTimeout": "Question timed out ({seconds}s), cancelled",
943
+ "adapter.errQuestionCancelledAbort": "Question cancelled (agent aborted)",
944
+ "adapter.errQuestionCancelledRelay": "Relay unreachable, question cancelled",
945
+ "adapter.logQuestionToPhone": "user-questions selection \u2192 sent to phone question card questionID={id} (session={session})",
946
+ "adapter.errQuestionUserCancelled": "User cancelled/rejected the question on the phone",
947
+ "adapter.logApprovalRequest": "Approval request (tool={tool}) \u2192 sent to phone permission card permissionID={id}",
948
+ "adapter.logAgentPresetFailed": "agentPreset resolution failed ({preset}); falling back to no preset: {message}",
949
+ "adapter.logSessionLiveAdopted": "Session {session} is already held by another agent in this process (live); adopting the existing agent to continue: {message}",
950
+ "adapter.logDisposeSkipped": "Adopted external live agent does not run dispose (session {session} is managed by its original holder)",
951
+ "adapter.logAgentCreateFailed": "Failed to create/resume agent ({session}): {message}",
952
+ "adapter.errSessionBusyLive": "Session {session} is busy (live); try again later",
953
+ "adapter.errAgentsUnavailable": "agents service unavailable",
954
+ "adapter.logToolReason": "dsh requests to run tool {tool}",
955
+ "adapter.logGatewayConnected": "Connected to local OpenClaw Gateway ({version})",
956
+ "adapter.logGatewayDisconnected": "Disconnected from OpenClaw Gateway; the official client is reconnecting\u2026",
957
+ "adapter.logGatewayConnectFailed": "Cannot connect to local OpenClaw Gateway (first time, approve the device locally: `openclaw devices list` + `openclaw devices approve <requestId>`)",
958
+ "adapter.errGatewayNoSessionKey": "Gateway did not return a session key",
959
+ "adapter.logDeleteSessionFailed": "Failed to delete session ({session}): {message} (still acking as deleted)",
960
+ "adapter.logApprovalReplyFailed": "Approval reply failed ({id}): {message}",
961
+ "adapter.logPendingApproval": "session.pending: resent {count} pending approval(s) (session={session})",
962
+ "adapter.workspaceDefault": "Default",
963
+ "adapter.cursorSessionTitle": "Cursor session",
964
+ "adapter.reasonDisconnect": "Relay disconnected, auto-rejecting (fail-closed)",
965
+ "adapter.warnInvalidEnv": "Ignoring invalid {name}: {raw} ({list})",
966
+ "adapter.errStartFailed": "Failed to start:",
967
+ "adapter.msgStarted": "{name} adapter started (Ctrl+C to quit)",
968
+ "adapter.warnCliMissing": 'Executable "{bin}" not found; install it (e.g. npm i -g @openai/codex) or set TUNNELBOX_CODEX_BIN to its path',
969
+ "adapter.errCliNotFound": '{name} executable "{bin}" not found: install the Codex CLI (npm i -g @openai/codex) or set TUNNELBOX_CODEX_BIN',
970
+ "adapter.errSessionNotFound": "Session not found or already deleted",
971
+ "adapter.checkHeader": "tunnelbox-codex environment check",
972
+ "adapter.checkCliOk": "{name} executable: {path}",
973
+ "adapter.checkCliMissing": "{name} executable not found ({bin})",
974
+ "bin.yes": "yes",
975
+ "bin.no": "no",
976
+ "adapter.errAppServerSpawn": "Failed to start codex app-server: {message} (make sure your Codex CLI supports `codex app-server`)",
977
+ "adapter.errAppServerExit": "codex app-server exited; pending approvals/choices were auto-declined",
978
+ "adapter.logUnsupportedServerRequest": "unsupported app-server request: {method}",
979
+ "adapter.logQuestionNative": "choice request -> phone choice card questionID={id} (session={session})",
980
+ "adapter.logPermissionNative": "approval request -> phone approval card permissionID={id} (session={session})",
981
+ "adapter.checkAppServerOk": "codex app-server available",
982
+ "adapter.checkAppServerMissing": "this Codex CLI does not support `codex app-server` (please upgrade Codex CLI)"
654
983
  };
655
984
  var ja_JP_default = {
656
985
  "agent.err.createSession": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u4F5C\u6210\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
@@ -701,7 +1030,7 @@ var ja_JP_default = {
701
1030
  "install.scanHint": "\u30B9\u30DE\u30DB\u3067 tunnelbox App\u300C\u30B9\u30AD\u30E3\u30F3\u3057\u3066\u30DA\u30A2\u30EA\u30F3\u30B0\u300D\u3092\u958B\u304D\u3001\u4E0A\u306E QR \u30B3\u30FC\u30C9\u3092\u30B9\u30AD\u30E3\u30F3\u3057\u3066\u63A5\u7D9A\uFF1A",
702
1031
  "pair.heading": "tunnelbox \u30B9\u30DE\u30DB\u30DA\u30A2\u30EA\u30F3\u30B0",
703
1032
  "pair.howTo": "\u30B9\u30DE\u30DB\u3067 tunnelbox App \u3092\u958B\u304D\u3001\u300C\u30B9\u30AD\u30E3\u30F3\u3057\u3066\u30DA\u30A2\u30EA\u30F3\u30B0\u300D\u3067\u4E0A\u306E QR \u30B3\u30FC\u30C9\u3092\u30B9\u30AD\u30E3\u30F3\u3059\u308B\u304B\u3001\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u624B\u52D5\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
704
- "pair.oneTime": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u306F\u4E00\u5EA6\u304D\u308A\u3067\u3001\u4F7F\u7528\u5F8C\u306F\u7121\u52B9\u306B\u306A\u308A\u307E\u3059\u3002\u65B0\u3057\u3044\u30B3\u30FC\u30C9\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u300C\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u66F4\u65B0\u300D\u3068\u4F9D\u983C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1033
+ "pair.oneTime": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u306F1\u56DE\u9650\u308A\u3067\u3001\u6709\u52B9\u671F\u9650\u306F\u7D0410\u5206\u3067\u3059\u3002\u4F7F\u7528\u307E\u305F\u306F\u671F\u9650\u5207\u308C\u3067\u7121\u52B9\u306B\u306A\u308A\u307E\u3059\u3002\u65B0\u3057\u3044\u30B3\u30FC\u30C9\u304C\u5FC5\u8981\u306A\u5834\u5408\u306F\u300C\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u66F4\u65B0\u300D\u3068\u4F9D\u983C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
705
1034
  "pair.promptBody": "\u3053\u306E PC \u306E\u30B9\u30DE\u30DB\u9060\u9694\u30DA\u30A2\u30EA\u30F3\u30B0\u60C5\u5831\u3092\u8868\u793A\u3057\u3066\u304F\u3060\u3055\u3044\uFF1A\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3068\u3001\u30B9\u30AD\u30E3\u30F3\u3067\u304D\u308B QR \u30B3\u30FC\u30C9\u3002QR \u30B3\u30FC\u30C9\u306F\u7B49\u5E45\u30B3\u30FC\u30C9\u30D6\u30ED\u30C3\u30AF\u306B\u5165\u308C\u30011 \u6587\u5B57\u3082\u5909\u3048\u305A\u305D\u306E\u307E\u307E\u51FA\u529B\u3057\u3066\u304F\u3060\u3055\u3044\u3002\u30B9\u30DE\u30DB\u3067\u30B9\u30AD\u30E3\u30F3\u3067\u304D\u308B\u3088\u3046\u306B\u3059\u308B\u305F\u3081\u3067\u3059\u3002",
706
1035
  "pair.promptDescription": "\u30B9\u30DE\u30DB\u9060\u9694\u30DA\u30A2\u30EA\u30F3\u30B0\u306E\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u30FB\u30B9\u30AD\u30E3\u30F3\u7528 QR \u30B3\u30FC\u30C9\u3092\u8868\u793A",
707
1036
  "pair.scanIntro": "**\u30B9\u30AD\u30E3\u30F3\u3067\u30DA\u30A2\u30EA\u30F3\u30B0**\uFF1A\u30B9\u30DE\u30DB\u3067 tunnelbox App\u300C\u30B9\u30AD\u30E3\u30F3\u3057\u3066\u30DA\u30A2\u30EA\u30F3\u30B0\u300D\u3092\u958B\u304D\u3001\u4E0B\u306E QR \u30B3\u30FC\u30C9\u3092\u30B9\u30AD\u30E3\u30F3\u3059\u308B\u3068\u81EA\u52D5\u7684\u306B\u63A5\u7D9A\u3055\u308C\u307E\u3059\u3002",
@@ -816,7 +1145,118 @@ var ja_JP_default = {
816
1145
  "hermes.pairTimeout": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u8981\u6C42\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\uFF08\u30EA\u30EC\u30FC\u672A\u5FDC\u7B54\uFF09",
817
1146
  "hermes.errToolPair": "tunnelbox_pair \u5931\u6557: {err}",
818
1147
  "hermes.errToolStatus": "tunnelbox_status \u5931\u6557: {err}",
819
- "hermes.cliUsage": "\u4F7F\u7528\u65B9\u6CD5: /tunnelbox <pair|status>\n pair \u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u53D6\u5F97\u3057\u3066\u8868\u793A\n status \u30EA\u30EC\u30FC/\u30D0\u30A4\u30F3\u30C9/\u63A5\u7D9A\u72B6\u614B\u3092\u8868\u793A"
1148
+ "hermes.cliUsage": "\u4F7F\u7528\u65B9\u6CD5: /tunnelbox <pair|status>\n pair \u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u53D6\u5F97\u3057\u3066\u8868\u793A\n status \u30EA\u30EC\u30FC/\u30D0\u30A4\u30F3\u30C9/\u63A5\u7D9A\u72B6\u614B\u3092\u8868\u793A",
1149
+ "qr.validFor": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u306E\u6709\u52B9\u671F\u9650\u306F\u7D0410\u5206\u3067\u3059\u3002\u671F\u9650\u5207\u308C\u306E\u5834\u5408\u306F\u30D1\u30BD\u30B3\u30F3\u5074\u3067\u518D\u53D6\u5F97\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1150
+ "pair.toolDesc": "\u3053\u306E\u30D1\u30BD\u30B3\u30F3\u306E\u30B9\u30DE\u30DB\u9023\u643A\u60C5\u5831\uFF08\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3068\u30B9\u30AD\u30E3\u30F3\u53EF\u80FD\u306AQR\u30B3\u30FC\u30C9\uFF09\u3092\u8868\u793A\u3057\u307E\u3059\u3002\u30DA\u30A2\u30EA\u30F3\u30B0\u3084QR\u30B3\u30FC\u30C9\u306E\u30B9\u30AD\u30E3\u30F3\u3001\u30B9\u30DE\u30DB\u304B\u3089\u306E\u64CD\u4F5C\u306B\u3064\u3044\u3066\u8CEA\u554F\u3055\u308C\u305F\u3068\u304D\u306B\u547C\u3073\u51FA\u3057\u307E\u3059\u3002",
1151
+ "pair.toolRefreshDesc": "\u30EA\u30EC\u30FC\u306B\u65B0\u3057\u3044\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u8981\u6C42\u3059\u308B\u304B\u3069\u3046\u304B",
1152
+ "state.errSaveState": "\u72B6\u614B\u306E\u4FDD\u5B58\u306B\u5931\u6557\u3057\u307E\u3057\u305F",
1153
+ "adapter.logConnected": "\u30EA\u30EC\u30FC\u306B\u63A5\u7D9A\u3057\u307E\u3057\u305F {url}",
1154
+ "adapter.logDisconnected": "\u30EA\u30EC\u30FC\u304B\u3089\u5207\u65AD\u3055\u308C\u307E\u3057\u305F\u3002\u81EA\u52D5\u7684\u306B\u518D\u63A5\u7D9A\u3057\u3066\u3044\u307E\u3059\u2026",
1155
+ "adapter.logPairCode": "\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u751F\u6210\u3057\u307E\u3057\u305F: {code}",
1156
+ "adapter.logClaimed": "\u30B9\u30DE\u30DB\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u7D10\u4ED8\u3051\u307E\u3057\u305F\u3002\u4EE5\u964D\u306F\u30B9\u30DE\u30DB\u306E\u300C\u30DE\u30A4\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u30FC\u300D\u304B\u3089\u76F4\u63A5\u63A5\u7D9A\u3057\u307E\u3059",
1157
+ "adapter.logResetIdentity": "\u30A2\u30AB\u30A6\u30F3\u30C8\u304B\u3089\u89E3\u9664\u3055\u308C\u307E\u3057\u305F\u3002ID\u3092\u30EA\u30BB\u30C3\u30C8\u3057\u3001\u65B0\u3057\u3044\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u751F\u6210\u3057\u3066\u3044\u307E\u3059\u2026",
1158
+ "adapter.logUnhandledType": "\u672A\u51E6\u7406\u306E\u30E1\u30C3\u30BB\u30FC\u30B8\u30BF\u30A4\u30D7: {type}",
1159
+ "adapter.errNoRelay": "\u30EA\u30EC\u30FCURL\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u30D3\u30EB\u30C9\u6642\u306B --env \u3067\u65E2\u5B9A\u5024\u3092\u6CE8\u5165\u3059\u308B\u304B\u3001\u5B9F\u884C\u6642\u306B TUNNELBOX_RELAY_URL \u3067\u4E0A\u66F8\u304D\u3057\u3066\u304F\u3060\u3055\u3044",
1160
+ "adapter.errBusy": "\u3053\u306E\u30BB\u30C3\u30B7\u30E7\u30F3\u306F\u5B9F\u884C\u4E2D\u3067\u3059\u3002\u5B8C\u4E86\u3092\u5F85\u3064\u304B\u3001\u5148\u306B\u505C\u6B62\u3057\u3066\u304F\u3060\u3055\u3044",
1161
+ "adapter.errBadWorkspaceEmpty": "\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u306E\u30D1\u30B9\u304C\u3042\u308A\u307E\u305B\u3093",
1162
+ "adapter.errBadWorkspaceNotDir": "\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u304C\u5B58\u5728\u3057\u306A\u3044\u304B\u4F7F\u7528\u3067\u304D\u307E\u305B\u3093",
1163
+ "adapter.errWorkspaceMissing": "\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u304C\u5B58\u5728\u3057\u307E\u305B\u3093: {dir}",
1164
+ "adapter.cmdNew": "\u65B0\u3057\u3044\u30BB\u30C3\u30B7\u30E7\u30F3",
1165
+ "adapter.cmdHelp": "\u30D8\u30EB\u30D7\u3092\u8868\u793A",
1166
+ "adapter.helpText": "\u4F7F\u7528\u53EF\u80FD\u306A\u30B3\u30DE\u30F3\u30C9\uFF1A\n- /new \u65B0\u3057\u3044\u30BB\u30C3\u30B7\u30E7\u30F3\n- /help \u30D8\u30EB\u30D7\u3092\u8868\u793A",
1167
+ "adapter.newSessionTitle": "\u65B0\u3057\u3044\u30BB\u30C3\u30B7\u30E7\u30F3",
1168
+ "install.langHelpTitle": "install-local \u304C\u5BFE\u5FDC\u3059\u308B\u8A00\u8A9E\uFF08--lang <tag>\uFF09\uFF1A",
1169
+ "install.langHelpExample": "\u4F8B: npm run install-local -- --lang de-DE",
1170
+ "install.unknownLang": '\u4E0D\u660E\u306A\u8A00\u8A9E "{raw}" \u306E\u305F\u3081 en-US \u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059\u3002\u5BFE\u5FDC: {list}',
1171
+ "hermes.errAskRequired": "question \u306F\u5FC5\u9808\u3067\u3059",
1172
+ "hermes.msgPhoneUnavailable": "\u30B9\u30DE\u30DB\u304C\u5229\u7528\u3067\u304D\u306A\u3044\u304B\u5FDC\u7B54\u304C\u3042\u308A\u307E\u305B\u3093\u3002\u7D44\u307F\u8FBC\u307F\u306E clarify \u3067\u30ED\u30FC\u30AB\u30EB\u306B\u8CEA\u554F\u3059\u308B\u304B\u3001\u3054\u81EA\u8EAB\u3067\u5224\u65AD\u3057\u3066\u7D9A\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1173
+ "hermes.errClarifyUnavailable": "clarify \u30B5\u30DD\u30FC\u30C8\u306F\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
1174
+ "hermes.errAskFailed": "tunnelbox_ask \u306B\u5931\u6557\u3057\u307E\u3057\u305F: {err}",
1175
+ "hermes.errClarifyFailed": "clarify \u306B\u5931\u6557\u3057\u307E\u3057\u305F: {err}",
1176
+ "bin.denied": "\u30B9\u30DE\u30DB\u3067\u62D2\u5426\u3055\u308C\u307E\u3057\u305F",
1177
+ "bin.timeout": "\u627F\u8A8D\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F\uFF08fail-closed\uFF09",
1178
+ "bin.reqRun": "Claude Code \u304C {tool} \u306E\u5B9F\u884C\u3092\u8981\u6C42\u3057\u3066\u3044\u307E\u3059",
1179
+ "bin.pairTitle": "tunnelbox \u30B9\u30DE\u30DB\u9023\u643A",
1180
+ "bin.pairCodeLine": " \u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9: {code}",
1181
+ "bin.pairHint": "tunnelbox \u30A2\u30D7\u30EA\u3092\u958B\u304D\u300C\u30B9\u30AD\u30E3\u30F3\u3057\u3066\u30DA\u30A2\u30EA\u30F3\u30B0\u300D\u3067QR\u30B3\u30FC\u30C9\u3092\u8AAD\u307F\u53D6\u308B\u304B\u3001\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u3092\u624B\u5165\u529B\u3057\u3066\u304F\u3060\u3055\u3044\uFF081\u56DE\u9650\u308A\uFF09\u3002",
1182
+ "bin.pairWritten": " \u9023\u643A\u60C5\u5831\u3092\u66F8\u304D\u8FBC\u307F\u307E\u3057\u305F: {path}",
1183
+ "bin.pairRequestFailed": "\u30EA\u30EC\u30FC\u3078\u306E\u30DA\u30A2\u30EA\u30F3\u30B0\u30B3\u30FC\u30C9\u8981\u6C42\u306B\u5931\u6557\u3057\u307E\u3057\u305F\u3002",
1184
+ "bin.alreadyClaimed": "\u3053\u306E\u30D1\u30BD\u30B3\u30F3\u306F\u65E2\u306B\u30B9\u30DE\u30DB\u30A2\u30AB\u30A6\u30F3\u30C8\u306B\u7D10\u4ED8\u3051\u3089\u308C\u3066\u3044\u307E\u3059\u3002\u30B9\u30DE\u30DB\u306E\u300C\u30DE\u30A4\u30B3\u30F3\u30D4\u30E5\u30FC\u30BF\u30FC\u300D\u304B\u3089\u76F4\u63A5\u63A5\u7D9A\u3067\u304D\u307E\u3059\u3002\u518D\u30DA\u30A2\u30EA\u30F3\u30B0\u3059\u308B\u306B\u306F\u3001\u5148\u306B\u30B9\u30DE\u30DB\u5074\u3067\u89E3\u9664\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1185
+ "bin.noRelay": "\u30EA\u30EC\u30FCURL\u304C\u8A2D\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\u74B0\u5883\u5909\u6570 TUNNELBOX_RELAY_URL \u3092\u8A2D\u5B9A\u3057\u3066\u518D\u8A66\u884C\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1186
+ "bin.connectFailed": "\u30EA\u30EC\u30FC\u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093: {relay}\nTUNNELBOX_RELAY_URL \u3092\u8A2D\u5B9A\u3059\u308B\u304B\u3001official-plugin \u306E\u72B6\u614B\u30D5\u30A1\u30A4\u30EB\u3067\u69CB\u6210\u3057\u3066\u304F\u3060\u3055\u3044\u3002",
1187
+ "bin.statusRelay": "\u30EA\u30EC\u30FC: {value}",
1188
+ "bin.statusAgent": "\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8ID: {value}",
1189
+ "bin.statusClaimed": "\u30B9\u30DE\u30DB\u9023\u643A: {value}",
1190
+ "bin.statusStateFile": "\u72B6\u614B\u30D5\u30A1\u30A4\u30EB: {value}",
1191
+ "bin.statusLatest": "\u6700\u65B0\u306E\u9023\u643A\u60C5\u5831:",
1192
+ "bin.usage": "\u4F7F\u7528\u6CD5: tunnelbox <pair|status|ask>",
1193
+ "bin.usagePair": " pair \u30B9\u30DE\u30DB\u9023\u643A\u30B3\u30FC\u30C9\u3092\u53D6\u5F97\u3057\u3066\u8868\u793A",
1194
+ "bin.usageStatus": " status \u30EA\u30EC\u30FC/\u9023\u643A\u72B6\u614B\u3092\u8868\u793A",
1195
+ "bin.usageAsk": " ask \u30C4\u30FC\u30EB\u627F\u8A8D\u3092\u30B9\u30DE\u30DB\u306B\u8EE2\u9001",
1196
+ "adapter.logMsgUncaught": "\u30E1\u30C3\u30BB\u30FC\u30B8\u51E6\u7406\u3067\u672A\u6355\u6349\u306E\u4F8B\u5916: {message}",
1197
+ "adapter.logHandleFailed": "{type} \u306E\u51E6\u7406\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {message}",
1198
+ "adapter.logPromptFailed": "session.prompt \u306B\u5931\u6557\u3057\u307E\u3057\u305F: {message}",
1199
+ "adapter.logAbortSent": "\u4E2D\u6B62\u3092\u9001\u4FE1\u3057\u307E\u3057\u305F (session={session})",
1200
+ "adapter.errUserDenied": "\u30E6\u30FC\u30B6\u30FC\u304C\u62D2\u5426\u3057\u307E\u3057\u305F",
1201
+ "adapter.logPendingResent": "session.pending: \u672A\u51E6\u7406\u30EA\u30AF\u30A8\u30B9\u30C8\u3092 {count} \u4EF6\u518D\u9001\u3057\u307E\u3057\u305F",
1202
+ "adapter.logWorkspaceSwitched": "\u30EF\u30FC\u30AF\u30B9\u30DA\u30FC\u30B9\u3092\u5207\u308A\u66FF\u3048\u307E\u3057\u305F: {path}",
1203
+ "adapter.logNewSession": "\u65B0\u898F\u30BB\u30C3\u30B7\u30E7\u30F3\u3092\u4FDD\u5B58 codexId={codexId} (alias={session})",
1204
+ "adapter.logSessionError": "\u30BF\u30FC\u30F3\u30A8\u30E9\u30FC (session={session}): {message}",
1205
+ "adapter.logDshSent": "dsh \u306B\u9001\u4FE1\u3057\u307E\u3057\u305F (session={session})",
1206
+ "adapter.logReadHistoryFailed": "\u30BB\u30C3\u30B7\u30E7\u30F3\u5C65\u6B74\u306E\u8AAD\u307F\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({session}): {message}",
1207
+ "adapter.logAnswererInitFailed": "\u5FDC\u7B54\u8005\u306E\u521D\u671F\u5316\u306B\u5931\u6557\u3057\u307E\u3057\u305F: {message}",
1208
+ "adapter.logRemoteMode": "\u4E21\u5074\u540C\u6642\u8868\u793A\u30E2\u30FC\u30C9: \u9078\u629E/\u627F\u8A8D\u306F typert \u30DE\u30EB\u30C1\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u653E\u9001\u3092\u4F7F\u7528\u3002\u30B9\u30DE\u30DB\u3068 dsh web \u304C\u540C\u3058\u753B\u9762\u3092\u5171\u6709\u3057\u3001\u5148\u306B\u56DE\u7B54\u3057\u305F\u65B9\u304C\u6709\u52B9",
1209
+ "adapter.logRemoteProbeFailed": "typert \u30EA\u30E2\u30FC\u30C8\u30A4\u30D9\u30F3\u30C8\u30BD\u30FC\u30B9\u306E\u691C\u51FA\u306B\u5931\u6557\u3002\u30ED\u30FC\u30AB\u30EB\u5FDC\u7B54\u30E2\u30FC\u30C9\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF\u3057\u307E\u3059: {message}",
1210
+ "adapter.logLocalMode": "\u30ED\u30FC\u30AB\u30EB\u5FDC\u7B54\u30E2\u30FC\u30C9: \u9078\u629E/\u627F\u8A8D\u306F\u30B9\u30DE\u30DB\u304C\u56DE\u7B54\uFF08headless\u3001dsh web \u653E\u9001\u306A\u3057\uFF09",
1211
+ "adapter.logRemoteStreamInterrupted": "remote events \u30B9\u30C8\u30EA\u30FC\u30E0\u304C\u4E2D\u65AD\u3057\u307E\u3057\u305F: {message}",
1212
+ "adapter.logResultRejected": "$events/result \u304C\u53D7\u7406\u3055\u308C\u307E\u305B\u3093\u3067\u3057\u305F ({eventId}): {message}",
1213
+ "adapter.logResultBackfillFailed": "$events/result \u306E\u66F8\u304D\u623B\u3057\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({eventId}): {message}",
1214
+ "adapter.logRemoteQuestion": "remote \u8CEA\u554F\u653E\u9001 \u2192 \u30B9\u30DE\u30DB\u8CEA\u554F\u30AB\u30FC\u30C9 questionID={id} (session={session})",
1215
+ "adapter.errRemoteReadyFrame": "remote events \u306E\u6700\u521D\u306E\u30D5\u30EC\u30FC\u30E0\u304C\u7570\u5E38\u3067\u3059",
1216
+ "adapter.logRemoteApproval": "remote \u627F\u8A8D\u653E\u9001 \u2192 \u30B9\u30DE\u30DB\u6A29\u9650\u30AB\u30FC\u30C9 permissionID={id} (session={session})",
1217
+ "adapter.logUserQuestionRoute": "user-questions \u9078\u629E \u2192 session={session} \u306B\u30EB\u30FC\u30C6\u30A3\u30F3\u30B0",
1218
+ "adapter.errDshQuestionEmpty": "dsh \u306E\u8CEA\u554F\u5185\u5BB9\u304C\u7A7A\u3067\u3059",
1219
+ "adapter.errQuestionTimeout": "\u8CEA\u554F\u304C\u30BF\u30A4\u30E0\u30A2\u30A6\u30C8\u3057\u307E\u3057\u305F ({seconds}s)\u3001\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F",
1220
+ "adapter.errQuestionCancelledAbort": "\u8CEA\u554F\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F\uFF08\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u4E2D\u6B62\uFF09",
1221
+ "adapter.errQuestionCancelledRelay": "\u30EA\u30EC\u30FC\u306B\u5230\u9054\u3067\u304D\u305A\u3001\u8CEA\u554F\u304C\u30AD\u30E3\u30F3\u30BB\u30EB\u3055\u308C\u307E\u3057\u305F",
1222
+ "adapter.logQuestionToPhone": "user-questions \u9078\u629E \u2192 \u30B9\u30DE\u30DB\u8CEA\u554F\u30AB\u30FC\u30C9\u306B\u9001\u4FE1 questionID={id} (session={session})",
1223
+ "adapter.errQuestionUserCancelled": "\u30E6\u30FC\u30B6\u30FC\u304C\u30B9\u30DE\u30DB\u3067\u8CEA\u554F\u3092\u30AD\u30E3\u30F3\u30BB\u30EB/\u62D2\u5426\u3057\u307E\u3057\u305F",
1224
+ "adapter.logApprovalRequest": "\u627F\u8A8D\u30EA\u30AF\u30A8\u30B9\u30C8 (tool={tool}) \u2192 \u30B9\u30DE\u30DB\u6A29\u9650\u30AB\u30FC\u30C9\u306B\u9001\u4FE1 permissionID={id}",
1225
+ "adapter.logAgentPresetFailed": "agentPreset \u306E\u89E3\u6C7A\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({preset})\u3002preset \u306A\u3057\u306B\u30D5\u30A9\u30FC\u30EB\u30D0\u30C3\u30AF: {message}",
1226
+ "adapter.logSessionLiveAdopted": "\u30BB\u30C3\u30B7\u30E7\u30F3 {session} \u306F\u3053\u306E\u30D7\u30ED\u30BB\u30B9\u306E\u5225\u306E\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u304C\u4FDD\u6301\u4E2D\uFF08live\uFF09\u3002\u65E2\u5B58\u306E\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u3092\u63A1\u7528\u3057\u3066\u7D99\u7D9A\u3057\u307E\u3059: {message}",
1227
+ "adapter.logDisposeSkipped": "\u63A1\u7528\u3057\u305F\u5916\u90E8 live \u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306F dispose \u3092\u5B9F\u884C\u3057\u307E\u305B\u3093\uFF08\u30BB\u30C3\u30B7\u30E7\u30F3 {session} \u306F\u5143\u306E\u4FDD\u6301\u8005\u304C\u7BA1\u7406\uFF09",
1228
+ "adapter.logAgentCreateFailed": "\u30A8\u30FC\u30B8\u30A7\u30F3\u30C8\u306E\u4F5C\u6210/\u518D\u958B\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({session}): {message}",
1229
+ "adapter.errSessionBusyLive": "\u30BB\u30C3\u30B7\u30E7\u30F3 {session} \u306F\u4F7F\u7528\u4E2D\u3067\u3059\uFF08live\uFF09\u3002\u5F8C\u3067\u3082\u3046\u4E00\u5EA6\u304A\u8A66\u3057\u304F\u3060\u3055\u3044",
1230
+ "adapter.errAgentsUnavailable": "agents \u30B5\u30FC\u30D3\u30B9\u304C\u5229\u7528\u3067\u304D\u307E\u305B\u3093",
1231
+ "adapter.logToolReason": "dsh \u304C\u30C4\u30FC\u30EB {tool} \u306E\u5B9F\u884C\u3092\u8981\u6C42\u3057\u3066\u3044\u307E\u3059",
1232
+ "adapter.logGatewayConnected": "\u30ED\u30FC\u30AB\u30EB OpenClaw Gateway \u306B\u63A5\u7D9A\u3057\u307E\u3057\u305F\uFF08{version}\uFF09",
1233
+ "adapter.logGatewayDisconnected": "OpenClaw Gateway \u304B\u3089\u5207\u65AD\u3055\u308C\u307E\u3057\u305F\u3002\u516C\u5F0F\u30AF\u30E9\u30A4\u30A2\u30F3\u30C8\u304C\u518D\u63A5\u7D9A\u3057\u3066\u3044\u307E\u3059\u2026",
1234
+ "adapter.logGatewayConnectFailed": "\u30ED\u30FC\u30AB\u30EB OpenClaw Gateway \u306B\u63A5\u7D9A\u3067\u304D\u307E\u305B\u3093\uFF08\u521D\u56DE\u306F\u672C\u6A5F\u3067\u30C7\u30D0\u30A4\u30B9\u3092\u627F\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044: `openclaw devices list` + `openclaw devices approve <requestId>`\uFF09",
1235
+ "adapter.errGatewayNoSessionKey": "Gateway \u304C\u30BB\u30C3\u30B7\u30E7\u30F3 key \u3092\u8FD4\u3057\u307E\u305B\u3093\u3067\u3057\u305F",
1236
+ "adapter.logDeleteSessionFailed": "\u30BB\u30C3\u30B7\u30E7\u30F3\u306E\u524A\u9664\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({session}): {message}\uFF08\u524A\u9664\u6E08\u307F\u3068\u3057\u3066\u5FDC\u7B54\uFF09",
1237
+ "adapter.logApprovalReplyFailed": "\u627F\u8A8D\u5FDC\u7B54\u306B\u5931\u6557\u3057\u307E\u3057\u305F ({id}): {message}",
1238
+ "adapter.logPendingApproval": "session.pending: \u672A\u51E6\u7406\u306E\u627F\u8A8D\u3092 {count} \u4EF6\u518D\u9001\u3057\u307E\u3057\u305F (session={session})",
1239
+ "adapter.workspaceDefault": "\u30C7\u30D5\u30A9\u30EB\u30C8",
1240
+ "adapter.cursorSessionTitle": "Cursor \u30BB\u30C3\u30B7\u30E7\u30F3",
1241
+ "adapter.reasonDisconnect": "\u30EA\u30EC\u30FC\u5207\u65AD\u3001\u81EA\u52D5\u62D2\u5426\uFF08fail-closed\uFF09",
1242
+ "adapter.warnInvalidEnv": "\u7121\u52B9\u306A {name} \u3092\u7121\u8996\u3057\u307E\u3059: {raw}\uFF08{list}\uFF09",
1243
+ "adapter.errStartFailed": "\u8D77\u52D5\u306B\u5931\u6557\u3057\u307E\u3057\u305F:",
1244
+ "adapter.msgStarted": "{name} \u30A2\u30C0\u30D7\u30BF\u30FC\u3092\u8D77\u52D5\u3057\u307E\u3057\u305F\uFF08Ctrl+C \u3067\u7D42\u4E86\uFF09",
1245
+ "adapter.warnCliMissing": "\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u300C{bin}\u300D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\u3002\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\u3059\u308B\uFF08\u4F8B: npm i -g @openai/codex\uFF09\u304B\u3001TUNNELBOX_CODEX_BIN \u3067\u30D1\u30B9\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
1246
+ "adapter.errCliNotFound": "{name} \u306E\u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u300C{bin}\u300D\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF1ACodex CLI \u3092\u30A4\u30F3\u30B9\u30C8\u30FC\u30EB\uFF08npm i -g @openai/codex\uFF09\u3059\u308B\u304B TUNNELBOX_CODEX_BIN \u3092\u8A2D\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044",
1247
+ "adapter.errSessionNotFound": "\u30BB\u30C3\u30B7\u30E7\u30F3\u304C\u5B58\u5728\u3057\u306A\u3044\u304B\u3001\u3059\u3067\u306B\u524A\u9664\u3055\u308C\u3066\u3044\u307E\u3059",
1248
+ "adapter.checkHeader": "tunnelbox-codex \u74B0\u5883\u30C1\u30A7\u30C3\u30AF",
1249
+ "adapter.checkCliOk": "{name} \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB: {path}",
1250
+ "adapter.checkCliMissing": "{name} \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093\uFF08{bin}\uFF09",
1251
+ "bin.yes": "\u306F\u3044",
1252
+ "bin.no": "\u3044\u3044\u3048",
1253
+ "adapter.errAppServerSpawn": "codex app-server \u3092\u8D77\u52D5\u3067\u304D\u307E\u305B\u3093: {message}\uFF08Codex CLI \u304C `codex app-server` \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u308B\u304B\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\uFF09",
1254
+ "adapter.errAppServerExit": "codex app-server \u304C\u7D42\u4E86\u3057\u307E\u3057\u305F\u3002\u4FDD\u7559\u4E2D\u306E\u627F\u8A8D/\u9078\u629E\u306F\u81EA\u52D5\u7684\u306B\u62D2\u5426\u3055\u308C\u307E\u3057\u305F",
1255
+ "adapter.logUnsupportedServerRequest": "\u672A\u5BFE\u5FDC\u306E app-server \u30EA\u30AF\u30A8\u30B9\u30C8: {method}",
1256
+ "adapter.logQuestionNative": "\u9078\u629E\u30EA\u30AF\u30A8\u30B9\u30C8 -> \u30B9\u30DE\u30DB\u9078\u629E\u30AB\u30FC\u30C9 questionID={id} (session={session})",
1257
+ "adapter.logPermissionNative": "\u627F\u8A8D\u30EA\u30AF\u30A8\u30B9\u30C8 -> \u30B9\u30DE\u30DB\u627F\u8A8D\u30AB\u30FC\u30C9 permissionID={id} (session={session})",
1258
+ "adapter.checkAppServerOk": "codex app-server \u5229\u7528\u53EF\u80FD",
1259
+ "adapter.checkAppServerMissing": "\u3053\u306E Codex CLI \u306F `codex app-server` \u306B\u5BFE\u5FDC\u3057\u3066\u3044\u307E\u305B\u3093\uFF08Codex CLI \u3092\u66F4\u65B0\u3057\u3066\u304F\u3060\u3055\u3044\uFF09"
820
1260
  };
821
1261
  var ko_KR_default = {
822
1262
  "agent.err.createSession": "\uC138\uC158 \uC0DD\uC131 \uC2E4\uD328",
@@ -867,7 +1307,7 @@ var ko_KR_default = {
867
1307
  "install.scanHint": "\uD734\uB300\uD3F0\uC5D0\uC11C tunnelbox \uC571 \u201C\uC2A4\uCE94\uD558\uC5EC \uC5F0\uACB0\u201D\uC744 \uC5F4\uACE0 \uC704 QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uC5EC \uC5F0\uACB0\uD558\uC138\uC694:",
868
1308
  "pair.heading": "tunnelbox \uD734\uB300\uD3F0 \uD398\uC5B4\uB9C1",
869
1309
  "pair.howTo": "\uD734\uB300\uD3F0\uC5D0\uC11C tunnelbox \uC571\uC744 \uC5F4\uACE0 \u201C\uC2A4\uCE94\uD558\uC5EC \uC5F0\uACB0\u201D\uB85C \uC704 QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uAC70\uB098 \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB97C \uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694.",
870
- "pair.oneTime": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB294 \uC77C\uD68C\uC6A9\uC774\uBA70 \uC0AC\uC6A9 \uD6C4\uC5D0\uB294 \uB9CC\uB8CC\uB429\uB2C8\uB2E4. \uC0C8 \uCF54\uB4DC\uAC00 \uD544\uC694\uD558\uBA74 \u201C\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC0C8\uB85C\uACE0\uCE68\u201D\uC744 \uC694\uCCAD\uD558\uC138\uC694.",
1310
+ "pair.oneTime": '\uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB294 1\uD68C\uC6A9\uC774\uBA70 \uC57D 10\uBD84\uAC04 \uC720\uD6A8\uD569\uB2C8\uB2E4. \uC0AC\uC6A9\uD558\uAC70\uB098 \uB9CC\uB8CC\uB418\uBA74 \uBB34\uD6A8\uAC00 \uB429\uB2C8\uB2E4. \uC0C8 \uCF54\uB4DC\uAC00 \uD544\uC694\uD558\uBA74 "\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC0C8\uB85C \uACE0\uCE68"\uC744 \uC694\uCCAD\uD558\uC138\uC694.',
871
1311
  "pair.promptBody": "\uC774 PC\uC758 \uD734\uB300\uD3F0 \uC6D0\uACA9 \uD398\uC5B4\uB9C1 \uC815\uBCF4\uB97C \uBCF4\uC5EC\uC8FC\uC138\uC694: \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uC640 \uC2A4\uCE94\uD560 \uC218 \uC788\uB294 QR \uCF54\uB4DC. QR \uCF54\uB4DC\uB294 \uACE0\uC815\uD3ED \uCF54\uB4DC \uBE14\uB85D\uC5D0 \uB123\uACE0 \uD55C \uAE00\uC790\uB3C4 \uBC14\uAFB8\uC9C0 \uB9D0\uACE0 \uADF8\uB300\uB85C \uD45C\uC2DC\uD574 \uC8FC\uC138\uC694. \uD734\uB300\uD3F0\uC73C\uB85C \uC2A4\uCE94\uD560 \uC218 \uC788\uB3C4\uB85D \uD558\uAE30 \uC704\uD568\uC785\uB2C8\uB2E4.",
872
1312
  "pair.promptDescription": "\uD734\uB300\uD3F0 \uC6D0\uACA9 \uD398\uC5B4\uB9C1\uC758 \uD398\uC5B4\uB9C1 \uCF54\uB4DC\xB7\uC2A4\uCE94\uC6A9 QR \uCF54\uB4DC \uD45C\uC2DC",
873
1313
  "pair.scanIntro": "**\uC2A4\uCE94\uC73C\uB85C \uC5F0\uACB0**: \uD734\uB300\uD3F0\uC5D0\uC11C tunnelbox \uC571 \u201C\uC2A4\uCE94\uD558\uC5EC \uC5F0\uACB0\u201D\uC744 \uC5F4\uACE0 \uC544\uB798 QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uBA74 \uC790\uB3D9\uC73C\uB85C \uC5F0\uACB0\uB429\uB2C8\uB2E4.",
@@ -982,7 +1422,118 @@ var ko_KR_default = {
982
1422
  "hermes.pairTimeout": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC694\uCCAD \uC2DC\uAC04 \uCD08\uACFC(\uB9B4\uB808\uC774 \uBBF8\uC751\uB2F5)",
983
1423
  "hermes.errToolPair": "tunnelbox_pair \uC2E4\uD328: {err}",
984
1424
  "hermes.errToolStatus": "tunnelbox_status \uC2E4\uD328: {err}",
985
- "hermes.cliUsage": "\uC0AC\uC6A9\uBC95: /tunnelbox <pair|status>\n pair \uD734\uB300\uD3F0 \uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC694\uCCAD/\uCD9C\uB825\n status \uB9B4\uB808\uC774/\uBC14\uC778\uB529/\uC5F0\uACB0 \uC0C1\uD0DC \uD45C\uC2DC"
1425
+ "hermes.cliUsage": "\uC0AC\uC6A9\uBC95: /tunnelbox <pair|status>\n pair \uD734\uB300\uD3F0 \uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC694\uCCAD/\uCD9C\uB825\n status \uB9B4\uB808\uC774/\uBC14\uC778\uB529/\uC5F0\uACB0 \uC0C1\uD0DC \uD45C\uC2DC",
1426
+ "qr.validFor": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB294 \uC57D 10\uBD84\uAC04 \uC720\uD6A8\uD569\uB2C8\uB2E4. \uB9CC\uB8CC\uB418\uBA74 \uCEF4\uD4E8\uD130\uC5D0\uC11C \uC0C8\uB85C \uBC1B\uC73C\uC138\uC694.",
1427
+ "pair.toolDesc": "\uC774 \uCEF4\uD4E8\uD130\uC758 \uC2A4\uB9C8\uD2B8\uD3F0 \uD398\uC5B4\uB9C1 \uC815\uBCF4(\uD398\uC5B4\uB9C1 \uCF54\uB4DC\uC640 \uC2A4\uCE94 \uAC00\uB2A5\uD55C QR \uCF54\uB4DC)\uB97C \uD45C\uC2DC\uD569\uB2C8\uB2E4. \uD398\uC5B4\uB9C1, QR \uCF54\uB4DC \uC2A4\uCE94, \uC2A4\uB9C8\uD2B8\uD3F0\uC73C\uB85C \uC774 \uCEF4\uD4E8\uD130 \uC81C\uC5B4\uC5D0 \uB300\uD574 \uBB3C\uC5B4\uBCFC \uB54C \uD638\uCD9C\uD558\uC138\uC694.",
1428
+ "pair.toolRefreshDesc": "\uB9B4\uB808\uC774\uC5D0 \uC0C8 \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB97C \uC694\uCCAD\uD560\uC9C0 \uC5EC\uBD80",
1429
+ "state.errSaveState": "\uC0C1\uD0DC \uC800\uC7A5 \uC2E4\uD328",
1430
+ "adapter.logConnected": "\uB9B4\uB808\uC774\uC5D0 \uC5F0\uACB0\uB428 {url}",
1431
+ "adapter.logDisconnected": "\uB9B4\uB808\uC774\uC640 \uC5F0\uACB0\uC774 \uB04A\uC5B4\uC84C\uC2B5\uB2C8\uB2E4. \uC790\uB3D9\uC73C\uB85C \uC7AC\uC5F0\uACB0 \uC911\u2026",
1432
+ "adapter.logPairCode": "\uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC0DD\uC131\uB428: {code}",
1433
+ "adapter.logClaimed": "\uC2A4\uB9C8\uD2B8\uD3F0 \uACC4\uC815\uC5D0 \uC5F0\uACB0\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uC774\uC81C\uBD80\uD130 \uC2A4\uB9C8\uD2B8\uD3F0\uC758 '\uB0B4 \uCEF4\uD4E8\uD130'\uC5D0\uC11C \uC9C1\uC811 \uC5F0\uACB0\uD569\uB2C8\uB2E4",
1434
+ "adapter.logResetIdentity": "\uACC4\uC815\uC5D0\uC11C \uD574\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4. ID\uB97C \uC7AC\uC124\uC815\uD558\uACE0 \uC0C8 \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB97C \uC0DD\uC131 \uC911\u2026",
1435
+ "adapter.logUnhandledType": "\uCC98\uB9AC\uB418\uC9C0 \uC54A\uC740 \uBA54\uC2DC\uC9C0 \uC720\uD615: {type}",
1436
+ "adapter.errNoRelay": "\uB9B4\uB808\uC774 URL\uC774 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uBE4C\uB4DC \uC2DC --env\uB85C \uAE30\uBCF8\uAC12\uC744 \uC8FC\uC785\uD558\uAC70\uB098 \uB7F0\uD0C0\uC784\uC5D0 TUNNELBOX_RELAY_URL\uB85C \uC7AC\uC815\uC758\uD558\uC138\uC694",
1437
+ "adapter.errBusy": "\uC774 \uC138\uC158\uC774 \uC544\uC9C1 \uC2E4\uD589 \uC911\uC785\uB2C8\uB2E4. \uC644\uB8CC\uB97C \uAE30\uB2E4\uB9AC\uAC70\uB098 \uBA3C\uC800 \uC911\uC9C0\uD558\uC138\uC694",
1438
+ "adapter.errBadWorkspaceEmpty": "\uC791\uC5C5 \uACF5\uAC04 \uACBD\uB85C\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4",
1439
+ "adapter.errBadWorkspaceNotDir": "\uB514\uB809\uD130\uB9AC\uAC00 \uC5C6\uAC70\uB098 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
1440
+ "adapter.errWorkspaceMissing": "\uC791\uC5C5 \uACF5\uAC04\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4: {dir}",
1441
+ "adapter.cmdNew": "\uC0C8 \uC138\uC158",
1442
+ "adapter.cmdHelp": "\uB3C4\uC6C0\uB9D0 \uD45C\uC2DC",
1443
+ "adapter.helpText": "\uC9C0\uC6D0\uB418\uB294 \uBA85\uB839:\n- /new \uC0C8 \uC138\uC158\n- /help \uB3C4\uC6C0\uB9D0 \uD45C\uC2DC",
1444
+ "adapter.newSessionTitle": "\uC0C8 \uC138\uC158",
1445
+ "install.langHelpTitle": "install-local \uC9C0\uC6D0 \uC5B8\uC5B4(--lang <tag>):",
1446
+ "install.langHelpExample": "\uC608: npm run install-local -- --lang de-DE",
1447
+ "install.unknownLang": '\uC54C \uC218 \uC5C6\uB294 \uC5B8\uC5B4 "{raw}"\uC774\uBBC0\uB85C en-US\uB85C \uB300\uCCB4\uD569\uB2C8\uB2E4. \uC9C0\uC6D0: {list}',
1448
+ "hermes.errAskRequired": "question\uC740 \uD544\uC218\uC785\uB2C8\uB2E4",
1449
+ "hermes.msgPhoneUnavailable": "\uC2A4\uB9C8\uD2B8\uD3F0\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uAC70\uB098 \uC751\uB2F5\uC774 \uC5C6\uC2B5\uB2C8\uB2E4. \uB0B4\uC7A5 clarify\uB85C \uB85C\uCEEC\uC5D0\uC11C \uC9C8\uBB38\uD558\uAC70\uB098 \uC9C1\uC811 \uD310\uB2E8\uD558\uC5EC \uACC4\uC18D\uD558\uC138\uC694.",
1450
+ "hermes.errClarifyUnavailable": "clarify \uC9C0\uC6D0\uC744 \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
1451
+ "hermes.errAskFailed": "tunnelbox_ask \uC2E4\uD328: {err}",
1452
+ "hermes.errClarifyFailed": "clarify \uC2E4\uD328: {err}",
1453
+ "bin.denied": "\uC2A4\uB9C8\uD2B8\uD3F0\uC5D0\uC11C \uAC70\uBD80\uB428",
1454
+ "bin.timeout": "\uC2B9\uC778 \uC2DC\uAC04 \uCD08\uACFC(fail-closed)",
1455
+ "bin.reqRun": "Claude Code\uAC00 {tool} \uC2E4\uD589\uC744 \uC694\uCCAD\uD569\uB2C8\uB2E4",
1456
+ "bin.pairTitle": "tunnelbox \uC2A4\uB9C8\uD2B8\uD3F0 \uD398\uC5B4\uB9C1",
1457
+ "bin.pairCodeLine": " \uD398\uC5B4\uB9C1 \uCF54\uB4DC: {code}",
1458
+ "bin.pairHint": "tunnelbox \uC571\uC744 \uC5F4\uACE0 '\uC2A4\uCE94\uD558\uC5EC \uD398\uC5B4\uB9C1'\uC73C\uB85C QR \uCF54\uB4DC\uB97C \uC2A4\uCE94\uD558\uAC70\uB098 \uD398\uC5B4\uB9C1 \uCF54\uB4DC\uB97C \uC9C1\uC811 \uC785\uB825\uD558\uC138\uC694(1\uD68C\uC6A9).",
1459
+ "bin.pairWritten": " \uD398\uC5B4\uB9C1 \uC815\uBCF4 \uC800\uC7A5\uB428: {path}",
1460
+ "bin.pairRequestFailed": "\uB9B4\uB808\uC774\uC5D0 \uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC694\uCCAD \uC2E4\uD328.",
1461
+ "bin.alreadyClaimed": "\uC774 \uCEF4\uD4E8\uD130\uB294 \uC774\uBBF8 \uC2A4\uB9C8\uD2B8\uD3F0 \uACC4\uC815\uC5D0 \uC5F0\uACB0\uB418\uC5B4 \uC788\uC2B5\uB2C8\uB2E4. \uC2A4\uB9C8\uD2B8\uD3F0\uC758 '\uB0B4 \uCEF4\uD4E8\uD130'\uC5D0\uC11C \uC9C1\uC811 \uC5F0\uACB0\uD558\uC138\uC694. \uB2E4\uC2DC \uD398\uC5B4\uB9C1\uD558\uB824\uBA74 \uBA3C\uC800 \uC2A4\uB9C8\uD2B8\uD3F0\uC5D0\uC11C \uD574\uC81C\uD558\uC138\uC694.",
1462
+ "bin.noRelay": "\uB9B4\uB808\uC774 URL\uC774 \uC124\uC815\uB418\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4. \uD658\uACBD \uBCC0\uC218 TUNNELBOX_RELAY_URL\uC744 \uC124\uC815\uD55C \uD6C4 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694.",
1463
+ "bin.connectFailed": "\uB9B4\uB808\uC774\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {relay}\nTUNNELBOX_RELAY_URL\uC744 \uC124\uC815\uD558\uAC70\uB098 official-plugin \uC0C1\uD0DC \uD30C\uC77C\uC5D0\uC11C \uAD6C\uC131\uD558\uC138\uC694.",
1464
+ "bin.statusRelay": "\uB9B4\uB808\uC774: {value}",
1465
+ "bin.statusAgent": "\uC5D0\uC774\uC804\uD2B8 ID: {value}",
1466
+ "bin.statusClaimed": "\uC2A4\uB9C8\uD2B8\uD3F0 \uC5F0\uACB0: {value}",
1467
+ "bin.statusStateFile": "\uC0C1\uD0DC \uD30C\uC77C: {value}",
1468
+ "bin.statusLatest": "\uCD5C\uC2E0 \uD398\uC5B4\uB9C1 \uC815\uBCF4:",
1469
+ "bin.usage": "\uC0AC\uC6A9\uBC95: tunnelbox <pair|status|ask>",
1470
+ "bin.usagePair": " pair \uC2A4\uB9C8\uD2B8\uD3F0 \uD398\uC5B4\uB9C1 \uCF54\uB4DC \uC694\uCCAD \uBC0F \uCD9C\uB825",
1471
+ "bin.usageStatus": " status \uB9B4\uB808\uC774/\uC5F0\uACB0 \uC0C1\uD0DC \uD45C\uC2DC",
1472
+ "bin.usageAsk": " ask \uB3C4\uAD6C \uC2B9\uC778\uC744 \uC2A4\uB9C8\uD2B8\uD3F0\uC73C\uB85C \uC804\uB2EC",
1473
+ "adapter.logMsgUncaught": "\uBA54\uC2DC\uC9C0 \uCC98\uB9AC \uC911 \uCC98\uB9AC\uB418\uC9C0 \uC54A\uC740 \uC608\uC678: {message}",
1474
+ "adapter.logHandleFailed": "{type} \uCC98\uB9AC \uC2E4\uD328: {message}",
1475
+ "adapter.logPromptFailed": "session.prompt \uC2E4\uD328: {message}",
1476
+ "adapter.logAbortSent": "\uC911\uB2E8 \uC804\uC1A1\uB428 (session={session})",
1477
+ "adapter.errUserDenied": "\uC0AC\uC6A9\uC790\uAC00 \uAC70\uBD80\uD568",
1478
+ "adapter.logPendingResent": "session.pending: \uBCF4\uB958 \uC911\uC778 \uC694\uCCAD {count}\uAC74 \uC7AC\uC804\uC1A1",
1479
+ "adapter.logWorkspaceSwitched": "\uC791\uC5C5 \uACF5\uAC04 \uC804\uD658: {path}",
1480
+ "adapter.logNewSession": "\uC0C8 \uC138\uC158 \uC800\uC7A5\uB428 codexId={codexId} (alias={session})",
1481
+ "adapter.logSessionError": "\uD134 \uC624\uB958 (session={session}): {message}",
1482
+ "adapter.logDshSent": "dsh\uB85C \uC804\uC1A1\uB428 (session={session})",
1483
+ "adapter.logReadHistoryFailed": "\uC138\uC158 \uAE30\uB85D \uC77D\uAE30 \uC2E4\uD328({session}): {message}",
1484
+ "adapter.logAnswererInitFailed": "\uC751\uB2F5\uC790 \uCD08\uAE30\uD654 \uC2E4\uD328: {message}",
1485
+ "adapter.logRemoteMode": "\uC591\uB2E8 \uB3D9\uC2DC \uD45C\uC2DC \uBAA8\uB4DC: \uC120\uD0DD/\uC2B9\uC778\uC740 typert \uB2E4\uC911 \uD074\uB77C\uC774\uC5B8\uD2B8 \uBE0C\uB85C\uB4DC\uCE90\uC2A4\uD2B8\uB97C \uC0AC\uC6A9\uD558\uBA70 \uC2A4\uB9C8\uD2B8\uD3F0\uACFC dsh web\uC774 \uAC19\uC740 \uD654\uBA74\uC744 \uACF5\uC720\uD558\uACE0 \uBA3C\uC800 \uB2F5\uD55C \uCABD\uC774 \uC801\uC6A9\uB429\uB2C8\uB2E4",
1486
+ "adapter.logRemoteProbeFailed": "typert \uC6D0\uACA9 \uC774\uBCA4\uD2B8 \uC18C\uC2A4 \uD0D0\uC0C9 \uC2E4\uD328. \uB85C\uCEEC \uC751\uB2F5 \uBAA8\uB4DC\uB85C \uB300\uCCB4\uD569\uB2C8\uB2E4: {message}",
1487
+ "adapter.logLocalMode": "\uB85C\uCEEC \uC751\uB2F5 \uBAA8\uB4DC: \uC120\uD0DD/\uC2B9\uC778\uC740 \uC2A4\uB9C8\uD2B8\uD3F0\uC774 \uC751\uB2F5(headless, dsh web \uBE0C\uB85C\uB4DC\uCE90\uC2A4\uD2B8 \uC5C6\uC74C)",
1488
+ "adapter.logRemoteStreamInterrupted": "remote events \uC2A4\uD2B8\uB9BC \uC911\uB2E8: {message}",
1489
+ "adapter.logResultRejected": "$events/result \uC218\uB77D\uB418\uC9C0 \uC54A\uC74C({eventId}): {message}",
1490
+ "adapter.logResultBackfillFailed": "$events/result \uC7AC\uAE30\uC785 \uC2E4\uD328({eventId}): {message}",
1491
+ "adapter.logRemoteQuestion": "remote \uC9C8\uBB38 \uBE0C\uB85C\uB4DC\uCE90\uC2A4\uD2B8 \u2192 \uC2A4\uB9C8\uD2B8\uD3F0 \uC9C8\uBB38 \uCE74\uB4DC questionID={id} (session={session})",
1492
+ "adapter.errRemoteReadyFrame": "remote events \uCCAB \uD504\uB808\uC784 \uC774\uC0C1",
1493
+ "adapter.logRemoteApproval": "remote \uC2B9\uC778 \uBE0C\uB85C\uB4DC\uCE90\uC2A4\uD2B8 \u2192 \uC2A4\uB9C8\uD2B8\uD3F0 \uAD8C\uD55C \uCE74\uB4DC permissionID={id} (session={session})",
1494
+ "adapter.logUserQuestionRoute": "user-questions \uC120\uD0DD \u2192 session={session}\uC73C\uB85C \uB77C\uC6B0\uD305",
1495
+ "adapter.errDshQuestionEmpty": "dsh \uC9C8\uBB38 \uB0B4\uC6A9\uC774 \uBE44\uC5B4 \uC788\uC2B5\uB2C8\uB2E4",
1496
+ "adapter.errQuestionTimeout": "\uC9C8\uBB38 \uC2DC\uAC04 \uCD08\uACFC({seconds}s), \uCDE8\uC18C\uB428",
1497
+ "adapter.errQuestionCancelledAbort": "\uC9C8\uBB38 \uCDE8\uC18C\uB428(\uC5D0\uC774\uC804\uD2B8 \uC911\uB2E8)",
1498
+ "adapter.errQuestionCancelledRelay": "\uB9B4\uB808\uC774\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC5B4 \uC9C8\uBB38\uC774 \uCDE8\uC18C\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1499
+ "adapter.logQuestionToPhone": "user-questions \uC120\uD0DD \u2192 \uC2A4\uB9C8\uD2B8\uD3F0 \uC9C8\uBB38 \uCE74\uB4DC\uB85C \uC804\uC1A1 questionID={id} (session={session})",
1500
+ "adapter.errQuestionUserCancelled": "\uC0AC\uC6A9\uC790\uAC00 \uC2A4\uB9C8\uD2B8\uD3F0\uC5D0\uC11C \uC9C8\uBB38\uC744 \uCDE8\uC18C/\uAC70\uBD80\uD588\uC2B5\uB2C8\uB2E4",
1501
+ "adapter.logApprovalRequest": "\uC2B9\uC778 \uC694\uCCAD(tool={tool}) \u2192 \uC2A4\uB9C8\uD2B8\uD3F0 \uAD8C\uD55C \uCE74\uB4DC\uB85C \uC804\uC1A1 permissionID={id}",
1502
+ "adapter.logAgentPresetFailed": "agentPreset \uD574\uC11D \uC2E4\uD328({preset}), preset \uC5C6\uC774 \uB300\uCCB4: {message}",
1503
+ "adapter.logSessionLiveAdopted": "\uC138\uC158 {session}\uC740 \uC774 \uD504\uB85C\uC138\uC2A4\uC758 \uB2E4\uB978 \uC5D0\uC774\uC804\uD2B8\uAC00 \uBCF4\uC720 \uC911(live)\uC785\uB2C8\uB2E4. \uAE30\uC874 \uC5D0\uC774\uC804\uD2B8\uB97C \uCC44\uD0DD\uD558\uC5EC \uACC4\uC18D\uD569\uB2C8\uB2E4: {message}",
1504
+ "adapter.logDisposeSkipped": "\uCC44\uD0DD\uD55C \uC678\uBD80 live \uC5D0\uC774\uC804\uD2B8\uB294 dispose\uB97C \uC2E4\uD589\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4(\uC138\uC158 {session}\uC740 \uC6D0\uB798 \uBCF4\uC720\uC790\uAC00 \uAD00\uB9AC)",
1505
+ "adapter.logAgentCreateFailed": "\uC5D0\uC774\uC804\uD2B8 \uC0DD\uC131/\uBCF5\uC6D0 \uC2E4\uD328({session}): {message}",
1506
+ "adapter.errSessionBusyLive": "\uC138\uC158 {session}\uC774 \uC0AC\uC6A9 \uC911(live)\uC785\uB2C8\uB2E4. \uB098\uC911\uC5D0 \uB2E4\uC2DC \uC2DC\uB3C4\uD558\uC138\uC694",
1507
+ "adapter.errAgentsUnavailable": "agents \uC11C\uBE44\uC2A4\uB97C \uC0AC\uC6A9\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4",
1508
+ "adapter.logToolReason": "dsh\uAC00 \uB3C4\uAD6C {tool} \uC2E4\uD589\uC744 \uC694\uCCAD\uD569\uB2C8\uB2E4",
1509
+ "adapter.logGatewayConnected": "\uB85C\uCEEC OpenClaw Gateway\uC5D0 \uC5F0\uACB0\uB428({version})",
1510
+ "adapter.logGatewayDisconnected": "OpenClaw Gateway\uC640 \uC5F0\uACB0\uC774 \uB04A\uC5B4\uC84C\uC2B5\uB2C8\uB2E4. \uACF5\uC2DD \uD074\uB77C\uC774\uC5B8\uD2B8\uAC00 \uC7AC\uC5F0\uACB0 \uC911\u2026",
1511
+ "adapter.logGatewayConnectFailed": "\uB85C\uCEEC OpenClaw Gateway\uC5D0 \uC5F0\uACB0\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4(\uCD5C\uCD08\uC5D0\uB294 \uB85C\uCEEC\uC5D0\uC11C \uC7A5\uCE58\uB97C \uC2B9\uC778\uD558\uC138\uC694: `openclaw devices list` + `openclaw devices approve <requestId>`)",
1512
+ "adapter.errGatewayNoSessionKey": "Gateway\uAC00 \uC138\uC158 key\uB97C \uBC18\uD658\uD558\uC9C0 \uC54A\uC558\uC2B5\uB2C8\uB2E4",
1513
+ "adapter.logDeleteSessionFailed": "\uC138\uC158 \uC0AD\uC81C \uC2E4\uD328({session}): {message}(\uC0AD\uC81C\uB428\uC73C\uB85C \uC751\uB2F5)",
1514
+ "adapter.logApprovalReplyFailed": "\uC2B9\uC778 \uC751\uB2F5 \uC2E4\uD328({id}): {message}",
1515
+ "adapter.logPendingApproval": "session.pending: \uBCF4\uB958 \uC911\uC778 \uC2B9\uC778 {count}\uAC74 \uC7AC\uC804\uC1A1 (session={session})",
1516
+ "adapter.workspaceDefault": "\uAE30\uBCF8",
1517
+ "adapter.cursorSessionTitle": "Cursor \uC138\uC158",
1518
+ "adapter.reasonDisconnect": "\uB9B4\uB808\uC774 \uC5F0\uACB0 \uB04A\uAE40, \uC790\uB3D9 \uAC70\uBD80(fail-closed)",
1519
+ "adapter.warnInvalidEnv": "\uC798\uBABB\uB41C {name} \uBB34\uC2DC: {raw}({list})",
1520
+ "adapter.errStartFailed": "\uC2DC\uC791 \uC2E4\uD328:",
1521
+ "adapter.msgStarted": "{name} \uC5B4\uB311\uD130 \uC2DC\uC791\uB428(Ctrl+C\uB85C \uC885\uB8CC)",
1522
+ "adapter.warnCliMissing": "\uC2E4\uD589 \uD30C\uC77C '{bin}'\uC744(\uB97C) \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4. \uC124\uCE58\uD558\uAC70\uB098(\uC608: npm i -g @openai/codex) TUNNELBOX_CODEX_BIN\uC73C\uB85C \uACBD\uB85C\uB97C \uC9C0\uC815\uD558\uC138\uC694",
1523
+ "adapter.errCliNotFound": "{name} \uC2E4\uD589 \uD30C\uC77C '{bin}'\uC744(\uB97C) \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: Codex CLI\uB97C \uC124\uCE58(npm i -g @openai/codex)\uD558\uAC70\uB098 TUNNELBOX_CODEX_BIN\uC744 \uC124\uC815\uD558\uC138\uC694",
1524
+ "adapter.errSessionNotFound": "\uC138\uC158\uC774 \uC874\uC7AC\uD558\uC9C0 \uC54A\uAC70\uB098 \uC774\uBBF8 \uC0AD\uC81C\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1525
+ "adapter.checkHeader": "tunnelbox-codex \uD658\uACBD \uC810\uAC80",
1526
+ "adapter.checkCliOk": "{name} \uC2E4\uD589 \uD30C\uC77C: {path}",
1527
+ "adapter.checkCliMissing": "{name} \uC2E4\uD589 \uD30C\uC77C\uC744 \uCC3E\uC744 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4({bin})",
1528
+ "bin.yes": "\uC608",
1529
+ "bin.no": "\uC544\uB2C8\uC694",
1530
+ "adapter.errAppServerSpawn": "codex app-server \uB97C \uC2DC\uC791\uD560 \uC218 \uC5C6\uC2B5\uB2C8\uB2E4: {message} (Codex CLI \uAC00 `codex app-server` \uB97C \uC9C0\uC6D0\uD558\uB294\uC9C0 \uD655\uC778\uD558\uC138\uC694)",
1531
+ "adapter.errAppServerExit": "codex app-server \uAC00 \uC885\uB8CC\uB418\uC5C8\uC2B5\uB2C8\uB2E4. \uB300\uAE30 \uC911\uC778 \uC2B9\uC778/\uC120\uD0DD\uC740 \uC790\uB3D9\uC73C\uB85C \uAC70\uBD80\uB418\uC5C8\uC2B5\uB2C8\uB2E4",
1532
+ "adapter.logUnsupportedServerRequest": "\uC9C0\uC6D0\uB418\uC9C0 \uC54A\uB294 app-server \uC694\uCCAD: {method}",
1533
+ "adapter.logQuestionNative": "\uC120\uD0DD \uC694\uCCAD -> \uD734\uB300\uD3F0 \uC120\uD0DD \uCE74\uB4DC questionID={id} (session={session})",
1534
+ "adapter.logPermissionNative": "\uC2B9\uC778 \uC694\uCCAD -> \uD734\uB300\uD3F0 \uC2B9\uC778 \uCE74\uB4DC permissionID={id} (session={session})",
1535
+ "adapter.checkAppServerOk": "codex app-server \uC0AC\uC6A9 \uAC00\uB2A5",
1536
+ "adapter.checkAppServerMissing": "\uC774 Codex CLI \uB294 `codex app-server` \uB97C \uC9C0\uC6D0\uD558\uC9C0 \uC54A\uC2B5\uB2C8\uB2E4 (Codex CLI \uB97C \uC5C5\uADF8\uB808\uC774\uB4DC\uD558\uC138\uC694)"
986
1537
  };
987
1538
  var fr_FR_default = {
988
1539
  "agent.err.createSession": "\xC9chec de la cr\xE9ation de la session",
@@ -1033,7 +1584,7 @@ var fr_FR_default = {
1033
1584
  "install.scanHint": "Ouvrez tunnelbox sur votre t\xE9l\xE9phone, touchez \u201CScanner pour appairer\u201D, puis scannez le QR ci-dessus pour connecter :",
1034
1585
  "pair.heading": "Appairage t\xE9l\xE9phone tunnelbox",
1035
1586
  "pair.howTo": "Ouvrez l'application tunnelbox sur votre t\xE9l\xE9phone, scannez le QR ci-dessus avec \u201CScanner pour appairer\u201D, ou saisissez le code d'appairage manuellement.",
1036
- "pair.oneTime": "Le code d'appairage est \xE0 usage unique et expire apr\xE8s utilisation ; demandez \xE0 \u201Craffra\xEEchir le code d'appairage\u201D pour en obtenir un nouveau.",
1587
+ "pair.oneTime": "Le code d'appairage est \xE0 usage unique et valable environ 10 minutes ; il devient inutilisable une fois utilis\xE9 ou expir\xE9. Demandez \xAB rafra\xEEchir le code d'appairage \xBB pour en obtenir un nouveau.",
1037
1588
  "pair.promptBody": "Veuillez afficher les informations d'appairage t\xE9l\xE9phone de cet ordinateur : le code d'appairage et un QR code scannable. Gardez le QR code dans un bloc de code \xE0 largeur fixe et reproduisez-le caract\xE8re par caract\xE8re pour que mon t\xE9l\xE9phone puisse le scanner.",
1038
1589
  "pair.promptDescription": "Afficher le code d'appairage et le QR code scannable",
1039
1590
  "pair.scanIntro": "**Appairer par scan** : ouvrez l'application tunnelbox sur votre t\xE9l\xE9phone, touchez \u201CScanner pour appairer\u201D, puis scannez le QR ci-dessous pour vous connecter automatiquement.",
@@ -1148,7 +1699,118 @@ var fr_FR_default = {
1148
1699
  "hermes.pairTimeout": "D\xE9lai d\xE9pass\xE9 pour le code d'appairage (relais sans r\xE9ponse)",
1149
1700
  "hermes.errToolPair": "\xE9chec de tunnelbox_pair : {err}",
1150
1701
  "hermes.errToolStatus": "\xE9chec de tunnelbox_status : {err}",
1151
- "hermes.cliUsage": "Utilisation : /tunnelbox <pair|status>\n pair demander et afficher un code d'appairage\n status afficher l'\xE9tat relais/liaison/connexion"
1702
+ "hermes.cliUsage": "Utilisation : /tunnelbox <pair|status>\n pair demander et afficher un code d'appairage\n status afficher l'\xE9tat relais/liaison/connexion",
1703
+ "qr.validFor": "Le code d'appairage est valable environ 10 minutes ; s'il expire, r\xE9cup\xE9rez-en un nouveau sur votre ordinateur.",
1704
+ "pair.toolDesc": "Affiche les informations d'appairage t\xE9l\xE9phone de cet ordinateur (code d'appairage et QR code scannable). \xC0 appeler lorsque l'utilisateur parle d'appairage, de scan de QR code ou de contr\xF4le de cet ordinateur depuis son t\xE9l\xE9phone.",
1705
+ "pair.toolRefreshDesc": "Demander ou non un nouveau code d'appairage au relais",
1706
+ "state.errSaveState": "\xC9chec de l'enregistrement de l'\xE9tat",
1707
+ "adapter.logConnected": "Connect\xE9 au relais {url}",
1708
+ "adapter.logDisconnected": "D\xE9connect\xE9 du relais, reconnexion automatique\u2026",
1709
+ "adapter.logPairCode": "Code d'appairage g\xE9n\xE9r\xE9 : {code}",
1710
+ "adapter.logClaimed": "Associ\xE9 \xE0 votre compte t\xE9l\xE9phone. D\xE9sormais, le t\xE9l\xE9phone se connecte directement depuis \xAB Mes ordinateurs \xBB",
1711
+ "adapter.logResetIdentity": "Dissoci\xE9 du compte ; r\xE9initialisation de l'identit\xE9 et g\xE9n\xE9ration d'un nouveau code d'appairage\u2026",
1712
+ "adapter.logUnhandledType": "Type de message non g\xE9r\xE9 : {type}",
1713
+ "adapter.errNoRelay": "Aucune URL de relais configur\xE9e : compilez avec --env pour injecter une valeur par d\xE9faut, ou remplacez-la \xE0 l'ex\xE9cution avec TUNNELBOX_RELAY_URL",
1714
+ "adapter.errBusy": "Cette session est toujours en cours ; attendez la fin ou arr\xEAtez-la d'abord",
1715
+ "adapter.errBadWorkspaceEmpty": "Chemin d'espace de travail manquant",
1716
+ "adapter.errBadWorkspaceNotDir": "Le r\xE9pertoire n'existe pas ou est inutilisable",
1717
+ "adapter.errWorkspaceMissing": "L'espace de travail n'existe pas : {dir}",
1718
+ "adapter.cmdNew": "Nouvelle session",
1719
+ "adapter.cmdHelp": "Afficher l'aide",
1720
+ "adapter.helpText": "Commandes prises en charge :\n- /new nouvelle session\n- /help afficher l'aide",
1721
+ "adapter.newSessionTitle": "Nouvelle session",
1722
+ "install.langHelpTitle": "Langues prises en charge par install-local (--lang <tag>) :",
1723
+ "install.langHelpExample": "Exemple : npm run install-local -- --lang de-DE",
1724
+ "install.unknownLang": "Langue inconnue \xAB {raw} \xBB, retour \xE0 en-US. Prises en charge : {list}",
1725
+ "hermes.errAskRequired": "question est obligatoire",
1726
+ "hermes.msgPhoneUnavailable": "T\xE9l\xE9phone indisponible ou sans r\xE9ponse : utilisez le clarify int\xE9gr\xE9 pour poser la question localement, ou d\xE9cidez par vous-m\xEAme.",
1727
+ "hermes.errClarifyUnavailable": "Prise en charge de clarify indisponible",
1728
+ "hermes.errAskFailed": "\xC9chec de tunnelbox_ask : {err}",
1729
+ "hermes.errClarifyFailed": "\xC9chec de clarify : {err}",
1730
+ "bin.denied": "Refus\xE9 depuis votre t\xE9l\xE9phone",
1731
+ "bin.timeout": "D\xE9lai d'approbation d\xE9pass\xE9 (fail-closed)",
1732
+ "bin.reqRun": "Claude Code demande d'ex\xE9cuter {tool}",
1733
+ "bin.pairTitle": "Appairage t\xE9l\xE9phone tunnelbox",
1734
+ "bin.pairCodeLine": " Code d'appairage : {code}",
1735
+ "bin.pairHint": "Ouvrez l'app tunnelbox, touchez \xAB Scanner pour appairer \xBB et scannez le QR code, ou saisissez le code d'appairage manuellement (usage unique).",
1736
+ "bin.pairWritten": " Infos d'appairage \xE9crites dans : {path}",
1737
+ "bin.pairRequestFailed": "\xC9chec de la demande de code d'appairage au relais.",
1738
+ "bin.alreadyClaimed": "Cet ordinateur est d\xE9j\xE0 associ\xE9 \xE0 un compte t\xE9l\xE9phone ; connectez-vous directement depuis \xAB Mes ordinateurs \xBB. Pour r\xE9appairer, dissociez-le d'abord sur votre t\xE9l\xE9phone.",
1739
+ "bin.noRelay": "Aucune URL de relais configur\xE9e : d\xE9finissez TUNNELBOX_RELAY_URL puis r\xE9essayez.",
1740
+ "bin.connectFailed": "Impossible de se connecter au relais : {relay}\nD\xE9finissez TUNNELBOX_RELAY_URL ou configurez-le dans le fichier d'\xE9tat official-plugin.",
1741
+ "bin.statusRelay": "Relais : {value}",
1742
+ "bin.statusAgent": "ID de l'agent : {value}",
1743
+ "bin.statusClaimed": "T\xE9l\xE9phone associ\xE9 : {value}",
1744
+ "bin.statusStateFile": "Fichier d'\xE9tat : {value}",
1745
+ "bin.statusLatest": "Derni\xE8res infos d'appairage :",
1746
+ "bin.usage": "Utilisation : tunnelbox <pair|status|ask>",
1747
+ "bin.usagePair": " pair demander et afficher un code d'appairage t\xE9l\xE9phone",
1748
+ "bin.usageStatus": " status afficher l'\xE9tat du relais/de l'association",
1749
+ "bin.usageAsk": " ask transf\xE9rer une approbation d'outil au t\xE9l\xE9phone",
1750
+ "adapter.logMsgUncaught": "Exception non intercept\xE9e lors du traitement du message : {message}",
1751
+ "adapter.logHandleFailed": "\xC9chec du traitement de {type} : {message}",
1752
+ "adapter.logPromptFailed": "\xC9chec de session.prompt : {message}",
1753
+ "adapter.logAbortSent": "Interruption envoy\xE9e (session={session})",
1754
+ "adapter.errUserDenied": "Refus\xE9 par l'utilisateur",
1755
+ "adapter.logPendingResent": "session.pending : {count} demande(s) en attente renvoy\xE9e(s)",
1756
+ "adapter.logWorkspaceSwitched": "Espace de travail chang\xE9 : {path}",
1757
+ "adapter.logNewSession": "Nouvelle session enregistr\xE9e codexId={codexId} (alias={session})",
1758
+ "adapter.logSessionError": "Erreur de tour (session={session}) : {message}",
1759
+ "adapter.logDshSent": "Envoy\xE9 \xE0 dsh (session={session})",
1760
+ "adapter.logReadHistoryFailed": "\xC9chec de lecture de l'historique de session ({session}) : {message}",
1761
+ "adapter.logAnswererInitFailed": "\xC9chec d'initialisation du r\xE9pondeur : {message}",
1762
+ "adapter.logRemoteMode": "Mode double affichage : les s\xE9lections/approbations passent par la diffusion multi-clients typert ; t\xE9l\xE9phone et dsh web partagent la vue, la premi\xE8re r\xE9ponse l'emporte",
1763
+ "adapter.logRemoteProbeFailed": "\xC9chec de d\xE9tection de la source d'\xE9v\xE9nements distante typert ; retour au mode de r\xE9ponse local : {message}",
1764
+ "adapter.logLocalMode": "Mode de r\xE9ponse local : s\xE9lections/approbations trait\xE9es par le t\xE9l\xE9phone (headless, sans diffusion dsh web)",
1765
+ "adapter.logRemoteStreamInterrupted": "Flux remote events interrompu : {message}",
1766
+ "adapter.logResultRejected": "$events/result non accept\xE9 ({eventId}) : {message}",
1767
+ "adapter.logResultBackfillFailed": "\xC9chec du renvoi de $events/result ({eventId}) : {message}",
1768
+ "adapter.logRemoteQuestion": "Diffusion de question remote \u2192 carte de question t\xE9l\xE9phone questionID={id} (session={session})",
1769
+ "adapter.errRemoteReadyFrame": "Premi\xE8re trame remote events inattendue",
1770
+ "adapter.logRemoteApproval": "Diffusion d'approbation remote \u2192 carte d'autorisation t\xE9l\xE9phone permissionID={id} (session={session})",
1771
+ "adapter.logUserQuestionRoute": "S\xE9lection user-questions \u2192 rout\xE9e vers session={session}",
1772
+ "adapter.errDshQuestionEmpty": "Le contenu de la question dsh est vide",
1773
+ "adapter.errQuestionTimeout": "D\xE9lai de question d\xE9pass\xE9 ({seconds}s), annul\xE9e",
1774
+ "adapter.errQuestionCancelledAbort": "Question annul\xE9e (agent interrompu)",
1775
+ "adapter.errQuestionCancelledRelay": "Relais injoignable, question annul\xE9e",
1776
+ "adapter.logQuestionToPhone": "S\xE9lection user-questions \u2192 envoy\xE9e \xE0 la carte de question du t\xE9l\xE9phone questionID={id} (session={session})",
1777
+ "adapter.errQuestionUserCancelled": "L'utilisateur a annul\xE9/refus\xE9 la question sur le t\xE9l\xE9phone",
1778
+ "adapter.logApprovalRequest": "Demande d'approbation (tool={tool}) \u2192 envoy\xE9e \xE0 la carte d'autorisation du t\xE9l\xE9phone permissionID={id}",
1779
+ "adapter.logAgentPresetFailed": "\xC9chec de r\xE9solution d'agentPreset ({preset}) ; retour sans preset : {message}",
1780
+ "adapter.logSessionLiveAdopted": "La session {session} est d\xE9j\xE0 d\xE9tenue par un autre agent de ce processus (live) ; adoption de l'agent existant pour continuer : {message}",
1781
+ "adapter.logDisposeSkipped": "L'agent live externe adopt\xE9 n'ex\xE9cute pas dispose (la session {session} est g\xE9r\xE9e par son d\xE9tenteur d'origine)",
1782
+ "adapter.logAgentCreateFailed": "\xC9chec de cr\xE9ation/reprise de l'agent ({session}) : {message}",
1783
+ "adapter.errSessionBusyLive": "La session {session} est occup\xE9e (live) ; r\xE9essayez plus tard",
1784
+ "adapter.errAgentsUnavailable": "Service agents indisponible",
1785
+ "adapter.logToolReason": "dsh demande d'ex\xE9cuter l'outil {tool}",
1786
+ "adapter.logGatewayConnected": "Connect\xE9 au Gateway OpenClaw local ({version})",
1787
+ "adapter.logGatewayDisconnected": "D\xE9connect\xE9 du Gateway OpenClaw ; le client officiel se reconnecte\u2026",
1788
+ "adapter.logGatewayConnectFailed": "Impossible de se connecter au Gateway OpenClaw local (la premi\xE8re fois, approuvez l'appareil en local : `openclaw devices list` + `openclaw devices approve <requestId>`)",
1789
+ "adapter.errGatewayNoSessionKey": "Le Gateway n'a pas renvoy\xE9 de cl\xE9 de session",
1790
+ "adapter.logDeleteSessionFailed": "\xC9chec de suppression de session ({session}) : {message} (accus\xE9 de suppression tout de m\xEAme)",
1791
+ "adapter.logApprovalReplyFailed": "\xC9chec de la r\xE9ponse d'approbation ({id}) : {message}",
1792
+ "adapter.logPendingApproval": "session.pending : {count} approbation(s) en attente renvoy\xE9e(s) (session={session})",
1793
+ "adapter.workspaceDefault": "Par d\xE9faut",
1794
+ "adapter.cursorSessionTitle": "Session Cursor",
1795
+ "adapter.reasonDisconnect": "Relais d\xE9connect\xE9, refus automatique (fail-closed)",
1796
+ "adapter.warnInvalidEnv": "Valeur {name} invalide ignor\xE9e : {raw} ({list})",
1797
+ "adapter.errStartFailed": "\xC9chec du d\xE9marrage :",
1798
+ "adapter.msgStarted": "Adaptateur {name} d\xE9marr\xE9 (Ctrl+C pour quitter)",
1799
+ "adapter.warnCliMissing": "Ex\xE9cutable \xAB {bin} \xBB introuvable ; installez-le (ex. npm i -g @openai/codex) ou d\xE9finissez TUNNELBOX_CODEX_BIN avec son chemin",
1800
+ "adapter.errCliNotFound": "Ex\xE9cutable {name} \xAB {bin} \xBB introuvable : installez le Codex CLI (npm i -g @openai/codex) ou d\xE9finissez TUNNELBOX_CODEX_BIN",
1801
+ "adapter.errSessionNotFound": "Session introuvable ou d\xE9j\xE0 supprim\xE9e",
1802
+ "adapter.checkHeader": "V\xE9rification de l'environnement tunnelbox-codex",
1803
+ "adapter.checkCliOk": "Ex\xE9cutable {name} : {path}",
1804
+ "adapter.checkCliMissing": "Ex\xE9cutable {name} introuvable ({bin})",
1805
+ "bin.yes": "oui",
1806
+ "bin.no": "non",
1807
+ "adapter.errAppServerSpawn": "Impossible de d\xE9marrer codex app-server : {message} (v\xE9rifiez que votre Codex CLI prend en charge `codex app-server`)",
1808
+ "adapter.errAppServerExit": "codex app-server s'est arr\xEAt\xE9 ; les approbations/choix en attente ont \xE9t\xE9 refus\xE9s automatiquement",
1809
+ "adapter.logUnsupportedServerRequest": "requ\xEAte app-server non prise en charge : {method}",
1810
+ "adapter.logQuestionNative": "demande de choix -> carte de choix du t\xE9l\xE9phone questionID={id} (session={session})",
1811
+ "adapter.logPermissionNative": "demande d'approbation -> carte d'approbation du t\xE9l\xE9phone permissionID={id} (session={session})",
1812
+ "adapter.checkAppServerOk": "codex app-server disponible",
1813
+ "adapter.checkAppServerMissing": "ce Codex CLI ne prend pas en charge `codex app-server` (veuillez mettre \xE0 jour Codex CLI)"
1152
1814
  };
1153
1815
  var de_DE_default = {
1154
1816
  "agent.err.createSession": "Sitzung konnte nicht erstellt werden",
@@ -1199,7 +1861,7 @@ var de_DE_default = {
1199
1861
  "install.scanHint": "\xD6ffnen Sie tunnelbox auf dem Telefon, tippen Sie auf \u201CZum Pairing scannen\u201D und scannen Sie den QR-Code oben zum Verbinden:",
1200
1862
  "pair.heading": "tunnelbox Telefon-Pairing",
1201
1863
  "pair.howTo": "\xD6ffnen Sie die tunnelbox-App auf dem Telefon und scannen Sie den QR-Code oben mit \u201CZum Pairing scannen\u201D, oder geben Sie den Pairing-Code manuell ein.",
1202
- "pair.oneTime": "Der Pairing-Code ist einmalig und verf\xE4llt nach der Nutzung; f\xFCr einen neuen Code \u201CPairing-Code aktualisieren\u201D anfordern.",
1864
+ "pair.oneTime": "Der Kopplungscode ist einmalig und etwa 10 Minuten g\xFCltig; nach Nutzung oder Ablauf wird er ung\xFCltig. Fordern Sie zum Erneuern \u201EKopplungscode aktualisieren\u201C an.",
1203
1865
  "pair.promptBody": "Zeigen Sie bitte die Telefon-Pairing-Informationen dieses Computers an: den Pairing-Code und einen scannbaren QR-Code. Behalten Sie den QR-Code in einem Codeblock mit fester Breite und geben Sie ihn zeichengenau wieder, damit mein Telefon ihn scannen kann.",
1204
1866
  "pair.promptDescription": "Pairing-Code und scannbaren QR-Code anzeigen",
1205
1867
  "pair.scanIntro": "**Per Scan pairen**: \xD6ffnen Sie die tunnelbox-App auf dem Telefon, tippen Sie auf \u201CZum Pairing scannen\u201D und scannen Sie den QR-Code unten, um sich automatisch zu verbinden.",
@@ -1314,7 +1976,118 @@ var de_DE_default = {
1314
1976
  "hermes.pairTimeout": "Zeit\xFCberschreitung bei der Pairing-Code-Anfrage (Relay antwortete nicht)",
1315
1977
  "hermes.errToolPair": "tunnelbox_pair fehlgeschlagen: {err}",
1316
1978
  "hermes.errToolStatus": "tunnelbox_status fehlgeschlagen: {err}",
1317
- "hermes.cliUsage": "Verwendung: /tunnelbox <pair|status>\n pair Pairing-Code anfordern und anzeigen\n status Relay/Bindung/Verbindung anzeigen"
1979
+ "hermes.cliUsage": "Verwendung: /tunnelbox <pair|status>\n pair Pairing-Code anfordern und anzeigen\n status Relay/Bindung/Verbindung anzeigen",
1980
+ "qr.validFor": "Der Kopplungscode ist etwa 10 Minuten g\xFCltig; holen Sie bei Ablauf einen neuen auf Ihrem Computer.",
1981
+ "pair.toolDesc": "Zeigt die Telefon-Kopplungsinfo dieses Computers (Kopplungscode und scannbarer QR-Code). Aufrufen, wenn der Nutzer nach Kopplung, QR-Code-Scan oder Steuerung dieses Computers vom Telefon fragt.",
1982
+ "pair.toolRefreshDesc": "Ob ein neuer Kopplungscode vom Relay angefordert werden soll",
1983
+ "state.errSaveState": "Status konnte nicht gespeichert werden",
1984
+ "adapter.logConnected": "Mit Relay verbunden {url}",
1985
+ "adapter.logDisconnected": "Vom Relay getrennt, automatische Wiederverbindung\u2026",
1986
+ "adapter.logPairCode": "Kopplungscode erzeugt: {code}",
1987
+ "adapter.logClaimed": "Mit Ihrem Telefonkonto verkn\xFCpft. Ab jetzt verbindet sich das Telefon direkt \xFCber \u201EMeine Computer\u201C",
1988
+ "adapter.logResetIdentity": "Vom Konto getrennt; Identit\xE4t wird zur\xFCckgesetzt und neuer Kopplungscode erzeugt\u2026",
1989
+ "adapter.logUnhandledType": "Unbehandelter Nachrichtentyp: {type}",
1990
+ "adapter.errNoRelay": "Keine Relay-URL konfiguriert: mit --env einen Standardwert einbauen oder zur Laufzeit mit TUNNELBOX_RELAY_URL \xFCberschreiben",
1991
+ "adapter.errBusy": "Diese Sitzung l\xE4uft noch; warten Sie auf den Abschluss oder stoppen Sie sie zuerst",
1992
+ "adapter.errBadWorkspaceEmpty": "Arbeitsbereich-Pfad fehlt",
1993
+ "adapter.errBadWorkspaceNotDir": "Verzeichnis existiert nicht oder ist unbrauchbar",
1994
+ "adapter.errWorkspaceMissing": "Arbeitsbereich existiert nicht: {dir}",
1995
+ "adapter.cmdNew": "Neue Sitzung",
1996
+ "adapter.cmdHelp": "Hilfe anzeigen",
1997
+ "adapter.helpText": "Unterst\xFCtzte Befehle:\n- /new neue Sitzung\n- /help Hilfe anzeigen",
1998
+ "adapter.newSessionTitle": "Neue Sitzung",
1999
+ "install.langHelpTitle": "Von install-local unterst\xFCtzte Sprachen (--lang <tag>):",
2000
+ "install.langHelpExample": "Beispiel: npm run install-local -- --lang de-DE",
2001
+ "install.unknownLang": 'Unbekannte Sprache "{raw}", R\xFCckfall auf en-US. Unterst\xFCtzt: {list}',
2002
+ "hermes.errAskRequired": "question ist erforderlich",
2003
+ "hermes.msgPhoneUnavailable": "Telefon nicht verf\xFCgbar oder keine Antwort: Nutzen Sie das integrierte clarify f\xFCr eine lokale Frage oder entscheiden Sie selbst.",
2004
+ "hermes.errClarifyUnavailable": "clarify-Unterst\xFCtzung nicht verf\xFCgbar",
2005
+ "hermes.errAskFailed": "tunnelbox_ask fehlgeschlagen: {err}",
2006
+ "hermes.errClarifyFailed": "clarify fehlgeschlagen: {err}",
2007
+ "bin.denied": "Vom Telefon abgelehnt",
2008
+ "bin.timeout": "Genehmigung Zeit\xFCberschreitung (fail-closed)",
2009
+ "bin.reqRun": "Claude Code fordert die Ausf\xFChrung von {tool} an",
2010
+ "bin.pairTitle": "tunnelbox Telefon-Kopplung",
2011
+ "bin.pairCodeLine": " Kopplungscode: {code}",
2012
+ "bin.pairHint": "\xD6ffnen Sie die tunnelbox-App, tippen Sie auf \u201EZum Koppeln scannen\u201C und scannen Sie den QR-Code, oder geben Sie den Kopplungscode manuell ein (einmalig).",
2013
+ "bin.pairWritten": " Kopplungsinfo geschrieben nach: {path}",
2014
+ "bin.pairRequestFailed": "Anforderung eines Kopplungscodes vom Relay fehlgeschlagen.",
2015
+ "bin.alreadyClaimed": "Dieser Computer ist bereits mit einem Telefonkonto verkn\xFCpft; verbinden Sie sich direkt \xFCber \u201EMeine Computer\u201C. Zum erneuten Koppeln zuerst am Telefon trennen.",
2016
+ "bin.noRelay": "Keine Relay-URL konfiguriert: setzen Sie TUNNELBOX_RELAY_URL und versuchen Sie es erneut.",
2017
+ "bin.connectFailed": "Verbindung zum Relay nicht m\xF6glich: {relay}\nSetzen Sie TUNNELBOX_RELAY_URL oder konfigurieren Sie es in der official-plugin-Statusdatei.",
2018
+ "bin.statusRelay": "Relay: {value}",
2019
+ "bin.statusAgent": "Agent-ID: {value}",
2020
+ "bin.statusClaimed": "Telefon verkn\xFCpft: {value}",
2021
+ "bin.statusStateFile": "Statusdatei: {value}",
2022
+ "bin.statusLatest": "Neueste Kopplungsinfo:",
2023
+ "bin.usage": "Verwendung: tunnelbox <pair|status|ask>",
2024
+ "bin.usagePair": " pair Telefon-Kopplungscode anfordern und ausgeben",
2025
+ "bin.usageStatus": " status Relay-/Verkn\xFCpfungsstatus anzeigen",
2026
+ "bin.usageAsk": " ask eine Tool-Genehmigung ans Telefon weiterleiten",
2027
+ "adapter.logMsgUncaught": "Unabgefangene Ausnahme bei der Nachrichtenverarbeitung: {message}",
2028
+ "adapter.logHandleFailed": "Verarbeitung von {type} fehlgeschlagen: {message}",
2029
+ "adapter.logPromptFailed": "session.prompt fehlgeschlagen: {message}",
2030
+ "adapter.logAbortSent": "Abbruch gesendet (session={session})",
2031
+ "adapter.errUserDenied": "Vom Nutzer abgelehnt",
2032
+ "adapter.logPendingResent": "session.pending: {count} ausstehende Anfrage(n) erneut gesendet",
2033
+ "adapter.logWorkspaceSwitched": "Arbeitsbereich gewechselt: {path}",
2034
+ "adapter.logNewSession": "Neue Sitzung gespeichert codexId={codexId} (alias={session})",
2035
+ "adapter.logSessionError": "Turn-Fehler (session={session}): {message}",
2036
+ "adapter.logDshSent": "An dsh gesendet (session={session})",
2037
+ "adapter.logReadHistoryFailed": "Sitzungsverlauf lesen fehlgeschlagen ({session}): {message}",
2038
+ "adapter.logAnswererInitFailed": "Initialisierung des Antwortgebers fehlgeschlagen: {message}",
2039
+ "adapter.logRemoteMode": "Dualanzeige-Modus: Auswahl/Genehmigung \xFCber typert-Multi-Client-Broadcast; Telefon und dsh web teilen die Ansicht, die erste Antwort gewinnt",
2040
+ "adapter.logRemoteProbeFailed": "typert-Remote-Ereignisquellen-Pr\xFCfung fehlgeschlagen; R\xFCckfall auf lokalen Antwortmodus: {message}",
2041
+ "adapter.logLocalMode": "Lokaler Antwortmodus: Auswahl/Genehmigung erfolgt durch das Telefon (headless, ohne dsh web-Broadcast)",
2042
+ "adapter.logRemoteStreamInterrupted": "remote events-Stream unterbrochen: {message}",
2043
+ "adapter.logResultRejected": "$events/result nicht akzeptiert ({eventId}): {message}",
2044
+ "adapter.logResultBackfillFailed": "$events/result-R\xFCckschreiben fehlgeschlagen ({eventId}): {message}",
2045
+ "adapter.logRemoteQuestion": "remote-Frage-Broadcast \u2192 Telefon-Fragekarte questionID={id} (session={session})",
2046
+ "adapter.errRemoteReadyFrame": "Unerwarteter erster Frame von remote events",
2047
+ "adapter.logRemoteApproval": "remote-Genehmigungs-Broadcast \u2192 Telefon-Berechtigungskarte permissionID={id} (session={session})",
2048
+ "adapter.logUserQuestionRoute": "user-questions-Auswahl \u2192 weitergeleitet an session={session}",
2049
+ "adapter.errDshQuestionEmpty": "dsh-Frageinhalt ist leer",
2050
+ "adapter.errQuestionTimeout": "Frage-Zeit\xFCberschreitung ({seconds}s), abgebrochen",
2051
+ "adapter.errQuestionCancelledAbort": "Frage abgebrochen (Agent abgebrochen)",
2052
+ "adapter.errQuestionCancelledRelay": "Relay nicht erreichbar, Frage abgebrochen",
2053
+ "adapter.logQuestionToPhone": "user-questions-Auswahl \u2192 an Telefon-Fragekarte gesendet questionID={id} (session={session})",
2054
+ "adapter.errQuestionUserCancelled": "Nutzer hat die Frage am Telefon abgebrochen/abgelehnt",
2055
+ "adapter.logApprovalRequest": "Genehmigungsanfrage (tool={tool}) \u2192 an Telefon-Berechtigungskarte gesendet permissionID={id}",
2056
+ "adapter.logAgentPresetFailed": "agentPreset-Aufl\xF6sung fehlgeschlagen ({preset}); R\xFCckfall ohne Preset: {message}",
2057
+ "adapter.logSessionLiveAdopted": "Sitzung {session} wird bereits von einem anderen Agent in diesem Prozess gehalten (live); vorhandener Agent wird \xFCbernommen: {message}",
2058
+ "adapter.logDisposeSkipped": "\xDCbernommener externer Live-Agent f\xFChrt dispose nicht aus (Sitzung {session} wird vom urspr\xFCnglichen Halter verwaltet)",
2059
+ "adapter.logAgentCreateFailed": "Agent erstellen/fortsetzen fehlgeschlagen ({session}): {message}",
2060
+ "adapter.errSessionBusyLive": "Sitzung {session} ist belegt (live); versuchen Sie es sp\xE4ter erneut",
2061
+ "adapter.errAgentsUnavailable": "agents-Dienst nicht verf\xFCgbar",
2062
+ "adapter.logToolReason": "dsh fordert die Ausf\xFChrung des Tools {tool} an",
2063
+ "adapter.logGatewayConnected": "Mit lokalem OpenClaw Gateway verbunden ({version})",
2064
+ "adapter.logGatewayDisconnected": "Vom OpenClaw Gateway getrennt; der offizielle Client verbindet sich neu\u2026",
2065
+ "adapter.logGatewayConnectFailed": "Verbindung zum lokalen OpenClaw Gateway nicht m\xF6glich (beim ersten Mal das Ger\xE4t lokal freigeben: `openclaw devices list` + `openclaw devices approve <requestId>`)",
2066
+ "adapter.errGatewayNoSessionKey": "Gateway hat keinen Sitzungsschl\xFCssel zur\xFCckgegeben",
2067
+ "adapter.logDeleteSessionFailed": "Sitzung l\xF6schen fehlgeschlagen ({session}): {message} (wird dennoch als gel\xF6scht best\xE4tigt)",
2068
+ "adapter.logApprovalReplyFailed": "Genehmigungsantwort fehlgeschlagen ({id}): {message}",
2069
+ "adapter.logPendingApproval": "session.pending: {count} ausstehende Genehmigung(en) erneut gesendet (session={session})",
2070
+ "adapter.workspaceDefault": "Standard",
2071
+ "adapter.cursorSessionTitle": "Cursor-Sitzung",
2072
+ "adapter.reasonDisconnect": "Relay getrennt, automatische Ablehnung (fail-closed)",
2073
+ "adapter.warnInvalidEnv": "Ung\xFCltiges {name} ignoriert: {raw} ({list})",
2074
+ "adapter.errStartFailed": "Start fehlgeschlagen:",
2075
+ "adapter.msgStarted": "{name}-Adapter gestartet (Ctrl+C zum Beenden)",
2076
+ "adapter.warnCliMissing": "Ausf\xFChrbare Datei \u201E{bin}\u201C nicht gefunden; installieren Sie sie (z. B. npm i -g @openai/codex) oder setzen Sie TUNNELBOX_CODEX_BIN auf ihren Pfad",
2077
+ "adapter.errCliNotFound": "Ausf\xFChrbare Datei {name} \u201E{bin}\u201C nicht gefunden: Installieren Sie die Codex CLI (npm i -g @openai/codex) oder setzen Sie TUNNELBOX_CODEX_BIN",
2078
+ "adapter.errSessionNotFound": "Sitzung nicht gefunden oder bereits gel\xF6scht",
2079
+ "adapter.checkHeader": "tunnelbox-codex-Umgebungspr\xFCfung",
2080
+ "adapter.checkCliOk": "Ausf\xFChrbare Datei {name}: {path}",
2081
+ "adapter.checkCliMissing": "Ausf\xFChrbare Datei {name} nicht gefunden ({bin})",
2082
+ "bin.yes": "ja",
2083
+ "bin.no": "nein",
2084
+ "adapter.errAppServerSpawn": "codex app-server konnte nicht gestartet werden: {message} (pr\xFCfen Sie, ob Ihre Codex CLI `codex app-server` unterst\xFCtzt)",
2085
+ "adapter.errAppServerExit": "codex app-server wurde beendet; ausstehende Genehmigungen/Auswahlen wurden automatisch abgelehnt",
2086
+ "adapter.logUnsupportedServerRequest": "nicht unterst\xFCtzte app-server-Anfrage: {method}",
2087
+ "adapter.logQuestionNative": "Auswahlanfrage -> Auswahlkarte am Handy questionID={id} (session={session})",
2088
+ "adapter.logPermissionNative": "Genehmigungsanfrage -> Genehmigungskarte am Handy permissionID={id} (session={session})",
2089
+ "adapter.checkAppServerOk": "codex app-server verf\xFCgbar",
2090
+ "adapter.checkAppServerMissing": "diese Codex CLI unterst\xFCtzt `codex app-server` nicht (bitte Codex CLI aktualisieren)"
1318
2091
  };
1319
2092
  var es_ES_default = {
1320
2093
  "agent.err.createSession": "No se pudo crear la sesi\xF3n",
@@ -1365,7 +2138,7 @@ var es_ES_default = {
1365
2138
  "install.scanHint": "Abra tunnelbox en el tel\xE9fono, pulse \u201CEscanear para emparejar\u201D y escanee el c\xF3digo QR superior para conectar:",
1366
2139
  "pair.heading": "Emparejamiento de tel\xE9fono tunnelbox",
1367
2140
  "pair.howTo": "Abra la aplicaci\xF3n tunnelbox en el tel\xE9fono y escanee el c\xF3digo QR superior con \u201CEscanear para emparejar\u201D, o introduzca el c\xF3digo de emparejamiento manualmente.",
1368
- "pair.oneTime": "El c\xF3digo de emparejamiento es de un solo uso y caduca al utilizarse; pida \u201Cactualizar el c\xF3digo de emparejamiento\u201D para obtener uno nuevo.",
2141
+ "pair.oneTime": "El c\xF3digo de emparejamiento es de un solo uso y v\xE1lido unos 10 minutos; deja de funcionar al usarse o caducar. Pida \xABactualizar el c\xF3digo de emparejamiento\xBB para obtener uno nuevo.",
1369
2142
  "pair.promptBody": "Mu\xE9strame la informaci\xF3n de emparejamiento con el tel\xE9fono de este ordenador: el c\xF3digo de emparejamiento y un c\xF3digo QR escaneable. Mant\xE9n el c\xF3digo QR dentro de un bloque de c\xF3digo de ancho fijo y reprod\xFAcelo car\xE1cter por car\xE1cter para que mi tel\xE9fono pueda escanearlo.",
1370
2143
  "pair.promptDescription": "Mostrar el c\xF3digo de emparejamiento y el QR escaneable",
1371
2144
  "pair.scanIntro": "**Emparejar escaneando**: abra la aplicaci\xF3n tunnelbox en el tel\xE9fono, pulse \u201CEscanear para emparejar\u201D y escanee el c\xF3digo QR inferior para conectar autom\xE1ticamente.",
@@ -1480,7 +2253,118 @@ var es_ES_default = {
1480
2253
  "hermes.pairTimeout": "Tiempo de espera agotado al solicitar el c\xF3digo de emparejamiento (rel\xE9 sin respuesta)",
1481
2254
  "hermes.errToolPair": "fallo de tunnelbox_pair: {err}",
1482
2255
  "hermes.errToolStatus": "fallo de tunnelbox_status: {err}",
1483
- "hermes.cliUsage": "Uso: /tunnelbox <pair|status>\n pair solicitar e imprimir un c\xF3digo de emparejamiento\n status mostrar estado de rel\xE9/enlace/conexi\xF3n"
2256
+ "hermes.cliUsage": "Uso: /tunnelbox <pair|status>\n pair solicitar e imprimir un c\xF3digo de emparejamiento\n status mostrar estado de rel\xE9/enlace/conexi\xF3n",
2257
+ "qr.validFor": "El c\xF3digo de emparejamiento es v\xE1lido durante unos 10 minutos; si caduca, obtenga uno nuevo en su computadora.",
2258
+ "pair.toolDesc": "Muestra la informaci\xF3n de emparejamiento telef\xF3nico de esta computadora (c\xF3digo de emparejamiento y c\xF3digo QR escaneable). Llamar cuando el usuario pregunte sobre emparejamiento, escaneo de QR o controlar esta computadora desde el tel\xE9fono.",
2259
+ "pair.toolRefreshDesc": "Si se debe solicitar un nuevo c\xF3digo de emparejamiento al rel\xE9",
2260
+ "state.errSaveState": "No se pudo guardar el estado",
2261
+ "adapter.logConnected": "Conectado al rel\xE9 {url}",
2262
+ "adapter.logDisconnected": "Desconectado del rel\xE9, reconectando autom\xE1ticamente\u2026",
2263
+ "adapter.logPairCode": "C\xF3digo de emparejamiento generado: {code}",
2264
+ "adapter.logClaimed": "Vinculado a su cuenta de tel\xE9fono. A partir de ahora el tel\xE9fono se conecta directamente desde \xABMis computadoras\xBB",
2265
+ "adapter.logResetIdentity": "Desvinculado de la cuenta; restableciendo identidad y generando un nuevo c\xF3digo de emparejamiento\u2026",
2266
+ "adapter.logUnhandledType": "Tipo de mensaje no gestionado: {type}",
2267
+ "adapter.errNoRelay": "No hay URL de rel\xE9 configurada: compile con --env para inyectar un valor predeterminado, o sobrescr\xEDbala en tiempo de ejecuci\xF3n con TUNNELBOX_RELAY_URL",
2268
+ "adapter.errBusy": "Esta sesi\xF3n sigue en ejecuci\xF3n; espere a que termine o det\xE9ngala primero",
2269
+ "adapter.errBadWorkspaceEmpty": "Falta la ruta del espacio de trabajo",
2270
+ "adapter.errBadWorkspaceNotDir": "El directorio no existe o no es utilizable",
2271
+ "adapter.errWorkspaceMissing": "El espacio de trabajo no existe: {dir}",
2272
+ "adapter.cmdNew": "Nueva sesi\xF3n",
2273
+ "adapter.cmdHelp": "Mostrar ayuda",
2274
+ "adapter.helpText": "Comandos admitidos:\n- /new nueva sesi\xF3n\n- /help mostrar ayuda",
2275
+ "adapter.newSessionTitle": "Nueva sesi\xF3n",
2276
+ "install.langHelpTitle": "Idiomas admitidos por install-local (--lang <tag>):",
2277
+ "install.langHelpExample": "Ejemplo: npm run install-local -- --lang de-DE",
2278
+ "install.unknownLang": "Idioma desconocido \xAB{raw}\xBB, se usar\xE1 en-US. Admitidos: {list}",
2279
+ "hermes.errAskRequired": "question es obligatorio",
2280
+ "hermes.msgPhoneUnavailable": "Tel\xE9fono no disponible o sin respuesta: use el clarify integrado para preguntar localmente, o decida por su cuenta.",
2281
+ "hermes.errClarifyUnavailable": "Compatibilidad con clarify no disponible",
2282
+ "hermes.errAskFailed": "tunnelbox_ask fall\xF3: {err}",
2283
+ "hermes.errClarifyFailed": "clarify fall\xF3: {err}",
2284
+ "bin.denied": "Rechazado desde su tel\xE9fono",
2285
+ "bin.timeout": "Aprobaci\xF3n agotada (fail-closed)",
2286
+ "bin.reqRun": "Claude Code solicita ejecutar {tool}",
2287
+ "bin.pairTitle": "Emparejamiento telef\xF3nico tunnelbox",
2288
+ "bin.pairCodeLine": " C\xF3digo de emparejamiento: {code}",
2289
+ "bin.pairHint": "Abra la app tunnelbox, toque \xABEscanear para emparejar\xBB y escanee el c\xF3digo QR, o introduzca el c\xF3digo de emparejamiento manualmente (un solo uso).",
2290
+ "bin.pairWritten": " Informaci\xF3n de emparejamiento escrita en: {path}",
2291
+ "bin.pairRequestFailed": "No se pudo solicitar un c\xF3digo de emparejamiento al rel\xE9.",
2292
+ "bin.alreadyClaimed": "Esta computadora ya est\xE1 vinculada a una cuenta de tel\xE9fono; con\xE9ctese directamente desde \xABMis computadoras\xBB. Para volver a emparejar, desvinc\xFAlela primero en el tel\xE9fono.",
2293
+ "bin.noRelay": "No hay URL de rel\xE9 configurada: defina TUNNELBOX_RELAY_URL e int\xE9ntelo de nuevo.",
2294
+ "bin.connectFailed": "No se puede conectar al rel\xE9: {relay}\nDefina TUNNELBOX_RELAY_URL o config\xFArelo en el archivo de estado de official-plugin.",
2295
+ "bin.statusRelay": "Rel\xE9: {value}",
2296
+ "bin.statusAgent": "ID del agente: {value}",
2297
+ "bin.statusClaimed": "Tel\xE9fono vinculado: {value}",
2298
+ "bin.statusStateFile": "Archivo de estado: {value}",
2299
+ "bin.statusLatest": "\xDAltima informaci\xF3n de emparejamiento:",
2300
+ "bin.usage": "Uso: tunnelbox <pair|status|ask>",
2301
+ "bin.usagePair": " pair solicitar e imprimir un c\xF3digo de emparejamiento",
2302
+ "bin.usageStatus": " status mostrar estado del rel\xE9/vinculaci\xF3n",
2303
+ "bin.usageAsk": " ask reenviar una aprobaci\xF3n de herramienta al tel\xE9fono",
2304
+ "adapter.logMsgUncaught": "Excepci\xF3n no capturada al procesar el mensaje: {message}",
2305
+ "adapter.logHandleFailed": "Error al procesar {type}: {message}",
2306
+ "adapter.logPromptFailed": "session.prompt fall\xF3: {message}",
2307
+ "adapter.logAbortSent": "Cancelaci\xF3n enviada (session={session})",
2308
+ "adapter.errUserDenied": "Rechazado por el usuario",
2309
+ "adapter.logPendingResent": "session.pending: {count} solicitud(es) pendiente(s) reenviada(s)",
2310
+ "adapter.logWorkspaceSwitched": "Espacio de trabajo cambiado: {path}",
2311
+ "adapter.logNewSession": "Nueva sesi\xF3n guardada codexId={codexId} (alias={session})",
2312
+ "adapter.logSessionError": "Error de turno (session={session}): {message}",
2313
+ "adapter.logDshSent": "Enviado a dsh (session={session})",
2314
+ "adapter.logReadHistoryFailed": "Error al leer el historial de sesi\xF3n ({session}): {message}",
2315
+ "adapter.logAnswererInitFailed": "Error al inicializar el respondedor: {message}",
2316
+ "adapter.logRemoteMode": "Modo de visualizaci\xF3n dual: selecciones/aprobaciones usan difusi\xF3n multicliente typert; tel\xE9fono y dsh web comparten la vista, gana la primera respuesta",
2317
+ "adapter.logRemoteProbeFailed": "Fall\xF3 la detecci\xF3n de la fuente de eventos remota typert; se usar\xE1 el modo de respuesta local: {message}",
2318
+ "adapter.logLocalMode": "Modo de respuesta local: selecciones/aprobaciones respondidas por el tel\xE9fono (headless, sin difusi\xF3n de dsh web)",
2319
+ "adapter.logRemoteStreamInterrupted": "Flujo remote events interrumpido: {message}",
2320
+ "adapter.logResultRejected": "$events/result no aceptado ({eventId}): {message}",
2321
+ "adapter.logResultBackfillFailed": "Error al rellenar $events/result ({eventId}): {message}",
2322
+ "adapter.logRemoteQuestion": "Difusi\xF3n de pregunta remote \u2192 tarjeta de pregunta del tel\xE9fono questionID={id} (session={session})",
2323
+ "adapter.errRemoteReadyFrame": "Primer fotograma de remote events inesperado",
2324
+ "adapter.logRemoteApproval": "Difusi\xF3n de aprobaci\xF3n remote \u2192 tarjeta de permiso del tel\xE9fono permissionID={id} (session={session})",
2325
+ "adapter.logUserQuestionRoute": "Selecci\xF3n de user-questions \u2192 enrutada a session={session}",
2326
+ "adapter.errDshQuestionEmpty": "El contenido de la pregunta de dsh est\xE1 vac\xEDo",
2327
+ "adapter.errQuestionTimeout": "Pregunta agotada ({seconds}s), cancelada",
2328
+ "adapter.errQuestionCancelledAbort": "Pregunta cancelada (agente abortado)",
2329
+ "adapter.errQuestionCancelledRelay": "Rel\xE9 inaccesible, pregunta cancelada",
2330
+ "adapter.logQuestionToPhone": "Selecci\xF3n de user-questions \u2192 enviada a la tarjeta de pregunta del tel\xE9fono questionID={id} (session={session})",
2331
+ "adapter.errQuestionUserCancelled": "El usuario cancel\xF3/rechaz\xF3 la pregunta en el tel\xE9fono",
2332
+ "adapter.logApprovalRequest": "Solicitud de aprobaci\xF3n (tool={tool}) \u2192 enviada a la tarjeta de permiso del tel\xE9fono permissionID={id}",
2333
+ "adapter.logAgentPresetFailed": "Error al resolver agentPreset ({preset}); se usar\xE1 sin preset: {message}",
2334
+ "adapter.logSessionLiveAdopted": "La sesi\xF3n {session} ya est\xE1 retenida por otro agente de este proceso (live); se adopta el agente existente para continuar: {message}",
2335
+ "adapter.logDisposeSkipped": "El agente live externo adoptado no ejecuta dispose (la sesi\xF3n {session} la gestiona su titular original)",
2336
+ "adapter.logAgentCreateFailed": "Error al crear/reanudar el agente ({session}): {message}",
2337
+ "adapter.errSessionBusyLive": "La sesi\xF3n {session} est\xE1 ocupada (live); int\xE9ntelo m\xE1s tarde",
2338
+ "adapter.errAgentsUnavailable": "Servicio agents no disponible",
2339
+ "adapter.logToolReason": "dsh solicita ejecutar la herramienta {tool}",
2340
+ "adapter.logGatewayConnected": "Conectado al Gateway OpenClaw local ({version})",
2341
+ "adapter.logGatewayDisconnected": "Desconectado del Gateway OpenClaw; el cliente oficial se est\xE1 reconectando\u2026",
2342
+ "adapter.logGatewayConnectFailed": "No se puede conectar al Gateway OpenClaw local (la primera vez, apruebe el dispositivo localmente: `openclaw devices list` + `openclaw devices approve <requestId>`)",
2343
+ "adapter.errGatewayNoSessionKey": "El Gateway no devolvi\xF3 una clave de sesi\xF3n",
2344
+ "adapter.logDeleteSessionFailed": "Error al eliminar la sesi\xF3n ({session}): {message} (se confirma como eliminada igualmente)",
2345
+ "adapter.logApprovalReplyFailed": "Error en la respuesta de aprobaci\xF3n ({id}): {message}",
2346
+ "adapter.logPendingApproval": "session.pending: {count} aprobaci\xF3n(es) pendiente(s) reenviada(s) (session={session})",
2347
+ "adapter.workspaceDefault": "Predeterminado",
2348
+ "adapter.cursorSessionTitle": "Sesi\xF3n de Cursor",
2349
+ "adapter.reasonDisconnect": "Rel\xE9 desconectado, rechazo autom\xE1tico (fail-closed)",
2350
+ "adapter.warnInvalidEnv": "Se ignora {name} no v\xE1lido: {raw} ({list})",
2351
+ "adapter.errStartFailed": "Error al iniciar:",
2352
+ "adapter.msgStarted": "Adaptador {name} iniciado (Ctrl+C para salir)",
2353
+ "adapter.warnCliMissing": "Ejecutable \xAB{bin}\xBB no encontrado; inst\xE1lelo (p. ej. npm i -g @openai/codex) o defina TUNNELBOX_CODEX_BIN con su ruta",
2354
+ "adapter.errCliNotFound": "Ejecutable {name} \xAB{bin}\xBB no encontrado: instale el Codex CLI (npm i -g @openai/codex) o defina TUNNELBOX_CODEX_BIN",
2355
+ "adapter.errSessionNotFound": "Sesi\xF3n no encontrada o ya eliminada",
2356
+ "adapter.checkHeader": "Comprobaci\xF3n del entorno de tunnelbox-codex",
2357
+ "adapter.checkCliOk": "Ejecutable {name}: {path}",
2358
+ "adapter.checkCliMissing": "Ejecutable {name} no encontrado ({bin})",
2359
+ "bin.yes": "s\xED",
2360
+ "bin.no": "no",
2361
+ "adapter.errAppServerSpawn": "No se pudo iniciar codex app-server: {message} (comprueba que tu Codex CLI admita `codex app-server`)",
2362
+ "adapter.errAppServerExit": "codex app-server se cerr\xF3; las aprobaciones/elecciones pendientes se rechazaron autom\xE1ticamente",
2363
+ "adapter.logUnsupportedServerRequest": "solicitud de app-server no admitida: {method}",
2364
+ "adapter.logQuestionNative": "solicitud de elecci\xF3n -> tarjeta de elecci\xF3n del tel\xE9fono questionID={id} (session={session})",
2365
+ "adapter.logPermissionNative": "solicitud de aprobaci\xF3n -> tarjeta de aprobaci\xF3n del tel\xE9fono permissionID={id} (session={session})",
2366
+ "adapter.checkAppServerOk": "codex app-server disponible",
2367
+ "adapter.checkAppServerMissing": "este Codex CLI no admite `codex app-server` (actualiza Codex CLI)"
1484
2368
  };
1485
2369
  var DEFAULT_LANG = "en-US";
1486
2370
  var dicts = {
@@ -1536,6 +2420,9 @@ function t(lang, key, vars) {
1536
2420
  }
1537
2421
  return text;
1538
2422
  }
2423
+ function makeT(lang) {
2424
+ return (key, vars) => t(lang, key, vars);
2425
+ }
1539
2426
  function baseName() {
1540
2427
  return join(homedir(), ".tunnelbox");
1541
2428
  }
@@ -1551,7 +2438,7 @@ function saveState(st, type) {
1551
2438
  mkdirSync(dirname(p), { recursive: true });
1552
2439
  writeFileSync(p, JSON.stringify(st, null, 2), "utf8");
1553
2440
  } catch (e) {
1554
- console.error("[tunnelbox] \u4FDD\u5B58\u72B6\u6001\u5931\u8D25", e);
2441
+ console.error(`[tunnelbox] ${t(st.lang ?? resolveLang(), "state.errSaveState")}`, e);
1555
2442
  }
1556
2443
  }
1557
2444
  function loadState(type) {
@@ -1579,11 +2466,12 @@ function loadState(type) {
1579
2466
  return fallback;
1580
2467
  }
1581
2468
  }
1582
- function writePairingFile(code, type) {
2469
+ function writePairingFile(code, type, lang) {
1583
2470
  const p = join(baseName(), `remote-pairing${suffix(type)}.txt`);
1584
2471
  try {
1585
2472
  mkdirSync(dirname(p), { recursive: true });
1586
- writeFileSync(p, `\u914D\u5BF9\u7801: ${code}
2473
+ const label = t(lang ?? resolveLang(), "qr.codeLabel");
2474
+ writeFileSync(p, `${label}: ${code}
1587
2475
  `, "utf8");
1588
2476
  } catch {
1589
2477
  }
@@ -1618,7 +2506,7 @@ function padVisual(s, width, align = "left") {
1618
2506
  }
1619
2507
  async function printPairing(code, type, name2, lang) {
1620
2508
  const resolved = lang ? normalizeLang(lang) : resolveLang();
1621
- const file = writePairingFile(code, type);
2509
+ const file = writePairingFile(code, type, resolved);
1622
2510
  const tt = (key, vars) => t(resolved, key, vars);
1623
2511
  const title = type ? tt("qr.titleWithType", { type }) : tt("qr.titleNoType");
1624
2512
  const codeLine = `${tt("qr.codeLabel")}: ${code}`;
@@ -1633,6 +2521,7 @@ async function printPairing(code, type, name2, lang) {
1633
2521
  console.log("\u2502 " + padVisual(codeLine, W - 2) + " \u2502");
1634
2522
  console.log("\u2514" + bar + "\u2518");
1635
2523
  console.log(" " + hint);
2524
+ console.log(" " + tt("qr.validFor"));
1636
2525
  try {
1637
2526
  const mod = await import("qrcode");
1638
2527
  const render = mod.default ?? mod;
@@ -1745,6 +2634,8 @@ var MessagesCache = class {
1745
2634
  var messagesCache = new MessagesCache();
1746
2635
 
1747
2636
  // src/bridge.ts
2637
+ import { randomBytes as randomBytes2 } from "node:crypto";
2638
+ import { hostname } from "node:os";
1748
2639
  import { installModelSelection } from "@deepseek-ai/dsh-agent";
1749
2640
  import { createUserMessage } from "@deepseek-ai/dsh-llm";
1750
2641
  import { SessionId } from "@deepseek-ai/dsh-session";
@@ -2114,18 +3005,20 @@ function findDir(dir, name2) {
2114
3005
  }
2115
3006
 
2116
3007
  // src/bridge.ts
2117
- var VERSION = true ? "0.1.18" : "0.0.0-dev";
3008
+ var VERSION = true ? "0.1.20" : "0.0.0-dev";
2118
3009
  var AGENT_TYPE = "dsh";
2119
3010
  var APPROVAL_TIMEOUT_MS = 12e4;
2120
3011
  var ADAPTER_COMMANDS = [
2121
- { name: "new", description: "\u65B0\u5EFA\u4F1A\u8BDD" },
2122
- { name: "help", description: "\u663E\u793A\u5E2E\u52A9" }
3012
+ { name: "new", descriptionKey: "adapter.cmdNew" },
3013
+ { name: "help", descriptionKey: "adapter.cmdHelp" }
2123
3014
  ];
2124
3015
  var TunnelboxBridge = class {
2125
3016
  constructor(ctx, cfg) {
2126
3017
  this.ctx = ctx;
2127
3018
  this.cfg = cfg;
2128
3019
  this.currentWorkspace = cfg.cwd || process.cwd();
3020
+ this.lang = resolveLang({ config: cfg.lang, saved: this.state.lang });
3021
+ this.t = makeT(this.lang);
2129
3022
  this.ctx.on("session/event", (session, event) => this.onSessionEvent(session.id, event));
2130
3023
  }
2131
3024
  ws = new RelayClient();
@@ -2157,16 +3050,18 @@ var TunnelboxBridge = class {
2157
3050
  currentWorkspace = "";
2158
3051
  /** session.create 指定工作区但尚未建 agent 的暂存(sessionID → workspace)。 */
2159
3052
  pendingWorkspaces = /* @__PURE__ */ new Map();
3053
+ t;
3054
+ lang;
2160
3055
  get home() {
2161
3056
  return dshHome();
2162
3057
  }
2163
3058
  async start() {
2164
3059
  await this.ctx.get("loader")?.await();
2165
- void this.setupAnswerer().catch((e) => this.log(`\u5E94\u7B54\u5668\u521D\u59CB\u5316\u5931\u8D25: ${e.message}`));
3060
+ void this.setupAnswerer().catch((e) => this.log(this.t("adapter.logAnswererInitFailed", { message: e.message })));
2166
3061
  const url = (process.env.TUNNELBOX_RELAY_URL || this.cfg.relayUrl || injectedRelayUrl() || "").replace(/\/+$/, "");
2167
3062
  this.relayBase = url;
2168
3063
  if (!url) {
2169
- this.log("\u672A\u914D\u7F6E\u4E2D\u7EE7\u5730\u5740\uFF1A\u6784\u5EFA\u8BF7\u7528 --env \u6CE8\u5165\u9ED8\u8BA4\uFF0C\u8FD0\u884C\u53EF\u7528 TUNNELBOX_RELAY_URL \u8986\u76D6");
3064
+ this.log(this.t("adapter.errNoRelay"));
2170
3065
  return;
2171
3066
  }
2172
3067
  this.connect(url);
@@ -2206,20 +3101,20 @@ var TunnelboxBridge = class {
2206
3101
  {
2207
3102
  onOpen: () => {
2208
3103
  this.everConnected = true;
2209
- this.log("\u5DF2\u8FDE\u63A5\u4E2D\u7EE7 " + url);
3104
+ this.log(this.t("adapter.logConnected", { url }));
2210
3105
  this.announce();
2211
3106
  },
2212
3107
  onMessage: (env) => {
2213
3108
  void this.onMessage(env).catch((e) => {
2214
3109
  const err = e;
2215
- this.log(`\u6D88\u606F\u5904\u7406\u672A\u6355\u83B7\u5F02\u5E38: ${err.message}
2216
- ${err.stack ?? ""}`);
3110
+ this.log(this.t("adapter.logMsgUncaught", { message: err.message }) + (err.stack ? `
3111
+ ${err.stack}` : ""));
2217
3112
  });
2218
3113
  },
2219
3114
  onClose: () => {
2220
3115
  if (this.everConnected) {
2221
3116
  this.everConnected = false;
2222
- this.log("\u4E0E\u4E2D\u7EE7\u65AD\u5F00\uFF0C\u6B63\u5728\u81EA\u52A8\u91CD\u8FDE\u2026");
3117
+ this.log(this.t("adapter.logDisconnected"));
2223
3118
  }
2224
3119
  },
2225
3120
  onError: () => {
@@ -2257,15 +3152,15 @@ ${err.stack ?? ""}`);
2257
3152
  case "pair.created": {
2258
3153
  const code = env.payload.code;
2259
3154
  writePairingJson({ code, relayUrl: this.relayBase, at: Date.now() }, AGENT_TYPE);
2260
- this.log("\u751F\u6210\u914D\u5BF9\u7801: " + code);
2261
- void printPairing(code, AGENT_TYPE, hostname());
3155
+ this.log(this.t("adapter.logPairCode", { code }));
3156
+ void printPairing(code, AGENT_TYPE, hostname(), this.lang);
2262
3157
  return;
2263
3158
  }
2264
3159
  case "agent.claimed":
2265
3160
  this.claimed = true;
2266
3161
  this.state.claimed = true;
2267
3162
  saveState(this.state, AGENT_TYPE);
2268
- this.log("\u5DF2\u7ED1\u5B9A\u5230\u624B\u673A\u8D26\u53F7\uFF0C\u4E4B\u540E\u624B\u673A\u4ECE\u300C\u6211\u7684\u7535\u8111\u300D\u76F4\u63A5\u8FDE\u63A5");
3163
+ this.log(this.t("adapter.logClaimed"));
2269
3164
  return;
2270
3165
  case "agent.revoked":
2271
3166
  this.resetIdentity();
@@ -2297,10 +3192,10 @@ ${err.stack ?? ""}`);
2297
3192
  case "error":
2298
3193
  return;
2299
3194
  default:
2300
- this.log("\u672A\u5904\u7406\u7684\u6D88\u606F\u7C7B\u578B: " + env.type);
3195
+ this.log(this.t("adapter.logUnhandledType", { type: env.type }));
2301
3196
  }
2302
3197
  } catch (e) {
2303
- this.log(`\u5904\u7406 ${env.type} \u5931\u8D25: ${e.message}`);
3198
+ this.log(this.t("adapter.logHandleFailed", { type: env.type, message: e.message }));
2304
3199
  this.reply(env, "error", { code: "HANDLER_ERROR", message: e.message, id: env.id });
2305
3200
  }
2306
3201
  }
@@ -2319,7 +3214,7 @@ ${err.stack ?? ""}`);
2319
3214
  const last = events[events.length - 1];
2320
3215
  sessions.set(id, {
2321
3216
  id,
2322
- title: text ? text.length > 30 ? text.slice(0, 30) + "\u2026" : text : "\u65B0\u4F1A\u8BDD",
3217
+ title: text ? text.length > 30 ? text.slice(0, 30) + "\u2026" : text : this.t("adapter.newSessionTitle"),
2323
3218
  created: events[0]?.time ?? Date.now(),
2324
3219
  updated: last?.time ?? Date.now(),
2325
3220
  status: "idle",
@@ -2336,7 +3231,7 @@ ${err.stack ?? ""}`);
2336
3231
  const now = Date.now();
2337
3232
  this.pendingWorkspaces.set(id, workspace);
2338
3233
  this.reply(env, "session.created", {
2339
- session: { id, title: "\u65B0\u4F1A\u8BDD", created: now, updated: now, status: "idle", workspace }
3234
+ session: { id, title: this.t("adapter.newSessionTitle"), created: now, updated: now, status: "idle", workspace }
2340
3235
  });
2341
3236
  }
2342
3237
  async sessionMessages(env) {
@@ -2361,7 +3256,7 @@ ${err.stack ?? ""}`);
2361
3256
  return await readSessionEvents(sp, sessionID);
2362
3257
  } catch (e) {
2363
3258
  const m = e.message;
2364
- if (!/not found|not exist/i.test(m)) this.log(`\u8BFB\u53D6\u4F1A\u8BDD\u5386\u53F2\u5931\u8D25(${sessionID}): ${m}`);
3259
+ if (!/not found|not exist/i.test(m)) this.log(this.t("adapter.logReadHistoryFailed", { session: sessionID, message: m }));
2365
3260
  }
2366
3261
  }
2367
3262
  return [];
@@ -2375,7 +3270,7 @@ ${err.stack ?? ""}`);
2375
3270
  this.reply(env, "message.part", {
2376
3271
  sessionID: payload.sessionID,
2377
3272
  messageID: `m-${Date.now()}`,
2378
- part: { id: "t", type: "text", text: "\u652F\u6301\u7684\u547D\u4EE4\uFF1A\n- /new \u65B0\u5EFA\u4F1A\u8BDD\n- /help \u663E\u793A\u5E2E\u52A9", complete: true }
3273
+ part: { id: "t", type: "text", text: this.t("adapter.helpText"), complete: true }
2379
3274
  });
2380
3275
  return;
2381
3276
  }
@@ -2383,7 +3278,7 @@ ${err.stack ?? ""}`);
2383
3278
  handle.agent.followup(
2384
3279
  createUserMessage({ content: [{ type: "text", text }], source: { kind: "user" } })
2385
3280
  );
2386
- this.log(`\u5DF2\u53D1\u9001\u5230 dsh (session=${payload.sessionID})`);
3281
+ this.log(this.t("adapter.logDshSent", { session: payload.sessionID }));
2387
3282
  }
2388
3283
  async sessionDelete(env) {
2389
3284
  const { sessionID } = env.payload;
@@ -2404,7 +3299,11 @@ ${err.stack ?? ""}`);
2404
3299
  this.send(envelope("session.status", { sessionID, status: "idle" }));
2405
3300
  }
2406
3301
  async commandList(env) {
2407
- this.reply(env, "commands", { commands: ADAPTER_COMMANDS });
3302
+ const commands = ADAPTER_COMMANDS.map((c) => ({
3303
+ name: c.name,
3304
+ description: this.t(c.descriptionKey)
3305
+ }));
3306
+ this.reply(env, "commands", { commands });
2408
3307
  }
2409
3308
  // ---- 工作区 ----
2410
3309
  async workspaceList(env) {
@@ -2421,7 +3320,7 @@ ${err.stack ?? ""}`);
2421
3320
  const path = (env.payload?.path || "").trim();
2422
3321
  const sp = this.getSessionPersistence();
2423
3322
  if (!path) {
2424
- this.reply(env, "error", { code: "BAD_WORKSPACE", message: "\u7F3A\u5C11\u5DE5\u4F5C\u533A\u8DEF\u5F84", id: env.id });
3323
+ this.reply(env, "error", { code: "BAD_WORKSPACE", message: this.t("adapter.errBadWorkspaceEmpty"), id: env.id });
2425
3324
  return;
2426
3325
  }
2427
3326
  let workspaces = [];
@@ -2429,11 +3328,11 @@ ${err.stack ?? ""}`);
2429
3328
  workspaces = await listWorkspaces(sp, this.currentWorkspace);
2430
3329
  }
2431
3330
  if (workspaces.length && !workspaces.some((w) => w.path === path)) {
2432
- this.reply(env, "error", { code: "BAD_WORKSPACE", message: "\u8BE5\u5DE5\u4F5C\u533A\u4E0D\u5B58\u5728", id: env.id });
3331
+ this.reply(env, "error", { code: "BAD_WORKSPACE", message: this.t("adapter.errBadWorkspaceNotDir"), id: env.id });
2433
3332
  return;
2434
3333
  }
2435
3334
  this.currentWorkspace = path;
2436
- this.log("\u5207\u6362\u5DE5\u4F5C\u533A: " + path);
3335
+ this.log(this.t("adapter.logWorkspaceSwitched", { path }));
2437
3336
  this.announce();
2438
3337
  this.reply(env, "workspaces", { workspaces, current: this.currentWorkspace });
2439
3338
  }
@@ -2481,7 +3380,7 @@ ${err.stack ?? ""}`);
2481
3380
  if (Date.now() - q.at >= APPROVAL_TIMEOUT_MS) continue;
2482
3381
  if (this.send(envelope("question.request", q.req))) n++;
2483
3382
  }
2484
- if (n) this.log(`session.pending \u8865\u53D1\u5F85\u5BA1\u6279/\u5F85\u56DE\u7B54 ${n} \u6761 (session=${sessionID})`);
3383
+ if (n) this.log(this.t("adapter.logPendingApproval", { count: n, session: sessionID }));
2485
3384
  }
2486
3385
  /** 记录未决审批请求(供 session.pending 补发);审批解决/超时/中止时用 clearPendingRequest 移除。 */
2487
3386
  addPendingRequest(req) {
@@ -2518,17 +3417,17 @@ ${err.stack ?? ""}`);
2518
3417
  const gen = gw.openRemoteEvents({ args: {} }, ac.signal);
2519
3418
  const first = await gen.next();
2520
3419
  const ready = first.done ? void 0 : first.value;
2521
- if (ready?.type !== "ready" || !ready.clientId) throw new Error("remote events \u9996\u5E27\u5F02\u5E38");
3420
+ if (ready?.type !== "ready" || !ready.clientId) throw new Error(this.t("adapter.errRemoteReadyFrame"));
2522
3421
  this.remoteClientId = ready.clientId;
2523
3422
  this.remoteAc = ac;
2524
3423
  this.answerMode = "remote";
2525
- this.log("\u53CC\u7AEF\u540C\u663E\u6A21\u5F0F\uFF1A\u9009\u62E9/\u5BA1\u6279\u8D70 typert \u591A\u7AEF\u5E7F\u64AD\uFF0C\u624B\u673A\u4E0E dsh web \u540C\u663E\u3001\u8C01\u7B54\u8C01\u5F97");
3424
+ this.log(this.t("adapter.logRemoteMode"));
2526
3425
  void this.drainRemoteEvents(gen, ac);
2527
3426
  } catch (e) {
2528
3427
  ac.abort();
2529
3428
  const err = e;
2530
3429
  const expected = err.code === "gateway/service-unavailable" || /service-unavailable|unavailable/i.test(err.message);
2531
- if (!expected) this.log(`typert \u8FDC\u7A0B\u4E8B\u4EF6\u6E90\u63A2\u6D4B\u5931\u8D25\uFF0C\u56DE\u9000\u672C\u5730\u5E94\u7B54\u6A21\u5F0F: ${err.message}`);
3430
+ if (!expected) this.log(this.t("adapter.logRemoteProbeFailed", { message: err.message }));
2532
3431
  this.activateLocalAnswerers();
2533
3432
  }
2534
3433
  }
@@ -2539,13 +3438,13 @@ ${err.stack ?? ""}`);
2539
3438
  this.answerMode = "local";
2540
3439
  this.ctx.on("approval/request", (req, next) => this.onApproval(req, next), { prepend: true });
2541
3440
  this.ctx.on("user-questions/request", (request, next) => this.onUserQuestion(request, next), { prepend: true });
2542
- this.log("\u672C\u5730\u5E94\u7B54\u6A21\u5F0F\uFF1A\u9009\u62E9/\u5BA1\u6279\u7531\u624B\u673A\u4F5C\u7B54\uFF08headless\uFF0C\u65E0 dsh web \u5E7F\u64AD\uFF09");
3441
+ this.log(this.t("adapter.logLocalMode"));
2543
3442
  }
2544
3443
  async drainRemoteEvents(gen, ac) {
2545
3444
  try {
2546
3445
  for await (const raw of gen) this.onRemoteFrame(raw);
2547
3446
  } catch (e) {
2548
- if (!ac.signal.aborted) this.log(`remote events \u6D41\u4E2D\u65AD: ${e.message}`);
3447
+ if (!ac.signal.aborted) this.log(this.t("adapter.logRemoteStreamInterrupted", { message: e.message }));
2549
3448
  } finally {
2550
3449
  if (this.remoteAc === ac) {
2551
3450
  this.remoteAc = null;
@@ -2588,9 +3487,9 @@ ${err.stack ?? ""}`);
2588
3487
  if (!gw || !this.remoteClientId) return;
2589
3488
  void gw.dispatchRpc("$events/result", { args: { clientId: this.remoteClientId, eventId, outcome } }).then(
2590
3489
  (res) => {
2591
- if (res && res.ok === false) this.log(`$events/result \u672A\u63A5\u53D7(${eventId}): ${res.error?.message ?? "unknown"}`);
3490
+ if (res && res.ok === false) this.log(this.t("adapter.logResultRejected", { eventId, message: res.error?.message ?? "unknown" }));
2592
3491
  },
2593
- (e) => this.log(`$events/result \u56DE\u586B\u5931\u8D25(${eventId}): ${e.message}`)
3492
+ (e) => this.log(this.t("adapter.logResultBackfillFailed", { eventId, message: e.message }))
2594
3493
  );
2595
3494
  }
2596
3495
  /** remote 提问广播:手机在线即推卡;作答/让位经网关与浏览器竞答。 */
@@ -2608,7 +3507,7 @@ ${err.stack ?? ""}`);
2608
3507
  const timer = setTimeout(() => this.remoteQuestionTimeout(eventId), APPROVAL_TIMEOUT_MS);
2609
3508
  this.remoteQuestions.set(eventId, { agentId, at: Date.now(), req: payload, items: meta, timer });
2610
3509
  this.send(envelope("question.request", payload));
2611
- this.log(`remote \u63D0\u95EE\u5E7F\u64AD \u2192 \u624B\u673A\u63D0\u95EE\u5361 questionID=${eventId} (session=${agentId})`);
3510
+ this.log(this.t("adapter.logRemoteQuestion", { id: eventId, session: agentId }));
2612
3511
  }
2613
3512
  /** 手机超时未答:让位(next),不干扰其它端继续作答,并关掉本端卡。 */
2614
3513
  remoteQuestionTimeout(eventId) {
@@ -2634,12 +3533,12 @@ ${err.stack ?? ""}`);
2634
3533
  args = call.args || {};
2635
3534
  }
2636
3535
  }
2637
- const reason = body.reason || (Object.keys(args).length ? JSON.stringify(args, null, 2) : `dsh \u8BF7\u6C42\u6267\u884C\u5DE5\u5177 ${tool}`);
3536
+ const reason = body.reason || (Object.keys(args).length ? JSON.stringify(args, null, 2) : this.t("adapter.logToolReason", { tool }));
2638
3537
  const payload = { id: eventId, sessionID: agentId, tool, args, prompt: reason, createdAt: Date.now() };
2639
3538
  const timer = setTimeout(() => this.remoteApprovalTimeout(eventId), APPROVAL_TIMEOUT_MS);
2640
3539
  this.remoteApprovals.set(eventId, { agentId, at: Date.now(), req: payload, timer });
2641
3540
  this.send(envelope("permission.request", payload));
2642
- this.log(`remote \u5BA1\u6279\u5E7F\u64AD \u2192 \u624B\u673A\u6743\u9650\u5361 permissionID=${eventId} (session=${agentId})`);
3541
+ this.log(this.t("adapter.logRemoteApproval", { id: eventId, session: agentId }));
2643
3542
  }
2644
3543
  /** 手机超时未审批:让位(next),浏览器仍可允许/拒绝。 */
2645
3544
  remoteApprovalTimeout(eventId) {
@@ -2751,17 +3650,17 @@ ${err.stack ?? ""}`);
2751
3650
  * 返回该 Promise 即代表本应答者认领(不再调用 next);手机取消/超时/发起方中止时拒绝。
2752
3651
  */
2753
3652
  async askPhoneQuestion(sessionID, request) {
2754
- this.log(`user-questions \u9009\u62E9 \u2192 \u8DEF\u7531 session=${sessionID}`);
3653
+ this.log(this.t("adapter.logUserQuestionRoute", { session: sessionID }));
2755
3654
  const rawItems = request.questions ?? [];
2756
3655
  const items = this.buildQuestionItems(rawItems);
2757
- if (!items.length) throw new Error("dsh \u63D0\u95EE\u5185\u5BB9\u4E3A\u7A7A");
3656
+ if (!items.length) throw new Error(this.t("adapter.errDshQuestionEmpty"));
2758
3657
  const id = `q-${++this.questionSeq}-${Date.now()}`;
2759
3658
  const req = this.questionCardPayload(id, sessionID, items, this.findAskAnchor(this.liveSessionOf(sessionID)));
2760
3659
  const meta = items.map((x) => ({ id: x.id, options: new Set(x.options) }));
2761
3660
  return new Promise((resolve, reject) => {
2762
3661
  const timer = setTimeout(() => {
2763
3662
  this.pendingQuestions.delete(id);
2764
- reject(new Error(`\u63D0\u95EE\u8D85\u65F6(${APPROVAL_TIMEOUT_MS / 1e3}s)\uFF0C\u5DF2\u53D6\u6D88`));
3663
+ reject(new Error(this.t("adapter.errQuestionTimeout", { seconds: APPROVAL_TIMEOUT_MS / 1e3 })));
2765
3664
  }, APPROVAL_TIMEOUT_MS);
2766
3665
  this.pendingQuestions.set(id, { sessionID, at: Date.now(), req, items: meta, timer, resolve, reject });
2767
3666
  request.signal?.addEventListener(
@@ -2769,7 +3668,7 @@ ${err.stack ?? ""}`);
2769
3668
  () => {
2770
3669
  clearTimeout(timer);
2771
3670
  this.pendingQuestions.delete(id);
2772
- reject(new Error("\u63D0\u95EE\u5DF2\u53D6\u6D88\uFF08agent \u4E2D\u6B62\uFF09"));
3671
+ reject(new Error(this.t("adapter.errQuestionCancelledAbort")));
2773
3672
  },
2774
3673
  { once: true }
2775
3674
  );
@@ -2777,9 +3676,9 @@ ${err.stack ?? ""}`);
2777
3676
  if (!ok) {
2778
3677
  clearTimeout(timer);
2779
3678
  this.pendingQuestions.delete(id);
2780
- reject(new Error("\u4E2D\u7EE7\u4E0D\u53EF\u8FBE\uFF0C\u63D0\u95EE\u5DF2\u53D6\u6D88"));
3679
+ reject(new Error(this.t("adapter.errQuestionCancelledRelay")));
2781
3680
  }
2782
- this.log(`user-questions \u9009\u62E9 \u2192 \u53D1\u9001\u5230\u624B\u673A\u63D0\u95EE\u5361 questionID=${id} (session=${sessionID})`);
3681
+ this.log(this.t("adapter.logQuestionToPhone", { id, session: sessionID }));
2783
3682
  });
2784
3683
  }
2785
3684
  async questionReply(env) {
@@ -2802,7 +3701,7 @@ ${err.stack ?? ""}`);
2802
3701
  clearTimeout(q.timer);
2803
3702
  this.pendingQuestions.delete(p.questionID);
2804
3703
  if (p.reject) {
2805
- q.reject(new Error("\u7528\u6237\u5728\u624B\u673A\u7AEF\u53D6\u6D88/\u62D2\u7EDD\u4E86\u63D0\u95EE"));
3704
+ q.reject(new Error(this.t("adapter.errQuestionUserCancelled")));
2806
3705
  } else {
2807
3706
  q.resolve({ answers: this.buildAnswerRows(q.items, Array.isArray(p.answers) ? p.answers : []) });
2808
3707
  }
@@ -2838,8 +3737,8 @@ ${err.stack ?? ""}`);
2838
3737
  const call = req.callId ? findToolCall([...liveSessionEvents(agent?.session)], String(req.callId)) : null;
2839
3738
  const tool = call?.name || req.toolName;
2840
3739
  const args = call?.args || {};
2841
- const reason = req.reason || (Object.keys(args).length ? JSON.stringify(args, null, 2) : `dsh \u8BF7\u6C42\u6267\u884C\u5DE5\u5177 ${tool}`);
2842
- this.log(`\u5BA1\u6279\u8BF7\u6C42(tool=${tool}) \u2192 \u53D1\u9001\u5230\u624B\u673A\u6743\u9650\u5361 permissionID=${id}`);
3740
+ const reason = req.reason || (Object.keys(args).length ? JSON.stringify(args, null, 2) : this.t("adapter.logToolReason", { tool }));
3741
+ this.log(this.t("adapter.logApprovalRequest", { tool, id }));
2843
3742
  const payload = { id, sessionID, tool, args, prompt: reason, createdAt: Date.now() };
2844
3743
  return new Promise((resolve) => {
2845
3744
  const timer = setTimeout(() => {
@@ -2892,7 +3791,7 @@ ${err.stack ?? ""}`);
2892
3791
  }
2893
3792
  async ensureAgentNow(sessionID) {
2894
3793
  const agents = this.ctx.get("agents");
2895
- if (!agents) throw new Error("agents \u670D\u52A1\u4E0D\u53EF\u7528");
3794
+ if (!agents) throw new Error(this.t("adapter.errAgentsUnavailable"));
2896
3795
  const dm = this.ctx.get("agentDefaultModel");
2897
3796
  const selection = dm?.currentSelection();
2898
3797
  const provider = this.cfg.provider || selection?.provider || "deepseek-official";
@@ -2905,7 +3804,7 @@ ${err.stack ?? ""}`);
2905
3804
  try {
2906
3805
  resolvedId = (await presets.resolve(presetId)).id;
2907
3806
  } catch (e) {
2908
- this.log(`agentPreset \u89E3\u6790\u5931\u8D25(${presetId})\uFF0C\u964D\u7EA7\u4E3A\u65E0 preset: ${e.message}`);
3807
+ this.log(this.t("adapter.logAgentPresetFailed", { preset: presetId, message: e.message }));
2909
3808
  }
2910
3809
  }
2911
3810
  const setup = async (agentCtx) => {
@@ -2934,21 +3833,21 @@ ${err.stack ?? ""}`);
2934
3833
  const err = e;
2935
3834
  const live = agents.get(sessionID);
2936
3835
  if (live && typeof live === "object") {
2937
- this.log(`\u4F1A\u8BDD ${sessionID} \u5DF2\u7531\u672C\u8FDB\u7A0B\u5176\u5B83 agent \u6301\u6709\uFF08live\uFF09\uFF0C\u91C7\u7EB3\u73B0\u6709 agent \u7EE7\u7EED\u9A71\u52A8: ${err.message}`);
2938
- const adopted = { agent: live, dispose: async () => this.log(`\u5DF2\u91C7\u7EB3\u7684\u5916\u90E8 live agent \u4E0D\u6267\u884C dispose\uFF08\u4F1A\u8BDD ${sessionID} \u7531\u539F\u6301\u6709\u8005\u7BA1\u7406\uFF09`) };
3836
+ this.log(this.t("adapter.logSessionLiveAdopted", { session: sessionID, message: err.message }));
3837
+ const adopted = { agent: live, dispose: async () => this.log(this.t("adapter.logDisposeSkipped", { session: sessionID })) };
2939
3838
  this.pendingWorkspaces.delete(sessionID);
2940
3839
  this.handles.set(sessionID, adopted);
2941
3840
  return adopted;
2942
3841
  }
2943
- this.log(`\u521B\u5EFA/\u6062\u590D agent \u5931\u8D25(${sessionID}): ${err.message}`);
2944
- throw new Error(`\u4F1A\u8BDD ${sessionID} \u6B63\u88AB\u5360\u7528\uFF08live\uFF09\uFF0C\u8BF7\u7A0D\u540E\u91CD\u8BD5`);
3842
+ this.log(this.t("adapter.logAgentCreateFailed", { session: sessionID, message: err.message }));
3843
+ throw new Error(this.t("adapter.errSessionBusyLive", { session: sessionID }));
2945
3844
  }
2946
3845
  this.pendingWorkspaces.delete(sessionID);
2947
3846
  this.handles.set(sessionID, handle);
2948
3847
  return handle;
2949
3848
  }
2950
3849
  resetIdentity() {
2951
- this.log("\u88AB\u8D26\u53F7\u89E3\u7ED1\uFF0C\u6B63\u5728\u91CD\u7F6E\u8EAB\u4EFD\u5E76\u91CD\u65B0\u751F\u6210\u914D\u5BF9\u7801\u2026");
3850
+ this.log(this.t("adapter.logResetIdentity"));
2952
3851
  this.claimed = false;
2953
3852
  this.state.agentId = randomBytes2(16).toString("hex");
2954
3853
  this.state.claimed = false;
@@ -2997,12 +3896,14 @@ var Config = Schema.object({
2997
3896
  provider: Schema.string().default("deepseek-official"),
2998
3897
  model: Schema.string().default("deepseek-v4-flash"),
2999
3898
  cwd: Schema.string().default(process.cwd()),
3000
- agentPreset: Schema.string().default("")
3899
+ agentPreset: Schema.string().default(""),
3900
+ lang: Schema.string().default("")
3001
3901
  });
3002
3902
  function apply(ctx, config) {
3003
3903
  const bridge = new TunnelboxBridge(ctx, config);
3004
3904
  void bridge.start().catch((e) => {
3005
- console.error("[tunnelbox:dsh] \u542F\u52A8\u5931\u8D25:", e);
3905
+ const lang = resolveLang({ config: config.lang, saved: loadState("dsh").lang });
3906
+ console.error(`[tunnelbox:dsh] ${t(lang, "adapter.errStartFailed")}`, e);
3006
3907
  });
3007
3908
  ctx.effect(() => {
3008
3909
  return () => bridge.dispose();