@tocca-systems/twp-cli 0.13.0 → 0.14.1

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.
@@ -11,6 +11,42 @@
11
11
  `CHANGELOG.md` に残してあります。顧客向けの履歴は public 公開以降を対象とします。
12
12
  -->
13
13
 
14
+ ## 0.14.1
15
+
16
+ `/context` に、いま効いている `--permission-mode` と監査ログの置き場所を表示するようになりました。
17
+
18
+ - `permission-mode: denyAll(read を含む全ツールを拒否)` のように、何が拒否されるかまで出ます。指定していないときは「未指定(モードの方針のまま)」と出ます。
19
+ - `監査ログ: <パス>` … このセッションの監査ログの置き場所です。まだツールを1本も実行していない間は「未作成・最初のツール実行で作る」と付きます(ファイルは最初のツール実行で作られます)。
20
+ - 監査ログの各行に、ツール呼び出しごとの相関IDが載るようになりました。判定(`decision`)と結果(`result`)を行の順序ではなく ID で突き合わせられます。
21
+
22
+ ## 0.14.0
23
+
24
+ ループが計画を立てるかどうかを設定で切り替えられるようになりました(`plan_enabled` / 環境変数 `PLAN_ENABLED`・既定は従来どおり計画します)。
25
+
26
+ - 無効にすると、キューが空のサイクルでも計画のための AI を起動しません。積まれた仕事の実行だけを行います。
27
+ - 積まれた仕事・定期スケジュールの扱いは変わりません。
28
+ - キューが空のまま待ち続けてもループは終了しません(仕事が積まれ次第そのまま実行します)。
29
+
30
+ `twp task create` / `twp task update` で指定できる項目が増えました。
31
+
32
+ - `--category` / `--milestone` / `--label` … 名前でも ID でも指定できます(`--label` は複数指定でき、指定したものが全体になります)
33
+ - `--estimated-hours` … 見積工数(0〜9999・小数可)
34
+ - `--custom-field <フィールド名>=<値>` … カスタムフィールド(複数指定可・編集には管理者またはマネージャー権限が要ります)
35
+ - `--parent <キー|ID>` … 親タスクを指定してサブタスクとして作成します
36
+ - `--clear <項目>`(`twp task update` のみ)… 担当者・期日・開始日・優先度・カテゴリ・マイルストーン・ラベル・見積工数・本文・親タスクを空にします。指定しなかった項目は変わりません
37
+
38
+ 指定できる項目名は `twp task update help` に一覧があります。
39
+
40
+ codex のレートリミット検知で、特定の形をした長いログ行を処理するときにループが固まることがある問題を修正しました。
41
+
42
+ - 検知する内容は変わりません(従来どおりのログ行を同じように検知します)。
43
+ - 設定の変更は不要です。
44
+
45
+ AI が1ターンも実行しないまま終わった実行を「完了」ではなく「失敗」として記録するようになりました。
46
+
47
+ - 失敗として記録されるため、そのアイテムは次のサイクルで再度実行されます。
48
+ - 対象は「実行ターン数が 0 と計測でき、かつ最終報告に出力契約行が無い」実行だけです。ターン数を計測できない CLI(claude 以外)の実行は従来どおり完了として記録します。
49
+
14
50
  ## 0.13.0
15
51
 
16
52
  `--status` や `--type` に渡せる値を、エラーを踏まずに調べられるようになりました。
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __twpCreateRequire } from 'node:module';
2
2
  const require = __twpCreateRequire(import.meta.url);
