wtt-connect 0.2.64 → 0.2.65
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/package.json +1 -1
- package/src/main.js +57 -0
- package/src/runner.js +17 -0
- package/src/wtt-api.js +34 -0
package/package.json
CHANGED
package/src/main.js
CHANGED
|
@@ -10,6 +10,7 @@ import { smokeChat, smokeTask } from './smoke.js';
|
|
|
10
10
|
import { ArtifactManager } from './artifacts.js';
|
|
11
11
|
import { DurableStore } from './store.js';
|
|
12
12
|
import { WTTClient } from './wtt-client.js';
|
|
13
|
+
import { WTTApi } from './wtt-api.js';
|
|
13
14
|
import { log, redact } from './logger.js';
|
|
14
15
|
import { adapterBin, normalizeProfileName } from './adapters/generic-cli.js';
|
|
15
16
|
import { normalizeAdapterName } from './adapters/index.js';
|
|
@@ -38,6 +39,7 @@ export async function main(args) {
|
|
|
38
39
|
if (cmd === 'upload-artifact' || cmd === 'opendesign-upload') return uploadArtifact(loadConfig(argv), argv);
|
|
39
40
|
if (cmd === 'preview-port' || cmd === 'sandbox-preview') return previewPort(loadConfig(argv), argv);
|
|
40
41
|
if (cmd === 'cleanup-previews' || cmd === 'preview-cleanup') return cleanupPreviewsCommand(loadConfig(argv), argv);
|
|
42
|
+
if (cmd === 'feishu' || cmd === 'lark') return feishuCommand(loadConfig(argv), argv);
|
|
41
43
|
if (cmd === 'start') {
|
|
42
44
|
const config = loadConfig(argv);
|
|
43
45
|
if (!config.agentId) throw new Error('WTT_AGENT_ID is required');
|
|
@@ -92,6 +94,9 @@ function parseArgs(args) {
|
|
|
92
94
|
else if (a === '--source') out.source = args[++i];
|
|
93
95
|
else if (a === '--source-id') out.sourceId = args[++i];
|
|
94
96
|
else if (a === '--title') out.title = args[++i];
|
|
97
|
+
else if (a === '--content') out.content = args[++i];
|
|
98
|
+
else if (a === '--folder-token') out.folderToken = args[++i];
|
|
99
|
+
else if (a === '--max-chars') out.maxChars = Number(args[++i]);
|
|
95
100
|
else if (a === '--entry') out.entry = args[++i];
|
|
96
101
|
else if (a === '--type') out.type = args[++i];
|
|
97
102
|
else if (a === '--port') out.port = Number(args[++i]);
|
|
@@ -151,10 +156,62 @@ Commands:
|
|
|
151
156
|
Create a Cloud Sandbox live preview URL; snapshots are opt-in
|
|
152
157
|
cleanup-previews [--keep-last <n>]
|
|
153
158
|
Stop preview servers previously registered by this agent
|
|
159
|
+
feishu read-doc <url-or-token> [--max-chars n]
|
|
160
|
+
Read a Feishu/Lark doc shared with the WTT Bot
|
|
161
|
+
feishu create-doc --title <title> [--content text|--file path] [--folder-token token]
|
|
162
|
+
Create a Feishu/Lark doc through the WTT Bot
|
|
163
|
+
feishu append-doc <url-or-token> (--content text|--file path)
|
|
164
|
+
Append text to a Feishu/Lark doc through the WTT Bot
|
|
154
165
|
help Show this help
|
|
155
166
|
`);
|
|
156
167
|
}
|
|
157
168
|
|
|
169
|
+
async function feishuCommand(config, argv) {
|
|
170
|
+
const subcommand = String(argv._[0] || '').trim().toLowerCase();
|
|
171
|
+
const api = new WTTApi(config);
|
|
172
|
+
if (!config.agentId) throw new Error('WTT_AGENT_ID is required');
|
|
173
|
+
if (!config.token) throw new Error('WTT_TOKEN or WTT_AGENT_TOKEN is required');
|
|
174
|
+
if (subcommand === 'read-doc' || subcommand === 'read') {
|
|
175
|
+
const urlOrToken = String(argv._[1] || argv.url || argv.token || '').trim();
|
|
176
|
+
if (!urlOrToken) throw new Error('feishu read-doc requires <url-or-token>');
|
|
177
|
+
const result = await api.feishuReadDoc({ urlOrToken, maxChars: argv.maxChars });
|
|
178
|
+
console.log(JSON.stringify(result, null, 2));
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (subcommand === 'create-doc' || subcommand === 'create') {
|
|
182
|
+
const title = String(argv.title || '').trim();
|
|
183
|
+
if (!title) throw new Error('feishu create-doc requires --title <title>');
|
|
184
|
+
const content = readCommandContent(argv);
|
|
185
|
+
const result = await api.feishuCreateDoc({ title, content, folderToken: argv.folderToken || '' });
|
|
186
|
+
console.log(JSON.stringify(result, null, 2));
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
if (subcommand === 'append-doc' || subcommand === 'append') {
|
|
190
|
+
const urlOrToken = String(argv._[1] || argv.url || argv.token || '').trim();
|
|
191
|
+
if (!urlOrToken) throw new Error('feishu append-doc requires <url-or-token>');
|
|
192
|
+
const content = readCommandContent(argv);
|
|
193
|
+
if (!content.trim()) throw new Error('feishu append-doc requires --content <text> or --file <path>');
|
|
194
|
+
const result = await api.feishuAppendDoc({ urlOrToken, content });
|
|
195
|
+
console.log(JSON.stringify(result, null, 2));
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
throw new Error([
|
|
199
|
+
'unknown feishu command',
|
|
200
|
+
'Usage:',
|
|
201
|
+
' wtt-connect feishu read-doc <url-or-token> [--max-chars n]',
|
|
202
|
+
' wtt-connect feishu create-doc --title <title> [--content text|--file path] [--folder-token token]',
|
|
203
|
+
' wtt-connect feishu append-doc <url-or-token> (--content text|--file path)',
|
|
204
|
+
].join('\n'));
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
function readCommandContent(argv) {
|
|
208
|
+
if (typeof argv.content === 'string') return argv.content;
|
|
209
|
+
const file = Array.isArray(argv.files) ? argv.files[0] : '';
|
|
210
|
+
if (!file) return '';
|
|
211
|
+
const resolved = path.resolve(String(file));
|
|
212
|
+
return fs.readFileSync(resolved, 'utf8');
|
|
213
|
+
}
|
|
214
|
+
|
|
158
215
|
async function previewPort(config, argv) {
|
|
159
216
|
const port = Number(argv.port || argv._[0]);
|
|
160
217
|
if (!Number.isInteger(port) || port < 1024 || port > 65535 || port === 3000) {
|
package/src/runner.js
CHANGED
|
@@ -254,6 +254,7 @@ export class Runner {
|
|
|
254
254
|
staged.promptBlock,
|
|
255
255
|
renderTranscriptBlock(transcripts),
|
|
256
256
|
renderCloudSandboxStorageInstruction(this.config, topicId),
|
|
257
|
+
renderFeishuToolInstruction(this.config),
|
|
257
258
|
renderGeneratedFileArtifactInstruction(this.config, topicId),
|
|
258
259
|
'Reply naturally and concisely unless the user asks for detail.',
|
|
259
260
|
].filter(Boolean).join('\n');
|
|
@@ -1142,6 +1143,21 @@ function renderGeneratedFileArtifactInstruction(config, topicId = '') {
|
|
|
1142
1143
|
].join('\n');
|
|
1143
1144
|
}
|
|
1144
1145
|
|
|
1146
|
+
function renderFeishuToolInstruction(config) {
|
|
1147
|
+
if (!config.agentId || !config.token) return '';
|
|
1148
|
+
return [
|
|
1149
|
+
'Feishu/Lark document tool rule, for internal execution only:',
|
|
1150
|
+
'- If the user asks you to read, summarize, analyze, create, or append a Feishu/Lark document, or provides a docs.feishu.cn / feishu.cn / larksuite.com docx/wiki link, call the local WTT Feishu tool instead of guessing from the URL.',
|
|
1151
|
+
'- Read a document: `wtt-connect feishu read-doc "<feishu_doc_or_wiki_url>" --max-chars 50000`.',
|
|
1152
|
+
'- Create a document: `wtt-connect feishu create-doc --title "Title" --content "text"` or put larger content in a file and use `--file path`.',
|
|
1153
|
+
'- Append to a document: `wtt-connect feishu append-doc "<feishu_doc_or_wiki_url>" --content "text"` or `--file path`.',
|
|
1154
|
+
'- The backend only proxies explicit tool calls; do not claim you accessed a Feishu document unless the command succeeds.',
|
|
1155
|
+
'- If the command returns a permission error, tell the user to share the document with the WTT Bot or grant the WTT Feishu app cloud document permissions.',
|
|
1156
|
+
'- The first version intentionally supports read/create/append only. Do not attempt destructive delete, clear, or overwrite operations.',
|
|
1157
|
+
'- When the user explicitly asks to write/create/append a Feishu document, proceed without asking for an extra confirmation.',
|
|
1158
|
+
].join('\n');
|
|
1159
|
+
}
|
|
1160
|
+
|
|
1145
1161
|
function renderCloudSandboxStorageInstruction(config, topicId = '') {
|
|
1146
1162
|
if (!config.cloudSandbox) return '';
|
|
1147
1163
|
const workDir = config.workDir || process.cwd();
|
|
@@ -1645,6 +1661,7 @@ function buildTaskPrompt(task, config, staged = { promptBlock: '' }, transcripts
|
|
|
1645
1661
|
'',
|
|
1646
1662
|
config.requireCommitPush ? 'For code changes, commit and push before final response, and include commit id.' : '',
|
|
1647
1663
|
renderCloudSandboxStorageInstruction(config, task.topic_id || task.topicId || ''),
|
|
1664
|
+
renderFeishuToolInstruction(config),
|
|
1648
1665
|
renderGeneratedFileArtifactInstruction(config, task.topic_id || task.topicId || ''),
|
|
1649
1666
|
'Return a concise final summary with evidence, changed files, tests, artifacts, and blockers.',
|
|
1650
1667
|
].filter(Boolean).join('\n');
|
package/src/wtt-api.js
CHANGED
|
@@ -130,4 +130,38 @@ export class WTTApi {
|
|
|
130
130
|
}
|
|
131
131
|
}
|
|
132
132
|
|
|
133
|
+
async feishuReadDoc({ urlOrToken, maxChars } = {}) {
|
|
134
|
+
return this.request('POST', '/integrations/feishu/agent/doc/read', {
|
|
135
|
+
headers: this.agentHeaders(),
|
|
136
|
+
json: {
|
|
137
|
+
agent_id: this.config.agentId,
|
|
138
|
+
url_or_token: urlOrToken,
|
|
139
|
+
...(maxChars ? { max_chars: Number(maxChars) } : {}),
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
async feishuCreateDoc({ title, content = '', folderToken = '' } = {}) {
|
|
145
|
+
return this.request('POST', '/integrations/feishu/agent/doc/create', {
|
|
146
|
+
headers: this.agentHeaders(),
|
|
147
|
+
json: {
|
|
148
|
+
agent_id: this.config.agentId,
|
|
149
|
+
title,
|
|
150
|
+
content,
|
|
151
|
+
...(folderToken ? { folder_token: folderToken } : {}),
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
async feishuAppendDoc({ urlOrToken, content } = {}) {
|
|
157
|
+
return this.request('POST', '/integrations/feishu/agent/doc/append', {
|
|
158
|
+
headers: this.agentHeaders(),
|
|
159
|
+
json: {
|
|
160
|
+
agent_id: this.config.agentId,
|
|
161
|
+
url_or_token: urlOrToken,
|
|
162
|
+
content,
|
|
163
|
+
},
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
|
|
133
167
|
}
|