teamshare-bridge 0.11.2 → 0.14.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/dist/bridge/daemon.js +91 -18
- package/dist/bridge/daemon.js.map +1 -1
- package/dist/bridge/index.js +38 -0
- package/dist/bridge/index.js.map +1 -1
- package/dist/bridge/service.d.ts +11 -0
- package/dist/bridge/service.js +137 -7
- package/dist/bridge/service.js.map +1 -1
- package/dist/bridge/spawn.d.ts +3 -1
- package/dist/bridge/spawn.js +6 -2
- package/dist/bridge/spawn.js.map +1 -1
- package/dist/cli/commands/build.js +1 -1
- package/dist/cli/commands/build.js.map +1 -1
- package/dist/cli/commands/chat.js +2 -1
- package/dist/cli/commands/chat.js.map +1 -1
- package/dist/cli/commands/doc.js +5 -1
- package/dist/cli/commands/doc.js.map +1 -1
- package/dist/cli/commands/harness.js +5 -9
- package/dist/cli/commands/harness.js.map +1 -1
- package/dist/cli/commands/link.js +1 -1
- package/dist/cli/commands/link.js.map +1 -1
- package/dist/cli/commands/run.js +1 -0
- package/dist/cli/commands/run.js.map +1 -1
- package/dist/cli/commands/worker.js +1 -0
- package/dist/cli/commands/worker.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/utils.d.ts +5 -0
- package/dist/cli/utils.js +19 -1
- package/dist/cli/utils.js.map +1 -1
- package/dist/lib/agy-pty.js +20 -7
- package/dist/lib/agy-pty.js.map +1 -1
- package/dist/lib/api.d.ts +1 -0
- package/dist/lib/api.js.map +1 -1
- package/dist/lib/chat-reply.d.ts +4 -0
- package/dist/lib/chat-reply.js +71 -12
- package/dist/lib/chat-reply.js.map +1 -1
- package/dist/lib/doc-reply.d.ts +8 -0
- package/dist/lib/doc-reply.js +104 -16
- package/dist/lib/doc-reply.js.map +1 -1
- package/dist/lib/git-auto.d.ts +6 -9
- package/dist/lib/git-auto.js +9 -23
- package/dist/lib/git-auto.js.map +1 -1
- package/dist/lib/git-pipeline.js +6 -23
- package/dist/lib/git-pipeline.js.map +1 -1
- package/dist/lib/harness-adapter.d.ts +5 -1
- package/dist/lib/harness-adapter.js +360 -35
- package/dist/lib/harness-adapter.js.map +1 -1
- package/dist/lib/harness-models.d.ts +17 -0
- package/dist/lib/harness-models.js +146 -0
- package/dist/lib/harness-models.js.map +1 -0
- package/dist/lib/harness-output.d.ts +19 -0
- package/dist/lib/harness-output.js +114 -0
- package/dist/lib/harness-output.js.map +1 -0
- package/dist/lib/harness.d.ts +13 -2
- package/dist/lib/harness.js +103 -19
- package/dist/lib/harness.js.map +1 -1
- package/dist/lib/llm.d.ts +11 -0
- package/dist/lib/llm.js +34 -4
- package/dist/lib/llm.js.map +1 -1
- package/dist/lib/opencode-model-seed.d.ts +7 -0
- package/dist/lib/opencode-model-seed.js +97 -0
- package/dist/lib/opencode-model-seed.js.map +1 -0
- package/package.json +47 -50
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.discoverHarnessModels = discoverHarnessModels;
|
|
4
|
+
exports.pushHarnessCatalog = pushHarnessCatalog;
|
|
5
|
+
/**
|
|
6
|
+
* Harness model discovery (IMP-9xx): asks each installed CLI for its native
|
|
7
|
+
* model list and pushes it to the TeamShare catalog so the web picker stays
|
|
8
|
+
* current as providers ship models. Discovery never gates a session - a
|
|
9
|
+
* failed push only means the UI falls back to free text.
|
|
10
|
+
*
|
|
11
|
+
* All three harnesses (opencode, antigravity, codex) are attempted on
|
|
12
|
+
* daemon boot and via `teamshare-bridge models sync`. Each returns null
|
|
13
|
+
* gracefully when its CLI is absent, uninstalled, or broken.
|
|
14
|
+
*/
|
|
15
|
+
const node_child_process_1 = require("node:child_process");
|
|
16
|
+
const harness_1 = require("./harness");
|
|
17
|
+
/** Runs `<bin> [shim-args] <args>` sync, returns combined stdout+stderr. */
|
|
18
|
+
function runResolved(bin, args, timeoutMs = 20_000) {
|
|
19
|
+
const res = (0, node_child_process_1.spawnSync)(bin.file, [...(bin.args ?? []), ...args], {
|
|
20
|
+
encoding: 'utf8',
|
|
21
|
+
timeout: timeoutMs,
|
|
22
|
+
maxBuffer: 4 * 1024 * 1024,
|
|
23
|
+
});
|
|
24
|
+
return `${res.stdout ?? ''}${res.stderr ?? ''}`;
|
|
25
|
+
}
|
|
26
|
+
/** `opencode models` → plain text, one `provider/model` id per line. */
|
|
27
|
+
function fromOpencode() {
|
|
28
|
+
const bin = (0, harness_1.resolveBin)('opencode');
|
|
29
|
+
if (!bin)
|
|
30
|
+
return null;
|
|
31
|
+
const out = runResolved(bin, ['models']);
|
|
32
|
+
const models = [];
|
|
33
|
+
for (const line of out.split(/\r?\n/)) {
|
|
34
|
+
const id = line.trim();
|
|
35
|
+
if (!id)
|
|
36
|
+
continue;
|
|
37
|
+
if (/^(op|usage|available|the |model)/i.test(id))
|
|
38
|
+
continue;
|
|
39
|
+
if (!/^[a-z][a-z0-9_./-]+$/i.test(id))
|
|
40
|
+
continue;
|
|
41
|
+
models.push({ modelId: id, label: id.replace(/^(opencode-go|opencode)\//, '') });
|
|
42
|
+
}
|
|
43
|
+
return models.length ? { source: 'discovered', models } : null;
|
|
44
|
+
}
|
|
45
|
+
/** `cursor agent models` → plain text, one model slug per line. */
|
|
46
|
+
function fromCursor() {
|
|
47
|
+
const bin = (0, harness_1.resolveBin)('cursor');
|
|
48
|
+
if (!bin)
|
|
49
|
+
return null;
|
|
50
|
+
const out = runResolved(bin, ['agent', 'models']);
|
|
51
|
+
const models = [];
|
|
52
|
+
for (const line of out.split(/\r?\n/)) {
|
|
53
|
+
const id = line.trim();
|
|
54
|
+
if (!id)
|
|
55
|
+
continue;
|
|
56
|
+
if (/^(model|available|slug|name|cursor)/i.test(id))
|
|
57
|
+
continue;
|
|
58
|
+
if (!/^[a-z][a-z0-9_./\-]+$/i.test(id))
|
|
59
|
+
continue;
|
|
60
|
+
models.push({ modelId: id, label: id });
|
|
61
|
+
}
|
|
62
|
+
return models.length ? { source: 'discovered', models } : null;
|
|
63
|
+
}
|
|
64
|
+
/** `agy models` → TSV rows of `slug<TAB>Display Label`. */
|
|
65
|
+
function fromAgy() {
|
|
66
|
+
const bin = (0, harness_1.resolveBin)('agy');
|
|
67
|
+
if (!bin)
|
|
68
|
+
return null;
|
|
69
|
+
const out = runResolved(bin, ['models']);
|
|
70
|
+
const models = [];
|
|
71
|
+
for (const line of out.split(/\r?\n/)) {
|
|
72
|
+
const trimmed = line.trim();
|
|
73
|
+
if (!trimmed || /fetching|available models/i.test(trimmed))
|
|
74
|
+
continue;
|
|
75
|
+
const [id, ...rest] = trimmed.split(/\t|\s{2,}/);
|
|
76
|
+
if (!id || !rest.length)
|
|
77
|
+
continue;
|
|
78
|
+
if (!/^[\w.-]+$/.test(id))
|
|
79
|
+
continue;
|
|
80
|
+
models.push({ modelId: id, label: rest.join(' ').trim() });
|
|
81
|
+
}
|
|
82
|
+
return models.length ? { source: 'discovered', models } : null;
|
|
83
|
+
}
|
|
84
|
+
/** `codex debug models --bundled` → JSON { models: [{slug, display_name}] }. */
|
|
85
|
+
function fromCodex() {
|
|
86
|
+
const bin = (0, harness_1.resolveBin)('codex');
|
|
87
|
+
if (!bin)
|
|
88
|
+
return null;
|
|
89
|
+
const out = runResolved(bin, ['debug', 'models', '--bundled']);
|
|
90
|
+
const jsonStart = out.indexOf('{');
|
|
91
|
+
if (jsonStart === -1)
|
|
92
|
+
return null;
|
|
93
|
+
try {
|
|
94
|
+
const parsed = JSON.parse(out.slice(jsonStart));
|
|
95
|
+
const list = Array.isArray(parsed.models) ? parsed.models : [];
|
|
96
|
+
const models = list
|
|
97
|
+
.filter((m) => typeof m.slug === 'string')
|
|
98
|
+
.map((m) => ({
|
|
99
|
+
modelId: m.slug,
|
|
100
|
+
label: typeof m.display_name === 'string' ? m.display_name : undefined,
|
|
101
|
+
meta: Array.isArray(m.reasoning_efforts) && m.reasoning_efforts.length
|
|
102
|
+
? { efforts: m.reasoning_efforts }
|
|
103
|
+
: undefined,
|
|
104
|
+
}));
|
|
105
|
+
return models.length ? { source: 'discovered', models } : null;
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Native discovery per harness — attempts the CLI, returns null on failure
|
|
113
|
+
* (never throws). Callers treat null as "no models available" and skip
|
|
114
|
+
* the push silently so a broken/absent CLI never blocks sessions.
|
|
115
|
+
*/
|
|
116
|
+
function discoverHarnessModels(harness) {
|
|
117
|
+
try {
|
|
118
|
+
if (harness === 'opencode')
|
|
119
|
+
return fromOpencode();
|
|
120
|
+
if (harness === 'antigravity')
|
|
121
|
+
return fromAgy();
|
|
122
|
+
if (harness === 'codex')
|
|
123
|
+
return fromCodex();
|
|
124
|
+
if (harness === 'cursor')
|
|
125
|
+
return fromCursor();
|
|
126
|
+
}
|
|
127
|
+
catch {
|
|
128
|
+
return null;
|
|
129
|
+
}
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
/** Pushes one harness batch to the TeamShare catalog (agent-key auth). */
|
|
133
|
+
async function pushHarnessCatalog(baseUrl, apiKey, harness, batch) {
|
|
134
|
+
const base = baseUrl.replace(/\/+$/, '');
|
|
135
|
+
const res = await fetch(`${base}/model-catalog/discover`, {
|
|
136
|
+
method: 'POST',
|
|
137
|
+
headers: { 'Content-Type': 'application/json', 'X-Api-Key': apiKey },
|
|
138
|
+
body: JSON.stringify({ harness, source: batch.source, models: batch.models }),
|
|
139
|
+
});
|
|
140
|
+
if (!res.ok) {
|
|
141
|
+
throw new Error(`catalog push failed (${res.status}): ${await res.text().catch(() => '')}`.slice(0, 200));
|
|
142
|
+
}
|
|
143
|
+
const body = (await res.json());
|
|
144
|
+
return body.data?.stored ?? batch.models.length;
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=harness-models.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-models.js","sourceRoot":"","sources":["../../src/lib/harness-models.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured-output parsing for harnesses that emit JSON / NDJSON
|
|
3
|
+
* (antigravity `--output-format json`, claude `stream-json`, gemini json, ...).
|
|
4
|
+
*
|
|
5
|
+
* The reply loops call parseHarnessOutput() on the raw stdout and get back the
|
|
6
|
+
* plain-text reply. Defensive by design: when nothing structured is found the
|
|
7
|
+
* raw text is returned unchanged, so plain-text harnesses (opencode, codex
|
|
8
|
+
* exec) are never touched.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* Best-effort extraction of the plain-text reply from structured stdout.
|
|
12
|
+
* Returns null when nothing structured was found (caller keeps raw text).
|
|
13
|
+
*/
|
|
14
|
+
export declare function tryExtractStructuredReply(raw: string): string | null;
|
|
15
|
+
/**
|
|
16
|
+
* Extract the plain-text reply for a harness. `structured` mirrors the
|
|
17
|
+
* adapter's `structuredOutput` flag; plain-text harnesses pass through.
|
|
18
|
+
*/
|
|
19
|
+
export declare function parseHarnessOutput(structured: boolean, raw: string): string;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Structured-output parsing for harnesses that emit JSON / NDJSON
|
|
4
|
+
* (antigravity `--output-format json`, claude `stream-json`, gemini json, ...).
|
|
5
|
+
*
|
|
6
|
+
* The reply loops call parseHarnessOutput() on the raw stdout and get back the
|
|
7
|
+
* plain-text reply. Defensive by design: when nothing structured is found the
|
|
8
|
+
* raw text is returned unchanged, so plain-text harnesses (opencode, codex
|
|
9
|
+
* exec) are never touched.
|
|
10
|
+
*/
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.tryExtractStructuredReply = tryExtractStructuredReply;
|
|
13
|
+
exports.parseHarnessOutput = parseHarnessOutput;
|
|
14
|
+
function isObject(v) {
|
|
15
|
+
return typeof v === 'object' && v !== null;
|
|
16
|
+
}
|
|
17
|
+
function asString(v) {
|
|
18
|
+
return typeof v === 'string' ? v : null;
|
|
19
|
+
}
|
|
20
|
+
/** Extract text from a single claude `stream-json` event line. */
|
|
21
|
+
function claudeEventText(obj) {
|
|
22
|
+
if (obj.type === 'content_block_delta') {
|
|
23
|
+
const delta = obj.delta;
|
|
24
|
+
if (isObject(delta) && delta.type === 'text_delta')
|
|
25
|
+
return asString(delta.text);
|
|
26
|
+
}
|
|
27
|
+
if (obj.type === 'assistant') {
|
|
28
|
+
const content = obj.content;
|
|
29
|
+
if (Array.isArray(content)) {
|
|
30
|
+
const parts = [];
|
|
31
|
+
for (const c of content) {
|
|
32
|
+
if (isObject(c) && asString(c.text))
|
|
33
|
+
parts.push(c.text);
|
|
34
|
+
}
|
|
35
|
+
if (parts.length)
|
|
36
|
+
return parts.join('');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
/** Extract a reply from a single parsed JSON object (agy json shape). */
|
|
42
|
+
function parseObjectReply(obj) {
|
|
43
|
+
if (asString(obj.response))
|
|
44
|
+
return obj.response;
|
|
45
|
+
if (asString(obj.text))
|
|
46
|
+
return obj.text;
|
|
47
|
+
if (asString(obj.message))
|
|
48
|
+
return obj.message;
|
|
49
|
+
if (asString(obj.content))
|
|
50
|
+
return obj.content;
|
|
51
|
+
if (isObject(obj.message) && Array.isArray(obj.message.content)) {
|
|
52
|
+
const parts = [];
|
|
53
|
+
for (const item of obj.message.content) {
|
|
54
|
+
if (isObject(item) && asString(item.text))
|
|
55
|
+
parts.push(item.text);
|
|
56
|
+
}
|
|
57
|
+
if (parts.length)
|
|
58
|
+
return parts.join('');
|
|
59
|
+
}
|
|
60
|
+
return null;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Best-effort extraction of the plain-text reply from structured stdout.
|
|
64
|
+
* Returns null when nothing structured was found (caller keeps raw text).
|
|
65
|
+
*/
|
|
66
|
+
function tryExtractStructuredReply(raw) {
|
|
67
|
+
const trimmed = raw.trim();
|
|
68
|
+
if (!trimmed)
|
|
69
|
+
return null;
|
|
70
|
+
// NDJSON stream (claude stream-json) - one JSON object per line.
|
|
71
|
+
const lines = trimmed.split(/\r?\n/);
|
|
72
|
+
if (lines.length > 1) {
|
|
73
|
+
const texts = [];
|
|
74
|
+
let sawEvent = false;
|
|
75
|
+
for (const line of lines) {
|
|
76
|
+
const t = line.trim();
|
|
77
|
+
if (!t || !t.startsWith('{'))
|
|
78
|
+
continue;
|
|
79
|
+
try {
|
|
80
|
+
const obj = JSON.parse(t);
|
|
81
|
+
sawEvent = true;
|
|
82
|
+
const text = claudeEventText(obj) ?? parseObjectReply(obj);
|
|
83
|
+
if (text)
|
|
84
|
+
texts.push(text);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
/* not a JSON line - skip */
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (sawEvent && texts.length)
|
|
91
|
+
return texts.join('');
|
|
92
|
+
}
|
|
93
|
+
// Single JSON object.
|
|
94
|
+
try {
|
|
95
|
+
const obj = JSON.parse(trimmed);
|
|
96
|
+
return parseObjectReply(obj);
|
|
97
|
+
}
|
|
98
|
+
catch {
|
|
99
|
+
/* not JSON */
|
|
100
|
+
}
|
|
101
|
+
return null;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Extract the plain-text reply for a harness. `structured` mirrors the
|
|
105
|
+
* adapter's `structuredOutput` flag; plain-text harnesses pass through.
|
|
106
|
+
*/
|
|
107
|
+
function parseHarnessOutput(structured, raw) {
|
|
108
|
+
const trimmed = raw.trim();
|
|
109
|
+
if (!structured)
|
|
110
|
+
return trimmed;
|
|
111
|
+
const extracted = tryExtractStructuredReply(trimmed);
|
|
112
|
+
return extracted !== null ? extracted : trimmed;
|
|
113
|
+
}
|
|
114
|
+
//# sourceMappingURL=harness-output.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"harness-output.js","sourceRoot":"","sources":["../../src/lib/harness-output.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/harness.d.ts
CHANGED
|
@@ -2,6 +2,15 @@ export interface HarnessRunOptions {
|
|
|
2
2
|
maxBuffer?: number;
|
|
3
3
|
/** Hard kill ceiling for TTY-routed runs (agy); minutes. */
|
|
4
4
|
timeoutMin?: number;
|
|
5
|
+
/** Working directory the harness runs in (must match the MCP config cwd). */
|
|
6
|
+
cwd?: string;
|
|
7
|
+
/** Extra env for the child (TTY path only; piped path merges via adapter). */
|
|
8
|
+
env?: NodeJS.ProcessEnv;
|
|
9
|
+
/**
|
|
10
|
+
* Route through a pseudo-terminal when the harness gates stdout on isatty
|
|
11
|
+
* (mirrors the adapter's `needsTty`). When false, always piped.
|
|
12
|
+
*/
|
|
13
|
+
needsTty?: boolean;
|
|
5
14
|
/**
|
|
6
15
|
* Agent API key injected into a per-session opencode config so the
|
|
7
16
|
* teamshare MCP server authenticates as THIS agent (never the global
|
|
@@ -12,6 +21,8 @@ export interface HarnessRunOptions {
|
|
|
12
21
|
opencodeMcpUrl?: string;
|
|
13
22
|
/** Session mode header for the MCP override ('run' | 'build' | 'chat' | 'doc'). */
|
|
14
23
|
opencodeSessionMode?: string;
|
|
24
|
+
/** TTY runs only: per-line transcript tap (tee agy output into session logs). */
|
|
25
|
+
onLine?: (line: string) => void;
|
|
15
26
|
}
|
|
16
27
|
export interface ResolvedBin {
|
|
17
28
|
file: string;
|
|
@@ -41,8 +52,8 @@ export declare function writeOpencodeMcpConfig(agentKey: string, apiBaseUrl: str
|
|
|
41
52
|
export declare function runHarness(cmd: string, args: string[], opts?: HarnessRunOptions): string;
|
|
42
53
|
export declare function hasBin(bin: string): boolean;
|
|
43
54
|
/**
|
|
44
|
-
* runHarness variant for TTY-gated harnesses (
|
|
45
|
-
* the run through a pseudo-terminal so its isatty-gated stdout actually
|
|
55
|
+
* runHarness variant for TTY-gated harnesses (adapter `needsTty: true`):
|
|
56
|
+
* routes the run through a pseudo-terminal so its isatty-gated stdout actually
|
|
46
57
|
* emits, and returns the cleaned transcript as the reply text. Every other
|
|
47
58
|
* binary keeps the plain piped path. Chat/doc callers should prefer this.
|
|
48
59
|
*/
|
package/dist/lib/harness.js
CHANGED
|
@@ -32,6 +32,32 @@ function whereShim(bin) {
|
|
|
32
32
|
.find((s) => /\.(cmd|bat|ps1)$/i.test(s));
|
|
33
33
|
return line ?? null;
|
|
34
34
|
}
|
|
35
|
+
/** All absolute PATH hits for a command (where.exe), trimmed + non-empty. */
|
|
36
|
+
function whereAll(bin) {
|
|
37
|
+
if (process.platform !== 'win32')
|
|
38
|
+
return [];
|
|
39
|
+
const res = (0, node_child_process_1.spawnSync)('where', [bin], { encoding: 'utf8' });
|
|
40
|
+
if (res.status !== 0)
|
|
41
|
+
return [];
|
|
42
|
+
return (res.stdout ?? '')
|
|
43
|
+
.split(/\r?\n/)
|
|
44
|
+
.map((s) => s.trim())
|
|
45
|
+
.filter(Boolean);
|
|
46
|
+
}
|
|
47
|
+
/** Extracts the real executable target from an npm .cmd/.bat/.ps1 shim. */
|
|
48
|
+
function fromShim(shimPath) {
|
|
49
|
+
const text = (0, node_fs_1.readFileSync)(shimPath, 'utf8');
|
|
50
|
+
const match = text.match(/"([^"]+\.(?:exe|js))"/i);
|
|
51
|
+
if (!match)
|
|
52
|
+
return null;
|
|
53
|
+
const expanded = expand(match[1], (0, node_path_1.dirname)(shimPath));
|
|
54
|
+
const file = (0, node_path_1.isAbsolute)(expanded) ? expanded : (0, node_path_1.join)((0, node_path_1.dirname)(shimPath), expanded);
|
|
55
|
+
if (!(0, node_fs_1.existsSync)(file))
|
|
56
|
+
return null;
|
|
57
|
+
if (/\.exe$/i.test(file))
|
|
58
|
+
return { file };
|
|
59
|
+
return { file: process.execPath, args: [file] };
|
|
60
|
+
}
|
|
35
61
|
/** Expands shim placeholders (%dp0%, %~dp0%, %basedir%, $basedir, $PSScriptRoot). */
|
|
36
62
|
function expand(target, shimDir) {
|
|
37
63
|
return target
|
|
@@ -39,6 +65,30 @@ function expand(target, shimDir) {
|
|
|
39
65
|
.replace(/%\w+%/g, '')
|
|
40
66
|
.trim();
|
|
41
67
|
}
|
|
68
|
+
/**
|
|
69
|
+
* Well-known install dirs per binary (IMP-9xx): CLI installers often update
|
|
70
|
+
* the registry PATH for FUTURE shells only - a long-lived daemon keeps its
|
|
71
|
+
* spawn-time env forever, so `where` misses freshly installed tools. These
|
|
72
|
+
* fallbacks let resolution still succeed without a daemon restart.
|
|
73
|
+
*/
|
|
74
|
+
const KNOWN_INSTALL_DIRS = {
|
|
75
|
+
codex: ['%LOCALAPPDATA%\\Programs\\OpenAI\\Codex\\bin'],
|
|
76
|
+
agy: ['%LOCALAPPDATA%\\agy\\bin'],
|
|
77
|
+
};
|
|
78
|
+
function fromKnownDirs(bin) {
|
|
79
|
+
const dirs = KNOWN_INSTALL_DIRS[bin];
|
|
80
|
+
if (!dirs)
|
|
81
|
+
return null;
|
|
82
|
+
for (const raw of dirs) {
|
|
83
|
+
const dir = raw.replace(/%([^%]+)%/g, (_, k) => process.env[k] ?? '');
|
|
84
|
+
for (const name of [`${bin}.exe`, bin]) {
|
|
85
|
+
const file = (0, node_path_1.join)(dir, name);
|
|
86
|
+
if ((0, node_fs_1.existsSync)(file))
|
|
87
|
+
return { file };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
42
92
|
/**
|
|
43
93
|
* Resolves a PATH command to something Node can spawn without a shell.
|
|
44
94
|
* Windows npm shims (opencode.cmd / opencode.ps1, claude.cmd) cannot be
|
|
@@ -47,22 +97,33 @@ function expand(target, shimDir) {
|
|
|
47
97
|
* run via node) is extracted from the shim file instead.
|
|
48
98
|
*/
|
|
49
99
|
function resolveBin(bin) {
|
|
50
|
-
if (tryExec(bin, ['--version']))
|
|
100
|
+
if (tryExec(bin, ['--version'])) {
|
|
101
|
+
// IMP-9xx: bare names break node-pty - ConPTY cannot PATH/PATHEXT
|
|
102
|
+
// resolve, it fails with the opaque "File not found: ". When an
|
|
103
|
+
// absolute executable exists on PATH, prefer it so TTY runs work.
|
|
104
|
+
if ((0, node_path_1.isAbsolute)(bin))
|
|
105
|
+
return { file: bin };
|
|
106
|
+
for (const line of whereAll(bin)) {
|
|
107
|
+
if (/\.(exe|js)$/i.test(line) && (0, node_fs_1.existsSync)(line)) {
|
|
108
|
+
return /\.exe$/i.test(line) ? { file: line } : { file: process.execPath, args: [line] };
|
|
109
|
+
}
|
|
110
|
+
if (/\.(cmd|bat|ps1)$/i.test(line)) {
|
|
111
|
+
const fromShimResult = fromShim(line);
|
|
112
|
+
if (fromShimResult)
|
|
113
|
+
return fromShimResult;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
51
116
|
return { file: bin };
|
|
117
|
+
}
|
|
52
118
|
const shim = whereShim(bin);
|
|
53
|
-
if (
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
if (!(0, node_fs_1.existsSync)(file))
|
|
62
|
-
return null;
|
|
63
|
-
if (/\.exe$/i.test(file))
|
|
64
|
-
return { file };
|
|
65
|
-
return { file: process.execPath, args: [file] };
|
|
119
|
+
if (shim) {
|
|
120
|
+
const fromShimResult = fromShim(shim);
|
|
121
|
+
if (fromShimResult)
|
|
122
|
+
return fromShimResult;
|
|
123
|
+
}
|
|
124
|
+
// Fresh install the daemon's PATH can't see yet - try known dirs before
|
|
125
|
+
// giving up so users don't need to restart the daemon after installs.
|
|
126
|
+
return fromKnownDirs(bin);
|
|
66
127
|
}
|
|
67
128
|
/**
|
|
68
129
|
* Writes a throwaway opencode config that overrides the teamshare MCP
|
|
@@ -124,6 +185,7 @@ function runHarness(cmd, args, opts = {}) {
|
|
|
124
185
|
const out = (0, node_child_process_1.execFileSync)(bin.file, [...(bin.args ?? []), ...args], {
|
|
125
186
|
encoding: 'utf8',
|
|
126
187
|
maxBuffer: opts.maxBuffer ?? 2 * 1024 * 1024,
|
|
188
|
+
cwd: opts.cwd,
|
|
127
189
|
env: mcpEnv ? { ...process.env, ...mcpEnv.env } : undefined,
|
|
128
190
|
});
|
|
129
191
|
return out.trim();
|
|
@@ -142,28 +204,50 @@ function runHarness(cmd, args, opts = {}) {
|
|
|
142
204
|
function hasBin(bin) {
|
|
143
205
|
return resolveBin(bin) !== null;
|
|
144
206
|
}
|
|
207
|
+
let ptyWarned = false;
|
|
145
208
|
/**
|
|
146
|
-
* runHarness variant for TTY-gated harnesses (
|
|
147
|
-
* the run through a pseudo-terminal so its isatty-gated stdout actually
|
|
209
|
+
* runHarness variant for TTY-gated harnesses (adapter `needsTty: true`):
|
|
210
|
+
* routes the run through a pseudo-terminal so its isatty-gated stdout actually
|
|
148
211
|
* emits, and returns the cleaned transcript as the reply text. Every other
|
|
149
212
|
* binary keeps the plain piped path. Chat/doc callers should prefer this.
|
|
150
213
|
*/
|
|
151
214
|
async function runHarnessTtyAware(cmd, args, opts = {}) {
|
|
152
|
-
if (
|
|
215
|
+
if (!opts.needsTty)
|
|
216
|
+
return runHarness(cmd, args, opts);
|
|
217
|
+
if (!(0, agy_pty_1.ptyAvailable)()) {
|
|
218
|
+
// IMP-9xx: npm 11's allow-scripts blocks node-pty's install scripts by
|
|
219
|
+
// default, so its native build may be missing. This used to surface as a
|
|
220
|
+
// confusing silent empty reply - explain the one-time fix instead.
|
|
221
|
+
if (!ptyWarned) {
|
|
222
|
+
ptyWarned = true;
|
|
223
|
+
console.warn('[harness] TTY-gated harness requested but node-pty is unavailable ' +
|
|
224
|
+
'(npm blocked its install scripts). Piped fallback in use; if the ' +
|
|
225
|
+
'harness needs a TTY, run: npm i -g --allow-scripts=node-pty teamshare-bridge ' +
|
|
226
|
+
'(or: npm config set allow-scripts=node-pty --location=user)');
|
|
227
|
+
}
|
|
153
228
|
return runHarness(cmd, args, opts);
|
|
229
|
+
}
|
|
154
230
|
const bin = resolveBin(cmd);
|
|
155
231
|
if (!bin)
|
|
156
232
|
throw new Error(`No harness found (install ${cmd})`);
|
|
157
233
|
const res = await (0, agy_pty_1.runAgyPty)({
|
|
158
234
|
file: bin.file,
|
|
159
235
|
args: [...(bin.args ?? []), ...args],
|
|
236
|
+
cwd: opts.cwd,
|
|
237
|
+
env: opts.env,
|
|
160
238
|
timeoutMin: opts.timeoutMin ?? 10,
|
|
239
|
+
// IMP-9xx: tee the transcript into the session log - TTY runs used to
|
|
240
|
+
// leave 0-byte capture files, making failures undiagnosable.
|
|
241
|
+
onLine: opts.onLine,
|
|
161
242
|
});
|
|
162
243
|
const text = res.output.trim();
|
|
163
244
|
if (res.code === 124)
|
|
164
245
|
throw new Error('agy timed out (session cap)');
|
|
165
|
-
if (res.code !== 0
|
|
166
|
-
|
|
246
|
+
if (res.code !== 0) {
|
|
247
|
+
// IMP-9xx: a non-zero exit is NEVER a successful reply, even when agy
|
|
248
|
+
// printed something (it prints errors on stdout too).
|
|
249
|
+
throw new Error(`agy exited with code ${res.code}: ${text ? text.slice(-400) : '(no output)'}`);
|
|
250
|
+
}
|
|
167
251
|
return text;
|
|
168
252
|
}
|
|
169
253
|
//# sourceMappingURL=harness.js.map
|
package/dist/lib/harness.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/lib/harness.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/lib/harness.ts"],"names":[],"mappings":"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"}
|
package/dist/lib/llm.d.ts
CHANGED
|
@@ -63,6 +63,17 @@ export declare function runLlmSession(api: TeamshareApi, taskId: string, brief:
|
|
|
63
63
|
* Returns the final reply text.
|
|
64
64
|
*/
|
|
65
65
|
export declare function runProjectSession(api: TeamshareApi, projectId: string, prompt: string, opts: LlmOptions, projectName?: string): Promise<string>;
|
|
66
|
+
/**
|
|
67
|
+
* Document-assistant self-mode session (IMP-9xx): identical tool loop to
|
|
68
|
+
* {@link runProjectSession} but framed around ONE document. Lets a doc
|
|
69
|
+
* comment mention trigger real actions (create_task, add_comment, search…)
|
|
70
|
+
* even without an installed harness - parity with what the harness path
|
|
71
|
+
* gets through the per-session MCP config.
|
|
72
|
+
*/
|
|
73
|
+
export declare function runDocumentSession(api: TeamshareApi, ctx: {
|
|
74
|
+
projectId: string;
|
|
75
|
+
documentId: string;
|
|
76
|
+
}, prompt: string, opts: LlmOptions): Promise<string>;
|
|
66
77
|
/**
|
|
67
78
|
* Single-shot chat completion (no tools) - used by the chat-reply loop to
|
|
68
79
|
* draft a reply to a mention and by the run-report writer. Same env
|
package/dist/lib/llm.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.QUESTION_MARKER = exports.DEFAULT_LLM_MODEL = exports.DEFAULT_LLM_BASE_U
|
|
|
4
4
|
exports.buildTools = buildTools;
|
|
5
5
|
exports.runLlmSession = runLlmSession;
|
|
6
6
|
exports.runProjectSession = runProjectSession;
|
|
7
|
+
exports.runDocumentSession = runDocumentSession;
|
|
7
8
|
exports.complete = complete;
|
|
8
9
|
exports.completeStream = completeStream;
|
|
9
10
|
/**
|
|
@@ -587,10 +588,6 @@ async function runLlmSession(api, taskId, brief, opts, projectId) {
|
|
|
587
588
|
* Returns the final reply text.
|
|
588
589
|
*/
|
|
589
590
|
async function runProjectSession(api, projectId, prompt, opts, projectName) {
|
|
590
|
-
const tools = buildTools(api, {
|
|
591
|
-
defaultProjectId: projectId,
|
|
592
|
-
agentUserId: opts.agentUserId,
|
|
593
|
-
});
|
|
594
591
|
const projectLabel = projectName ? `"${projectName}" (${projectId})` : projectId;
|
|
595
592
|
const systemBase = `You are ${opts.agentName}, a TeamShare project assistant for project ${projectLabel}. ` +
|
|
596
593
|
(opts.systemPrompt ? `${opts.systemPrompt}\n\n` : '') +
|
|
@@ -611,6 +608,39 @@ async function runProjectSession(api, projectId, prompt, opts, projectName) {
|
|
|
611
608
|
'Never mention local folder names or repo names (e.g. teamshare-bridge, frontend, teamshare-backend). ' +
|
|
612
609
|
'If the person asks about code work, mention tasks or documents in TeamShare, not local folders. ' +
|
|
613
610
|
'Reply concisely in plain text; keep it under 4000 characters.';
|
|
611
|
+
return runToolLoop(api, projectId, systemBase, prompt, opts);
|
|
612
|
+
}
|
|
613
|
+
/**
|
|
614
|
+
* Document-assistant self-mode session (IMP-9xx): identical tool loop to
|
|
615
|
+
* {@link runProjectSession} but framed around ONE document. Lets a doc
|
|
616
|
+
* comment mention trigger real actions (create_task, add_comment, search…)
|
|
617
|
+
* even without an installed harness - parity with what the harness path
|
|
618
|
+
* gets through the per-session MCP config.
|
|
619
|
+
*/
|
|
620
|
+
async function runDocumentSession(api, ctx, prompt, opts) {
|
|
621
|
+
const systemBase = `You are ${opts.agentName}, a TeamShare document assistant replying inside the comment thread of document ${ctx.documentId}. ` +
|
|
622
|
+
(opts.systemPrompt ? `${opts.systemPrompt}\n\n` : '') +
|
|
623
|
+
'The user prompt already contains the document content and thread - answer from it directly. ' +
|
|
624
|
+
`create_task, create_document and add_comment are PINNED to this document's project (${ctx.projectId}) - ` +
|
|
625
|
+
'any projectId you might pass is ignored in favor of it. ' +
|
|
626
|
+
'Only ever claim you created/updated something if a tool actually returned it - if a tool errors, say so honestly. ' +
|
|
627
|
+
(opts.agentUserId
|
|
628
|
+
? `Your TeamShare user id is ${opts.agentUserId}.\n`
|
|
629
|
+
: '') +
|
|
630
|
+
'You have tools: get_project, list_tasks, get_task, create_task, update_task, ' +
|
|
631
|
+
'add_comment, list_documents, read_document, create_document, update_document_note, search, ' +
|
|
632
|
+
'ask_human, list_subtasks, create_subtask, update_subtask, create_checklist_item, update_checklist_item, delete_checklist_item. ' +
|
|
633
|
+
'If the comment asks you to do something actionable, use the appropriate tool instead of only describing it. ' +
|
|
634
|
+
'Be direct and structured: open with the answer itself, then short bullets where helpful. No filler, no hedging. ' +
|
|
635
|
+
'Keep the reply SHORT - under 150 words, plain text only; this is a document comment thread, not a report (hard cap 4000 characters).';
|
|
636
|
+
return runToolLoop(api, ctx.projectId, systemBase, prompt, opts);
|
|
637
|
+
}
|
|
638
|
+
/** Shared pinned-project tool loop behind both session flavors. */
|
|
639
|
+
async function runToolLoop(api, defaultProjectId, systemBase, prompt, opts) {
|
|
640
|
+
const tools = buildTools(api, {
|
|
641
|
+
defaultProjectId,
|
|
642
|
+
agentUserId: opts.agentUserId,
|
|
643
|
+
});
|
|
614
644
|
const messages = [
|
|
615
645
|
{ role: 'system', content: systemBase },
|
|
616
646
|
{ role: 'user', content: prompt },
|