wtt-connect 0.2.63 → 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 +52 -1
- package/src/runtime-info.js +138 -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
|
@@ -228,8 +228,9 @@ export class Runner {
|
|
|
228
228
|
return;
|
|
229
229
|
}
|
|
230
230
|
}
|
|
231
|
+
const skillSlashPrompt = isSlashPassthrough ? this.skillSlashPrompt(content, m.metadata) : '';
|
|
231
232
|
const compactSummary = this.store.getSession(sessionKey).compactSummary || '';
|
|
232
|
-
const prompt = isSlashPassthrough ? content : [
|
|
233
|
+
const prompt = isSlashPassthrough ? (skillSlashPrompt || content) : [
|
|
233
234
|
'You are replying to a WTT Web conversation. Do not mention implementation internals unless asked.',
|
|
234
235
|
`WTT topic_id: ${topicId}`,
|
|
235
236
|
`WTT topic_type: ${messageTopicType(m) || 'unknown'}`,
|
|
@@ -253,6 +254,7 @@ export class Runner {
|
|
|
253
254
|
staged.promptBlock,
|
|
254
255
|
renderTranscriptBlock(transcripts),
|
|
255
256
|
renderCloudSandboxStorageInstruction(this.config, topicId),
|
|
257
|
+
renderFeishuToolInstruction(this.config),
|
|
256
258
|
renderGeneratedFileArtifactInstruction(this.config, topicId),
|
|
257
259
|
'Reply naturally and concisely unless the user asks for detail.',
|
|
258
260
|
].filter(Boolean).join('\n');
|
|
@@ -434,6 +436,12 @@ export class Runner {
|
|
|
434
436
|
return `${adapterDisplayName(adapter.name)} session cleared for this WTT topic. The next turn starts a fresh agent thread/session.`;
|
|
435
437
|
}
|
|
436
438
|
|
|
439
|
+
skillSlashPrompt(content, metadata = null) {
|
|
440
|
+
const runtime = this.runtimeInfo();
|
|
441
|
+
const commands = Array.isArray(runtime.skill_commands) ? runtime.skill_commands : [];
|
|
442
|
+
return buildSkillSlashPrompt(content, metadata, commands);
|
|
443
|
+
}
|
|
444
|
+
|
|
437
445
|
async compactAdapterSession(adapter, context = {}, command = '/compact', args = '') {
|
|
438
446
|
const sessionKey = context.sessionKey || 'default';
|
|
439
447
|
const topicId = String(context.topicId || '').trim();
|
|
@@ -764,6 +772,33 @@ export class Runner {
|
|
|
764
772
|
}
|
|
765
773
|
}
|
|
766
774
|
|
|
775
|
+
export function buildSkillSlashPrompt(content, metadata = null, commands = []) {
|
|
776
|
+
const parsed = parseSlashCommand(content);
|
|
777
|
+
if (!parsed) return '';
|
|
778
|
+
const meta = parseMetadata(metadata);
|
|
779
|
+
const metadataSkillId = String(meta?.skill_id || meta?.skillId || '').trim();
|
|
780
|
+
const metadataFamily = String(meta?.command_family || meta?.commandFamily || '').trim().toLowerCase();
|
|
781
|
+
const matched = (Array.isArray(commands) ? commands : []).find((item) => String(item?.cmd || '').trim().toLowerCase() === parsed.command)
|
|
782
|
+
|| (metadataFamily === 'skill' || metadataSkillId ? {
|
|
783
|
+
cmd: parsed.command,
|
|
784
|
+
skill_id: metadataSkillId || parsed.command.replace(/^\/+/, ''),
|
|
785
|
+
name: metadataSkillId || parsed.command.replace(/^\/+/, ''),
|
|
786
|
+
desc: '',
|
|
787
|
+
} : null);
|
|
788
|
+
if (!matched) return '';
|
|
789
|
+
const skillName = String(matched.name || matched.skill_id || matched.cmd || '').trim().replace(/^\/+/, '');
|
|
790
|
+
const skillId = String(matched.skill_id || skillName).trim();
|
|
791
|
+
const args = String(parsed.args || '').trim();
|
|
792
|
+
return [
|
|
793
|
+
`Use the ${skillName} skill${skillId && skillId !== skillName ? ` (${skillId})` : ''}.`,
|
|
794
|
+
matched.desc ? `Skill description: ${matched.desc}` : null,
|
|
795
|
+
'',
|
|
796
|
+
args ? `User request: ${args}` : 'User request: Run this skill for the current conversation.',
|
|
797
|
+
'',
|
|
798
|
+
`Original slash command: ${content}`,
|
|
799
|
+
].filter(Boolean).join('\n');
|
|
800
|
+
}
|
|
801
|
+
|
|
767
802
|
function adapterDisplayName(name) {
|
|
768
803
|
if (name === 'claude-code') return 'Claude Code';
|
|
769
804
|
if (name === 'codex') return 'Codex';
|
|
@@ -1108,6 +1143,21 @@ function renderGeneratedFileArtifactInstruction(config, topicId = '') {
|
|
|
1108
1143
|
].join('\n');
|
|
1109
1144
|
}
|
|
1110
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
|
+
|
|
1111
1161
|
function renderCloudSandboxStorageInstruction(config, topicId = '') {
|
|
1112
1162
|
if (!config.cloudSandbox) return '';
|
|
1113
1163
|
const workDir = config.workDir || process.cwd();
|
|
@@ -1611,6 +1661,7 @@ function buildTaskPrompt(task, config, staged = { promptBlock: '' }, transcripts
|
|
|
1611
1661
|
'',
|
|
1612
1662
|
config.requireCommitPush ? 'For code changes, commit and push before final response, and include commit id.' : '',
|
|
1613
1663
|
renderCloudSandboxStorageInstruction(config, task.topic_id || task.topicId || ''),
|
|
1664
|
+
renderFeishuToolInstruction(config),
|
|
1614
1665
|
renderGeneratedFileArtifactInstruction(config, task.topic_id || task.topicId || ''),
|
|
1615
1666
|
'Return a concise final summary with evidence, changed files, tests, artifacts, and blockers.',
|
|
1616
1667
|
].filter(Boolean).join('\n');
|
package/src/runtime-info.js
CHANGED
|
@@ -3,6 +3,9 @@ import path from 'node:path';
|
|
|
3
3
|
import fs from 'node:fs';
|
|
4
4
|
import { execFileSync } from 'node:child_process';
|
|
5
5
|
|
|
6
|
+
let skillCommandCache = { at: 0, commands: [] };
|
|
7
|
+
const SKILL_COMMAND_CACHE_MS = 60_000;
|
|
8
|
+
|
|
6
9
|
export function buildRuntimeInfo(config, runtimeState = {}) {
|
|
7
10
|
const workdir = resolveWorkDir(config.workDir);
|
|
8
11
|
const git = gitInfo(workdir);
|
|
@@ -30,10 +33,145 @@ export function buildRuntimeInfo(config, runtimeState = {}) {
|
|
|
30
33
|
node: process.version,
|
|
31
34
|
mode: config.mode,
|
|
32
35
|
git,
|
|
36
|
+
skill_commands: discoverSkillCommands(config, workdir),
|
|
33
37
|
updated_at: new Date().toISOString(),
|
|
34
38
|
};
|
|
35
39
|
}
|
|
36
40
|
|
|
41
|
+
export function discoverSkillCommands(config = {}, workdir = resolveWorkDir(config.workDir)) {
|
|
42
|
+
const now = Date.now();
|
|
43
|
+
if (now - skillCommandCache.at < SKILL_COMMAND_CACHE_MS) return skillCommandCache.commands;
|
|
44
|
+
const roots = skillRoots(config, workdir);
|
|
45
|
+
const seenCommands = new Set();
|
|
46
|
+
const commands = [];
|
|
47
|
+
for (const root of roots) {
|
|
48
|
+
for (const skillFile of findSkillFiles(root, 5)) {
|
|
49
|
+
const parsed = parseSkillFile(skillFile);
|
|
50
|
+
if (!parsed.id) continue;
|
|
51
|
+
const commandName = normalizeSkillCommandName(parsed.name || parsed.id);
|
|
52
|
+
if (!commandName) continue;
|
|
53
|
+
const cmd = `/${commandName}`;
|
|
54
|
+
const key = cmd.toLowerCase();
|
|
55
|
+
if (seenCommands.has(key)) continue;
|
|
56
|
+
seenCommands.add(key);
|
|
57
|
+
commands.push({
|
|
58
|
+
cmd,
|
|
59
|
+
desc: parsed.description || `Use ${parsed.name || parsed.id} skill`,
|
|
60
|
+
family: 'skill',
|
|
61
|
+
mode: 'passthrough',
|
|
62
|
+
skill_id: parsed.id,
|
|
63
|
+
name: parsed.name || parsed.id,
|
|
64
|
+
source: parsed.source,
|
|
65
|
+
});
|
|
66
|
+
if (commands.length >= 120) break;
|
|
67
|
+
}
|
|
68
|
+
if (commands.length >= 120) break;
|
|
69
|
+
}
|
|
70
|
+
skillCommandCache = { at: now, commands };
|
|
71
|
+
return commands;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function skillRoots(config = {}, workdir = '') {
|
|
75
|
+
const home = os.homedir();
|
|
76
|
+
const roots = [
|
|
77
|
+
path.join(home, '.codex', 'skills'),
|
|
78
|
+
path.join(home, '.agents', 'skills'),
|
|
79
|
+
path.join(home, '.claude', 'skills'),
|
|
80
|
+
path.join(home, '.claude', 'mattpocock-skills', 'skills'),
|
|
81
|
+
workdir ? path.join(workdir, '.codex', 'skills') : '',
|
|
82
|
+
workdir ? path.join(workdir, '.claude', 'skills') : '',
|
|
83
|
+
process.cwd() ? path.join(process.cwd(), '.codex', 'skills') : '',
|
|
84
|
+
process.cwd() ? path.join(process.cwd(), '.claude', 'skills') : '',
|
|
85
|
+
];
|
|
86
|
+
const extra = String(process.env.WTT_CONNECT_SKILL_ROOTS || config.skillRoots || '').split(path.delimiter);
|
|
87
|
+
return Array.from(new Set(
|
|
88
|
+
[...roots, ...extra]
|
|
89
|
+
.map((item) => String(item || '').trim())
|
|
90
|
+
.filter(Boolean)
|
|
91
|
+
.map((item) => path.resolve(item))
|
|
92
|
+
));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function findSkillFiles(root, maxDepth = 4) {
|
|
96
|
+
const out = [];
|
|
97
|
+
if (!root || !fs.existsSync(root)) return out;
|
|
98
|
+
const visit = (dir, depth) => {
|
|
99
|
+
if (depth < 0 || out.length >= 160) return;
|
|
100
|
+
let entries = [];
|
|
101
|
+
try {
|
|
102
|
+
entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
103
|
+
} catch {
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
if (entries.some((entry) => entry.isFile() && entry.name === 'SKILL.md')) {
|
|
107
|
+
out.push(path.join(dir, 'SKILL.md'));
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
for (const entry of entries) {
|
|
111
|
+
if (!entry.isDirectory()) continue;
|
|
112
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.git')) continue;
|
|
113
|
+
visit(path.join(dir, entry.name), depth - 1);
|
|
114
|
+
if (out.length >= 160) return;
|
|
115
|
+
}
|
|
116
|
+
};
|
|
117
|
+
visit(root, maxDepth);
|
|
118
|
+
return out;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function parseSkillFile(file) {
|
|
122
|
+
try {
|
|
123
|
+
const text = fs.readFileSync(file, 'utf8');
|
|
124
|
+
const fallbackId = path.basename(path.dirname(file));
|
|
125
|
+
const frontmatter = text.match(/^---\s*\n([\s\S]*?)\n---/);
|
|
126
|
+
const meta = frontmatter ? parseSimpleYaml(frontmatter[1]) : {};
|
|
127
|
+
const id = String(meta.name || fallbackId || '').trim();
|
|
128
|
+
return {
|
|
129
|
+
id,
|
|
130
|
+
name: id,
|
|
131
|
+
description: String(meta.description || firstMarkdownSentence(text) || '').trim(),
|
|
132
|
+
source: sourceForSkillPath(file),
|
|
133
|
+
};
|
|
134
|
+
} catch {
|
|
135
|
+
return { id: '', name: '', description: '', source: 'local' };
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function parseSimpleYaml(text) {
|
|
140
|
+
const out = {};
|
|
141
|
+
for (const line of String(text || '').split(/\r?\n/)) {
|
|
142
|
+
const match = line.match(/^([A-Za-z0-9_-]+)\s*:\s*(.*)$/);
|
|
143
|
+
if (!match) continue;
|
|
144
|
+
const key = match[1];
|
|
145
|
+
let value = match[2].trim();
|
|
146
|
+
value = value.replace(/^['"]|['"]$/g, '');
|
|
147
|
+
out[key] = value;
|
|
148
|
+
}
|
|
149
|
+
return out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
function firstMarkdownSentence(text) {
|
|
153
|
+
const body = String(text || '').replace(/^---\s*\n[\s\S]*?\n---/, '').trim();
|
|
154
|
+
const line = body.split(/\r?\n/).map((item) => item.trim().replace(/^#+\s*/, '')).find(Boolean);
|
|
155
|
+
return line || '';
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function normalizeSkillCommandName(value) {
|
|
159
|
+
const raw = String(value || '').trim().split(':').pop() || '';
|
|
160
|
+
return raw
|
|
161
|
+
.replace(/[^A-Za-z0-9_-]+/g, '-')
|
|
162
|
+
.replace(/^-+|-+$/g, '')
|
|
163
|
+
.slice(0, 80)
|
|
164
|
+
.toLowerCase();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
function sourceForSkillPath(file) {
|
|
168
|
+
const normalized = String(file || '');
|
|
169
|
+
if (normalized.includes(`${path.sep}.codex${path.sep}`)) return 'codex-local';
|
|
170
|
+
if (normalized.includes(`${path.sep}.claude${path.sep}`)) return 'claude-local';
|
|
171
|
+
if (normalized.includes(`${path.sep}.agents${path.sep}`)) return 'agents-local';
|
|
172
|
+
return 'local';
|
|
173
|
+
}
|
|
174
|
+
|
|
37
175
|
function runtimeModel(config, adapter, runtimeState = {}) {
|
|
38
176
|
const fromRun = String(runtimeState.current_model || runtimeState.model || '').trim();
|
|
39
177
|
if (fromRun) return fromRun;
|
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
|
}
|