weaver-work-cli 0.1.1 → 0.1.2
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 +15 -2
- package/dist/internal/e10/auth/commands.js +1 -1
- package/dist/internal/e10/auth/crypto.js +7 -22
- package/dist/internal/e10/auth/session.js +1 -1
- package/dist/shortcuts/invoice/index.js +7 -2
- package/dist/shortcuts/invoice/manifest.js +22 -11
- package/dist/shortcuts/invoice/operations/ocr-preview.js +6 -3
- package/dist/shortcuts/invoice/operations/shared.js +24 -6
- package/dist/shortcuts/invoice/operations/validate-preview.js +1 -1
- package/docs/_catalog.md +1 -0
- package/docs/agent-invoice.md +12 -1
- package/docs/agent-skill-install.md +92 -0
- package/docs/invoice.md +9 -4
- package/package.json +1 -1
- package/skill-template/domains/shared.md +6 -2
- package/skill-template/skill-template.md +15 -0
- package/skills/weaver-work-cli-invoice/SKILL.md +21 -2
- package/skills/weaver-work-cli-invoice/references/invoice-agent-entry.md +2 -0
- package/skills/weaver-work-cli-invoice/references/invoice-download.md +2 -0
- package/skills/weaver-work-cli-invoice/references/invoice-enterprise-list.md +6 -4
- package/skills/weaver-work-cli-invoice/references/invoice-file-upload.md +6 -2
- package/skills/weaver-work-cli-invoice/references/invoice-import.md +10 -2
- package/skills/weaver-work-cli-invoice/references/invoice-ocr-preview.md +2 -0
- package/skills/weaver-work-cli-invoice/references/invoice-personal-list.md +8 -5
- package/skills/weaver-work-cli-invoice/references/invoice-validation-preview.md +1 -1
- package/skills/weaver-work-cli-shared/SKILL.md +16 -6
- package/skills/weaver-work-cli-shared/references/e10-auth-and-session.md +8 -1
- package/skills/weaver-work-cli-shared/references/json-output-contract.md +25 -0
- package/skills/weaver-work-cli-shared/references/weaver-work-cli-installation.md +13 -1
package/README.md
CHANGED
|
@@ -91,7 +91,15 @@ weaver-work-cli skills install invoice
|
|
|
91
91
|
`skills install invoice` 会同时安装 `weaver-work-cli-shared` 和
|
|
92
92
|
`weaver-work-cli-invoice`。默认目标目录是 `$CODEX_HOME/skills`,未设置
|
|
93
93
|
`CODEX_HOME` 时使用 `~/.codex/skills`;需要自定义时可加
|
|
94
|
-
`--target-dir <path
|
|
94
|
+
`--target-dir <path>`。默认目标面向 Codex CLI;WorkBuddy 等桌面 Agent 的
|
|
95
|
+
用户级 Skill 目录不是默认目标,需显式指定:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
weaver-work-cli skills install invoice --target-dir ~/.workbuddy/skills
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
各 Agent 环境的 skill 目录、从本地开发仓库升级到最新版的完整流程与验证
|
|
102
|
+
步骤见 `docs/agent-skill-install.md`。
|
|
95
103
|
|
|
96
104
|
卸载全局命令:
|
|
97
105
|
|
|
@@ -315,7 +323,10 @@ weaver-work-cli --json invoice download --fid <fid> --file-id <fileId> --output
|
|
|
315
323
|
写操作固定使用 `prepare -> apply`:
|
|
316
324
|
|
|
317
325
|
```bash
|
|
318
|
-
echo '{"file":"./invoice.pdf"
|
|
326
|
+
echo '{"file":"./invoice.pdf"}' \
|
|
327
|
+
| weaver-work-cli --json invoice run invoice.ocr.preview --input -
|
|
328
|
+
|
|
329
|
+
echo '{"file":"./invoice.pdf","validate":true,"syncToOa":true}' \
|
|
319
330
|
| weaver-work-cli --json invoice import prepare --input -
|
|
320
331
|
|
|
321
332
|
echo '{"file":"./invoice.pdf","continuation":"<prepare返回值>","confirm":true}' \
|
|
@@ -324,6 +335,8 @@ echo '{"file":"./invoice.pdf","continuation":"<prepare返回值>","confirm":true
|
|
|
324
335
|
|
|
325
336
|
Agent 应优先调用 `weaver-work-cli --json invoice run <operation> --input -`,并读取 `weaver-work-cli invoice schema` 获取 operation 契约。共享、转让和标签接口因缺少稳定 ID 来源和写后回查契约,当前不暴露给 Agent。
|
|
326
337
|
|
|
338
|
+
输出处理参考飞书 CLI 的 Agent 友好实践,但当前项目仍是轻量输出层:`ctx.output.write` 在 JSON 模式下直接把完整 envelope 打到 stdout,失败写 stderr;暂未提供通用 `--jq`、`--format table/ndjson` 或 `--page-all`。因此业务 Skill 会预先要求 Agent 控制响应量:列表默认 `page_size=10`,按业务分页字段继续;给用户只渲染摘要、关键字段、数量和下一步,超长详情/OCR/调试 JSON 优先落本地文件并返回路径。
|
|
339
|
+
|
|
327
340
|
如需交付通用 Agent Skill 包:
|
|
328
341
|
|
|
329
342
|
```bash
|
|
@@ -128,7 +128,7 @@ async function resolveUserInfo(baseUrl, eteamsId, rawCookie = '', agentType = ''
|
|
|
128
128
|
'content-type': 'application/json',
|
|
129
129
|
eteamsid: eteamsId,
|
|
130
130
|
cookie: buildE10CookieHeader(rawCookie, eteamsId, agentType),
|
|
131
|
-
'user-agent': agentType ? `AgentType=${agentType},IsAgent=true` :
|
|
131
|
+
'user-agent': agentType ? `AgentType=${agentType},IsAgent=true` : DEFAULT_AGENT_TYPE,
|
|
132
132
|
origin: baseUrl,
|
|
133
133
|
},
|
|
134
134
|
redirect: 'manual',
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';
|
|
2
2
|
import { existsSync, mkdirSync, readFileSync } from 'node:fs';
|
|
3
|
-
import { homedir } from 'node:os';
|
|
4
3
|
import { resolve } from 'node:path';
|
|
5
4
|
import { Entry as KeyringEntry } from '@napi-rs/keyring';
|
|
6
5
|
import { writeWithRetry } from '../../../core/write-with-retry.js';
|
|
@@ -9,15 +8,11 @@ const ALGORITHM = 'aes-256-gcm';
|
|
|
9
8
|
const IV_LENGTH = 12;
|
|
10
9
|
const TAG_LENGTH = 16;
|
|
11
10
|
const KEYCHAIN_SERVICE = 'weaver-work-cli';
|
|
12
|
-
const LEGACY_KEYCHAIN_SERVICE = 'e10-cli';
|
|
13
11
|
const KEYCHAIN_ACCOUNT = 'auth-key';
|
|
14
12
|
let encKey = null;
|
|
15
13
|
function getKeyFilePath() {
|
|
16
14
|
return resolve(getE10AuthRoot(), '.key');
|
|
17
15
|
}
|
|
18
|
-
function getLegacyKeyFilePath() {
|
|
19
|
-
return resolve(homedir(), '.e10-cli', '.key');
|
|
20
|
-
}
|
|
21
16
|
function readKeychainKey(service) {
|
|
22
17
|
try {
|
|
23
18
|
const entry = new KeyringEntry(service, KEYCHAIN_ACCOUNT);
|
|
@@ -73,13 +68,6 @@ function getEncKey() {
|
|
|
73
68
|
writeWithRetry(keyFile, encKey.toString('base64'), { mode: 0o600 });
|
|
74
69
|
return encKey;
|
|
75
70
|
}
|
|
76
|
-
function getDecryptKeys() {
|
|
77
|
-
const keys = [getEncKey()];
|
|
78
|
-
const legacyKey = readKeychainKey(LEGACY_KEYCHAIN_SERVICE) || readKeyFile(getLegacyKeyFilePath());
|
|
79
|
-
if (legacyKey && !keys.some((key) => key.equals(legacyKey)))
|
|
80
|
-
keys.push(legacyKey);
|
|
81
|
-
return keys;
|
|
82
|
-
}
|
|
83
71
|
export function encryptAuthData(plaintext) {
|
|
84
72
|
const iv = randomBytes(IV_LENGTH);
|
|
85
73
|
const cipher = createCipheriv(ALGORITHM, getEncKey(), iv, { authTagLength: TAG_LENGTH });
|
|
@@ -95,17 +83,14 @@ export function decryptAuthData(wrapper) {
|
|
|
95
83
|
const iv = combined.subarray(0, IV_LENGTH);
|
|
96
84
|
const tag = combined.subarray(combined.length - TAG_LENGTH);
|
|
97
85
|
const encrypted = combined.subarray(IV_LENGTH, combined.length - TAG_LENGTH);
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
// Try the next known key.
|
|
106
|
-
}
|
|
86
|
+
try {
|
|
87
|
+
const decipher = createDecipheriv(ALGORITHM, getEncKey(), iv, { authTagLength: TAG_LENGTH });
|
|
88
|
+
decipher.setAuthTag(tag);
|
|
89
|
+
return Buffer.concat([decipher.update(encrypted), decipher.final()]).toString('utf-8');
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return null;
|
|
107
93
|
}
|
|
108
|
-
return null;
|
|
109
94
|
}
|
|
110
95
|
export function parseAuthFile(raw) {
|
|
111
96
|
try {
|
|
@@ -254,7 +254,7 @@ export class E10AuthSession {
|
|
|
254
254
|
return buildE10CookieHeader(raw, this.eteamsId, this.agentType);
|
|
255
255
|
}
|
|
256
256
|
uaHeader() {
|
|
257
|
-
return this.agentType ? `AgentType=${this.agentType},IsAgent=true` : '
|
|
257
|
+
return this.agentType ? `AgentType=${this.agentType},IsAgent=true` : 'weaver-work-cli';
|
|
258
258
|
}
|
|
259
259
|
toJSON() {
|
|
260
260
|
return {
|
|
@@ -48,6 +48,11 @@ function intOption(value) {
|
|
|
48
48
|
const parsed = Number(value);
|
|
49
49
|
return Number.isInteger(parsed) ? parsed : undefined;
|
|
50
50
|
}
|
|
51
|
+
function stringOption(value) {
|
|
52
|
+
if (value === undefined || value === null || value === '')
|
|
53
|
+
return undefined;
|
|
54
|
+
return String(value);
|
|
55
|
+
}
|
|
51
56
|
function successEnvelope(operation, result) {
|
|
52
57
|
return {
|
|
53
58
|
schemaVersion: 1,
|
|
@@ -111,7 +116,7 @@ export const invoiceShortcut = {
|
|
|
111
116
|
content: opts.content,
|
|
112
117
|
page_size: intOption(opts.pageSize),
|
|
113
118
|
start_pos: intOption(opts.startPos),
|
|
114
|
-
sreim:
|
|
119
|
+
sreim: stringOption(opts.sreim),
|
|
115
120
|
}));
|
|
116
121
|
}));
|
|
117
122
|
const enterprise = invoice.command('enterprise').description('Enterprise invoice folder commands');
|
|
@@ -128,7 +133,7 @@ export const invoiceShortcut = {
|
|
|
128
133
|
content: opts.content,
|
|
129
134
|
page_size: intOption(opts.pageSize),
|
|
130
135
|
start_pos: intOption(opts.startPos),
|
|
131
|
-
sreim:
|
|
136
|
+
sreim: stringOption(opts.sreim),
|
|
132
137
|
}));
|
|
133
138
|
}));
|
|
134
139
|
invoice.command('get')
|
|
@@ -20,10 +20,10 @@ const listProperties = {
|
|
|
20
20
|
total_end: { type: 'string', pattern: '^\\d+(\\.\\d{1,2})?$' },
|
|
21
21
|
attribute: { type: 'integer', enum: [0, 1, 2] },
|
|
22
22
|
sreim: {
|
|
23
|
-
type: '
|
|
24
|
-
enum: [0, 1, 2, 3, 4],
|
|
25
|
-
default: 3,
|
|
26
|
-
description: '
|
|
23
|
+
type: 'string',
|
|
24
|
+
enum: ['0', '1', '2', '3', '4'],
|
|
25
|
+
default: '3',
|
|
26
|
+
description: '报销状态筛选。默认不要传本字段,CLI 会使用 "3"=未报销发票;只有用户明确要求全部/报销中/已报销/不可报销时才传。取值:"0"=全部发票,"1"=发票报销中,"2"=报销完成,"3"=未报销发票,"4"=不可报销',
|
|
27
27
|
},
|
|
28
28
|
valids: { type: 'array', items: { type: 'integer', enum: [0, 1, 2, 3, 4, 5] } },
|
|
29
29
|
sources: { type: 'array', items: { type: 'integer' } },
|
|
@@ -43,21 +43,26 @@ const listProperties = {
|
|
|
43
43
|
required: ['sort_type', 'sort'],
|
|
44
44
|
},
|
|
45
45
|
},
|
|
46
|
-
bill_type: {
|
|
46
|
+
bill_type: {
|
|
47
|
+
type: 'integer',
|
|
48
|
+
enum: [0, 1],
|
|
49
|
+
default: 0,
|
|
50
|
+
description: '票据类型:0=发票,1=凭证。默认不要传本字段,CLI 会使用 0 查询发票;只有用户明确要求查凭证时才传 1。',
|
|
51
|
+
},
|
|
47
52
|
};
|
|
48
53
|
export const invoiceOperations = [
|
|
49
54
|
{
|
|
50
55
|
name: 'invoice.list',
|
|
51
56
|
risk: 'read',
|
|
52
57
|
scope: 'personal',
|
|
53
|
-
fixed: { flag: 0, defaultSreim: 3 },
|
|
58
|
+
fixed: { flag: 0, defaultSreim: '3', defaultBillType: 0 },
|
|
54
59
|
inputSchema: { type: 'object', additionalProperties: false, properties: listProperties },
|
|
55
60
|
},
|
|
56
61
|
{
|
|
57
62
|
name: 'invoice.enterprise.list',
|
|
58
63
|
risk: 'read',
|
|
59
64
|
scope: 'enterprise',
|
|
60
|
-
fixed: { flag: 6, defaultSreim: 3 },
|
|
65
|
+
fixed: { flag: 6, defaultSreim: '3', defaultBillType: 0 },
|
|
61
66
|
inputSchema: { type: 'object', additionalProperties: false, properties: listProperties },
|
|
62
67
|
},
|
|
63
68
|
{
|
|
@@ -76,7 +81,7 @@ export const invoiceOperations = [
|
|
|
76
81
|
{
|
|
77
82
|
name: 'invoice.upload',
|
|
78
83
|
risk: 'external-artifact',
|
|
79
|
-
fixed: { ocr:
|
|
84
|
+
fixed: { ocr: 0 },
|
|
80
85
|
inputSchema: {
|
|
81
86
|
type: 'object',
|
|
82
87
|
additionalProperties: false,
|
|
@@ -106,7 +111,7 @@ export const invoiceOperations = [
|
|
|
106
111
|
{
|
|
107
112
|
name: 'invoice.validate.preview',
|
|
108
113
|
risk: 'external-read',
|
|
109
|
-
fixed: { flag: 100, is_save: 1, needLog:
|
|
114
|
+
fixed: { flag: 100, is_save: 1, needLog: true },
|
|
110
115
|
inputSchema: {
|
|
111
116
|
type: 'object',
|
|
112
117
|
additionalProperties: false,
|
|
@@ -125,8 +130,14 @@ export const invoiceOperations = [
|
|
|
125
130
|
additionalProperties: false,
|
|
126
131
|
properties: {
|
|
127
132
|
file: { type: 'string', minLength: 1 },
|
|
128
|
-
validate: {
|
|
129
|
-
|
|
133
|
+
validate: {
|
|
134
|
+
type: 'boolean',
|
|
135
|
+
description: '是否在导入时请求服务端查验。正常上传发票流程默认应传 true;只有用户明确要求跳过查验时才传 false。',
|
|
136
|
+
},
|
|
137
|
+
syncToOa: {
|
|
138
|
+
type: 'boolean',
|
|
139
|
+
description: '是否同步到 OA。validate=true 时必须为 true;正常导入推荐传 true。',
|
|
140
|
+
},
|
|
130
141
|
},
|
|
131
142
|
required: ['file', 'validate', 'syncToOa'],
|
|
132
143
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { InvoiceCliError, invoiceValidationError } from '../errors.js';
|
|
2
|
+
import { toErrorEnvelope } from '../../../core/errors.js';
|
|
2
3
|
import { previewOcr, uploadFromInput, uploadInvoiceFile, workflow } from './shared.js';
|
|
3
4
|
export class InvoiceOcrPreviewOperation {
|
|
4
5
|
name = 'invoice.ocr.preview';
|
|
@@ -10,16 +11,18 @@ export class InvoiceOcrPreviewOperation {
|
|
|
10
11
|
throw invoiceValidationError('input_ambiguous', 'upload 与 file/url 只能选择一种来源');
|
|
11
12
|
}
|
|
12
13
|
const suppliedUpload = uploadFromInput(input);
|
|
13
|
-
const upload = suppliedUpload || await uploadInvoiceFile(input, host);
|
|
14
|
+
const upload = suppliedUpload || await uploadInvoiceFile(input, host, { ocr: true });
|
|
14
15
|
let ocr;
|
|
15
16
|
try {
|
|
16
17
|
ocr = await previewOcr(upload, host);
|
|
17
18
|
}
|
|
18
19
|
catch (error) {
|
|
19
20
|
if (!suppliedUpload) {
|
|
20
|
-
|
|
21
|
+
const cause = toErrorEnvelope(error);
|
|
22
|
+
throw new InvoiceCliError('partial', 'artifact_uploaded', `文件已上传但 OCR 预览失败:${cause.message}`, {
|
|
23
|
+
code: cause.code,
|
|
21
24
|
partialData: { upload, workflow: workflow('invoice.ocr.preview', 'OCR_RUNNING') },
|
|
22
|
-
details: { stage: 'ocr' },
|
|
25
|
+
details: { stage: 'ocr', cause },
|
|
23
26
|
exitCode: 11,
|
|
24
27
|
});
|
|
25
28
|
}
|
|
@@ -366,12 +366,12 @@ function normalizeUploadResponse(value, source) {
|
|
|
366
366
|
fail: false,
|
|
367
367
|
};
|
|
368
368
|
}
|
|
369
|
-
export async function uploadInvoiceFile(input, host) {
|
|
369
|
+
export async function uploadInvoiceFile(input, host, options = {}) {
|
|
370
370
|
const source = uploadSource(input);
|
|
371
371
|
const prepared = await normalizeFileSource(source);
|
|
372
372
|
const result = await host.invoiceMultipartRequest({
|
|
373
373
|
path: '/api/inc/file/uploadFileSpilit',
|
|
374
|
-
fields: { ...prepared.fields, ocr: '1' },
|
|
374
|
+
fields: { ...prepared.fields, ocr: options.ocr ? '1' : '0' },
|
|
375
375
|
file: prepared.file,
|
|
376
376
|
});
|
|
377
377
|
return normalizeUploadResponse(result, source);
|
|
@@ -406,8 +406,19 @@ function ocrInfo(result) {
|
|
|
406
406
|
const infos = Array.isArray(result?.infos) ? result.infos : [];
|
|
407
407
|
const failed = infos.filter((item) => item?.ret?.ret !== 0);
|
|
408
408
|
if (failed.length) {
|
|
409
|
-
|
|
410
|
-
|
|
409
|
+
const first = failed[0]?.ret || {};
|
|
410
|
+
const message = typeof first.message === 'string' && first.message.trim()
|
|
411
|
+
? first.message
|
|
412
|
+
: '部分文件页 OCR 失败';
|
|
413
|
+
throw new InvoiceCliError('api', 'ocr_item_failed', message, {
|
|
414
|
+
code: first.ret,
|
|
415
|
+
details: {
|
|
416
|
+
failed: failed.map((item) => ({
|
|
417
|
+
code: item?.ret?.ret,
|
|
418
|
+
message: item?.ret?.message || 'OCR 失败',
|
|
419
|
+
lang: item?.ret?.lang,
|
|
420
|
+
})),
|
|
421
|
+
},
|
|
411
422
|
exitCode: 1,
|
|
412
423
|
});
|
|
413
424
|
}
|
|
@@ -458,13 +469,13 @@ export async function previewOcr(upload, host) {
|
|
|
458
469
|
return { results, invoices };
|
|
459
470
|
}
|
|
460
471
|
export async function listInvoices(input, host, flag) {
|
|
461
|
-
const body = { flag, page_size: 10, start_pos: 0, req_type: 1, sreim: 3, req_base: reqBase() };
|
|
472
|
+
const body = { flag, page_size: 10, start_pos: 0, req_type: 1, sreim: '3', bill_type: 0, req_base: reqBase() };
|
|
462
473
|
for (const [key, value] of Object.entries(input)) {
|
|
463
474
|
if (key === 'flag')
|
|
464
475
|
continue;
|
|
465
476
|
if (!LIST_FIELDS.has(key))
|
|
466
477
|
throw invoiceValidationError('input_field_unsupported', `列表查询不支持字段:${key}`);
|
|
467
|
-
body[key] = value;
|
|
478
|
+
body[key] = key === 'sreim' ? normalizeSreim(value) : value;
|
|
468
479
|
}
|
|
469
480
|
const result = await host.invoiceRequest({ path: '/api/inc/sync', method: 'POST', body });
|
|
470
481
|
return {
|
|
@@ -479,6 +490,13 @@ export async function listInvoices(input, host, flag) {
|
|
|
479
490
|
},
|
|
480
491
|
};
|
|
481
492
|
}
|
|
493
|
+
function normalizeSreim(value) {
|
|
494
|
+
const normalized = typeof value === 'number' && Number.isInteger(value) ? String(value) : value;
|
|
495
|
+
if (typeof normalized !== 'string' || !/^[0-4]$/u.test(normalized)) {
|
|
496
|
+
throw invoiceValidationError('invoice_field_invalid', 'sreim 必须是字符串 "0"、"1"、"2"、"3" 或 "4"');
|
|
497
|
+
}
|
|
498
|
+
return normalized;
|
|
499
|
+
}
|
|
482
500
|
export function normalizeAddInfo(rawInfo) {
|
|
483
501
|
const info = structuredClone(asObject(rawInfo, 'info'));
|
|
484
502
|
assertNoForbiddenKeys(info, 'info');
|
package/docs/_catalog.md
CHANGED
|
@@ -8,5 +8,6 @@
|
|
|
8
8
|
| Agent 共享规则、安装检查、JSON 输出、高风险写入 | `skills/weaver-work-cli-shared/SKILL.md` |
|
|
9
9
|
| Agent 共享规则细节:安装、E10 登录、JSON 输出、写入协议 | `skills/weaver-work-cli-shared/references/` |
|
|
10
10
|
| 业票通发票管理、invoice operation、写操作 prepare/apply | `docs/invoice.md` |
|
|
11
|
+
| 把随包 Agent Skill 安装/升级到本机 Agent(Codex/WorkBuddy 目录、从本地仓库发布最新版) | `docs/agent-skill-install.md` |
|
|
11
12
|
| Agent 调用业票通 CLI 的入口路由 | `skills/weaver-work-cli-invoice/SKILL.md` |
|
|
12
13
|
| Agent 调用业票通 CLI 的具体 reference | `skills/weaver-work-cli-invoice/references/` |
|
package/docs/agent-invoice.md
CHANGED
|
@@ -32,16 +32,27 @@ weaver-work-cli --json invoice run <operation> --input -
|
|
|
32
32
|
|
|
33
33
|
不要直接 `curl`、`fetch` 或浏览器自动化访问 E10 `/api/inc/*`。不要输出或索取 Cookie、ETEAMSID、发票 Token。
|
|
34
34
|
|
|
35
|
+
## 输出与大数据处理
|
|
36
|
+
|
|
37
|
+
当前项目的输出方式是 JSON envelope 直接写 stdout,失败 envelope 写 stderr;不像飞书 CLI 已内置 `--format table/pretty/ndjson`、`--jq` 和通用翻页参数。因此 Agent 调用时要主动控量:
|
|
38
|
+
|
|
39
|
+
- 列表默认 `page_size=10`,需要更多时再按 `start_pos` 分页。
|
|
40
|
+
- 回复用户时只展示结论、数量、关键字段和下一步,不要原样粘完整 stdout JSON。
|
|
41
|
+
- 发票列表/详情优先展示 `fid`、代码/号码、购销方、金额、日期、查验/报销状态和附件摘要。
|
|
42
|
+
- 全量统计按页读取并只累计必要字段;超长 OCR、详情或调试 JSON 需要保留时落本地文件,再返回路径和摘要。
|
|
43
|
+
|
|
35
44
|
## 推荐工作流
|
|
36
45
|
|
|
37
46
|
处理“把这张发票录入业票通”的典型流程:
|
|
38
47
|
|
|
39
48
|
1. 查询个人票夹和企业票夹,确认目标不存在。
|
|
40
49
|
2. `invoice.ocr.preview` 预览文件识别结果,预览阶段固定不保存。
|
|
41
|
-
3. 用户确认后执行 `invoice.import.prepare`,输入必须显式包含 `validate` 和 `syncToOa
|
|
50
|
+
3. 用户确认后执行 `invoice.import.prepare`,输入必须显式包含 `validate` 和 `syncToOa`;默认传 `validate=true`、`syncToOa=true`,表示导入时请求服务端查验并按服务端要求同步 OA。
|
|
42
51
|
4. 把 prepare 返回的 `continuation` 原样交给 `invoice.import.apply`,并传 `confirm=true`。
|
|
43
52
|
5. 使用返回的 `fid` 回查详情,按实际结果报告查验状态、写入状态和附件信息。
|
|
44
53
|
|
|
54
|
+
只有用户明确要求跳过发票查验或离线导入时,Agent 才能传 `validate=false`。这种结果必须报告为“跳过查验”,不能写成“查验通过”。
|
|
55
|
+
|
|
45
56
|
删除、编辑、新增同样必须使用 `prepare -> apply`。出现 `partial/write_uncertain` 时停止,不能自动重试写操作。
|
|
46
57
|
|
|
47
58
|
## 暂缓能力
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# Agent Skill 安装与升级
|
|
2
|
+
|
|
3
|
+
本文说明如何把 `weaver-work-cli` 随包 Agent Skill(以 `invoice` 为例)安装或升级到本机 Agent 的 skill 目录。适用两类读者:
|
|
4
|
+
|
|
5
|
+
- 首次让 Codex / WorkBuddy 等 Agent 识别发票业务的使用者;
|
|
6
|
+
- 在本仓库修改 Skill 内容后,需要把最新版同步到本机 Agent 环境的开发者。
|
|
7
|
+
|
|
8
|
+
Agent 运行期调用规则不在这里,见 `skills/weaver-work-cli-shared/SKILL.md` 与 `skills/weaver-work-cli-invoice/SKILL.md`。人类视角的安装总览见 `README.md`。
|
|
9
|
+
|
|
10
|
+
## 最短命令
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
weaver-work-cli skills install invoice --target-dir <目标skills目录>
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
- `skills install invoice` 会同时安装 `weaver-work-cli-shared` 与 `weaver-work-cli-invoice`,无需分别安装。
|
|
17
|
+
- 默认目标为 `$CODEX_HOME/skills`(未设置时 `~/.codex/skills`);其它目录必须用 `--target-dir <path>` 显式指定。
|
|
18
|
+
- 安装是文件拷贝,不需要 E10 登录;登录只在执行业务命令(`invoice run ...`)前需要。
|
|
19
|
+
|
|
20
|
+
## 各 Agent 环境的 skill 目录
|
|
21
|
+
|
|
22
|
+
| Agent 环境 | skill 根目录 | 安装方式 |
|
|
23
|
+
| --- | --- | --- |
|
|
24
|
+
| Codex CLI | `$CODEX_HOME/skills`,默认 `~/.codex/skills` | `skills install invoice`(默认目标) |
|
|
25
|
+
| WorkBuddy(桌面端) | `~/.workbuddy/skills`(用户级) | `skills install invoice --target-dir ~/.workbuddy/skills` |
|
|
26
|
+
| 其它 Agent | 由 Agent 配置决定 | `skills install invoice --target-dir <path>` |
|
|
27
|
+
|
|
28
|
+
不确定 Agent 读哪个目录时先问用户,不要盲目同时安装到多个目录。装到 `~/.workbuddy/skills` 不会同步 `~/.codex/skills`,反之亦然。
|
|
29
|
+
|
|
30
|
+
## 核心事实(先读,避免误操作)
|
|
31
|
+
|
|
32
|
+
1. **内容源是包内 `skills/` 目录**,不经过编译;`npm run build` 只保证 CLI 代码通过构建期 TS 校验,不产出 Skill。
|
|
33
|
+
2. **`skills install` 是拷贝语义**:装出的是真实副本,不与源目录联动。之后源里改动 Skill,已安装目录不会自动更新,需重跑安装;覆盖安装只写入与覆盖同名文件,**不会清理目标里已不存在的旧文件**,需要干净结果时先整目录移除再安装。
|
|
34
|
+
3. **目标目录已有旧条目(旧副本或软链)时不能直接覆盖**:命令内部是递归拷贝,目标为软链时会报 `ERR_FS_CP_DIR_TO_NON_DIR` 失败;先移除该条目再安装(移除软链只断链,不影响其指向的目录)。
|
|
35
|
+
4. **本机 CLI 若为 `npm link` 指向本地仓库**,`skills list/install` 反映的是仓库当前工作区内容,包含未提交改动——开发期可直接发布最新工作区。
|
|
36
|
+
5. 拷贝会过滤 dotfiles、`scripts/`、`assets/`、`node_modules/`;`SKILL.md`、`references/`、`product.json` 会完整拷贝。
|
|
37
|
+
|
|
38
|
+
## 首次安装
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
# 1. 确认命令可用且能看到随包 Skill
|
|
42
|
+
weaver-work-cli --version
|
|
43
|
+
weaver-work-cli skills list
|
|
44
|
+
|
|
45
|
+
# 2. 安装到目标目录(示例:WorkBuddy)
|
|
46
|
+
weaver-work-cli skills install invoice --target-dir ~/.workbuddy/skills
|
|
47
|
+
|
|
48
|
+
# 3. 验证:结果是真实目录,不是软链
|
|
49
|
+
ls -la ~/.workbuddy/skills/
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
## 从本地开发仓库升级到最新
|
|
53
|
+
|
|
54
|
+
在仓库根目录执行:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
# 1. 前置检查:确认全局 CLI 来源与待发布的工作区状态
|
|
58
|
+
which weaver-work-cli
|
|
59
|
+
git status --short
|
|
60
|
+
|
|
61
|
+
# 2. 重新构建,通过构建期 TS 校验(clean + tsc)
|
|
62
|
+
npm run build
|
|
63
|
+
|
|
64
|
+
# 3. 移除目标目录旧条目(软链/旧副本),再安装
|
|
65
|
+
rm ~/.workbuddy/skills/weaver-work-cli-invoice ~/.workbuddy/skills/weaver-work-cli-shared
|
|
66
|
+
weaver-work-cli skills install invoice --target-dir ~/.workbuddy/skills
|
|
67
|
+
|
|
68
|
+
# 4. 验证安装的是最新内容(与仓库工作区一致)
|
|
69
|
+
diff -q skills/weaver-work-cli-invoice/SKILL.md ~/.workbuddy/skills/weaver-work-cli-invoice/SKILL.md
|
|
70
|
+
diff -q skills/weaver-work-cli-shared/SKILL.md ~/.workbuddy/skills/weaver-work-cli-shared/SKILL.md
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
构建失败(tsc 报错)时先修复 TS 错误再安装;`skills install` 的内容源不依赖 `dist/`,但发布前应保证仓库可构建。
|
|
74
|
+
|
|
75
|
+
## 验证清单与生效
|
|
76
|
+
|
|
77
|
+
安装本身不校验业务 API。要确认对 Agent 生效:
|
|
78
|
+
|
|
79
|
+
- 目录结构正确:`~/.workbuddy/skills/weaver-work-cli-invoice/{SKILL.md,product.json,references/}` 与 `weaver-work-cli-shared/{SKILL.md,references/}`。
|
|
80
|
+
- 内容一致:上述 `diff` 无差异,或 `weaver-work-cli skills read weaver-work-cli-invoice` 与仓库一致。
|
|
81
|
+
- **Agent 需重新加载**:新建会话或按 Agent 规则重载 Skill 后才读取新内容;已打开的会话不会热更新。
|
|
82
|
+
- 业务可用性:安装后仍需完成 E10 登录(`weaver-work-cli auth login --base-url "<E10_BASE_URL>"`),并可按 `weaver-work-cli invoice schema` 验证 operation 契约。
|
|
83
|
+
|
|
84
|
+
## 常见问题
|
|
85
|
+
|
|
86
|
+
| 现象 | 处理 |
|
|
87
|
+
| --- | --- |
|
|
88
|
+
| `weaver-work-cli: command not found` | 先安装运行时:`npm install -g weaver-work-cli`,再 `setup invoice` |
|
|
89
|
+
| 安装报 `ERR_FS_CP_DIR_TO_NON_DIR` | 目标目录对应条目是软链,先 `rm <target>/weaver-work-cli-*` 断链再安装 |
|
|
90
|
+
| `unknown packaged skill` | 确认 `weaver-work-cli skills list` 输出的包内 Skill 名称;目标是全名或 `invoice` 等短名 |
|
|
91
|
+
| 改了仓库 Skill 但 Agent 看不到 | 已安装目录是拷贝,需重跑安装;且 Agent 需新会话重载 |
|
|
92
|
+
| 需要离线/平台导入的独立归档 | 用 `npm run build:invoice-skill`,产物 `dist/weaver-work-cli-invoice-skill.zip`;日常本机安装优先用 `skills install` |
|
package/docs/invoice.md
CHANGED
|
@@ -34,6 +34,8 @@ echo '{"page_size":10,"start_pos":0}' | weaver-work-cli --json invoice run invoi
|
|
|
34
34
|
|
|
35
35
|
成功和失败都使用 JSON envelope。成功写 stdout;失败写 stderr,并设置非 0 退出码。
|
|
36
36
|
|
|
37
|
+
当前输出层是完整 JSON 直接写 stdout,不提供飞书 CLI 的 `--jq`、`--format table/ndjson` 或通用 `--page-all`。Agent 使用时应默认小页读取和摘要渲染:列表先 `page_size=10`,按 `start_pos` 继续;回复只展示关键字段和数量,超长详情/OCR/调试 JSON 落本地文件后给路径。
|
|
38
|
+
|
|
37
39
|
## Operation 目录
|
|
38
40
|
|
|
39
41
|
| Operation | 风险 | 固定规则 |
|
|
@@ -41,10 +43,10 @@ echo '{"page_size":10,"start_pos":0}' | weaver-work-cli --json invoice run invoi
|
|
|
41
43
|
| `invoice.list` | 只读 | 个人票夹固定 `flag=0` |
|
|
42
44
|
| `invoice.enterprise.list` | 只读 | 企业票夹固定 `flag=6`,权限失败不降级个人票夹 |
|
|
43
45
|
| `invoice.get` | 只读 | `fid` 优先,或按 `number` 查询 |
|
|
44
|
-
| `invoice.upload` | 外部制品 | 固定上传 `ocr=
|
|
46
|
+
| `invoice.upload` | 外部制品 | 固定上传 `ocr=0`,只取上传文件 ID,不做上传阶段解析 |
|
|
45
47
|
| `invoice.ocr.preview` | 上传+只读 | 固定 `flag=13`、`is_sync=1`、`is_save=1`,不保存票夹 |
|
|
46
48
|
| `invoice.validate.preview` | 外部查询 | 先取详情,固定 `flag=100`、`is_save=1`,不回写查验结果 |
|
|
47
|
-
| `invoice.import.prepare/apply` | 高风险写 | continuation 绑定本地文件 SHA-256
|
|
49
|
+
| `invoice.import.prepare/apply` | 高风险写 | continuation 绑定本地文件 SHA-256;导入默认推荐 `validate=true`、`syncToOa=true` |
|
|
48
50
|
| `invoice.add.prepare/apply` | 高风险写 | 单张票面校验、重复检查、确认后新增并回查 |
|
|
49
51
|
| `invoice.update.prepare/apply` | 高风险写 | 基于完整详情修改白名单字段,保留附件并回查 |
|
|
50
52
|
| `invoice.download` | 本地文件写 | 先校验 `fileId` 属于目标 `fid`,拒绝覆盖 |
|
|
@@ -67,14 +69,17 @@ weaver-work-cli --json invoice download --fid <fid> --file-id <fileId> --output
|
|
|
67
69
|
写操作必须先 prepare,再 apply:
|
|
68
70
|
|
|
69
71
|
```bash
|
|
70
|
-
echo '{"file":"./invoice.pdf"
|
|
72
|
+
echo '{"file":"./invoice.pdf"}' \
|
|
73
|
+
| weaver-work-cli --json invoice run invoice.ocr.preview --input -
|
|
74
|
+
|
|
75
|
+
echo '{"file":"./invoice.pdf","validate":true,"syncToOa":true}' \
|
|
71
76
|
| weaver-work-cli --json invoice import prepare --input -
|
|
72
77
|
|
|
73
78
|
echo '{"file":"./invoice.pdf","continuation":"<prepare返回值>","confirm":true}' \
|
|
74
79
|
| weaver-work-cli --json invoice import apply --input -
|
|
75
80
|
```
|
|
76
81
|
|
|
77
|
-
`validate=false` 表示跳过查验,不能描述为“查验通过”。写操作出现网络中断、部分成功或回查失败时,CLI 返回 `partial/write_uncertain`,Agent 禁止自动重复提交。
|
|
82
|
+
导入本地发票文件时,面向 Agent 的正常链路是先 `invoice.ocr.preview`,再 `invoice.import.prepare` 使用 `validate=true`、`syncToOa=true`。只有用户明确要求跳过查验或离线导入时才传 `validate=false`;`validate=false` 表示跳过查验,不能描述为“查验通过”。写操作出现网络中断、部分成功或回查失败时,CLI 返回 `partial/write_uncertain`,Agent 禁止自动重复提交。
|
|
78
83
|
|
|
79
84
|
## 编辑白名单
|
|
80
85
|
|
package/package.json
CHANGED
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
共享底座用于所有 `weaver-work-cli-*` 业务 Skill。入口 `SKILL.md` 保留安装检查、E10 认证、JSON
|
|
1
|
+
共享底座用于所有 `weaver-work-cli-*` 业务 Skill。入口 `SKILL.md` 保留安装检查、E10 认证、JSON 输出、大结果渲染、高风险写入和安全边界的强触发索引;细节拆到 `references/`:
|
|
2
2
|
|
|
3
3
|
- `weaver-work-cli-installation.md`:安装、构建、全局 link、当前 skill 列表。
|
|
4
4
|
- `e10-auth-and-session.md`:登录、profile、auth 文件、E10 会话和 `WEAVER_*` 环境变量。
|
|
5
|
-
- `json-output-contract.md`:stdout/stderr、JSON envelope
|
|
5
|
+
- `json-output-contract.md`:stdout/stderr、JSON envelope、退出码、脚本判断规则、大结果渲染和分页控量。
|
|
6
6
|
- `high-risk-write.md`:`prepare -> apply`、用户确认、continuation 和停止条件。
|
|
7
7
|
|
|
8
|
+
认证状态只能通过 `weaver-work-cli auth root/status/profile list/profile current`、`weaver-work-cli doctor --e10` 和业务命令 JSON 错误判断;禁止 Agent 直接读取、列出或解析 `~/.e10-cli`、`/Users/<user>/.e10-cli`、auth、config 或 Keychain 数据。
|
|
9
|
+
|
|
10
|
+
涉及附件、图片、本地文件、远程 URL 文件或文件内容解析的操作,Agent 必须先提醒用户文件内容可能被上传到业务系统、OCR/解析服务,并可能进入当前大模型上下文;只有用户明确确认后才能继续读取、上传、解析、OCR 或导入文件。生成单接口 reference 时,需要在对应“注意”里标记该确认要求。
|
|
11
|
+
|
|
8
12
|
业务 Skill 只链接共享底座,不复制共享规则正文,避免多处规则漂移。
|
|
@@ -8,7 +8,9 @@ metadata:
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-work-cli-shared/SKILL.md`](../weaver-work-cli-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。**
|
|
11
|
+
认证和登录态只能按共享规则通过 `weaver-work-cli auth ...` 命令判断;禁止直接读取、列出或 `cat` `~/.e10-cli`、`/Users/<user>/.e10-cli`、auth、config 或 Keychain 数据。
|
|
11
12
|
所有命令通过 `weaver-work-cli --json {{command}} run <operation> --input -` 执行。调用前先按需读取 references 下对应的文件,查参数结构,不要猜字段;**references 是第一信息源**,`weaver-work-cli {{command}} schema` 是 operation、字段和风险等级的合约来源。
|
|
13
|
+
涉及附件、图片、本地文件、远程 URL 文件或文件内容解析的 operation,执行前必须提醒用户:文件内容可能被上传到业务系统、OCR/解析服务,并可能进入当前大模型上下文用于理解和处理;必须等待用户明确确认后才继续。
|
|
12
14
|
|
|
13
15
|
## 路由优先级(先判断是不是 {{title}},再选 operation)
|
|
14
16
|
|
|
@@ -36,6 +38,13 @@ metadata:
|
|
|
36
38
|
|
|
37
39
|
{{minimum_info_rules}}
|
|
38
40
|
|
|
41
|
+
### 1.5) 大结果只摘要给用户
|
|
42
|
+
|
|
43
|
+
- 当前 CLI 的 `--json` 会把完整 JSON envelope 写 stdout;Agent 回复时不要原样粘贴完整 JSON
|
|
44
|
+
- 列表默认先取小页,优先 `page_size=10` 或本业务 schema 中等价的小页参数;用户没有要求全量时不要自动扫完整数据集
|
|
45
|
+
- 需要全量统计时,按分页字段分批读取,只累计任务所需字段和去重键,并报告已读取页数、命中数和是否还有更多
|
|
46
|
+
- 超长文本、大数组、OCR/导出/详情原始响应或调试 JSON 需要保留时,优先落本地文件并向用户提供摘要和路径
|
|
47
|
+
|
|
39
48
|
### 2) 已知对象时直达动作
|
|
40
49
|
|
|
41
50
|
{{direct_action_rules}}
|
|
@@ -46,6 +55,12 @@ metadata:
|
|
|
46
55
|
- **除非错误明确提示可恢复或需要补充参数,否则不要重复刷同一个 operation**
|
|
47
56
|
- 写请求已经发出后,遇到结果不确定必须停止;不要把 `.apply` 当成可重试读操作
|
|
48
57
|
|
|
58
|
+
### 4) 附件、图片和文件解析确认
|
|
59
|
+
|
|
60
|
+
- 命中上传附件、上传图片、读取本地文件、使用远程 URL 文件、OCR、文件解析、导入文件或复用已上传文件对象时,必须先提醒数据处理风险并等待用户明确确认。
|
|
61
|
+
- 风险提醒必须说明文件内容可能进入大模型上下文,也可能被发送到业务系统或 OCR/解析服务。
|
|
62
|
+
- 用户未确认前,不要运行会读取、上传、解析、OCR 或导入该文件的命令;单接口 reference 的“注意”里也必须标出这个确认要求。
|
|
63
|
+
|
|
49
64
|
## 写操作失败处理:{{write_uncertain_label}} 决策树
|
|
50
65
|
|
|
51
66
|
{{write_uncertain_tree}}
|
|
@@ -8,7 +8,9 @@ metadata:
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
10
|
**CRITICAL — 开始前 MUST 先用 Read 工具读取 [`../weaver-work-cli-shared/SKILL.md`](../weaver-work-cli-shared/SKILL.md),其中包含安装、E10 认证、JSON 输出和高风险写入规则。**
|
|
11
|
+
认证和登录态只能按共享规则通过 `weaver-work-cli auth ...` 命令判断;禁止直接读取、列出或 `cat` `~/.e10-cli`、`/Users/<user>/.e10-cli`、auth、config 或 Keychain 数据。
|
|
11
12
|
所有命令通过 `weaver-work-cli --json invoice run <operation> --input -` 执行。调用前先按需读取 references 下对应的文件,查参数结构,不要猜字段;**references 是第一信息源**,`weaver-work-cli invoice schema` 是 operation、字段和风险等级的合约来源。
|
|
13
|
+
涉及发票附件、图片、本地文件、远程 URL 文件或 OCR/文件解析的操作,执行前必须提醒用户:文件内容可能被上传到 E10 业票通、OCR/查验服务,并可能进入当前大模型上下文用于理解和处理;必须等待用户明确确认后才继续。
|
|
12
14
|
|
|
13
15
|
## 路由优先级(先判断是不是业票通发票,再选 operation)
|
|
14
16
|
|
|
@@ -46,7 +48,7 @@ metadata:
|
|
|
46
48
|
|
|
47
49
|
- 查票夹/详情:`invoice.list` 或 `invoice.enterprise.list` -> 必要时 `invoice.get`
|
|
48
50
|
- OCR 识别预览:`invoice.ocr.preview`;如果先上传,可复用 `invoice.upload` 返回的 `upload`
|
|
49
|
-
-
|
|
51
|
+
- 导入文件:先 `invoice.ocr.preview` 预览票面识别结果;用户确认导入后,默认用 `invoice.import.prepare` 且传 `validate=true`、`syncToOa=true` -> 用户确认 -> `invoice.import.apply` -> 按返回 `fid` 回查/报告。只有用户明确要求“跳过查验/不同步 OA”时,才使用 `validate=false` 或 `syncToOa=false`。
|
|
50
52
|
- 手工新增:`invoice.add.prepare` -> 用户确认 -> `invoice.add.apply`
|
|
51
53
|
- 编辑发票:`invoice.update.prepare` -> 用户确认 -> `invoice.update.apply`
|
|
52
54
|
- 删除发票:`invoice.delete.prepare` -> 用户确认 -> `invoice.delete.apply`
|
|
@@ -56,9 +58,19 @@ metadata:
|
|
|
56
58
|
### 1) 先拿最小必要信息,再执行
|
|
57
59
|
|
|
58
60
|
- 只是查票夹时,优先直接用 `invoice.list` 或 `invoice.enterprise.list`
|
|
61
|
+
- 列表默认先取小页,优先 `page_size=10`;用户没有要求全量时不要自动翻完整票夹
|
|
62
|
+
- 查询个人/企业票夹时,用户没有明确要求“全部发票/已报销/报销中/不可报销”就不要传 `sreim`;CLI 默认 `sreim="3"`,只查未报销发票
|
|
63
|
+
- 查询个人/企业票夹时,用户没有明确要求“凭证”就不要传 `bill_type`;CLI 默认 `bill_type=0`,只查发票
|
|
59
64
|
- 用户已经给出 `fid` 时,不要先查列表再过滤,直接用 `invoice.get` 或对应 prepare
|
|
60
65
|
- 只有需要附件归属、可编辑/可删除状态或完整票面时,才补 `invoice.get`
|
|
61
66
|
|
|
67
|
+
### 1.5) 大结果只摘要给用户
|
|
68
|
+
|
|
69
|
+
- 当前 CLI 会把完整 JSON envelope 写 stdout;Agent 回复时不要原样贴完整 JSON
|
|
70
|
+
- 列表最多先展示最相关的前 10 条,包含 `fid`、代码/号码、购销方、金额、日期、查验/报销状态和附件摘要
|
|
71
|
+
- 需要全量统计时,按 `start_pos` 分页读取并累计必要字段;说明已读取页数、命中数和是否还有更多
|
|
72
|
+
- OCR、详情或调试用完整响应过长时,优先落本地文件并向用户提供摘要和文件路径
|
|
73
|
+
|
|
62
74
|
### 2) 已知对象时直达动作
|
|
63
75
|
|
|
64
76
|
- 已拿到 `fid`、`fileId`、本地文件路径或完整 `info` 时,优先调用对应 operation
|
|
@@ -72,6 +84,11 @@ metadata:
|
|
|
72
84
|
- 写请求已经发出后,遇到结果不确定必须停止;不要把 `.apply` 当成可重试读操作
|
|
73
85
|
- **错误为 `authentication`(未登录,如 `E10 auth not found`)或 `session_expired`(登录态失效)时:立即停止当前操作,不要用示例占位域名或自行猜域名登录,也不要盲目重试**。先读取共享规则 `../weaver-work-cli-shared/references/e10-auth-and-session.md`,按其中流程用宿主提问/弹框让用户输入 E10 登录域名或选择已有 profile,完成登录后再继续原操作。
|
|
74
86
|
|
|
87
|
+
### 4) 附件、图片和文件解析确认
|
|
88
|
+
|
|
89
|
+
- 执行 `invoice.upload`、`invoice.ocr.preview`、`invoice.import.prepare/apply`,或任何会读取本地发票文件、上传远程 URL 文件、解析图片/PDF/OFD/XML、复用已上传 `upload` 对象的步骤前,必须先提醒用户文件内容可能进入大模型上下文,也可能发送到 E10 业票通或 OCR/查验服务。
|
|
90
|
+
- 用户未明确确认前,不要运行上传、OCR、解析、导入或复用已上传文件对象的命令。
|
|
91
|
+
|
|
75
92
|
## 写操作失败处理:`partial/write_uncertain` 决策树
|
|
76
93
|
|
|
77
94
|
当导入 / 新增 / 编辑 / 删除等写操作返回 `partial/write_uncertain`,或提示网络中断、部分成功、回查失败、回查字段不一致时,按下面规则处理:
|
|
@@ -91,7 +108,8 @@ metadata:
|
|
|
91
108
|
weaver-work-cli invoice schema
|
|
92
109
|
printf '%s\n' '{"page_size":10,"start_pos":0}' | weaver-work-cli --json invoice run invoice.list --input -
|
|
93
110
|
printf '%s\n' '{"fid":"12345"}' | weaver-work-cli --json invoice run invoice.get --input -
|
|
94
|
-
printf '%s\n' '{"file":"./invoice.pdf"
|
|
111
|
+
printf '%s\n' '{"file":"./invoice.pdf"}' | weaver-work-cli --json invoice run invoice.ocr.preview --input -
|
|
112
|
+
printf '%s\n' '{"file":"./invoice.pdf","validate":true,"syncToOa":true}' | weaver-work-cli --json invoice run invoice.import.prepare --input -
|
|
95
113
|
printf '%s\n' '{"file":"./invoice.pdf","continuation":"<prepare返回值>","confirm":true}' | weaver-work-cli --json invoice run invoice.import.apply --input -
|
|
96
114
|
```
|
|
97
115
|
## 不在本 skill 范围
|
|
@@ -99,5 +117,6 @@ printf '%s\n' '{"file":"./invoice.pdf","continuation":"<prepare返回值>","conf
|
|
|
99
117
|
- 禁止加载原始 `weaver-e10-yepiaotong` Skill 代替 CLI。
|
|
100
118
|
- 禁止 curl、fetch、浏览器自动化或直接访问 E10 `/api/inc/*`。
|
|
101
119
|
- 禁止读取或复制 CLI runtime 内部 Token、Cookie、ETEAMSID。
|
|
120
|
+
- 禁止读取、列出、`cat` 或解析 `~/.e10-cli`、`/Users/<user>/.e10-cli`、auth、config 或 Keychain 数据。
|
|
102
121
|
- 共享、转让和标签当前未纳入 CLI manifest;需要先补稳定 ID 来源、输入 schema、prepare/apply、写后回查和测试后再开放。
|
|
103
122
|
- 非发票类 E10 能力、通用流程编排、表单/审批/组织等业务不由本 Skill 承载。
|
|
@@ -35,4 +35,6 @@ printf '%s\n' '{"page_size":10,"start_pos":0}' \
|
|
|
35
35
|
|
|
36
36
|
成功结果在 stdout,失败结果在 stderr。判断规则读取共享 reference:`../../weaver-work-cli-shared/references/json-output-contract.md`。
|
|
37
37
|
|
|
38
|
+
列表、详情、OCR 或回查结果可能很长时,不要把 stdout 的完整 envelope 直接展示给用户。默认 `page_size=10` 小页读取;只渲染发票识别和决策所需字段,例如 `fid`、代码/号码、购销方、金额、日期、查验/报销状态、附件数量/文件名。需要更多结果时按 `start_pos` 分页继续;需要保留完整原始 JSON 时落本地文件并返回路径。
|
|
39
|
+
|
|
38
40
|
高风险写入读取共享 reference:`../../weaver-work-cli-shared/references/high-risk-write.md`。
|
|
@@ -19,4 +19,6 @@ printf '%s\n' '{"fid":"12345","fileId":"67890","output":"./invoice-12345.pdf"}'
|
|
|
19
19
|
|
|
20
20
|
## 注意
|
|
21
21
|
|
|
22
|
+
下载附件不会把文件内容发送给大模型;但如果后续要读取、解析、OCR 或转传下载后的附件,必须先提醒用户文件内容可能进入大模型上下文或外部解析服务,并等待用户明确确认。
|
|
23
|
+
|
|
22
24
|
如果用户没有 `fileId`,先用 `invoice.get` 查看详情里的 `flist`。`output` 已存在时 CLI 会失败,不要自动覆盖用户文件。
|
|
@@ -8,13 +8,15 @@
|
|
|
8
8
|
|
|
9
9
|
| Operation | 固定规则 |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| `invoice.enterprise.list` | 固定 `flag=6`;默认 `sreim=3`,只查未报销发票 |
|
|
11
|
+
| `invoice.enterprise.list` | 固定 `flag=6`;默认 `sreim="3"`、`bill_type=0`,只查未报销发票 |
|
|
12
12
|
|
|
13
13
|
## 输入
|
|
14
14
|
|
|
15
|
-
列表字段以 `weaver-work-cli invoice schema` 为准,字段语义与个人票夹一致。常用字段包括 `page_size`、`start_pos`、`content
|
|
15
|
+
列表字段以 `weaver-work-cli invoice schema` 为准,字段语义与个人票夹一致。常用字段包括 `page_size`、`start_pos`、`content`、购销方、日期、金额、票种、查验状态、来源和排序。`sreim` 只有用户明确指定报销状态时才传;`bill_type` 只有用户明确要求查凭证时才传。
|
|
16
16
|
|
|
17
|
-
`sreim`
|
|
17
|
+
`sreim` 是字符串类型的查询筛选参数:`"0"` 获取全部发票,`"1"` 发票报销中,`"2"` 报销完成,`"3"` 获取未报销发票,`"4"` 获取不可报销。用户没有明确要求“全部发票/已报销/报销中/不可报销”时,必须省略 `sreim`,让 CLI 默认传 `"3"` 查询未报销发票。
|
|
18
|
+
|
|
19
|
+
`bill_type` 是票据类型筛选参数:`0` 获取发票,`1` 获取凭证。用户没有明确要求“凭证”时,必须省略 `bill_type`,让 CLI 默认传 `0` 查询发票。
|
|
18
20
|
|
|
19
21
|
## 示例
|
|
20
22
|
|
|
@@ -22,7 +24,7 @@
|
|
|
22
24
|
printf '%s\n' '{"page_size":10,"start_pos":0,"buyer_company":"泛微"}' \
|
|
23
25
|
| weaver-work-cli --json invoice run invoice.enterprise.list --input -
|
|
24
26
|
|
|
25
|
-
printf '%s\n' '{"page_size":10,"start_pos":0,"sreim":2}' \
|
|
27
|
+
printf '%s\n' '{"page_size":10,"start_pos":0,"sreim":"2"}' \
|
|
26
28
|
| weaver-work-cli --json invoice run invoice.enterprise.list --input -
|
|
27
29
|
```
|
|
28
30
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| Operation | 固定规则 |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| `invoice.upload` | 固定上传 `ocr=
|
|
11
|
+
| `invoice.upload` | 固定上传 `ocr=0`,只取得文件 ID,不做上传阶段解析 |
|
|
12
12
|
|
|
13
13
|
## 文件来源
|
|
14
14
|
|
|
@@ -25,4 +25,8 @@ printf '%s\n' '{"file":"./invoice.pdf"}' \
|
|
|
25
25
|
|
|
26
26
|
## 返回
|
|
27
27
|
|
|
28
|
-
返回规范化后的 `upload` 对象,包含 `id`、`ids`、`fileType`、`fileName`、`totalPages`、`hasFanWei`、`ocrMap` 和 `fail=false`。后续 `invoice.ocr.preview`
|
|
28
|
+
返回规范化后的 `upload` 对象,包含 `id`、`ids`、`fileType`、`fileName`、`totalPages`、`hasFanWei`、`ocrMap` 和 `fail=false`。后续 `invoice.ocr.preview` 可以直接复用这个对象;只有明确需要 OCR 预览时才调用 `invoice.ocr.preview`。
|
|
29
|
+
|
|
30
|
+
## 注意
|
|
31
|
+
|
|
32
|
+
上传前必须先提醒用户:发票附件/图片/文件内容可能被上传到 E10 业票通,并可能进入当前大模型上下文用于理解和处理;只有用户明确确认后才执行 `invoice.upload`。用户仅提供文件路径或文件名不等于同意上传。
|
|
@@ -8,13 +8,17 @@
|
|
|
8
8
|
|
|
9
9
|
| 阶段 | Operation | 必填输入 |
|
|
10
10
|
| --- | --- | --- |
|
|
11
|
+
| 识别预览 | `invoice.ocr.preview` | `file` |
|
|
11
12
|
| 准备导入 | `invoice.import.prepare` | `file`、`validate`、`syncToOa` |
|
|
12
13
|
| 确认导入 | `invoice.import.apply` | `file`、`continuation`、`confirm=true` |
|
|
13
14
|
|
|
14
15
|
## 示例
|
|
15
16
|
|
|
16
17
|
```bash
|
|
17
|
-
printf '%s\n' '{"file":"./invoice.pdf"
|
|
18
|
+
printf '%s\n' '{"file":"./invoice.pdf"}' \
|
|
19
|
+
| weaver-work-cli --json invoice run invoice.ocr.preview --input -
|
|
20
|
+
|
|
21
|
+
printf '%s\n' '{"file":"./invoice.pdf","validate":true,"syncToOa":true}' \
|
|
18
22
|
| weaver-work-cli --json invoice run invoice.import.prepare --input -
|
|
19
23
|
|
|
20
24
|
printf '%s\n' '{"file":"./invoice.pdf","continuation":"<prepare返回值>","confirm":true}' \
|
|
@@ -23,6 +27,10 @@ printf '%s\n' '{"file":"./invoice.pdf","continuation":"<prepare返回值>","conf
|
|
|
23
27
|
|
|
24
28
|
## 注意
|
|
25
29
|
|
|
26
|
-
|
|
30
|
+
导入前必须先提醒用户:发票附件/图片/文件内容可能被上传到 E10 业票通、OCR/查验服务,并可能进入当前大模型上下文用于理解和处理;只有用户明确确认后才执行 `invoice.import.prepare/apply`。用户仅提供文件路径或文件名不等于同意导入或解析。
|
|
31
|
+
|
|
32
|
+
导入本地发票文件的正常业务链路是:先 OCR 预览票面 -> 再导入并查验 -> 最后回查导入结果。Agent 不要因为用户只说“上传/导入发票”就默认跳过查验。
|
|
33
|
+
|
|
34
|
+
`validate` 和 `syncToOa` 必须显式传布尔值。默认推荐 `validate=true`、`syncToOa=true`;`validate=true` 分支由服务端固定同步 OA,不能设置 `syncToOa=false`。只有用户明确要求跳过发票查验或离线导入时,才传 `validate=false`;`validate=false` 表示跳过查验,不能描述为“查验通过”。
|
|
27
35
|
|
|
28
36
|
`.prepare` 返回 `preview`、`continuation`、`expiresInSeconds` 和 `workflow.state="AWAITING_CONFIRMATION"`。展示风险后等待用户明确确认,再调用 `.apply`。
|
|
@@ -30,4 +30,6 @@ printf '%s\n' '{"upload":{...}}' \
|
|
|
30
30
|
|
|
31
31
|
## 注意
|
|
32
32
|
|
|
33
|
+
OCR 前必须先提醒用户:发票附件/图片/文件内容可能被上传到 E10 业票通和 OCR 服务,并可能进入当前大模型上下文用于理解和处理;只有用户明确确认后才执行 `invoice.ocr.preview` 或复用已上传的 `upload` 对象继续 OCR。
|
|
34
|
+
|
|
33
35
|
`saved=false` 表示 CLI 不把 OCR 预览描述为已入票夹。用户要导入时走 `invoice.import.prepare -> invoice.import.apply`。
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
| Operation | 固定规则 |
|
|
10
10
|
| --- | --- |
|
|
11
|
-
| `invoice.list` | 固定 `flag=0`;默认 `sreim=3`,只查未报销发票 |
|
|
11
|
+
| `invoice.list` | 固定 `flag=0`;默认 `sreim="3"`、`bill_type=0`,只查未报销发票 |
|
|
12
12
|
|
|
13
13
|
## 输入
|
|
14
14
|
|
|
@@ -24,9 +24,12 @@
|
|
|
24
24
|
- `total_begin`、`total_end`
|
|
25
25
|
- `valids`、`sources`、`types`
|
|
26
26
|
- `sorts`
|
|
27
|
-
- `sreim
|
|
27
|
+
- `sreim`(只有用户明确指定报销状态时才传)
|
|
28
|
+
- `bill_type`(只有用户明确要求查凭证时才传)
|
|
28
29
|
|
|
29
|
-
`sreim`
|
|
30
|
+
`sreim` 是字符串类型的查询筛选参数:`"0"` 获取全部发票,`"1"` 发票报销中,`"2"` 报销完成,`"3"` 获取未报销发票,`"4"` 获取不可报销。用户没有明确要求“全部发票/已报销/报销中/不可报销”时,必须省略 `sreim`,让 CLI 默认传 `"3"` 查询未报销发票。不要为了“最近发票”“查询发票”“个人票夹”主动传 `sreim="0"`。
|
|
31
|
+
|
|
32
|
+
`bill_type` 是票据类型筛选参数:`0` 获取发票,`1` 获取凭证。用户没有明确要求“凭证”时,必须省略 `bill_type`,让 CLI 默认传 `0` 查询发票。
|
|
30
33
|
|
|
31
34
|
## 示例
|
|
32
35
|
|
|
@@ -34,7 +37,7 @@
|
|
|
34
37
|
printf '%s\n' '{"page_size":10,"start_pos":0,"content":"滴滴"}' \
|
|
35
38
|
| weaver-work-cli --json invoice run invoice.list --input -
|
|
36
39
|
|
|
37
|
-
printf '%s\n' '{"page_size":10,"start_pos":0,"sreim":
|
|
40
|
+
printf '%s\n' '{"page_size":10,"start_pos":0,"sreim":"2"}' \
|
|
38
41
|
| weaver-work-cli --json invoice run invoice.list --input -
|
|
39
42
|
```
|
|
40
43
|
|
|
@@ -44,4 +47,4 @@ printf '%s\n' '{"page_size":10,"start_pos":0,"sreim":0}' \
|
|
|
44
47
|
|
|
45
48
|
## 注意
|
|
46
49
|
|
|
47
|
-
不要在输入里传 `flag`;即使传入也会被 CLI 忽略并固定为个人票夹。空筛选条件直接省略,不要把空字符串传给 integer
|
|
50
|
+
不要在输入里传 `flag`;即使传入也会被 CLI 忽略并固定为个人票夹。空筛选条件直接省略,不要把空字符串传给 integer 字段。除非用户明确要求全部或某个报销状态,否则不要传 `sreim`;除非用户明确要求凭证,否则不要传 `bill_type`。
|
|
@@ -8,7 +8,7 @@ metadata:
|
|
|
8
8
|
|
|
9
9
|
# weaver-work-cli 共享规则
|
|
10
10
|
|
|
11
|
-
所有 `weaver-work-cli-*` Skill 共享的底座:命令可用性、E10 认证、JSON
|
|
11
|
+
所有 `weaver-work-cli-*` Skill 共享的底座:命令可用性、E10 认证、JSON 输出契约、大结果渲染与高风险操作。
|
|
12
12
|
|
|
13
13
|
## 通用准则
|
|
14
14
|
|
|
@@ -23,12 +23,18 @@ weaver-work-cli doctor --e10
|
|
|
23
23
|
|
|
24
24
|
3. 业务输入只描述业务对象和意图。认证、Cookie、ETEAMSID、业务 Token、接口地址和回查细节都由 CLI 托管。
|
|
25
25
|
|
|
26
|
+
4. 认证诊断只能通过 `weaver-work-cli auth root/status/profile list/profile current`、`weaver-work-cli doctor --e10` 和业务命令 JSON 错误完成。禁止直接 `ls`、`cat`、复制或解析用户态认证目录和认证文件。
|
|
27
|
+
|
|
28
|
+
5. 涉及附件、图片、本地文件、远程 URL 文件或文件内容解析的操作,执行前必须先向用户说明:文件内容可能会被上传到业务系统、OCR/解析服务,并可能进入当前大模型上下文用于理解和处理。必须等待用户明确确认后,才继续上传、读取、解析、OCR、导入或复用已上传文件对象;用户未确认时只说明风险和所需确认,不执行相关命令。
|
|
29
|
+
|
|
26
30
|
## 输出契约
|
|
27
31
|
|
|
28
32
|
Agent 调用业务能力时优先加 `--json`。成功看进程退出码 0 和 JSON envelope 的 `ok=true`;失败看非 0 退出码和 stderr JSON 的 `error.type/subtype/message`。不要用老式 `code == 0` 判断成功。
|
|
29
33
|
|
|
30
34
|
返回 `partial`、`write_uncertain`、登录失效、回查失败或网络中断时,立即停止当前写流程,不自动重试写入或删除。
|
|
31
35
|
|
|
36
|
+
当前 CLI 的 JSON 输出是完整 envelope 直接写 stdout;没有飞书 CLI 那种通用 `--jq`、`--format table/ndjson` 或 `--page-all`。列表、详情、OCR、导出等可能产生大响应时,必须先读 [`json-output-contract.md`](references/json-output-contract.md) 的“大结果渲染与提效规则”:默认小页读取、只保留任务所需字段、分页有预算,回复用户时给摘要和路径,不要原样粘贴超长 JSON。
|
|
37
|
+
|
|
32
38
|
## Reference 强触发索引
|
|
33
39
|
|
|
34
40
|
命中任一触发条件时,执行下一步前读取对应 reference。命中多条时按表中顺序读取,同一 reference 只读取一次。
|
|
@@ -37,17 +43,21 @@ Agent 调用业务能力时优先加 `--json`。成功看进程退出码 0 和 J
|
|
|
37
43
|
| --- | --- |
|
|
38
44
|
| 命令不可用、安装、构建、全局 link、检查可用 skill | [`weaver-work-cli-installation.md`](references/weaver-work-cli-installation.md) |
|
|
39
45
|
| 登录、profile、E10 会话、baseUrl、auth 文件、`WEAVER_*` 环境变量;**未登录或登录失效(需要用户提供登录域名)** | [`e10-auth-and-session.md`](references/e10-auth-and-session.md) |
|
|
40
|
-
| 判断 stdout/stderr、JSON envelope
|
|
46
|
+
| 判断 stdout/stderr、JSON envelope、退出码、脚本封装、自动化调用、大结果渲染/分页控量 | [`json-output-contract.md`](references/json-output-contract.md) |
|
|
41
47
|
| 准备执行写入/删除/导入/更新、遇到 `confirmation.required`、`partial.write_uncertain`、网络中断或回查失败 | [`high-risk-write.md`](references/high-risk-write.md) |
|
|
42
48
|
|
|
43
49
|
## 安全规则
|
|
44
50
|
|
|
45
51
|
1. 禁止输出或索取 Cookie、ETEAMSID、业务 Token、access token、app key、app secret。
|
|
46
52
|
|
|
47
|
-
2.
|
|
53
|
+
2. 禁止读取、列出、`cat`、复制或解析任何 `e10-login` / `e10-cli` 历史认证目录,例如 `~/.e10-cli` 或 `/Users/<user>/.e10-cli`;也禁止直接读取 `auth`、`config.json` 或 Keychain 项来推断登录态。
|
|
54
|
+
|
|
55
|
+
3. 禁止绕过 `weaver-work-cli` 直接 `curl`、`fetch`、浏览器自动化或访问 E10 业务接口。
|
|
56
|
+
|
|
57
|
+
4. 写入、删除、导入、更新等高风险操作必须使用 CLI 提供的确认流程;业务 Skill 要求 `prepare -> apply` 时,必须把 prepare 返回的 continuation 原样传给 apply,并在 apply 前取得用户明确确认。
|
|
48
58
|
|
|
49
|
-
|
|
59
|
+
5. 不能猜测 CLI 未暴露的内部字段、接口路径、ID 解析逻辑或回查语义。
|
|
50
60
|
|
|
51
|
-
|
|
61
|
+
6. 未登录或登录失效(`authentication` / `session_expired` / `auth status` 未登录)时,必须先通过宿主提问或弹框向用户确认 E10 登录域名,或用 `auth profile list` 让用户选择已有 profile;**禁止**使用示例占位域名登录,也禁止在拿到域名前反复重试业务命令。具体流程读取 [`e10-auth-and-session.md`](references/e10-auth-and-session.md)。
|
|
52
62
|
|
|
53
|
-
|
|
63
|
+
7. 附件、图片上传或文件解析属于敏感数据处理。即便 operation 风险等级不是高风险写入,也必须先取得用户对“文件内容可能进入大模型/外部解析服务”的明确确认;不能把用户仅提供文件路径或文件名视为同意解析或上传。
|
|
@@ -13,6 +13,12 @@ weaver-work-cli auth whoami
|
|
|
13
13
|
|
|
14
14
|
`--no-check` 只读取本地登录态;需要实际验证服务端可用性时使用业务命令或明确带 live 校验的命令。
|
|
15
15
|
|
|
16
|
+
## 认证隔离与禁止探查旧目录
|
|
17
|
+
|
|
18
|
+
`weaver-work-cli auth root` 是唯一用于确认本 CLI 认证根目录的命令;默认根目录是 `~/.weaver-work-cli/e10`。Agent 不得因为历史兼容信息去读取、列出或 `cat` `~/.e10-cli`、`/Users/<user>/.e10-cli`、`e10-login` / `e10-cli` 的 auth、config 或 Keychain 数据。
|
|
19
|
+
|
|
20
|
+
登录态判断只允许通过 `weaver-work-cli auth status --no-check`、`weaver-work-cli auth profile list/current`、`weaver-work-cli doctor --e10` 和业务命令返回的 JSON 错误完成。只有用户明确提供外部 auth 文件路径时,才可按用户要求使用 `--auth <path>` 或 `E10_AUTH_PATH`;不能主动搜索旧认证目录。
|
|
21
|
+
|
|
16
22
|
## 未登录 / 登录失效:必须先向用户提问登录域名,再登录
|
|
17
23
|
|
|
18
24
|
业务命令依赖 E10 登录态。出现以下任一情况即判定为未登录或登录失效:
|
|
@@ -27,6 +33,7 @@ weaver-work-cli auth whoami
|
|
|
27
33
|
- 使用示例占位域名(如 `https://weapp.xxx.cn`)或自行猜测域名执行登录
|
|
28
34
|
- 未向用户确认登录域名前,反复重试业务命令
|
|
29
35
|
- 要求用户提供 Cookie、ETEAMSID、业务 Token(见安全边界)
|
|
36
|
+
- 读取、列出或解析 `~/.e10-cli`、`/Users/<user>/.e10-cli`、`e10-login` / `e10-cli` 的历史 auth、config 或 Keychain 数据
|
|
30
37
|
|
|
31
38
|
**正确流程(按序执行,缺一不可):**
|
|
32
39
|
|
|
@@ -80,4 +87,4 @@ weaver-work-cli --profile <name> auth status --no-check
|
|
|
80
87
|
|
|
81
88
|
## 安全边界
|
|
82
89
|
|
|
83
|
-
Agent 不要要求用户贴 Cookie、ETEAMSID、业务 Token、app key 或 app secret
|
|
90
|
+
Agent 不要要求用户贴 Cookie、ETEAMSID、业务 Token、app key 或 app secret,也不要直接读取用户机器上的 auth、config 或 Keychain 数据。业务 Skill 只负责调用 CLI;登录态读取、Cookie 拼接、业务 Token 获取和 HTTP header 注入都由 `weaver-work-cli` 内部完成。
|
|
@@ -59,3 +59,28 @@
|
|
|
59
59
|
| `11` | 部分完成或结果不确定 |
|
|
60
60
|
|
|
61
61
|
`retryable=true` 只表示读操作或准备阶段可能可以重试;写入请求已经发出后,遇到 `partial/write_uncertain` 必须停止并交给用户判断。
|
|
62
|
+
|
|
63
|
+
## 大结果渲染与提效规则
|
|
64
|
+
|
|
65
|
+
当前 `weaver-work-cli` 输出层是轻量封装:JSON 模式把完整结果写 stdout,文本模式写人类可读文本;不像飞书 CLI 已内置 `--format table/pretty/ndjson`、`--jq` 或通用 `--page-all`。Agent 因此必须在调用和回复阶段主动控量,避免把超长接口响应原样渲染给用户。
|
|
66
|
+
|
|
67
|
+
### 调用前控量
|
|
68
|
+
|
|
69
|
+
- 列表类 operation 默认先取小页:优先 `page_size=10`,需要更多结果时再按用户目标递增,通常不要超过 `20`。
|
|
70
|
+
- 用户只想定位一个对象时,用筛选字段缩小范围;已有 `fid`、`number`、文件路径或 continuation 时直达对应 operation,不要先拉全量列表。
|
|
71
|
+
- 用户说“全部 / 全量 / 统计”时,先说明会分页读取;每页读取后只保留任务所需字段和去重键,避免在上下文里累计完整原始响应。
|
|
72
|
+
- 有 `hasMore`、`start_pos`、`page_token`、`next_page_token` 等分页字段时,用它们继续翻页;没有明确分页信号时不要无界循环。
|
|
73
|
+
|
|
74
|
+
### 回复时渲染
|
|
75
|
+
|
|
76
|
+
- 不要把完整 stdout JSON 直接粘给用户。优先输出结论、命中数量、关键字段、下一页/剩余数据提示和必要的文件路径。
|
|
77
|
+
- 列表结果只展示最相关的前 `10` 条;如果用户要求更多,分批展示并说明还可以继续读取。
|
|
78
|
+
- 详情结果只展示与用户问题相关的字段。发票类详情通常优先展示 `fid`、号码/代码、购销方、金额、日期、查验/报销状态和附件摘要。
|
|
79
|
+
- 超长文本、大数组、OCR 原文、逐项明细或调试需要的完整 JSON,优先写入本地文件再给路径;不要在对话里展开。可用 shell 重定向保存完整 stdout,或业务 operation 暴露 `output` 参数时使用其文件输出。
|
|
80
|
+
- 如果为了调试必须引用原始 envelope,只截取必要字段:`ok`、`operation`、`meta`、`warnings`、`error` 或 `data` 的相关子树。
|
|
81
|
+
|
|
82
|
+
### 参考飞书 CLI 的实践
|
|
83
|
+
|
|
84
|
+
- 飞书 CLI 用 `--format json` 保留机器可读 envelope,用 `pretty/table/ndjson/csv` 降低人读成本;本 CLI 目前主要依赖 `--json` envelope,因此 Agent 回复时承担 pretty/table 摘要职责。
|
|
85
|
+
- 飞书 CLI 的分页实践是显式页预算(如 `--page-limit`)和页间延迟;本 CLI 业务 operation 应使用自身 schema 中的 `page_size/start_pos` 等字段模拟同样的预算控制。
|
|
86
|
+
- 飞书 CLI 对大产物倾向返回 artifact 文件路径;本 CLI 遇到下载、导出、OCR 或超长 JSON 时也应优先落盘并只向用户展示路径和摘要。
|
|
@@ -55,7 +55,19 @@ weaver-work-cli skills install invoice
|
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
该命令会同时安装 `weaver-work-cli-shared` 和 `weaver-work-cli-invoice` 到
|
|
58
|
-
`$CODEX_HOME/skills`;未设置 `CODEX_HOME` 时使用 `~/.codex/skills
|
|
58
|
+
`$CODEX_HOME/skills`;未设置 `CODEX_HOME` 时使用 `~/.codex/skills`。默认目标
|
|
59
|
+
面向 Codex CLI;WorkBuddy 等桌面 Agent 的用户级 Skill 目录不是默认目标,需
|
|
60
|
+
显式指定后再安装:
|
|
61
|
+
|
|
62
|
+
```bash
|
|
63
|
+
weaver-work-cli skills install invoice --target-dir ~/.workbuddy/skills
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
`skills install` 是拷贝语义,装出的是真实副本,不与源目录联动。目标目录里
|
|
67
|
+
已有旧条目(旧副本或软链)时不能直接覆盖:目标是软链会报
|
|
68
|
+
`ERR_FS_CP_DIR_TO_NON_DIR`,先 `rm` 断链再安装;覆盖安装不会清理目标里已
|
|
69
|
+
不存在的旧文件。安装只是文件拷贝,不需要 E10 登录;Agent 需新会话或重载
|
|
70
|
+
Skill 后才读取新内容。完整安装/升级流程见仓库 `docs/agent-skill-install.md`。
|
|
59
71
|
|
|
60
72
|
交付给 Agent 的 Skill ZIP 不内置运行时,只声明依赖本机可用的 `weaver-work-cli`
|
|
61
73
|
bin。ZIP 主要用于平台导入、离线分发或版本归档,不应作为普通用户的必经安装步骤。
|