@inf-monkeys-tech/monkeys-cli 0.10.2 → 0.10.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/README.md +23 -0
- package/README.zh.md +23 -0
- package/bin/run.js +39 -6
- package/bin/update-cache.js +7 -0
- package/dist/commands/update.d.ts +14 -0
- package/dist/commands/update.d.ts.map +1 -0
- package/dist/commands/update.js +110 -0
- package/dist/commands/update.js.map +1 -0
- package/dist/contracts/result.d.ts +6 -0
- package/dist/contracts/result.d.ts.map +1 -1
- package/dist/contracts/result.js +7 -2
- package/dist/contracts/result.js.map +1 -1
- package/dist/output/render.d.ts.map +1 -1
- package/dist/output/render.js +7 -2
- package/dist/output/render.js.map +1 -1
- package/dist/update/notifier.d.ts +43 -0
- package/dist/update/notifier.d.ts.map +1 -0
- package/dist/update/notifier.js +242 -0
- package/dist/update/notifier.js.map +1 -0
- package/dist/update/updater.d.ts +26 -0
- package/dist/update/updater.d.ts.map +1 -0
- package/dist/update/updater.js +91 -0
- package/dist/update/updater.js.map +1 -0
- package/oclif.manifest.json +50 -1
- package/package.json +5 -4
- package/skills/monkeys/SKILL.md +1 -1
- package/skills/monkeys/references/compatibility.md +2 -0
package/README.md
CHANGED
|
@@ -165,6 +165,29 @@ monkeys profile use --name <profile-name> --output json
|
|
|
165
165
|
monkeys profile test --name <profile-name> --output json
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
## Updates
|
|
169
|
+
|
|
170
|
+
Every normal CLI invocation reads a local update cache. When npm `latest` is newer, JSON output includes `_notice.update`, while text output prints the exact recovery command:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
Update available: 0.10.2 → 0.10.3. Run `monkeys update` to install.
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
The cache is refreshed from npm in a detached background process at most once every 24 hours, so update discovery does not delay the requested command. CI environments, non-release builds, and processes with `MONKEYS_CLI_NO_UPDATE_NOTIFIER=1` skip the notifier.
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# Check only; makes no installation changes
|
|
180
|
+
monkeys update --check --output json
|
|
181
|
+
|
|
182
|
+
# Upgrade the global npm package and sync the matching bundled Skill
|
|
183
|
+
monkeys update
|
|
184
|
+
|
|
185
|
+
# Reinstall the current latest CLI and retry Skill synchronization
|
|
186
|
+
monkeys update --force
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Running bare `monkeys` in an interactive terminal also offers an optional `[y/N]` upgrade prompt. The update command always resolves the target version live from npm instead of trusting the cached notice.
|
|
190
|
+
|
|
168
191
|
## Command System
|
|
169
192
|
|
|
170
193
|
monkeys-cli provides three levels of access, from stable domain operations to the low-level API actually published by a deployment.
|
package/README.zh.md
CHANGED
|
@@ -165,6 +165,29 @@ monkeys profile use --name <profile-name> --output json
|
|
|
165
165
|
monkeys profile test --name <profile-name> --output json
|
|
166
166
|
```
|
|
167
167
|
|
|
168
|
+
## 版本更新
|
|
169
|
+
|
|
170
|
+
每次正常调用 CLI 都会读取本地更新缓存。npm `latest` 高于当前版本时,JSON 输出会包含 `_notice.update`,Text 输出会直接提示准确的恢复命令:
|
|
171
|
+
|
|
172
|
+
```text
|
|
173
|
+
Update available: 0.10.2 → 0.10.3. Run `monkeys update` to install.
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
CLI 最多每 24 小时在独立后台进程中刷新一次 npm 缓存,不会因版本查询拖慢当前命令。CI、非发布版本以及设置了 `MONKEYS_CLI_NO_UPDATE_NOTIFIER=1` 的进程不会检查更新。
|
|
177
|
+
|
|
178
|
+
```bash
|
|
179
|
+
# 只检查,不执行安装
|
|
180
|
+
monkeys update --check --output json
|
|
181
|
+
|
|
182
|
+
# 升级全局 npm 包,并同步新包中匹配版本的 Skill
|
|
183
|
+
monkeys update
|
|
184
|
+
|
|
185
|
+
# 强制重装当前最新版,并重试 Skill 同步
|
|
186
|
+
monkeys update --force
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
在交互式终端裸运行 `monkeys` 时,还会显示可选的 `[y/N]` 升级询问。执行升级时始终从 npm 实时解析目标版本,不会直接信任缓存中的提示版本。
|
|
190
|
+
|
|
168
191
|
## 命令体系
|
|
169
192
|
|
|
170
193
|
monkeys-cli 提供三种调用粒度,从稳定领域操作到部署实际发布的底层 API。
|
package/bin/run.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { createInterface } from 'node:readline/promises';
|
|
5
|
+
|
|
3
6
|
const args = process.argv.slice(2);
|
|
4
7
|
const install = args.length === 1 && args[0] === 'install';
|
|
8
|
+
const update = args[0] === 'update';
|
|
5
9
|
const fastVersion =
|
|
6
10
|
args[0] === 'version' &&
|
|
7
11
|
args[1] === 'show' &&
|
|
@@ -10,15 +14,34 @@ const fastProfileList =
|
|
|
10
14
|
args[0] === 'profile' &&
|
|
11
15
|
args[1] === 'list' &&
|
|
12
16
|
(args.length === 2 || (args.length === 4 && args[2] === '--output' && ['json', 'text'].includes(args[3])));
|
|
17
|
+
|
|
18
|
+
let packageJson;
|
|
19
|
+
let updateNotice;
|
|
20
|
+
if (!install && !update) {
|
|
21
|
+
packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
22
|
+
const { initializeUpdateNotifier } = await import('../dist/update/notifier.js');
|
|
23
|
+
updateNotice = await initializeUpdateNotifier(packageJson.version);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (args.length === 0 && updateNotice && process.stdin.isTTY && process.stdout.isTTY && process.stderr.isTTY) {
|
|
27
|
+
try {
|
|
28
|
+
const prompt = createInterface({ input: process.stdin, output: process.stderr });
|
|
29
|
+
try {
|
|
30
|
+
const answer = await prompt.question(`A newer monkeys CLI is available (current ${updateNotice.current}). Upgrade now? [y/N]: `);
|
|
31
|
+
if (['y', 'yes'].includes(answer.trim().toLowerCase())) process.argv.splice(2, 0, 'update');
|
|
32
|
+
} finally {
|
|
33
|
+
prompt.close();
|
|
34
|
+
}
|
|
35
|
+
} catch {
|
|
36
|
+
// The optional prompt must never block the requested CLI help output.
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
13
40
|
if (install) {
|
|
14
41
|
const { runInstallWizardCli } = await import('./install-wizard.js');
|
|
15
42
|
await runInstallWizardCli();
|
|
16
43
|
} else if (fastVersion) {
|
|
17
|
-
const
|
|
18
|
-
import('node:fs/promises'),
|
|
19
|
-
import('../dist/contracts/version.js'),
|
|
20
|
-
]);
|
|
21
|
-
const packageJson = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8'));
|
|
44
|
+
const { BUNDLED_SKILL_MINIMUM_CLI_VERSION, BUNDLED_SKILL_NAME, COMMAND_SCHEMA_MAJOR } = await import('../dist/contracts/version.js');
|
|
22
45
|
const data = {
|
|
23
46
|
cliVersion: packageJson.version,
|
|
24
47
|
commandSchemaMajor: COMMAND_SCHEMA_MAJOR,
|
|
@@ -30,10 +53,20 @@ if (install) {
|
|
|
30
53
|
const output = outputIndex >= 0 ? args[outputIndex + 1] : 'text';
|
|
31
54
|
if (output === 'json') {
|
|
32
55
|
process.stdout.write(
|
|
33
|
-
`${JSON.stringify({
|
|
56
|
+
`${JSON.stringify({
|
|
57
|
+
...(updateNotice ? { _notice: { update: updateNotice } } : {}),
|
|
58
|
+
data,
|
|
59
|
+
meta: { command: 'version show', schemaVersion: '1', timestamp: new Date().toISOString() },
|
|
60
|
+
ok: true,
|
|
61
|
+
})}\n`,
|
|
34
62
|
);
|
|
35
63
|
} else {
|
|
36
64
|
process.stdout.write(`${JSON.stringify(data, null, 2)}\n`);
|
|
65
|
+
if (updateNotice) {
|
|
66
|
+
process.stdout.write(
|
|
67
|
+
`\nUpdate available: ${updateNotice.current} → ${updateNotice.latest}. Run \`${updateNotice.command}\` to install.\n`,
|
|
68
|
+
);
|
|
69
|
+
}
|
|
37
70
|
}
|
|
38
71
|
} else if (fastProfileList) {
|
|
39
72
|
const { renderFastProfileList } = await import('../dist/config/fast-profile-list.js');
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { Command } from '@oclif/core';
|
|
2
|
+
export default class Update extends Command {
|
|
3
|
+
static description: string;
|
|
4
|
+
static examples: string[];
|
|
5
|
+
static flags: {
|
|
6
|
+
check: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
7
|
+
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;
|
|
8
|
+
output: import("@oclif/core/interfaces").OptionFlag<string, import("@oclif/core/interfaces").CustomOptions>;
|
|
9
|
+
};
|
|
10
|
+
run(): Promise<void>;
|
|
11
|
+
private printResult;
|
|
12
|
+
private toCliError;
|
|
13
|
+
}
|
|
14
|
+
//# sourceMappingURL=update.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.d.ts","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAS,MAAM,aAAa,CAAC;AAmB7C,MAAM,CAAC,OAAO,OAAO,MAAO,SAAQ,OAAO;IACzC,OAAgB,WAAW,SAA0C;IACrE,OAAgB,QAAQ,WAAkF;IAC1G,OAAgB,KAAK;QACnB,KAAK;QACL,KAAK;QACL,MAAM;MACN;IAEI,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAmEzB;IAED,OAAO,CAAC,WAAW;IAqBnB,OAAO,CAAC,UAAU;CAYnB"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
import { Command, Flags } from '@oclif/core';
|
|
2
|
+
import { errorResult, successResult } from '../contracts/result.js';
|
|
3
|
+
import { asCliError, CliError, EXIT_CODES } from '../errors/cli-error.js';
|
|
4
|
+
import { renderResult } from '../output/render.js';
|
|
5
|
+
import { redactValue } from '../security/redact.js';
|
|
6
|
+
import { clearPendingUpdateNotice, fetchLatestVersion, isNewerVersion } from '../update/notifier.js';
|
|
7
|
+
import { installCliAndSkill, UpdateProcessError } from '../update/updater.js';
|
|
8
|
+
export default class Update extends Command {
|
|
9
|
+
static description = '检查或安装最新版本的 monkeys CLI,并同步同版本 Skill。';
|
|
10
|
+
static examples = ['<%= config.bin %> update --check --output json', '<%= config.bin %> update'];
|
|
11
|
+
static flags = {
|
|
12
|
+
check: Flags.boolean({ default: false, summary: '只检查更新,不执行安装' }),
|
|
13
|
+
force: Flags.boolean({ default: false, summary: '即使已是最新版本也重新安装 CLI 与 Skill' }),
|
|
14
|
+
output: Flags.string({ default: 'text', options: ['json', 'text'], summary: '输出格式' }),
|
|
15
|
+
};
|
|
16
|
+
async run() {
|
|
17
|
+
clearPendingUpdateNotice();
|
|
18
|
+
const { flags } = await this.parse(Update);
|
|
19
|
+
const output = flags.output;
|
|
20
|
+
const currentVersion = this.config.version;
|
|
21
|
+
try {
|
|
22
|
+
let latestVersion;
|
|
23
|
+
try {
|
|
24
|
+
latestVersion = await fetchLatestVersion();
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
throw new CliError('无法查询 npm 最新版本。', {
|
|
28
|
+
cause: error,
|
|
29
|
+
code: 'UPDATE_CHECK_FAILED',
|
|
30
|
+
exitCode: EXIT_CODES.network,
|
|
31
|
+
recovery: ['检查网络或 npm registry 访问后重试 monkeys update --check。'],
|
|
32
|
+
retryable: true,
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
const updateAvailable = isNewerVersion(latestVersion, currentVersion);
|
|
36
|
+
if (flags.check) {
|
|
37
|
+
const result = {
|
|
38
|
+
action: updateAvailable ? 'update_available' : 'already_up_to_date',
|
|
39
|
+
autoUpdate: true,
|
|
40
|
+
command: 'monkeys update',
|
|
41
|
+
currentVersion,
|
|
42
|
+
latestVersion,
|
|
43
|
+
previousVersion: currentVersion,
|
|
44
|
+
};
|
|
45
|
+
this.printResult(result, output);
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
if (!updateAvailable && !flags.force) {
|
|
49
|
+
this.printResult({
|
|
50
|
+
action: 'already_up_to_date',
|
|
51
|
+
autoUpdate: true,
|
|
52
|
+
command: 'monkeys update',
|
|
53
|
+
currentVersion,
|
|
54
|
+
latestVersion,
|
|
55
|
+
previousVersion: currentVersion,
|
|
56
|
+
}, output);
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
if (output === 'text')
|
|
60
|
+
process.stderr.write(`Updating monkeys ${currentVersion} → ${latestVersion} via npm ...\n`);
|
|
61
|
+
const installed = await installCliAndSkill(latestVersion);
|
|
62
|
+
this.printResult({
|
|
63
|
+
action: 'updated',
|
|
64
|
+
autoUpdate: true,
|
|
65
|
+
command: 'monkeys update',
|
|
66
|
+
currentVersion: installed.currentVersion,
|
|
67
|
+
latestVersion,
|
|
68
|
+
previousVersion: currentVersion,
|
|
69
|
+
skillsAction: installed.skillsAction,
|
|
70
|
+
...(installed.skillsWarning ? { skillsWarning: installed.skillsWarning } : {}),
|
|
71
|
+
}, output);
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
const cliError = this.toCliError(error);
|
|
75
|
+
this.log(renderResult(redactValue(errorResult(cliError.toErrorDetail(), { command: 'update' })), output));
|
|
76
|
+
this.exit(cliError.exitCode);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
printResult(result, output) {
|
|
80
|
+
if (output === 'json') {
|
|
81
|
+
this.log(renderResult(successResult(result, { command: 'update' }), output));
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
switch (result.action) {
|
|
85
|
+
case 'already_up_to_date':
|
|
86
|
+
this.log(`✓ monkeys ${result.currentVersion} is already up to date.`);
|
|
87
|
+
break;
|
|
88
|
+
case 'update_available':
|
|
89
|
+
this.log(`Update available: ${result.currentVersion} → ${result.latestVersion}\n\nRun \`${result.command}\` to install.`);
|
|
90
|
+
break;
|
|
91
|
+
case 'updated':
|
|
92
|
+
this.log(`✓ Successfully updated monkeys from ${result.previousVersion} to ${result.currentVersion}.`);
|
|
93
|
+
this.log(result.skillsAction === 'synced' ? '✓ Monkeys Skill updated.' : `⚠ ${result.skillsWarning ?? 'Monkeys Skill update failed.'}`);
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
toCliError(error) {
|
|
98
|
+
if (error instanceof UpdateProcessError) {
|
|
99
|
+
return new CliError(error.message, {
|
|
100
|
+
cause: error,
|
|
101
|
+
code: 'UPDATE_FAILED',
|
|
102
|
+
exitCode: EXIT_CODES.internal,
|
|
103
|
+
recovery: ['检查 npm/npx、网络和全局安装目录权限后重试。', '仅重试 Skill 可运行 monkeys update --force。'],
|
|
104
|
+
safeDetails: { command: error.command, detail: error.detail },
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
return asCliError(error);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=update.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update.js","sourceRoot":"","sources":["../../src/commands/update.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { type UpdateNotice } from '../update/notifier.js';
|
|
2
3
|
export declare const RESULT_SCHEMA_VERSION: '1';
|
|
3
4
|
export declare const contextSummarySchema: z.ZodObject<{
|
|
4
5
|
authSurface: z.ZodOptional<z.ZodString>;
|
|
@@ -18,10 +19,14 @@ export interface ResultMeta {
|
|
|
18
19
|
warnings?: string[];
|
|
19
20
|
}
|
|
20
21
|
export interface SuccessResult<T> {
|
|
22
|
+
_notice?: SystemNotice;
|
|
21
23
|
data: T;
|
|
22
24
|
meta: ResultMeta;
|
|
23
25
|
ok: true;
|
|
24
26
|
}
|
|
27
|
+
export interface SystemNotice {
|
|
28
|
+
update?: UpdateNotice;
|
|
29
|
+
}
|
|
25
30
|
export interface ErrorDetail {
|
|
26
31
|
code: string;
|
|
27
32
|
fallbackEligible: boolean;
|
|
@@ -31,6 +36,7 @@ export interface ErrorDetail {
|
|
|
31
36
|
safeDetails?: unknown;
|
|
32
37
|
}
|
|
33
38
|
export interface ErrorResult {
|
|
39
|
+
_notice?: SystemNotice;
|
|
34
40
|
error: ErrorDetail;
|
|
35
41
|
meta: ResultMeta;
|
|
36
42
|
ok: false;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/contracts/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"result.d.ts","sourceRoot":"","sources":["../../src/contracts/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAA0B,KAAK,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAElF,eAAO,MAAM,qBAAqB,EAAG,GAAY,CAAC;AAElD,eAAO,MAAM,oBAAoB;;;;;;;iBAO/B,CAAC;AAEH,MAAM,MAAM,cAAc,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAElE,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,cAAc,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,OAAO,qBAAqB,CAAC;IAC5C,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,aAAa,CAAC,CAAC;IAC9B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,IAAI,EAAE,CAAC,CAAC;IACR,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,IAAI,CAAC;CACV;AAED,MAAM,WAAW,YAAY;IAC3B,MAAM,CAAC,EAAE,YAAY,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,gBAAgB,EAAE,OAAO,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,EAAE,CAAC;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,WAAW,CAAC;IACnB,IAAI,EAAE,UAAU,CAAC;IACjB,EAAE,EAAE,KAAK,CAAC;CACX;AAED,MAAM,MAAM,aAAa,CAAC,CAAC,IAAI,WAAW,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC;AAW9D,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,GAAG,WAAW,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAEjH;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,IAAI,CAAC,UAAU,EAAE,eAAe,GAAG,WAAW,CAAC,GAAG,WAAW,CAElH"}
|
package/dist/contracts/result.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { getPendingUpdateNotice } from '../update/notifier.js';
|
|
2
3
|
export const RESULT_SCHEMA_VERSION = '1';
|
|
3
4
|
export const contextSummarySchema = z.object({
|
|
4
5
|
authSurface: z.string().optional(),
|
|
@@ -11,10 +12,14 @@ export const contextSummarySchema = z.object({
|
|
|
11
12
|
function createMeta(input) {
|
|
12
13
|
return { ...input, schemaVersion: RESULT_SCHEMA_VERSION, timestamp: new Date().toISOString() };
|
|
13
14
|
}
|
|
15
|
+
function currentNotice() {
|
|
16
|
+
const update = getPendingUpdateNotice();
|
|
17
|
+
return update ? { _notice: { update } } : {};
|
|
18
|
+
}
|
|
14
19
|
export function successResult(data, meta) {
|
|
15
|
-
return { data, meta: createMeta(meta), ok: true };
|
|
20
|
+
return { ...currentNotice(), data, meta: createMeta(meta), ok: true };
|
|
16
21
|
}
|
|
17
22
|
export function errorResult(error, meta) {
|
|
18
|
-
return { error, meta: createMeta(meta), ok: false };
|
|
23
|
+
return { ...currentNotice(), error, meta: createMeta(meta), ok: false };
|
|
19
24
|
}
|
|
20
25
|
//# sourceMappingURL=result.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/contracts/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;
|
|
1
|
+
{"version":3,"file":"result.js","sourceRoot":"","sources":["../../src/contracts/result.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,sBAAsB,EAAqB,MAAM,uBAAuB,CAAC;AAElF,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAY,CAAC;AAElD,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAAC,CAAC,MAAM,CAAC;IAC3C,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,UAAU,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IACjC,WAAW,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAClC,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC3B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CAC9B,CAAC,CAAC;AA0CH,SAAS,UAAU,CAAC,KAAsD;IACxE,OAAO,EAAE,GAAG,KAAK,EAAE,aAAa,EAAE,qBAAqB,EAAE,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AACjG,CAAC;AAED,SAAS,aAAa;IACpB,MAAM,MAAM,GAAG,sBAAsB,EAAE,CAAC;IACxC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;AAC/C,CAAC;AAED,MAAM,UAAU,aAAa,CAAI,IAAO,EAAE,IAAqD;IAC7F,OAAO,EAAE,GAAG,aAAa,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC;AACxE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAkB,EAAE,IAAqD;IACnG,OAAO,EAAE,GAAG,aAAa,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC;AAC1E,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/output/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAMtD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/output/render.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,GAAG,MAAM,CAAC;AAMtD,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,GAAG,MAAM,CAWtF"}
|
package/dist/output/render.js
CHANGED
|
@@ -6,8 +6,13 @@ export function renderResult(result, format) {
|
|
|
6
6
|
return JSON.stringify(result);
|
|
7
7
|
if (format === 'ndjson') {
|
|
8
8
|
const items = result.ok && Array.isArray(result.data) ? result.data : [result];
|
|
9
|
-
|
|
9
|
+
const lines = items.map((item) => JSON.stringify(item));
|
|
10
|
+
if (result.ok && Array.isArray(result.data) && result._notice)
|
|
11
|
+
lines.push(JSON.stringify({ _notice: result._notice }));
|
|
12
|
+
return lines.join('\n');
|
|
10
13
|
}
|
|
11
|
-
|
|
14
|
+
const body = result.ok ? renderTextValue(result.data) : `${result.error.code}: ${result.error.message}`;
|
|
15
|
+
const update = result._notice?.update;
|
|
16
|
+
return update ? `${body}\n\nUpdate available: ${update.current} → ${update.latest}. Run \`${update.command}\` to install.` : body;
|
|
12
17
|
}
|
|
13
18
|
//# sourceMappingURL=render.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/output/render.ts"],"names":[],"mappings":"AAIA,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,YAAY,CAAI,MAAwB,EAAE,MAAoB;IAC5E,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/E,
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../src/output/render.ts"],"names":[],"mappings":"AAIA,SAAS,eAAe,CAAC,KAAc;IACrC,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED,MAAM,UAAU,YAAY,CAAI,MAAwB,EAAE,MAAoB;IAC5E,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;IACrD,IAAI,MAAM,KAAK,QAAQ,EAAE,CAAC;QACxB,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC/E,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QACxD,IAAI,MAAM,CAAC,EAAE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;QACvH,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC;IACxG,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC;IACtC,OAAO,MAAM,CAAC,CAAC,CAAC,GAAG,IAAI,yBAAyB,MAAM,CAAC,OAAO,MAAM,MAAM,CAAC,MAAM,WAAW,MAAM,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC;AACpI,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
export declare const UPDATE_CHECK_TTL_MS: number;
|
|
2
|
+
export declare const UPDATE_FETCH_TIMEOUT_MS = 15000;
|
|
3
|
+
export declare const UPDATE_NOTIFIER_DISABLE_ENV = "MONKEYS_CLI_NO_UPDATE_NOTIFIER";
|
|
4
|
+
export declare const UPDATE_REGISTRY_URL = "https://registry.npmjs.org/@inf-monkeys-tech%2Fmonkeys-cli/latest";
|
|
5
|
+
export interface UpdateNotice {
|
|
6
|
+
command: 'monkeys update';
|
|
7
|
+
current: string;
|
|
8
|
+
latest: string;
|
|
9
|
+
message: string;
|
|
10
|
+
}
|
|
11
|
+
export interface UpdateState {
|
|
12
|
+
checkedAt: number;
|
|
13
|
+
latestVersion: string;
|
|
14
|
+
}
|
|
15
|
+
export interface FetchLatestOptions {
|
|
16
|
+
fetchImpl?: typeof fetch;
|
|
17
|
+
registryUrl?: string;
|
|
18
|
+
timeoutMs?: number;
|
|
19
|
+
}
|
|
20
|
+
export interface UpdateCacheOptions extends FetchLatestOptions {
|
|
21
|
+
env?: NodeJS.ProcessEnv;
|
|
22
|
+
nowMs?: number;
|
|
23
|
+
statePath?: string;
|
|
24
|
+
}
|
|
25
|
+
export interface InitializeUpdateNotifierOptions extends UpdateCacheOptions {
|
|
26
|
+
scheduleRefresh?: (currentVersion: string) => void;
|
|
27
|
+
}
|
|
28
|
+
export declare function compareVersions(left: string, right: string): number | undefined;
|
|
29
|
+
export declare function isNewerVersion(candidate: string, current: string): boolean;
|
|
30
|
+
export declare function isReleaseVersion(version: string): boolean;
|
|
31
|
+
export declare function isCiEnvironment(env?: NodeJS.ProcessEnv): boolean;
|
|
32
|
+
export declare function shouldSkipUpdateNotifier(currentVersion: string, env?: NodeJS.ProcessEnv): boolean;
|
|
33
|
+
export declare function updateStatePath(env?: NodeJS.ProcessEnv): string;
|
|
34
|
+
export declare function createUpdateNotice(current: string, latest: string): UpdateNotice;
|
|
35
|
+
export declare function getPendingUpdateNotice(): UpdateNotice | undefined;
|
|
36
|
+
export declare function clearPendingUpdateNotice(): void;
|
|
37
|
+
export declare function setPendingUpdateNotice(notice: UpdateNotice | undefined): void;
|
|
38
|
+
export declare function readUpdateState(path?: string): Promise<UpdateState | undefined>;
|
|
39
|
+
export declare function fetchLatestVersion(options?: FetchLatestOptions): Promise<string>;
|
|
40
|
+
export declare function refreshUpdateCache(currentVersion: string, options?: UpdateCacheOptions): Promise<boolean>;
|
|
41
|
+
export declare function scheduleUpdateCacheRefresh(currentVersion: string): void;
|
|
42
|
+
export declare function initializeUpdateNotifier(currentVersion: string, options?: InitializeUpdateNotifierOptions): Promise<UpdateNotice | undefined>;
|
|
43
|
+
//# sourceMappingURL=notifier.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifier.d.ts","sourceRoot":"","sources":["../../src/update/notifier.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,mBAAmB,QAAuB,CAAC;AACxD,eAAO,MAAM,uBAAuB,QAAS,CAAC;AAC9C,eAAO,MAAM,2BAA2B,mCAAmC,CAAC;AAC5E,eAAO,MAAM,mBAAmB,sEAAsE,CAAC;AAWvG,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,gBAAgB,CAAC;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,kBAAkB;IACjC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,kBAAkB;IAC5D,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;IACxB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,+BAAgC,SAAQ,kBAAkB;IACzE,eAAe,CAAC,EAAE,CAAC,cAAc,EAAE,MAAM,KAAK,IAAI,CAAC;CACpD;AAmCD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAS/E;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAE1E;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE7E;AAED,wBAAgB,wBAAwB,CAAC,cAAc,EAAE,MAAM,EAAE,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,OAAO,CAE9G;AAED,wBAAgB,eAAe,CAAC,GAAG,GAAE,MAAM,CAAC,UAAwB,GAAG,MAAM,CAE5E;AAED,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,YAAY,CAOhF;AAED,wBAAgB,sBAAsB,IAAI,YAAY,GAAG,SAAS,CAEjE;AAED,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,YAAY,GAAG,SAAS,GAAG,IAAI,CAE7E;AAUD,wBAAsB,eAAe,CAAC,IAAI,SAAoB,GAAG,OAAO,CAAC,WAAW,GAAG,SAAS,CAAC,CAMhG;AAqCD,wBAAsB,kBAAkB,CAAC,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,MAAM,CAAC,CAY1F;AAqBD,wBAAsB,kBAAkB,CAAC,cAAc,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,OAAO,CAAC,CAuBnH;AAED,wBAAgB,0BAA0B,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAavE;AAED,wBAAsB,wBAAwB,CAC5C,cAAc,EAAE,MAAM,EACtB,OAAO,GAAE,+BAAoC,GAC5C,OAAO,CAAC,YAAY,GAAG,SAAS,CAAC,CAenC"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { open, mkdir, readFile, rename, rm, stat } from 'node:fs/promises';
|
|
3
|
+
import { dirname, join } from 'node:path';
|
|
4
|
+
import { fileURLToPath } from 'node:url';
|
|
5
|
+
import { configDirectory, resolveConfigPath } from '../config/paths.js';
|
|
6
|
+
export const UPDATE_CHECK_TTL_MS = 24 * 60 * 60 * 1_000;
|
|
7
|
+
export const UPDATE_FETCH_TIMEOUT_MS = 15_000;
|
|
8
|
+
export const UPDATE_NOTIFIER_DISABLE_ENV = 'MONKEYS_CLI_NO_UPDATE_NOTIFIER';
|
|
9
|
+
export const UPDATE_REGISTRY_URL = 'https://registry.npmjs.org/@inf-monkeys-tech%2Fmonkeys-cli/latest';
|
|
10
|
+
const MAX_RESPONSE_BYTES = 256 * 1_024;
|
|
11
|
+
const REFRESH_LOCK_STALE_MS = UPDATE_FETCH_TIMEOUT_MS * 2;
|
|
12
|
+
const UPDATE_STATE_FILE = 'update-state.json';
|
|
13
|
+
let pendingUpdateNotice;
|
|
14
|
+
function isNodeError(error, code) {
|
|
15
|
+
return error instanceof Error && 'code' in error && error.code === code;
|
|
16
|
+
}
|
|
17
|
+
function parseVersion(value) {
|
|
18
|
+
const match = /^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+[0-9A-Za-z.-]+)?$/.exec(value.trim());
|
|
19
|
+
if (!match)
|
|
20
|
+
return undefined;
|
|
21
|
+
const core = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
22
|
+
if (!core.every(Number.isSafeInteger))
|
|
23
|
+
return undefined;
|
|
24
|
+
return { core, prerelease: match[4]?.split('.') ?? [] };
|
|
25
|
+
}
|
|
26
|
+
function comparePrerelease(left, right) {
|
|
27
|
+
if (left.length === 0 || right.length === 0)
|
|
28
|
+
return left.length === right.length ? 0 : left.length === 0 ? 1 : -1;
|
|
29
|
+
const length = Math.max(left.length, right.length);
|
|
30
|
+
for (let index = 0; index < length; index += 1) {
|
|
31
|
+
const leftValue = left[index];
|
|
32
|
+
const rightValue = right[index];
|
|
33
|
+
if (leftValue === undefined || rightValue === undefined)
|
|
34
|
+
return leftValue === rightValue ? 0 : leftValue === undefined ? -1 : 1;
|
|
35
|
+
if (leftValue === rightValue)
|
|
36
|
+
continue;
|
|
37
|
+
const leftNumeric = /^\d+$/.test(leftValue);
|
|
38
|
+
const rightNumeric = /^\d+$/.test(rightValue);
|
|
39
|
+
if (leftNumeric && rightNumeric)
|
|
40
|
+
return Number(leftValue) - Number(rightValue);
|
|
41
|
+
if (leftNumeric !== rightNumeric)
|
|
42
|
+
return leftNumeric ? -1 : 1;
|
|
43
|
+
return leftValue.localeCompare(rightValue);
|
|
44
|
+
}
|
|
45
|
+
return 0;
|
|
46
|
+
}
|
|
47
|
+
export function compareVersions(left, right) {
|
|
48
|
+
const parsedLeft = parseVersion(left);
|
|
49
|
+
const parsedRight = parseVersion(right);
|
|
50
|
+
if (!parsedLeft || !parsedRight)
|
|
51
|
+
return undefined;
|
|
52
|
+
for (let index = 0; index < parsedLeft.core.length; index += 1) {
|
|
53
|
+
const difference = parsedLeft.core[index] - parsedRight.core[index];
|
|
54
|
+
if (difference !== 0)
|
|
55
|
+
return difference;
|
|
56
|
+
}
|
|
57
|
+
return comparePrerelease(parsedLeft.prerelease, parsedRight.prerelease);
|
|
58
|
+
}
|
|
59
|
+
export function isNewerVersion(candidate, current) {
|
|
60
|
+
return (compareVersions(candidate, current) ?? 0) > 0;
|
|
61
|
+
}
|
|
62
|
+
export function isReleaseVersion(version) {
|
|
63
|
+
return parseVersion(version) !== undefined;
|
|
64
|
+
}
|
|
65
|
+
export function isCiEnvironment(env = process.env) {
|
|
66
|
+
return ['CI', 'BUILD_NUMBER', 'RUN_ID'].some((key) => Boolean(env[key]));
|
|
67
|
+
}
|
|
68
|
+
export function shouldSkipUpdateNotifier(currentVersion, env = process.env) {
|
|
69
|
+
return Boolean(env[UPDATE_NOTIFIER_DISABLE_ENV]) || isCiEnvironment(env) || !isReleaseVersion(currentVersion);
|
|
70
|
+
}
|
|
71
|
+
export function updateStatePath(env = process.env) {
|
|
72
|
+
return join(configDirectory(resolveConfigPath(env)), UPDATE_STATE_FILE);
|
|
73
|
+
}
|
|
74
|
+
export function createUpdateNotice(current, latest) {
|
|
75
|
+
return {
|
|
76
|
+
command: 'monkeys update',
|
|
77
|
+
current,
|
|
78
|
+
latest,
|
|
79
|
+
message: `monkeys ${latest} available, current ${current}, run: monkeys update`,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export function getPendingUpdateNotice() {
|
|
83
|
+
return pendingUpdateNotice;
|
|
84
|
+
}
|
|
85
|
+
export function clearPendingUpdateNotice() {
|
|
86
|
+
pendingUpdateNotice = undefined;
|
|
87
|
+
}
|
|
88
|
+
export function setPendingUpdateNotice(notice) {
|
|
89
|
+
pendingUpdateNotice = notice;
|
|
90
|
+
}
|
|
91
|
+
function parseUpdateState(value) {
|
|
92
|
+
if (typeof value !== 'object' || value === null)
|
|
93
|
+
return undefined;
|
|
94
|
+
const candidate = value;
|
|
95
|
+
if (!Number.isSafeInteger(candidate.checkedAt) || typeof candidate.latestVersion !== 'string')
|
|
96
|
+
return undefined;
|
|
97
|
+
if (!isReleaseVersion(candidate.latestVersion))
|
|
98
|
+
return undefined;
|
|
99
|
+
return { checkedAt: candidate.checkedAt, latestVersion: candidate.latestVersion };
|
|
100
|
+
}
|
|
101
|
+
export async function readUpdateState(path = updateStatePath()) {
|
|
102
|
+
try {
|
|
103
|
+
return parseUpdateState(JSON.parse(await readFile(path, 'utf8')));
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return undefined;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
async function atomicWrite(path, content) {
|
|
110
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
111
|
+
const temporary = `${path}.tmp-${process.pid}-${Date.now()}-${Math.random().toString(16).slice(2)}`;
|
|
112
|
+
let handle;
|
|
113
|
+
try {
|
|
114
|
+
handle = await open(temporary, 'wx', 0o600);
|
|
115
|
+
await handle.writeFile(content, 'utf8');
|
|
116
|
+
await handle.sync();
|
|
117
|
+
await handle.close();
|
|
118
|
+
handle = undefined;
|
|
119
|
+
await rename(temporary, path);
|
|
120
|
+
}
|
|
121
|
+
finally {
|
|
122
|
+
if (handle !== undefined)
|
|
123
|
+
await handle.close();
|
|
124
|
+
await rm(temporary, { force: true });
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
async function readLimitedBody(response) {
|
|
128
|
+
if (!response.body)
|
|
129
|
+
return '';
|
|
130
|
+
const reader = response.body.getReader();
|
|
131
|
+
const chunks = [];
|
|
132
|
+
let total = 0;
|
|
133
|
+
for (;;) {
|
|
134
|
+
const { done, value } = await reader.read();
|
|
135
|
+
if (done)
|
|
136
|
+
break;
|
|
137
|
+
total += value.byteLength;
|
|
138
|
+
if (total > MAX_RESPONSE_BYTES) {
|
|
139
|
+
await reader.cancel();
|
|
140
|
+
throw new Error('npm registry response exceeds the maximum allowed size');
|
|
141
|
+
}
|
|
142
|
+
chunks.push(value);
|
|
143
|
+
}
|
|
144
|
+
return Buffer.concat(chunks).toString('utf8');
|
|
145
|
+
}
|
|
146
|
+
export async function fetchLatestVersion(options = {}) {
|
|
147
|
+
const fetchImpl = options.fetchImpl ?? fetch;
|
|
148
|
+
const response = await fetchImpl(options.registryUrl ?? UPDATE_REGISTRY_URL, {
|
|
149
|
+
headers: { accept: 'application/json' },
|
|
150
|
+
signal: AbortSignal.timeout(options.timeoutMs ?? UPDATE_FETCH_TIMEOUT_MS),
|
|
151
|
+
});
|
|
152
|
+
if (!response.ok)
|
|
153
|
+
throw new Error(`npm registry returned HTTP ${response.status}`);
|
|
154
|
+
const body = JSON.parse(await readLimitedBody(response));
|
|
155
|
+
if (typeof body.version !== 'string' || !isReleaseVersion(body.version)) {
|
|
156
|
+
throw new Error('npm registry returned an invalid package version');
|
|
157
|
+
}
|
|
158
|
+
return body.version;
|
|
159
|
+
}
|
|
160
|
+
async function acquireRefreshLock(path, nowMs) {
|
|
161
|
+
await mkdir(dirname(path), { recursive: true, mode: 0o700 });
|
|
162
|
+
try {
|
|
163
|
+
const handle = await open(path, 'wx', 0o600);
|
|
164
|
+
await handle.writeFile(JSON.stringify({ createdAt: nowMs, pid: process.pid }));
|
|
165
|
+
return handle;
|
|
166
|
+
}
|
|
167
|
+
catch (error) {
|
|
168
|
+
if (!isNodeError(error, 'EEXIST'))
|
|
169
|
+
return undefined;
|
|
170
|
+
const existing = await stat(path).catch(() => undefined);
|
|
171
|
+
if (!existing || nowMs - existing.mtimeMs <= REFRESH_LOCK_STALE_MS)
|
|
172
|
+
return undefined;
|
|
173
|
+
await rm(path, { force: true });
|
|
174
|
+
try {
|
|
175
|
+
return await open(path, 'wx', 0o600);
|
|
176
|
+
}
|
|
177
|
+
catch {
|
|
178
|
+
return undefined;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
export async function refreshUpdateCache(currentVersion, options = {}) {
|
|
183
|
+
const env = options.env ?? process.env;
|
|
184
|
+
if (shouldSkipUpdateNotifier(currentVersion, env))
|
|
185
|
+
return false;
|
|
186
|
+
const path = options.statePath ?? updateStatePath(env);
|
|
187
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
188
|
+
const cached = await readUpdateState(path);
|
|
189
|
+
if (cached && nowMs - cached.checkedAt < UPDATE_CHECK_TTL_MS)
|
|
190
|
+
return false;
|
|
191
|
+
const lockPath = `${path}.lock`;
|
|
192
|
+
const lock = await acquireRefreshLock(lockPath, nowMs);
|
|
193
|
+
if (!lock)
|
|
194
|
+
return false;
|
|
195
|
+
try {
|
|
196
|
+
const latestState = await readUpdateState(path);
|
|
197
|
+
if (latestState && nowMs - latestState.checkedAt < UPDATE_CHECK_TTL_MS)
|
|
198
|
+
return false;
|
|
199
|
+
const latestVersion = await fetchLatestVersion(options);
|
|
200
|
+
await atomicWrite(path, `${JSON.stringify({ checkedAt: nowMs, latestVersion })}\n`);
|
|
201
|
+
return true;
|
|
202
|
+
}
|
|
203
|
+
catch {
|
|
204
|
+
return false;
|
|
205
|
+
}
|
|
206
|
+
finally {
|
|
207
|
+
await lock.close().catch(() => undefined);
|
|
208
|
+
await rm(lockPath, { force: true }).catch(() => undefined);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
export function scheduleUpdateCacheRefresh(currentVersion) {
|
|
212
|
+
try {
|
|
213
|
+
const worker = fileURLToPath(new URL('../../bin/update-cache.js', import.meta.url));
|
|
214
|
+
const child = spawn(process.execPath, [worker, currentVersion], {
|
|
215
|
+
detached: true,
|
|
216
|
+
env: process.env,
|
|
217
|
+
stdio: 'ignore',
|
|
218
|
+
windowsHide: true,
|
|
219
|
+
});
|
|
220
|
+
child.unref();
|
|
221
|
+
}
|
|
222
|
+
catch {
|
|
223
|
+
// Update discovery must never affect the requested command.
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
export async function initializeUpdateNotifier(currentVersion, options = {}) {
|
|
227
|
+
clearPendingUpdateNotice();
|
|
228
|
+
const env = options.env ?? process.env;
|
|
229
|
+
if (shouldSkipUpdateNotifier(currentVersion, env))
|
|
230
|
+
return undefined;
|
|
231
|
+
const path = options.statePath ?? updateStatePath(env);
|
|
232
|
+
const nowMs = options.nowMs ?? Date.now();
|
|
233
|
+
const state = await readUpdateState(path);
|
|
234
|
+
if (state && isNewerVersion(state.latestVersion, currentVersion)) {
|
|
235
|
+
setPendingUpdateNotice(createUpdateNotice(currentVersion, state.latestVersion));
|
|
236
|
+
}
|
|
237
|
+
if (!state || nowMs - state.checkedAt >= UPDATE_CHECK_TTL_MS) {
|
|
238
|
+
(options.scheduleRefresh ?? scheduleUpdateCacheRefresh)(currentVersion);
|
|
239
|
+
}
|
|
240
|
+
return getPendingUpdateNotice();
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=notifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notifier.js","sourceRoot":"","sources":["../../src/update/notifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export declare const MONKEYS_NPM_PACKAGE = "@inf-monkeys-tech/monkeys-cli";
|
|
2
|
+
export interface ProcessResult {
|
|
3
|
+
error?: Error;
|
|
4
|
+
status: number | null;
|
|
5
|
+
stderr: string;
|
|
6
|
+
stdout: string;
|
|
7
|
+
}
|
|
8
|
+
export type ProcessRunner = (command: string, args: string[]) => ProcessResult;
|
|
9
|
+
export interface InstallUpdateOptions {
|
|
10
|
+
packageName?: string;
|
|
11
|
+
runner?: ProcessRunner;
|
|
12
|
+
}
|
|
13
|
+
export interface InstallUpdateResult {
|
|
14
|
+
currentVersion: string;
|
|
15
|
+
packageRoot: string;
|
|
16
|
+
skillsAction: 'failed' | 'synced';
|
|
17
|
+
skillsWarning?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class UpdateProcessError extends Error {
|
|
20
|
+
readonly command: string;
|
|
21
|
+
readonly detail: string;
|
|
22
|
+
constructor(message: string, command: string, detail: string);
|
|
23
|
+
}
|
|
24
|
+
export declare function runUpdateProcess(command: string, args: string[]): ProcessResult;
|
|
25
|
+
export declare function installCliAndSkill(latestVersion: string, options?: InstallUpdateOptions): Promise<InstallUpdateResult>;
|
|
26
|
+
//# sourceMappingURL=updater.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.d.ts","sourceRoot":"","sources":["../../src/update/updater.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,mBAAmB,kCAAkC,CAAC;AAInE,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,aAAa,CAAC;AAE/E,MAAM,WAAW,oBAAoB;IACnC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,aAAa,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,QAAQ,GAAG,QAAQ,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,qBAAa,kBAAmB,SAAQ,KAAK;IAC3C,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAExB,YAAY,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAK3D;CACF;AAED,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,aAAa,CAe/E;AAuBD,wBAAsB,kBAAkB,CAAC,aAAa,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC,CAoDhI"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { spawnSync } from 'node:child_process';
|
|
2
|
+
import { readFile } from 'node:fs/promises';
|
|
3
|
+
import { isAbsolute, join } from 'node:path';
|
|
4
|
+
export const MONKEYS_NPM_PACKAGE = '@inf-monkeys-tech/monkeys-cli';
|
|
5
|
+
const UPDATE_PROCESS_TIMEOUT_MS = 120_000;
|
|
6
|
+
const MAX_PROCESS_DETAIL = 2_000;
|
|
7
|
+
export class UpdateProcessError extends Error {
|
|
8
|
+
command;
|
|
9
|
+
detail;
|
|
10
|
+
constructor(message, command, detail) {
|
|
11
|
+
super(message);
|
|
12
|
+
this.name = 'UpdateProcessError';
|
|
13
|
+
this.command = command;
|
|
14
|
+
this.detail = detail;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
export function runUpdateProcess(command, args) {
|
|
18
|
+
const windows = process.platform === 'win32';
|
|
19
|
+
const executable = windows ? (process.env.ComSpec ?? 'cmd.exe') : command;
|
|
20
|
+
const commandArgs = windows ? ['/d', '/s', '/c', command, ...args] : args;
|
|
21
|
+
const result = spawnSync(executable, commandArgs, {
|
|
22
|
+
encoding: 'utf8',
|
|
23
|
+
timeout: UPDATE_PROCESS_TIMEOUT_MS,
|
|
24
|
+
windowsHide: true,
|
|
25
|
+
});
|
|
26
|
+
return {
|
|
27
|
+
...(result.error ? { error: result.error } : {}),
|
|
28
|
+
status: result.status,
|
|
29
|
+
stderr: result.stderr ?? '',
|
|
30
|
+
stdout: result.stdout ?? '',
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function processDetail(result) {
|
|
34
|
+
return `${result.stdout}\n${result.stderr}`.trim().slice(0, MAX_PROCESS_DETAIL);
|
|
35
|
+
}
|
|
36
|
+
function requireSuccess(result, command, message) {
|
|
37
|
+
if (!result.error && result.status === 0)
|
|
38
|
+
return;
|
|
39
|
+
throw new UpdateProcessError(message, command, processDetail(result) || result.error?.message || 'unknown failure');
|
|
40
|
+
}
|
|
41
|
+
function parseGlobalRoot(result) {
|
|
42
|
+
requireSuccess(result, 'npm root --global', '无法确定 npm 全局安装目录。');
|
|
43
|
+
const lines = result.stdout
|
|
44
|
+
.split(/\r?\n/)
|
|
45
|
+
.map((line) => line.trim())
|
|
46
|
+
.filter(Boolean);
|
|
47
|
+
if (lines.length !== 1 || !isAbsolute(lines[0])) {
|
|
48
|
+
throw new UpdateProcessError('npm 返回了无效的全局安装目录。', 'npm root --global', processDetail(result));
|
|
49
|
+
}
|
|
50
|
+
return lines[0];
|
|
51
|
+
}
|
|
52
|
+
export async function installCliAndSkill(latestVersion, options = {}) {
|
|
53
|
+
const packageName = options.packageName ?? MONKEYS_NPM_PACKAGE;
|
|
54
|
+
const runner = options.runner ?? runUpdateProcess;
|
|
55
|
+
const installResult = runner('npm', ['install', '--global', `${packageName}@${latestVersion}`]);
|
|
56
|
+
requireSuccess(installResult, `npm install --global ${packageName}@${latestVersion}`, 'npm 全局升级失败。');
|
|
57
|
+
const globalRoot = parseGlobalRoot(runner('npm', ['root', '--global']));
|
|
58
|
+
const packageRoot = join(globalRoot, ...packageName.split('/'));
|
|
59
|
+
let manifest;
|
|
60
|
+
try {
|
|
61
|
+
manifest = JSON.parse(await readFile(join(packageRoot, 'package.json'), 'utf8'));
|
|
62
|
+
}
|
|
63
|
+
catch (error) {
|
|
64
|
+
throw new UpdateProcessError('无法验证升级后的 npm 包。', `read ${join(packageRoot, 'package.json')}`, error instanceof Error ? error.message : String(error));
|
|
65
|
+
}
|
|
66
|
+
if (manifest.name !== packageName || manifest.version !== latestVersion) {
|
|
67
|
+
throw new UpdateProcessError('升级后的 npm 包版本与目标版本不一致。', `read ${join(packageRoot, 'package.json')}`, JSON.stringify({
|
|
68
|
+
actualName: manifest.name,
|
|
69
|
+
actualVersion: manifest.version,
|
|
70
|
+
expectedName: packageName,
|
|
71
|
+
expectedVersion: latestVersion,
|
|
72
|
+
}));
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
await readFile(join(packageRoot, 'skills', 'monkeys', 'SKILL.md'), 'utf8');
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
throw new UpdateProcessError('升级后的 npm 包缺少 monkeys Skill。', `read ${join(packageRoot, 'skills', 'monkeys', 'SKILL.md')}`, error instanceof Error ? error.message : String(error));
|
|
79
|
+
}
|
|
80
|
+
const skillsResult = runner('npx', ['-y', 'skills', 'add', join(packageRoot, 'skills'), '-y', '-g', '--copy']);
|
|
81
|
+
if (skillsResult.error || skillsResult.status !== 0) {
|
|
82
|
+
return {
|
|
83
|
+
currentVersion: latestVersion,
|
|
84
|
+
packageRoot,
|
|
85
|
+
skillsAction: 'failed',
|
|
86
|
+
skillsWarning: `CLI 已升级,但 Skill 同步失败:${processDetail(skillsResult) || skillsResult.error?.message || 'unknown failure'}`,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
return { currentVersion: latestVersion, packageRoot, skillsAction: 'synced' };
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=updater.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"updater.js","sourceRoot":"","sources":["../../src/update/updater.ts"],"names":[],"mappings":"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"}
|
package/oclif.manifest.json
CHANGED
|
@@ -9206,6 +9206,55 @@
|
|
|
9206
9206
|
],
|
|
9207
9207
|
"strict": true
|
|
9208
9208
|
},
|
|
9209
|
+
"update": {
|
|
9210
|
+
"aliases": [],
|
|
9211
|
+
"args": {},
|
|
9212
|
+
"description": "检查或安装最新版本的 monkeys CLI,并同步同版本 Skill。",
|
|
9213
|
+
"enableJsonFlag": false,
|
|
9214
|
+
"examples": [
|
|
9215
|
+
"<%= config.bin %> update --check --output json",
|
|
9216
|
+
"<%= config.bin %> update"
|
|
9217
|
+
],
|
|
9218
|
+
"flags": {
|
|
9219
|
+
"check": {
|
|
9220
|
+
"allowNo": false,
|
|
9221
|
+
"name": "check",
|
|
9222
|
+
"summary": "只检查更新,不执行安装",
|
|
9223
|
+
"type": "boolean"
|
|
9224
|
+
},
|
|
9225
|
+
"force": {
|
|
9226
|
+
"allowNo": false,
|
|
9227
|
+
"name": "force",
|
|
9228
|
+
"summary": "即使已是最新版本也重新安装 CLI 与 Skill",
|
|
9229
|
+
"type": "boolean"
|
|
9230
|
+
},
|
|
9231
|
+
"output": {
|
|
9232
|
+
"default": "text",
|
|
9233
|
+
"hasDynamicHelp": false,
|
|
9234
|
+
"multiple": false,
|
|
9235
|
+
"name": "output",
|
|
9236
|
+
"options": [
|
|
9237
|
+
"json",
|
|
9238
|
+
"text"
|
|
9239
|
+
],
|
|
9240
|
+
"summary": "输出格式",
|
|
9241
|
+
"type": "option"
|
|
9242
|
+
}
|
|
9243
|
+
},
|
|
9244
|
+
"hasDynamicHelp": false,
|
|
9245
|
+
"hiddenAliases": [],
|
|
9246
|
+
"id": "update",
|
|
9247
|
+
"isESM": true,
|
|
9248
|
+
"pluginAlias": "@inf-monkeys-tech/monkeys-cli",
|
|
9249
|
+
"pluginName": "@inf-monkeys-tech/monkeys-cli",
|
|
9250
|
+
"pluginType": "core",
|
|
9251
|
+
"relativePath": [
|
|
9252
|
+
"dist",
|
|
9253
|
+
"commands",
|
|
9254
|
+
"update.js"
|
|
9255
|
+
],
|
|
9256
|
+
"strict": true
|
|
9257
|
+
},
|
|
9209
9258
|
"version:check": {
|
|
9210
9259
|
"aliases": [],
|
|
9211
9260
|
"args": {},
|
|
@@ -9876,5 +9925,5 @@
|
|
|
9876
9925
|
"strict": true
|
|
9877
9926
|
}
|
|
9878
9927
|
},
|
|
9879
|
-
"version": "0.10.
|
|
9928
|
+
"version": "0.10.4"
|
|
9880
9929
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inf-monkeys-tech/monkeys-cli",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.4",
|
|
4
4
|
"packageManager": "bun@1.3.14",
|
|
5
5
|
"description": "面向 AI Agent、自动化和人工操作的 Monkeys 命令行客户端",
|
|
6
6
|
"type": "module",
|
|
@@ -37,10 +37,11 @@
|
|
|
37
37
|
"smoke:installer": "node ./scripts/install-wizard-smoke.mjs",
|
|
38
38
|
"smoke:npm": "node ./scripts/npm-install-smoke.mjs",
|
|
39
39
|
"smoke:standalone": "node ./scripts/standalone-smoke.mjs",
|
|
40
|
+
"smoke:update": "node ./scripts/update-notifier-smoke.mjs",
|
|
40
41
|
"test": "vitest run",
|
|
41
42
|
"test:watch": "vitest",
|
|
42
|
-
"verify": "bun run format:check && bun run lint && bun run test && bun run build && bun run version:smoke && bun run smoke:installer && bun run smoke:npm && bun run benchmark",
|
|
43
|
-
"version:smoke": "node ./
|
|
43
|
+
"verify": "bun run format:check && bun run lint && bun run test && bun run build && bun run version:smoke && bun run smoke:update && bun run smoke:installer && bun run smoke:npm && bun run benchmark",
|
|
44
|
+
"version:smoke": "node ./scripts/version-smoke.mjs"
|
|
44
45
|
},
|
|
45
46
|
"oclif": {
|
|
46
47
|
"bin": "monkeys",
|
|
@@ -86,5 +87,5 @@
|
|
|
86
87
|
"publishConfig": {
|
|
87
88
|
"access": "public"
|
|
88
89
|
},
|
|
89
|
-
"monkeysReleaseCommit": "
|
|
90
|
+
"monkeysReleaseCommit": "648e57673fad23c8cc34421cde54cac0e1045c81"
|
|
90
91
|
}
|
package/skills/monkeys/SKILL.md
CHANGED
|
@@ -9,7 +9,7 @@ description: 理解并通过 monkeys CLI 安全操作 Monkeys 平台的多租户
|
|
|
9
9
|
|
|
10
10
|
## 执行流程
|
|
11
11
|
|
|
12
|
-
1. 运行 `monkeys version show --output json`,确认 CLI 可用和命令 Schema
|
|
12
|
+
1. 运行 `monkeys version show --output json`,确认 CLI 可用和命令 Schema 兼容。若输出包含 `_notice.update`,向用户报告新版本和 `monkeys update`;只有用户明确同意升级后才执行该全局安装命令。
|
|
13
13
|
2. 选择明确的 `--profile`。Data 任务按[Data 视角路由](references/data-perspective.md)选择显式 `--perspective`:Kernel 全局读取默认不传 `--team`,只有用户明确筛选时才传;Field、View、Feature Value、Advanced Search 和 Asset Export 等需要数据资源定位时传已确认的 `--resource-team`。Studio 使用明确的 Team 上下文。不要在任务中途隐式切换上下文。
|
|
14
14
|
3. 在第一次使用命令或参数不确定时运行 `monkeys <命令> --help`。以 CLI 帮助为参数真相,不凭记忆补参数。
|
|
15
15
|
4. 优先调用 Workflow、Execution、Agent Work、File、Data、System Config 等语义命令,并使用 `--output json`。解析结构化结果和退出码,不解析面向人的 Text 文案。
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
- 本 Skill 面向命令 Schema Major `1`,最低 CLI 版本 `0.10.0`。
|
|
4
4
|
- 开始任务时运行 `monkeys version show --output json`。
|
|
5
|
+
- 任意结构化输出中的 `_notice.update` 表示 npm `latest` 高于当前 CLI;报告 `current`、`latest` 与 `command`。可用 `monkeys update --check --output json` 实时复核,只有用户明确授权后才运行 `monkeys update` 或 `monkeys update --force`。
|
|
6
|
+
- `monkeys update` 升级全局 npm 包后,从新包的全局安装目录同步同版本 `monkeys` Skill;若 CLI 已升级但 `skillsAction=failed`,报告警告并在用户同意后用 `monkeys update --force` 重试,不回滚或猜测 Skill 路径。
|
|
5
7
|
- CLI Major、命令 Schema Major 或 Skill 声明不兼容时停止写操作,升级匹配版本后再继续。
|
|
6
8
|
- OpenAPI Snapshot 可动态刷新,但语义命令合同不会因刷新而被静默改写。
|
|
7
9
|
- Data 合同由 Deployment 的 `data_contract=auto|ontology-v1|bucket-v1` 决定;`auto` 依次采用精确 OpenAPI、同一上下文缓存和有界只读探测。只有 Ontology 路由明确返回 404 时才探测旧 Bucket 路由。
|