3
- import{failureHint,isAuthError,isCliFatalText,isRateLimited,isServerAiType,isUntrusted,maxTurnsReached,rateLimitWaitSeconds,tailForScan}from"./chunk-NAQ7OCUV.js";import{DEFAULT_CLAUDE_LAUNCHER,activeSlotPath,detectAiClis,detectClaudeAutoSwitch,isClaudeAi,isUsableModelId,modelFitsRoute,resolveSpawnTarget,usesBedrock,wrapWithAutoSwitch}from"./chunk-3WJHTPOZ.js";import{isForceOnly,killProcessTree,system32}from"./chunk-N2UVRM3Z.js";import{findExecutable,isWindowsDriveAbsolute}from"./chunk-PMOUHEJQ.js";
3
+ import{failureHint,isAuthError,isCliFatalText,isRateLimited,isServerAiType,isUntrusted,maxTurnsReached,rateLimitWaitSeconds,tailForScan}from"./chunk-ZOOEH7ZE.js";import{DEFAULT_CLAUDE_LAUNCHER,activeSlotPath,detectAiClis,detectClaudeAutoSwitch,isClaudeAi,isUsableModelId,modelFitsRoute,resolveSpawnTarget,usesBedrock,wrapWithAutoSwitch}from"./chunk-3WJHTPOZ.js";import{isForceOnly,killProcessTree,system32}from"./chunk-N2UVRM3Z.js";import{findExecutable,isWindowsDriveAbsolute}from"./chunk-PMOUHEJQ.js";
4
4
  import{stripTerminalControls}from"./chunk-NHYMHCAT.js";import"./chunk-VSJBJXZO.js";import{spawnSync}from"child_process";import fs2 from"fs";import path2 from"path";import{spawn}from"child_process";import fs from"fs";import path from"path";var FINAL_REPORT_BEGIN="<<<AI_FINAL_REPORT>>>";var FINAL_REPORT_END="<<<END_AI_FINAL_REPORT>>>";var ClaudeStreamRenderer=class{constructor(now=()=>new Date){this.now=now}now;toolNames=new Map;toolCount=0;result={subtype:null,isError:null,numTurns:null,costUsd:null,durationMs:null,tokensIn:null,tokensOut:null,rateLimited:false,resetsAt:null,finalText:""};push(line){const trimmed=line.trim();if(trimmed==="")return[];let event;try{const parsed=JSON.parse(trimmed);if(parsed===null||typeof parsed!=="\
5
5
  object"||Array.isArray(parsed)){return[line]}event=parsed}catch{return[line]}switch(event["type"]){case"rate_limit_event":return this.onRateLimit(event);case"assistant":return this.onAssistant(event);case"user":return this.onUser(event);case"result":return this.onResult(event);default:return event["type"]==="system"?[]:[line]}}sawRateLimit(){return this.result.rateLimited}lastRateLimitNote="";onRateLimit(event){const info=event["rate_limit_info"];if(info===null||typeof info!=="object")return[];const rec=info;
6
6
  const status=typeof rec["status"]==="string"?rec["status"]:"";const resets=typeof rec["resetsAt"]==="number"?rec["resetsAt"]:null;if(status==="")return[];const at=isSaneEpochSec(resets)?` resets=${new Date(resets*1e3).toISOString()}`:"";if(status.startsWith("allowed")){if(status==="allowed")return[];const seen=`${status}|${resets??""}`;if(seen===this.lastRateLimitNote)return[];this.lastRateLimitNote=seen;return[this.line(`\u2139\uFE0F \u4E0A\u9650\u306B\u63A5\u8FD1\uFF08status=${status}${at}\uFF09\u2014 \u5B9F\
@@ -1,7 +1,7 @@
1
1
  import { createRequire as __twpCreateRequire } from 'node:module';
2
2
  const require = __twpCreateRequire(import.meta.url);
3
- import{RESIDENT_TOKEN_CAP,buildResidentSet,buildSystemPrompt,createAuditLogger,currentBranch,displayCwd,runTurn}from"./chunk-R7T4VOIN.js";import"./chunk-N2UVRM3Z.js";import{applyPermissionMode,checkPermission,getMode,isModeId,nextMode}from"./chunk-NNOYO67O.js";import{require_fuzzysort}from"./chunk-DIMZRTLE.js";import{isFullWidth,isWide,stringWidth,stripAnsi}from"./chunk-WVS4W5FY.js";import{RelayError,builtinCatalog,createRuntime,loadCachedCatalog,modelLabel,pickModel,
4
- toModelInfos}from"./chunk-RQFG3OUL.js";import{checkMinSupportedVersion,isBelowMinSupported,minSupportedBlockMessage}from"./chunk-DXXFUNYN.js";import"./chunk-PMOUHEJQ.js";import"./chunk-63LDNYGW.js";import"./chunk-NERYSBA4.js";import"./chunk-RZVI6PMW.js";import{proxyDiagnostics}from"./chunk-J7QYPKVK.js";import{stripTerminalControls}from"./chunk-NHYMHCAT.js";import{__commonJS,__export,__require,__toESM}from"./chunk-VSJBJXZO.js";var require_react_production=__commonJS({"node_modules/react/cjs/react.production.js"(exports){"use strict";var REACT_ELEMENT_TYPE=Symbol.for("react.transitional.element");var REACT_PORTAL_TYPE=Symbol.for("react.portal");var REACT_FRAGMENT_TYPE=Symbol.for("react.fragment");var REACT_STRICT_MODE_TYPE=Symbol.for("react.strict_mode");var REACT_PROFILER_TYPE=Symbol.for("react.profiler");var REACT_CONSUMER_TYPE=Symbol.for("react.consumer");var REACT_CONTEXT_TYPE=Symbol.for("react.context");var REACT_FORWARD_REF_TYPE=Symbol.
3
+ import{RESIDENT_TOKEN_CAP,buildResidentSet,buildSystemPrompt,createAuditLogger,currentBranch,describeAuditLog,displayCwd,runTurn}from"./chunk-ZVZL4QHS.js";import"./chunk-N2UVRM3Z.js";import{applyPermissionMode,checkPermission,describePermissionMode,getMode,isModeId,nextMode}from"./chunk-4WK2ECUX.js";import{require_fuzzysort}from"./chunk-DIMZRTLE.js";import{isFullWidth,isWide,stringWidth,stripAnsi}from"./chunk-WVS4W5FY.js";import{RelayError,builtinCatalog,createRuntime,
4
+ loadCachedCatalog,modelLabel,pickModel,toModelInfos}from"./chunk-RQFG3OUL.js";import{checkMinSupportedVersion,isBelowMinSupported,minSupportedBlockMessage}from"./chunk-DXXFUNYN.js";import"./chunk-PMOUHEJQ.js";import"./chunk-63LDNYGW.js";import"./chunk-NERYSBA4.js";import"./chunk-RZVI6PMW.js";import{proxyDiagnostics}from"./chunk-J7QYPKVK.js";import{stripTerminalControls}from"./chunk-NHYMHCAT.js";import{__commonJS,__export,__require,__toESM}from"./chunk-VSJBJXZO.js";var require_react_production=__commonJS({"node_modules/react/cjs/react.production.js"(exports){"use strict";var REACT_ELEMENT_TYPE=Symbol.for("react.transitional.element");var REACT_PORTAL_TYPE=Symbol.for("react.portal");var REACT_FRAGMENT_TYPE=Symbol.for("react.fragment");var REACT_STRICT_MODE_TYPE=Symbol.for("react.strict_mode");var REACT_PROFILER_TYPE=Symbol.for("react.profiler");var REACT_CONSUMER_TYPE=Symbol.for("react.consumer");var REACT_CONTEXT_TYPE=Symbol.for("react.context");var REACT_FORWARD_REF_TYPE=Symbol.
5
5
  for("react.forward_ref");var REACT_SUSPENSE_TYPE=Symbol.for("react.suspense");var REACT_MEMO_TYPE=Symbol.for("react.memo");var REACT_LAZY_TYPE=Symbol.for("react.lazy");var REACT_ACTIVITY_TYPE=Symbol.for("react.activity");var REACT_VIEW_TRANSITION_TYPE=Symbol.for("react.view_transition");var MAYBE_ITERATOR_SYMBOL=Symbol.iterator;function getIteratorFn(maybeIterable){if(null===maybeIterable||"object"!==typeof maybeIterable)return null;maybeIterable=MAYBE_ITERATOR_SYMBOL&&maybeIterable[MAYBE_ITERATOR_SYMBOL]||
6
6
  maybeIterable["@@iterator"];return"function"===typeof maybeIterable?maybeIterable:null}var ReactNoopUpdateQueue={isMounted:function(){return false},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}};var assign=Object.assign;var emptyObject={};function Component(props,context,updater){this.props=props;this.context=context;this.refs=emptyObject;this.updater=updater||ReactNoopUpdateQueue}Component.prototype.isReactComponent={};Component.prototype.setState=
7
7
  function(partialState,callback){if("object"!==typeof partialState&&"function"!==typeof partialState&&null!=partialState)throw Error("takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,partialState,callback,"setState")};Component.prototype.forceUpdate=function(callback){this.updater.enqueueForceUpdate(this,callback,"forceUpdate")};function ComponentDummy(){}ComponentDummy.prototype=Component.prototype;function PureComponent2(props,context,updater){
@@ -1287,16 +1287,16 @@ notice",tone:"info",text:`\u30E2\u30FC\u30C9\u3092 ${getMode(to).label}\uFF08${t
1287
1287
  xit \u306F /quit \u3082\u53EF\uFF09`,...PENDING_COMMANDS.length>0?[`\u672A\u5B9F\u88C5\u306E\u305F\u3081\u767B\u9332\u3057\u3066\u3044\u306A\u3044\u30B3\u30DE\u30F3\u30C9: ${PENDING_COMMANDS.map(c=>c.name).join(" ")}`]:[],"\u30AD\u30FC: Shift+Tab \u307E\u305F\u306F Alt+M \u3067\u30E2\u30FC\u30C9\u5DE1\u56DE \xB7 Ctrl+R \u3067\u76F4\u524D\u306E\u30C4\u30FC\u30EB\u51FA\u529B\u3092\u5C55\u958B","\u6539\u884C: Shift+Enter\uFF08kitty \u5BFE\u5FDC\u7AEF\u672B\uFF09\xB7 Ctrl+J\uFF08\u5168\u7AEF\u672B\uFF09\xB7 \\ \u3092\u6253\u3063\u3066\u304B\u3089 Enter \u3067\u3082\u53EF"].
1288
1288
  join("\n")});return;case"/context":{const snapshot=runtime.context.snapshot();const t=snapshot.totals;const resident=buildResidentSet(getMode(modeRef.current),{...permissionMode!==void 0?{permissionMode}:{}});commit({kind:"notice",tone:"info",text:[`\u30E2\u30C7\u30EB: ${modelLabel(model)}\uFF08\u30E2\u30FC\u30C9\u3068\u306F\u72EC\u7ACB\uFF09`,`\u30E2\u30FC\u30C9: ${getMode(modeRef.current).label} \u2014 \u6709\u52B9\u30C4\u30FC\u30EB glob: ${getMode(modeRef.current).tools.join(" ")}`,`\u63A5\u7D9A\u5148: ${runtime.
1289
1289
  relayUrl}\uFF08\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB: ${runtime.profileName}\uFF09`,`\u30BF\u30FC\u30F3\u6570: ${snapshot.turns} \xB7 \u76F4\u8FD1\u306E\u30D7\u30ED\u30F3\u30D7\u30C8\u9577: ${snapshot.lastPromptTokens} tok`,`\u30B3\u30F3\u30C6\u30AD\u30B9\u30C8\u6B8B\u91CF: ${snapshot.remainingPercent}%\uFF08\u7A93 200,000 tok \u306E\u6982\u7B97\uFF09`,`\u5B9F\u6E2C\u30C8\u30FC\u30AF\u30F3\u5408\u8A08: input ${t.inputTokens} / cache_read ${t.cacheReadTokens} / cache_write ${t.cacheWriteTokens} / \
1290
- output ${t.outputTokens}`,...snapshot.droppedMessages>0?[`\u4E0A\u9650\u306E\u305F\u3081\u843D\u3068\u3057\u305F\u3084\u308A\u53D6\u308A: ${snapshot.droppedMessages} \u4EF6`]:[],`\u5E38\u99D0\u30C4\u30FC\u30EB: ${resident.tools.length} \u672C / \u30B9\u30AD\u30FC\u30DE\u6982\u7B97 ${resident.tokens} tok\uFF08\u4E0A\u9650 ${RESIDENT_TOKEN_CAP} tok\uFF09`,` ${resident.tools.map(t2=>t2.name).join(" ")||"\uFF08\u306A\u3057\uFF09"}`,...resident.dropped.length>0?[` \u4E0A\u9650\u8D85\u904E\u3067\u5916\u3057\u305F\u30C4\u30FC\u30EB: ${resident.
1291
- dropped.join(" ")}`]:[],"TWP API \u306E\u30C4\u30FC\u30EB\uFF08\u30E1\u30BF\u30C4\u30FC\u30EB\u30FB\u30AB\u30BF\u30ED\u30B0\u914D\u4FE1\uFF09\u306F\u5225\u30BF\u30B9\u30AF\u3067\u8F09\u308A\u307E\u3059"].join("\n")});return}case"/demo":void runDemo("\uFF08\u30C7\u30E2\u518D\u751F\uFF09\u30C4\u30FC\u30EB\u30AB\u30FC\u30C9\u3068\u6A29\u9650\u30C0\u30A4\u30A2\u30ED\u30B0");return;default:commit({kind:"notice",tone:"warn",text:`\u4E0D\u660E\u306A\u30B3\u30DE\u30F3\u30C9: ${name}`})}},[catalog,commit,
1292
- exit,model,runDemo,runtime]);const submit=(0,import_react38.useCallback)(()=>{if(busyRef.current){commit({kind:"notice",tone:"warn",text:"\u5B9F\u884C\u4E2D\u3067\u3059\u3002Ctrl+C \u3067\u4E2D\u65AD\u3057\u3066\u304B\u3089\u9001\u4FE1\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5165\u529B\u306F\u4FDD\u6301\u3057\u3066\u3044\u307E\u3059\uFF09"});return}const text=bufferRef.current.text.trim();clearBuffer();setOverlay("none");if(text==="")return;if(text.startsWith("/")){runCommand(text);return}void runTurn2(
1293
- text)},[clearBuffer,commit,runCommand,runTurn2]);const paletteItems=(0,import_react38.useMemo)(()=>paletteFor(buffer.text,mode),[buffer.text,mode]);const onKey=(0,import_react38.useCallback)(ev=>{setKeyLog(prev=>[...prev.slice(-49),ev]);if(ev.name==="ctrl-d"){exit();return}if(ev.name==="ctrl-c"){if(busyRef.current){if(abortRef.current)return;abortRef.current=true;streamAbortRef.current?.abort();permissionResolver.current?.("no");stream.cancel();abortSleep();setRunningTool(null);if(!streamAbortRef.
1294
- current){commit({kind:"notice",tone:"warn",text:"\u4E2D\u65AD\u3057\u307E\u3057\u305F\uFF08Ctrl+C\uFF09"})}return}if(bufferRef.current.text!==""){clearBuffer();return}if(ctrlCArmed){exit();return}setCtrlCArmed(true);commit({kind:"notice",tone:"info",text:"\u3082\u3046\u4E00\u5EA6 Ctrl+C \u3067\u7D42\u4E86\u3057\u307E\u3059\uFF08Ctrl+D \u3067\u3082\u7D42\u4E86\uFF09"});return}setCtrlCArmed(false);if(ev.name==="shift-tab"||ev.name==="alt-m"){const to=nextMode(modeRef.current);setMode(to);return}if(ev.
1295
- name==="ctrl-r"){const last=lastToolRef.current;if(last)commit({kind:"tool",run:{...last,summary:`${last.summary}\uFF08\u5C55\u958B\uFF09`},expanded:true});return}if(overlay==="permission"){const resolve=permissionResolver.current;if(!resolve)return;if(ev.name==="paste"&&ev.value){const pasted=ev.value.replace(/\r\n?/g,"\n");setBuffer(b=>insert(b,pasted));return}const choices=pendingPermission?choicesFor(pendingPermission):PERMISSION_CHOICES;if(ev.name==="up")setSelected(s=>Math.max(0,s-1));else if(ev.
1296
- name==="down")setSelected(s=>Math.min(choices.length-1,s+1));else if(ev.name==="enter")resolve(choices[selectedRef.current]?.key??"no");else if(ev.name==="escape")resolve("no");else if(ev.name==="char"&&ev.value&&"123".includes(ev.value)){resolve(choices[Number(ev.value)-1]?.key??"no")}return}if(overlay==="doctor"){if(ev.name==="escape")setOverlay("none");return}if(overlay==="model"){if(ev.name==="up")setSelected(s=>Math.max(0,s-1));else if(ev.name==="down")setSelected(s=>Math.min(catalog.ids.length-
1297
- 1,s+1));else if(ev.name==="escape")setOverlay("none");else if(ev.name==="enter"){const pickedId=catalog.ids[selectedRef.current];if(pickedId!==void 0){setModel(pickedId);commit({kind:"notice",tone:"info",text:`\u30E2\u30C7\u30EB\u3092 ${modelLabel(pickedId)} \u306B\u5207\u308A\u66FF\u3048\u307E\u3057\u305F\uFF08\u30E2\u30FC\u30C9\u306F ${getMode(modeRef.current).label} \u306E\u307E\u307E\uFF09`})}setOverlay("none")}return}const palette=busyRef.current?[]:paletteFor(bufferRef.current.text,modeRef.
1298
- current);if(palette.length>0){if(ev.name==="up"){setSelected(s=>Math.max(0,s-1));return}if(ev.name==="down"){setSelected(s=>Math.min(palette.length-1,s+1));return}if(ev.name==="tab"){const picked=palette[selectedRef.current];if(picked){setBuffer(()=>({text:picked.name,cursor:picked.name.length}));setSelected(0)}return}if(ev.name==="enter"){const picked=palette[selectedRef.current];if(picked){clearBuffer();runCommand(picked.name)}return}if(ev.name==="escape"){clearBuffer();return}}switch(ev.name){case"\
1299
- char":if(ev.value){setBuffer(b=>insert(b,ev.value??""));setSelected(0)}return;case"paste":if(ev.value){const pasted=ev.value.replace(/\r\n?/g,"\n");setBuffer(b=>insert(b,pasted));setSelected(0)}return;case"newline":setBuffer(b=>insert(b,"\n"));return;case"enter":{const b=bufferRef.current;if(b.cursor>0&&b.text[b.cursor-1]==="\\"){setBuffer(prev=>({text:`${prev.text.slice(0,prev.cursor-1)}
1290
+ output ${t.outputTokens}`,...snapshot.droppedMessages>0?[`\u4E0A\u9650\u306E\u305F\u3081\u843D\u3068\u3057\u305F\u3084\u308A\u53D6\u308A: ${snapshot.droppedMessages} \u4EF6`]:[],`permission-mode: ${describePermissionMode(permissionMode)}`,`\u76E3\u67FB\u30ED\u30B0: ${describeAuditLog(audit)}`,`\u5E38\u99D0\u30C4\u30FC\u30EB: ${resident.tools.length} \u672C / \u30B9\u30AD\u30FC\u30DE\u6982\u7B97 ${resident.tokens} tok\uFF08\u4E0A\u9650 ${RESIDENT_TOKEN_CAP} tok\uFF09`,` ${resident.tools.map(t2=>t2.
1291
+ name).join(" ")||"\uFF08\u306A\u3057\uFF09"}`,...resident.dropped.length>0?[` \u4E0A\u9650\u8D85\u904E\u3067\u5916\u3057\u305F\u30C4\u30FC\u30EB: ${resident.dropped.join(" ")}`]:[],"TWP API \u306E\u30C4\u30FC\u30EB\uFF08\u30E1\u30BF\u30C4\u30FC\u30EB\u30FB\u30AB\u30BF\u30ED\u30B0\u914D\u4FE1\uFF09\u306F\u5225\u30BF\u30B9\u30AF\u3067\u8F09\u308A\u307E\u3059"].join("\n")});return}case"/demo":void runDemo("\uFF08\u30C7\u30E2\u518D\u751F\uFF09\u30C4\u30FC\u30EB\u30AB\u30FC\u30C9\u3068\u6A29\u9650\u30C0\u30A4\u30A2\u30ED\u30B0");
1292
+ return;default:commit({kind:"notice",tone:"warn",text:`\u4E0D\u660E\u306A\u30B3\u30DE\u30F3\u30C9: ${name}`})}},[audit,catalog,commit,exit,model,permissionMode,runDemo,runtime]);const submit=(0,import_react38.useCallback)(()=>{if(busyRef.current){commit({kind:"notice",tone:"warn",text:"\u5B9F\u884C\u4E2D\u3067\u3059\u3002Ctrl+C \u3067\u4E2D\u65AD\u3057\u3066\u304B\u3089\u9001\u4FE1\u3057\u3066\u304F\u3060\u3055\u3044\uFF08\u5165\u529B\u306F\u4FDD\u6301\u3057\u3066\u3044\u307E\u3059\uFF09"});return}
1293
+ const text=bufferRef.current.text.trim();clearBuffer();setOverlay("none");if(text==="")return;if(text.startsWith("/")){runCommand(text);return}void runTurn2(text)},[clearBuffer,commit,runCommand,runTurn2]);const paletteItems=(0,import_react38.useMemo)(()=>paletteFor(buffer.text,mode),[buffer.text,mode]);const onKey=(0,import_react38.useCallback)(ev=>{setKeyLog(prev=>[...prev.slice(-49),ev]);if(ev.name==="ctrl-d"){exit();return}if(ev.name==="ctrl-c"){if(busyRef.current){if(abortRef.current)return;
1294
+ abortRef.current=true;streamAbortRef.current?.abort();permissionResolver.current?.("no");stream.cancel();abortSleep();setRunningTool(null);if(!streamAbortRef.current){commit({kind:"notice",tone:"warn",text:"\u4E2D\u65AD\u3057\u307E\u3057\u305F\uFF08Ctrl+C\uFF09"})}return}if(bufferRef.current.text!==""){clearBuffer();return}if(ctrlCArmed){exit();return}setCtrlCArmed(true);commit({kind:"notice",tone:"info",text:"\u3082\u3046\u4E00\u5EA6 Ctrl+C \u3067\u7D42\u4E86\u3057\u307E\u3059\uFF08Ctrl+D \u3067\u3082\u7D42\u4E86\uFF09"});
1295
+ return}setCtrlCArmed(false);if(ev.name==="shift-tab"||ev.name==="alt-m"){const to=nextMode(modeRef.current);setMode(to);return}if(ev.name==="ctrl-r"){const last=lastToolRef.current;if(last)commit({kind:"tool",run:{...last,summary:`${last.summary}\uFF08\u5C55\u958B\uFF09`},expanded:true});return}if(overlay==="permission"){const resolve=permissionResolver.current;if(!resolve)return;if(ev.name==="paste"&&ev.value){const pasted=ev.value.replace(/\r\n?/g,"\n");setBuffer(b=>insert(b,pasted));return}const choices=pendingPermission?
1296
+ choicesFor(pendingPermission):PERMISSION_CHOICES;if(ev.name==="up")setSelected(s=>Math.max(0,s-1));else if(ev.name==="down")setSelected(s=>Math.min(choices.length-1,s+1));else if(ev.name==="enter")resolve(choices[selectedRef.current]?.key??"no");else if(ev.name==="escape")resolve("no");else if(ev.name==="char"&&ev.value&&"123".includes(ev.value)){resolve(choices[Number(ev.value)-1]?.key??"no")}return}if(overlay==="doctor"){if(ev.name==="escape")setOverlay("none");return}if(overlay==="model"){if(ev.
1297
+ name==="up")setSelected(s=>Math.max(0,s-1));else if(ev.name==="down")setSelected(s=>Math.min(catalog.ids.length-1,s+1));else if(ev.name==="escape")setOverlay("none");else if(ev.name==="enter"){const pickedId=catalog.ids[selectedRef.current];if(pickedId!==void 0){setModel(pickedId);commit({kind:"notice",tone:"info",text:`\u30E2\u30C7\u30EB\u3092 ${modelLabel(pickedId)} \u306B\u5207\u308A\u66FF\u3048\u307E\u3057\u305F\uFF08\u30E2\u30FC\u30C9\u306F ${getMode(modeRef.current).label} \u306E\u307E\u307E\uFF09`})}
1298
+ setOverlay("none")}return}const palette=busyRef.current?[]:paletteFor(bufferRef.current.text,modeRef.current);if(palette.length>0){if(ev.name==="up"){setSelected(s=>Math.max(0,s-1));return}if(ev.name==="down"){setSelected(s=>Math.min(palette.length-1,s+1));return}if(ev.name==="tab"){const picked=palette[selectedRef.current];if(picked){setBuffer(()=>({text:picked.name,cursor:picked.name.length}));setSelected(0)}return}if(ev.name==="enter"){const picked=palette[selectedRef.current];if(picked){clearBuffer();
1299
+ runCommand(picked.name)}return}if(ev.name==="escape"){clearBuffer();return}}switch(ev.name){case"char":if(ev.value){setBuffer(b=>insert(b,ev.value??""));setSelected(0)}return;case"paste":if(ev.value){const pasted=ev.value.replace(/\r\n?/g,"\n");setBuffer(b=>insert(b,pasted));setSelected(0)}return;case"newline":setBuffer(b=>insert(b,"\n"));return;case"enter":{const b=bufferRef.current;if(b.cursor>0&&b.text[b.cursor-1]==="\\"){setBuffer(prev=>({text:`${prev.text.slice(0,prev.cursor-1)}
1300
1300
  ${prev.text.slice(prev.cursor)}`,cursor:prev.cursor}));return}submit();return}case"backspace":setBuffer(b=>{const prev=prevBoundary(b.text,b.cursor);return prev===b.cursor?b:{text:b.text.slice(0,prev)+b.text.slice(b.cursor),cursor:prev}});setSelected(0);return;case"delete":setBuffer(b=>({text:b.text.slice(0,b.cursor)+b.text.slice(nextBoundary(b.text,b.cursor)),cursor:b.cursor}));return;case"left":setBuffer(b=>({...b,cursor:prevBoundary(b.text,b.cursor)}));return;case"right":setBuffer(b=>({...b,cursor:nextBoundary(
1301
1301
  b.text,b.cursor)}));return;case"home":setBuffer(b=>({...b,cursor:0}));return;case"end":setBuffer(b=>({...b,cursor:b.text.length}));return;case"ctrl-u":clearBuffer();return;default:return}},[busy,clearBuffer,commit,ctrlCArmed,exit,overlay,setBuffer,setSelected,stream,submit,runCommand]);useTerminalInput(onKey,setPasting);const streamRows=fitTailRows(stream.text,size.columns,budget.body).rows;const diffBudget=budget.body-12;const listBudget=Math.max(1,budget.body-6);const doctorBudget=Math.max(1,budget.
1302
1302
  body-11-doctorNetworkRows(networkDiagnostics));return(0,import_jsx_runtime9.jsxs)(Box_default,{flexDirection:"column",children:[(0,import_jsx_runtime9.jsx)(Static,{items,children:item=>(0,import_jsx_runtime9.jsx)(ItemView,{item},item.id)}),(0,import_jsx_runtime9.jsxs)(Box_default,{flexDirection:"column",marginTop:1,children:[stream.streaming||stream.text!==""?(0,import_jsx_runtime9.jsx)(Box_default,{flexDirection:"column",children:streamRows.map((line,i)=>(0,import_jsx_runtime9.jsx)(Text,{wrap:"\
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __twpCreateRequire } from 'node:module';
2
2
  const require = __twpCreateRequire(import.meta.url);
3
- import{readBody}from"./chunk-QVXZEUKN.js";import{isRecord,pick,requireResolved,singleRef,withResolved}from"./chunk-GFC2ASHE.js";import{BACKLOG_BASE_PATH,BACKLOG_PROJECT_SCOPE_LABEL,BACKLOG_SCOPE_LABEL,backlogSpacePath,resolveNamed}from"./chunk-GXVXQT57.js";import"./chunk-JKSXUBND.js";import"./chunk-II5RVJQN.js";import{ApiResponseError,UsageError}from"./chunk-M3GWY6NT.js";import"./chunk-5QCAIKFE.js";import"./chunk-NERYSBA4.js";import"./chunk-RZVI6PMW.js";
3
+ import{readBody}from"./chunk-QVXZEUKN.js";import{isRecord,pick,requireResolved,singleRef,withResolved}from"./chunk-GFC2ASHE.js";import{BACKLOG_BASE_PATH,BACKLOG_PROJECT_SCOPE_LABEL,BACKLOG_SCOPE_LABEL,backlogSpacePath,resolveNamed}from"./chunk-V4VHRASG.js";import"./chunk-JKSXUBND.js";import"./chunk-II5RVJQN.js";import{ApiResponseError,UsageError}from"./chunk-M3GWY6NT.js";import"./chunk-5QCAIKFE.js";import"./chunk-NERYSBA4.js";import"./chunk-RZVI6PMW.js";
4
4
  import"./chunk-J7QYPKVK.js";import"./chunk-NHYMHCAT.js";import"./chunk-VSJBJXZO.js";var DEFAULT_COUNT=20;var MAX_COUNT=100;var NUMERIC=/^[0-9]+$/;function isExactNumericId(value){return NUMERIC.test(value)&&String(Number(value))===value}var ISSUE_REF=/^(?:[A-Za-z0-9_]+-[0-9]+|[0-9]+)$/;var DATE=/^[0-9]{4}-[0-9]{2}-[0-9]{2}$/;var SPACE_COLUMNS=["id","space_url"];var PROJECT_COLUMNS=["id","projectKey","name"];var ISSUE_LIST_COLUMNS=["issueKey","summary","status","assignee","priority","dueDate","updated","descriptionTruncated"];var ISSUE_GET_COLUMNS=["id","issueKey","projectId","s\
5
5
  ummary","description","descriptionTruncated","status","issueType","priority","assignee","createdUser","parentIssueId","startDate","dueDate","estimatedHours","actualHours","created","updated"];var COMMENT_COLUMNS=["id","created","createdUserId","createdUser","content","changeLog"];function commentRow(row){const source=isRecord(row)?row:{};const user=isRecord(source["createdUser"])?source["createdUser"]:{};return pick({...source,createdUserId:user["id"]??null,createdUser:user["name"]??null},COMMENT_COLUMNS)}
6
6
  var ATTACHMENT_COLUMNS=["id","name","size","contentType","createdUserId","createdUser","created"];var STATUS_COLUMNS=["id","name","color"];var USER_COLUMNS=["id","userId","name","mailAddress","roleType"];var SPACE_FLAG={name:"--space",summary:"Backlog \u30B9\u30DA\u30FC\u30B9\uFF08ID / \u30B9\u30DA\u30FC\u30B9URL / \u30B5\u30D6\u30C9\u30E1\u30A4\u30F3\uFF09\u3002\u767B\u9332\u304C1\u4EF6\u306A\u3089\u7701\u7565\u3067\u304D\u307E\u3059",takesValue:true,placeholder:"<ID|URL>"};var BODY_MAX_CHARS=1e5;
@@ -3,5 +3,7 @@ const require = __twpCreateRequire(import.meta.url);
3
3
  var MODE_IDS=["dev","biz","plan"];function isModeId(value){return value!==void 0&&MODE_IDS.includes(value)}var MODES=[{id:"dev",label:"\u958B\u767A",color:"green",description:"\u30ED\u30FC\u30AB\u30EB\u30C4\u30FC\u30EB\u5168\u90E8 \uFF0B \u958B\u767A\u7CFB TWP \u30C9\u30E1\u30A4\u30F3\u5E38\u99D0",tools:["read_file","write_file","edit_file","bash","shell","glob","grep","git","twp_*"],permissions:{read_file:"allow",glob:"allow",grep:"allow",git:"allow",twp_get_task:"allow",twp_list_tasks:"allow",
4
4
  twp_update_task:"ask",bash:"ask",shell:"ask",write_file:"ask",edit_file:"ask","*":"ask"}},{id:"biz",label:"\u696D\u52D9",color:"cyan",description:"TWP \u30C9\u30E1\u30A4\u30F3\u4E2D\u5FC3\u3002bash \u3068 write_file \u306F deny",tools:["twp_*","read_file","glob","grep"],permissions:{read_file:"allow",glob:"allow",grep:"allow",twp_get_task:"allow",twp_list_tasks:"allow",twp_update_task:"ask",bash:"deny",shell:"deny",write_file:"deny",edit_file:"deny","*":"ask"}},{id:"plan",label:"\u30D7\u30E9\u30F3",
5
5
  color:"magenta",description:"\u8AAD\u307F\u53D6\u308A\u306E\u307F\u3002\u5168\u66F8\u304D\u8FBC\u307F deny",tools:["read_file","glob","grep","twp_get_*","twp_list_*"],permissions:{read_file:"allow",glob:"allow",grep:"allow",twp_get_task:"allow",twp_list_tasks:"allow",bash:"deny",shell:"deny",write_file:"deny",edit_file:"deny","*":"deny"}}];function getMode(id){const found=MODES.find(m=>m.id===id);if(!found)throw new Error(`unknown mode: ${id}`);return found}function nextMode(id){const i=MODES.findIndex(
6
- m=>m.id===id);const next=MODES[(i+1)%MODES.length];return next?next.id:"dev"}function checkPermission(toolName,mode){return mode.permissions[toolName]??mode.permissions["*"]??"ask"}var PERMISSION_MODE_IDS=["plan","acceptEdits","denyAll"];function isPermissionModeId(value){return value!==void 0&&PERMISSION_MODE_IDS.includes(value)}function applyPermissionMode(decision,risk,permissionMode){if(permissionMode===void 0)return{decision,reason:null};if(decision==="deny")return{decision,reason:null};switch(permissionMode){case"denyAll":return{decision:"deny",reason:"permission-mode=denyAll\uFF08\u5168\u30C4\u30FC\u30EB\u3092\u62D2\u5426\uFF09"};case"plan":if(risk==="read")return{decision,
7
- reason:null};return{decision:"deny",reason:`permission-mode=plan\uFF08${risk} \u30C4\u30FC\u30EB\u3092\u62D2\u5426\uFF09`};case"acceptEdits":if(risk==="write"&&decision==="ask"){return{decision:"allow",reason:"permission-mode=acceptEdits\uFF08write \u3092\u81EA\u52D5\u627F\u8A8D\uFF09"}}return{decision,reason:null};default:return{decision:"deny",reason:"\u4E0D\u660E\u306A permission-mode\uFF08\u5B89\u5168\u5074\u3067\u62D2\u5426\uFF09"}}}export{isModeId,getMode,nextMode,checkPermission,isPermissionModeId,applyPermissionMode};
6
+ m=>m.id===id);const next=MODES[(i+1)%MODES.length];return next?next.id:"dev"}function checkPermission(toolName,mode){return mode.permissions[toolName]??mode.permissions["*"]??"ask"}var PERMISSION_MODE_IDS=["plan","acceptEdits","denyAll"];function isPermissionModeId(value){return value!==void 0&&PERMISSION_MODE_IDS.includes(value)}function describePermissionMode(permissionMode){if(permissionMode===void 0)return"\u672A\u6307\u5B9A\uFF08\u30E2\u30FC\u30C9\u306E\u65B9\u91DD\u306E\u307E\u307E\uFF09";switch(permissionMode){case"plan":return"plan\uFF08read \u306E\u307F\u8A31\u53EF\u3002write / exec \u306F\u62D2\u5426\uFF09";case"acceptEdits":return"acceptEdits\uFF08write \u306E\u78BA\u8A8D\u3092\u81EA\u52D5\u627F\u8A8D\u3002read\
7
+ / exec \u306F\u30E2\u30FC\u30C9\u306E\u307E\u307E\uFF09";case"denyAll":return"denyAll\uFF08read \u3092\u542B\u3080\u5168\u30C4\u30FC\u30EB\u3092\u62D2\u5426\uFF09";default:{const exhaustive=permissionMode;return`${String(exhaustive)}\uFF08\u4E0D\u660E\u306A\u5024\u3002\u5B89\u5168\u5074\u3067\u5168\u62D2\u5426\uFF09`}}}function applyPermissionMode(decision,risk,permissionMode){if(permissionMode===void 0)return{decision,reason:null};if(decision==="deny")return{decision,reason:null};switch(permissionMode){case"\
8
+ denyAll":return{decision:"deny",reason:"permission-mode=denyAll\uFF08\u5168\u30C4\u30FC\u30EB\u3092\u62D2\u5426\uFF09"};case"plan":if(risk==="read")return{decision,reason:null};return{decision:"deny",reason:`permission-mode=plan\uFF08${risk} \u30C4\u30FC\u30EB\u3092\u62D2\u5426\uFF09`};case"acceptEdits":if(risk==="write"&&decision==="ask"){return{decision:"allow",reason:"permission-mode=acceptEdits\uFF08write \u3092\u81EA\u52D5\u627F\u8A8D\uFF09"}}return{decision,reason:null};default:return{decision:"\
9
+ deny",reason:"\u4E0D\u660E\u306A permission-mode\uFF08\u5B89\u5168\u5074\u3067\u62D2\u5426\uFF09"}}}export{isModeId,getMode,nextMode,checkPermission,isPermissionModeId,describePermissionMode,applyPermissionMode};
@@ -37,10 +37,10 @@ if(exclusiveSkills.size===0&&statusEndpoint!==null){warnings.push("operations.st
37
37
  stringArray(o["high_risk_skills"],"high_risk_skills",warnings)),preflightHosts:stringArray(o["preflight_hosts"],"preflight_hosts",warnings),releaseRecoverySkill,postSuccessEnqueue:stringMap(o["post_success_enqueue"],"post_success_enqueue",warnings),contractSkills:new Set(stringArray(o["contract_skills"],"contract_skills",warnings)),zeroTargetGates:parseZeroTargetGates(o["zero_target_gates"],warnings)},warnings}}function describeOperations(ops){if(ops===NO_OPERATIONS||ops.exclusiveSkills.size===0&&
38
38
  ops.highRiskSkills.size===0){return"\u904B\u7528\u8A2D\u5B9A: \u306A\u3057\uFF08\u30B9\u30AD\u30EB\u540D\u306B\u3088\u308B\u7279\u5225\u6271\u3044\u306F\u884C\u3044\u307E\u305B\u3093\uFF09"}const parts=[];if(ops.exclusiveSkills.size>0&&ops.statusEndpoint){parts.push(`\u6392\u4ED6 ${[...ops.exclusiveSkills].join(",")} \u2190 ${ops.statusEndpoint.url}`)}else if(ops.exclusiveSkills.size>0){parts.push(`\u6392\u4ED6 ${[...ops.exclusiveSkills].join(",")}\uFF08\u554F\u3044\u5408\u308F\u305B\u5148\u304C\u7121\u3044\u305F\u3081\u7121\u52B9\uFF09`)}
39
39
  if(ops.highRiskSkills.size>0)parts.push(`\u9AD8\u30EA\u30B9\u30AF ${ops.highRiskSkills.size}\u4EF6`);if(ops.releaseRecoverySkill)parts.push(`\u56DE\u53CE ${ops.releaseRecoverySkill}`);return`\u904B\u7528\u8A2D\u5B9A: ${parts.join(" / ")}`}function sanitizeInt(value,fallback,min=1){const n=typeof value==="number"?value:Number.parseInt(String(value??""),10);if(Number.isInteger(n)&&n>=min)return{value:n,warning:null};if(value===void 0||value===null||value==="")return{value:fallback,warning:null};return{value:fallback,warning:`'${String(value)}' \u306F${min}\u4EE5\u4E0A\u306E\u6574\u6570\u3067\u306F\u3042\u308A\u307E\u305B\u3093 \u2192 \u65E2\u5B9A ${fallback} \u3092\u4F7F\u3044\u307E\u3059`}}function nonEmpty(value){const t=value?.trim();
40
- return t===void 0||t===""?void 0:value}function resolveCharterEnabled(raw,local,warn){const v=(raw??"").trim();if(v!=="")return isBoolishTrue(v);if(local===void 0)return true;if(typeof local==="boolean")return local;if(typeof local==="string")return isBoolishTrue(local.trim()===""?"true":local);warn(`charter_enabled \u306F\u771F\u507D\u5024\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08'${String(local)}' \u306F\u89E3\u91C8\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u61B2\u7AE0\u3092\u524D\u7F6E\u3057\u307E\u3059\uFF09`);
41
- return true}function charterWrapper(raw,local,key,warn){if(raw!==void 0)return raw;if(local===void 0)return null;if(typeof local==="string")return local;warn(`${key} \u306F\u6587\u5B57\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08'${String(local)}' \u306F\u7121\u8996\u3057\u3001\u65E2\u5B9A\u306E\u56F2\u307F\u6587\u3092\u4F7F\u3044\u307E\u3059\uFF09`);return null}function loopStateDir(env=process.env){const explicit=env.TWP_OPS_STATE_DIR?.trim();if(explicit)return explicit;return path.
42
- join(os.homedir(),".twp-ops")}function releaseOutcomeLogPath(env=process.env){const explicit=env.RELEASE_OUTCOME_LOG?.trim();if(explicit)return explicit;return path.join(loopStateDir(env),"release-outcomes.tsv")}function localConfigPath(projectId,env=process.env){return path.join(twpHomeDir(env),"loops",`${projectFileKey(projectId)}.json`)}function loadLocalConfig(projectId,env=process.env){const file=localConfigPath(projectId,env);try{const parsed=JSON.parse(fs.readFileSync(file,"utf8"));return parsed!==
43
- null&&typeof parsed==="object"?parsed:{}}catch(err){if(err.code==="ENOENT")return{};throw new Error(`\u30EB\u30FC\u30D7\u8A2D\u5B9A\u306E\u8AAD\u307F\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${file}
40
+ return t===void 0||t===""?void 0:value}function resolveCharterEnabled(raw,local,warn){return resolveBoolSetting(raw,local,"charter_enabled",true,"\u61B2\u7AE0\u3092\u524D\u7F6E\u3057\u307E\u3059",warn)}function resolveBoolSetting(raw,local,key,fallback,fallbackNote,warn){const v=(raw??"").trim();if(v!=="")return isBoolishTrue(v);if(local===void 0)return fallback;if(typeof local==="boolean")return local;if(typeof local==="string")return isBoolishTrue(local.trim()===""?String(fallback):local);warn(
41
+ `${key} \u306F\u771F\u507D\u5024\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08'${String(local)}' \u306F\u89E3\u91C8\u3067\u304D\u306A\u3044\u305F\u3081\u3001${fallbackNote}\uFF09`);return fallback}function charterWrapper(raw,local,key,warn){if(raw!==void 0)return raw;if(local===void 0)return null;if(typeof local==="string")return local;warn(`${key} \u306F\u6587\u5B57\u5217\u3067\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\uFF08'${String(local)}' \u306F\u7121\u8996\u3057\u3001\u65E2\u5B9A\u306E\u56F2\u307F\u6587\u3092\u4F7F\u3044\u307E\u3059\uFF09`);
42
+ return null}function loopStateDir(env=process.env){const explicit=env.TWP_OPS_STATE_DIR?.trim();if(explicit)return explicit;return path.join(os.homedir(),".twp-ops")}function releaseOutcomeLogPath(env=process.env){const explicit=env.RELEASE_OUTCOME_LOG?.trim();if(explicit)return explicit;return path.join(loopStateDir(env),"release-outcomes.tsv")}function localConfigPath(projectId,env=process.env){return path.join(twpHomeDir(env),"loops",`${projectFileKey(projectId)}.json`)}function loadLocalConfig(projectId,env=process.
43
+ env){const file=localConfigPath(projectId,env);try{const parsed=JSON.parse(fs.readFileSync(file,"utf8"));return parsed!==null&&typeof parsed==="object"?parsed:{}}catch(err){if(err.code==="ENOENT")return{};throw new Error(`\u30EB\u30FC\u30D7\u8A2D\u5B9A\u306E\u8AAD\u307F\u53D6\u308A\u306B\u5931\u6557\u3057\u307E\u3057\u305F: ${file}
44
44
  ${err.message}`,{cause:err})}}function resolveRunnerId(stateDir,env=process.env){const file=env.RUNNER_ID_FILE&&env.RUNNER_ID_FILE.trim()!==""?env.RUNNER_ID_FILE:path.join(stateDir,"runner-id");let candidate=env.RUNNER_ID?.trim()??"";if(!candidate){try{candidate=fs.readFileSync(file,"utf8").split("\n")[0]?.trim()??""}catch{candidate=""}}let warning=null;if(candidate&&!/^[A-Za-z0-9._-]+$/.test(candidate)){warning=`runner_id '${candidate}' \u306B\u4F7F\u3048\u306A\u3044\u6587\u5B57\u304C\u542B\u307E\u308C\u308B\u305F\u3081\u63A1\u756A\u3057\u76F4\u3057\u307E\u3057\u305F\uFF08[A-Za-z0-9._-] \u306E\u307F\uFF09`;
45
45
  candidate=""}if(!candidate){const host=(os.hostname()||"host").split(".")[0]??"host";const hostPart=host.replace(/[^A-Za-z0-9._-]/g,"-").slice(0,32)||"host";candidate=`${hostPart}-${randomBytes(4).toString("hex")}`;try{fs.mkdirSync(path.dirname(file),{recursive:true,mode:448});fs.writeFileSync(file,`${candidate}
46
46
  `,{mode:384})}catch{warning=`runner_id \u3092 ${file} \u3078\u4FDD\u5B58\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F\u3002\u8D77\u52D5\u306E\u305F\u3073\u306B\u5225\u30E9\u30F3\u30CA\u30FC\u3068\u3057\u3066\u767B\u9332\u3055\u308C\u3001\u53F0\u6570\u4E0A\u9650\u306B\u9054\u3057\u307E\u3059`}}return{runnerId:candidate,warning}}function buildRunId(runnerId,now=new Date){const stamp=now.toISOString().replace(/[-:]/g,"").replace(/\.\d+Z$/,"Z");return`${runnerId}#${stamp}#${process.pid}`}function buildLoopConfig(input){
@@ -53,5 +53,5 @@ projectId:input.projectId,projectRef:input.projectRef,apiUrl:input.apiUrl,runner
53
53
  NT_LOOP_CONTENDED_MAX="),queueUndeterminedMax:num(env.QUEUE_UNDETERMINED_MAX,5,1,"QUEUE_UNDETERMINED_MAX="),staleReclaimHours:num(env.STALE_RECLAIM_HOURS,3,0,"STALE_RECLAIM_HOURS="),planLockTtlSec,planLockWaitMaxSec:num(env.PLAN_LOCK_WAIT_MAX,planLockTtlSec,0,"PLAN_LOCK_WAIT_MAX="),planLockPollIntervalSec:num(env.PLAN_LOCK_POLL_INTERVAL,60,1,"PLAN_LOCK_POLL_INTERVAL="),planLockRenewIntervalSec:num(env.PLAN_LOCK_RENEW_INTERVAL,Math.trunc(planLockTtlSec/3),1,"PLAN_LOCK_RENEW_INTERVAL="),planLockStealAttempts:num(
54
54
  env.PLAN_LOCK_STEAL_ATTEMPTS,3,0,"PLAN_LOCK_STEAL_ATTEMPTS="),planLockPermanentMax:num(env.PLAN_LOCK_PERMANENT_MAX,3,1,"PLAN_LOCK_PERMANENT_MAX="),scheduleMidcycleMax:num(env.SCHEDULE_MIDCYCLE_MAX,6,1,"SCHEDULE_MIDCYCLE_MAX="),blockerRecoveryMaxPerDay:num(env.BLOCKER_RECOVERY_MAX_PER_DAY,2,1,"BLOCKER_RECOVERY_MAX_PER_DAY="),releaseRerunAutoEnqueue:env.RELEASE_RERUN_AUTOENQUEUE_ENABLED!=="false",releaseRerunMaxPerCause:num(env.RELEASE_RERUN_MAX_PER_CAUSE,2,1,"RELEASE_RERUN_MAX_PER_CAUSE="),writebackMaxAgeDays:num(
55
55
  env.AGENT_LOOP_WRITEBACK_MAX_AGE_DAYS,7,1,"AGENT_LOOP_WRITEBACK_MAX_AGE_DAYS="),scheduleTimezone:nonEmpty(env.AGENT_LOOP_SCHEDULE_TZ)??"Asia/Tokyo",counterTimezone:nonEmpty(env.AGENT_LOOP_COUNTER_TZ)??"Asia/Tokyo",compileCommand:local.compile_command!==void 0&&local.compile_command.length>0?local.compile_command:null,charterFile:nonEmpty(env.CHARTER_FILE)??nonEmpty(local.charter_file)??"CONSTITUTION.md",charterEnabled:resolveCharterEnabled(env.CHARTER_ENABLED,local.charter_enabled,m=>warnings.push(
56
- m)),charterPrefix:charterWrapper(env.CHARTER_PREFIX,local.charter_prefix,"charter_prefix",m=>warnings.push(m)),charterSuffix:charterWrapper(env.CHARTER_SUFFIX,local.charter_suffix,"charter_suffix",m=>warnings.push(m)),ai:ai.config,operations:operations.operations,claudeLauncher:claudeLauncher.launcher,prefetch:prefetch.hooks,preflight:preflight.hooks,configHash:ai.config.hash(),version:input.version,warnings,releaseOutcomeLogPath:releaseOutcomeLogPath(env)}}function localDate(timezone,now=new Date){
57
- const fmt=new Intl.DateTimeFormat("en-CA",{timeZone:timezone,year:"numeric",month:"2-digit",day:"2-digit"});return fmt.format(now)}export{parseClaudeLauncher,evaluateOwnership,runPrefetch,runPreflight,formatHookWiring,formatHookIds,describeOperations,loopStateDir,localConfigPath,buildLoopConfig,localDate};
56
+ m)),charterPrefix:charterWrapper(env.CHARTER_PREFIX,local.charter_prefix,"charter_prefix",m=>warnings.push(m)),charterSuffix:charterWrapper(env.CHARTER_SUFFIX,local.charter_suffix,"charter_suffix",m=>warnings.push(m)),planEnabled:resolveBoolSetting(env.PLAN_ENABLED,local.plan_enabled,"plan_enabled",true,"\u8A08\u753B\u30D5\u30A7\u30FC\u30BA\u3092\u5B9F\u884C\u3057\u307E\u3059",m=>warnings.push(m)),ai:ai.config,operations:operations.operations,claudeLauncher:claudeLauncher.launcher,prefetch:prefetch.
57
+ hooks,preflight:preflight.hooks,configHash:ai.config.hash(),version:input.version,warnings,releaseOutcomeLogPath:releaseOutcomeLogPath(env)}}function localDate(timezone,now=new Date){const fmt=new Intl.DateTimeFormat("en-CA",{timeZone:timezone,year:"numeric",month:"2-digit",day:"2-digit"});return fmt.format(now)}export{parseClaudeLauncher,evaluateOwnership,runPrefetch,runPreflight,formatHookWiring,formatHookIds,describeOperations,loopStateDir,localConfigPath,buildLoopConfig,localDate};
@@ -24,8 +24,9 @@ res.status)}safeProjectIdPolicy.assertId(projectId);return{projectId,task}}async
24
24
  id"])===null){throw new ResolveError("\u30E6\u30FC\u30B6\u30FC\u53D6\u5F97\u306E\u5FDC\u7B54\u306B user.id \u304C\u3042\u308A\u307E\u305B\u3093\u3002\u63A5\u7D9A\u5148\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",res.status)}return{id:user["id"],name:str(user["name"])??user["id"],email:str(user["email"])}}async status(projectId,input){return resolveNamed(this.applyAlias("status",input),await this.statuses(projectId),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9"})}async taskType(projectId,input){
25
25
  return resolveNamed(this.applyAlias("type",input),await this.taskTypes(projectId),{flag:"--type",label:"\u7A2E\u5225"})}async assignee(projectId,input,flag="--assignee"){if(input.trim().toLowerCase()===SELF_REF)return this.self();const value=this.applyAlias("assignee",input);if(value.trim().toLowerCase()===SELF_REF)return this.self();return resolveNamed(value,await this.members(projectId),{flag,label:"\u30E1\u30F3\u30D0\u30FC"})}async self(){const me=await this.currentUser();return{id:me.id,name:me.
26
26
  name,...me.email!==null?{aliases:[me.email]}:{}}}async defaultStatus(projectId){return requireDefault(await this.statuses(projectId),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9"})}async defaultTaskType(projectId){return requireDefault(await this.taskTypes(projectId),{flag:"--type",label:"\u7A2E\u5225"})}async statuses(projectId){return namedFromRows(await this.taskMasterRows("status",projectId),"\u30B9\u30C6\u30FC\u30BF\u30B9",codedMasterRow)}async taskTypes(projectId){return namedFromRows(
27
- await this.taskMasterRows("type",projectId),"\u7A2E\u5225",codedMasterRow)}async taskMasterRows(kind,projectId){const spec=TASK_MASTERS[kind];return this.cached(spec.scope,projectId,async()=>rawListFrom(await this.get(`/api/v2/projects/${encodeURIComponent(projectId)}/${spec.path}`),spec.envelope,spec.label))}async privateStatuses(){return this.privateMasters("statuses","\u30B9\u30C6\u30FC\u30BF\u30B9")}async privateTaskTypes(){return this.privateMasters("types","\u7A2E\u5225")}async privateStatus(input){
28
- return resolveNamed(this.applyAlias("status",input),await this.privateStatuses(),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9",scope:PRIVATE_SCOPE_LABEL})}async privateTaskType(input){return resolveNamed(this.applyAlias("type",input),await this.privateTaskTypes(),{flag:"--type",label:"\u7A2E\u5225",scope:PRIVATE_SCOPE_LABEL})}async privateDefaultStatus(){return requireDefault(await this.privateStatuses(),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9",scope:PRIVATE_SCOPE_LABEL})}async privateDefaultTaskType(){
27
+ await this.taskMasterRows("type",projectId),"\u7A2E\u5225",codedMasterRow)}async taskMaster(kind,projectId,input,flag){const spec=TASK_MASTERS[kind];return resolveNamed(input,await this.taskMasterRefs(kind,projectId),{flag,label:spec.label})}async taskMasterRefs(kind,projectId){const spec=TASK_MASTERS[kind];return namedFromRows(await this.taskMasterRows(kind,projectId),spec.label,codedMasterRow)}async privateTaskMaster(envelope,input,flag,label){return resolveNamed(input,await this.privateMasters(
28
+ envelope,label),{flag,label,scope:PRIVATE_SCOPE_LABEL})}async taskMasterRows(kind,projectId){const spec=TASK_MASTERS[kind];return this.cached(spec.scope,projectId,async()=>rawListFrom(await this.get(`/api/v2/projects/${encodeURIComponent(projectId)}/${spec.path}`),spec.envelope,spec.label))}async privateStatuses(){return this.privateMasters("statuses","\u30B9\u30C6\u30FC\u30BF\u30B9")}async privateTaskTypes(){return this.privateMasters("types","\u7A2E\u5225")}async privateStatus(input){return resolveNamed(
29
+ this.applyAlias("status",input),await this.privateStatuses(),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9",scope:PRIVATE_SCOPE_LABEL})}async privateTaskType(input){return resolveNamed(this.applyAlias("type",input),await this.privateTaskTypes(),{flag:"--type",label:"\u7A2E\u5225",scope:PRIVATE_SCOPE_LABEL})}async privateDefaultStatus(){return requireDefault(await this.privateStatuses(),{flag:"--status",label:"\u30B9\u30C6\u30FC\u30BF\u30B9",scope:PRIVATE_SCOPE_LABEL})}async privateDefaultTaskType(){
29
30
  return requireDefault(await this.privateTaskTypes(),{flag:"--type",label:"\u7A2E\u5225",scope:PRIVATE_SCOPE_LABEL})}async privateTask(ref){const trimmed=ref.trim();const res=await this.get(`${PRIVATE_TASKS_PATH}/${encodeURIComponent(trimmed)}`);if(res.status===404){throw new ResolveError(`\u500B\u4EBA\u30BF\u30B9\u30AF\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093: ${trimmed}`,404)}if(!res.ok){throw new ResolveError(`\u500B\u4EBA\u30BF\u30B9\u30AF\u3092\u53D6\u5F97\u3067\u304D\u307E\u305B\u3093\u3067\u3057\u305F: ${trimmed}\
30
31
  \uFF08HTTP ${res.status}\uFF09\u3002\u63A5\u7D9A\u5148\u3068\u30ED\u30B0\u30A4\u30F3\u72B6\u614B\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002`,res.status)}const task=isRecord(res.json)?res.json["task"]:void 0;if(!isRecord(task)){throw new ResolveError("\u500B\u4EBA\u30BF\u30B9\u30AF\u306E\u5FDC\u7B54\u306B task \u304C\u3042\u308A\u307E\u305B\u3093\u3002\u63A5\u7D9A\u5148\u3092\u78BA\u8A8D\u3057\u3066\u304F\u3060\u3055\u3044\u3002",res.status)}return task}async privateMasters(envelope,label){
31
32
  return namedFromRows(await this.privateMasterRows(envelope,label),label,codedMasterRow)}async privateMasterRows(envelope,label){return this.cached(`private-${envelope}`,PRIVATE_MASTERS_CACHE_KEY,async()=>rawListFrom(await this.privateMastersResponse(),envelope,label))}privateMastersResponse(){this.privateMastersInFlight??=this.get(`${PRIVATE_TASKS_PATH}/masters`);return this.privateMastersInFlight}async members(projectId){return this.cached("members",projectId,()=>this.namedList(`/api/v2/project\
@@ -6,7 +6,7 @@ this.note].join("\n");return Promise.resolve({outcome:"ok",usedAi:"noop",serverA
6
6
  super('\u5B9F\u884C\u30A8\u30F3\u30B8\u30F3\u304C\u6307\u5B9A\u3055\u308C\u3066\u3044\u307E\u305B\u3093\u3002\n \u5B9F AI \u3092\u8D77\u52D5\u3059\u308B\u306A\u3089 --engine cli\uFF08\u8A2D\u5B9A\u306A\u3089 "engine": "cli"\uFF09\u3092\u6307\u5B9A\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n \u9AA8\u683C\u3060\u3051\u3092\u691C\u8A3C\u3057\u305F\u3044\u5834\u5408\u306F --engine noop \u3092**\u660E\u793A**\u3057\u3066\u304F\u3060\u3055\u3044\u3002\n \u26A0\uFE0F noop \u306F AI \u30921\u3064\u3082\u8D77\u52D5\u305B\u305A\u30A2\u30A4\u30C6\u30E0\u3092 completed \u306B\u3057\u307E\u3059\u3002**\u5B9F\u30AD\u30E5\u30FC\uFF08\u672C\u756A\u306E TWP \u7B49\uFF09\u3078\u5411\u3051\u306A\u3044\u3053\u3068**\n \u5B9A\u671F\u7531\u6765\u306E\u30A2\u30A4\u30C6\u30E0\u306A\u3089\u67A0\u307E\u3067\u6D88\u5316\u3055\u308C\u3001\u305D\u306E\u7A93\u306E release-deploy / develop-merge \u304C\u767A\u706B\u3057\u306A\u304F\u306A\u308A\u307E\u3059\u3002')}};var MAX_SCAN_BYTES=512*1024;var PROGRESS_PREFIX=/^\s*\[\d{2}:\d{2}:\d{2}\]\s*/;var FINAL_REPORT_BEGIN="<<<AI_FINAL_REPORT>>>";var FINAL_REPORT_END="<<<END_AI_FINAL_REPORT>>>";var TRANSCRIPT_MARKER=/^(>>|<<|⛔|!!)\s/;function stripProgressPrefix(line){return line.replace(PROGRESS_PREFIX,"").trim()}function stripTranscript(raw){return filterLines(raw,true)}function stripModelProse(raw){return filterLines(raw,false)}function filterLines(raw,dropToolLines){const out=[];let inReport=false;for(const line of raw.
7
7
  split("\n")){if(line.includes(FINAL_REPORT_BEGIN)){inReport=true;continue}if(line.includes(FINAL_REPORT_END)){inReport=false;continue}if(inReport||line.includes("\u{1F4AC}"))continue;if(dropToolLines&&TRANSCRIPT_MARKER.test(stripProgressPrefix(line)))continue;out.push(line)}return out.join("\n")}var UNTRUSTED_PATTERNS=[/has not been trusted/i,/Ignoring [0-9]+ permissions\.allow entries/i];function isUntrusted(raw){const text=stripTranscript(raw);return UNTRUSTED_PATTERNS.some(p=>p.test(text))}var CLI_FATAL_TEXT_PATTERNS=[
8
8
  /^api error\b/i,/^failed to authenticate\b/i];function isCliFatalText(text){const head=text.trim();return CLI_FATAL_TEXT_PATTERNS.some(p=>p.test(head))}var CODEX_PLAIN_LIMIT_PATTERNS=[/^(?:error\s*:\s*)?you(?:'ve| have)? hit (?:your|the) (?:usage|session|weekly|rate|quota|spend) (?:limit|cap)\b.*$/i,/^(?:error\s*:\s*)?(?:your|the) (?:usage|rate|session|quota) limit (?:has been )?(?:reached|exceeded)\b.*$/i,/^(?:error\s*:\s*)?(?:usage|rate|session|quota) limit (?:reached|exceeded)\b.*$/i,/^try again at\s+(?:jan|feb|mar|apr|may|jun|jul|aug|sep|oct|nov|dec)[a-z]*\s+\d{1,2}(?:st|nd|rd|th)?\b.*$/i];
9
- var CODEX_RUST_LIMIT_PATTERN=/^(?:\d{4}-\d{2}-\d{2}T\S+\s+)?(?:ERROR|WARN)\s+codex(?:[_:][a-z0-9_:-]+)*\s*:\s*.*(?:\b(?:429|529)\b|(?:usage|rate|session)[ ._-]*limit|quota[_ -]?(?:exhausted|exceeded))/i;var COMMON_LIMIT_PATTERNS=[/(?:status|code|http)[^a-z0-9]{0,10}429/i,/429[^0-9].{0,15}(?:too many|rate|throttl)/i,/(?:status|code|http)[^a-z0-9]{0,10}529/i,/529[^0-9].{0,15}overloaded/i,/too many requests/i,/max.?spend.?(?:limit|reached|exceeded)/i,/spending.?limit/i,/resets?\s+\d+(?::\d+)?\s*(?:am|pm)/i];
9
+ var CODEX_RUST_LIMIT_PATTERN=/^(?:\d{4}-\d{2}-\d{2}T\S+\s+)?(?:ERROR|WARN)\s+codex(?:[_:]+[a-z0-9-]+){0,8}\s*:\s*.*(?:\b(?:429|529)\b|(?:usage|rate|session)[ ._-]*limit|quota[_ -]?(?:exhausted|exceeded))/i;var COMMON_LIMIT_PATTERNS=[/(?:status|code|http)[^a-z0-9]{0,10}429/i,/429[^0-9].{0,15}(?:too many|rate|throttl)/i,/(?:status|code|http)[^a-z0-9]{0,10}529/i,/529[^0-9].{0,15}overloaded/i,/too many requests/i,/max.?spend.?(?:limit|reached|exceeded)/i,/spending.?limit/i,/resets?\s+\d+(?::\d+)?\s*(?:am|pm)/i];
10
10
  var GEMINI_LIMIT_PATTERNS=[/terminalquotaerror/i,/retryablequotaerror/i,/quota_exhausted/i,/model_capacity_exhausted/i,/exhausted your capacity/i,/no capacity available/i,/ratelimitexceeded/i];var CLAUDE_LIMIT_PATTERNS=[/rate.?limit/i,/usage.?limit/i,/session.?limit/i,/quota.?(?:exceeded|reached|limit)/i,/(?:api|server|model).{0,20}overloaded/i,/hit.{0,10}(?:your|the).{0,20}limit/i];function isRateLimited(raw,ai){const text=stripTranscript(raw);if(ai==="codex"){for(const line of text.split("\n")){
11
11
  const normalized=stripProgressPrefix(line);if(CODEX_RUST_LIMIT_PATTERN.test(normalized))return true;if(CODEX_PLAIN_LIMIT_PATTERNS.some(p=>fullMatch(p,normalized)))return true}return false}const patterns=[...COMMON_LIMIT_PATTERNS,...ai==="gemini"?GEMINI_LIMIT_PATTERNS:[],...ai==="claude"?CLAUDE_LIMIT_PATTERNS:[]];return patterns.some(p=>p.test(text))}function fullMatch(pattern,value){const m=pattern.exec(value);return m!==null&&m[0]===value}var AUTH_ERROR_PATTERNS=[/(?:status|code|http)[^a-z0-9]{0,10}401/i,
12
12
  /(?:status|code|http)[^a-z0-9]{0,10}403/i,/401\s+unauthorized/i,/403\s+forbidden/i,/invalid.{0,10}(?:api.?key|token|credential)/i,/authentication.{0,10}(?:failed|error|invalid)/i,/(?:api.?key|token).{0,10}(?:invalid|expired|missing|rejected)/i,/not logged in/i,/please (?:run )?login/i,/(?:codex|gemini|copilot|claude)\s+login/i,/failed to authenticate/i,/oauth (?:session|token).{0,30}(?:expired|invalid|revoked)/i];function isAuthError(raw){const text=stripModelProse(raw);return AUTH_ERROR_PATTERNS.
@@ -14,4 +14,4 @@ some(p=>p.test(text))}function rateLimitWaitSeconds(raw,now=new Date){const clau
14
14
  hour,minute,0,0);if(reset.getTime()<=now.getTime())reset.setDate(reset.getDate()+1);const wait=Math.trunc((reset.getTime()-now.getTime())/1e3);if(wait>0&&wait<=21600)return wait+30}}const gemini=/reset\s+after\s+(\d+)h(\d+)m(?:(\d+)s)?/i.exec(raw);if(gemini){const wait=Number(gemini[1])*3600+Number(gemini[2])*60+Number(gemini[3]??0);if(wait>0&&wait<=86400)return wait+30}const codex=/try again at\s+(\w+)\s+(\d+)(?:st|nd|rd|th)?,?\s*(\d{4})?\s+(\d{1,2}):(\d{2})\s*(AM|PM)/i.exec(raw);if(codex){const months={
15
15
  jan:0,feb:1,mar:2,apr:3,may:4,jun:5,jul:6,aug:7,sep:8,oct:9,nov:10,dec:11};const mon=months[(codex[1]??"").slice(0,3).toLowerCase()];if(mon!==void 0){let hour=Number(codex[4]);const ampm=(codex[6]??"").toLowerCase();if(ampm==="pm"&&hour!==12)hour+=12;else if(ampm==="am"&&hour===12)hour=0;const year=codex[3]?Number(codex[3]):now.getFullYear();const reset=new Date(year,mon,Number(codex[2]),hour,Number(codex[5]),0,0);const wait=Math.trunc((reset.getTime()-now.getTime())/1e3);if(wait>0)return wait+30}}
16
16
  return null}function maxTurnsReached(raw,maxTurns){if(!Number.isFinite(maxTurns)||maxTurns<=0)return false;const matches=raw.match(/完了 \(turns: (\d+)/g);const last=matches?.[matches.length-1];if(last===void 0)return false;const turns=Number.parseInt(/(\d+)$/.exec(last)?.[1]??"",10);return Number.isInteger(turns)&&turns>=maxTurns}function tailForScan(text){return text.length<=MAX_SCAN_BYTES?text:text.slice(text.length-MAX_SCAN_BYTES)}var HINT_MAX_CHARS=200;var HINT_ALLOWED=[/^(?:error|fatal|panic|exception|warn(?:ing)?)\b\s*[:!-]?\s/i,
17
- /^(?:\d{4}-\d{2}-\d{2}T\S+\s+)?(?:ERROR|WARN)\s+codex(?:[_:][a-z0-9_-]+)*\s*:/i,/^api error\b/i,/^failed to authenticate\b/i];function failureHint(raw){const text=stripTranscript(tailForScan(raw));const lines=text.split("\n");for(let i=lines.length-1;i>=0;i-=1){const line=stripProgressPrefix(lines[i]??"");if(line===""||!HINT_ALLOWED.some(p=>p.test(line)))continue;const points=Array.from(line);return points.length<=HINT_MAX_CHARS?line:`${points.slice(0,HINT_MAX_CHARS).join("")}\u2026`}return""}export{isAiUnavailable,needsHumanToRestoreAi,aiUnavailableLabel,isServerAiType,NoopEngine,UnknownEngineError,assertKnownEngine,EngineNotConfiguredError,isUntrusted,isCliFatalText,isRateLimited,isAuthError,rateLimitWaitSeconds,maxTurnsReached,tailForScan,failureHint};
17
+ /^(?:\d{4}-\d{2}-\d{2}T\S+\s+)?(?:ERROR|WARN)\s+codex(?:[_:]+[a-z0-9-]+){0,8}\s*:/i,/^api error\b/i,/^failed to authenticate\b/i];function failureHint(raw){const text=stripTranscript(tailForScan(raw));const lines=text.split("\n");for(let i=lines.length-1;i>=0;i-=1){const line=stripProgressPrefix(lines[i]??"");if(line===""||!HINT_ALLOWED.some(p=>p.test(line)))continue;const points=Array.from(line);return points.length<=HINT_MAX_CHARS?line:`${points.slice(0,HINT_MAX_CHARS).join("")}\u2026`}return""}export{isAiUnavailable,needsHumanToRestoreAi,aiUnavailableLabel,isServerAiType,NoopEngine,UnknownEngineError,assertKnownEngine,EngineNotConfiguredError,isUntrusted,isCliFatalText,isRateLimited,isAuthError,rateLimitWaitSeconds,maxTurnsReached,tailForScan,failureHint};
@@ -1,6 +1,6 @@
1
1
  import { createRequire as __twpCreateRequire } from 'node:module';
2
2
  const require = __twpCreateRequire(import.meta.url);
3
- import{isForceOnly,killProcessTree,system32}from"./chunk-N2UVRM3Z.js";import{applyPermissionMode,checkPermission}from"./chunk-NNOYO67O.js";import{DEFAULT_MAX_TOKENS,emptyUsage}from"./chunk-RQFG3OUL.js";import{findExecutable,isWindowsDriveAbsolute}from"./chunk-PMOUHEJQ.js";import{configReadDirs,ensureTwpHome,twpHomeDir}from"./chunk-RZVI6PMW.js";import{sep as sep2}from"path";import{realpathSync}from"fs";import{homedir}from"os";import{dirname,isAbsolute,relative,resolve,sep}from"path";var PathDeniedError=class extends Error{constructor(message){super(message);this.name="PathDeniedError"}};function resolveToolPath(input,cwd,home=homedir()){if(typeof input!=="string"||input.trim()===""){throw new PathDeniedError("path must be a non-empty string")}const expanded=expandHome(input,home);const abs=isAbsolute(expanded)?resolve(expanded):resolve(cwd,expanded);const root=realOrSelf(resolve(cwd));assertInside(abs,resolve(cwd),abs);assertNotSecret(abs,home);const real=realOrSelf(abs);if(real!==
3
+ import{isForceOnly,killProcessTree,system32}from"./chunk-N2UVRM3Z.js";import{applyPermissionMode,checkPermission}from"./chunk-4WK2ECUX.js";import{DEFAULT_MAX_TOKENS,emptyUsage}from"./chunk-RQFG3OUL.js";import{findExecutable,isWindowsDriveAbsolute}from"./chunk-PMOUHEJQ.js";import{configReadDirs,ensureTwpHome,twpHomeDir}from"./chunk-RZVI6PMW.js";import{sep as sep2}from"path";import{realpathSync}from"fs";import{homedir}from"os";import{dirname,isAbsolute,relative,resolve,sep}from"path";var PathDeniedError=class extends Error{constructor(message){super(message);this.name="PathDeniedError"}};function resolveToolPath(input,cwd,home=homedir()){if(typeof input!=="string"||input.trim()===""){throw new PathDeniedError("path must be a non-empty string")}const expanded=expandHome(input,home);const abs=isAbsolute(expanded)?resolve(expanded):resolve(cwd,expanded);const root=realOrSelf(resolve(cwd));assertInside(abs,resolve(cwd),abs);assertNotSecret(abs,home);const real=realOrSelf(abs);if(real!==
4
4
  abs){assertInside(real,root,abs);assertNotSecret(real,home)}return abs}function realToolPath(input,cwd,home=homedir()){return realOrSelf(resolveToolPath(input,cwd,home))}function assertInside(target,root,reported){const rel=relative(root,target);const outside=rel===".."||rel.startsWith(`..${sep}`)||isAbsolute(rel);if(outside){throw new PathDeniedError(`path escapes the working directory (${reported}). Only paths under ${root} can be accessed.`)}}function realOrSelf(target){let current=target;const rest=[];
5
5
  for(;;){try{const real=realpathSync(current);return rest.length===0?real:resolve(real,...rest.reverse())}catch{const parent=dirname(current);if(parent===current)return target;rest.push(current.slice(parent.length+1));current=parent}}}function assertNotSecret(absPath,home=homedir(),env=process.env){const reason=secretReason(absPath,home,env);if(reason!==null)throw new PathDeniedError(`refusing to access ${absPath}: ${reason}`)}function secretReason(absPath,_home=homedir(),env=process.env){const lower=absPath.
6
6
  toLowerCase();const segments=lower.split(sep);const base=segments[segments.length-1]??"";const parent=segments[segments.length-2]??"";if(base===".env"||base.startsWith(".env."))return".env files are denied (design \xA77)";if(segments.includes(".ssh"))return"SSH key material is denied (design \xA77)";if(parent===".git"&&base==="config"){return".git/config is denied (it can hold a GitHub token in the remote URL)"}if(base===".netrc"||base==="_netrc"||base===".npmrc")return"credential files are deni\
@@ -8,22 +8,23 @@ ed";if(parent===".aws"&&(base==="credentials"||base==="config"))return"AWS crede
8
8
  audit logs are denied (design \xA77)";for(const dir of configReadDirs(env)){if(lower.startsWith(resolve(dir,"logs").toLowerCase()+sep)){return"TWP audit logs are denied (design \xA77)"}}}return null}function toolRelative(cwd,absPath){const rel=relative(cwd,absPath);return sep==="\\"?rel.split("\\").join("/"):rel}function isInsideCwd(absPath,cwd){const root=resolve(cwd);if(!withinLexically(absPath,root))return false;const real=realOrSelf(absPath);return real===absPath||withinLexically(real,realOrSelf(
9
9
  root))}function withinLexically(target,root){const rel=relative(root,target);return!(rel===".."||rel.startsWith(`..${sep}`)||isAbsolute(rel))}function expandHome(input,home){if(input==="~")return home;if(input.startsWith("~/")||input.startsWith(`~${sep}`))return resolve(home,input.slice(2));return input}function isSingleCommand(command){let quote=null;for(let i=0;i<command.length;i++){const ch=command[i];const next=command[i+1];if(quote==="'"){if(ch==="'")quote=null;continue}if(quote==='"'){if(ch==="\\"){i++;continue}if(ch==="`")return false;if(ch==="$"&&next==="(")return false;if(ch==='"')quote=null;continue}switch(ch){case'"':case"'":quote=ch;continue;case"\\":i++;continue;case";":case"&":case"|":case"\n":case"`":case">":case"<":return false;case"$":if(next==="(")return false;continue;default:
10
10
  continue}}return true}function isRecursiveForceRemove(command){const re=/(^|[^\w.-])(rm|rmdir)([^\w.-]|$)/g;for(;;){const m=re.exec(command);if(m===null)return false;const tail=command.slice(m.index+m[0].length);const segment=tail.split(/[;&|\n]/)[0]??"";const tokens=segment.split(/\s+/).filter(t=>t.startsWith("-"));let recursive=false;let force=false;for(const flag of tokens){if(flag==="--recursive")recursive=true;if(flag==="--force")force=true;if(!flag.startsWith("--")){if(flag.includes("r")||
11
- flag.includes("R"))recursive=true;if(flag.includes("f"))force=true}}if(recursive&&force)return true}}function neverAutoAllowReason(toolName,input){if(toolName!=="bash"&&toolName!=="shell")return null;const command=typeof input["command"]==="string"?input["command"]:"";if(isRecursiveForceRemove(command))return"rm -rf \u3092\u542B\u3080\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059";if(!isSingleCommand(command)){return"\u8907\u6570\u306E\u30B3\u30DE\u30F3\u30C9\u306B\u5206\u5C90\u3057\u3066\u3044\u308B\u305F\u3081\uFF08&& ; | $() \u306A\u3069\uFF09\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059"}
11
+ flag.includes("R"))recursive=true;if(flag.includes("f"))force=true}}if(recursive&&force)return true}}function neverAutoAllowReason(tool,input){if(tool.risk!=="exec")return null;let declared;try{declared=tool.execCommands?.(input)??null}catch{declared=null}const shell=(declared?.shell??[]).filter(command=>typeof command==="string"&&command!=="");const argv=(declared?.argv??[]).map(entry=>Array.isArray(entry)?entry.join(" "):"").filter(command=>command!=="");if(shell.length===0&&argv.length===0){return`${tool.
12
+ name} \u304C\u5B9F\u884C\u3059\u308B\u30B3\u30DE\u30F3\u30C9\u3092\u7279\u5B9A\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059`}for(const command of[...shell,...argv]){if(isRecursiveForceRemove(command))return"rm -rf \u3092\u542B\u3080\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059"}for(const command of shell){if(!isSingleCommand(command)){return"\u8907\u6570\u306E\u30B3\u30DE\u30F3\u30C9\u306B\u5206\u5C90\u3057\u3066\u3044\u308B\u305F\u3081\uFF08&& ; | $() \u306A\u3069\uFF09\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059"}}
12
13
  return null}function autoApproveExemptReason(tool,input,cwd){if(tool.risk!=="write")return null;const raw=input["path"]??input["file_path"]??input["dest"]??input["target"]??input["filename"];if(typeof raw!=="string"||raw==="")return"\u66F8\u304D\u8FBC\u307F\u5148\u3092\u5224\u5B9A\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059";let absolute;try{absolute=realToolPath(raw,cwd)}catch{return"\u66F8\u304D\u8FBC\u307F\u5148\u3092\u89E3\u6C7A\u3067\u304D\u306A\u3044\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059"}
13
14
  const segments=absolute.toLowerCase().split(sep2);const base=segments[segments.length-1]??"";if(segments.includes(".git"))return".git/ \u914D\u4E0B\u306F\u6B21\u306E git \u64CD\u4F5C\u3067\u5B9F\u884C\u3055\u308C\u308B\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059";if(segments.includes(".github"))return".github/ \u914D\u4E0B\u306F CI \u304C\u5B9F\u884C\u3059\u308B\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059";if(segments.includes(".claude"))return".claude/ \u914D\u4E0B\u306F\u30D5\u30C3\u30AF\u5B9A\u7FA9\u3092\u542B\
14
15
  \u3080\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059";if(segments.includes(".husky")||segments.includes(".githooks")){return"git hook \u306E\u30C7\u30A3\u30EC\u30AF\u30C8\u30EA\u306A\u306E\u3067\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059"}if(base==="package.json"||base==="makefile"||base===".envrc"||base===".mcp.json"){return`${base} \u306F\u5F8C\u7D9A\u306E\u5B9F\u884C\u306B\u5F71\u97FF\u3059\u308B\u305F\u3081\u3001\u6BCE\u56DE\u78BA\u8A8D\u3057\u307E\u3059`}return null}function validateInput(schema,input){const errors=[];if(typeof input!=="object"||input===null||Array.isArray(input)){return{ok:false,errors:["input must be a JSON object"],value:{}}}const value={...input};const props=schema.properties??{};for(const key of schema.required??[]){if(value[key]===void 0||value[key]===null)errors.push(`missing required property: ${key}`)}if(schema.additionalProperties===false){for(const key of Object.keys(value)){if(!(key in props))errors.push(`unknown property: ${key}`)}}
15
16
  for(const[key,sub]of Object.entries(props)){if(value[key]===void 0){if(sub.default!==void 0)value[key]=sub.default;continue}checkValue(`${key}`,sub,value[key],errors)}return{ok:errors.length===0,errors,value}}function checkValue(path4,schema,value,errors){switch(schema.type){case"string":if(typeof value!=="string")errors.push(`${path4} must be a string`);break;case"boolean":if(typeof value!=="boolean")errors.push(`${path4} must be a boolean`);break;case"integer":if(typeof value!=="number"||!Number.
16
17
  isInteger(value))errors.push(`${path4} must be an integer`);break;case"number":if(typeof value!=="number"||!Number.isFinite(value))errors.push(`${path4} must be a number`);break;case"array":if(!Array.isArray(value)){errors.push(`${path4} must be an array`);break}if(schema.items){value.forEach((item,i)=>checkValue(`${path4}[${i}]`,schema.items,item,errors))}break;case"object":if(typeof value!=="object"||value===null||Array.isArray(value)){errors.push(`${path4} must be an object`)}break;default:break}
17
- if(schema.enum&&!schema.enum.some(v=>v===value)){errors.push(`${path4} must be one of: ${schema.enum.join(", ")}`)}if(typeof value==="number"){if(schema.minimum!==void 0&&value<schema.minimum)errors.push(`${path4} must be >= ${schema.minimum}`);if(schema.maximum!==void 0&&value>schema.maximum)errors.push(`${path4} must be <= ${schema.maximum}`)}}async function executeTool(tool,rawInput,deps){const validated=validateInput(tool.inputSchema,rawInput);if(!validated.ok){const content=`Invalid input for ${tool.name}:
18
- - ${validated.errors.join("\n- ")}`;deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:"error",bytes:Buffer.byteLength(content),mode:deps.mode.id,reasonCode:"invalid_input"});return{content,isError:true,summary:`${tool.name} \xB7 \u5165\u529B\u304C\u4E0D\u6B63`}}const input=validated.value;const recordDecision=(decision,reasonCode,reason)=>{deps.audit.record({event:"decision",tool:tool.name,risk:tool.risk,decision,reasonCode,reason,mode:deps.mode.id,rawInput:input})};const modePolicy=checkPermission(
19
- tool.name,deps.mode);const overlay=applyPermissionMode(modePolicy,tool.risk,deps.permissionMode);const policy=overlay.decision;if(policy==="deny"){recordDecision("deny",overlay.reason===null?"mode_policy":"permission_mode",overlay.reason??`mode=${deps.mode.id} \u306E\u65B9\u91DD`);return{content:overlay.reason===null?`permission denied: ${tool.name} is not available in ${deps.mode.id} mode.`:`permission denied: ${tool.name} is blocked by --permission-mode=${deps.permissionMode??""}.`,isError:true,
20
- denied:true,summary:overlay.reason===null?`${tool.name} \xB7 deny\uFF08${deps.mode.label}\u30E2\u30FC\u30C9\uFF09`:`${tool.name} \xB7 deny\uFF08--permission-mode=${deps.permissionMode??""}\uFF09`}}const preview=safePreview(tool,input);const noAlwaysReason=neverAutoAllowReason(tool.name,input)??autoApproveExemptReason(tool,input,deps.ctx.cwd);const needsAsk=policy==="ask"||noAlwaysReason!==null;if(needsAsk){const skip=noAlwaysReason===null&&deps.sessionAllow.has(tool.name);if(skip)recordDecision(
21
- "allow","session_allow","\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u306E\u300C\u4ECA\u5F8C\u805E\u304B\u306A\u3044\u300D");if(!skip){if(!deps.askPermission){recordDecision("deny",noAlwaysReason===null?"non_interactive":"guard",noAlwaysReason??"\u975E\u5BFE\u8A71\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u627F\u8A8D\u304C\u5FC5\u8981\uFF08deny-and-continue\uFF09");return{content:`permission denied: ${tool.name} requires approval, and this session is non-interactive. `+(noAlwaysReason===null?"":`Reason: ${noAlwaysReason}\
22
- `)+"Explain what you would run instead of running it.",isError:true,denied:true,summary:`${tool.name} \xB7 \u975E\u5BFE\u8A71\u306E\u305F\u3081\u62D2\u5426`}}let diff;try{diff=await tool.prepare?.(input,deps.ctx)??void 0}catch(err){diff=void 0;if(err instanceof PathDeniedError){recordDecision("deny","path_denied","\u4FDD\u8B77\u3055\u308C\u305F\u30D1\u30B9\uFF08paths.ts\uFF09");return{content:err.message,isError:true,denied:true,summary:`${tool.name} \xB7 deny\uFF08\u4FDD\u8B77\u3055\u308C\u305F\u30D1\u30B9\uFF09`}}}
23
- const answer=await deps.askPermission({tool,input,preview,...diff?{diff}:{},noAlwaysReason});if(answer==="no"){recordDecision("deny","user_declined","\u5229\u7528\u8005\u304C\u62D2\u5426");return{content:`permission denied: the user declined to run ${tool.name}.`,isError:true,denied:true,summary:`${tool.name} \xB7 \u5229\u7528\u8005\u304C\u62D2\u5426`}}if(answer==="always"&&noAlwaysReason===null)deps.sessionAllow.add(tool.name);recordDecision("allow","user_approved",answer==="always"?"\u5229\u7528\u8005\u304C\u627F\u8A8D\uFF08\u4ECA\u5F8C\u805E\
24
- \u304B\u306A\u3044\uFF09":"\u5229\u7528\u8005\u304C\u627F\u8A8D")}}else{recordDecision("allow",overlay.reason===null?"mode_policy":"permission_mode",overlay.reason??`mode=${deps.mode.id} \u306E\u65B9\u91DD`)}deps.onStart?.(tool,preview);try{const result=await tool.run(input,deps.ctx);deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:result.isError===true?"error":"ok",bytes:Buffer.byteLength(result.content),mode:deps.mode.id});return{summary:preview,...result}}catch(err){if(err instanceof
25
- PathDeniedError){deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:"denied",bytes:Buffer.byteLength(err.message),mode:deps.mode.id,reasonCode:"path_denied"});return{content:err.message,isError:true,denied:true,summary:`${tool.name} \xB7 deny\uFF08\u4FDD\u8B77\u3055\u308C\u305F\u30D1\u30B9\uFF09`}}const message=`${tool.name} failed: ${err.message}`;deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:"error",bytes:Buffer.byteLength(message),mode:deps.mode.
26
- id});return{content:message,isError:true,summary:`${tool.name} \xB7 \u30A8\u30E9\u30FC`}}}function safePreview(tool,input){try{return tool.preview(input)}catch{return tool.name}}function toWireTool(def){return{name:def.name,description:def.description,input_schema:def.inputSchema}}var DEFAULT_MAX_STEPS=24;function buildSystemPrompt(ctx){const tools=ctx.toolNames??[];const capability=tools.length===0?["- **\u30C4\u30FC\u30EB\u5B9F\u884C\u306F\u307E\u3060\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002** \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u66F8\u304D\u30FB\u30B3\u30DE\u30F3\u30C9\u5B9F\u884C\u30FBTWP API \u64CD\u4F5C\u30FBWeb \u691C\u7D22\u306F\u3044\u305A\u308C\u3082\u884C\u3048\u307E\u305B\u3093","- \u5B9F\u884C\u304C\u5FC5\u8981\u306A\u3053\u3068\u306F\u3001\u5229\u7528\u8005\u304C\u81EA\u5206\u3067\u5B9F\u884C\u3067\u304D\u308B\u30B3\u30DE\u30F3\u30C9\u3084\u624B\u9806\u3068\u3057\u3066\u63D0\u793A\u3057\u3066\u304F\u3060\u3055\u3044"]:
18
+ if(schema.enum&&!schema.enum.some(v=>v===value)){errors.push(`${path4} must be one of: ${schema.enum.join(", ")}`)}if(typeof value==="number"){if(schema.minimum!==void 0&&value<schema.minimum)errors.push(`${path4} must be >= ${schema.minimum}`);if(schema.maximum!==void 0&&value>schema.maximum)errors.push(`${path4} must be <= ${schema.maximum}`)}}async function executeTool(tool,rawInput,deps,callId){const validated=validateInput(tool.inputSchema,rawInput);if(!validated.ok){const content=`Invalid input for ${tool.name}:
19
+ - ${validated.errors.join("\n- ")}`;deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:"error",bytes:Buffer.byteLength(content),mode:deps.mode.id,reasonCode:"invalid_input",callId});return{content,isError:true,summary:`${tool.name} \xB7 \u5165\u529B\u304C\u4E0D\u6B63`}}const input=validated.value;const recordDecision=(decision,reasonCode,reason)=>{deps.audit.record({event:"decision",tool:tool.name,risk:tool.risk,decision,reasonCode,reason,mode:deps.mode.id,rawInput:input,callId})};
20
+ const modePolicy=checkPermission(tool.name,deps.mode);const overlay=applyPermissionMode(modePolicy,tool.risk,deps.permissionMode);const policy=overlay.decision;if(policy==="deny"){recordDecision("deny",overlay.reason===null?"mode_policy":"permission_mode",overlay.reason??`mode=${deps.mode.id} \u306E\u65B9\u91DD`);return{content:overlay.reason===null?`permission denied: ${tool.name} is not available in ${deps.mode.id} mode.`:`permission denied: ${tool.name} is blocked by --permission-mode=${deps.
21
+ permissionMode??""}.`,isError:true,denied:true,summary:overlay.reason===null?`${tool.name} \xB7 deny\uFF08${deps.mode.label}\u30E2\u30FC\u30C9\uFF09`:`${tool.name} \xB7 deny\uFF08--permission-mode=${deps.permissionMode??""}\uFF09`}}const preview=safePreview(tool,input);const noAlwaysReason=neverAutoAllowReason(tool,input)??autoApproveExemptReason(tool,input,deps.ctx.cwd);const needsAsk=policy==="ask"||noAlwaysReason!==null;if(needsAsk){const skip=noAlwaysReason===null&&deps.sessionAllow.has(tool.
22
+ name);if(skip)recordDecision("allow","session_allow","\u30BB\u30C3\u30B7\u30E7\u30F3\u5185\u306E\u300C\u4ECA\u5F8C\u805E\u304B\u306A\u3044\u300D");if(!skip){if(!deps.askPermission){recordDecision("deny",noAlwaysReason===null?"non_interactive":"guard",noAlwaysReason??"\u975E\u5BFE\u8A71\u30BB\u30C3\u30B7\u30E7\u30F3\u3067\u627F\u8A8D\u304C\u5FC5\u8981\uFF08deny-and-continue\uFF09");return{content:`permission denied: ${tool.name} requires approval, and this session is non-interactive. `+(noAlwaysReason===
23
+ null?"":`Reason: ${noAlwaysReason} `)+"Explain what you would run instead of running it.",isError:true,denied:true,summary:`${tool.name} \xB7 \u975E\u5BFE\u8A71\u306E\u305F\u3081\u62D2\u5426`}}let diff;try{diff=await tool.prepare?.(input,deps.ctx)??void 0}catch(err){diff=void 0;if(err instanceof PathDeniedError){recordDecision("deny","path_denied","\u4FDD\u8B77\u3055\u308C\u305F\u30D1\u30B9\uFF08paths.ts\uFF09");return{content:err.message,isError:true,denied:true,summary:`${tool.name} \xB7 deny\uFF08\u4FDD\u8B77\u3055\
24
+ \u308C\u305F\u30D1\u30B9\uFF09`}}}const answer=await deps.askPermission({tool,input,preview,...diff?{diff}:{},noAlwaysReason});if(answer==="no"){recordDecision("deny","user_declined","\u5229\u7528\u8005\u304C\u62D2\u5426");return{content:`permission denied: the user declined to run ${tool.name}.`,isError:true,denied:true,summary:`${tool.name} \xB7 \u5229\u7528\u8005\u304C\u62D2\u5426`}}if(answer==="always"&&noAlwaysReason===null)deps.sessionAllow.add(tool.name);recordDecision("allow","user_appro\
25
+ ved",answer==="always"?"\u5229\u7528\u8005\u304C\u627F\u8A8D\uFF08\u4ECA\u5F8C\u805E\u304B\u306A\u3044\uFF09":"\u5229\u7528\u8005\u304C\u627F\u8A8D")}}else{recordDecision("allow",overlay.reason===null?"mode_policy":"permission_mode",overlay.reason??`mode=${deps.mode.id} \u306E\u65B9\u91DD`)}deps.onStart?.(tool,preview);try{const result=await tool.run(input,deps.ctx);deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:result.isError===true?"error":"ok",bytes:Buffer.byteLength(
26
+ result.content),mode:deps.mode.id,callId});return{summary:preview,...result}}catch(err){if(err instanceof PathDeniedError){deps.audit.record({event:"result",tool:tool.name,risk:tool.risk,outcome:"denied",bytes:Buffer.byteLength(err.message),mode:deps.mode.id,reasonCode:"path_denied",callId});return{content:err.message,isError:true,denied:true,summary:`${tool.name} \xB7 deny\uFF08\u4FDD\u8B77\u3055\u308C\u305F\u30D1\u30B9\uFF09`}}const message=`${tool.name} failed: ${err.message}`;deps.audit.record(
27
+ {event:"result",tool:tool.name,risk:tool.risk,outcome:"error",bytes:Buffer.byteLength(message),mode:deps.mode.id,callId});return{content:message,isError:true,summary:`${tool.name} \xB7 \u30A8\u30E9\u30FC`}}}function safePreview(tool,input){try{return tool.preview(input)}catch{return tool.name}}function toWireTool(def){return{name:def.name,description:def.description,input_schema:def.inputSchema}}var DEFAULT_MAX_STEPS=24;function buildSystemPrompt(ctx){const tools=ctx.toolNames??[];const capability=tools.length===0?["- **\u30C4\u30FC\u30EB\u5B9F\u884C\u306F\u307E\u3060\u5229\u7528\u3067\u304D\u307E\u305B\u3093\u3002** \u30D5\u30A1\u30A4\u30EB\u306E\u8AAD\u307F\u66F8\u304D\u30FB\u30B3\u30DE\u30F3\u30C9\u5B9F\u884C\u30FBTWP API \u64CD\u4F5C\u30FBWeb \u691C\u7D22\u306F\u3044\u305A\u308C\u3082\u884C\u3048\u307E\u305B\u3093","- \u5B9F\u884C\u304C\u5FC5\u8981\u306A\u3053\u3068\u306F\u3001\u5229\u7528\u8005\u304C\u81EA\u5206\u3067\u5B9F\u884C\u3067\u304D\u308B\u30B3\u30DE\u30F3\u30C9\u3084\u624B\u9806\u3068\u3057\u3066\u63D0\u793A\u3057\u3066\u304F\u3060\u3055\u3044"]:
27
28
  [`- \u4F7F\u3048\u308B\u30C4\u30FC\u30EB: ${tools.join(" / ")}`,"- **\u63A8\u6E2C\u3067\u7B54\u3048\u305A\u3001\u307E\u305A\u30C4\u30FC\u30EB\u3067\u78BA\u304B\u3081\u3066\u304F\u3060\u3055\u3044\u3002** \u30D5\u30A1\u30A4\u30EB\u306E\u5185\u5BB9\u30FB\u30B3\u30DE\u30F3\u30C9\u306E\u7D50\u679C\u30FB\u73FE\u5728\u306E\u72B6\u614B\u306F\u3059\u3079\u3066\u5B9F\u969B\u306B\u8AAD\u3093\u3067\u304B\u3089\u7B54\u3048\u307E\u3059","- \u4E00\u5EA6\u306B1\u3064\u305A\u3064\u78BA\u304B\u3081\u3001\u7D50\u679C\u3092\u898B\u3066\u304B\u3089\u6B21\u3092\u6C7A\u3081\u3066\u304F\u3060\u3055\u3044",
28
29
  "- \u30C4\u30FC\u30EB\u304C\u62D2\u5426\u3055\u308C\u305F\uFF08permission denied\uFF09\u3068\u304D\u306F\u3001\u540C\u3058\u547C\u3073\u51FA\u3057\u3092\u7E70\u308A\u8FD4\u3055\u305A\u3001\u4F55\u3092\u3057\u305F\u3044\u306E\u304B\u3092\u5229\u7528\u8005\u306B\u8AAC\u660E\u3057\u3066\u304F\u3060\u3055\u3044"];return[`\u3042\u306A\u305F\u306F TWP\uFF08Tocca Working Platform\uFF09\u306E CLI\u300Ctwp\u300D${ctx.cliVersion} \u306E\u4E2D\u3067\u52D5\u304F\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u3067\u3059\u3002`,
29
30
  "\u51FA\u529B\u306F\u7AEF\u672B\u306B\u8868\u793A\u3055\u308C\u307E\u3059\u3002\u65E5\u672C\u8A9E\u3067\u3001\u7D50\u8AD6\u3092\u5148\u306B\u3001\u7C21\u6F54\u306B\u7B54\u3048\u3066\u304F\u3060\u3055\u3044\u3002","","## \u3044\u307E\u3067\u304D\u308B\u3053\u3068\u30FB\u3067\u304D\u306A\u3044\u3053\u3068","",...capability,"- \u898B\u3066\u3044\u306A\u3044\u30D5\u30A1\u30A4\u30EB\u306E\u5185\u5BB9\u3084\u5B9F\u884C\u3057\u3066\u3044\u306A\u3044\u30B3\u30DE\u30F3\u30C9\u306E\u7D50\u679C\u3092\u3001\u898B\u305F\u30FB\u5B9F\u884C\u3057\u305F\u304B\u306E\u3088\u3046\u306B\u66F8\u304B\u306A\u3044\u3067\u304F\u3060\u3055\u3044",
@@ -32,28 +33,29 @@ tools??[];const wire=tools.map(toWireTool);context.addUser(request.input);let dr
32
33
  completeTurn("");err.usage=totals;throw err}add(totals,outcome.usage);context.applyUsage(outcome.usage);lastText=outcome.text;if(outcome.aborted||outcome.upstreamError!==null||outcome.toolUses.length===0){const kept=context.completeTurn(outcome.text);return{text:outcome.text,usage:totals,aborted:outcome.aborted,upstreamError:outcome.upstreamError,stopReason:outcome.stopReason,droppedMessages,emptyResponse:!kept,toolCalls,maxStepsReached:false}}const results=await runToolUses(outcome.toolUses,tools,
33
34
  request);toolCalls+=results.length;context.addToolExchange(outcome.text,outcome.toolUses,results);if(request.signal?.aborted===true){return{text:outcome.text,usage:totals,aborted:true,upstreamError:null,stopReason:outcome.stopReason,droppedMessages,emptyResponse:false,toolCalls,maxStepsReached:false}}droppedMessages+=context.trimToFit(maxTokens)}return{text:lastText,usage:totals,aborted:false,upstreamError:null,stopReason:"max_steps",droppedMessages,emptyResponse:false,toolCalls,maxStepsReached:true}}
