codexmate 0.0.27 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +421 -421
- package/README.zh.md +354 -354
- package/cli/agents-files.js +224 -224
- package/cli/archive-helpers.js +446 -446
- package/cli/auth-profiles.js +375 -375
- package/cli/builtin-proxy.js +1620 -1299
- package/cli/claude-proxy.js +1022 -1022
- package/cli/config-bootstrap.js +384 -384
- package/cli/config-health.js +338 -338
- package/cli/doctor-core.js +903 -903
- package/cli/import-skills-url.js +356 -356
- package/cli/openai-bridge.js +1489 -1091
- package/cli/openclaw-config.js +629 -629
- package/cli/session-convert-args.js +65 -65
- package/cli/session-convert-io.js +82 -82
- package/cli/session-convert.js +43 -43
- package/cli/session-usage.concurrent.js +28 -28
- package/cli/session-usage.js +118 -118
- package/cli/session-usage.models.js +176 -176
- package/cli/skills.js +1141 -1141
- package/cli/zip-commands.js +510 -510
- package/cli.js +15264 -15251
- package/lib/automation.js +404 -404
- package/lib/cli-file-utils.js +151 -151
- package/lib/cli-models-utils.js +440 -379
- package/lib/cli-network-utils.js +190 -190
- package/lib/cli-path-utils.js +85 -85
- package/lib/cli-session-utils.js +121 -121
- package/lib/cli-sessions.js +417 -417
- package/lib/cli-utils.js +155 -155
- package/lib/download-artifacts.js +92 -92
- package/lib/mcp-stdio.js +453 -453
- package/lib/task-orchestrator.js +869 -869
- package/lib/text-diff.js +303 -303
- package/lib/workflow-engine.js +340 -340
- package/package.json +3 -1
- package/plugins/README.md +20 -20
- package/plugins/README.zh-CN.md +20 -20
- package/plugins/prompt-templates/comment-polish/index.mjs +25 -25
- package/plugins/prompt-templates/computed.mjs +253 -253
- package/plugins/prompt-templates/index.mjs +8 -8
- package/plugins/prompt-templates/manifest.mjs +15 -15
- package/plugins/prompt-templates/methods.mjs +553 -619
- package/plugins/prompt-templates/overview.mjs +91 -90
- package/plugins/prompt-templates/ownership.mjs +19 -19
- package/plugins/prompt-templates/rule-ack/index.mjs +21 -21
- package/plugins/prompt-templates/storage.mjs +64 -64
- package/plugins/registry.mjs +16 -16
- package/web-ui/app.js +625 -634
- package/web-ui/index.html +35 -35
- package/web-ui/logic.agents-diff.mjs +386 -386
- package/web-ui/logic.claude.mjs +168 -168
- package/web-ui/logic.codex.mjs +56 -0
- package/web-ui/logic.mjs +5 -5
- package/web-ui/logic.runtime.mjs +128 -128
- package/web-ui/logic.session-convert.mjs +70 -70
- package/web-ui/logic.sessions.mjs +765 -765
- package/web-ui/modules/api.mjs +90 -90
- package/web-ui/modules/app.computed.dashboard.mjs +225 -171
- package/web-ui/modules/app.computed.index.mjs +17 -17
- package/web-ui/modules/app.computed.main-tabs.mjs +205 -205
- package/web-ui/modules/app.computed.session.mjs +994 -994
- package/web-ui/modules/app.constants.mjs +15 -15
- package/web-ui/modules/app.methods.agents.mjs +632 -632
- package/web-ui/modules/app.methods.claude-config.mjs +190 -184
- package/web-ui/modules/app.methods.codex-config.mjs +892 -860
- package/web-ui/modules/app.methods.index.mjs +92 -92
- package/web-ui/modules/app.methods.install.mjs +205 -205
- package/web-ui/modules/app.methods.navigation.mjs +743 -743
- package/web-ui/modules/app.methods.openclaw-core.mjs +814 -814
- package/web-ui/modules/app.methods.openclaw-editing.mjs +372 -372
- package/web-ui/modules/app.methods.openclaw-persist.mjs +369 -369
- package/web-ui/modules/app.methods.providers.mjs +412 -404
- package/web-ui/modules/app.methods.runtime.mjs +345 -345
- package/web-ui/modules/app.methods.session-actions.mjs +593 -596
- package/web-ui/modules/app.methods.session-browser.mjs +984 -989
- package/web-ui/modules/app.methods.session-timeline.mjs +479 -479
- package/web-ui/modules/app.methods.session-trash.mjs +439 -439
- package/web-ui/modules/app.methods.startup-claude.mjs +533 -526
- package/web-ui/modules/app.methods.task-orchestration.mjs +556 -556
- package/web-ui/modules/config-mode.computed.mjs +124 -124
- package/web-ui/modules/config-template-confirm-pref.mjs +33 -33
- package/web-ui/modules/i18n.dict.mjs +2109 -2131
- package/web-ui/modules/i18n.mjs +56 -56
- package/web-ui/modules/plugins.computed.mjs +3 -3
- package/web-ui/modules/plugins.methods.mjs +3 -3
- package/web-ui/modules/plugins.storage.mjs +11 -11
- package/web-ui/modules/provider-url-display.mjs +17 -0
- package/web-ui/modules/sessions-filters-url.mjs +85 -85
- package/web-ui/modules/skills.computed.mjs +107 -107
- package/web-ui/modules/skills.methods.mjs +481 -481
- package/web-ui/partials/index/layout-footer.html +13 -13
- package/web-ui/partials/index/layout-header.html +475 -475
- package/web-ui/partials/index/modal-config-template-agents.html +174 -174
- package/web-ui/partials/index/modal-confirm-toast.html +32 -32
- package/web-ui/partials/index/modal-health-check.html +45 -45
- package/web-ui/partials/index/modal-openclaw-config.html +280 -280
- package/web-ui/partials/index/modal-skills.html +200 -200
- package/web-ui/partials/index/modals-basic.html +165 -165
- package/web-ui/partials/index/panel-config-claude.html +188 -187
- package/web-ui/partials/index/panel-config-codex.html +312 -283
- package/web-ui/partials/index/panel-config-openclaw.html +83 -83
- package/web-ui/partials/index/panel-dashboard.html +186 -186
- package/web-ui/partials/index/panel-docs.html +147 -147
- package/web-ui/partials/index/panel-market.html +177 -177
- package/web-ui/partials/index/panel-orchestration.html +391 -391
- package/web-ui/partials/index/panel-plugins.html +253 -279
- package/web-ui/partials/index/panel-sessions.html +316 -326
- package/web-ui/partials/index/panel-settings.html +253 -274
- package/web-ui/partials/index/panel-usage.html +371 -371
- package/web-ui/res/json5.min.js +1 -1
- package/web-ui/res/vue.global.prod.js +13 -13
- package/web-ui/session-helpers.mjs +576 -576
- package/web-ui/source-bundle.cjs +233 -233
- package/web-ui/styles/base-theme.css +281 -268
- package/web-ui/styles/controls-forms.css +422 -423
- package/web-ui/styles/dashboard.css +274 -274
- package/web-ui/styles/docs-panel.css +247 -247
- package/web-ui/styles/feedback.css +108 -108
- package/web-ui/styles/health-check-dialog.css +144 -144
- package/web-ui/styles/layout-shell.css +606 -603
- package/web-ui/styles/modals-core.css +466 -464
- package/web-ui/styles/navigation-panels.css +391 -390
- package/web-ui/styles/openclaw-structured.css +266 -266
- package/web-ui/styles/plugins-panel.css +523 -523
- package/web-ui/styles/responsive.css +454 -454
- package/web-ui/styles/sessions-list.css +419 -415
- package/web-ui/styles/sessions-preview.css +411 -411
- package/web-ui/styles/sessions-toolbar-trash.css +330 -330
- package/web-ui/styles/sessions-usage.css +1040 -1040
- package/web-ui/styles/settings-panel.css +185 -185
- package/web-ui/styles/skills-list.css +303 -303
- package/web-ui/styles/skills-market.css +406 -406
- package/web-ui/styles/task-orchestration.css +822 -822
- package/web-ui/styles/titles-cards.css +472 -408
- package/web-ui/styles.css +21 -21
- package/web-ui.html +17 -17
package/lib/cli-network-utils.js
CHANGED
|
@@ -1,190 +1,190 @@
|
|
|
1
|
-
const http = require('http');
|
|
2
|
-
const https = require('https');
|
|
3
|
-
|
|
4
|
-
function shouldRetryWithIpv4(result) {
|
|
5
|
-
if (!result || result.ok || typeof result.error !== 'string') {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
return /timeout|timed out|ETIMEDOUT|ENETUNREACH|EHOSTUNREACH|EAI_AGAIN/i.test(result.error);
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
function performProbeRequest(transport, parsed, requestOptions, options = {}) {
|
|
12
|
-
return new Promise((resolve) => {
|
|
13
|
-
const start = Date.now();
|
|
14
|
-
const req = transport.request(parsed, requestOptions, (res) => {
|
|
15
|
-
const chunks = [];
|
|
16
|
-
let size = 0;
|
|
17
|
-
res.on('data', (chunk) => {
|
|
18
|
-
if (!chunk) return;
|
|
19
|
-
size += chunk.length;
|
|
20
|
-
if (size <= options.maxBytes) {
|
|
21
|
-
chunks.push(chunk);
|
|
22
|
-
}
|
|
23
|
-
});
|
|
24
|
-
res.on('end', () => {
|
|
25
|
-
resolve({
|
|
26
|
-
ok: true,
|
|
27
|
-
status: res.statusCode || 0,
|
|
28
|
-
durationMs: Date.now() - start,
|
|
29
|
-
body: chunks.length > 0 ? Buffer.concat(chunks).toString('utf-8') : ''
|
|
30
|
-
});
|
|
31
|
-
});
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
if (options.timeoutMs > 0) {
|
|
35
|
-
req.setTimeout(options.timeoutMs, () => {
|
|
36
|
-
req.destroy(new Error('timeout'));
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
req.on('error', (err) => {
|
|
41
|
-
resolve({
|
|
42
|
-
ok: false,
|
|
43
|
-
error: err.message || 'request failed',
|
|
44
|
-
durationMs: Date.now() - start
|
|
45
|
-
});
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
if (options.payload) {
|
|
49
|
-
req.write(options.payload);
|
|
50
|
-
}
|
|
51
|
-
req.end();
|
|
52
|
-
});
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
async function probeUrl(targetUrl, options = {}) {
|
|
56
|
-
let parsed;
|
|
57
|
-
try {
|
|
58
|
-
parsed = new URL(targetUrl);
|
|
59
|
-
} catch (e) {
|
|
60
|
-
return { ok: false, error: 'Invalid URL' };
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
const protocol = parsed.protocol;
|
|
64
|
-
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
65
|
-
return {
|
|
66
|
-
ok: false,
|
|
67
|
-
error: `ERR_INVALID_PROTOCOL: Protocol "${protocol}" not supported. Expected "http:" or "https:"`
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
const transport = protocol === 'https:' ? https : http;
|
|
72
|
-
const headers = {
|
|
73
|
-
'User-Agent': 'codexmate-health-check',
|
|
74
|
-
'Accept': 'application/json'
|
|
75
|
-
};
|
|
76
|
-
if (options.headers && typeof options.headers === 'object') {
|
|
77
|
-
for (const [key, value] of Object.entries(options.headers)) {
|
|
78
|
-
if (value === undefined || value === null) continue;
|
|
79
|
-
headers[key] = String(value);
|
|
80
|
-
}
|
|
81
|
-
}
|
|
82
|
-
if (options.apiKey) {
|
|
83
|
-
const apiKeyHeader = typeof options.apiKeyHeader === 'string' ? options.apiKeyHeader.trim() : '';
|
|
84
|
-
if (apiKeyHeader) {
|
|
85
|
-
if (headers[apiKeyHeader] === undefined) {
|
|
86
|
-
headers[apiKeyHeader] = String(options.apiKey);
|
|
87
|
-
}
|
|
88
|
-
} else if (headers.Authorization === undefined) {
|
|
89
|
-
headers['Authorization'] = `Bearer ${options.apiKey}`;
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 0;
|
|
94
|
-
const maxBytes = Number.isFinite(options.maxBytes) ? options.maxBytes : 256 * 1024;
|
|
95
|
-
const requestOptions = {
|
|
96
|
-
method: 'GET',
|
|
97
|
-
headers
|
|
98
|
-
};
|
|
99
|
-
|
|
100
|
-
const firstResult = await performProbeRequest(transport, parsed, requestOptions, {
|
|
101
|
-
timeoutMs,
|
|
102
|
-
maxBytes
|
|
103
|
-
});
|
|
104
|
-
if (!shouldRetryWithIpv4(firstResult)) {
|
|
105
|
-
return firstResult;
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
const secondResult = await performProbeRequest(transport, parsed, {
|
|
109
|
-
...requestOptions,
|
|
110
|
-
family: 4
|
|
111
|
-
}, {
|
|
112
|
-
timeoutMs,
|
|
113
|
-
maxBytes
|
|
114
|
-
});
|
|
115
|
-
return secondResult.ok ? secondResult : firstResult;
|
|
116
|
-
}
|
|
117
|
-
|
|
118
|
-
async function probeJsonPost(targetUrl, body, options = {}) {
|
|
119
|
-
let parsed;
|
|
120
|
-
try {
|
|
121
|
-
parsed = new URL(targetUrl);
|
|
122
|
-
} catch (e) {
|
|
123
|
-
return { ok: false, error: 'Invalid URL' };
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const protocol = parsed.protocol;
|
|
127
|
-
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
128
|
-
return {
|
|
129
|
-
ok: false,
|
|
130
|
-
error: `ERR_INVALID_PROTOCOL: Protocol "${protocol}" not supported. Expected "http:" or "https:"`
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
const transport = protocol === 'https:' ? https : http;
|
|
135
|
-
const headers = {
|
|
136
|
-
'User-Agent': 'codexmate-health-check',
|
|
137
|
-
'Accept': 'application/json',
|
|
138
|
-
'Content-Type': 'application/json'
|
|
139
|
-
};
|
|
140
|
-
if (options.headers && typeof options.headers === 'object') {
|
|
141
|
-
for (const [key, value] of Object.entries(options.headers)) {
|
|
142
|
-
if (value === undefined || value === null) continue;
|
|
143
|
-
headers[key] = String(value);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
if (options.apiKey) {
|
|
147
|
-
const apiKeyHeader = typeof options.apiKeyHeader === 'string' ? options.apiKeyHeader.trim() : '';
|
|
148
|
-
if (apiKeyHeader) {
|
|
149
|
-
if (headers[apiKeyHeader] === undefined) {
|
|
150
|
-
headers[apiKeyHeader] = String(options.apiKey);
|
|
151
|
-
}
|
|
152
|
-
} else if (headers.Authorization === undefined) {
|
|
153
|
-
headers['Authorization'] = `Bearer ${options.apiKey}`;
|
|
154
|
-
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
const payload = JSON.stringify(body || {});
|
|
158
|
-
headers['Content-Length'] = Buffer.byteLength(payload);
|
|
159
|
-
|
|
160
|
-
const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 0;
|
|
161
|
-
const maxBytes = Number.isFinite(options.maxBytes) ? options.maxBytes : 256 * 1024;
|
|
162
|
-
const requestOptions = {
|
|
163
|
-
method: 'POST',
|
|
164
|
-
headers
|
|
165
|
-
};
|
|
166
|
-
|
|
167
|
-
const firstResult = await performProbeRequest(transport, parsed, requestOptions, {
|
|
168
|
-
timeoutMs,
|
|
169
|
-
maxBytes,
|
|
170
|
-
payload
|
|
171
|
-
});
|
|
172
|
-
if (!shouldRetryWithIpv4(firstResult)) {
|
|
173
|
-
return firstResult;
|
|
174
|
-
}
|
|
175
|
-
|
|
176
|
-
const secondResult = await performProbeRequest(transport, parsed, {
|
|
177
|
-
...requestOptions,
|
|
178
|
-
family: 4
|
|
179
|
-
}, {
|
|
180
|
-
timeoutMs,
|
|
181
|
-
maxBytes,
|
|
182
|
-
payload
|
|
183
|
-
});
|
|
184
|
-
return secondResult.ok ? secondResult : firstResult;
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
module.exports = {
|
|
188
|
-
probeUrl,
|
|
189
|
-
probeJsonPost
|
|
190
|
-
};
|
|
1
|
+
const http = require('http');
|
|
2
|
+
const https = require('https');
|
|
3
|
+
|
|
4
|
+
function shouldRetryWithIpv4(result) {
|
|
5
|
+
if (!result || result.ok || typeof result.error !== 'string') {
|
|
6
|
+
return false;
|
|
7
|
+
}
|
|
8
|
+
return /timeout|timed out|ETIMEDOUT|ENETUNREACH|EHOSTUNREACH|EAI_AGAIN/i.test(result.error);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
function performProbeRequest(transport, parsed, requestOptions, options = {}) {
|
|
12
|
+
return new Promise((resolve) => {
|
|
13
|
+
const start = Date.now();
|
|
14
|
+
const req = transport.request(parsed, requestOptions, (res) => {
|
|
15
|
+
const chunks = [];
|
|
16
|
+
let size = 0;
|
|
17
|
+
res.on('data', (chunk) => {
|
|
18
|
+
if (!chunk) return;
|
|
19
|
+
size += chunk.length;
|
|
20
|
+
if (size <= options.maxBytes) {
|
|
21
|
+
chunks.push(chunk);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
res.on('end', () => {
|
|
25
|
+
resolve({
|
|
26
|
+
ok: true,
|
|
27
|
+
status: res.statusCode || 0,
|
|
28
|
+
durationMs: Date.now() - start,
|
|
29
|
+
body: chunks.length > 0 ? Buffer.concat(chunks).toString('utf-8') : ''
|
|
30
|
+
});
|
|
31
|
+
});
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
if (options.timeoutMs > 0) {
|
|
35
|
+
req.setTimeout(options.timeoutMs, () => {
|
|
36
|
+
req.destroy(new Error('timeout'));
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
req.on('error', (err) => {
|
|
41
|
+
resolve({
|
|
42
|
+
ok: false,
|
|
43
|
+
error: err.message || 'request failed',
|
|
44
|
+
durationMs: Date.now() - start
|
|
45
|
+
});
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
if (options.payload) {
|
|
49
|
+
req.write(options.payload);
|
|
50
|
+
}
|
|
51
|
+
req.end();
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function probeUrl(targetUrl, options = {}) {
|
|
56
|
+
let parsed;
|
|
57
|
+
try {
|
|
58
|
+
parsed = new URL(targetUrl);
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return { ok: false, error: 'Invalid URL' };
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const protocol = parsed.protocol;
|
|
64
|
+
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
error: `ERR_INVALID_PROTOCOL: Protocol "${protocol}" not supported. Expected "http:" or "https:"`
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
const transport = protocol === 'https:' ? https : http;
|
|
72
|
+
const headers = {
|
|
73
|
+
'User-Agent': 'codexmate-health-check',
|
|
74
|
+
'Accept': 'application/json'
|
|
75
|
+
};
|
|
76
|
+
if (options.headers && typeof options.headers === 'object') {
|
|
77
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
78
|
+
if (value === undefined || value === null) continue;
|
|
79
|
+
headers[key] = String(value);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
if (options.apiKey) {
|
|
83
|
+
const apiKeyHeader = typeof options.apiKeyHeader === 'string' ? options.apiKeyHeader.trim() : '';
|
|
84
|
+
if (apiKeyHeader) {
|
|
85
|
+
if (headers[apiKeyHeader] === undefined) {
|
|
86
|
+
headers[apiKeyHeader] = String(options.apiKey);
|
|
87
|
+
}
|
|
88
|
+
} else if (headers.Authorization === undefined) {
|
|
89
|
+
headers['Authorization'] = `Bearer ${options.apiKey}`;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 0;
|
|
94
|
+
const maxBytes = Number.isFinite(options.maxBytes) ? options.maxBytes : 256 * 1024;
|
|
95
|
+
const requestOptions = {
|
|
96
|
+
method: 'GET',
|
|
97
|
+
headers
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
const firstResult = await performProbeRequest(transport, parsed, requestOptions, {
|
|
101
|
+
timeoutMs,
|
|
102
|
+
maxBytes
|
|
103
|
+
});
|
|
104
|
+
if (!shouldRetryWithIpv4(firstResult)) {
|
|
105
|
+
return firstResult;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const secondResult = await performProbeRequest(transport, parsed, {
|
|
109
|
+
...requestOptions,
|
|
110
|
+
family: 4
|
|
111
|
+
}, {
|
|
112
|
+
timeoutMs,
|
|
113
|
+
maxBytes
|
|
114
|
+
});
|
|
115
|
+
return secondResult.ok ? secondResult : firstResult;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async function probeJsonPost(targetUrl, body, options = {}) {
|
|
119
|
+
let parsed;
|
|
120
|
+
try {
|
|
121
|
+
parsed = new URL(targetUrl);
|
|
122
|
+
} catch (e) {
|
|
123
|
+
return { ok: false, error: 'Invalid URL' };
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const protocol = parsed.protocol;
|
|
127
|
+
if (protocol !== 'http:' && protocol !== 'https:') {
|
|
128
|
+
return {
|
|
129
|
+
ok: false,
|
|
130
|
+
error: `ERR_INVALID_PROTOCOL: Protocol "${protocol}" not supported. Expected "http:" or "https:"`
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
const transport = protocol === 'https:' ? https : http;
|
|
135
|
+
const headers = {
|
|
136
|
+
'User-Agent': 'codexmate-health-check',
|
|
137
|
+
'Accept': 'application/json',
|
|
138
|
+
'Content-Type': 'application/json'
|
|
139
|
+
};
|
|
140
|
+
if (options.headers && typeof options.headers === 'object') {
|
|
141
|
+
for (const [key, value] of Object.entries(options.headers)) {
|
|
142
|
+
if (value === undefined || value === null) continue;
|
|
143
|
+
headers[key] = String(value);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if (options.apiKey) {
|
|
147
|
+
const apiKeyHeader = typeof options.apiKeyHeader === 'string' ? options.apiKeyHeader.trim() : '';
|
|
148
|
+
if (apiKeyHeader) {
|
|
149
|
+
if (headers[apiKeyHeader] === undefined) {
|
|
150
|
+
headers[apiKeyHeader] = String(options.apiKey);
|
|
151
|
+
}
|
|
152
|
+
} else if (headers.Authorization === undefined) {
|
|
153
|
+
headers['Authorization'] = `Bearer ${options.apiKey}`;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const payload = JSON.stringify(body || {});
|
|
158
|
+
headers['Content-Length'] = Buffer.byteLength(payload);
|
|
159
|
+
|
|
160
|
+
const timeoutMs = Number.isFinite(options.timeoutMs) ? options.timeoutMs : 0;
|
|
161
|
+
const maxBytes = Number.isFinite(options.maxBytes) ? options.maxBytes : 256 * 1024;
|
|
162
|
+
const requestOptions = {
|
|
163
|
+
method: 'POST',
|
|
164
|
+
headers
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
const firstResult = await performProbeRequest(transport, parsed, requestOptions, {
|
|
168
|
+
timeoutMs,
|
|
169
|
+
maxBytes,
|
|
170
|
+
payload
|
|
171
|
+
});
|
|
172
|
+
if (!shouldRetryWithIpv4(firstResult)) {
|
|
173
|
+
return firstResult;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const secondResult = await performProbeRequest(transport, parsed, {
|
|
177
|
+
...requestOptions,
|
|
178
|
+
family: 4
|
|
179
|
+
}, {
|
|
180
|
+
timeoutMs,
|
|
181
|
+
maxBytes,
|
|
182
|
+
payload
|
|
183
|
+
});
|
|
184
|
+
return secondResult.ok ? secondResult : firstResult;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
module.exports = {
|
|
188
|
+
probeUrl,
|
|
189
|
+
probeJsonPost
|
|
190
|
+
};
|
package/lib/cli-path-utils.js
CHANGED
|
@@ -1,85 +1,85 @@
|
|
|
1
|
-
const fs = require('fs');
|
|
2
|
-
const path = require('path');
|
|
3
|
-
const { spawnSync } = require('child_process');
|
|
4
|
-
|
|
5
|
-
function normalizePathForCompare(targetPath, options = {}) {
|
|
6
|
-
const ignoreCase = !!options.ignoreCase;
|
|
7
|
-
let resolved = '';
|
|
8
|
-
try {
|
|
9
|
-
resolved = fs.realpathSync.native ? fs.realpathSync.native(targetPath) : fs.realpathSync(targetPath);
|
|
10
|
-
} catch (e) {
|
|
11
|
-
resolved = path.resolve(targetPath);
|
|
12
|
-
}
|
|
13
|
-
return ignoreCase ? resolved.toLowerCase() : resolved;
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
function isPathInside(targetPath, rootPath) {
|
|
17
|
-
if (!targetPath || !rootPath) {
|
|
18
|
-
return false;
|
|
19
|
-
}
|
|
20
|
-
const ignoreCase = process.platform === 'win32';
|
|
21
|
-
const resolvedTarget = normalizePathForCompare(targetPath, { ignoreCase });
|
|
22
|
-
const resolvedRoot = normalizePathForCompare(rootPath, { ignoreCase });
|
|
23
|
-
if (resolvedTarget === resolvedRoot) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
const separator = resolvedRoot.includes('/') && !resolvedRoot.includes('\\') ? '/' : path.sep;
|
|
27
|
-
const rootWithSlash = resolvedRoot.endsWith(separator) ? resolvedRoot : resolvedRoot + separator;
|
|
28
|
-
return resolvedTarget.startsWith(rootWithSlash);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
function resolveCopyTargetRoot(targetDir) {
|
|
32
|
-
const base = typeof targetDir === 'string' ? targetDir.trim() : '';
|
|
33
|
-
const pathApi = base.includes('/') && !base.includes('\\') && path.posix ? path.posix : path;
|
|
34
|
-
const suffixSegments = [];
|
|
35
|
-
let current = pathApi.resolve(base || '');
|
|
36
|
-
while (current && !fs.existsSync(current)) {
|
|
37
|
-
const parent = pathApi.dirname(current);
|
|
38
|
-
if (!parent || parent === current) {
|
|
39
|
-
break;
|
|
40
|
-
}
|
|
41
|
-
suffixSegments.unshift(pathApi.basename(current));
|
|
42
|
-
current = parent;
|
|
43
|
-
}
|
|
44
|
-
let resolvedRoot = normalizePathForCompare(current || base);
|
|
45
|
-
if (!resolvedRoot) {
|
|
46
|
-
resolvedRoot = pathApi.resolve(base || '');
|
|
47
|
-
}
|
|
48
|
-
for (const segment of suffixSegments) {
|
|
49
|
-
resolvedRoot = pathApi.join(resolvedRoot, segment);
|
|
50
|
-
}
|
|
51
|
-
return resolvedRoot;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
function commandExists(command, args = '') {
|
|
55
|
-
const cmd = typeof command === 'string' ? command.trim() : '';
|
|
56
|
-
const argText = typeof args === 'string' ? args.trim() : '';
|
|
57
|
-
if (!cmd || cmd.includes('\0') || /[\r\n]/.test(cmd)) {
|
|
58
|
-
return false;
|
|
59
|
-
}
|
|
60
|
-
const argv = argText ? argText.split(/\s+/g).filter(Boolean) : [];
|
|
61
|
-
const hasSeparators = cmd.includes('/') || cmd.includes('\\');
|
|
62
|
-
const useShell = process.platform === 'win32' && !hasSeparators;
|
|
63
|
-
if (useShell) {
|
|
64
|
-
if (!/^[A-Za-z0-9._-]+$/.test(cmd)) return false;
|
|
65
|
-
if (argText && /[\r\n;&|<>`$]/.test(argText)) return false;
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
const probe = spawnSync(cmd, argv, {
|
|
69
|
-
stdio: 'ignore',
|
|
70
|
-
windowsHide: true,
|
|
71
|
-
timeout: 5000,
|
|
72
|
-
shell: useShell
|
|
73
|
-
});
|
|
74
|
-
return probe.status === 0;
|
|
75
|
-
} catch (_) {
|
|
76
|
-
return false;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
module.exports = {
|
|
81
|
-
normalizePathForCompare,
|
|
82
|
-
isPathInside,
|
|
83
|
-
resolveCopyTargetRoot,
|
|
84
|
-
commandExists
|
|
85
|
-
};
|
|
1
|
+
const fs = require('fs');
|
|
2
|
+
const path = require('path');
|
|
3
|
+
const { spawnSync } = require('child_process');
|
|
4
|
+
|
|
5
|
+
function normalizePathForCompare(targetPath, options = {}) {
|
|
6
|
+
const ignoreCase = !!options.ignoreCase;
|
|
7
|
+
let resolved = '';
|
|
8
|
+
try {
|
|
9
|
+
resolved = fs.realpathSync.native ? fs.realpathSync.native(targetPath) : fs.realpathSync(targetPath);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
resolved = path.resolve(targetPath);
|
|
12
|
+
}
|
|
13
|
+
return ignoreCase ? resolved.toLowerCase() : resolved;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
function isPathInside(targetPath, rootPath) {
|
|
17
|
+
if (!targetPath || !rootPath) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
const ignoreCase = process.platform === 'win32';
|
|
21
|
+
const resolvedTarget = normalizePathForCompare(targetPath, { ignoreCase });
|
|
22
|
+
const resolvedRoot = normalizePathForCompare(rootPath, { ignoreCase });
|
|
23
|
+
if (resolvedTarget === resolvedRoot) {
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
const separator = resolvedRoot.includes('/') && !resolvedRoot.includes('\\') ? '/' : path.sep;
|
|
27
|
+
const rootWithSlash = resolvedRoot.endsWith(separator) ? resolvedRoot : resolvedRoot + separator;
|
|
28
|
+
return resolvedTarget.startsWith(rootWithSlash);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function resolveCopyTargetRoot(targetDir) {
|
|
32
|
+
const base = typeof targetDir === 'string' ? targetDir.trim() : '';
|
|
33
|
+
const pathApi = base.includes('/') && !base.includes('\\') && path.posix ? path.posix : path;
|
|
34
|
+
const suffixSegments = [];
|
|
35
|
+
let current = pathApi.resolve(base || '');
|
|
36
|
+
while (current && !fs.existsSync(current)) {
|
|
37
|
+
const parent = pathApi.dirname(current);
|
|
38
|
+
if (!parent || parent === current) {
|
|
39
|
+
break;
|
|
40
|
+
}
|
|
41
|
+
suffixSegments.unshift(pathApi.basename(current));
|
|
42
|
+
current = parent;
|
|
43
|
+
}
|
|
44
|
+
let resolvedRoot = normalizePathForCompare(current || base);
|
|
45
|
+
if (!resolvedRoot) {
|
|
46
|
+
resolvedRoot = pathApi.resolve(base || '');
|
|
47
|
+
}
|
|
48
|
+
for (const segment of suffixSegments) {
|
|
49
|
+
resolvedRoot = pathApi.join(resolvedRoot, segment);
|
|
50
|
+
}
|
|
51
|
+
return resolvedRoot;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
function commandExists(command, args = '') {
|
|
55
|
+
const cmd = typeof command === 'string' ? command.trim() : '';
|
|
56
|
+
const argText = typeof args === 'string' ? args.trim() : '';
|
|
57
|
+
if (!cmd || cmd.includes('\0') || /[\r\n]/.test(cmd)) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
const argv = argText ? argText.split(/\s+/g).filter(Boolean) : [];
|
|
61
|
+
const hasSeparators = cmd.includes('/') || cmd.includes('\\');
|
|
62
|
+
const useShell = process.platform === 'win32' && !hasSeparators;
|
|
63
|
+
if (useShell) {
|
|
64
|
+
if (!/^[A-Za-z0-9._-]+$/.test(cmd)) return false;
|
|
65
|
+
if (argText && /[\r\n;&|<>`$]/.test(argText)) return false;
|
|
66
|
+
}
|
|
67
|
+
try {
|
|
68
|
+
const probe = spawnSync(cmd, argv, {
|
|
69
|
+
stdio: 'ignore',
|
|
70
|
+
windowsHide: true,
|
|
71
|
+
timeout: 5000,
|
|
72
|
+
shell: useShell
|
|
73
|
+
});
|
|
74
|
+
return probe.status === 0;
|
|
75
|
+
} catch (_) {
|
|
76
|
+
return false;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = {
|
|
81
|
+
normalizePathForCompare,
|
|
82
|
+
isPathInside,
|
|
83
|
+
resolveCopyTargetRoot,
|
|
84
|
+
commandExists
|
|
85
|
+
};
|