codexmate 0.0.3 → 0.0.4
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/.github/workflows/release.yml +42 -42
- package/README.md +93 -74
- package/README.zh-CN.md +96 -77
- package/cli.js +237 -66
- package/cmd/publish-npm.cmd +65 -65
- package/package.json +27 -25
- package/res/screenshot.png +0 -0
- package/web-ui.html +494 -131
package/cli.js
CHANGED
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
const fs = require('fs');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
-
const toml = require('@iarna/toml');
|
|
5
|
+
const toml = require('@iarna/toml');
|
|
6
|
+
const JSON5 = require('json5');
|
|
6
7
|
const { exec, execSync } = require('child_process');
|
|
7
8
|
const http = require('http');
|
|
8
9
|
const https = require('https');
|
|
@@ -13,16 +14,19 @@ const PORT = 3737;
|
|
|
13
14
|
// ============================================================================
|
|
14
15
|
// 配置
|
|
15
16
|
// ============================================================================
|
|
16
|
-
const CONFIG_DIR = path.join(os.homedir(), '.codex');
|
|
17
|
-
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.toml');
|
|
18
|
-
const AUTH_FILE = path.join(CONFIG_DIR, 'auth.json');
|
|
19
|
-
const MODELS_FILE = path.join(CONFIG_DIR, 'models.json');
|
|
20
|
-
const CURRENT_MODELS_FILE = path.join(CONFIG_DIR, 'provider-current-models.json');
|
|
21
|
-
const INIT_MARK_FILE = path.join(CONFIG_DIR, 'codexmate-init.json');
|
|
22
|
-
const CODEX_SESSIONS_DIR = path.join(CONFIG_DIR, 'sessions');
|
|
23
|
-
const
|
|
24
|
-
const
|
|
25
|
-
const
|
|
17
|
+
const CONFIG_DIR = path.join(os.homedir(), '.codex');
|
|
18
|
+
const CONFIG_FILE = path.join(CONFIG_DIR, 'config.toml');
|
|
19
|
+
const AUTH_FILE = path.join(CONFIG_DIR, 'auth.json');
|
|
20
|
+
const MODELS_FILE = path.join(CONFIG_DIR, 'models.json');
|
|
21
|
+
const CURRENT_MODELS_FILE = path.join(CONFIG_DIR, 'provider-current-models.json');
|
|
22
|
+
const INIT_MARK_FILE = path.join(CONFIG_DIR, 'codexmate-init.json');
|
|
23
|
+
const CODEX_SESSIONS_DIR = path.join(CONFIG_DIR, 'sessions');
|
|
24
|
+
const OPENCLAW_DIR = path.join(os.homedir(), '.openclaw');
|
|
25
|
+
const OPENCLAW_CONFIG_FILE = path.join(OPENCLAW_DIR, 'openclaw.json');
|
|
26
|
+
const OPENCLAW_WORKSPACE_DIR = path.join(OPENCLAW_DIR, 'workspace');
|
|
27
|
+
const CLAUDE_DIR = path.join(os.homedir(), '.claude');
|
|
28
|
+
const CLAUDE_SETTINGS_FILE = path.join(CLAUDE_DIR, 'settings.json');
|
|
29
|
+
const CLAUDE_PROJECTS_DIR = path.join(os.homedir(), '.claude', 'projects');
|
|
26
30
|
|
|
27
31
|
const DEFAULT_MODELS = ['gpt-5.3-codex', 'gpt-5.1-codex-max', 'gpt-4-turbo', 'gpt-4'];
|
|
28
32
|
const SPEED_TEST_TIMEOUT_MS = 8000;
|
|
@@ -34,8 +38,8 @@ const SESSION_TITLE_READ_BYTES = 64 * 1024;
|
|
|
34
38
|
const CODEXMATE_MANAGED_MARKER = '# codexmate-managed: true';
|
|
35
39
|
const SESSION_LIST_CACHE_TTL_MS = 4000;
|
|
36
40
|
const SESSION_SUMMARY_READ_BYTES = 256 * 1024;
|
|
37
|
-
const SESSION_CONTENT_READ_BYTES = SESSION_SUMMARY_READ_BYTES;
|
|
38
|
-
const DEFAULT_CONTENT_SCAN_LIMIT = 10;
|
|
41
|
+
const SESSION_CONTENT_READ_BYTES = SESSION_SUMMARY_READ_BYTES;
|
|
42
|
+
const DEFAULT_CONTENT_SCAN_LIMIT = 10;
|
|
39
43
|
const SESSION_SCAN_FACTOR = 4;
|
|
40
44
|
const SESSION_SCAN_MIN_FILES = 800;
|
|
41
45
|
const MAX_SESSION_PATH_LIST_SIZE = 2000;
|
|
@@ -228,11 +232,11 @@ function readAgentsFile(params = {}) {
|
|
|
228
232
|
}
|
|
229
233
|
}
|
|
230
234
|
|
|
231
|
-
function applyAgentsFile(params = {}) {
|
|
232
|
-
const filePath = resolveAgentsFilePath(params);
|
|
233
|
-
const dirCheck = validateAgentsBaseDir(filePath);
|
|
234
|
-
if (dirCheck.error) {
|
|
235
|
-
return { error: dirCheck.error };
|
|
235
|
+
function applyAgentsFile(params = {}) {
|
|
236
|
+
const filePath = resolveAgentsFilePath(params);
|
|
237
|
+
const dirCheck = validateAgentsBaseDir(filePath);
|
|
238
|
+
if (dirCheck.error) {
|
|
239
|
+
return { error: dirCheck.error };
|
|
236
240
|
}
|
|
237
241
|
|
|
238
242
|
const content = typeof params.content === 'string' ? params.content : '';
|
|
@@ -243,10 +247,165 @@ function applyAgentsFile(params = {}) {
|
|
|
243
247
|
try {
|
|
244
248
|
fs.writeFileSync(filePath, finalContent, 'utf-8');
|
|
245
249
|
return { success: true, path: filePath };
|
|
246
|
-
} catch (e) {
|
|
247
|
-
return { error: `写入 AGENTS.md 失败: ${e.message}` };
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
+
} catch (e) {
|
|
251
|
+
return { error: `写入 AGENTS.md 失败: ${e.message}` };
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function resolveHomePath(input) {
|
|
256
|
+
const raw = typeof input === 'string' ? input.trim() : '';
|
|
257
|
+
if (!raw) return '';
|
|
258
|
+
if (raw === '~') return os.homedir();
|
|
259
|
+
if (raw.startsWith('~/') || raw.startsWith('~\\')) {
|
|
260
|
+
return path.join(os.homedir(), raw.slice(2));
|
|
261
|
+
}
|
|
262
|
+
return raw;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function resolveOpenclawWorkspaceDir(config) {
|
|
266
|
+
const workspace = config
|
|
267
|
+
&& config.agents
|
|
268
|
+
&& config.agents.defaults
|
|
269
|
+
&& typeof config.agents.defaults.workspace === 'string'
|
|
270
|
+
? config.agents.defaults.workspace
|
|
271
|
+
: '';
|
|
272
|
+
const resolved = resolveHomePath(workspace);
|
|
273
|
+
if (!resolved) {
|
|
274
|
+
return OPENCLAW_WORKSPACE_DIR;
|
|
275
|
+
}
|
|
276
|
+
if (path.isAbsolute(resolved)) {
|
|
277
|
+
return resolved;
|
|
278
|
+
}
|
|
279
|
+
return path.join(OPENCLAW_DIR, resolved);
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
function readOpenclawConfigFile() {
|
|
283
|
+
const filePath = OPENCLAW_CONFIG_FILE;
|
|
284
|
+
if (!fs.existsSync(filePath)) {
|
|
285
|
+
return {
|
|
286
|
+
exists: false,
|
|
287
|
+
path: filePath,
|
|
288
|
+
content: '',
|
|
289
|
+
lineEnding: os.EOL === '\r\n' ? '\r\n' : '\n'
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
try {
|
|
294
|
+
const raw = fs.readFileSync(filePath, 'utf-8');
|
|
295
|
+
return {
|
|
296
|
+
exists: true,
|
|
297
|
+
path: filePath,
|
|
298
|
+
content: stripUtf8Bom(raw),
|
|
299
|
+
lineEnding: detectLineEnding(raw)
|
|
300
|
+
};
|
|
301
|
+
} catch (e) {
|
|
302
|
+
return { error: `读取 OpenClaw 配置失败: ${e.message}` };
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function parseOpenclawConfigText(content) {
|
|
307
|
+
const raw = stripUtf8Bom(typeof content === 'string' ? content : '');
|
|
308
|
+
if (!raw.trim()) {
|
|
309
|
+
return { ok: false, error: 'OpenClaw 配置内容不能为空' };
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
const parsed = JSON5.parse(raw);
|
|
313
|
+
if (!parsed || typeof parsed !== 'object' || Array.isArray(parsed)) {
|
|
314
|
+
return { ok: false, error: '配置格式错误(根节点必须是对象)' };
|
|
315
|
+
}
|
|
316
|
+
return { ok: true, data: parsed };
|
|
317
|
+
} catch (e) {
|
|
318
|
+
return { ok: false, error: `配置解析失败: ${e.message}` };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
function getOpenclawWorkspaceInfo() {
|
|
323
|
+
const readResult = readOpenclawConfigFile();
|
|
324
|
+
let workspaceDir = OPENCLAW_WORKSPACE_DIR;
|
|
325
|
+
let configError = readResult.error || '';
|
|
326
|
+
if (!configError && readResult.exists && readResult.content.trim()) {
|
|
327
|
+
const parsed = parseOpenclawConfigText(readResult.content);
|
|
328
|
+
if (parsed.ok) {
|
|
329
|
+
workspaceDir = resolveOpenclawWorkspaceDir(parsed.data);
|
|
330
|
+
} else {
|
|
331
|
+
configError = parsed.error || '';
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return {
|
|
335
|
+
workspaceDir,
|
|
336
|
+
configError,
|
|
337
|
+
configPath: readResult.path || OPENCLAW_CONFIG_FILE
|
|
338
|
+
};
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
function readOpenclawAgentsFile() {
|
|
342
|
+
const workspaceInfo = getOpenclawWorkspaceInfo();
|
|
343
|
+
const baseDir = workspaceInfo.workspaceDir;
|
|
344
|
+
const filePath = path.join(baseDir, AGENTS_FILE_NAME);
|
|
345
|
+
|
|
346
|
+
if (!fs.existsSync(baseDir)) {
|
|
347
|
+
return {
|
|
348
|
+
exists: false,
|
|
349
|
+
path: filePath,
|
|
350
|
+
content: '',
|
|
351
|
+
lineEnding: os.EOL === '\r\n' ? '\r\n' : '\n',
|
|
352
|
+
workspaceDir: baseDir,
|
|
353
|
+
configError: workspaceInfo.configError,
|
|
354
|
+
baseDirMissing: true
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
const readResult = readAgentsFile({ baseDir });
|
|
359
|
+
return {
|
|
360
|
+
...readResult,
|
|
361
|
+
workspaceDir: baseDir,
|
|
362
|
+
configError: workspaceInfo.configError
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function applyOpenclawAgentsFile(params = {}) {
|
|
367
|
+
const workspaceInfo = getOpenclawWorkspaceInfo();
|
|
368
|
+
const baseDir = workspaceInfo.workspaceDir;
|
|
369
|
+
ensureDir(baseDir);
|
|
370
|
+
const result = applyAgentsFile({
|
|
371
|
+
...params,
|
|
372
|
+
baseDir
|
|
373
|
+
});
|
|
374
|
+
return {
|
|
375
|
+
...result,
|
|
376
|
+
workspaceDir: baseDir,
|
|
377
|
+
configError: workspaceInfo.configError
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function applyOpenclawConfig(params = {}) {
|
|
382
|
+
const content = typeof params.content === 'string' ? params.content : '';
|
|
383
|
+
const lineEnding = params.lineEnding === '\r\n' ? '\r\n' : '\n';
|
|
384
|
+
const normalized = normalizeLineEnding(content, lineEnding);
|
|
385
|
+
const parsed = parseOpenclawConfigText(normalized);
|
|
386
|
+
if (!parsed.ok) {
|
|
387
|
+
return { success: false, error: parsed.error };
|
|
388
|
+
}
|
|
389
|
+
|
|
390
|
+
try {
|
|
391
|
+
ensureDir(OPENCLAW_DIR);
|
|
392
|
+
const backupPath = backupFileIfNeededOnce(OPENCLAW_CONFIG_FILE);
|
|
393
|
+
fs.writeFileSync(OPENCLAW_CONFIG_FILE, normalized, 'utf-8');
|
|
394
|
+
const result = {
|
|
395
|
+
success: true,
|
|
396
|
+
targetPath: OPENCLAW_CONFIG_FILE
|
|
397
|
+
};
|
|
398
|
+
if (backupPath) {
|
|
399
|
+
result.backupPath = backupPath;
|
|
400
|
+
}
|
|
401
|
+
return result;
|
|
402
|
+
} catch (e) {
|
|
403
|
+
return {
|
|
404
|
+
success: false,
|
|
405
|
+
error: e.message || '写入 OpenClaw 配置失败'
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
}
|
|
250
409
|
|
|
251
410
|
function readJsonObjectFromFile(filePath, fallback = {}) {
|
|
252
411
|
if (!fs.existsSync(filePath)) {
|
|
@@ -996,23 +1155,23 @@ function scanSessionContentForQuery(session, tokens, options = {}) {
|
|
|
996
1155
|
? Math.max(0, Number(options.snippetLimit))
|
|
997
1156
|
: 0;
|
|
998
1157
|
|
|
999
|
-
const messages = [];
|
|
1000
|
-
for (const record of records) {
|
|
1001
|
-
const message = extractMessageFromRecord(record, session.source);
|
|
1002
|
-
if (!message || !message.text) {
|
|
1003
|
-
continue;
|
|
1004
|
-
}
|
|
1005
|
-
messages.push(message);
|
|
1006
|
-
}
|
|
1007
|
-
|
|
1008
|
-
const filteredMessages = roleFilter === 'system'
|
|
1009
|
-
? messages
|
|
1010
|
-
: removeLeadingSystemMessage(messages);
|
|
1011
|
-
|
|
1012
|
-
let count = 0;
|
|
1013
|
-
const snippets = [];
|
|
1014
|
-
|
|
1015
|
-
for (const message of filteredMessages) {
|
|
1158
|
+
const messages = [];
|
|
1159
|
+
for (const record of records) {
|
|
1160
|
+
const message = extractMessageFromRecord(record, session.source);
|
|
1161
|
+
if (!message || !message.text) {
|
|
1162
|
+
continue;
|
|
1163
|
+
}
|
|
1164
|
+
messages.push(message);
|
|
1165
|
+
}
|
|
1166
|
+
|
|
1167
|
+
const filteredMessages = roleFilter === 'system'
|
|
1168
|
+
? messages
|
|
1169
|
+
: removeLeadingSystemMessage(messages);
|
|
1170
|
+
|
|
1171
|
+
let count = 0;
|
|
1172
|
+
const snippets = [];
|
|
1173
|
+
|
|
1174
|
+
for (const message of filteredMessages) {
|
|
1016
1175
|
if (roleFilter !== 'all' && message.role !== roleFilter) {
|
|
1017
1176
|
continue;
|
|
1018
1177
|
}
|
|
@@ -1039,11 +1198,11 @@ function applySessionQueryFilter(sessions, options = {}) {
|
|
|
1039
1198
|
}
|
|
1040
1199
|
|
|
1041
1200
|
const mode = normalizeQueryMode(options.queryMode);
|
|
1042
|
-
const scope = normalizeQueryScope(options.queryScope);
|
|
1043
|
-
const roleFilter = normalizeRoleFilter(options.roleFilter);
|
|
1044
|
-
const contentScanLimit = Number.isFinite(Number(options.contentScanLimit))
|
|
1045
|
-
? Math.max(1, Number(options.contentScanLimit))
|
|
1046
|
-
: DEFAULT_CONTENT_SCAN_LIMIT;
|
|
1201
|
+
const scope = normalizeQueryScope(options.queryScope);
|
|
1202
|
+
const roleFilter = normalizeRoleFilter(options.roleFilter);
|
|
1203
|
+
const contentScanLimit = Number.isFinite(Number(options.contentScanLimit))
|
|
1204
|
+
? Math.max(1, Number(options.contentScanLimit))
|
|
1205
|
+
: DEFAULT_CONTENT_SCAN_LIMIT;
|
|
1047
1206
|
const contentScanBytes = Number.isFinite(Number(options.contentScanBytes))
|
|
1048
1207
|
? Math.max(1024, Number(options.contentScanBytes))
|
|
1049
1208
|
: SESSION_CONTENT_READ_BYTES;
|
|
@@ -1095,7 +1254,7 @@ function applySessionQueryFilter(sessions, options = {}) {
|
|
|
1095
1254
|
|
|
1096
1255
|
return results;
|
|
1097
1256
|
}
|
|
1098
|
-
function collectRecentJsonlFiles(rootDir, options = {}) {
|
|
1257
|
+
function collectRecentJsonlFiles(rootDir, options = {}) {
|
|
1099
1258
|
if (!fs.existsSync(rootDir)) {
|
|
1100
1259
|
return [];
|
|
1101
1260
|
}
|
|
@@ -1553,18 +1712,18 @@ function listAllSessions(params = {}) {
|
|
|
1553
1712
|
sessions = sessions.filter(item => matchesSessionPathFilter(item, normalizedPathFilter));
|
|
1554
1713
|
}
|
|
1555
1714
|
|
|
1556
|
-
let result = sessions;
|
|
1557
|
-
if (hasQuery) {
|
|
1558
|
-
result = applySessionQueryFilter(result, {
|
|
1559
|
-
tokens: queryTokens,
|
|
1560
|
-
queryMode: params.queryMode,
|
|
1561
|
-
queryScope: params.queryScope,
|
|
1562
|
-
roleFilter: params.roleFilter,
|
|
1563
|
-
contentScanLimit: params.contentScanLimit,
|
|
1564
|
-
contentScanBytes: params.contentScanBytes
|
|
1565
|
-
});
|
|
1566
|
-
}
|
|
1567
|
-
result = mergeAndLimitSessions(result, limit);
|
|
1715
|
+
let result = sessions;
|
|
1716
|
+
if (hasQuery) {
|
|
1717
|
+
result = applySessionQueryFilter(result, {
|
|
1718
|
+
tokens: queryTokens,
|
|
1719
|
+
queryMode: params.queryMode,
|
|
1720
|
+
queryScope: params.queryScope,
|
|
1721
|
+
roleFilter: params.roleFilter,
|
|
1722
|
+
contentScanLimit: params.contentScanLimit,
|
|
1723
|
+
contentScanBytes: params.contentScanBytes
|
|
1724
|
+
});
|
|
1725
|
+
}
|
|
1726
|
+
result = mergeAndLimitSessions(result, limit);
|
|
1568
1727
|
if (!hasQuery) {
|
|
1569
1728
|
setSessionListCache(cacheKey, result);
|
|
1570
1729
|
}
|
|
@@ -2853,15 +3012,27 @@ function cmdStart() {
|
|
|
2853
3012
|
case 'apply-config-template':
|
|
2854
3013
|
result = applyConfigTemplate(params || {});
|
|
2855
3014
|
break;
|
|
2856
|
-
case 'get-agents-file':
|
|
2857
|
-
result = readAgentsFile(params || {});
|
|
2858
|
-
break;
|
|
2859
|
-
case 'apply-agents-file':
|
|
2860
|
-
result = applyAgentsFile(params || {});
|
|
2861
|
-
break;
|
|
2862
|
-
case '
|
|
2863
|
-
|
|
2864
|
-
|
|
3015
|
+
case 'get-agents-file':
|
|
3016
|
+
result = readAgentsFile(params || {});
|
|
3017
|
+
break;
|
|
3018
|
+
case 'apply-agents-file':
|
|
3019
|
+
result = applyAgentsFile(params || {});
|
|
3020
|
+
break;
|
|
3021
|
+
case 'get-openclaw-config':
|
|
3022
|
+
result = readOpenclawConfigFile();
|
|
3023
|
+
break;
|
|
3024
|
+
case 'apply-openclaw-config':
|
|
3025
|
+
result = applyOpenclawConfig(params || {});
|
|
3026
|
+
break;
|
|
3027
|
+
case 'get-openclaw-agents-file':
|
|
3028
|
+
result = readOpenclawAgentsFile();
|
|
3029
|
+
break;
|
|
3030
|
+
case 'apply-openclaw-agents-file':
|
|
3031
|
+
result = applyOpenclawAgentsFile(params || {});
|
|
3032
|
+
break;
|
|
3033
|
+
case 'switch':
|
|
3034
|
+
case 'use':
|
|
3035
|
+
case 'add':
|
|
2865
3036
|
case 'delete':
|
|
2866
3037
|
case 'update':
|
|
2867
3038
|
result = { error: 'Codex 配置改动已切换为模板确认模式,请使用模板编辑器并手动确认应用。' };
|
package/cmd/publish-npm.cmd
CHANGED
|
@@ -1,65 +1,65 @@
|
|
|
1
|
-
@echo off
|
|
2
|
-
setlocal enableextensions
|
|
3
|
-
set "VERBOSE_ECHO=0"
|
|
4
|
-
if /i "%VERBOSE%"=="1" (
|
|
5
|
-
set "VERBOSE_ECHO=1"
|
|
6
|
-
@echo on
|
|
7
|
-
set "NPM_CONFIG_LOGLEVEL=notice"
|
|
8
|
-
)
|
|
9
|
-
|
|
10
|
-
set "REGISTRY=https://registry.npmjs.org/"
|
|
11
|
-
set "PUBLISH_RC=1"
|
|
12
|
-
for %%I in ("%~dp0..") do set "ROOT_DIR=%%~fI"
|
|
13
|
-
set "LOCAL_NPMRC=%ROOT_DIR%\.npmrc"
|
|
14
|
-
|
|
15
|
-
where npm >nul 2>&1
|
|
16
|
-
if errorlevel 1 (
|
|
17
|
-
echo npm not found in PATH.
|
|
18
|
-
exit /b 1
|
|
19
|
-
)
|
|
20
|
-
|
|
21
|
-
if "%NPM_TOKEN%"=="" (
|
|
22
|
-
if exist "%LOCAL_NPMRC%" (
|
|
23
|
-
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
24
|
-
for /f "usebackq tokens=2,* delims==" %%A in (`findstr /i /c:"_authToken=" "%LOCAL_NPMRC%"`) do (
|
|
25
|
-
if "%%B"=="" (@set "NPM_TOKEN=%%A") else (@set "NPM_TOKEN=%%A=%%B")
|
|
26
|
-
)
|
|
27
|
-
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
28
|
-
)
|
|
29
|
-
)
|
|
30
|
-
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
31
|
-
if "%NPM_TOKEN%"=="" (
|
|
32
|
-
echo NPM_TOKEN is not set and no token found in %LOCAL_NPMRC%.
|
|
33
|
-
exit /b 1
|
|
34
|
-
)
|
|
35
|
-
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
36
|
-
|
|
37
|
-
set "TMP_NPMRC=%TEMP%\npmrc-codexmate-publish-%RANDOM%.tmp"
|
|
38
|
-
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
39
|
-
> "%TMP_NPMRC%" echo //registry.npmjs.org/:_authToken=%NPM_TOKEN%
|
|
40
|
-
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
41
|
-
set "NPM_CONFIG_USERCONFIG=%TMP_NPMRC%"
|
|
42
|
-
set "NPM_CONFIG_REGISTRY=%REGISTRY%"
|
|
43
|
-
|
|
44
|
-
call npm whoami --registry %REGISTRY%
|
|
45
|
-
if errorlevel 1 goto cleanup
|
|
46
|
-
|
|
47
|
-
echo [step] npm pack --dry-run
|
|
48
|
-
call npm pack --dry-run --registry %REGISTRY%
|
|
49
|
-
if errorlevel 1 goto cleanup
|
|
50
|
-
|
|
51
|
-
echo [step] npm publish
|
|
52
|
-
if not "%~1"=="" (
|
|
53
|
-
call npm publish --registry %REGISTRY% --otp %~1
|
|
54
|
-
) else if not "%NPM_OTP%"=="" (
|
|
55
|
-
call npm publish --registry %REGISTRY% --otp %NPM_OTP%
|
|
56
|
-
) else (
|
|
57
|
-
call npm publish --registry %REGISTRY%
|
|
58
|
-
)
|
|
59
|
-
set "PUBLISH_RC=%ERRORLEVEL%"
|
|
60
|
-
|
|
61
|
-
goto cleanup
|
|
62
|
-
|
|
63
|
-
:cleanup
|
|
64
|
-
if exist "%TMP_NPMRC%" del /f /q "%TMP_NPMRC%"
|
|
65
|
-
exit /b %PUBLISH_RC%
|
|
1
|
+
@echo off
|
|
2
|
+
setlocal enableextensions
|
|
3
|
+
set "VERBOSE_ECHO=0"
|
|
4
|
+
if /i "%VERBOSE%"=="1" (
|
|
5
|
+
set "VERBOSE_ECHO=1"
|
|
6
|
+
@echo on
|
|
7
|
+
set "NPM_CONFIG_LOGLEVEL=notice"
|
|
8
|
+
)
|
|
9
|
+
|
|
10
|
+
set "REGISTRY=https://registry.npmjs.org/"
|
|
11
|
+
set "PUBLISH_RC=1"
|
|
12
|
+
for %%I in ("%~dp0..") do set "ROOT_DIR=%%~fI"
|
|
13
|
+
set "LOCAL_NPMRC=%ROOT_DIR%\.npmrc"
|
|
14
|
+
|
|
15
|
+
where npm >nul 2>&1
|
|
16
|
+
if errorlevel 1 (
|
|
17
|
+
echo npm not found in PATH.
|
|
18
|
+
exit /b 1
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
if "%NPM_TOKEN%"=="" (
|
|
22
|
+
if exist "%LOCAL_NPMRC%" (
|
|
23
|
+
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
24
|
+
for /f "usebackq tokens=2,* delims==" %%A in (`findstr /i /c:"_authToken=" "%LOCAL_NPMRC%"`) do (
|
|
25
|
+
if "%%B"=="" (@set "NPM_TOKEN=%%A") else (@set "NPM_TOKEN=%%A=%%B")
|
|
26
|
+
)
|
|
27
|
+
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
28
|
+
)
|
|
29
|
+
)
|
|
30
|
+
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
31
|
+
if "%NPM_TOKEN%"=="" (
|
|
32
|
+
echo NPM_TOKEN is not set and no token found in %LOCAL_NPMRC%.
|
|
33
|
+
exit /b 1
|
|
34
|
+
)
|
|
35
|
+
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
36
|
+
|
|
37
|
+
set "TMP_NPMRC=%TEMP%\npmrc-codexmate-publish-%RANDOM%.tmp"
|
|
38
|
+
if "%VERBOSE_ECHO%"=="1" @echo off
|
|
39
|
+
> "%TMP_NPMRC%" echo //registry.npmjs.org/:_authToken=%NPM_TOKEN%
|
|
40
|
+
if "%VERBOSE_ECHO%"=="1" @echo on
|
|
41
|
+
set "NPM_CONFIG_USERCONFIG=%TMP_NPMRC%"
|
|
42
|
+
set "NPM_CONFIG_REGISTRY=%REGISTRY%"
|
|
43
|
+
|
|
44
|
+
call npm whoami --registry %REGISTRY%
|
|
45
|
+
if errorlevel 1 goto cleanup
|
|
46
|
+
|
|
47
|
+
echo [step] npm pack --dry-run
|
|
48
|
+
call npm pack --dry-run --registry %REGISTRY%
|
|
49
|
+
if errorlevel 1 goto cleanup
|
|
50
|
+
|
|
51
|
+
echo [step] npm publish
|
|
52
|
+
if not "%~1"=="" (
|
|
53
|
+
call npm publish --registry %REGISTRY% --otp %~1
|
|
54
|
+
) else if not "%NPM_OTP%"=="" (
|
|
55
|
+
call npm publish --registry %REGISTRY% --otp %NPM_OTP%
|
|
56
|
+
) else (
|
|
57
|
+
call npm publish --registry %REGISTRY%
|
|
58
|
+
)
|
|
59
|
+
set "PUBLISH_RC=%ERRORLEVEL%"
|
|
60
|
+
|
|
61
|
+
goto cleanup
|
|
62
|
+
|
|
63
|
+
:cleanup
|
|
64
|
+
if exist "%TMP_NPMRC%" del /f /q "%TMP_NPMRC%"
|
|
65
|
+
exit /b %PUBLISH_RC%
|
package/package.json
CHANGED
|
@@ -1,25 +1,27 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "codexmate",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "Codex 提供商管理 CLI 工具",
|
|
5
|
-
"bin": {
|
|
6
|
-
"codexmate": "./cli.js"
|
|
7
|
-
},
|
|
8
|
-
"scripts": {
|
|
9
|
-
"start": "node cli.js"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@iarna/toml": "^2.2.5"
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
"
|
|
20
|
-
"
|
|
21
|
-
"
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
"
|
|
25
|
-
|
|
1
|
+
{
|
|
2
|
+
"name": "codexmate",
|
|
3
|
+
"version": "0.0.4",
|
|
4
|
+
"description": "Codex 提供商管理 CLI 工具",
|
|
5
|
+
"bin": {
|
|
6
|
+
"codexmate": "./cli.js"
|
|
7
|
+
},
|
|
8
|
+
"scripts": {
|
|
9
|
+
"start": "node cli.js"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@iarna/toml": "^2.2.5",
|
|
13
|
+
"json5": "^2.2.3"
|
|
14
|
+
},
|
|
15
|
+
"engines": {
|
|
16
|
+
"node": ">=14"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"codex",
|
|
20
|
+
"ai",
|
|
21
|
+
"llm",
|
|
22
|
+
"cli"
|
|
23
|
+
],
|
|
24
|
+
"author": "ymkiux",
|
|
25
|
+
"license": "Apache-2.0"
|
|
26
|
+
}
|
|
27
|
+
|
package/res/screenshot.png
CHANGED
|
Binary file
|