34
35
  async function runToolUses(toolUses,tools,request){const results=[];for(const call of toolUses){request.onToolUse?.({name:call.name,input:call.input});const result=await runOne(call,tools,request);request.onToolResult?.({name:call.name,input:call.input},result);results.push({type:"tool_result",tool_use_id:call.id,content:result.content===""?"(no output)":result.content,...result.isError===true?{is_error:true}:{}})}return results}async function runOne(call,tools,request){const auditUnexecuted=(reasonCode,reason)=>{
35
- if(!request.execute)return;request.execute.audit.record({event:"decision",tool:call.name,risk:"unknown",decision:"deny",reasonCode,reason,mode:request.execute.mode.id,rawInput:typeof call.input==="object"&&call.input!==null?call.input:{}})};if(request.signal?.aborted===true){auditUnexecuted("interrupted","\u5229\u7528\u8005\u304C\u4E2D\u65AD\u3057\u305F\u305F\u3081\u5B9F\u884C\u3057\u306A\u3044");return{content:"interrupted by the user before this tool ran",isError:true,summary:`${call.name} \xB7 \u4E2D\
36
- \u65AD`}}const tool=tools.find(t=>t.name===call.name);if(!tool){auditUnexecuted("unknown_tool","\u30E2\u30C7\u30EB\u306B\u6E21\u3057\u3066\u3044\u306A\u3044\u30C4\u30FC\u30EB\u540D\uFF08\u5E38\u99D0\u30BB\u30C3\u30C8\u306B\u7121\u3044\uFF09");return{content:`Unknown tool: ${call.name}. Available tools: ${tools.map(t=>t.name).join(", ")||"(none)"}`,isError:true,summary:`${call.name} \xB7 \u672A\u77E5\u306E\u30C4\u30FC\u30EB`}}if(!request.execute){return{content:`Tool ${call.name} cannot run: this\
37
- session has no tool execution context.`,isError:true,summary:`${call.name} \xB7 \u5B9F\u884C\u74B0\u5883\u306A\u3057`}}return executeTool(tool,call.input,{...request.execute,ctx:{...request.execute.ctx,...request.signal?{signal:request.signal}:{}}})}function add(target,source){target.inputTokens+=source.inputTokens;target.cacheReadTokens+=source.cacheReadTokens;target.cacheWriteTokens+=source.cacheWriteTokens;target.outputTokens+=source.outputTokens}import fs from"fs";import path from"path";import crypto from"crypto";var MAX_LINE_BYTES=4096;var MAX_FILE_BYTES=5*1024*1024;var MAX_AGE_DAYS=14;var MAX_FILES=200;var PRUNE_GRACE_MS=6*60*60*1e3;var MAX_STRING_BYTES=200;var MAX_TOOL_NAME_BYTES=120;var REDACT_KEYS=new Set(["content","contents","new_string","old_string","body","text","patch","diff","data","stdin","password","passwd","pwd","secret","secret_key","token","access_token","refresh_token","id_token","session_token","api_key","apikey","api-key","key","private_key","client_secret","authorization","auth","cook\
38
- ie","headers","signature","credential","credentials"]);var SECRET_PATTERNS=[/(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi,/\b(?:sk|pk|rk)-[A-Za-z0-9_-]{8,}/g,/\bgh[pousr]_[A-Za-z0-9]{8,}/g,/\bAKIA[0-9A-Z]{12,}/g,/-----BEGIN[^-]*PRIVATE KEY-----/g,/\b(?:password|passwd|pwd|token|secret|api[_-]?key)\s*[:=]\s*[^\s;&|<>'"`]+/gi,/\b[A-Fa-f0-9]{40,}\b/g,/\b[A-Za-z0-9+_-]{40,}={0,2}\b/g];function scrubSecrets(value){let out=value;for(const re of SECRET_PATTERNS)out=out.replace(re,"[REDACTED]");return out}
39
- var TOKEN_RE=/[^\s=:,;&|<>'"`()[\]{}/\\]+/g;var SEPARATOR_RE=/[\s=:,;&|<>'"`()[\]{}/\\]/;var SecretRegistry=class _SecretRegistry{static MAX_HASHES=4096;static MAX_PHRASES=64;static MIN_LENGTH=12;static MAX_LENGTH=512;hashes=new Set;phrases=[];saturated=false;learn(value,depth=0){if(value!==null&&typeof value==="object"&&depth<8){const children=Array.isArray(value)?value:Object.values(value);for(const child of children)this.learn(child,depth+1);return}const text=typeof value==="string"?value:safeStringify(
40
- value);if(text==="")return;for(const line of text.split(/\r?\n/)){const trimmed=line.trim();if(trimmed==="")continue;const eq=trimmed.indexOf("=");if(eq>0)this.add(unquote(trimmed.slice(eq+1).trim()),true);if(!/\s/.test(trimmed))this.add(unquote(trimmed),false)}}add(candidate,fromEnv){if(candidate.length<_SecretRegistry.MIN_LENGTH)return;if(candidate.length>_SecretRegistry.MAX_LENGTH)return;const hasSeparator=SEPARATOR_RE.test(candidate);if(hasSeparator&&!fromEnv)return;if(hasSeparator){if(this.
41
- phrases.includes(candidate))return;if(this.phrases.length>=_SecretRegistry.MAX_PHRASES){this.saturated=true;return}this.phrases.push(candidate);return}const hash=digest(candidate);if(this.hashes.has(hash))return;if(this.hashes.size>=_SecretRegistry.MAX_HASHES){this.saturated=true;return}this.hashes.add(hash)}scrub(text){let out=text;for(const phrase of this.phrases){if(out.includes(phrase))out=out.split(phrase).join("[REDACTED]")}if(this.hashes.size===0)return out;return out.replace(TOKEN_RE,token=>token.
42
- length>=_SecretRegistry.MIN_LENGTH&&this.hashes.has(digest(token))?"[REDACTED]":token)}};function digest(value){return crypto.createHash("sha256").update(value,"utf8").digest("hex").slice(0,24)}function unquote(value){const first=value[0];if((first==='"'||first==="'")&&value.endsWith(first)&&value.length>1)return value.slice(1,-1);return value}function safeStringify(value){try{return JSON.stringify(value)??""}catch{return""}}function nullAuditLogger(){return{path:null,sessionId:"",record:()=>void 0}}
43
- function createAuditLogger(ctx){const env=ctx.env??process.env;if(env.TWP_NO_AUDIT==="1")return nullAuditLogger();const sessionId=newSessionId();const file=path.join(twpHomeDir(env),"logs",`session-${sessionId}.jsonl`);let fd=null;let written=0;let stopped=false;const registry=new SecretRegistry;let reportedSaturation=false;const open=()=>{if(fd!==null)return true;if(stopped)return false;try{const dir=path.join(ensureTwpHome(env),"logs");const link=lstatOrNull(dir);if(link!==null&&link.isSymbolicLink()){
44
- stopped=true;return false}fs.mkdirSync(dir,{recursive:true,mode:448});if(process.platform!=="win32"){try{fs.chmodSync(dir,448)}catch{}}prune(dir);const handle=fs.openSync(file,"a",384);if(process.platform!=="win32"){try{fs.fchmodSync(handle,384)}catch{fs.closeSync(handle);try{fs.unlinkSync(file)}catch{}stopped=true;return false}}fd=handle;ctx.onOpen?.(file);return true}catch{stopped=true;return false}};const writeAll=(handle,text)=>{const buf=Buffer.from(text,"utf8");let offset=0;while(offset<buf.
45
- length){const n=fs.writeSync(handle,buf,offset,buf.length-offset);if(n<=0)throw new Error("writeSync made no progress");offset+=n}written+=buf.length};const writeLine=payload=>{if(stopped||!open()||fd===null)return;try{let line=`${JSON.stringify(payload)}
36
+ if(!request.execute)return;request.execute.audit.record({event:"decision",tool:call.name,risk:"unknown",decision:"deny",reasonCode,reason,mode:request.execute.mode.id,rawInput:typeof call.input==="object"&&call.input!==null?call.input:{},callId:call.id})};if(request.signal?.aborted===true){auditUnexecuted("interrupted","\u5229\u7528\u8005\u304C\u4E2D\u65AD\u3057\u305F\u305F\u3081\u5B9F\u884C\u3057\u306A\u3044");return{content:"interrupted by the user before this tool ran",isError:true,summary:`${call.
37
+ name} \xB7 \u4E2D\u65AD`}}const tool=tools.find(t=>t.name===call.name);if(!tool){auditUnexecuted("unknown_tool","\u30E2\u30C7\u30EB\u306B\u6E21\u3057\u3066\u3044\u306A\u3044\u30C4\u30FC\u30EB\u540D\uFF08\u5E38\u99D0\u30BB\u30C3\u30C8\u306B\u7121\u3044\uFF09");return{content:`Unknown tool: ${call.name}. Available tools: ${tools.map(t=>t.name).join(", ")||"(none)"}`,isError:true,summary:`${call.name} \xB7 \u672A\u77E5\u306E\u30C4\u30FC\u30EB`}}if(!request.execute){return{content:`Tool ${call.name}\
38
+ cannot run: this session has no tool execution context.`,isError:true,summary:`${call.name} \xB7 \u5B9F\u884C\u74B0\u5883\u306A\u3057`}}return executeTool(tool,call.input,{...request.execute,ctx:{...request.execute.ctx,...request.signal?{signal:request.signal}:{}}},call.id)}function add(target,source){target.inputTokens+=source.inputTokens;target.cacheReadTokens+=source.cacheReadTokens;target.cacheWriteTokens+=source.cacheWriteTokens;target.outputTokens+=source.outputTokens}import fs from"fs";import path from"path";import crypto from"crypto";var MAX_LINE_BYTES=4096;var MAX_FILE_BYTES=5*1024*1024;var MAX_CALL_ID_BYTES=64;var MAX_AGE_DAYS=14;var MAX_FILES=200;var PRUNE_GRACE_MS=6*60*60*1e3;var MAX_STRING_BYTES=200;var MAX_TOOL_NAME_BYTES=120;var REDACT_KEYS=new Set(["content","contents","new_string","old_string","body","text","patch","diff","data","stdin","password","passwd","pwd","secret","secret_key","token","access_token","refresh_token","id_token","session_token","api_key","apikey","api-key","key","private_key","client_secret","au\
39
+ thorization","auth","cookie","headers","signature","credential","credentials"]);var SECRET_PATTERNS=[/(?:bearer|basic)\s+[A-Za-z0-9._~+/=-]{8,}/gi,/\b(?:sk|pk|rk)-[A-Za-z0-9_-]{8,}/g,/\bgh[pousr]_[A-Za-z0-9]{8,}/g,/\bAKIA[0-9A-Z]{12,}/g,/-----BEGIN[^-]*PRIVATE KEY-----/g,/\b(?:password|passwd|pwd|token|secret|api[_-]?key)\s*[:=]\s*[^\s;&|<>'"`]+/gi,/\b[A-Fa-f0-9]{40,}\b/g,/\b[A-Za-z0-9+_-]{40,}={0,2}\b/g];function scrubSecrets(value){let out=value;for(const re of SECRET_PATTERNS)out=out.replace(
40
+ re,"[REDACTED]");return out}var TOKEN_RE=/[^\s=:,;&|<>'"`()[\]{}/\\]+/g;var SEPARATOR_RE=/[\s=:,;&|<>'"`()[\]{}/\\]/;var SecretRegistry=class _SecretRegistry{static MAX_HASHES=4096;static MAX_PHRASES=64;static MIN_LENGTH=12;static MAX_LENGTH=512;hashes=new Set;phrases=[];saturated=false;learn(value,depth=0){if(value!==null&&typeof value==="object"&&depth<8){const children=Array.isArray(value)?value:Object.values(value);for(const child of children)this.learn(child,depth+1);return}const text=typeof value===
41
+ "string"?value:safeStringify(value);if(text==="")return;for(const line of text.split(/\r?\n/)){const trimmed=line.trim();if(trimmed==="")continue;const eq=trimmed.indexOf("=");if(eq>0)this.add(unquote(trimmed.slice(eq+1).trim()),true);if(!/\s/.test(trimmed))this.add(unquote(trimmed),false)}}add(candidate,fromEnv){if(candidate.length<_SecretRegistry.MIN_LENGTH)return;if(candidate.length>_SecretRegistry.MAX_LENGTH)return;const hasSeparator=SEPARATOR_RE.test(candidate);if(hasSeparator&&!fromEnv)return;
42
+ if(hasSeparator){if(this.phrases.includes(candidate))return;if(this.phrases.length>=_SecretRegistry.MAX_PHRASES){this.saturated=true;return}this.phrases.push(candidate);return}const hash=digest(candidate);if(this.hashes.has(hash))return;if(this.hashes.size>=_SecretRegistry.MAX_HASHES){this.saturated=true;return}this.hashes.add(hash)}scrub(text){let out=text;for(const phrase of this.phrases){if(out.includes(phrase))out=out.split(phrase).join("[REDACTED]")}if(this.hashes.size===0)return out;return out.
43
+ replace(TOKEN_RE,token=>token.length>=_SecretRegistry.MIN_LENGTH&&this.hashes.has(digest(token))?"[REDACTED]":token)}};function digest(value){return crypto.createHash("sha256").update(value,"utf8").digest("hex").slice(0,24)}function unquote(value){const first=value[0];if((first==='"'||first==="'")&&value.endsWith(first)&&value.length>1)return value.slice(1,-1);return value}function safeStringify(value){try{return JSON.stringify(value)??""}catch{return""}}function sanitizeEvent(event,registry){if(event.
44
+ event!=="decision")return event;const{rawInput,...rest}=event;return{...rest,input:sanitizeInput(rawInput,registry)}}function describeAuditLog(logger){if(logger.path===null)return"\u7121\u52B9\uFF08TWP_NO_AUDIT=1\uFF09";if(!logger.opened)return`${logger.path}\uFF08\u672A\u4F5C\u6210\u30FB\u6700\u521D\u306E\u30C4\u30FC\u30EB\u5B9F\u884C\u3067\u4F5C\u308B\uFF09`;return logger.path}function nullAuditLogger(){return{path:null,sessionId:"",opened:false,record:()=>void 0,close:()=>void 0}}function createAuditLogger(ctx){
45
+ const env=ctx.env??process.env;if(env.TWP_NO_AUDIT==="1")return nullAuditLogger();const sessionId=newSessionId();const file=path.join(twpHomeDir(env),"logs",`session-${sessionId}.jsonl`);let fd=null;let everOpened=false;let written=0;let stopped=false;const registry=new SecretRegistry;let reportedSaturation=false;const open=()=>{if(fd!==null)return true;if(stopped)return false;try{const dir=path.join(ensureTwpHome(env),"logs");const link=lstatOrNull(dir);if(link!==null&&link.isSymbolicLink()){stopped=
46
+ true;return false}fs.mkdirSync(dir,{recursive:true,mode:448});if(process.platform!=="win32"){try{fs.chmodSync(dir,448)}catch{}}prune(dir);const handle=fs.openSync(file,"a",384);if(process.platform!=="win32"){try{fs.fchmodSync(handle,384)}catch{fs.closeSync(handle);try{fs.unlinkSync(file)}catch{}stopped=true;return false}}fd=handle;everOpened=true;ctx.onOpen?.(file);return true}catch{stopped=true;return false}};const writeAll=(handle,text)=>{const buf=Buffer.from(text,"utf8");let offset=0;while(offset<
47
+ buf.length){const n=fs.writeSync(handle,buf,offset,buf.length-offset);if(n<=0)throw new Error("writeSync made no progress");offset+=n}written+=buf.length};const writeLine=payload=>{if(stopped||!open()||fd===null)return;try{let line=`${JSON.stringify(payload)}
46
48
  `;if(Buffer.byteLength(line)>MAX_LINE_BYTES&&"input"in payload){const rest={...payload};delete rest["input"];line=`${JSON.stringify({...rest,_dropped:"line_too_long"})}
47
49
  `}if(Buffer.byteLength(line)>MAX_LINE_BYTES){line=`${JSON.stringify({ts:now(),v:1,session:sessionId,event:payload["event"],tool:clamp(String(payload["tool"]??""),40),_dropped:"line_too_long"})}
48
50
  `}if(written+Buffer.byteLength(line)>MAX_FILE_BYTES){stopped=true;writeAll(fd,`${JSON.stringify({ts:now(),v:1,session:sessionId,event:"truncated"})}
49
51
  `);return}writeAll(fd,line)}catch{stopped=true}};const common={v:1,session:sessionId,permission_mode:ctx.permissionMode??null};let wroteHeader=false;const header=()=>{if(wroteHeader)return;writeLine({ts:now(),...common,event:"session_start",mode:ctx.mode,model:ctx.model,cwd:ctx.cwd,cli_version:ctx.cliVersion,interactive:ctx.interactive,pid:process.pid});if(fd!==null&&!stopped)wroteHeader=true};const reportSaturation=()=>{if(!registry.saturated||reportedSaturation)return;reportedSaturation=true;writeLine(
50
- {ts:now(),...common,event:"registry_saturated"})};return{path:file,sessionId,record(event){header();const tool=clamp(event.tool,MAX_TOOL_NAME_BYTES);if(event.event==="decision"){const input=sanitizeInput(event.rawInput,registry);writeLine({ts:now(),...common,event:"decision",tool,risk:event.risk,decision:event.decision,reason_code:event.reasonCode,reason:event.reason,mode:event.mode,input});reportSaturation();return}writeLine({ts:now(),...common,event:"result",tool,risk:event.risk,outcome:event.
51
- outcome,bytes:event.bytes,mode:event.mode,...event.reasonCode!==void 0?{reason_code:event.reasonCode}:{}})}}}function now(){return new Date().toISOString()}function lstatOrNull(target){try{return fs.lstatSync(target)}catch{return null}}function clamp(value,maxBytes){const total=Buffer.byteLength(value);if(total<=maxBytes)return value;let out=value;while(out.length>0&&Buffer.byteLength(out)>maxBytes)out=out.slice(0,-1);return`${out}\u2026(+${total-Buffer.byteLength(out)})`}function sanitizeInput(rawInput,registry){
52
- learnSecrets(rawInput,0,registry);return sanitizeObject(rawInput,0,registry)}function learnSecrets(value,depth,registry){if(depth>8||value===null||typeof value!=="object")return;if(Array.isArray(value)){for(const item of value)learnSecrets(item,depth+1,registry);return}for(const[key,child]of Object.entries(value)){if(REDACT_KEYS.has(key.toLowerCase()))registry.learn(child);else learnSecrets(child,depth+1,registry)}}function sanitizeObject(obj,depth,registry){const out={};let keys=0;for(const[key,
53
- value]of Object.entries(obj)){if(keys>=20){out["_twp_more_keys"]=true;break}keys++;if(REDACT_KEYS.has(key.toLowerCase())){out[key]=`<redacted ${byteLengthOf(value)} bytes>`;continue}out[key]=sanitizeValue(value,depth+1,registry)}return out}function sanitizeValue(value,depth,registry){if(value===null||typeof value==="number"||typeof value==="boolean")return value;if(typeof value==="string"){return clamp(registry.scrub(scrubSecrets(value)),MAX_STRING_BYTES)}if(depth>=3)return"<depth>";if(Array.isArray(
54
- value)){const head=value.slice(0,10).map(v=>sanitizeValue(v,depth+1,registry));return value.length>10?[...head,`\u2026(+${value.length-10})`]:head}if(typeof value==="object")return sanitizeObject(value,depth,registry);return`<${typeof value}>`}function byteLengthOf(value){if(typeof value==="string")return Buffer.byteLength(value);try{return Buffer.byteLength(JSON.stringify(value)??"")}catch{return 0}}function prune(dir,nowMs=Date.now()){let entries;try{entries=fs.readdirSync(dir).filter(n=>/^session-.*\.jsonl$/.
55
- test(n))}catch{return}const stats=[];for(const name of entries){try{stats.push({name,mtime:fs.statSync(path.join(dir,name)).mtimeMs})}catch{}}stats.sort((a,b)=>b.mtime-a.mtime);const cutoff=nowMs-MAX_AGE_DAYS*24*60*60*1e3;stats.forEach((entry,index)=>{const overCount=index>=MAX_FILES-1;const tooOld=entry.mtime<cutoff;if(!tooOld&&!overCount)return;if(!tooOld&&nowMs-entry.mtime<PRUNE_GRACE_MS)return;try{fs.unlinkSync(path.join(dir,entry.name))}catch{}})}var CROCKFORD="0123456789ABCDEFGHJKMNPQRSTVW\
56
- XYZ";function newSessionId(nowMs=Date.now()){let time="";let remaining=nowMs;for(let i=0;i<10;i++){time=`${CROCKFORD[remaining%32]??"0"}${time}`;remaining=Math.floor(remaining/32)}const bytes=crypto.randomBytes(16);let rand="";for(const byte of bytes)rand+=CROCKFORD[byte%32]??"0";return`${time}${rand}`}import{readFileSync}from"fs";import{dirname as dirname2,join,resolve as resolve2,sep as sep3}from"path";function currentBranch(cwd=process.cwd()){let dir=cwd;for(;;){const gitPath=join(dir,".git");const head=readHead(gitPath);if(head!==null)return head;const parent=dirname2(dir);if(parent===dir)return null;dir=parent}}function readHead(gitPath){let headFile=join(gitPath,"HEAD");try{const stat2=readFileSync(gitPath,"utf8");const m=/^gitdir:\s*(.+)$/m.exec(stat2);if(m?.[1])headFile=join(resolve2(dirname2(
52
+ {ts:now(),...common,event:"registry_saturated"})};return{path:file,sessionId,get opened(){return everOpened},record(event){header();const safe=sanitizeEvent(event,registry);const tool=clamp(safe.tool,MAX_TOOL_NAME_BYTES);const callId=safe.callId===void 0?{}:{call_id:clamp(safe.callId,MAX_CALL_ID_BYTES)};if(safe.event==="decision"){writeLine({ts:now(),...common,event:"decision",tool,...callId,risk:safe.risk,decision:safe.decision,reason_code:safe.reasonCode,reason:safe.reason,mode:safe.mode,input:safe.
53
+ input});reportSaturation();return}writeLine({ts:now(),...common,event:"result",tool,...callId,risk:safe.risk,outcome:safe.outcome,bytes:safe.bytes,mode:safe.mode,...safe.reasonCode!==void 0?{reason_code:safe.reasonCode}:{}})},close(){stopped=true;if(fd===null)return;try{fs.closeSync(fd)}catch{}fd=null}}}function now(){return new Date().toISOString()}function lstatOrNull(target){try{return fs.lstatSync(target)}catch{return null}}function clamp(value,maxBytes){const total=Buffer.byteLength(value);
54
+ if(total<=maxBytes)return value;let out=value;while(out.length>0&&Buffer.byteLength(out)>maxBytes)out=out.slice(0,-1);return`${out}\u2026(+${total-Buffer.byteLength(out)})`}function sanitizeInput(rawInput,registry){learnSecrets(rawInput,0,registry);return sanitizeObject(rawInput,0,registry)}function learnSecrets(value,depth,registry){if(depth>8||value===null||typeof value!=="object")return;if(Array.isArray(value)){for(const item of value)learnSecrets(item,depth+1,registry);return}for(const[key,child]of Object.
55
+ entries(value)){if(REDACT_KEYS.has(key.toLowerCase()))registry.learn(child);else learnSecrets(child,depth+1,registry)}}function sanitizeObject(obj,depth,registry){const out={};let keys=0;for(const[key,value]of Object.entries(obj)){if(keys>=20){out["_twp_more_keys"]=true;break}keys++;if(REDACT_KEYS.has(key.toLowerCase())){out[key]=`<redacted ${byteLengthOf(value)} bytes>`;continue}out[key]=sanitizeValue(value,depth+1,registry)}return out}function sanitizeValue(value,depth,registry){if(value===null||
56
+ typeof value==="number"||typeof value==="boolean")return value;if(typeof value==="string"){return clamp(registry.scrub(scrubSecrets(value)),MAX_STRING_BYTES)}if(depth>=3)return"<depth>";if(Array.isArray(value)){const head=value.slice(0,10).map(v=>sanitizeValue(v,depth+1,registry));return value.length>10?[...head,`\u2026(+${value.length-10})`]:head}if(typeof value==="object")return sanitizeObject(value,depth,registry);return`<${typeof value}>`}function byteLengthOf(value){if(typeof value==="strin\
57
+ g")return Buffer.byteLength(value);try{return Buffer.byteLength(JSON.stringify(value)??"")}catch{return 0}}function prune(dir,nowMs=Date.now()){let entries;try{entries=fs.readdirSync(dir).filter(n=>/^session-.*\.jsonl$/.test(n))}catch{return}const stats=[];for(const name of entries){try{stats.push({name,mtime:fs.statSync(path.join(dir,name)).mtimeMs})}catch{}}stats.sort((a,b)=>b.mtime-a.mtime);const cutoff=nowMs-MAX_AGE_DAYS*24*60*60*1e3;stats.forEach((entry,index)=>{const overCount=index>=MAX_FILES-
58
+ 1;const tooOld=entry.mtime<cutoff;if(!tooOld&&!overCount)return;if(!tooOld&&nowMs-entry.mtime<PRUNE_GRACE_MS)return;try{fs.unlinkSync(path.join(dir,entry.name))}catch{}})}var CROCKFORD="0123456789ABCDEFGHJKMNPQRSTVWXYZ";function newSessionId(nowMs=Date.now()){let time="";let remaining=nowMs;for(let i=0;i<10;i++){time=`${CROCKFORD[remaining%32]??"0"}${time}`;remaining=Math.floor(remaining/32)}const bytes=crypto.randomBytes(16);let rand="";for(const byte of bytes)rand+=CROCKFORD[byte%32]??"0";return`${time}${rand}`}import{readFileSync}from"fs";import{dirname as dirname2,join,resolve as resolve2,sep as sep3}from"path";function currentBranch(cwd=process.cwd()){let dir=cwd;for(;;){const gitPath=join(dir,".git");const head=readHead(gitPath);if(head!==null)return head;const parent=dirname2(dir);if(parent===dir)return null;dir=parent}}function readHead(gitPath){let headFile=join(gitPath,"HEAD");try{const stat2=readFileSync(gitPath,"utf8");const m=/^gitdir:\s*(.+)$/m.exec(stat2);if(m?.[1])headFile=join(resolve2(dirname2(
57
59
  gitPath),m[1].trim()),"HEAD")}catch{}try{const head=readFileSync(headFile,"utf8").trim();const ref=/^ref:\s*refs\/heads\/(.+)$/.exec(head);if(ref?.[1])return ref[1];return head.slice(0,7)}catch{return null}}function displayCwd(cwd=process.cwd(),home=process.env["HOME"]??process.env["USERPROFILE"]??""){if(!home)return cwd;const stripped=home.replace(new RegExp(`${escapeSep()}+$`),"");if(stripped==="")return cwd;const normalize=p=>process.platform==="win32"?p.toLowerCase():p;const h=normalize(stripped);
58
60
  const c=normalize(cwd);if(c===h)return"~";if(c.startsWith(h+sep3))return`~${cwd.slice(stripped.length)}`;return cwd}function escapeSep(){return sep3==="\\"?"\\\\":sep3}import{spawn}from"child_process";function keepTailBytes(buf,maxBytes){if(buf.length<=maxBytes)return{text:buf.toString("utf8"),droppedBytes:0};const start=buf.length-maxBytes;let cut=start;while(cut<buf.length&&(buf[cut]&192)===128)cut++;return{text:buf.subarray(cut).toString("utf8"),droppedBytes:cut}}function keepHeadBytes(text,maxBytes){const buf=Buffer.from(text,"utf8");if(buf.length<=maxBytes)return{text,truncated:false};let cut=maxBytes;while(cut>0&&(buf[cut]&192)===128)cut--;return{text:buf.subarray(0,cut).toString("utf8"),
59
61
  truncated:true}}import{existsSync}from"fs";import path2 from"path";var GIT_BASH_CANDIDATES=["C:\\Program Files\\Git\\bin\\bash.exe","C:\\Program Files (x86)\\Git\\bin\\bash.exe","C:\\Program Files\\Git\\usr\\bin\\bash.exe"];function system32Path(env,...rest){return system32(env,...rest)??path2.win32.join("C:\\Windows\\System32",...rest)}function defaultProbe(filePath){try{return existsSync(filePath)}catch{return false}}function selectShell(platform=process.platform,probe=defaultProbe,env=process.env){if(platform!=="win32"){return{toolName:"bash",command:"/bin/b\
@@ -62,11 +64,11 @@ const pwsh=pwshPath(probe,env);if(pwsh!==null){return{toolName:"shell",command:p
62
64
  if(probe(sys.powershell)){return{toolName:"shell",command:sys.powershell,args:["-NoProfile","-NonInteractive","-Command"],kind:"powershell",note:"\u3053\u306E\u74B0\u5883\u306B bash \u304C\u306A\u3044\u305F\u3081 Windows PowerShell 5.1 \u3067\u5B9F\u884C\u3057\u307E\u3059\u3002**bash \u69CB\u6587\u306F\u4F7F\u3048\u307E\u305B\u3093**\uFF08`&&` \u306F\u4F7F\u3048\u305A `;` \u306B\u306A\u308A\u307E\u3059\uFF09"}}return{toolName:"shell",command:sys.cmd,args:["/d","/s","/c"],kind:"cmd",note:"\u3053\u306E\u74B0\u5883\u306B b\
63
65
  ash \u3082 PowerShell \u3082\u306A\u3044\u305F\u3081 cmd.exe \u3067\u5B9F\u884C\u3057\u307E\u3059\u3002**bash \u69CB\u6587\u306F\u4F7F\u3048\u307E\u305B\u3093**\uFF08cmd \u306E\u30D0\u30C3\u30C1\u69CB\u6587\u3067\u66F8\u3044\u3066\u304F\u3060\u3055\u3044\uFF09"}}function trustedBase(base){return typeof base==="string"&&isWindowsDriveAbsolute(base)}function gitBashCandidates(env){const fromEnv=[];for(const key of["ProgramFiles","ProgramFiles(x86)","ProgramW6432"]){const base=env[key];if(trustedBase(
64
66
  base))fromEnv.push(`${base}\\Git\\bin\\bash.exe`,`${base}\\Git\\usr\\bin\\bash.exe`)}return[...fromEnv,...GIT_BASH_CANDIDATES]}function pwshPath(probe,env){const bases=[env["ProgramFiles"],env["ProgramW6432"],"C:\\Program Files"].filter(trustedBase);for(const base of bases){for(const major of["7","6"]){const candidate=`${base}\\PowerShell\\${major}\\pwsh.exe`;if(probe(candidate))return candidate}}return null}var DEFAULT_TIMEOUT_MS=12e4;var MAX_TIMEOUT_MS=6e5;var MAX_OUTPUT_BYTES=1e5;function createBashTool(choice=selectShell()){const base=choice.toolName==="bash"?"Run a shell command with bash. Prefer specific tools (read_file / glob / grep) when they fit \u2014 they are cheaper and safer.":"Run a shell command. NOTE: bash is not available in this environment.";return{name:choice.toolName,domain:"local",risk:"exec",description:choice.note===null?base:`${base}
65
- ${choice.note}`,inputSchema:{type:"object",additionalProperties:false,properties:{command:{type:"string",description:"The command line to run"},timeout_ms:{type:"integer",description:`Timeout in milliseconds (default ${DEFAULT_TIMEOUT_MS}, max ${MAX_TIMEOUT_MS})`,minimum:1e3,maximum:MAX_TIMEOUT_MS}},required:["command"]},preview(input){const command=typeof input["command"]==="string"?input["command"]:"";const line=command.split("\n")[0]??"";return`${choice.toolName} \xB7 ${line.slice(0,80)}${line.
66
- length>80||command.includes("\n")?"\u2026":""}`},async run(input,ctx){const command=String(input["command"]);const timeout=clampTimeout(input["timeout_ms"]);return runCommand(choice,command,timeout,ctx.cwd,ctx.signal,ctx.env)}}}function clampTimeout(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_TIMEOUT_MS;return Math.min(MAX_TIMEOUT_MS,Math.max(1e3,Math.floor(value)))}function runCommand(choice,command,timeoutMs,cwd,signal,env=process.env){return new Promise(resolve5=>{
67
- const child=spawn(choice.command,[...choice.args,command],{cwd,env,shell:false,detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]});const chunks=[];let bytes=0;const collect=buf=>{chunks.push(buf);bytes+=buf.length;while(bytes-(chunks[0]?.length??0)>MAX_OUTPUT_BYTES*2&&chunks.length>1){const dropped=chunks.shift();if(!dropped)break;bytes-=dropped.length}};child.stdout.on("data",collect);child.stderr.on("data",collect);let outcome="ok";const kill=()=>{if(child.killed||child.exitCode!==
68
- null)return;if(isForceOnly()){killProcessTree(child,"SIGKILL");return}killProcessTree(child,"SIGTERM");setTimeout(()=>killProcessTree(child,"SIGKILL"),2e3).unref()};const timer=setTimeout(()=>{outcome="timeout";kill()},timeoutMs);const onAbort=()=>{outcome="aborted";kill()};if(signal){if(signal.aborted)onAbort();else signal.addEventListener("abort",onAbort,{once:true})}const finish=(exitCode,spawnError)=>{clearTimeout(timer);signal?.removeEventListener("abort",onAbort);const raw=Buffer.concat(chunks);
69
- const kept=keepTailBytes(raw,MAX_OUTPUT_BYTES);const body=kept.text;const head=kept.droppedBytes>0?`[output truncated: dropped the first ${kept.droppedBytes} bytes, showing the last ${Buffer.byteLength(body,"utf8")}]
67
+ ${choice.note}`,inputSchema:{type:"object",additionalProperties:false,properties:{command:{type:"string",description:"The command line to run"},timeout_ms:{type:"integer",description:`Timeout in milliseconds (default ${DEFAULT_TIMEOUT_MS}, max ${MAX_TIMEOUT_MS})`,minimum:1e3,maximum:MAX_TIMEOUT_MS}},required:["command"]},execCommands(input){const command=typeof input["command"]==="string"?input["command"]:"";return{shell:[command]}},preview(input){const command=typeof input["command"]==="string"?
68
+ input["command"]:"";const line=command.split("\n")[0]??"";return`${choice.toolName} \xB7 ${line.slice(0,80)}${line.length>80||command.includes("\n")?"\u2026":""}`},async run(input,ctx){const command=String(input["command"]);const timeout=clampTimeout(input["timeout_ms"]);return runCommand(choice,command,timeout,ctx.cwd,ctx.signal,ctx.env)}}}function clampTimeout(value){if(typeof value!=="number"||!Number.isFinite(value))return DEFAULT_TIMEOUT_MS;return Math.min(MAX_TIMEOUT_MS,Math.max(1e3,Math.floor(
69
+ value)))}function runCommand(choice,command,timeoutMs,cwd,signal,env=process.env){return new Promise(resolve5=>{const child=spawn(choice.command,[...choice.args,command],{cwd,env,shell:false,detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]});const chunks=[];let bytes=0;const collect=buf=>{chunks.push(buf);bytes+=buf.length;while(bytes-(chunks[0]?.length??0)>MAX_OUTPUT_BYTES*2&&chunks.length>1){const dropped=chunks.shift();if(!dropped)break;bytes-=dropped.length}};child.stdout.on(
70
+ "data",collect);child.stderr.on("data",collect);let outcome="ok";const kill=()=>{if(child.killed||child.exitCode!==null)return;if(isForceOnly()){killProcessTree(child,"SIGKILL");return}killProcessTree(child,"SIGTERM");setTimeout(()=>killProcessTree(child,"SIGKILL"),2e3).unref()};const timer=setTimeout(()=>{outcome="timeout";kill()},timeoutMs);const onAbort=()=>{outcome="aborted";kill()};if(signal){if(signal.aborted)onAbort();else signal.addEventListener("abort",onAbort,{once:true})}const finish=(exitCode,spawnError)=>{
71
+ clearTimeout(timer);signal?.removeEventListener("abort",onAbort);const raw=Buffer.concat(chunks);const kept=keepTailBytes(raw,MAX_OUTPUT_BYTES);const body=kept.text;const head=kept.droppedBytes>0?`[output truncated: dropped the first ${kept.droppedBytes} bytes, showing the last ${Buffer.byteLength(body,"utf8")}]
70
72
  `:"";if(spawnError){resolve5({content:`Failed to start ${choice.command}: ${spawnError.message}`,isError:true,summary:`${choice.toolName} \xB7 \u8D77\u52D5\u3067\u304D\u307E\u305B\u3093`});return}if(outcome==="timeout"){resolve5({content:`${head}${body}
71
73
  [timed out after ${timeoutMs}ms and was killed]`,isError:true,summary:`${choice.toolName} \xB7 \u30BF\u30A4\u30E0\u30A2\u30A6\u30C8 (${timeoutMs}ms)`});return}if(outcome==="aborted"){resolve5({content:`${head}${body}
72
74
  [interrupted by the user]`,isError:true,summary:`${choice.toolName} \xB7 \u4E2D\u65AD`});return}resolve5({content:body===""?`(no output, exit code ${exitCode??0})`:`${head}${body}`,...exitCode!==0?{isError:true}:{},summary:`${choice.toolName} \xB7 exit ${exitCode??0}`})};child.on("error",err=>finish(null,err));child.on("close",code=>finish(code))})}import{readFile,writeFile}from"fs/promises";function detectEol(text){let crlf=0;let lf=0;for(let i=0;i<text.length;i++){if(text.charCodeAt(i)!==10)continue;if(i>0&&text.charCodeAt(i-1)===13)crlf++;else lf++}return crlf>lf?"\r\n":"\n"}function toLf(text){return text.replace(/\r\n/g,"\n")}function applyEol(text,eol){if(eol==="\n")return toLf(text);return toLf(text).replace(/\n/g,"\r\n")}var editFileTool={name:"edit_file",domain:"local",risk:"write",description:"Replace an exact string in a file. old_string must match exactly and be unique unless replace_all is true. Read the file first \u2014 the match includes indentation. Line endings of the file are preserved.",inputSchema:{type:"object",additionalProperties:false,properties:{path:{type:"string",description:"File path, relative to the working directory"},old_string:{type:"string",description:"Exact text to replace (without l\
@@ -76,14 +78,14 @@ ok)return{content:applied.error,isError:true};await writeFile(abs,applied.after,
76
78
  error:"old_string must not be empty"};if(oldRaw===newRaw)return{ok:false,error:"old_string and new_string are identical"};const candidates=eol==="\r\n"?[applyEol(oldRaw,eol),oldRaw]:[oldRaw];for(const needle of candidates){const count=countOccurrences(before,needle);if(count===0)continue;if(count>1&&!replaceAll){return{ok:false,error:`old_string occurs ${count} times. Provide more surrounding context to make it unique, or set replace_all: true.`}}const replacement=applyEol(newRaw,eol);const after=replaceAll?
77
79
  before.split(needle).join(replacement):replaceOnce(before,needle,replacement);return{ok:true,after,count}}return{ok:false,error:"old_string not found in the file. Read the file again \u2014 whitespace and indentation must match exactly."}}function countOccurrences(haystack,needle){let count=0;let from=0;for(;;){const at=haystack.indexOf(needle,from);if(at===-1)return count;count+=1;from=at+needle.length}}function replaceOnce(haystack,needle,replacement){const at=haystack.indexOf(needle);return haystack.
78
80
  slice(0,at)+replacement+haystack.slice(at+needle.length)}import{spawn as spawn2}from"child_process";import path3 from"path";var GIT_TIMEOUT_MS=6e4;var MAX_GIT_OUTPUT_BYTES=1e5;var READ_ONLY_SUBCOMMANDS=["blame","branch","describe","diff","log","ls-files","rev-parse","shortlog","show","status","tag"];var DENIED_ARGS=new Set(["--no-index","-c","--config-env","--upload-pack","--receive-pack","--exec","--output"]);var LIST_ONLY_SUBCOMMANDS=new Set(["branch","tag"]);var gitTool={name:"git",domain:"local",risk:"exec",description:`Run a read-only git command. Allowed subcommands: ${READ_ONLY_SUBCOMMANDS.join(", ")}. Writing\
79
- operations (commit, push, checkout, add, ...) are not available here \u2014 use bash for those, which goes through the permission prompt.`,inputSchema:{type:"object",additionalProperties:false,properties:{subcommand:{type:"string",description:'The git subcommand, e.g. "log"',enum:[...READ_ONLY_SUBCOMMANDS]},args:{type:"array",description:'Arguments, e.g. ["--oneline", "-20"]. Each element is passed as a separate argv entry.',items:{type:"string"}}},required:["subcommand"]},preview(input){const args=Array.
80
- isArray(input["args"])?input["args"].map(String):[];return`git \xB7 ${String(input["subcommand"]??"")} ${args.join(" ")}`.trim()},async run(input,ctx){const sub=String(input["subcommand"]);if(!READ_ONLY_SUBCOMMANDS.includes(sub)){return{content:`git ${sub} is not available (read-only subcommands only: ${READ_ONLY_SUBCOMMANDS.join(", ")}). Use bash for write operations.`,isError:true}}const args=Array.isArray(input["args"])?input["args"].map(String):[];for(const arg of args){const head=arg.split(
81
- "=")[0]??arg;if(DENIED_ARGS.has(head)){return{content:`Argument ${arg} is not allowed for the git tool.`,isError:true}}}const argv=LIST_ONLY_SUBCOMMANDS.has(sub)?[sub,"--list",...args]:[sub,...args];const env=ctx.env??process.env;const exe=resolveGitExecutable({env});if(exe===null){return{content:'git executable was not found on PATH. On Windows the git tool resolves the executable to an absolute path from PATH (it never runs a bare "git", because Windows searches the current directory before PA\
82
- TH). Install Git for Windows or add its bin directory to PATH.',isError:true,summary:"git \xB7 \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093"}}return runGit(exe,argv,ctx.cwd,env,ctx.signal)}};function resolveGitExecutable(deps={}){const platform=deps.platform??process.platform;if(platform!=="win32")return"git";const env=deps.env??process.env;const common={platform,...deps.isExecutableFile!==void 0?{isExecutableFile:deps.isExecutableFile}:{}};const spawnable=findExecutable(
83
- "git",{...common,env:{...env,PATHEXT:".EXE;.COM"}});return spawnable??findExecutable("git",{...common,env})}function runGit(exe,argv,cwd,baseEnv,signal){return new Promise(resolve5=>{let child;try{child=spawn2(exe,["--no-pager",...argv],{cwd,shell:false,env:{...baseEnv,GIT_PAGER:"cat",PAGER:"cat",GIT_TERMINAL_PROMPT:"0",GIT_EDITOR:"true",EDITOR:"true"},detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]})}catch(e){const err=e;const name=path3.basename(exe);resolve5({content:err.code===
84
- "EINVAL"?`Failed to start git: the resolved executable (${name}) is a .cmd/.bat shim, which Node refuses to spawn without a shell. Install Git for Windows (which provides git.exe) or put its bin directory earlier on PATH.`:`Failed to start git (${name}): ${err.code??"unknown error"}`,isError:true,summary:"git \xB7 \u8D77\u52D5\u3067\u304D\u307E\u305B\u3093"});return}const chunks=[];let bytes=0;const collect=buf=>{chunks.push(buf);bytes+=buf.length;while(bytes-(chunks[0]?.length??0)>MAX_GIT_OUTPUT_BYTES*
85
- 2&&chunks.length>1){const dropped=chunks.shift();if(!dropped)break;bytes-=dropped.length}};child.stdout?.on("data",collect);child.stderr?.on("data",collect);let timedOut=false;const timer=setTimeout(()=>{timedOut=true;killProcessTree(child,"SIGKILL")},GIT_TIMEOUT_MS);const onAbort=()=>{killProcessTree(child,"SIGKILL")};if(signal){if(signal.aborted)onAbort();else signal.addEventListener("abort",onAbort,{once:true})}const finish=(code,err)=>{clearTimeout(timer);signal?.removeEventListener("abort",
86
- onAbort);const kept=keepTailBytes(Buffer.concat(chunks),MAX_GIT_OUTPUT_BYTES);const body=kept.text;const note=kept.droppedBytes>0?`
81
+ operations (commit, push, checkout, add, ...) are not available here \u2014 use bash for those, which goes through the permission prompt.`,inputSchema:{type:"object",additionalProperties:false,properties:{subcommand:{type:"string",description:'The git subcommand, e.g. "log"',enum:[...READ_ONLY_SUBCOMMANDS]},args:{type:"array",description:'Arguments, e.g. ["--oneline", "-20"]. Each element is passed as a separate argv entry.',items:{type:"string"}}},required:["subcommand"]},execCommands(input){const sub=String(
82
+ input["subcommand"]??"");const args=Array.isArray(input["args"])?input["args"].map(String):[];return{argv:[["git",...LIST_ONLY_SUBCOMMANDS.has(sub)?[sub,"--list"]:[sub],...args]]}},preview(input){const args=Array.isArray(input["args"])?input["args"].map(String):[];return`git \xB7 ${String(input["subcommand"]??"")} ${args.join(" ")}`.trim()},async run(input,ctx){const sub=String(input["subcommand"]);if(!READ_ONLY_SUBCOMMANDS.includes(sub)){return{content:`git ${sub} is not available (read-only su\
83
+ bcommands only: ${READ_ONLY_SUBCOMMANDS.join(", ")}). Use bash for write operations.`,isError:true}}const args=Array.isArray(input["args"])?input["args"].map(String):[];for(const arg of args){const head=arg.split("=")[0]??arg;if(DENIED_ARGS.has(head)){return{content:`Argument ${arg} is not allowed for the git tool.`,isError:true}}}const argv=LIST_ONLY_SUBCOMMANDS.has(sub)?[sub,"--list",...args]:[sub,...args];const env=ctx.env??process.env;const exe=resolveGitExecutable({env});if(exe===null){return{
84
+ content:'git executable was not found on PATH. On Windows the git tool resolves the executable to an absolute path from PATH (it never runs a bare "git", because Windows searches the current directory before PATH). Install Git for Windows or add its bin directory to PATH.',isError:true,summary:"git \xB7 \u5B9F\u884C\u30D5\u30A1\u30A4\u30EB\u304C\u898B\u3064\u304B\u308A\u307E\u305B\u3093"}}return runGit(exe,argv,ctx.cwd,env,ctx.signal)}};function resolveGitExecutable(deps={}){const platform=deps.
85
+ platform??process.platform;if(platform!=="win32")return"git";const env=deps.env??process.env;const common={platform,...deps.isExecutableFile!==void 0?{isExecutableFile:deps.isExecutableFile}:{}};const spawnable=findExecutable("git",{...common,env:{...env,PATHEXT:".EXE;.COM"}});return spawnable??findExecutable("git",{...common,env})}function runGit(exe,argv,cwd,baseEnv,signal){return new Promise(resolve5=>{let child;try{child=spawn2(exe,["--no-pager",...argv],{cwd,shell:false,env:{...baseEnv,GIT_PAGER:"\
86
+ cat",PAGER:"cat",GIT_TERMINAL_PROMPT:"0",GIT_EDITOR:"true",EDITOR:"true"},detached:process.platform!=="win32",stdio:["ignore","pipe","pipe"]})}catch(e){const err=e;const name=path3.basename(exe);resolve5({content:err.code==="EINVAL"?`Failed to start git: the resolved executable (${name}) is a .cmd/.bat shim, which Node refuses to spawn without a shell. Install Git for Windows (which provides git.exe) or put its bin directory earlier on PATH.`:`Failed to start git (${name}): ${err.code??"unknown \
87
+ error"}`,isError:true,summary:"git \xB7 \u8D77\u52D5\u3067\u304D\u307E\u305B\u3093"});return}const chunks=[];let bytes=0;const collect=buf=>{chunks.push(buf);bytes+=buf.length;while(bytes-(chunks[0]?.length??0)>MAX_GIT_OUTPUT_BYTES*2&&chunks.length>1){const dropped=chunks.shift();if(!dropped)break;bytes-=dropped.length}};child.stdout?.on("data",collect);child.stderr?.on("data",collect);let timedOut=false;const timer=setTimeout(()=>{timedOut=true;killProcessTree(child,"SIGKILL")},GIT_TIMEOUT_MS);
88
+ const onAbort=()=>{killProcessTree(child,"SIGKILL")};if(signal){if(signal.aborted)onAbort();else signal.addEventListener("abort",onAbort,{once:true})}const finish=(code,err)=>{clearTimeout(timer);signal?.removeEventListener("abort",onAbort);const kept=keepTailBytes(Buffer.concat(chunks),MAX_GIT_OUTPUT_BYTES);const body=kept.text;const note=kept.droppedBytes>0?`
87
89
  [output truncated: dropped the first ${kept.droppedBytes} bytes]`:"";if(err){resolve5({content:`Failed to run git (${path3.basename(exe)}): ${err.code??err.message}`,isError:true,summary:"git \xB7 \u8D77\u52D5\u3067\u304D\u307E\u305B\u3093"});return}if(timedOut){resolve5({content:`${body}${note}
88
90
  [timed out after ${GIT_TIMEOUT_MS}ms]`,isError:true,summary:"git \xB7 \u30BF\u30A4\u30E0\u30A2\u30A6\u30C8"});return}resolve5({content:body===""?`(no output, exit code ${code??0})`:`${body}${note}`,...code!==0?{isError:true}:{},summary:`git ${argv[0]??""} \xB7 exit ${code??0}`})};child.on("error",e=>finish(null,e));child.on("close",code=>finish(code))})}import{glob}from"fs/promises";import{resolve as resolve3}from"path";var MAX_GLOB_RESULTS=500;var DEFAULT_EXCLUDES=["**/node_modules/**","**/.git/**","**/dist/**","**/.next/**","**/vendor/**"];var globTool={name:"glob",domain:"local",risk:"read",description:'Find files by glob pattern (e.g. "src/**/*.ts"). Returns paths relative to the working directory, sorted. node_modules, .git, dist, .next and vendor are excluded by default.',inputSchema:{type:"object",additionalProperties:false,properties:{pattern:{type:"string",description:'Glob pattern, e.g. "**/*.test.ts"'},
89
91
  path:{type:"string",description:"Directory to search in (default: the working directory)"},include_ignored:{type:"boolean",description:"Include node_modules / dist / vendor etc.",default:false}},required:["pattern"]},preview(input){return`glob \xB7 ${String(input["pattern"]??"")}`},async run(input,ctx){const root=input["path"]===void 0?resolve3(ctx.cwd):resolveToolPath(String(input["path"]),ctx.cwd);const pattern=String(input["pattern"]);const exclude=input["include_ignored"]===true?[]:DEFAULT_EXCLUDES;
@@ -106,4 +108,4 @@ limit"]:DEFAULT_LIMIT_LINES;const slice=lines.slice(offset-1,offset-1+limit);let
106
108
  [truncated: file has ${lines.length} lines; re-read with offset/limit for the rest]`:"";if(body===""){const reason=lines.length===0?"(empty file)":`(no lines at offset ${offset}; the file has ${lines.length} lines)`;return{content:reason,summary:`read_file \xB7 ${toolRelative(ctx.cwd,abs)} (0 \u884C)`}}return{content:body+note,summary:`read_file \xB7 ${toolRelative(ctx.cwd,abs)} (${slice.length} \u884C${eol==="\r\n"?" \xB7 CRLF":""})`}}};import{mkdir,readFile as readFile4,writeFile as writeFile2}from"fs/promises";import{dirname as dirname3}from"path";var writeFileTool={name:"write_file",domain:"local",risk:"write",description:"Write the full content of a file, creating it (and parent directories) if needed. Overwrites the whole file \u2014 prefer edit_file for partial changes. The existing line ending style (LF/CRLF) is preserved.",inputSchema:{type:"object",additionalProperties:false,properties:{path:{type:"string",description:"File path, relative to the working directory"},content:{type:"string",description:"Full new content. Use \\n for li\
107
109
  ne breaks."}},required:["path","content"]},preview(input){const content=typeof input["content"]==="string"?input["content"]:"";return`write_file \xB7 ${String(input["path"]??"")} (${content.split("\n").length} \u884C)`},async prepare(input,ctx){const abs=resolveToolPath(String(input["path"]),ctx.cwd);const before=await readFile4(abs,"utf8").catch(()=>"");return{path:toolRelative(ctx.cwd,abs),before,after:String(input["content"]??"")}},async run(input,ctx){const abs=resolveToolPath(String(input["\
108
110
  path"]),ctx.cwd);const existing=await readFile4(abs,"utf8").catch(()=>null);const eol=existing===null?"\n":detectEol(existing);const body=applyEol(String(input["content"]),eol);await mkdir(dirname3(abs),{recursive:true});await writeFile2(abs,body,"utf8");const rel=toolRelative(ctx.cwd,abs);return{content:`Wrote ${rel} (${body.split(eol).length} lines${eol==="\r\n"?", CRLF preserved":""}).`,summary:`write_file \xB7 ${rel}`,diff:{path:rel,before:existing??"",after:String(input["content"])}}}};var RESIDENT_TOKEN_CAP=8e3;function localTools(choice=selectShell()){return[readFileTool,writeFileTool,editFileTool,createBashTool(choice),globTool,grepTool,gitTool]}function buildResidentSet(mode,opts={}){const all=opts.tools??localTools();const cap=opts.cap??RESIDENT_TOKEN_CAP;const eligible=all.filter(tool=>matchesAnyGlob(tool.name,mode.tools)&&applyPermissionMode(checkPermission(tool.name,mode),tool.risk,opts.permissionMode).decision!=="deny");const tools=[];const dropped=[];let tokens=0;for(const tool of eligible){const cost=estimateToolTokens(
109
- tool);if(tokens+cost>cap){dropped.push(tool.name);continue}tools.push(tool);tokens+=cost}return{tools,wire:tools.map(toWireTool),tokens,dropped}}function estimateToolTokens(tool){return Math.ceil(JSON.stringify(toWireTool(tool)).length/4)}function matchesAnyGlob(name,patterns){return patterns.some(pattern=>globToRegExp(pattern).test(name))}function globToRegExp(pattern){const escaped=pattern.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${escaped}$`)}export{buildSystemPrompt,runTurn,createAuditLogger,currentBranch,displayCwd,RESIDENT_TOKEN_CAP,buildResidentSet};
111
+ tool);if(tokens+cost>cap){dropped.push(tool.name);continue}tools.push(tool);tokens+=cost}return{tools,wire:tools.map(toWireTool),tokens,dropped}}function estimateToolTokens(tool){return Math.ceil(JSON.stringify(toWireTool(tool)).length/4)}function matchesAnyGlob(name,patterns){return patterns.some(pattern=>globToRegExp(pattern).test(name))}function globToRegExp(pattern){const escaped=pattern.replace(/[.+?^${}()|[\]\\]/g,"\\$&").replace(/\*/g,".*");return new RegExp(`^${escaped}$`)}export{buildSystemPrompt,runTurn,describeAuditLog,createAuditLogger,currentBranch,displayCwd,RESIDENT_TOKEN_CAP,buildResidentSet};