@tencent-ai/agent-sdk 0.3.206 → 0.3.210
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cli/CHANGELOG.md +61 -0
- package/cli/builtin/workflows/deep-research.workflow.js +77 -20
- package/cli/dist/codebuddy-headless.js +294 -246
- package/cli/dist/web-ui/assets/index-CH6e4vvI.css +32 -0
- package/cli/dist/web-ui/assets/index-GcU4pZms.js +1102 -0
- package/cli/dist/web-ui/index.html +2 -2
- package/cli/dist/web-ui/sw.js +1 -1
- package/cli/package.json +4 -4
- package/cli/product.cloudhosted.json +2 -2
- package/cli/product.internal.json +2 -2
- package/cli/product.ioa.json +2 -2
- package/cli/product.json +3 -3
- package/cli/product.selfhosted.json +2 -2
- package/cli/vendor/native-builds.json +18 -0
- package/cli/vendor/shim/broker-ipc-client.cjs +158 -0
- package/cli/vendor/shim/brokered-bin/codebuddy-toybox-dispatch +381 -0
- package/cli/vendor/shim/brokered-sandbox-bash-env.sh +10 -0
- package/cli/vendor/shim/genie-safe-delete.cjs +4 -781
- package/cli/vendor/shim/native/binding.gyp +13 -0
- package/cli/vendor/shim/native/brokered_sandbox_native.c +293 -0
- package/cli/vendor/shim/native/darwin-arm64/brokered-sandbox-native.node +0 -0
- package/cli/vendor/shim/native/darwin-x64/brokered-sandbox-native.node +0 -0
- package/cli/vendor/shim/node-brokered-fs-shim.cjs +932 -0
- package/cli/vendor/shim/node-language-shim.cjs +35 -0
- package/cli/vendor/shim/node-safe-delete-shim.cjs +810 -0
- package/cli/vendor/shim/safe-bin/safe-delete-bash-env.sh +1 -1
- package/cli/vendor/shim/safe-bin/safe-delete-common.sh +95 -34
- package/cli/vendor/shim/safe-delete-broker-delete.cjs +166 -0
- package/cli/vendor/shim/shell-runtime-bash-env.sh +8 -0
- package/cli/vendor/shim/sitecustomize.py +551 -22
- package/cli/vendor/toybox-macos/LICENSE +12 -0
- package/cli/vendor/toybox-macos/toybox +0 -0
- package/cli/vendor/toybox-macos/toybox.sb +19 -0
- package/cli/vendor/zsh-macos/LICENSE +37 -0
- package/cli/vendor/zsh-macos/bin/zsh +0 -0
- package/package.json +1 -1
- package/cli/dist/web-ui/assets/index-BZjhFKbY.js +0 -1051
- package/cli/dist/web-ui/assets/index-C5EhSt3C.css +0 -32
|
@@ -15,10 +15,10 @@
|
|
|
15
15
|
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
|
|
16
16
|
<meta name="mobile-web-app-capable" content="yes">
|
|
17
17
|
<link rel="apple-touch-icon" href="/pwa-icon.svg">
|
|
18
|
-
<script type="module" crossorigin src="/assets/index-
|
|
18
|
+
<script type="module" crossorigin src="/assets/index-GcU4pZms.js"></script>
|
|
19
19
|
<link rel="modulepreload" crossorigin href="/assets/markdown-Ce2Umeb2.js">
|
|
20
20
|
<link rel="modulepreload" crossorigin href="/assets/vendor-DpYitQz5.js">
|
|
21
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
21
|
+
<link rel="stylesheet" crossorigin href="/assets/index-CH6e4vvI.css">
|
|
22
22
|
<link rel="manifest" href="/manifest.webmanifest"></head>
|
|
23
23
|
<body class="bg-bg-primary text-text-primary min-h-screen overscroll-none">
|
|
24
24
|
<div id="root"></div>
|
package/cli/dist/web-ui/sw.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
if(!self.define){let e,s={};const o=(o,n)=>(o=new URL(o+".js",n).href,s[o]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=o,e.onload=s,document.head.appendChild(e)}else e=o,importScripts(o),s()}).then(()=>{let e=s[o];if(!e)throw new Error(`Module ${o} didn’t register its module`);return e}));self.define=(n,i)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let r={};const t=e=>o(e,l),f={module:{uri:l},exports:r,require:t};s[l]=Promise.all(n.map(e=>f[e]||t(e))).then(e=>(i(...e),r))}}define(["./workbox-fed2bdfe"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"sandbox_proxy.html",revision:"e54bd087bf8b90d87d84c3cd8f2c22e9"},{url:"pwa-icon.svg",revision:"673adddf1548f59682764258005b6034"},{url:"logo.svg",revision:"269aa921a3f446f8e17843c89ed7bf35"},{url:"index.html",revision:"
|
|
1
|
+
if(!self.define){let e,s={};const o=(o,n)=>(o=new URL(o+".js",n).href,s[o]||new Promise(s=>{if("document"in self){const e=document.createElement("script");e.src=o,e.onload=s,document.head.appendChild(e)}else e=o,importScripts(o),s()}).then(()=>{let e=s[o];if(!e)throw new Error(`Module ${o} didn’t register its module`);return e}));self.define=(n,i)=>{const l=e||("document"in self?document.currentScript.src:"")||location.href;if(s[l])return;let r={};const t=e=>o(e,l),f={module:{uri:l},exports:r,require:t};s[l]=Promise.all(n.map(e=>f[e]||t(e))).then(e=>(i(...e),r))}}define(["./workbox-fed2bdfe"],function(e){"use strict";self.skipWaiting(),e.clientsClaim(),e.precacheAndRoute([{url:"sandbox_proxy.html",revision:"e54bd087bf8b90d87d84c3cd8f2c22e9"},{url:"pwa-icon.svg",revision:"673adddf1548f59682764258005b6034"},{url:"logo.svg",revision:"269aa921a3f446f8e17843c89ed7bf35"},{url:"index.html",revision:"dca9a6f91dad44d4bb8b35848dac2f0d"},{url:"assets/workbox-window.prod.es5-BBnX5xw4.js",revision:null},{url:"assets/vendor-DpYitQz5.js",revision:null},{url:"assets/octicons-CaZ_fok2.woff2",revision:null},{url:"assets/mfixx-CpAhKOZz.woff2",revision:null},{url:"assets/markdown-Ce2Umeb2.js",revision:null},{url:"assets/index-GcU4pZms.js",revision:null},{url:"assets/index-DixJ0kqk.js",revision:null},{url:"assets/index-CH6e4vvI.css",revision:null},{url:"assets/fontawesome-B-jkhYfk.woff2",revision:null},{url:"assets/file-icons-C0jOugUK.woff2",revision:null},{url:"assets/devopicons-QN4QXivI.woff2",revision:null},{url:"logo.svg",revision:"269aa921a3f446f8e17843c89ed7bf35"},{url:"pwa-icon.svg",revision:"673adddf1548f59682764258005b6034"},{url:"manifest.webmanifest",revision:"7a003d0094122eb3e607566c757e9885"}],{}),e.cleanupOutdatedCaches(),e.registerRoute(new e.NavigationRoute(e.createHandlerBoundToURL("/index.html"),{denylist:[/^\/api/,/^\/gateway/,/^\/docs\//]})),e.registerRoute(/^https:\/\/fonts\.googleapis\.com/,new e.StaleWhileRevalidate({cacheName:"google-fonts-stylesheets",plugins:[]}),"GET"),e.registerRoute(/^https:\/\/fonts\.gstatic\.com/,new e.CacheFirst({cacheName:"google-fonts-webfonts",plugins:[new e.ExpirationPlugin({maxEntries:20,maxAgeSeconds:31536e3})]}),"GET")});
|
package/cli/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tencent-ai/codebuddy-code",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.119.3",
|
|
4
4
|
"description": "Use CodeBuddy, Tencent's AI assistant, right from your terminal. CodeBuddy can understand your codebase, edit files, run terminal commands, and handle entire workflows for you.",
|
|
5
5
|
"main": "lib/node/index.js",
|
|
6
6
|
"typings": "lib/node/index.d.ts",
|
|
@@ -18,9 +18,9 @@
|
|
|
18
18
|
"@lydell/node-pty-linux-x64": "1.2.0-beta.12",
|
|
19
19
|
"@lydell/node-pty-win32-arm64": "1.2.0-beta.12",
|
|
20
20
|
"@lydell/node-pty-win32-x64": "1.2.0-beta.12",
|
|
21
|
-
"@tencent-ai/sandbox-cli-darwin-arm64": "5.3.0-beta.
|
|
22
|
-
"@tencent-ai/sandbox-cli-darwin-x64": "5.3.0-beta.
|
|
23
|
-
"@tencent-ai/sandbox-cli-win32-x64": "5.3.0-beta.
|
|
21
|
+
"@tencent-ai/sandbox-cli-darwin-arm64": "5.3.0-beta.8",
|
|
22
|
+
"@tencent-ai/sandbox-cli-darwin-x64": "5.3.0-beta.8",
|
|
23
|
+
"@tencent-ai/sandbox-cli-win32-x64": "5.3.0-beta.10"
|
|
24
24
|
},
|
|
25
25
|
"keywords": [
|
|
26
26
|
"codebuddy",
|
|
@@ -827,6 +827,6 @@
|
|
|
827
827
|
"SelectImage": true,
|
|
828
828
|
"SkipToolCallSupportCheck": true
|
|
829
829
|
},
|
|
830
|
-
"commit": "
|
|
831
|
-
"date": "2026-07-
|
|
830
|
+
"commit": "72cfe535d28e0d79457fa34b0536105b21714c74",
|
|
831
|
+
"date": "2026-07-12T11:36:03.437Z"
|
|
832
832
|
}
|
package/cli/product.ioa.json
CHANGED
package/cli/product.json
CHANGED
|
@@ -781,7 +781,7 @@
|
|
|
781
781
|
},
|
|
782
782
|
{
|
|
783
783
|
"name": "tool-skill-description",
|
|
784
|
-
"template": "Execute a skill within the main conversation\n\nWhen users ask you to perform tasks, check if any of the available skills below match. Skills provide specialized capabilities and domain knowledge.\n\nWhen users reference a \"slash command\" or \"/<something>\" (e.g., \"/commit\", \"/review-pr\"), they are referring to a skill. Use this tool to invoke it.\n\nHow to invoke:\n- Use this tool with the skill name and optional arguments\n- Examples:\n - `skill: \"pdf\"` - invoke the pdf skill\n - `skill: \"commit\", args: \"-m 'Fix bug'\"` - invoke with arguments\n - `skill: \"ms-office-suite:pdf\"` - invoke using fully qualified name\n\nImportant:\n- When a skill matches the user's request, this is a BLOCKING REQUIREMENT: invoke the relevant Skill tool BEFORE generating any other response about the task\n- NEVER mention a skill without actually calling this tool\n- Do not invoke a skill that is already running\n- Do not use this tool for built-in CLI commands (like /help, /clear, etc.)\n- If you see a <command-name> tag in the current conversation turn, the skill has ALREADY been loaded - follow the instructions directly instead of calling this tool again\n\n<available_skills>\n{%- if skills and skills.length > 0 -%}\n{%- for skill in skills %}\n- {{skill.name}}: {% if skill.truncatedDescription == undefined %}{{skill.description}}{% elif skill.truncatedDescription %}{{skill.truncatedDescription}}{% endif %} (location: {{skill.location}})\n{%- endfor -%}\n{%- endif %}\n</available_skills>\n{%- if skillsOverview and skillsOverview.truncationMode != 'none' %}\n{%- if skillsOverview.omittedCount > 0 %}\n<!-- Showing {{skillsOverview.shownCount}} of {{skillsOverview.totalCount}} skills due to token limits -->\n{%- if skillsOverview.scanDirs and skillsOverview.scanDirs.length > 0 %}\nMore skills are available in these directories. Each subdirectory name is a skill name (containing a SKILL.md file). Discover them as needed, then invoke by name with this tool:\n{%- for dir in skillsOverview.scanDirs %}\n - {{dir.path}}\n{%- endfor %}\n{%- endif %}\n{%- else %}\n<!-- Descriptions for some skills have been trimmed to fit token limits. All listed names remain callable. -->\n{%- endif %}\n{%- endif %}\n"
|
|
784
|
+
"template": "Execute a skill within the main conversation\n\nWhen users ask you to perform tasks, check if any of the available skills below match. Skills provide specialized capabilities and domain knowledge.\n\nWhen users reference a \"slash command\" or \"/<something>\" (e.g., \"/commit\", \"/review-pr\"), they are referring to a skill. Use this tool to invoke it.\n\nHow to invoke:\n- Use this tool with the skill name and optional arguments\n- Examples:\n - `skill: \"pdf\"` - invoke the pdf skill\n - `skill: \"commit\", args: \"-m 'Fix bug'\"` - invoke with arguments\n - `skill: \"ms-office-suite:pdf\"` - invoke using fully qualified name\n\nImportant:\n- When a skill matches the user's request, this is a BLOCKING REQUIREMENT: invoke the relevant Skill tool BEFORE generating any other response about the task\n- NEVER mention a skill without actually calling this tool\n- Do not invoke a skill that is already running\n- Do not use this tool for built-in CLI commands (like /help, /clear, etc.)\n- If you see a <command-name> tag in the current conversation turn, the skill has ALREADY been loaded - follow the instructions directly instead of calling this tool again\n- If the name matches a deferred tool listed in <available_deferred_tools> (e.g., \"Workflow\"), do NOT use this Skill tool — use ToolSearch + DeferExecuteTool instead\n\n<available_skills>\n{%- if skills and skills.length > 0 -%}\n{%- for skill in skills %}\n- {{skill.name}}: {% if skill.truncatedDescription == undefined %}{{skill.description}}{% elif skill.truncatedDescription %}{{skill.truncatedDescription}}{% endif %} (location: {{skill.location}})\n{%- endfor -%}\n{%- endif %}\n</available_skills>\n{%- if skillsOverview and skillsOverview.truncationMode != 'none' %}\n{%- if skillsOverview.omittedCount > 0 %}\n<!-- Showing {{skillsOverview.shownCount}} of {{skillsOverview.totalCount}} skills due to token limits -->\n{%- if skillsOverview.scanDirs and skillsOverview.scanDirs.length > 0 %}\nMore skills are available in these directories. Each subdirectory name is a skill name (containing a SKILL.md file). Discover them as needed, then invoke by name with this tool:\n{%- for dir in skillsOverview.scanDirs %}\n - {{dir.path}}\n{%- endfor %}\n{%- endif %}\n{%- else %}\n<!-- Descriptions for some skills have been trimmed to fit token limits. All listed names remain callable. -->\n{%- endif %}\n{%- endif %}\n"
|
|
785
785
|
},
|
|
786
786
|
{
|
|
787
787
|
"name": "tool-skillmanage-description",
|
|
@@ -1765,6 +1765,6 @@
|
|
|
1765
1765
|
"deferLoading": true
|
|
1766
1766
|
}
|
|
1767
1767
|
],
|
|
1768
|
-
"commit": "
|
|
1769
|
-
"date": "2026-07-
|
|
1768
|
+
"commit": "72cfe535d28e0d79457fa34b0536105b21714c74",
|
|
1769
|
+
"date": "2026-07-12T11:36:03.447Z"
|
|
1770
1770
|
}
|
|
@@ -342,6 +342,6 @@
|
|
|
342
342
|
"ScheduledTasks": true,
|
|
343
343
|
"SkipToolCallSupportCheck": true
|
|
344
344
|
},
|
|
345
|
-
"commit": "
|
|
346
|
-
"date": "2026-07-
|
|
345
|
+
"commit": "72cfe535d28e0d79457fa34b0536105b21714c74",
|
|
346
|
+
"date": "2026-07-12T11:36:03.494Z"
|
|
347
347
|
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"schemaVersion": 1,
|
|
3
|
+
"sourceRepository": "tsbx-macos",
|
|
4
|
+
"artifacts": {
|
|
5
|
+
"toybox-macos/toybox": {
|
|
6
|
+
"sourceCommit": "bb6dd7af9ecd79ed62b70cfdf64fd24464db7525",
|
|
7
|
+
"buildCommand": "./build-toybox-macos.sh",
|
|
8
|
+
"platform": "macos",
|
|
9
|
+
"archs": ["x86_64", "arm64"]
|
|
10
|
+
},
|
|
11
|
+
"zsh-macos/bin/zsh": {
|
|
12
|
+
"sourceCommit": "bb6dd7af9ecd79ed62b70cfdf64fd24464db7525",
|
|
13
|
+
"buildCommand": "cd zsh-macos && ./build-zsh-macos.sh",
|
|
14
|
+
"platform": "macos",
|
|
15
|
+
"archs": ["x86_64", "arm64"]
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Neutral broker IPC client for vendor shims.
|
|
3
|
+
*
|
|
4
|
+
* Owns JSON-line socket transport only. Runtime-specific request semantics and
|
|
5
|
+
* response classification stay in the caller.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
'use strict';
|
|
9
|
+
|
|
10
|
+
const net = require('net');
|
|
11
|
+
const { spawnSync } = require('child_process');
|
|
12
|
+
|
|
13
|
+
const DEFAULT_TIMEOUT_MS = 5_000;
|
|
14
|
+
|
|
15
|
+
function brokerTimeoutMs() {
|
|
16
|
+
const parsed = Number.parseInt(process.env.CODEBUDDY_SANDBOX_BROKER_TIMEOUT_MS || '', 10);
|
|
17
|
+
return Number.isFinite(parsed) && parsed > 0 ? parsed : DEFAULT_TIMEOUT_MS;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function brokerSocketPath() {
|
|
21
|
+
return process.env.CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function parseBrokerResponse(line) {
|
|
25
|
+
try {
|
|
26
|
+
return JSON.parse(String(line || '').trim());
|
|
27
|
+
} catch (error) {
|
|
28
|
+
throw new Error(`Invalid broker response: ${error && error.message ? error.message : error}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function sendBrokerRequest(request, options = {}) {
|
|
33
|
+
const socketPath = options.socketPath || brokerSocketPath();
|
|
34
|
+
const timeoutMs = options.timeoutMs || brokerTimeoutMs();
|
|
35
|
+
return new Promise((resolve, reject) => {
|
|
36
|
+
if (!socketPath) {
|
|
37
|
+
reject(new Error('Broker socket unavailable'));
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
let settled = false;
|
|
42
|
+
let buffer = '';
|
|
43
|
+
const socket = net.createConnection(socketPath);
|
|
44
|
+
const finish = (error, response) => {
|
|
45
|
+
if (settled) { return; }
|
|
46
|
+
settled = true;
|
|
47
|
+
clearTimeout(timer);
|
|
48
|
+
socket.destroy();
|
|
49
|
+
if (error) { reject(error); } else { resolve(response); }
|
|
50
|
+
};
|
|
51
|
+
const timer = setTimeout(() => finish(new Error('Broker request timed out')), timeoutMs);
|
|
52
|
+
|
|
53
|
+
socket.setEncoding('utf8');
|
|
54
|
+
socket.on('connect', () => {
|
|
55
|
+
socket.write(`${JSON.stringify(request)}\n`);
|
|
56
|
+
});
|
|
57
|
+
socket.on('data', chunk => {
|
|
58
|
+
buffer += chunk;
|
|
59
|
+
const newlineIndex = buffer.indexOf('\n');
|
|
60
|
+
if (newlineIndex === -1) { return; }
|
|
61
|
+
try {
|
|
62
|
+
finish(undefined, parseBrokerResponse(buffer.slice(0, newlineIndex)));
|
|
63
|
+
} catch (error) {
|
|
64
|
+
finish(error);
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
socket.on('error', error => finish(error));
|
|
68
|
+
socket.on('end', () => {
|
|
69
|
+
if (!settled) {
|
|
70
|
+
finish(new Error('Broker closed without a response'));
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function sendBrokerRequestSync(request, options = {}) {
|
|
77
|
+
const socketPath = options.socketPath || brokerSocketPath();
|
|
78
|
+
if (!socketPath) {
|
|
79
|
+
throw new Error('Broker socket unavailable');
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const timeoutMs = options.timeoutMs || brokerTimeoutMs();
|
|
83
|
+
const line = JSON.stringify(request);
|
|
84
|
+
const nativeAddon = options.nativeAddon;
|
|
85
|
+
if (nativeAddon && typeof nativeAddon.requestBrokerSync === 'function') {
|
|
86
|
+
return parseBrokerResponse(nativeAddon.requestBrokerSync(socketPath, line, timeoutMs));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const nodeBin = process.env.CODEBUDDY_NODE_BIN || process.execPath;
|
|
90
|
+
const result = spawnSync(nodeBin, [
|
|
91
|
+
__filename,
|
|
92
|
+
'__request-sync',
|
|
93
|
+
socketPath,
|
|
94
|
+
line,
|
|
95
|
+
String(timeoutMs),
|
|
96
|
+
], {
|
|
97
|
+
encoding: 'utf8',
|
|
98
|
+
timeout: timeoutMs + 1_000,
|
|
99
|
+
windowsHide: true,
|
|
100
|
+
env: {
|
|
101
|
+
...process.env,
|
|
102
|
+
NODE_OPTIONS: '',
|
|
103
|
+
},
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
if (result.error) {
|
|
107
|
+
throw result.error;
|
|
108
|
+
}
|
|
109
|
+
if (result.status !== 0) {
|
|
110
|
+
throw new Error((result.stderr || '').trim() || `Broker sync helper exited with ${result.status}`);
|
|
111
|
+
}
|
|
112
|
+
return parseBrokerResponse(result.stdout);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function runSyncRequestCli(argv) {
|
|
116
|
+
const [, , mode, socketPath, line, timeoutValue] = argv;
|
|
117
|
+
if (mode !== '__request-sync') {
|
|
118
|
+
process.stderr.write('[broker-ipc-client] unsupported mode\n');
|
|
119
|
+
process.exit(2);
|
|
120
|
+
}
|
|
121
|
+
const timeoutMs = Number.parseInt(timeoutValue || '', 10) || DEFAULT_TIMEOUT_MS;
|
|
122
|
+
let settled = false;
|
|
123
|
+
let buffer = '';
|
|
124
|
+
const socket = net.createConnection(socketPath);
|
|
125
|
+
const finish = (code, message) => {
|
|
126
|
+
if (settled) { return; }
|
|
127
|
+
settled = true;
|
|
128
|
+
clearTimeout(timer);
|
|
129
|
+
socket.destroy();
|
|
130
|
+
if (message) {
|
|
131
|
+
(code === 0 ? process.stdout : process.stderr).write(message);
|
|
132
|
+
}
|
|
133
|
+
process.exit(code);
|
|
134
|
+
};
|
|
135
|
+
const timer = setTimeout(() => finish(124, 'Broker request timed out'), timeoutMs);
|
|
136
|
+
socket.setEncoding('utf8');
|
|
137
|
+
socket.on('connect', () => socket.write(`${line}\n`));
|
|
138
|
+
socket.on('data', chunk => {
|
|
139
|
+
buffer += chunk;
|
|
140
|
+
const newlineIndex = buffer.indexOf('\n');
|
|
141
|
+
if (newlineIndex !== -1) {
|
|
142
|
+
finish(0, buffer.slice(0, newlineIndex));
|
|
143
|
+
}
|
|
144
|
+
});
|
|
145
|
+
socket.on('error', error => finish(1, error && error.message ? error.message : String(error)));
|
|
146
|
+
socket.on('end', () => finish(2, 'Broker closed without a response'));
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
module.exports = {
|
|
150
|
+
brokerTimeoutMs,
|
|
151
|
+
parseBrokerResponse,
|
|
152
|
+
sendBrokerRequest,
|
|
153
|
+
sendBrokerRequestSync,
|
|
154
|
+
};
|
|
155
|
+
|
|
156
|
+
if (require.main === module) {
|
|
157
|
+
runSyncRequestCli(process.argv);
|
|
158
|
+
}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
#!/usr/bin/env sh
|
|
2
|
+
|
|
3
|
+
__cb_app="${0##*/}"
|
|
4
|
+
__cb_toybox="${CODEBUDDY_TOYBOX_BIN:-}"
|
|
5
|
+
__cb_brokered_dir="${CODEBUDDY_BROKERED_BIN_DIR:-${0%/*}}"
|
|
6
|
+
__cb_broker_client="${CODEBUDDY_BROKER_IPC_CLIENT:-${__cb_brokered_dir%/brokered-bin}/broker-ipc-client.cjs}"
|
|
7
|
+
|
|
8
|
+
__cb_cleanup() { /bin/rm -f "$__cb_err" 2>/dev/null || true; }
|
|
9
|
+
|
|
10
|
+
__cb_should_fallback() { case "$1" in *"Unknown command "*|*"Unknown option "*|*"unknown option "*|*"unrecognized option "*) return 0 ;; *) return 1 ;; esac; }
|
|
11
|
+
|
|
12
|
+
__cb_path_without_brokered_dir() {
|
|
13
|
+
__cb_old_ifs="$IFS"
|
|
14
|
+
IFS=:; __cb_new_path=
|
|
15
|
+
for __cb_dir in ${PATH:-}; do
|
|
16
|
+
[ "$__cb_dir" = "$__cb_brokered_dir" ] && continue
|
|
17
|
+
__cb_new_path="${__cb_new_path:+$__cb_new_path:}$__cb_dir"
|
|
18
|
+
done
|
|
19
|
+
IFS="$__cb_old_ifs"
|
|
20
|
+
printf '%s' "$__cb_new_path"
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
__cb_fallback() {
|
|
24
|
+
case "$__cb_app" in
|
|
25
|
+
rm|rmdir|unlink) [ ! -x "${CODEBUDDY_SAFE_DELETE_BIN_DIR:-}/${__cb_app}" ] || BASH_ENV= exec "${CODEBUDDY_SAFE_DELETE_BIN_DIR}/${__cb_app}" "$@" ;;
|
|
26
|
+
esac
|
|
27
|
+
|
|
28
|
+
__cb_fallback_path="$(__cb_path_without_brokered_dir)"
|
|
29
|
+
[ -z "$__cb_fallback_path" ] && return 127
|
|
30
|
+
PATH="$__cb_fallback_path" exec "$__cb_app" "$@"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
if [ "${CODEBUDDY_TOYBOX_DISPATCH_ACTIVE:-}" = "$__cb_app" ]; then
|
|
34
|
+
unset CODEBUDDY_TOYBOX_DISPATCH_ACTIVE
|
|
35
|
+
__cb_fallback "$@"
|
|
36
|
+
exit $?
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
__cb_prebackup_path() {
|
|
40
|
+
[ -n "${1:-}" ] || return 0
|
|
41
|
+
[ -f "$1" ] || return 0
|
|
42
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS:-}" ] || return 0
|
|
43
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_SESSION_ID:-}" ] || return 0
|
|
44
|
+
[ -n "${CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND:-}" ] || return 0
|
|
45
|
+
[ -f "$__cb_broker_client" ] || return 0
|
|
46
|
+
|
|
47
|
+
NODE_OPTIONS= "${CODEBUDDY_NODE_BIN:-node}" - "$__cb_broker_client" "$1" <<'NODE'
|
|
48
|
+
const { sendBrokerRequestSync } = require(process.argv[2]);
|
|
49
|
+
const response = sendBrokerRequestSync({
|
|
50
|
+
command: process.env.CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND,
|
|
51
|
+
operation: 'write',
|
|
52
|
+
path: process.argv[3],
|
|
53
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID,
|
|
54
|
+
toolCallId: process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID,
|
|
55
|
+
brokerTraceId: process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID,
|
|
56
|
+
runtime: 'toybox-dispatch',
|
|
57
|
+
});
|
|
58
|
+
if (response && (response.ok === true || response.decision === 'sandbox')) {
|
|
59
|
+
process.exit(0);
|
|
60
|
+
}
|
|
61
|
+
process.stderr.write(response && response.error ? response.error : 'Brokered write preflight denied');
|
|
62
|
+
process.exit(13);
|
|
63
|
+
NODE
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
__cb_prebackup_tree() {
|
|
67
|
+
[ -n "${1:-}" ] || return 0
|
|
68
|
+
[ -d "$1" ] || return 0
|
|
69
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS:-}" ] || return 0
|
|
70
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_SESSION_ID:-}" ] || return 0
|
|
71
|
+
[ -n "${CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND:-}" ] || return 0
|
|
72
|
+
[ -f "$__cb_broker_client" ] || return 0
|
|
73
|
+
|
|
74
|
+
NODE_OPTIONS= "${CODEBUDDY_NODE_BIN:-node}" - "$__cb_broker_client" "$1" <<'NODE'
|
|
75
|
+
const fs = require('fs');
|
|
76
|
+
const path = require('path');
|
|
77
|
+
const { sendBrokerRequestSync } = require(process.argv[2]);
|
|
78
|
+
|
|
79
|
+
function prebackupFile(filePath) {
|
|
80
|
+
const response = sendBrokerRequestSync({
|
|
81
|
+
command: process.env.CODEBUDDY_SANDBOX_FILE_TOKEN_OPERATION_COMMAND,
|
|
82
|
+
operation: 'write',
|
|
83
|
+
path: filePath,
|
|
84
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID,
|
|
85
|
+
toolCallId: process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID,
|
|
86
|
+
brokerTraceId: process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID,
|
|
87
|
+
runtime: 'toybox-dispatch',
|
|
88
|
+
});
|
|
89
|
+
if (response && (response.ok === true || response.decision === 'sandbox')) {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
process.stderr.write(response && response.error ? response.error : 'Brokered write preflight denied');
|
|
93
|
+
process.exit(13);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function walk(dir) {
|
|
97
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
98
|
+
const entryPath = path.join(dir, entry.name);
|
|
99
|
+
if (entry.isDirectory()) {
|
|
100
|
+
walk(entryPath);
|
|
101
|
+
} else if (entry.isFile()) {
|
|
102
|
+
prebackupFile(entryPath);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
walk(process.argv[3]);
|
|
108
|
+
NODE
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
__cb_prebackup_tree_or_file() {
|
|
112
|
+
if [ -f "$1" ]; then
|
|
113
|
+
__cb_prebackup_path "$1"
|
|
114
|
+
return $?
|
|
115
|
+
fi
|
|
116
|
+
if [ -d "$1" ]; then
|
|
117
|
+
__cb_prebackup_tree "$1"
|
|
118
|
+
return $?
|
|
119
|
+
fi
|
|
120
|
+
return 0
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
__cb_prebackup_truncate() {
|
|
124
|
+
__cb_after_options=
|
|
125
|
+
__cb_skip_next=
|
|
126
|
+
for __cb_arg in "$@"; do
|
|
127
|
+
if [ -n "$__cb_skip_next" ]; then __cb_skip_next=; continue; fi
|
|
128
|
+
if [ -n "$__cb_after_options" ]; then __cb_prebackup_path "$__cb_arg" || return $?; continue; fi
|
|
129
|
+
case "$__cb_arg" in
|
|
130
|
+
--) __cb_after_options=1 ;;
|
|
131
|
+
-s|--size) __cb_skip_next=1 ;;
|
|
132
|
+
--size=*) ;;
|
|
133
|
+
-*) ;;
|
|
134
|
+
*) __cb_prebackup_path "$__cb_arg" || return $? ;;
|
|
135
|
+
esac
|
|
136
|
+
done
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
__cb_prebackup_dd() {
|
|
140
|
+
for __cb_arg in "$@"; do
|
|
141
|
+
case "$__cb_arg" in
|
|
142
|
+
of=*) __cb_prebackup_path "${__cb_arg#of=}" || return $? ;;
|
|
143
|
+
esac
|
|
144
|
+
done
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
__cb_prebackup_tee() {
|
|
148
|
+
__cb_after_options=
|
|
149
|
+
for __cb_arg in "$@"; do
|
|
150
|
+
if [ -n "$__cb_after_options" ]; then __cb_prebackup_path "$__cb_arg" || return $?; continue; fi
|
|
151
|
+
case "$__cb_arg" in
|
|
152
|
+
--) __cb_after_options=1 ;;
|
|
153
|
+
-*) ;;
|
|
154
|
+
*) __cb_prebackup_path "$__cb_arg" || return $? ;;
|
|
155
|
+
esac
|
|
156
|
+
done
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
__cb_prebackup_last_operand() {
|
|
160
|
+
__cb_after_options=
|
|
161
|
+
__cb_last=
|
|
162
|
+
for __cb_arg in "$@"; do
|
|
163
|
+
if [ -n "$__cb_after_options" ]; then __cb_last="$__cb_arg"; continue; fi
|
|
164
|
+
case "$__cb_arg" in
|
|
165
|
+
--) __cb_after_options=1 ;;
|
|
166
|
+
-*) ;;
|
|
167
|
+
*) __cb_last="$__cb_arg" ;;
|
|
168
|
+
esac
|
|
169
|
+
done
|
|
170
|
+
[ -z "$__cb_last" ] || __cb_prebackup_tree_or_file "$__cb_last"
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
__cb_cp_target_for_source() {
|
|
174
|
+
__cb_src="$1"
|
|
175
|
+
__cb_dest="$2"
|
|
176
|
+
if [ -d "$__cb_dest" ] && [ -z "${__cb_cp_no_target_dir:-}" ]; then
|
|
177
|
+
__cb_base="${__cb_src%/}"
|
|
178
|
+
__cb_base="${__cb_base##*/}"
|
|
179
|
+
[ -z "$__cb_base" ] || __cb_prebackup_tree_or_file "$__cb_dest/$__cb_base"
|
|
180
|
+
return $?
|
|
181
|
+
fi
|
|
182
|
+
__cb_prebackup_tree_or_file "$__cb_dest"
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
__cb_prebackup_cp() {
|
|
186
|
+
__cb_after_options=
|
|
187
|
+
__cb_skip_next=
|
|
188
|
+
__cb_cp_no_target_dir=
|
|
189
|
+
__cb_cp_target_dir=
|
|
190
|
+
__cb_cp_count=0
|
|
191
|
+
__cb_cp_dest=
|
|
192
|
+
for __cb_arg in "$@"; do
|
|
193
|
+
if [ "$__cb_skip_next" = "target-dir" ]; then __cb_cp_target_dir="$__cb_arg"; __cb_skip_next=; continue; fi
|
|
194
|
+
if [ -n "$__cb_after_options" ]; then __cb_cp_count=$((__cb_cp_count + 1)); __cb_cp_dest="$__cb_arg"; continue; fi
|
|
195
|
+
case "$__cb_arg" in
|
|
196
|
+
--) __cb_after_options=1 ;;
|
|
197
|
+
-t|--target-directory) __cb_skip_next=target-dir ;;
|
|
198
|
+
--target-directory=*) __cb_cp_target_dir="${__cb_arg#*=}" ;;
|
|
199
|
+
-T|--no-target-directory) __cb_cp_no_target_dir=1 ;;
|
|
200
|
+
-*) ;;
|
|
201
|
+
*) __cb_cp_count=$((__cb_cp_count + 1)); __cb_cp_dest="$__cb_arg" ;;
|
|
202
|
+
esac
|
|
203
|
+
done
|
|
204
|
+
|
|
205
|
+
if [ -n "$__cb_cp_target_dir" ]; then
|
|
206
|
+
__cb_after_options=
|
|
207
|
+
__cb_skip_next=
|
|
208
|
+
for __cb_arg in "$@"; do
|
|
209
|
+
if [ "$__cb_skip_next" = "target-dir" ]; then __cb_skip_next=; continue; fi
|
|
210
|
+
if [ -n "$__cb_after_options" ]; then __cb_cp_target_for_source "$__cb_arg" "$__cb_cp_target_dir" || return $?; continue; fi
|
|
211
|
+
case "$__cb_arg" in
|
|
212
|
+
--) __cb_after_options=1 ;;
|
|
213
|
+
-t|--target-directory) __cb_skip_next=target-dir ;;
|
|
214
|
+
--target-directory=*|-T|--no-target-directory|-*) ;;
|
|
215
|
+
*) __cb_cp_target_for_source "$__cb_arg" "$__cb_cp_target_dir" || return $? ;;
|
|
216
|
+
esac
|
|
217
|
+
done
|
|
218
|
+
return 0
|
|
219
|
+
fi
|
|
220
|
+
|
|
221
|
+
[ "$__cb_cp_count" -ge 2 ] || return 0
|
|
222
|
+
__cb_after_options=
|
|
223
|
+
__cb_index=0
|
|
224
|
+
for __cb_arg in "$@"; do
|
|
225
|
+
if [ -n "$__cb_after_options" ]; then
|
|
226
|
+
__cb_index=$((__cb_index + 1))
|
|
227
|
+
[ "$__cb_index" -ge "$__cb_cp_count" ] || __cb_cp_target_for_source "$__cb_arg" "$__cb_cp_dest" || return $?
|
|
228
|
+
continue
|
|
229
|
+
fi
|
|
230
|
+
case "$__cb_arg" in
|
|
231
|
+
--) __cb_after_options=1 ;;
|
|
232
|
+
-t|--target-directory) __cb_skip_next=target-dir ;;
|
|
233
|
+
--target-directory=*|-T|--no-target-directory|-*) ;;
|
|
234
|
+
*)
|
|
235
|
+
__cb_index=$((__cb_index + 1))
|
|
236
|
+
[ "$__cb_index" -ge "$__cb_cp_count" ] || __cb_cp_target_for_source "$__cb_arg" "$__cb_cp_dest" || return $?
|
|
237
|
+
;;
|
|
238
|
+
esac
|
|
239
|
+
done
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
__cb_prebackup_targets() {
|
|
243
|
+
case "$__cb_app" in
|
|
244
|
+
truncate) __cb_prebackup_truncate "$@" ;;
|
|
245
|
+
tee) __cb_prebackup_tee "$@" ;;
|
|
246
|
+
cp) __cb_prebackup_cp "$@" ;;
|
|
247
|
+
dd) __cb_prebackup_dd "$@" ;;
|
|
248
|
+
esac
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
__cb_host_op_ln() {
|
|
252
|
+
[ "$__cb_app" = "ln" ] || return 125
|
|
253
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_IPC_ADDRESS:-}" ] || return 125
|
|
254
|
+
[ -n "${CODEBUDDY_SANDBOX_BROKER_SESSION_ID:-}" ] || return 125
|
|
255
|
+
[ -n "${CODEBUDDY_SANDBOX_HOST_FILE_OPERATION_COMMAND:-}" ] || return 125
|
|
256
|
+
[ -f "$__cb_broker_client" ] || return 125
|
|
257
|
+
|
|
258
|
+
# Only simple ln [-s] SRC DEST is dispatched; other flags fall back to toybox.
|
|
259
|
+
NODE_OPTIONS= "${CODEBUDDY_NODE_BIN:-node}" - "$__cb_broker_client" "$@" <<'NODE'
|
|
260
|
+
const fs = require('fs');
|
|
261
|
+
const path = require('path');
|
|
262
|
+
const { sendBrokerRequestSync } = require(process.argv[2]);
|
|
263
|
+
|
|
264
|
+
const args = process.argv.slice(3);
|
|
265
|
+
let symbolic = false;
|
|
266
|
+
let afterOptions = false;
|
|
267
|
+
const operands = [];
|
|
268
|
+
|
|
269
|
+
for (const arg of args) {
|
|
270
|
+
if (afterOptions) {
|
|
271
|
+
operands.push(arg);
|
|
272
|
+
continue;
|
|
273
|
+
}
|
|
274
|
+
if (arg === '--') {
|
|
275
|
+
afterOptions = true;
|
|
276
|
+
continue;
|
|
277
|
+
}
|
|
278
|
+
if (arg === '-s' || arg === '--symbolic') {
|
|
279
|
+
symbolic = true;
|
|
280
|
+
continue;
|
|
281
|
+
}
|
|
282
|
+
if (arg.startsWith('-')) {
|
|
283
|
+
process.exit(125);
|
|
284
|
+
}
|
|
285
|
+
operands.push(arg);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (operands.length !== 2) {
|
|
289
|
+
process.exit(125);
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
const [fromArg, toArg] = operands;
|
|
293
|
+
const toPath = path.resolve(process.cwd(), toArg);
|
|
294
|
+
const fromPath = symbolic ? fromArg : path.resolve(process.cwd(), fromArg);
|
|
295
|
+
let linkPath = toPath;
|
|
296
|
+
try {
|
|
297
|
+
if (fs.statSync(toPath).isDirectory()) {
|
|
298
|
+
linkPath = path.join(toPath, path.basename(fromArg));
|
|
299
|
+
}
|
|
300
|
+
} catch {
|
|
301
|
+
linkPath = toPath;
|
|
302
|
+
}
|
|
303
|
+
const response = sendBrokerRequestSync({
|
|
304
|
+
command: process.env.CODEBUDDY_SANDBOX_HOST_FILE_OPERATION_COMMAND,
|
|
305
|
+
operation: 'link',
|
|
306
|
+
from: fromPath,
|
|
307
|
+
to: linkPath,
|
|
308
|
+
symbolic,
|
|
309
|
+
sessionId: process.env.CODEBUDDY_SANDBOX_BROKER_SESSION_ID,
|
|
310
|
+
toolCallId: process.env.CODEBUDDY_SANDBOX_BROKER_TOOL_CALL_ID,
|
|
311
|
+
brokerTraceId: process.env.CODEBUDDY_SANDBOX_BROKER_TRACE_ID,
|
|
312
|
+
runtime: 'toybox-dispatch',
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
if (response && response.ok === true) {
|
|
316
|
+
process.exit(0);
|
|
317
|
+
}
|
|
318
|
+
if (response && response.decision === 'sandbox') {
|
|
319
|
+
process.exit(125);
|
|
320
|
+
}
|
|
321
|
+
process.stderr.write(response && response.error ? response.error : 'Brokered link operation denied');
|
|
322
|
+
process.exit(13);
|
|
323
|
+
NODE
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
# rm/rmdir/unlink 在沙箱模式下由 toybox 原生实现直接执行,不会经过
|
|
327
|
+
# safe-bin/rm,因此批量删除审批(safe-delete-bulk-guard.cjs)在这里补一次,
|
|
328
|
+
# 与 node-safe-delete-shim.cjs / sitecustomize.py 里的调用方式保持一致。
|
|
329
|
+
__cb_bulk_guard_delete_check() {
|
|
330
|
+
case "$__cb_app" in
|
|
331
|
+
rm|rmdir|unlink) ;;
|
|
332
|
+
*) return 0 ;;
|
|
333
|
+
esac
|
|
334
|
+
__cb_bg_common_sh="${__cb_brokered_dir%/brokered-bin}/safe-bin/safe-delete-common.sh"
|
|
335
|
+
[ -f "$__cb_bg_common_sh" ] || return 0
|
|
336
|
+
|
|
337
|
+
__cb_bg_targets=()
|
|
338
|
+
__cb_bg_after_dd=
|
|
339
|
+
for __cb_bg_arg in "$@"; do
|
|
340
|
+
if [ -n "$__cb_bg_after_dd" ]; then
|
|
341
|
+
__cb_bg_targets+=("$__cb_bg_arg")
|
|
342
|
+
continue
|
|
343
|
+
fi
|
|
344
|
+
case "$__cb_bg_arg" in
|
|
345
|
+
--) __cb_bg_after_dd=1 ;;
|
|
346
|
+
-*) ;;
|
|
347
|
+
*) __cb_bg_targets+=("$__cb_bg_arg") ;;
|
|
348
|
+
esac
|
|
349
|
+
done
|
|
350
|
+
[ "${#__cb_bg_targets[@]}" -gt 0 ] || return 0
|
|
351
|
+
|
|
352
|
+
# shellcheck source=/dev/null
|
|
353
|
+
. "$__cb_bg_common_sh"
|
|
354
|
+
safe_delete_bulk_guard_non_tmp_check "${__cb_bg_targets[@]}"
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
if [ -z "$__cb_toybox" ] || [ ! -x "$__cb_toybox" ]; then __cb_fallback "$@"; exit $?; fi
|
|
358
|
+
|
|
359
|
+
__cb_bulk_guard_delete_check "$@" || exit $?
|
|
360
|
+
__cb_prebackup_targets "$@" || exit $?
|
|
361
|
+
__cb_host_op_ln "$@"
|
|
362
|
+
__cb_host_op_status=$?
|
|
363
|
+
if [ "$__cb_host_op_status" -eq 0 ]; then exit 0; fi
|
|
364
|
+
if [ "$__cb_host_op_status" -ne 125 ]; then exit "$__cb_host_op_status"; fi
|
|
365
|
+
|
|
366
|
+
__cb_err="$(/usr/bin/mktemp "${TMPDIR:-/tmp}/codebuddy-toybox.XXXXXX" 2>/dev/null || mktemp "${TMPDIR:-/tmp}/codebuddy-toybox.XXXXXX" 2>/dev/null)"
|
|
367
|
+
if [ -z "${__cb_err:-}" ]; then CODEBUDDY_TOYBOX_DISPATCH_ACTIVE="$__cb_app" exec "$__cb_toybox" "$__cb_app" "$@"; fi
|
|
368
|
+
|
|
369
|
+
CODEBUDDY_TOYBOX_DISPATCH_ACTIVE="$__cb_app" "$__cb_toybox" "$__cb_app" "$@" 2>"$__cb_err"
|
|
370
|
+
__cb_status=$?
|
|
371
|
+
if [ "$__cb_status" -eq 0 ]; then [ ! -s "$__cb_err" ] || /bin/cat "$__cb_err" >&2 2>/dev/null || true; __cb_cleanup; exit 0; fi
|
|
372
|
+
|
|
373
|
+
__cb_msg="$(/bin/cat "$__cb_err" 2>/dev/null || true)"
|
|
374
|
+
if __cb_should_fallback "$__cb_msg"; then
|
|
375
|
+
__cb_cleanup; __cb_fallback "$@"
|
|
376
|
+
exit $?
|
|
377
|
+
fi
|
|
378
|
+
|
|
379
|
+
[ -z "$__cb_msg" ] || printf '%s' "$__cb_msg" >&2
|
|
380
|
+
__cb_cleanup
|
|
381
|
+
exit "$__cb_status"
|