teamshare-bridge 0.1.0
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 +343 -0
- package/dist/bridge/daemon.d.ts +1 -0
- package/dist/bridge/daemon.js +230 -0
- package/dist/bridge/daemon.js.map +1 -0
- package/dist/bridge/index.d.ts +2 -0
- package/dist/bridge/index.js +273 -0
- package/dist/bridge/index.js.map +1 -0
- package/dist/bridge/local-server.d.ts +29 -0
- package/dist/bridge/local-server.js +87 -0
- package/dist/bridge/local-server.js.map +1 -0
- package/dist/bridge/protocol.d.ts +4 -0
- package/dist/bridge/protocol.js +151 -0
- package/dist/bridge/protocol.js.map +1 -0
- package/dist/bridge/service.d.ts +32 -0
- package/dist/bridge/service.js +248 -0
- package/dist/bridge/service.js.map +1 -0
- package/dist/bridge/spawn.d.ts +15 -0
- package/dist/bridge/spawn.js +271 -0
- package/dist/bridge/spawn.js.map +1 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +543 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/lib/api.d.ts +191 -0
- package/dist/lib/api.js +209 -0
- package/dist/lib/api.js.map +1 -0
- package/dist/lib/brief.d.ts +16 -0
- package/dist/lib/brief.js +115 -0
- package/dist/lib/brief.js.map +1 -0
- package/dist/lib/chat-reply.d.ts +29 -0
- package/dist/lib/chat-reply.js +126 -0
- package/dist/lib/chat-reply.js.map +1 -0
- package/dist/lib/config.d.ts +25 -0
- package/dist/lib/config.js +81 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/doc-reply.d.ts +22 -0
- package/dist/lib/doc-reply.js +108 -0
- package/dist/lib/doc-reply.js.map +1 -0
- package/dist/lib/llm.d.ts +50 -0
- package/dist/lib/llm.js +444 -0
- package/dist/lib/llm.js.map +1 -0
- package/dist/lib/lock.d.ts +41 -0
- package/dist/lib/lock.js +148 -0
- package/dist/lib/lock.js.map +1 -0
- package/dist/lib/models.d.ts +30 -0
- package/dist/lib/models.js +51 -0
- package/dist/lib/models.js.map +1 -0
- package/dist/lib/partial-stream.d.ts +25 -0
- package/dist/lib/partial-stream.js +99 -0
- package/dist/lib/partial-stream.js.map +1 -0
- package/dist/lib/session-stream.d.ts +38 -0
- package/dist/lib/session-stream.js +191 -0
- package/dist/lib/session-stream.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runChatReply = runChatReply;
|
|
4
|
+
/**
|
|
5
|
+
* Agent chat-reply loop (`teamshare-agent chat`): reads the recent project
|
|
6
|
+
* channel and replies to EVERY message that mentions the agent, separately.
|
|
7
|
+
* Generation uses the configured harness (opencode `run` / `claude -p`,
|
|
8
|
+
* non-interactive, stdout captured) or the `--self` LLM completion.
|
|
9
|
+
* Phase C (IMP-530): `--self` replies stream token-by-token into the
|
|
10
|
+
* channel as `message:partial` frames when a stream socket is provided;
|
|
11
|
+
* the final message is still posted via POST /chat/messages.
|
|
12
|
+
*/
|
|
13
|
+
const node_child_process_1 = require("node:child_process");
|
|
14
|
+
const llm_1 = require("./llm");
|
|
15
|
+
const partial_stream_1 = require("./partial-stream");
|
|
16
|
+
const MAX_TARGETS = 10;
|
|
17
|
+
const CONTEXT_WINDOW = 10;
|
|
18
|
+
function hasBin(bin) {
|
|
19
|
+
try {
|
|
20
|
+
(0, node_child_process_1.execFileSync)(bin, ['--version'], { stdio: 'ignore' });
|
|
21
|
+
return true;
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
/** Generates a reply via the harness (non-interactive) or headless LLM. */
|
|
28
|
+
async function generateReply(agentName, target, prompt, opts, onToken) {
|
|
29
|
+
if (opts.echo) {
|
|
30
|
+
const reply = `@${target.author?.name ?? 'there'} — this is an automated acknowledgment from ${agentName}. I saw your message and I'm on it.`;
|
|
31
|
+
if (onToken)
|
|
32
|
+
onToken(reply);
|
|
33
|
+
return reply;
|
|
34
|
+
}
|
|
35
|
+
if (opts.selfMode || opts.harness === 'none') {
|
|
36
|
+
if (!opts.llm?.apiKey) {
|
|
37
|
+
throw new Error('--self / --harness none requires LLM_API_KEY (and optionally LLM_BASE_URL / LLM_MODEL)');
|
|
38
|
+
}
|
|
39
|
+
// Phase C: stream the completion when the caller provided a stream socket.
|
|
40
|
+
if (onToken) {
|
|
41
|
+
return (0, llm_1.completeStream)(prompt, opts.llm, onToken);
|
|
42
|
+
}
|
|
43
|
+
return (0, llm_1.complete)(prompt, opts.llm);
|
|
44
|
+
}
|
|
45
|
+
if (opts.harness === 'opencode' || (opts.harness === 'auto' && hasBin('opencode'))) {
|
|
46
|
+
return (0, node_child_process_1.execFileSync)('opencode', ['run', prompt], {
|
|
47
|
+
encoding: 'utf8',
|
|
48
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
49
|
+
}).trim();
|
|
50
|
+
}
|
|
51
|
+
if (opts.harness === 'claude' || (opts.harness === 'auto' && hasBin('claude'))) {
|
|
52
|
+
return (0, node_child_process_1.execFileSync)('claude', ['-p', prompt], {
|
|
53
|
+
encoding: 'utf8',
|
|
54
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
55
|
+
}).trim();
|
|
56
|
+
}
|
|
57
|
+
throw new Error('No harness found (install opencode or claude, or use --self with LLM_API_KEY)');
|
|
58
|
+
}
|
|
59
|
+
function mentionPrompt(agentName, target, context) {
|
|
60
|
+
const lines = context
|
|
61
|
+
.map((m) => `[${m.createdAt}] ${m.author?.name ?? '?'}: ${m.body}`)
|
|
62
|
+
.join('\n');
|
|
63
|
+
return [
|
|
64
|
+
`You are ${agentName}, a TeamShare project assistant. The project chat looks like this:`,
|
|
65
|
+
'',
|
|
66
|
+
lines,
|
|
67
|
+
'',
|
|
68
|
+
`The latest message mentions you (@${agentName}):`,
|
|
69
|
+
'',
|
|
70
|
+
`[${target.createdAt}] ${target.author?.name ?? 'someone'}: ${target.body}`,
|
|
71
|
+
'',
|
|
72
|
+
'Reply to that message directly. Address the person by name if known. Be concise and useful.',
|
|
73
|
+
].join('\n');
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Runs the chat reply loop. Heartbeats working/online around the work and
|
|
77
|
+
* posts one reply per mentioning message (in chronological order).
|
|
78
|
+
*/
|
|
79
|
+
async function runChatReply(api, agentId, projectId, mentionToken, opts) {
|
|
80
|
+
const token = mentionToken.replace(/^@/, '').toLowerCase();
|
|
81
|
+
const selfName = mentionToken.replace(/^@/, '');
|
|
82
|
+
const page = await api.listChatMessages(projectId, 1, 50);
|
|
83
|
+
const rows = [...(page ?? [])].sort((a, b) => new Date(a.createdAt).getTime() - new Date(b.createdAt).getTime());
|
|
84
|
+
if (!rows.length)
|
|
85
|
+
return { replied: 0, skipped: 0 };
|
|
86
|
+
// Every message that mentions the agent, excluding messages the agent
|
|
87
|
+
// itself authored (its own replies mention other people, not itself).
|
|
88
|
+
const targets = rows.filter((m) => {
|
|
89
|
+
const mentionsAgent = m.body.toLowerCase().includes(`@${token}`);
|
|
90
|
+
const isAgent = m.author?.kind === 'agent' ||
|
|
91
|
+
(m.author?.name ?? '').toLowerCase() === selfName.toLowerCase();
|
|
92
|
+
return mentionsAgent && !isAgent;
|
|
93
|
+
});
|
|
94
|
+
if (!targets.length)
|
|
95
|
+
return { replied: 0, skipped: 0 };
|
|
96
|
+
let replied = 0;
|
|
97
|
+
for (const target of targets.slice(0, MAX_TARGETS)) {
|
|
98
|
+
const targetIndex = rows.findIndex((r) => r.id === target.id);
|
|
99
|
+
const context = rows.slice(Math.max(0, targetIndex - CONTEXT_WINDOW), targetIndex + 1);
|
|
100
|
+
const prompt = mentionPrompt(selfName, target, context);
|
|
101
|
+
// Phase C: open a partial stream per target when configured (streaming
|
|
102
|
+
// is best-effort - failures fall back to the plain final post).
|
|
103
|
+
const draftId = `draft_${target.id}`;
|
|
104
|
+
let stream = null;
|
|
105
|
+
if (opts.stream && (opts.selfMode || opts.harness === 'none' || opts.echo)) {
|
|
106
|
+
stream = new partial_stream_1.PartialStream({
|
|
107
|
+
wsBase: opts.stream.wsBase,
|
|
108
|
+
apiKey: opts.stream.apiKey,
|
|
109
|
+
projectId: opts.stream.projectId,
|
|
110
|
+
channelId: opts.stream.channelId,
|
|
111
|
+
}, draftId);
|
|
112
|
+
stream.connect();
|
|
113
|
+
}
|
|
114
|
+
const reply = await generateReply(selfName, target, prompt, opts, (delta) => stream?.token(delta));
|
|
115
|
+
if (!reply) {
|
|
116
|
+
stream?.end();
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const posted = await api.postChatMessage(projectId, reply);
|
|
120
|
+
stream?.end(posted?.id ??
|
|
121
|
+
posted?.message?.id);
|
|
122
|
+
replied += 1;
|
|
123
|
+
}
|
|
124
|
+
return { replied, skipped: targets.length - replied };
|
|
125
|
+
}
|
|
126
|
+
//# sourceMappingURL=chat-reply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"chat-reply.js","sourceRoot":"","sources":["../../src/lib/chat-reply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/** Ports the website probes to detect the bridge (contract section 5). */
|
|
2
|
+
export declare const BRIDGE_CANDIDATE_PORTS: readonly [48231, 48242, 48253, 48264, 48275, 48286, 48297];
|
|
3
|
+
export interface AgentConfig {
|
|
4
|
+
agentId: string;
|
|
5
|
+
apiKey: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BridgeConfig {
|
|
8
|
+
agents: AgentConfig[];
|
|
9
|
+
port: number;
|
|
10
|
+
harness: 'auto' | 'opencode' | 'claude' | 'none';
|
|
11
|
+
quietHours: {
|
|
12
|
+
start: string;
|
|
13
|
+
end: string;
|
|
14
|
+
} | null;
|
|
15
|
+
wakeRules: {
|
|
16
|
+
priorities: string[];
|
|
17
|
+
} | null;
|
|
18
|
+
}
|
|
19
|
+
export declare function configPath(): string;
|
|
20
|
+
export declare function defaultConfig(): BridgeConfig;
|
|
21
|
+
export declare function loadConfig(): BridgeConfig;
|
|
22
|
+
export declare function saveConfig(config: BridgeConfig): void;
|
|
23
|
+
/** Adds/updates an agent key entry (used by `connect` and `add-agent`). */
|
|
24
|
+
export declare function upsertAgent(agentId: string, apiKey: string): BridgeConfig;
|
|
25
|
+
export declare function msg(err: unknown): string;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.BRIDGE_CANDIDATE_PORTS = void 0;
|
|
4
|
+
exports.configPath = configPath;
|
|
5
|
+
exports.defaultConfig = defaultConfig;
|
|
6
|
+
exports.loadConfig = loadConfig;
|
|
7
|
+
exports.saveConfig = saveConfig;
|
|
8
|
+
exports.upsertAgent = upsertAgent;
|
|
9
|
+
exports.msg = msg;
|
|
10
|
+
/**
|
|
11
|
+
* teamshare-bridge config: ~/.teamshare/config.json
|
|
12
|
+
*/
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
14
|
+
const node_os_1 = require("node:os");
|
|
15
|
+
const node_path_1 = require("node:path");
|
|
16
|
+
/** Ports the website probes to detect the bridge (contract section 5). */
|
|
17
|
+
exports.BRIDGE_CANDIDATE_PORTS = [
|
|
18
|
+
48231, 48242, 48253, 48264, 48275, 48286, 48297,
|
|
19
|
+
];
|
|
20
|
+
const CONFIG_DIR = (0, node_path_1.join)((0, node_os_1.homedir)(), '.teamshare');
|
|
21
|
+
const CONFIG_PATH = (0, node_path_1.join)(CONFIG_DIR, 'config.json');
|
|
22
|
+
function configPath() {
|
|
23
|
+
return CONFIG_PATH;
|
|
24
|
+
}
|
|
25
|
+
function defaultConfig() {
|
|
26
|
+
const pick = exports.BRIDGE_CANDIDATE_PORTS[Math.floor(Math.random() * exports.BRIDGE_CANDIDATE_PORTS.length)];
|
|
27
|
+
return {
|
|
28
|
+
agents: [],
|
|
29
|
+
port: pick,
|
|
30
|
+
harness: 'auto',
|
|
31
|
+
quietHours: null,
|
|
32
|
+
wakeRules: null,
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
function loadConfig() {
|
|
36
|
+
try {
|
|
37
|
+
if ((0, node_fs_1.existsSync)(CONFIG_PATH)) {
|
|
38
|
+
const raw = JSON.parse((0, node_fs_1.readFileSync)(CONFIG_PATH, 'utf8'));
|
|
39
|
+
const def = defaultConfig();
|
|
40
|
+
return {
|
|
41
|
+
agents: Array.isArray(raw.agents) ? raw.agents : [],
|
|
42
|
+
port: typeof raw.port === 'number' && Number.isInteger(raw.port)
|
|
43
|
+
? raw.port
|
|
44
|
+
: def.port,
|
|
45
|
+
harness: raw.harness ?? def.harness,
|
|
46
|
+
quietHours: raw.quietHours ?? null,
|
|
47
|
+
wakeRules: raw.wakeRules ?? null,
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
console.warn(`[config] failed to read ${CONFIG_PATH}: ${msg(err)}`);
|
|
53
|
+
}
|
|
54
|
+
const def = defaultConfig();
|
|
55
|
+
saveConfig(def);
|
|
56
|
+
return def;
|
|
57
|
+
}
|
|
58
|
+
function saveConfig(config) {
|
|
59
|
+
try {
|
|
60
|
+
(0, node_fs_1.mkdirSync)(CONFIG_DIR, { recursive: true });
|
|
61
|
+
(0, node_fs_1.writeFileSync)(CONFIG_PATH, JSON.stringify(config, null, 2), 'utf8');
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
console.warn(`[config] failed to write ${CONFIG_PATH}: ${msg(err)}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Adds/updates an agent key entry (used by `connect` and `add-agent`). */
|
|
68
|
+
function upsertAgent(agentId, apiKey) {
|
|
69
|
+
const config = loadConfig();
|
|
70
|
+
const existing = config.agents.find((a) => a.agentId === agentId);
|
|
71
|
+
if (existing)
|
|
72
|
+
existing.apiKey = apiKey;
|
|
73
|
+
else
|
|
74
|
+
config.agents.push({ agentId, apiKey });
|
|
75
|
+
saveConfig(config);
|
|
76
|
+
return config;
|
|
77
|
+
}
|
|
78
|
+
function msg(err) {
|
|
79
|
+
return err instanceof Error ? err.message : String(err);
|
|
80
|
+
}
|
|
81
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { TeamshareApi } from './api';
|
|
2
|
+
export interface DocReplyOptions {
|
|
3
|
+
harness: 'auto' | 'opencode' | 'claude' | 'none';
|
|
4
|
+
selfMode: boolean;
|
|
5
|
+
llm?: {
|
|
6
|
+
baseUrl: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
model: string;
|
|
9
|
+
temperature?: number;
|
|
10
|
+
maxTokens?: number;
|
|
11
|
+
};
|
|
12
|
+
/** Debug/testing switch (TS_CHAT_ECHO=1): post canned acknowledgments. */
|
|
13
|
+
echo?: boolean;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Runs the document reply loop: fetch the document + extract, find comments
|
|
17
|
+
* mentioning the agent, reply to each (one per comment, chronological).
|
|
18
|
+
*/
|
|
19
|
+
export declare function runDocReply(api: TeamshareApi, agentId: string, documentId: string, mentionToken: string, opts: DocReplyOptions): Promise<{
|
|
20
|
+
replied: number;
|
|
21
|
+
skipped: number;
|
|
22
|
+
}>;
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.runDocReply = runDocReply;
|
|
4
|
+
/**
|
|
5
|
+
* Phase F document assistant (`teamshare-agent doc`): reads a document's
|
|
6
|
+
* extracted text (Word/PPT/Excel/PDF) plus its comment thread, and replies
|
|
7
|
+
* to every comment that @mentions the agent. The reply quotes the relevant
|
|
8
|
+
* context - the document text is included in the prompt so the model can
|
|
9
|
+
* answer questions about the document content.
|
|
10
|
+
*/
|
|
11
|
+
const node_child_process_1 = require("node:child_process");
|
|
12
|
+
const llm_1 = require("./llm");
|
|
13
|
+
const MAX_TARGETS = 10;
|
|
14
|
+
const CONTEXT_WINDOW = 10;
|
|
15
|
+
const MAX_DOC_CHARS = 60_000;
|
|
16
|
+
function hasBin(bin) {
|
|
17
|
+
try {
|
|
18
|
+
(0, node_child_process_1.execFileSync)(bin, ['--version'], { stdio: 'ignore' });
|
|
19
|
+
return true;
|
|
20
|
+
}
|
|
21
|
+
catch {
|
|
22
|
+
return false;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
function generateReply(agentName, target, prompt, opts) {
|
|
26
|
+
if (opts.echo) {
|
|
27
|
+
return Promise.resolve(`@${target.author?.name ?? 'there'} — this is an automated acknowledgment from ${agentName}. I read the document and I'm on it.`);
|
|
28
|
+
}
|
|
29
|
+
if (opts.selfMode || opts.harness === 'none') {
|
|
30
|
+
if (!opts.llm?.apiKey) {
|
|
31
|
+
throw new Error('--self / --harness none requires LLM_API_KEY (and optionally LLM_BASE_URL / LLM_MODEL)');
|
|
32
|
+
}
|
|
33
|
+
return (0, llm_1.complete)(prompt, opts.llm);
|
|
34
|
+
}
|
|
35
|
+
if (opts.harness === 'opencode' || (opts.harness === 'auto' && hasBin('opencode'))) {
|
|
36
|
+
return Promise.resolve((0, node_child_process_1.execFileSync)('opencode', ['run', prompt], {
|
|
37
|
+
encoding: 'utf8',
|
|
38
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
39
|
+
}).trim());
|
|
40
|
+
}
|
|
41
|
+
if (opts.harness === 'claude' || (opts.harness === 'auto' && hasBin('claude'))) {
|
|
42
|
+
return Promise.resolve((0, node_child_process_1.execFileSync)('claude', ['-p', prompt], {
|
|
43
|
+
encoding: 'utf8',
|
|
44
|
+
maxBuffer: 2 * 1024 * 1024,
|
|
45
|
+
}).trim());
|
|
46
|
+
}
|
|
47
|
+
throw new Error('No harness found (install opencode or claude, or use --self with LLM_API_KEY)');
|
|
48
|
+
}
|
|
49
|
+
function docPrompt(agentName, docName, docText, target, context) {
|
|
50
|
+
const thread = context
|
|
51
|
+
.map((c) => `[${c.createdAt}] ${c.author?.name ?? '?'}: ${c.body}`)
|
|
52
|
+
.join('\n');
|
|
53
|
+
return [
|
|
54
|
+
`You are ${agentName}, a TeamShare document assistant. The document "${docName}" contains:`,
|
|
55
|
+
'',
|
|
56
|
+
'--- DOCUMENT CONTENT ---',
|
|
57
|
+
docText.slice(0, MAX_DOC_CHARS),
|
|
58
|
+
docText.length > MAX_DOC_CHARS ? '\n…[truncated]' : '',
|
|
59
|
+
'--- END DOCUMENT CONTENT ---',
|
|
60
|
+
'',
|
|
61
|
+
'The document comment thread looks like this:',
|
|
62
|
+
'',
|
|
63
|
+
thread,
|
|
64
|
+
'',
|
|
65
|
+
`The latest comment mentions you (@${agentName}):`,
|
|
66
|
+
'',
|
|
67
|
+
`[${target.createdAt}] ${target.author?.name ?? 'someone'}: ${target.body}`,
|
|
68
|
+
'',
|
|
69
|
+
'Answer that comment directly, based on the document content. Address the person by name if known. Be concise and useful; quote the document where helpful.',
|
|
70
|
+
]
|
|
71
|
+
.filter((line) => line !== '')
|
|
72
|
+
.join('\n');
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Runs the document reply loop: fetch the document + extract, find comments
|
|
76
|
+
* mentioning the agent, reply to each (one per comment, chronological).
|
|
77
|
+
*/
|
|
78
|
+
async function runDocReply(api, agentId, documentId, mentionToken, opts) {
|
|
79
|
+
const token = mentionToken.replace(/^@/, '').toLowerCase();
|
|
80
|
+
const selfName = mentionToken.replace(/^@/, '');
|
|
81
|
+
const [doc, docExtract] = await Promise.all([
|
|
82
|
+
api.getDocument(documentId),
|
|
83
|
+
api.getDocumentExtract(documentId).catch(() => null),
|
|
84
|
+
]);
|
|
85
|
+
const docText = docExtract?.text ?? '(no extractable text - link document or unsupported file)';
|
|
86
|
+
const rows = await api.listDocumentComments(documentId);
|
|
87
|
+
const targets = rows.filter((c) => {
|
|
88
|
+
const mentionsAgent = c.body.toLowerCase().includes(`@${token}`);
|
|
89
|
+
const isAgent = c.author?.kind === 'agent' ||
|
|
90
|
+
(c.author?.name ?? '').toLowerCase() === selfName.toLowerCase();
|
|
91
|
+
return mentionsAgent && !isAgent;
|
|
92
|
+
});
|
|
93
|
+
if (!targets.length)
|
|
94
|
+
return { replied: 0, skipped: 0 };
|
|
95
|
+
let replied = 0;
|
|
96
|
+
for (const target of targets.slice(0, MAX_TARGETS)) {
|
|
97
|
+
const targetIndex = rows.findIndex((r) => r.id === target.id);
|
|
98
|
+
const context = rows.slice(Math.max(0, targetIndex - CONTEXT_WINDOW), targetIndex + 1);
|
|
99
|
+
const prompt = docPrompt(selfName, doc.name, docText, target, context);
|
|
100
|
+
const reply = await generateReply(selfName, target, prompt, opts);
|
|
101
|
+
if (!reply)
|
|
102
|
+
continue;
|
|
103
|
+
await api.addComment({ documentId, body: reply });
|
|
104
|
+
replied += 1;
|
|
105
|
+
}
|
|
106
|
+
return { replied, skipped: targets.length - replied };
|
|
107
|
+
}
|
|
108
|
+
//# sourceMappingURL=doc-reply.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doc-reply.js","sourceRoot":"","sources":["../../src/lib/doc-reply.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { TeamshareApi } from './api';
|
|
2
|
+
export declare const DEFAULT_LLM_BASE_URL = "https://api.openai.com/v1";
|
|
3
|
+
export declare const DEFAULT_LLM_MODEL = "deepseek-chat";
|
|
4
|
+
interface ToolDef {
|
|
5
|
+
name: string;
|
|
6
|
+
description: string;
|
|
7
|
+
parameters: Record<string, unknown>;
|
|
8
|
+
}
|
|
9
|
+
export interface LlmResult {
|
|
10
|
+
summary: string;
|
|
11
|
+
iterations: number;
|
|
12
|
+
tokensUsed: number;
|
|
13
|
+
finishedBy: 'no-tool-call' | 'max-iterations' | 'task-done';
|
|
14
|
+
}
|
|
15
|
+
export interface LlmOptions {
|
|
16
|
+
baseUrl: string;
|
|
17
|
+
apiKey: string;
|
|
18
|
+
model: string;
|
|
19
|
+
agentName: string;
|
|
20
|
+
systemPrompt?: string | null;
|
|
21
|
+
/** Sampling temperature (0-2). Default 0.2 (Phase D). */
|
|
22
|
+
temperature?: number;
|
|
23
|
+
/** Token budget for the completion (Phase D). */
|
|
24
|
+
maxTokens?: number;
|
|
25
|
+
/** Resume a previous --self session for this task (Phase E, IMP-540). */
|
|
26
|
+
continue?: boolean;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Phase B ask-human (IMP-530): markers + polling for the `--self` loop.
|
|
30
|
+
* The MCP server implements the same contract for opencode sessions.
|
|
31
|
+
*/
|
|
32
|
+
export declare const QUESTION_MARKER = "[question]";
|
|
33
|
+
export declare function buildTools(api: TeamshareApi, askTimeoutMsOverride?: number): {
|
|
34
|
+
def: ToolDef;
|
|
35
|
+
run: (args: Record<string, unknown>) => Promise<unknown>;
|
|
36
|
+
}[];
|
|
37
|
+
export declare function runLlmSession(api: TeamshareApi, taskId: string, brief: string, opts: LlmOptions): Promise<LlmResult>;
|
|
38
|
+
/**
|
|
39
|
+
* Single-shot chat completion (no tools) - used by the chat-reply loop to
|
|
40
|
+
* draft a reply to a mention. Same env contract as `--self`.
|
|
41
|
+
*/
|
|
42
|
+
export declare function complete(prompt: string, opts: Pick<LlmOptions, 'baseUrl' | 'apiKey' | 'model' | 'temperature' | 'maxTokens'>): Promise<string>;
|
|
43
|
+
/**
|
|
44
|
+
* Phase C streaming (IMP-530): OpenAI-compatible SSE `chat/completions`
|
|
45
|
+
* (stream: true). Calls `onToken` with each content delta as it arrives;
|
|
46
|
+
* resolves with the full trimmed reply. Works with any OpenAI-compatible
|
|
47
|
+
* provider (Gemini, DeepSeek, OpenAI, Groq, OpenRouter, Mistral).
|
|
48
|
+
*/
|
|
49
|
+
export declare function completeStream(prompt: string, opts: Pick<LlmOptions, 'baseUrl' | 'apiKey' | 'model' | 'temperature' | 'maxTokens'>, onToken: (delta: string) => void): Promise<string>;
|
|
50
|
+
export {};
|