@pruddiman/hem 0.0.1-beta-5671db0

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 (78) hide show
  1. package/LICENSE +21 -0
  2. package/dist/agents/arbiter-agent.d.ts +72 -0
  3. package/dist/agents/arbiter-agent.js +149 -0
  4. package/dist/agents/architecture-agent.d.ts +148 -0
  5. package/dist/agents/architecture-agent.js +459 -0
  6. package/dist/agents/base-agent.d.ts +44 -0
  7. package/dist/agents/base-agent.js +57 -0
  8. package/dist/agents/crossref-agent.d.ts +140 -0
  9. package/dist/agents/crossref-agent.js +560 -0
  10. package/dist/agents/crossref-arbiter-agent.d.ts +72 -0
  11. package/dist/agents/crossref-arbiter-agent.js +147 -0
  12. package/dist/agents/documentation-agent.d.ts +55 -0
  13. package/dist/agents/documentation-agent.js +159 -0
  14. package/dist/agents/exploration-agent.d.ts +58 -0
  15. package/dist/agents/exploration-agent.js +102 -0
  16. package/dist/agents/grouping-agent.d.ts +167 -0
  17. package/dist/agents/grouping-agent.js +557 -0
  18. package/dist/agents/index-agent.d.ts +86 -0
  19. package/dist/agents/index-agent.js +360 -0
  20. package/dist/agents/organization-agent.d.ts +144 -0
  21. package/dist/agents/organization-agent.js +607 -0
  22. package/dist/auth.d.ts +372 -0
  23. package/dist/auth.js +1072 -0
  24. package/dist/broadcast-mcp.d.ts +21 -0
  25. package/dist/broadcast-mcp.js +59 -0
  26. package/dist/changelog.d.ts +85 -0
  27. package/dist/changelog.js +223 -0
  28. package/dist/decision-queue.d.ts +173 -0
  29. package/dist/decision-queue.js +265 -0
  30. package/dist/diff-scope.d.ts +24 -0
  31. package/dist/diff-scope.js +28 -0
  32. package/dist/discovery.d.ts +54 -0
  33. package/dist/discovery.js +405 -0
  34. package/dist/grouping.d.ts +37 -0
  35. package/dist/grouping.js +343 -0
  36. package/dist/helpers/format.d.ts +5 -0
  37. package/dist/helpers/format.js +13 -0
  38. package/dist/helpers/index.d.ts +11 -0
  39. package/dist/helpers/index.js +11 -0
  40. package/dist/helpers/parsing.d.ts +52 -0
  41. package/dist/helpers/parsing.js +128 -0
  42. package/dist/helpers/paths.d.ts +41 -0
  43. package/dist/helpers/paths.js +67 -0
  44. package/dist/helpers/strings.d.ts +45 -0
  45. package/dist/helpers/strings.js +97 -0
  46. package/dist/index.d.ts +135 -0
  47. package/dist/index.js +1087 -0
  48. package/dist/merge-utils.d.ts +22 -0
  49. package/dist/merge-utils.js +34 -0
  50. package/dist/orchestrator.d.ts +194 -0
  51. package/dist/orchestrator.js +1169 -0
  52. package/dist/output.d.ts +106 -0
  53. package/dist/output.js +243 -0
  54. package/dist/progress.d.ts +228 -0
  55. package/dist/progress.js +644 -0
  56. package/dist/providers/copilot.d.ts +247 -0
  57. package/dist/providers/copilot.js +598 -0
  58. package/dist/providers/index.d.ts +15 -0
  59. package/dist/providers/index.js +12 -0
  60. package/dist/providers/opencode.d.ts +156 -0
  61. package/dist/providers/opencode.js +416 -0
  62. package/dist/providers/types.d.ts +156 -0
  63. package/dist/providers/types.js +16 -0
  64. package/dist/resources.d.ts +76 -0
  65. package/dist/resources.js +151 -0
  66. package/dist/search-index.d.ts +71 -0
  67. package/dist/search-index.js +187 -0
  68. package/dist/search-mcp.d.ts +25 -0
  69. package/dist/search-mcp.js +100 -0
  70. package/dist/server-utils.d.ts +56 -0
  71. package/dist/server-utils.js +135 -0
  72. package/dist/session.d.ts +227 -0
  73. package/dist/session.js +370 -0
  74. package/dist/types.d.ts +272 -0
  75. package/dist/types.js +5 -0
  76. package/dist/worktree.d.ts +82 -0
  77. package/dist/worktree.js +187 -0
  78. package/package.json +45 -0
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Standalone stdio-based MCP server exposing the Hem doc search index.
4
+ *
5
+ * Exposes two tools:
6
+ * - `search_docs({ query, limit? })` — FTS5 keyword search over indexed docs
7
+ * - `get_docs_for_source({ source_path })` — find docs covering a source file
8
+ *
9
+ * Receives the SQLite DB path as the first CLI argument:
10
+ * node dist/search-mcp.js /path/to/.hem/search-index.db
11
+ *
12
+ * Opens the DB in read-only mode. Multiple agent processes may connect
13
+ * simultaneously; SQLite WAL mode handles concurrent reads safely.
14
+ *
15
+ * Registered in OpenCode via config.mcp as:
16
+ * { type: "local", command: ["node", "dist/search-mcp.js", dbPath], enabled: true }
17
+ */
18
+ import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
19
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
20
+ import { fileURLToPath } from "node:url";
21
+ import { z } from "zod/v4";
22
+ import { SearchIndex } from "./search-index.js";
23
+ /**
24
+ * Build the hem-search MCP server bound to the given SearchIndex.
25
+ * Exported for tests; the CLI bootstrap below wires it up to a stdio
26
+ * transport with a real read-only SQLite-backed index.
27
+ */
28
+ export function createSearchMcpServer(index) {
29
+ const server = new McpServer({
30
+ name: "hem-search",
31
+ version: "1.0.0",
32
+ });
33
+ server.registerTool("search_docs", {
34
+ description: "Search existing documentation files by keyword. Returns the most relevant " +
35
+ "docs with short snippets. Use this before creating or updating a doc to find " +
36
+ "existing coverage. Example: search_docs({ query: 'authentication session token' })",
37
+ inputSchema: {
38
+ query: z.string().describe("Search terms — keywords, phrases, or topic names"),
39
+ limit: z
40
+ .number()
41
+ .int()
42
+ .min(1)
43
+ .max(20)
44
+ .optional()
45
+ .describe("Maximum results to return (default 5, max 20)"),
46
+ },
47
+ }, ({ query, limit }) => {
48
+ const results = index.search(query, limit ?? 5);
49
+ return {
50
+ content: [
51
+ {
52
+ type: "text",
53
+ text: JSON.stringify({ results }),
54
+ },
55
+ ],
56
+ };
57
+ });
58
+ server.registerTool("get_docs_for_source", {
59
+ description: "Find documentation files that cover a given source code file. " +
60
+ "Useful for checking whether a source file is already documented. " +
61
+ "Example: get_docs_for_source({ source_path: 'src/auth/login.ts' })",
62
+ inputSchema: {
63
+ source_path: z
64
+ .string()
65
+ .describe("Relative path to the source file, e.g. 'src/auth/login.ts'"),
66
+ },
67
+ }, ({ source_path }) => {
68
+ const doc_paths = index.getDocsForSource(source_path);
69
+ return {
70
+ content: [
71
+ {
72
+ type: "text",
73
+ text: JSON.stringify({ doc_paths }),
74
+ },
75
+ ],
76
+ };
77
+ });
78
+ return server;
79
+ }
80
+ async function main() {
81
+ const dbPath = process.argv[2];
82
+ if (!dbPath) {
83
+ console.error("[hem-search] Usage: node search-mcp.js <dbPath>");
84
+ process.exit(1);
85
+ }
86
+ const index = SearchIndex.open(dbPath, /* readonly */ true);
87
+ const server = createSearchMcpServer(index);
88
+ const transport = new StdioServerTransport();
89
+ await server.connect(transport);
90
+ console.error("[hem-search] MCP server running on stdio");
91
+ }
92
+ // Only auto-run when invoked directly (not when imported by tests).
93
+ const isDirectRun = process.argv[1] !== undefined &&
94
+ fileURLToPath(import.meta.url) === process.argv[1];
95
+ if (isDirectRun) {
96
+ main().catch((err) => {
97
+ console.error("[hem-search] Fatal:", err);
98
+ process.exit(1);
99
+ });
100
+ }
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Server lifecycle utilities for Hem.
3
+ *
4
+ * Provides:
5
+ * - `findFreePort()` — discovers an available TCP port to avoid conflicts
6
+ * with stale OpenCode server processes from previous runs.
7
+ * - `trackServer()` / `untrackServer()` — registers the active server's
8
+ * `close()` function for automatic cleanup on process exit or signal
9
+ * (SIGINT, SIGTERM, SIGHUP, uncaughtException, unhandledRejection),
10
+ * preventing zombie child processes.
11
+ */
12
+ /**
13
+ * Find a free TCP port on 127.0.0.1.
14
+ *
15
+ * Binds a temporary server to port 0 (letting the OS assign an ephemeral
16
+ * port), reads the assigned port, then closes the server. This avoids
17
+ * the SDK's default port 4096 which may be held by a stale process.
18
+ */
19
+ export declare function findFreePort(): Promise<number>;
20
+ /**
21
+ * Register a server's `close()` function for automatic cleanup on
22
+ * process exit, signal (SIGINT, SIGTERM, SIGHUP), uncaughtException, or
23
+ * unhandledRejection.
24
+ *
25
+ * Call this immediately after `createOpencode()` resolves.
26
+ * Replaces any previously tracked server.
27
+ */
28
+ export declare function trackServer(closeFn: () => void): void;
29
+ /**
30
+ * Clear the tracked server cleanup function.
31
+ *
32
+ * Call this after `server.close()` in a `finally` block to prevent
33
+ * double-close on normal shutdown.
34
+ */
35
+ export declare function untrackServer(): void;
36
+ /**
37
+ * Attempt a `findFreePort` + server-creation sequence with automatic retry
38
+ * on port-conflict errors (`EADDRINUSE` and similar).
39
+ *
40
+ * Calls `factory()` up to `maxAttempts` times. If the factory throws an
41
+ * error whose message matches a port-conflict pattern, the error is
42
+ * swallowed and the next attempt proceeds. Non-port-conflict errors
43
+ * propagate immediately without further retries.
44
+ *
45
+ * The factory callback is responsible for calling `findFreePort()` and
46
+ * passing the result to `createOpencode()` (or equivalent). This keeps
47
+ * the retry logic decoupled from any specific server-creation API.
48
+ *
49
+ * @param factory - Async callback that discovers a port and creates
50
+ * the server. Called once per attempt.
51
+ * @param maxAttempts - Maximum number of attempts (default 3).
52
+ * @returns The value returned by a successful `factory()` call.
53
+ * @throws The last port-conflict error if all attempts are exhausted,
54
+ * or any non-port-conflict error immediately.
55
+ */
56
+ export declare function startWithRetry<T>(factory: () => Promise<T>, maxAttempts?: number): Promise<T>;
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Server lifecycle utilities for Hem.
3
+ *
4
+ * Provides:
5
+ * - `findFreePort()` — discovers an available TCP port to avoid conflicts
6
+ * with stale OpenCode server processes from previous runs.
7
+ * - `trackServer()` / `untrackServer()` — registers the active server's
8
+ * `close()` function for automatic cleanup on process exit or signal
9
+ * (SIGINT, SIGTERM, SIGHUP, uncaughtException, unhandledRejection),
10
+ * preventing zombie child processes.
11
+ */
12
+ import { createServer } from "node:net";
13
+ // ── Free port discovery ─────────────────────────────────────────────
14
+ /**
15
+ * Find a free TCP port on 127.0.0.1.
16
+ *
17
+ * Binds a temporary server to port 0 (letting the OS assign an ephemeral
18
+ * port), reads the assigned port, then closes the server. This avoids
19
+ * the SDK's default port 4096 which may be held by a stale process.
20
+ */
21
+ export function findFreePort() {
22
+ return new Promise((resolve, reject) => {
23
+ const srv = createServer();
24
+ srv.listen(0, "127.0.0.1", () => {
25
+ const addr = srv.address();
26
+ if (addr === null || typeof addr === "string") {
27
+ srv.close(() => reject(new Error("Failed to determine port from server address")));
28
+ return;
29
+ }
30
+ const port = addr.port;
31
+ srv.close(() => resolve(port));
32
+ });
33
+ srv.on("error", reject);
34
+ });
35
+ }
36
+ // ── Server process cleanup ──────────────────────────────────────────
37
+ //
38
+ // Only one OpenCode server is active at a time (the auth server is closed
39
+ // before the generation server starts), so a single `activeCleanup` slot
40
+ // is sufficient.
41
+ let activeCleanup = null;
42
+ let handlersRegistered = false;
43
+ function onExit() {
44
+ if (activeCleanup) {
45
+ activeCleanup();
46
+ activeCleanup = null;
47
+ }
48
+ }
49
+ function onSignal(signal) {
50
+ onExit();
51
+ // Re-raise the signal so the process exits with the correct code.
52
+ // We must remove our listener first to avoid infinite recursion.
53
+ process.removeAllListeners(signal);
54
+ process.kill(process.pid, signal);
55
+ }
56
+ function ensureHandlers() {
57
+ if (handlersRegistered)
58
+ return;
59
+ handlersRegistered = true;
60
+ process.on("exit", onExit);
61
+ process.on("SIGINT", () => onSignal("SIGINT"));
62
+ process.on("SIGTERM", () => onSignal("SIGTERM"));
63
+ process.on("SIGHUP", () => onSignal("SIGHUP"));
64
+ process.on("uncaughtException", () => {
65
+ onExit();
66
+ process.exit(1);
67
+ });
68
+ process.on("unhandledRejection", () => {
69
+ onExit();
70
+ process.exit(1);
71
+ });
72
+ }
73
+ /**
74
+ * Register a server's `close()` function for automatic cleanup on
75
+ * process exit, signal (SIGINT, SIGTERM, SIGHUP), uncaughtException, or
76
+ * unhandledRejection.
77
+ *
78
+ * Call this immediately after `createOpencode()` resolves.
79
+ * Replaces any previously tracked server.
80
+ */
81
+ export function trackServer(closeFn) {
82
+ ensureHandlers();
83
+ activeCleanup = closeFn;
84
+ }
85
+ /**
86
+ * Clear the tracked server cleanup function.
87
+ *
88
+ * Call this after `server.close()` in a `finally` block to prevent
89
+ * double-close on normal shutdown.
90
+ */
91
+ export function untrackServer() {
92
+ activeCleanup = null;
93
+ }
94
+ // ── Retry utility for port acquisition ──────────────────────────────
95
+ /** Default number of retry attempts for port acquisition. */
96
+ const DEFAULT_MAX_ATTEMPTS = 3;
97
+ /** Regex to detect port-conflict errors worth retrying. */
98
+ const PORT_CONFLICT_RE = /EADDRINUSE|port.*in use|already.*listening/i;
99
+ /**
100
+ * Attempt a `findFreePort` + server-creation sequence with automatic retry
101
+ * on port-conflict errors (`EADDRINUSE` and similar).
102
+ *
103
+ * Calls `factory()` up to `maxAttempts` times. If the factory throws an
104
+ * error whose message matches a port-conflict pattern, the error is
105
+ * swallowed and the next attempt proceeds. Non-port-conflict errors
106
+ * propagate immediately without further retries.
107
+ *
108
+ * The factory callback is responsible for calling `findFreePort()` and
109
+ * passing the result to `createOpencode()` (or equivalent). This keeps
110
+ * the retry logic decoupled from any specific server-creation API.
111
+ *
112
+ * @param factory - Async callback that discovers a port and creates
113
+ * the server. Called once per attempt.
114
+ * @param maxAttempts - Maximum number of attempts (default 3).
115
+ * @returns The value returned by a successful `factory()` call.
116
+ * @throws The last port-conflict error if all attempts are exhausted,
117
+ * or any non-port-conflict error immediately.
118
+ */
119
+ export async function startWithRetry(factory, maxAttempts = DEFAULT_MAX_ATTEMPTS) {
120
+ let lastError;
121
+ for (let attempt = 1; attempt <= maxAttempts; attempt++) {
122
+ try {
123
+ return await factory();
124
+ }
125
+ catch (error) {
126
+ const message = error instanceof Error ? error.message : String(error);
127
+ if (!PORT_CONFLICT_RE.test(message)) {
128
+ throw error;
129
+ }
130
+ lastError = error;
131
+ // Port conflict — retry with a fresh port on next iteration
132
+ }
133
+ }
134
+ throw lastError;
135
+ }
@@ -0,0 +1,227 @@
1
+ /**
2
+ * OpenCode session utilities for Hem.
3
+ *
4
+ * Provides the `SessionClient` interface, the centralized `SessionTracker`
5
+ * for monitoring session completion, the shared `promptAndWait()` helper
6
+ * for sending prompts, and JSON extraction helpers used by agent classes.
7
+ *
8
+ * `promptAndWait()` uses the async prompt flow:
9
+ * 1. `session.promptAsync()` — fire the prompt without blocking
10
+ * 2. Register the session with the centralized `SessionTracker`
11
+ * 3. Wait for the tracker to resolve (session disappears from the
12
+ * server's status map, meaning it has completed)
13
+ * 4. Read `session.messages()` to extract the response
14
+ *
15
+ * LLM-specific prompt building and session orchestration have been
16
+ * extracted into dedicated agent classes under `src/agents/`.
17
+ */
18
+ /** How often the tracker polls session status (ms). */
19
+ export declare const POLL_INTERVAL_MS = 250;
20
+ /** Hard ceiling timeout — if a session hasn't completed after this long,
21
+ * give up and recover from tool history (ms). */
22
+ export declare const MAX_PROMPT_TIMEOUT_MS: number;
23
+ /** Tighter timeout for exploration sessions — they typically finish in 2-3 min.
24
+ * Surfaces hangs 25 minutes earlier than the default ceiling. */
25
+ export declare const EXPLORATION_TIMEOUT_MS: number;
26
+ /** Timeout for documentation generation sessions — more complex than
27
+ * exploration but still bounded; surfaces hangs 20 minutes earlier. */
28
+ export declare const DOCUMENTATION_TIMEOUT_MS: number;
29
+ /**
30
+ * Status of an individual session as reported by the OpenCode server.
31
+ */
32
+ export interface SessionStatus {
33
+ type: "idle" | "busy" | "retry";
34
+ /** Present when type is "retry". */
35
+ attempt?: number;
36
+ message?: string;
37
+ next?: number;
38
+ }
39
+ /**
40
+ * A part from a message response. This is the union of all part types
41
+ * the SDK may return. We keep it loose to avoid coupling to every SDK
42
+ * part variant — callers inspect `type` to narrow.
43
+ */
44
+ export interface MessagePart {
45
+ type: string;
46
+ text?: string;
47
+ /** Present on "patch" parts — lists file paths the edit tool touched. */
48
+ files?: string[];
49
+ /** Present on "tool" parts — name of the tool invoked. */
50
+ tool?: string;
51
+ /** Present on "tool" parts — tool call state with input/output. */
52
+ state?: {
53
+ status?: string;
54
+ input?: Record<string, unknown>;
55
+ output?: string;
56
+ };
57
+ }
58
+ /**
59
+ * Minimal client interface required by agents.
60
+ *
61
+ * Mirrors the subset of `OpencodeClient` used for session creation,
62
+ * async prompting, status polling, and message retrieval.
63
+ * Easy to mock in tests without importing the SDK.
64
+ */
65
+ export interface SessionClient {
66
+ session: {
67
+ create(options?: {
68
+ body?: {
69
+ title?: string;
70
+ };
71
+ }): Promise<{
72
+ data?: {
73
+ id: string;
74
+ };
75
+ error?: unknown;
76
+ }>;
77
+ promptAsync(options: {
78
+ path: {
79
+ id: string;
80
+ };
81
+ body: {
82
+ parts: Array<{
83
+ type: "text";
84
+ text: string;
85
+ }>;
86
+ agent?: string;
87
+ };
88
+ }): Promise<{
89
+ data?: void;
90
+ error?: unknown;
91
+ }>;
92
+ status(options?: {
93
+ query?: {
94
+ directory?: string;
95
+ };
96
+ }): Promise<{
97
+ data?: Record<string, SessionStatus>;
98
+ error?: unknown;
99
+ }>;
100
+ messages(options: {
101
+ path: {
102
+ id: string;
103
+ };
104
+ }): Promise<{
105
+ data?: Array<{
106
+ info: {
107
+ role: string;
108
+ };
109
+ parts: Array<MessagePart>;
110
+ }>;
111
+ error?: unknown;
112
+ }>;
113
+ abort(options: {
114
+ path: {
115
+ id: string;
116
+ };
117
+ }): Promise<{
118
+ data?: boolean;
119
+ error?: unknown;
120
+ }>;
121
+ delete(options: {
122
+ path: {
123
+ id: string;
124
+ };
125
+ }): Promise<{
126
+ data?: boolean;
127
+ error?: unknown;
128
+ }>;
129
+ };
130
+ event: {
131
+ subscribe(options?: {
132
+ query?: {
133
+ directory?: string;
134
+ };
135
+ }): Promise<{
136
+ stream: AsyncGenerator<SseEvent, void, unknown>;
137
+ }>;
138
+ };
139
+ }
140
+ /**
141
+ * Minimal SSE event type for broadcast interception.
142
+ * We only need to match `message.part.updated` and `session.created` events.
143
+ */
144
+ export interface SseEvent {
145
+ type: string;
146
+ properties: Record<string, unknown>;
147
+ }
148
+ /**
149
+ * Centralized session completion tracker.
150
+ *
151
+ * Runs a single poll loop that calls `GET /session/status` once per
152
+ * interval and resolves individual session promises as they disappear
153
+ * from the server's status map (meaning they have completed).
154
+ *
155
+ * The OpenCode server only reports actively-processing sessions in the
156
+ * status map — completed sessions are removed entirely. The tracker
157
+ * exploits this: "present in map" = busy, "absent from map" = done.
158
+ *
159
+ * **Subagent awareness**: subscribes to SSE `session.created` events to
160
+ * detect child sessions spawned by any tracked parent. A parent session
161
+ * is not resolved as "done" until the parent itself AND all its
162
+ * descendants have disappeared from the status map.
163
+ *
164
+ * The poll loop is lazy: it starts on the first `track()` call and
165
+ * pauses when the tracked set becomes empty.
166
+ */
167
+ export interface SessionTracker {
168
+ /**
169
+ * Register a session ID to track.
170
+ *
171
+ * @param sessionId - The session to monitor.
172
+ * @param label - Human-readable label for logging (e.g., group ID).
173
+ * Defaults to truncated session ID.
174
+ * @returns A promise that resolves to `"done"` when the session completes,
175
+ * or `"timeout"` if the per-session deadline is exceeded.
176
+ */
177
+ track(sessionId: string, label?: string): Promise<"done" | "timeout">;
178
+ /** Stop the poll loop, SSE subscription, and clean up. */
179
+ stop(): void;
180
+ }
181
+ /**
182
+ * Creates a centralized session tracker with subagent awareness.
183
+ *
184
+ * The tracker subscribes to SSE `session.created` events to detect child
185
+ * sessions spawned by tracked parents. A parent is only resolved as "done"
186
+ * when both the parent and all its descendants have completed.
187
+ *
188
+ * If the SSE subscription fails, the tracker gracefully degrades to the
189
+ * original poll-only behavior (no child tracking).
190
+ *
191
+ * @param client - The OpenCode SDK client (for `session.status()` and `event.subscribe()`).
192
+ * @param options - Configuration: verbose logger, poll interval, per-session timeout.
193
+ * @returns A `SessionTracker` instance.
194
+ */
195
+ export declare function createSessionTracker(client: SessionClient, options?: {
196
+ verbose?: (msg: string) => void;
197
+ pollIntervalMs?: number;
198
+ maxTimeoutMs?: number;
199
+ }): SessionTracker;
200
+ /**
201
+ * Sends a prompt to an OpenCode session and returns the complete response.
202
+ *
203
+ * Uses the async prompt flow:
204
+ * 1. `session.promptAsync()` fires the prompt without blocking.
205
+ * 2. Registers the session with the centralized `SessionTracker` and
206
+ * waits for it to complete (disappear from the status map).
207
+ * 3. Reads `session.messages()` to extract the assistant's response.
208
+ * 4. If the hard ceiling is hit, recovers file paths from tool history.
209
+ *
210
+ * @param client - The OpenCode SDK client.
211
+ * @param sessionId - The session to prompt.
212
+ * @param parts - The message parts to send.
213
+ * @param options - Settings: tracker (required), verbose callback, agent selection.
214
+ * @returns The response parts from the assistant message.
215
+ * @throws {AuthExpiredError} If auth expires during the API call.
216
+ * @throws {Error} If the prompt fails to be accepted.
217
+ */
218
+ export declare function promptAndWait(client: SessionClient, sessionId: string, parts: Array<{
219
+ type: "text";
220
+ text: string;
221
+ }>, options: {
222
+ verbose?: (msg: string) => void;
223
+ agent?: string;
224
+ tracker: SessionTracker;
225
+ /** Human-readable label for tracker logging. */
226
+ label?: string;
227
+ }): Promise<Array<MessagePart>>;