@vibedgc/sdk 0.6.4

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.
@@ -0,0 +1,31 @@
1
+ import type { Env } from "./types.ts";
2
+ export declare const REPO_ROOT: string;
3
+ /** True when this file runs from a DGC source checkout (sdk/typescript inside the repository). */
4
+ export declare function isCheckout(): boolean;
5
+ /** The installed CLI launcher: `dgc` on PATH, then the vibedgc.com installer's ~/.local/bin/dgc. */
6
+ export declare function installedLauncher(env?: Env): string | undefined;
7
+ /** True when `python` has `-P` (3.11+): it keeps the working directory off sys.path. */
8
+ export declare function supportsSafePath(python: string, env?: Env): boolean;
9
+ /**
10
+ * `python -m dgc serve`, with `-P` where the interpreter has it: `-m` puts the working directory
11
+ * (the session cwd) first on sys.path, so a workspace with its own `dgc/` package would replace
12
+ * the runtime.
13
+ */
14
+ export declare function pythonRuntime(python: string, env?: Env): string[];
15
+ /**
16
+ * How to start `dgc serve`: DGC_PYTHON, then this checkout's .venv (source checkouts only),
17
+ * then the installed `dgc` launcher, then `python3 -m dgc`. The ready handshake checks the
18
+ * protocol either way.
19
+ */
20
+ export declare function defaultRuntime(env?: Env): string[];
21
+ /** Host variables every runtime child receives: program lookup, locale, terminal, time zone,
22
+ * temp and certificate locations. None is a credential; anything else must be passed on purpose
23
+ * (`extraEnv`, `inheritEnv`). Mirrors the Python SDK's BASE_ENV. */
24
+ export declare const BASE_ENV: ReadonlySet<string>;
25
+ /**
26
+ * The runtime child's environment. `inheritEnv` false (default) passes only BASE_ENV, a list of
27
+ * names adds those host variables, true passes everything (the host DGC_*_API_KEY values are
28
+ * still dropped in isolated mode). With `inherit` (inheritUserState) DGC_* and XDG_* variables
29
+ * pass too, since they locate the user's own DGC state.
30
+ */
31
+ export declare function isolatedEnv(stateDir: string, extra?: Record<string, string>, inherit?: boolean, projectRoot?: string, inheritEnv?: boolean | readonly string[], hostEnv?: Env): Env;
@@ -0,0 +1,148 @@
1
+ import { accessSync, constants, existsSync, mkdirSync, statSync } from "node:fs";
2
+ import { homedir } from "node:os";
3
+ import { delimiter, join } from "node:path";
4
+ import { execFileSync } from "node:child_process";
5
+ import { fileURLToPath } from "node:url";
6
+ import { DGCConfigError } from "./errors.js";
7
+ import { privateDir } from "./state.js";
8
+ export const REPO_ROOT = fileURLToPath(new URL("../../..", import.meta.url)).replace(/\/$/, "");
9
+ /** True when this file runs from a DGC source checkout (sdk/typescript inside the repository). */
10
+ export function isCheckout() {
11
+ return existsSync(join(REPO_ROOT, "dgc", "__init__.py"))
12
+ && existsSync(join(REPO_ROOT, "sdk", "typescript", "package.json"));
13
+ }
14
+ function executable(path) {
15
+ try {
16
+ accessSync(path, constants.X_OK);
17
+ return statSync(path).isFile();
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ /** The installed CLI launcher: `dgc` on PATH, then the vibedgc.com installer's ~/.local/bin/dgc. */
24
+ export function installedLauncher(env = process.env) {
25
+ for (const dir of (env.PATH || "").split(delimiter)) {
26
+ if (dir && executable(join(dir, "dgc")))
27
+ return join(dir, "dgc");
28
+ }
29
+ const local = join(env.HOME || homedir(), ".local", "bin", "dgc");
30
+ return executable(local) ? local : undefined;
31
+ }
32
+ const SAFE_PATH_CACHE = new Map();
33
+ /** True when `python` has `-P` (3.11+): it keeps the working directory off sys.path. */
34
+ export function supportsSafePath(python, env = process.env) {
35
+ const key = `${python}\0${env.PATH || ""}`;
36
+ const cached = SAFE_PATH_CACHE.get(key);
37
+ if (cached !== undefined)
38
+ return cached;
39
+ let answer = false;
40
+ if (python.includes("/") ? executable(python) : true) {
41
+ try {
42
+ const out = execFileSync(python, ["-c", "import sys; print(int(sys.version_info >= (3, 11)))"], {
43
+ encoding: "utf8", stdio: ["ignore", "pipe", "ignore"], timeout: 10_000,
44
+ env: { PATH: env.PATH || "", PYTHONDONTWRITEBYTECODE: "1" },
45
+ });
46
+ answer = out.trim() === "1";
47
+ }
48
+ catch {
49
+ answer = false;
50
+ }
51
+ }
52
+ SAFE_PATH_CACHE.set(key, answer);
53
+ return answer;
54
+ }
55
+ /**
56
+ * `python -m dgc serve`, with `-P` where the interpreter has it: `-m` puts the working directory
57
+ * (the session cwd) first on sys.path, so a workspace with its own `dgc/` package would replace
58
+ * the runtime.
59
+ */
60
+ export function pythonRuntime(python, env = process.env) {
61
+ return supportsSafePath(python, env) ? [python, "-P", "-m", "dgc", "serve"] : [python, "-m", "dgc", "serve"];
62
+ }
63
+ /**
64
+ * How to start `dgc serve`: DGC_PYTHON, then this checkout's .venv (source checkouts only),
65
+ * then the installed `dgc` launcher, then `python3 -m dgc`. The ready handshake checks the
66
+ * protocol either way.
67
+ */
68
+ export function defaultRuntime(env = process.env) {
69
+ if (env.DGC_PYTHON)
70
+ return pythonRuntime(env.DGC_PYTHON, env);
71
+ const checkoutPython = join(REPO_ROOT, ".venv/bin/python");
72
+ if (isCheckout() && existsSync(checkoutPython))
73
+ return pythonRuntime(checkoutPython, env);
74
+ const launcher = installedLauncher(env);
75
+ if (launcher)
76
+ return [launcher, "serve"];
77
+ return pythonRuntime("python3", env);
78
+ }
79
+ /** Host variables every runtime child receives: program lookup, locale, terminal, time zone,
80
+ * temp and certificate locations. None is a credential; anything else must be passed on purpose
81
+ * (`extraEnv`, `inheritEnv`). Mirrors the Python SDK's BASE_ENV. */
82
+ export const BASE_ENV = new Set([
83
+ "PATH", "HOME", "USER", "LOGNAME", "SHELL", "LANG", "LANGUAGE", "LC_ALL", "LC_CTYPE",
84
+ "LC_MESSAGES", "LC_COLLATE", "LC_NUMERIC", "LC_TIME", "LC_MONETARY", "TERM", "COLORTERM",
85
+ "NO_COLOR", "TZ", "TMPDIR", "TEMP", "TMP", "SSL_CERT_FILE", "SSL_CERT_DIR",
86
+ "REQUESTS_CA_BUNDLE", "CURL_CA_BUNDLE", "SYSTEMROOT", "SYSTEMDRIVE", "WINDIR", "COMSPEC",
87
+ "PATHEXT",
88
+ ]);
89
+ const SECRET_ENV = ["DGC_API_KEY", "DGC_SEARCH_API_KEY", "DGC_SUBAGENT_API_KEY", "DGC_FALLBACK_API_KEY"];
90
+ /**
91
+ * The runtime child's environment. `inheritEnv` false (default) passes only BASE_ENV, a list of
92
+ * names adds those host variables, true passes everything (the host DGC_*_API_KEY values are
93
+ * still dropped in isolated mode). With `inherit` (inheritUserState) DGC_* and XDG_* variables
94
+ * pass too, since they locate the user's own DGC state.
95
+ */
96
+ export function isolatedEnv(stateDir, extra, inherit = false, projectRoot, inheritEnv = false, hostEnv = process.env) {
97
+ let env;
98
+ if (inheritEnv === true) {
99
+ env = { ...hostEnv };
100
+ }
101
+ else {
102
+ env = {};
103
+ for (const [key, value] of Object.entries(hostEnv)) {
104
+ const upper = key.toUpperCase();
105
+ if (BASE_ENV.has(upper) || (inherit && (upper.startsWith("DGC_") || upper.startsWith("XDG_")))) {
106
+ env[key] = value;
107
+ }
108
+ }
109
+ for (const name of inheritEnv || []) {
110
+ if (!name || name.includes("=") || name.includes("\0")) {
111
+ throw new DGCConfigError(`inheritEnv has an invalid variable name: ${JSON.stringify(name)}`);
112
+ }
113
+ if (hostEnv[name] !== undefined)
114
+ env[name] = hostEnv[name];
115
+ }
116
+ }
117
+ env.PYTHONUNBUFFERED = "1";
118
+ env.PYTHONDONTWRITEBYTECODE = "1";
119
+ if (!inherit) {
120
+ for (const key of SECRET_ENV)
121
+ delete env[key];
122
+ const home = privateDir(join(stateDir, "home"));
123
+ privateDir(join(home, ".dgc"));
124
+ mkdirSync(join(home, ".config"), { recursive: true });
125
+ mkdirSync(join(home, ".local/share"), { recursive: true });
126
+ mkdirSync(join(home, ".local/state"), { recursive: true });
127
+ env.HOME = home;
128
+ env.USERPROFILE = home;
129
+ env.DGC_HOME = home;
130
+ env.DGC_SDK_ISOLATED = "1";
131
+ if (projectRoot)
132
+ env.DGC_PROJECT_ROOT = projectRoot;
133
+ env.XDG_CONFIG_HOME = join(home, ".config");
134
+ env.XDG_DATA_HOME = join(home, ".local/share");
135
+ env.XDG_STATE_HOME = join(home, ".local/state");
136
+ }
137
+ Object.assign(env, extra);
138
+ // Only a source checkout puts its own dgc/ on the child's path. An installed package must not:
139
+ // REPO_ROOT is then node_modules, and anything importable there would shadow the CLI's own
140
+ // pinned dependencies.
141
+ if (isCheckout()) {
142
+ const pathParts = [REPO_ROOT];
143
+ if (env.PYTHONPATH)
144
+ pathParts.push(env.PYTHONPATH);
145
+ env.PYTHONPATH = pathParts.join(delimiter);
146
+ }
147
+ return env;
148
+ }
@@ -0,0 +1,4 @@
1
+ /** Harness-side JSON Schema subset used for outputSchema. Unsupported keywords are rejected. */
2
+ export declare function assertSupported(schema: unknown): void;
3
+ export declare function extractJson(text: string): unknown;
4
+ export declare function validate(value: unknown, schema: Record<string, unknown>, path?: string): string[];
package/dist/schema.js ADDED
@@ -0,0 +1,124 @@
1
+ /** Harness-side JSON Schema subset used for outputSchema. Unsupported keywords are rejected. */
2
+ const ALLOWED = new Set([
3
+ "type", "properties", "required", "items", "enum", "additionalProperties",
4
+ "minLength", "maxLength", "minimum", "maximum", "minItems", "maxItems",
5
+ "description", "title", "default",
6
+ ]);
7
+ const JSON_FENCE = /```(?:json)?\s*(\{[\s\S]*?\}|\[[\s\S]*?\])\s*```/;
8
+ export function assertSupported(schema) {
9
+ if (!schema || typeof schema !== "object" || Array.isArray(schema) || !Object.keys(schema).length) {
10
+ throw new Error("outputSchema must be a non-empty object");
11
+ }
12
+ walk(schema);
13
+ }
14
+ function walk(node) {
15
+ if (!node || typeof node !== "object" || Array.isArray(node))
16
+ return;
17
+ const record = node;
18
+ if ("$ref" in record || "$id" in record || "$schema" in record) {
19
+ throw new Error("outputSchema must not use $ref, $id, or $schema");
20
+ }
21
+ for (const key of Object.keys(record)) {
22
+ if (!ALLOWED.has(key))
23
+ throw new Error(`outputSchema has unsupported keyword: ${key}`);
24
+ }
25
+ if (record.properties && typeof record.properties === "object") {
26
+ for (const child of Object.values(record.properties))
27
+ walk(child);
28
+ }
29
+ if (record.items && typeof record.items === "object")
30
+ walk(record.items);
31
+ }
32
+ export function extractJson(text) {
33
+ let raw = (text || "").trim();
34
+ if (!raw)
35
+ throw new Error("final text is empty");
36
+ const fenced = JSON_FENCE.exec(raw);
37
+ if (fenced)
38
+ raw = fenced[1];
39
+ else {
40
+ const obj = raw.indexOf("{");
41
+ const arr = raw.indexOf("[");
42
+ const starts = [obj, arr].filter((index) => index >= 0);
43
+ if (starts.length)
44
+ raw = raw.slice(Math.min(...starts));
45
+ }
46
+ return JSON.parse(raw);
47
+ }
48
+ export function validate(value, schema, path = "$") {
49
+ const errors = [];
50
+ const expected = schema.type;
51
+ if (expected) {
52
+ const types = Array.isArray(expected) ? expected : [expected];
53
+ if (!types.some((kind) => isType(value, String(kind)))) {
54
+ errors.push(`${path} should be ${expected}`);
55
+ return errors;
56
+ }
57
+ }
58
+ if ("enum" in schema && !(schema.enum || []).includes(value)) {
59
+ errors.push(`${path} is not one of the allowed values`);
60
+ }
61
+ if (typeof value === "string") {
62
+ if (typeof schema.minLength === "number" && value.length < schema.minLength) {
63
+ errors.push(`${path} is shorter than minLength`);
64
+ }
65
+ if (typeof schema.maxLength === "number" && value.length > schema.maxLength) {
66
+ errors.push(`${path} is longer than maxLength`);
67
+ }
68
+ }
69
+ if (typeof value === "number" && !Number.isNaN(value)) {
70
+ if (typeof schema.minimum === "number" && value < schema.minimum)
71
+ errors.push(`${path} is below minimum`);
72
+ if (typeof schema.maximum === "number" && value > schema.maximum)
73
+ errors.push(`${path} is above maximum`);
74
+ }
75
+ if (Array.isArray(value)) {
76
+ if (typeof schema.minItems === "number" && value.length < schema.minItems)
77
+ errors.push(`${path} has too few items`);
78
+ if (typeof schema.maxItems === "number" && value.length > schema.maxItems)
79
+ errors.push(`${path} has too many items`);
80
+ if (schema.items && typeof schema.items === "object" && !Array.isArray(schema.items)) {
81
+ value.forEach((item, index) => {
82
+ errors.push(...validate(item, schema.items, `${path}[${index}]`));
83
+ });
84
+ }
85
+ }
86
+ if (value && typeof value === "object" && !Array.isArray(value)) {
87
+ const record = value;
88
+ const props = (schema.properties && typeof schema.properties === "object")
89
+ ? schema.properties : {};
90
+ const required = Array.isArray(schema.required) ? schema.required : [];
91
+ for (const key of required) {
92
+ if (!(key in record))
93
+ errors.push(`${path}.${key} is required`);
94
+ }
95
+ const additional = schema.additionalProperties === undefined ? true : schema.additionalProperties;
96
+ for (const [key, item] of Object.entries(record)) {
97
+ if (key in props)
98
+ errors.push(...validate(item, props[key], `${path}.${key}`));
99
+ else if (additional === false)
100
+ errors.push(`${path}.${key} is not allowed`);
101
+ else if (additional && typeof additional === "object") {
102
+ errors.push(...validate(item, additional, `${path}.${key}`));
103
+ }
104
+ }
105
+ }
106
+ return errors;
107
+ }
108
+ function isType(value, kind) {
109
+ if (kind === "object")
110
+ return Boolean(value) && typeof value === "object" && !Array.isArray(value);
111
+ if (kind === "array")
112
+ return Array.isArray(value);
113
+ if (kind === "string")
114
+ return typeof value === "string";
115
+ if (kind === "integer")
116
+ return typeof value === "number" && Number.isInteger(value);
117
+ if (kind === "number")
118
+ return typeof value === "number" && !Number.isNaN(value);
119
+ if (kind === "boolean")
120
+ return typeof value === "boolean";
121
+ if (kind === "null")
122
+ return value === null;
123
+ return false;
124
+ }
@@ -0,0 +1,264 @@
1
+ import type { Transport } from "./transport.ts";
2
+ import type { ToolHub } from "./tools.ts";
3
+ import type { AuditLog } from "./audit.ts";
4
+ import type { UsageLog, UsageTotals } from "./usage.ts";
5
+ import { type Snapshot } from "./changes.ts";
6
+ import { type Policy } from "./policy.ts";
7
+ import type { StateLock } from "./state.ts";
8
+ import type { AbortSignalLike, Artifact, Denial, Checkpoint, Pricing, RunEvent, RunOptions, RunResult, SandboxStatus, SessionInfo, SessionOptions, TaskItem } from "./types.ts";
9
+ /** Best-effort category for a `tool_denied` reason (see {@link Denial}). */
10
+ export declare function denialSource(reason: string): Denial["source"];
11
+ /** Pump-side state of one run. Outcome events for its prompt ids land here, whoever reads them. */
12
+ export declare class Run {
13
+ readonly result: RunResult;
14
+ readonly requestId: string;
15
+ readonly ids: Set<string>;
16
+ readonly expect: Set<string>;
17
+ readonly steers: Set<string>;
18
+ readonly unresolved: Set<string>;
19
+ readonly returned: Set<string>;
20
+ readonly rejected: Map<string, string>;
21
+ readonly turnIds: Set<string>;
22
+ readonly startedIds: Set<string>;
23
+ liveTurn: string;
24
+ started: boolean;
25
+ cancelReason: "" | "cancelled" | "timeout" | "decision_failed";
26
+ cancelAt: number;
27
+ cancelSent: boolean;
28
+ decisionError: string;
29
+ usage: UsageTotals;
30
+ billed: number;
31
+ pendingBills: number;
32
+ usageUnknown: boolean;
33
+ done: boolean;
34
+ handle: RunHandle | null;
35
+ pumpStarted: boolean;
36
+ holdsFollowups: boolean;
37
+ held: boolean;
38
+ /** The workspace when this run's last turn ended: its "after", and a follow-up's "before". */
39
+ after: Snapshot | null;
40
+ private cancelWaiters;
41
+ private doneWaiters;
42
+ constructor(result: RunResult, requestId: string);
43
+ /** Resolves once a cancel (of any reason) is requested. */
44
+ cancelled(): Promise<void>;
45
+ noteCancel(): void;
46
+ markDone(): void;
47
+ waitDone(timeoutMs: number): Promise<void>;
48
+ }
49
+ /**
50
+ * Streaming handle. Iterate its events (`for await`), then call {@link result}. Leaving the loop
51
+ * early (`break`, `return`, a throw) cancels the run and waits (bounded) for DGC to stop, so the
52
+ * session is free again. `result()` drains whatever was not iterated.
53
+ */
54
+ export declare class RunHandle implements AsyncIterable<RunEvent> {
55
+ private readonly session;
56
+ /** @internal */
57
+ readonly run: Run;
58
+ private gen;
59
+ private primed;
60
+ private chain;
61
+ private finished;
62
+ private detach;
63
+ constructor(session: Session, run: Run);
64
+ get runId(): string;
65
+ /** True once the run is over and every event was consumed. */
66
+ get done(): boolean;
67
+ /**
68
+ * @internal Attach the pump. `prime` starts it now, so the prompt is sent when stream()
69
+ * returns; a run queued behind another starts when it is iterated or awaited (starting it here
70
+ * would drain the run in front of it behind its caller's back).
71
+ */
72
+ begin(gen: AsyncGenerator<RunEvent>, signal: AbortSignalLike | undefined, prime: boolean): void;
73
+ private step;
74
+ private finish;
75
+ [Symbol.asyncIterator](): AsyncIterator<RunEvent>;
76
+ /**
77
+ * Drain the run and return its result. `timeoutMs` bounds this wait (undefined/null waits until
78
+ * the run ends, which the run's own timeout bounds); if the run is still going when it lapses,
79
+ * DGCTimeoutError is thrown and the run keeps going (call {@link cancel} to stop it).
80
+ */
81
+ result(timeoutMs?: number | null): Promise<RunResult>;
82
+ /** Cancel this run. The result settles with `status: "cancelled"`. */
83
+ cancel(): void;
84
+ /** Cancel if still going, then drain (bounded); used when the consumer went away. */
85
+ abandon(timeoutMs?: number): Promise<void>;
86
+ private close;
87
+ }
88
+ /** @internal What DGC.session() hands a Session. */
89
+ export type SessionInit = {
90
+ options: SessionOptions;
91
+ unhandled: "deny" | "callback";
92
+ instructions: string;
93
+ toolHub: ToolHub | null;
94
+ cwd: string | null;
95
+ policy: Policy | null;
96
+ pricing?: Pricing;
97
+ department: string;
98
+ usageLog: UsageLog | null;
99
+ auditLog: AuditLog | null;
100
+ model: string;
101
+ permissionMode: string;
102
+ isolated: boolean;
103
+ maxTurns?: number;
104
+ verifyCommand: string;
105
+ stateLock: StateLock | null;
106
+ excludePaths: string[];
107
+ requestTimeoutMs: number;
108
+ sandbox: SandboxStatus;
109
+ };
110
+ export declare class Session {
111
+ sessionId: string;
112
+ sessionPath: string;
113
+ readonly transport: Transport;
114
+ readonly protocolVersion: unknown;
115
+ readonly capabilities: Record<string, unknown>;
116
+ /** Whether this session's shell commands run inside the OS sandbox. */
117
+ readonly sandbox: SandboxStatus;
118
+ private readonly init;
119
+ private closed;
120
+ private pending;
121
+ private owners;
122
+ private active;
123
+ private queued;
124
+ private turn;
125
+ private usageLast;
126
+ private billTo;
127
+ private taskIds;
128
+ private taskRevision;
129
+ private answeredIds;
130
+ private maxTurnsDirty;
131
+ private modelSeen;
132
+ constructor(transport: Transport, ready: Record<string, unknown>, init: SessionInit);
133
+ /** Advanced transport. Prefer {@link run} / {@link stream}. */
134
+ get raw(): Transport;
135
+ /** @internal The verify command, for the accumulator. */
136
+ get verifyCommand(): string;
137
+ close(): Promise<void>;
138
+ run(prompt: string, runOptions?: RunOptions): Promise<RunResult>;
139
+ /**
140
+ * Send `prompt` and return a handle over its events. `timeoutMs` limits each turn of the run
141
+ * (default 180 000; null for none). `maxTurns` caps tool iterations for this run only; the
142
+ * session's own setting is restored afterwards. `signal` cancels the run when aborted.
143
+ */
144
+ stream(prompt: string, runOptions?: RunOptions): RunHandle;
145
+ /**
146
+ * Queue a prompt behind the active run and return a handle for its own turn. With no run in
147
+ * flight this is {@link stream}. A follow-up is observed, audited and billed like any run.
148
+ * Behind a run with its own `maxTurns` or `outputSchema`, it is sent when that run is over (so
149
+ * it runs under the session's own settings). It does not run when the run in front of it is
150
+ * cancelled or times out.
151
+ */
152
+ followup(text: string, runOptions?: Omit<RunOptions, "maxTurns" | "workflow">): RunHandle;
153
+ /** Cancel the active run. DGC's stop also hands back prompts queued behind it. */
154
+ cancel(): void;
155
+ /**
156
+ * Add `text` to the run in flight. Throws unless a run is active. If DGC cannot fold it into
157
+ * the live turn, it runs as a further turn of the same run (its tool calls are part of that
158
+ * run's result, audit and usage).
159
+ */
160
+ steer(text: string): void;
161
+ /**
162
+ * Fill `sessionPath` once this session's own transcript exists. Only a transcript whose file
163
+ * name is this session's id is used; another session's transcript is never adopted.
164
+ */
165
+ bindIdentity(): Promise<void>;
166
+ private newResult;
167
+ private request;
168
+ /** Hold the stateDir lock around commands that make DGC save the isolated config. */
169
+ private configScope;
170
+ listSessions(): Promise<SessionInfo[]>;
171
+ listCheckpoints(): Promise<Checkpoint[]>;
172
+ rewind(index: number): Promise<Record<string, unknown>>;
173
+ fork(name?: string): Promise<Record<string, unknown>>;
174
+ history(): Promise<Record<string, unknown>>;
175
+ listSkills(): Promise<Array<{
176
+ name: string;
177
+ description: string;
178
+ source: string;
179
+ enabled: boolean;
180
+ }>>;
181
+ getGoal(): Promise<Record<string, unknown>>;
182
+ setGoal(text: string, status?: string): Promise<Record<string, unknown>>;
183
+ listMonitors(): Promise<unknown[]>;
184
+ listHooks(): Promise<Record<string, unknown>>;
185
+ getMemory(): Promise<Record<string, unknown>>;
186
+ addMemory(text: string, scope?: "project" | "user"): Promise<Record<string, unknown>>;
187
+ listPermissions(): Promise<Array<{
188
+ action: string;
189
+ rule: string;
190
+ }>>;
191
+ /**
192
+ * Add a rule. In an isolated session it lasts for this state_dir's sessions until the next
193
+ * session rewrites the config; a RuntimePolicy is not installed this way (it is per session).
194
+ */
195
+ addPermissionRule(action: "allow" | "ask" | "deny", rule: string): Promise<Array<{
196
+ action: string;
197
+ rule: string;
198
+ }>>;
199
+ removePermissionRule(action: "allow" | "ask" | "deny", rule: string): Promise<Array<{
200
+ action: string;
201
+ rule: string;
202
+ }>>;
203
+ addMcpServer(name: string, command: string, args?: string[]): Promise<unknown[]>;
204
+ listMcpServers(): Promise<unknown[]>;
205
+ getSkill(name: string): Promise<Record<string, unknown>>;
206
+ setSkillEnabled(name: string, enabled: boolean): Promise<unknown>;
207
+ stopMonitor(id?: string): Promise<unknown[]>;
208
+ listArtifacts(): Promise<Artifact[]>;
209
+ listAgents(): Promise<unknown[]>;
210
+ clearTodos(): Promise<TaskItem[]>;
211
+ getPlan(): Promise<Record<string, unknown>>;
212
+ getConfig(): Promise<Record<string, unknown>>;
213
+ getUsage(range?: string): Promise<Record<string, unknown>>;
214
+ newSession(): Promise<Record<string, unknown>>;
215
+ nameSession(name: string): Promise<Record<string, unknown>>;
216
+ deleteSession(path: string): Promise<SessionInfo[]>;
217
+ generateHandoff(save?: boolean): Promise<Record<string, unknown>>;
218
+ private read;
219
+ /**
220
+ * Bookkeeping every event gets, whichever reader takes it: turn ownership, prompt outcomes,
221
+ * usage billing, the audit row, and identity.
222
+ */
223
+ private observe;
224
+ /** A workflow prompt's turn carries no request id; give it to the run waiting for it. */
225
+ private adoptable;
226
+ private noteOutcome;
227
+ private account;
228
+ /** Drop control events left on the pipe (after resume/fork/rewind); stop at anything else. */
229
+ discardIdle(timeoutMs?: number): Promise<void>;
230
+ /** @internal */
231
+ cancelRun(run: Run, reason: "cancelled" | "timeout" | "decision_failed"): void;
232
+ /** @internal Drop a queued run nobody will drive. */
233
+ forget(run: Run): void;
234
+ private composePrompt;
235
+ /** Apply a run-scoped max_turns; DGC persists set_config, so it is restored after. */
236
+ private setRunMaxTurns;
237
+ private restoreMaxTurns;
238
+ private sendPrompt;
239
+ private pump;
240
+ /** Pump events until every turn this run owns has ended. */
241
+ private turns;
242
+ private completion;
243
+ /** The usage totals for a turn arrive right after its turn_end. */
244
+ private awaitBilling;
245
+ private finish;
246
+ private applySchema;
247
+ /** @internal */
248
+ projectTasks(rows: unknown): TaskItem[];
249
+ private recordUsage;
250
+ private finishUsage;
251
+ private answer;
252
+ private respond;
253
+ /**
254
+ * Ask an application callback (sync or async). `decisionTimeoutMs: null` waits as long as it
255
+ * takes; a cancel always wins. A callback that throws, times out, or returns an invalid answer
256
+ * gets `fallback`; with `permissions.unhandled: "callback"` that also stops the run.
257
+ */
258
+ private decide;
259
+ private permission;
260
+ private plan;
261
+ private answerOptions;
262
+ private answerMcp;
263
+ }
264
+ export declare function rowsToSessions(raw: unknown): SessionInfo[];