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.
Files changed (63) hide show
  1. package/dist/bridge/daemon.js +91 -18
  2. package/dist/bridge/daemon.js.map +1 -1
  3. package/dist/bridge/index.js +38 -0
  4. package/dist/bridge/index.js.map +1 -1
  5. package/dist/bridge/service.d.ts +11 -0
  6. package/dist/bridge/service.js +137 -7
  7. package/dist/bridge/service.js.map +1 -1
  8. package/dist/bridge/spawn.d.ts +3 -1
  9. package/dist/bridge/spawn.js +6 -2
  10. package/dist/bridge/spawn.js.map +1 -1
  11. package/dist/cli/commands/build.js +1 -1
  12. package/dist/cli/commands/build.js.map +1 -1
  13. package/dist/cli/commands/chat.js +2 -1
  14. package/dist/cli/commands/chat.js.map +1 -1
  15. package/dist/cli/commands/doc.js +5 -1
  16. package/dist/cli/commands/doc.js.map +1 -1
  17. package/dist/cli/commands/harness.js +5 -9
  18. package/dist/cli/commands/harness.js.map +1 -1
  19. package/dist/cli/commands/link.js +1 -1
  20. package/dist/cli/commands/link.js.map +1 -1
  21. package/dist/cli/commands/run.js +1 -0
  22. package/dist/cli/commands/run.js.map +1 -1
  23. package/dist/cli/commands/worker.js +1 -0
  24. package/dist/cli/commands/worker.js.map +1 -1
  25. package/dist/cli/index.js +1 -1
  26. package/dist/cli/index.js.map +1 -1
  27. package/dist/cli/utils.d.ts +5 -0
  28. package/dist/cli/utils.js +19 -1
  29. package/dist/cli/utils.js.map +1 -1
  30. package/dist/lib/agy-pty.js +20 -7
  31. package/dist/lib/agy-pty.js.map +1 -1
  32. package/dist/lib/api.d.ts +1 -0
  33. package/dist/lib/api.js.map +1 -1
  34. package/dist/lib/chat-reply.d.ts +4 -0
  35. package/dist/lib/chat-reply.js +71 -12
  36. package/dist/lib/chat-reply.js.map +1 -1
  37. package/dist/lib/doc-reply.d.ts +8 -0
  38. package/dist/lib/doc-reply.js +104 -16
  39. package/dist/lib/doc-reply.js.map +1 -1
  40. package/dist/lib/git-auto.d.ts +6 -9
  41. package/dist/lib/git-auto.js +9 -23
  42. package/dist/lib/git-auto.js.map +1 -1
  43. package/dist/lib/git-pipeline.js +6 -23
  44. package/dist/lib/git-pipeline.js.map +1 -1
  45. package/dist/lib/harness-adapter.d.ts +5 -1
  46. package/dist/lib/harness-adapter.js +360 -35
  47. package/dist/lib/harness-adapter.js.map +1 -1
  48. package/dist/lib/harness-models.d.ts +17 -0
  49. package/dist/lib/harness-models.js +146 -0
  50. package/dist/lib/harness-models.js.map +1 -0
  51. package/dist/lib/harness-output.d.ts +19 -0
  52. package/dist/lib/harness-output.js +114 -0
  53. package/dist/lib/harness-output.js.map +1 -0
  54. package/dist/lib/harness.d.ts +13 -2
  55. package/dist/lib/harness.js +103 -19
  56. package/dist/lib/harness.js.map +1 -1
  57. package/dist/lib/llm.d.ts +11 -0
  58. package/dist/lib/llm.js +34 -4
  59. package/dist/lib/llm.js.map +1 -1
  60. package/dist/lib/opencode-model-seed.d.ts +7 -0
  61. package/dist/lib/opencode-model-seed.js +97 -0
  62. package/dist/lib/opencode-model-seed.js.map +1 -0
  63. 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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"}
@@ -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 (antigravity / `agy`): routes
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
  */
@@ -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 (!shim)
54
- return null;
55
- const text = (0, node_fs_1.readFileSync)(shim, 'utf8');
56
- const match = text.match(/"([^"]+\.(?:exe|js))"/i);
57
- if (!match)
58
- return null;
59
- const expanded = expand(match[1], (0, node_path_1.dirname)(shim));
60
- const file = (0, node_path_1.isAbsolute)(expanded) ? expanded : (0, node_path_1.join)((0, node_path_1.dirname)(shim), expanded);
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 (antigravity / `agy`): routes
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 (cmd !== 'agy' || !(0, agy_pty_1.ptyAvailable)())
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 && !text)
166
- throw new Error(`agy exited with code ${res.code}`);
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
@@ -1 +1 @@
1
- {"version":3,"file":"harness.js","sourceRoot":"","sources":["../../src/lib/harness.ts"],"names":[],"mappings":"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"}
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 },