@oharness/engine 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/agent.d.ts +196 -0
- package/dist/agent/agent.js +758 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/compaction.d.ts +68 -0
- package/dist/agent/compaction.js +179 -0
- package/dist/agent/compaction.js.map +1 -0
- package/dist/agent/hooks.d.ts +77 -0
- package/dist/agent/hooks.js +152 -0
- package/dist/agent/hooks.js.map +1 -0
- package/dist/agent/memory.d.ts +45 -0
- package/dist/agent/memory.js +147 -0
- package/dist/agent/memory.js.map +1 -0
- package/dist/agent/overflow.d.ts +35 -0
- package/dist/agent/overflow.js +69 -0
- package/dist/agent/overflow.js.map +1 -0
- package/dist/agent/permissions.d.ts +181 -0
- package/dist/agent/permissions.js +289 -0
- package/dist/agent/permissions.js.map +1 -0
- package/dist/agent/prompt.d.ts +25 -0
- package/dist/agent/prompt.js +63 -0
- package/dist/agent/prompt.js.map +1 -0
- package/dist/agent/session.d.ts +108 -0
- package/dist/agent/session.js +231 -0
- package/dist/agent/session.js.map +1 -0
- package/dist/agent/settings.d.ts +37 -0
- package/dist/agent/settings.js +113 -0
- package/dist/agent/settings.js.map +1 -0
- package/dist/agent/skills.d.ts +58 -0
- package/dist/agent/skills.js +225 -0
- package/dist/agent/skills.js.map +1 -0
- package/dist/agent/store.d.ts +308 -0
- package/dist/agent/store.js +596 -0
- package/dist/agent/store.js.map +1 -0
- package/dist/agent/subagent.d.ts +44 -0
- package/dist/agent/subagent.js +138 -0
- package/dist/agent/subagent.js.map +1 -0
- package/dist/agent/titles.d.ts +8 -0
- package/dist/agent/titles.js +23 -0
- package/dist/agent/titles.js.map +1 -0
- package/dist/agent/workspace.d.ts +60 -0
- package/dist/agent/workspace.js +156 -0
- package/dist/agent/workspace.js.map +1 -0
- package/dist/artifacts/publish.d.ts +94 -0
- package/dist/artifacts/publish.js +104 -0
- package/dist/artifacts/publish.js.map +1 -0
- package/dist/artifacts/store.d.ts +324 -0
- package/dist/artifacts/store.js +500 -0
- package/dist/artifacts/store.js.map +1 -0
- package/dist/auth/index.d.ts +13 -0
- package/dist/auth/index.js +10 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/manager.d.ts +83 -0
- package/dist/auth/manager.js +266 -0
- package/dist/auth/manager.js.map +1 -0
- package/dist/auth/oauth.d.ts +83 -0
- package/dist/auth/oauth.js +327 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/providers/account.d.ts +59 -0
- package/dist/auth/providers/account.js +282 -0
- package/dist/auth/providers/account.js.map +1 -0
- package/dist/auth/providers/anthropic.d.ts +24 -0
- package/dist/auth/providers/anthropic.js +209 -0
- package/dist/auth/providers/anthropic.js.map +1 -0
- package/dist/auth/providers/generic.d.ts +57 -0
- package/dist/auth/providers/generic.js +155 -0
- package/dist/auth/providers/generic.js.map +1 -0
- package/dist/auth/providers/official.d.ts +3 -0
- package/dist/auth/providers/official.js +90 -0
- package/dist/auth/providers/official.js.map +1 -0
- package/dist/auth/providers/ottoport.d.ts +3 -0
- package/dist/auth/providers/ottoport.js +60 -0
- package/dist/auth/providers/ottoport.js.map +1 -0
- package/dist/auth/store.d.ts +22 -0
- package/dist/auth/store.js +138 -0
- package/dist/auth/store.js.map +1 -0
- package/dist/auth/types.d.ts +167 -0
- package/dist/auth/types.js +16 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/config.d.ts +197 -0
- package/dist/config.js +195 -0
- package/dist/config.js.map +1 -0
- package/dist/core/errors.d.ts +46 -0
- package/dist/core/errors.js +83 -0
- package/dist/core/errors.js.map +1 -0
- package/dist/core/tokens.d.ts +12 -0
- package/dist/core/tokens.js +56 -0
- package/dist/core/tokens.js.map +1 -0
- package/dist/core/types.d.ts +91 -0
- package/dist/core/types.js +49 -0
- package/dist/core/types.js.map +1 -0
- package/dist/harness.d.ts +302 -0
- package/dist/harness.js +695 -0
- package/dist/harness.js.map +1 -0
- package/dist/index.d.ts +32 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/client.d.ts +55 -0
- package/dist/mcp/client.js +199 -0
- package/dist/mcp/client.js.map +1 -0
- package/dist/mcp/index.d.ts +13 -0
- package/dist/mcp/index.js +8 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/manager.d.ts +77 -0
- package/dist/mcp/manager.js +325 -0
- package/dist/mcp/manager.js.map +1 -0
- package/dist/mcp/oauth.d.ts +63 -0
- package/dist/mcp/oauth.js +302 -0
- package/dist/mcp/oauth.js.map +1 -0
- package/dist/mcp/protocol.d.ts +130 -0
- package/dist/mcp/protocol.js +14 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/registry.d.ts +52 -0
- package/dist/mcp/registry.js +100 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/registry.json +293 -0
- package/dist/mcp/secrets.d.ts +20 -0
- package/dist/mcp/secrets.js +75 -0
- package/dist/mcp/secrets.js.map +1 -0
- package/dist/mcp/transport.d.ts +51 -0
- package/dist/mcp/transport.js +158 -0
- package/dist/mcp/transport.js.map +1 -0
- package/dist/paths.d.ts +37 -0
- package/dist/paths.js +63 -0
- package/dist/paths.js.map +1 -0
- package/dist/plugins.d.ts +55 -0
- package/dist/plugins.js +201 -0
- package/dist/plugins.js.map +1 -0
- package/dist/providers/builtin.d.ts +23 -0
- package/dist/providers/builtin.js +141 -0
- package/dist/providers/builtin.js.map +1 -0
- package/dist/providers/catalog.d.ts +129 -0
- package/dist/providers/catalog.js +254 -0
- package/dist/providers/catalog.js.map +1 -0
- package/dist/providers/catalog.json +472 -0
- package/dist/providers/discovery.d.ts +16 -0
- package/dist/providers/discovery.js +161 -0
- package/dist/providers/discovery.js.map +1 -0
- package/dist/providers/http.d.ts +24 -0
- package/dist/providers/http.js +139 -0
- package/dist/providers/http.js.map +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/index.js +8 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/piai.d.ts +124 -0
- package/dist/providers/piai.js +551 -0
- package/dist/providers/piai.js.map +1 -0
- package/dist/providers/registry.d.ts +65 -0
- package/dist/providers/registry.js +195 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/providers/resilient.d.ts +46 -0
- package/dist/providers/resilient.js +117 -0
- package/dist/providers/resilient.js.map +1 -0
- package/dist/providers/types.d.ts +182 -0
- package/dist/providers/types.js +50 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/schedule/cron.d.ts +35 -0
- package/dist/schedule/cron.js +125 -0
- package/dist/schedule/cron.js.map +1 -0
- package/dist/schedule/scheduler.d.ts +87 -0
- package/dist/schedule/scheduler.js +237 -0
- package/dist/schedule/scheduler.js.map +1 -0
- package/dist/storage/kv.d.ts +56 -0
- package/dist/storage/kv.js +173 -0
- package/dist/storage/kv.js.map +1 -0
- package/dist/storage/migrate.d.ts +11 -0
- package/dist/storage/migrate.js +93 -0
- package/dist/storage/migrate.js.map +1 -0
- package/dist/storage/project.d.ts +9 -0
- package/dist/storage/project.js +57 -0
- package/dist/storage/project.js.map +1 -0
- package/dist/storage/records.d.ts +32 -0
- package/dist/storage/records.js +48 -0
- package/dist/storage/records.js.map +1 -0
- package/dist/sync/client.d.ts +79 -0
- package/dist/sync/client.js +118 -0
- package/dist/sync/client.js.map +1 -0
- package/dist/sync/mirror.d.ts +85 -0
- package/dist/sync/mirror.js +389 -0
- package/dist/sync/mirror.js.map +1 -0
- package/dist/sync/protocol.d.ts +67 -0
- package/dist/sync/protocol.js +16 -0
- package/dist/sync/protocol.js.map +1 -0
- package/dist/sync/settings.d.ts +56 -0
- package/dist/sync/settings.js +60 -0
- package/dist/sync/settings.js.map +1 -0
- package/dist/tools/builtin/artifact.d.ts +16 -0
- package/dist/tools/builtin/artifact.js +134 -0
- package/dist/tools/builtin/artifact.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +3 -0
- package/dist/tools/builtin/bash.js +142 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/fs.d.ts +19 -0
- package/dist/tools/builtin/fs.js +280 -0
- package/dist/tools/builtin/fs.js.map +1 -0
- package/dist/tools/builtin/index.d.ts +22 -0
- package/dist/tools/builtin/index.js +42 -0
- package/dist/tools/builtin/index.js.map +1 -0
- package/dist/tools/builtin/mcp-resource.d.ts +3 -0
- package/dist/tools/builtin/mcp-resource.js +220 -0
- package/dist/tools/builtin/mcp-resource.js.map +1 -0
- package/dist/tools/builtin/memory.d.ts +10 -0
- package/dist/tools/builtin/memory.js +76 -0
- package/dist/tools/builtin/memory.js.map +1 -0
- package/dist/tools/builtin/recall.d.ts +13 -0
- package/dist/tools/builtin/recall.js +163 -0
- package/dist/tools/builtin/recall.js.map +1 -0
- package/dist/tools/builtin/search.d.ts +3 -0
- package/dist/tools/builtin/search.js +240 -0
- package/dist/tools/builtin/search.js.map +1 -0
- package/dist/tools/builtin/skill.d.ts +10 -0
- package/dist/tools/builtin/skill.js +46 -0
- package/dist/tools/builtin/skill.js.map +1 -0
- package/dist/tools/builtin/task.d.ts +9 -0
- package/dist/tools/builtin/task.js +68 -0
- package/dist/tools/builtin/task.js.map +1 -0
- package/dist/tools/builtin/todo.d.ts +20 -0
- package/dist/tools/builtin/todo.js +63 -0
- package/dist/tools/builtin/todo.js.map +1 -0
- package/dist/tools/define.d.ts +19 -0
- package/dist/tools/define.js +39 -0
- package/dist/tools/define.js.map +1 -0
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.js +5 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +39 -0
- package/dist/tools/registry.js +101 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +112 -0
- package/dist/tools/types.js +22 -0
- package/dist/tools/types.js.map +1 -0
- package/dist/util/id.d.ts +9 -0
- package/dist/util/id.js +19 -0
- package/dist/util/id.js.map +1 -0
- package/dist/util/json.d.ts +25 -0
- package/dist/util/json.js +100 -0
- package/dist/util/json.js.map +1 -0
- package/dist/util/jwt.d.ts +74 -0
- package/dist/util/jwt.js +177 -0
- package/dist/util/jwt.js.map +1 -0
- package/dist/util/logger.d.ts +13 -0
- package/dist/util/logger.js +59 -0
- package/dist/util/logger.js.map +1 -0
- package/dist/util/queue.d.ts +26 -0
- package/dist/util/queue.js +106 -0
- package/dist/util/queue.js.map +1 -0
- package/dist/util/schema.d.ts +17 -0
- package/dist/util/schema.js +98 -0
- package/dist/util/schema.js.map +1 -0
- package/dist/util/shell.d.ts +20 -0
- package/dist/util/shell.js +24 -0
- package/dist/util/shell.js.map +1 -0
- package/official.json +4 -0
- package/package.json +38 -0
- package/skills/artifact-authoring/SKILL.md +81 -0
- package/skills/canvas/SKILL.md +85 -0
- package/skills/skill-authoring/SKILL.md +85 -0
|
@@ -0,0 +1,596 @@
|
|
|
1
|
+
import { titleFromMessage } from "./titles.js";
|
|
2
|
+
import { userPath } from "../paths.js";
|
|
3
|
+
import { copyFile, mkdir } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { shortId, sessionId as newSessionId } from "../util/id.js";
|
|
6
|
+
import { safeTruncate } from "./compaction.js";
|
|
7
|
+
import { JsonStore } from "../storage/kv.js";
|
|
8
|
+
import { migrate } from "../storage/migrate.js";
|
|
9
|
+
import { projectId } from "../storage/project.js";
|
|
10
|
+
import { asRecord, messageId, orderRecords } from "../storage/records.js";
|
|
11
|
+
import { asAuditEntry } from "./permissions.js";
|
|
12
|
+
import { asArtifactRevision } from "../artifacts/store.js";
|
|
13
|
+
/**
|
|
14
|
+
* Cap on how much of an archive a single `recall` loads. Generous enough that
|
|
15
|
+
* ordinary sessions read in full, small enough that a runaway one cannot
|
|
16
|
+
* exhaust memory.
|
|
17
|
+
*/
|
|
18
|
+
export const MAX_ARCHIVE_READ_BYTES = 8 * 1024 * 1024;
|
|
19
|
+
/**
|
|
20
|
+
* Cap on how much of a permission trail one read loads. Smaller than the
|
|
21
|
+
* archive's: these are short lines, and a page showing the trail wants the
|
|
22
|
+
* recent end of it, not a session's entire history of tool calls.
|
|
23
|
+
*/
|
|
24
|
+
export const MAX_DECISION_READ_BYTES = 1024 * 1024;
|
|
25
|
+
export class SessionStore {
|
|
26
|
+
kv;
|
|
27
|
+
legacyRoot;
|
|
28
|
+
ready;
|
|
29
|
+
deviceId;
|
|
30
|
+
/** Which project a session was found under, so a second read is a direct hit. */
|
|
31
|
+
located = new Map();
|
|
32
|
+
watchers = new Set();
|
|
33
|
+
constructor(root) {
|
|
34
|
+
this.kv = new JsonStore(root ?? userPath("storage"));
|
|
35
|
+
// Only the default root has a predecessor to import. A caller that named
|
|
36
|
+
// its own directory means that directory, not "that one plus history from
|
|
37
|
+
// somewhere else".
|
|
38
|
+
this.legacyRoot = root ? undefined : userPath("sessions");
|
|
39
|
+
}
|
|
40
|
+
get root() {
|
|
41
|
+
return this.kv.root;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Watch local writes. Returns the unsubscribe.
|
|
45
|
+
*
|
|
46
|
+
* Sync needs to know when to push, and the alternatives are worse: polling
|
|
47
|
+
* the directory turns an event into a delay, and calling a client from the
|
|
48
|
+
* write paths would put a network dependency inside the only thing here that
|
|
49
|
+
* must not be able to fail. A watcher is told what changed and decides for
|
|
50
|
+
* itself, so nothing above this file is reachable from below it.
|
|
51
|
+
*
|
|
52
|
+
* Listeners are called after the write has landed, and one that throws is
|
|
53
|
+
* ignored — a mirror falling over is not a reason to lose a transcript.
|
|
54
|
+
*/
|
|
55
|
+
watch(listener) {
|
|
56
|
+
this.watchers.add(listener);
|
|
57
|
+
return () => this.watchers.delete(listener);
|
|
58
|
+
}
|
|
59
|
+
announce(change) {
|
|
60
|
+
for (const watcher of this.watchers) {
|
|
61
|
+
try {
|
|
62
|
+
watcher(change);
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// Deliberately swallowed; see `watch`.
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/** A session's transcript as records, ordered and deduplicated. */
|
|
70
|
+
async recordsOf(id) {
|
|
71
|
+
await this.prepare();
|
|
72
|
+
return this.records(id);
|
|
73
|
+
}
|
|
74
|
+
/** A session's metadata, without being told which project it is under. */
|
|
75
|
+
async readMeta(id) {
|
|
76
|
+
return this.findMeta(id);
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Take records that were written somewhere else.
|
|
80
|
+
*
|
|
81
|
+
* Distinct from `appendMessage`, which mints an id, a seq and this device —
|
|
82
|
+
* exactly the three fields that must survive the trip for a merge to work.
|
|
83
|
+
* The log is append-only and `orderRecords` deduplicates on read, so writing
|
|
84
|
+
* a record that is already held costs a line and changes nothing, which is
|
|
85
|
+
* what makes a retried pull safe.
|
|
86
|
+
*/
|
|
87
|
+
async mergeRecords(id, incoming) {
|
|
88
|
+
if (incoming.length === 0)
|
|
89
|
+
return 0;
|
|
90
|
+
await this.prepare();
|
|
91
|
+
const held = new Set((await this.records(id)).map((record) => record.id));
|
|
92
|
+
const fresh = incoming.filter((record) => !held.has(record.id));
|
|
93
|
+
if (fresh.length === 0)
|
|
94
|
+
return 0;
|
|
95
|
+
await this.kv.append(["message", id], fresh);
|
|
96
|
+
return fresh.length;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Take metadata written somewhere else, if it is newer.
|
|
100
|
+
*
|
|
101
|
+
* Generation first, then wall clock. A generation is bumped by a rewrite, so
|
|
102
|
+
* a device that compacted a session wins over one that merely kept appending
|
|
103
|
+
* to it — no amount of clock skew should let a stale full transcript
|
|
104
|
+
* overwrite a summary that replaced it.
|
|
105
|
+
*/
|
|
106
|
+
async mergeMeta(incoming) {
|
|
107
|
+
await this.prepare();
|
|
108
|
+
const held = await this.findMeta(incoming.id);
|
|
109
|
+
if (held) {
|
|
110
|
+
const heldGen = held.gen ?? 0;
|
|
111
|
+
const incomingGen = incoming.gen ?? 0;
|
|
112
|
+
if (incomingGen < heldGen)
|
|
113
|
+
return false;
|
|
114
|
+
if (incomingGen === heldGen && incoming.updatedAt <= held.updatedAt)
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
await this.putMeta(incoming);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
/** Layout changes run once, on first use, before anything reads. */
|
|
121
|
+
prepare() {
|
|
122
|
+
this.ready ??= migrate(this.kv, this.legacyRoot).catch(() => { });
|
|
123
|
+
return this.ready;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* This machine's id.
|
|
127
|
+
*
|
|
128
|
+
* Two devices appending to one session need to be distinguishable, and the
|
|
129
|
+
* tiebreak has to survive restarts — so it is stored rather than generated
|
|
130
|
+
* per process.
|
|
131
|
+
*/
|
|
132
|
+
device() {
|
|
133
|
+
this.deviceId ??= (async () => {
|
|
134
|
+
const existing = await this.kv.read(["device"]);
|
|
135
|
+
if (existing?.id)
|
|
136
|
+
return existing.id;
|
|
137
|
+
const id = `dev_${shortId(6)}`;
|
|
138
|
+
await this.kv.write(["device"], { id, createdAt: Date.now() });
|
|
139
|
+
return id;
|
|
140
|
+
})();
|
|
141
|
+
return this.deviceId;
|
|
142
|
+
}
|
|
143
|
+
async projectOf(meta) {
|
|
144
|
+
const id = meta.projectId ?? (await projectId(meta.cwd || this.kv.root));
|
|
145
|
+
this.located.set(meta.id, id);
|
|
146
|
+
return id;
|
|
147
|
+
}
|
|
148
|
+
/** Find a session's metadata without being told which project it is in. */
|
|
149
|
+
async findMeta(id) {
|
|
150
|
+
await this.prepare();
|
|
151
|
+
const known = this.located.get(id);
|
|
152
|
+
if (known) {
|
|
153
|
+
const hit = await this.kv.read(["session", known, id]);
|
|
154
|
+
if (hit)
|
|
155
|
+
return hit;
|
|
156
|
+
this.located.delete(id);
|
|
157
|
+
}
|
|
158
|
+
for (const key of await this.kv.list(["session"])) {
|
|
159
|
+
if (key[key.length - 1] !== id)
|
|
160
|
+
continue;
|
|
161
|
+
const meta = await this.kv.read(key);
|
|
162
|
+
if (meta) {
|
|
163
|
+
this.located.set(id, key[1]);
|
|
164
|
+
return meta;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
return undefined;
|
|
168
|
+
}
|
|
169
|
+
async create(meta) {
|
|
170
|
+
await this.prepare();
|
|
171
|
+
await this.writeMeta(meta);
|
|
172
|
+
}
|
|
173
|
+
async writeMeta(meta) {
|
|
174
|
+
const stored = await this.putMeta(meta);
|
|
175
|
+
this.announce({ kind: "write", id: meta.id, projectId: stored.projectId, meta: stored });
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* The write itself, without telling anyone.
|
|
179
|
+
*
|
|
180
|
+
* Applying what a pull returned goes through here: announcing it would have
|
|
181
|
+
* the mirror push back what it had just received, and while the server
|
|
182
|
+
* deduplicates that, a loop that is merely harmless is still a loop.
|
|
183
|
+
*/
|
|
184
|
+
async putMeta(meta) {
|
|
185
|
+
await this.prepare();
|
|
186
|
+
const project = await this.projectOf(meta);
|
|
187
|
+
const stored = { ...meta, projectId: project };
|
|
188
|
+
await this.kv.write(["session", project, meta.id], stored);
|
|
189
|
+
await this.touchProject(project, meta.cwd);
|
|
190
|
+
return stored;
|
|
191
|
+
}
|
|
192
|
+
async touchProject(id, cwd) {
|
|
193
|
+
const existing = await this.kv.read(["project", id]);
|
|
194
|
+
const now = Date.now();
|
|
195
|
+
// Rewritten only when something changed: a project record touched on every
|
|
196
|
+
// metadata write would be the busiest file in the store for no gain.
|
|
197
|
+
if (existing && existing.worktree === cwd)
|
|
198
|
+
return;
|
|
199
|
+
await this.kv.write(["project", id], {
|
|
200
|
+
id,
|
|
201
|
+
vcs: id.startsWith("dir-") ? "none" : "git",
|
|
202
|
+
worktree: cwd,
|
|
203
|
+
createdAt: existing?.createdAt ?? now,
|
|
204
|
+
updatedAt: now,
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
async appendMessage(id, message) {
|
|
208
|
+
await this.prepare();
|
|
209
|
+
const meta = await this.findMeta(id);
|
|
210
|
+
const seq = (meta?.seq ?? (await this.records(id)).length) + 1;
|
|
211
|
+
const record = {
|
|
212
|
+
id: messageId(),
|
|
213
|
+
seq,
|
|
214
|
+
device: await this.device(),
|
|
215
|
+
at: Date.now(),
|
|
216
|
+
message,
|
|
217
|
+
};
|
|
218
|
+
await this.kv.append(["message", id], [record]);
|
|
219
|
+
if (meta)
|
|
220
|
+
await this.writeMeta({ ...meta, seq });
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Record one artifact revision on disk.
|
|
224
|
+
*
|
|
225
|
+
* A log rather than a document, for the same reason the transcript is one:
|
|
226
|
+
* a revision is a thing that happened, appending never rewrites what is
|
|
227
|
+
* already there, and a crashed process still leaves everything written
|
|
228
|
+
* before it. It also means the version history comes free — the file is the
|
|
229
|
+
* history, in order.
|
|
230
|
+
*
|
|
231
|
+
* Keyed by session alone, like `message` and `archive`, because an artifact
|
|
232
|
+
* belongs to the conversation that made it and is found the same way.
|
|
233
|
+
*
|
|
234
|
+
* This is what makes an artifact something other than a by-product of the
|
|
235
|
+
* transcript. A model's write was always recoverable, because the content is
|
|
236
|
+
* the argument of a tool call and tool calls are in the transcript. A
|
|
237
|
+
* revision a person made in the canvas is not a tool call and was therefore
|
|
238
|
+
* nowhere: a restart brought the model's version back as the newest one and
|
|
239
|
+
* said nothing about what it had replaced.
|
|
240
|
+
*/
|
|
241
|
+
async appendArtifactRevision(id, revision) {
|
|
242
|
+
await this.prepare();
|
|
243
|
+
// The same three fields `appendMessage` mints, and the same counter: the
|
|
244
|
+
// mirror tracks one watermark per session, so a revision that numbered
|
|
245
|
+
// itself in a private sequence would either be pushed forever or never.
|
|
246
|
+
const meta = await this.findMeta(id);
|
|
247
|
+
const seq = (meta?.seq ?? (await this.records(id)).length) + 1;
|
|
248
|
+
const stored = {
|
|
249
|
+
id: `art_${shortId(8)}`,
|
|
250
|
+
seq,
|
|
251
|
+
device: await this.device(),
|
|
252
|
+
...revision,
|
|
253
|
+
};
|
|
254
|
+
await this.kv.append(["artifact", id], [stored]);
|
|
255
|
+
if (meta)
|
|
256
|
+
await this.writeMeta({ ...meta, seq });
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* Take artifact revisions written on another device.
|
|
260
|
+
*
|
|
261
|
+
* The counterpart to `mergeRecords`, and deliberately its shape: dedupe on
|
|
262
|
+
* the record id, append what is new, and let the reader fold the file
|
|
263
|
+
* together. A revision already held costs a line and changes nothing, which
|
|
264
|
+
* is what makes a retried pull safe.
|
|
265
|
+
*/
|
|
266
|
+
async mergeArtifactRevisions(id, incoming) {
|
|
267
|
+
if (incoming.length === 0)
|
|
268
|
+
return 0;
|
|
269
|
+
await this.prepare();
|
|
270
|
+
const held = new Set((await this.artifactRevisions(id)).map((revision) => revision.id).filter(Boolean));
|
|
271
|
+
const fresh = incoming.filter((revision) => !revision.id || !held.has(revision.id));
|
|
272
|
+
if (fresh.length === 0)
|
|
273
|
+
return 0;
|
|
274
|
+
await this.kv.append(["artifact", id], fresh);
|
|
275
|
+
return fresh.length;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Sessions that have written an artifact, whether or not they are loaded.
|
|
279
|
+
*
|
|
280
|
+
* A directory read, not a transcript read. Artifacts belong to sessions and
|
|
281
|
+
* a session's store is memory, so "everything on this machine" used to mean
|
|
282
|
+
* "everything currently open" — which is a listing that changes depending on
|
|
283
|
+
* which tabs happen to be open, and that is not a listing anybody can trust.
|
|
284
|
+
* The logs are the durable record; this says which ones exist so a caller
|
|
285
|
+
* can fold the ones it wants without opening a session to ask.
|
|
286
|
+
*/
|
|
287
|
+
async artifactSessions() {
|
|
288
|
+
await this.prepare();
|
|
289
|
+
return (await this.kv.listLogs(["artifact"])).map((key) => key[key.length - 1]);
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Every artifact revision recorded for a session, oldest first.
|
|
293
|
+
*
|
|
294
|
+
* `maxBytes` reads the tail, for a caller that is building a listing rather
|
|
295
|
+
* than restoring a session: the newest lines are the ones a listing shows,
|
|
296
|
+
* and a log with a megabyte of superseded revisions in it should not cost a
|
|
297
|
+
* megabyte to summarise.
|
|
298
|
+
*/
|
|
299
|
+
async artifactRevisions(id, maxBytes) {
|
|
300
|
+
await this.prepare();
|
|
301
|
+
const lines = await this.kv.readLog(["artifact", id], maxBytes);
|
|
302
|
+
const out = [];
|
|
303
|
+
for (const line of lines) {
|
|
304
|
+
const revision = asArtifactRevision(line);
|
|
305
|
+
// A line this build cannot read is skipped rather than fatal: the file
|
|
306
|
+
// is append-only and shared with future versions, and refusing to load
|
|
307
|
+
// any of it because of one line would lose the rest.
|
|
308
|
+
if (revision)
|
|
309
|
+
out.push(revision);
|
|
310
|
+
}
|
|
311
|
+
return out;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Record one permission decision, with the session it happened in.
|
|
315
|
+
*
|
|
316
|
+
* Beside the transcript rather than in a file of its own somewhere else,
|
|
317
|
+
* because a decision is a thing that happened *in this conversation*: kept
|
|
318
|
+
* here it is found the way everything else about the session is found,
|
|
319
|
+
* deleted when the session is deleted, and readable next to the tool call it
|
|
320
|
+
* was about. A separate audit file is a second truth that has to be
|
|
321
|
+
* correlated by timestamp, and correlating by timestamp is how two records
|
|
322
|
+
* of the same event end up disagreeing.
|
|
323
|
+
*
|
|
324
|
+
* No seq and no device, unlike messages and artifact revisions: nothing
|
|
325
|
+
* merges this log. It stays on the machine that wrote it — see `SessionMirror`,
|
|
326
|
+
* which pushes messages and artifacts and deliberately not this.
|
|
327
|
+
*/
|
|
328
|
+
async appendDecision(id, entry) {
|
|
329
|
+
await this.prepare();
|
|
330
|
+
await this.kv.append(["decision", id], [entry]);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* A session's permission trail, oldest first.
|
|
334
|
+
*
|
|
335
|
+
* Bounded like the archive read: the trail grows for the life of a session —
|
|
336
|
+
* every tool call adds a line — and a long unattended run should not be able
|
|
337
|
+
* to make reading it the most expensive thing the harness does.
|
|
338
|
+
*/
|
|
339
|
+
async decisions(id, maxBytes = MAX_DECISION_READ_BYTES) {
|
|
340
|
+
await this.prepare();
|
|
341
|
+
const lines = await this.kv.readLog(["decision", id], maxBytes);
|
|
342
|
+
const out = [];
|
|
343
|
+
for (const line of lines) {
|
|
344
|
+
const entry = asAuditEntry(line);
|
|
345
|
+
if (entry)
|
|
346
|
+
out.push(entry);
|
|
347
|
+
}
|
|
348
|
+
return out;
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Append messages to the archive before they leave the live transcript.
|
|
352
|
+
*
|
|
353
|
+
* Compaction replaces history with a lossy summary; without this the
|
|
354
|
+
* originals would be unrecoverable — not just to the agent, but to anyone
|
|
355
|
+
* debugging the session afterwards. The archive is append-only and is never
|
|
356
|
+
* rewritten.
|
|
357
|
+
*/
|
|
358
|
+
async archiveMessages(id, entries) {
|
|
359
|
+
if (entries.length === 0)
|
|
360
|
+
return;
|
|
361
|
+
await this.prepare();
|
|
362
|
+
const archivedAt = Date.now();
|
|
363
|
+
await this.kv.append(["archive", id], entries.map((entry) => ({ seq: entry.seq, archivedAt, message: entry.message })));
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Read the archive, newest-biased and bounded.
|
|
367
|
+
*
|
|
368
|
+
* The archive is append-only and grows for the life of a session — every
|
|
369
|
+
* compaction and every oversized tool result adds to it. Reading all of it
|
|
370
|
+
* into memory to answer one `recall` would eventually be the most expensive
|
|
371
|
+
* thing the harness does, so only the tail is loaded past a threshold.
|
|
372
|
+
*/
|
|
373
|
+
async readArchive(id, maxBytes = MAX_ARCHIVE_READ_BYTES) {
|
|
374
|
+
await this.prepare();
|
|
375
|
+
const lines = await this.kv.readLog(["archive", id], maxBytes);
|
|
376
|
+
return lines.filter((line) => Boolean(line && line.message));
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Branch a session into a new one.
|
|
380
|
+
*
|
|
381
|
+
* The parent is never touched — that is the whole point. Exploring a
|
|
382
|
+
* different approach should not cost you the transcript that got you here,
|
|
383
|
+
* and mutating in place makes "go back and try the other thing" impossible.
|
|
384
|
+
*/
|
|
385
|
+
async fork(sourceId, opts = {}) {
|
|
386
|
+
const source = await this.load(sourceId);
|
|
387
|
+
if (!source)
|
|
388
|
+
return undefined;
|
|
389
|
+
const messages = opts.keepMessages === undefined
|
|
390
|
+
? source.messages
|
|
391
|
+
: safeTruncate(source.messages, opts.keepMessages);
|
|
392
|
+
const id = opts.newId ?? newSessionId();
|
|
393
|
+
const now = Date.now();
|
|
394
|
+
const meta = {
|
|
395
|
+
...source.meta,
|
|
396
|
+
id,
|
|
397
|
+
createdAt: now,
|
|
398
|
+
updatedAt: now,
|
|
399
|
+
title: opts.title ?? (source.meta.title ? `${source.meta.title} (fork)` : undefined),
|
|
400
|
+
// Cost and turns belong to the parent's history, not the branch's.
|
|
401
|
+
turns: 0,
|
|
402
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
403
|
+
costUsd: 0,
|
|
404
|
+
forkedFrom: sourceId,
|
|
405
|
+
forkedAt: messages.length,
|
|
406
|
+
gen: 0,
|
|
407
|
+
seq: messages.length,
|
|
408
|
+
};
|
|
409
|
+
await this.writeMeta(meta);
|
|
410
|
+
await this.replaceMessages(id, messages);
|
|
411
|
+
// The archive holds what compaction dropped, which is always older than
|
|
412
|
+
// the live transcript — so it is valid for any fork point.
|
|
413
|
+
const target = this.kv.log(["archive", id]);
|
|
414
|
+
await mkdir(path.dirname(target), { recursive: true });
|
|
415
|
+
await copyFile(this.kv.log(["archive", sourceId]), target).catch(() => { });
|
|
416
|
+
return { id, meta, messages };
|
|
417
|
+
}
|
|
418
|
+
/** Permanently remove a session and everything it recorded. */
|
|
419
|
+
async delete(id) {
|
|
420
|
+
const meta = await this.findMeta(id);
|
|
421
|
+
if (!meta)
|
|
422
|
+
return false;
|
|
423
|
+
const project = meta.projectId ?? (await this.projectOf(meta));
|
|
424
|
+
await this.kv.remove(["session", project, id]);
|
|
425
|
+
await this.kv.removeLog(["message", id]);
|
|
426
|
+
await this.kv.removeLog(["archive", id]);
|
|
427
|
+
await this.kv.removeLog(["decision", id]);
|
|
428
|
+
// Every log keyed by this session, or deleting it leaves the parts that
|
|
429
|
+
// were added after the delete path was written — which is how a deleted
|
|
430
|
+
// session keeps its artifact revisions on disk forever.
|
|
431
|
+
await this.kv.removeLog(["artifact", id]);
|
|
432
|
+
this.located.delete(id);
|
|
433
|
+
// Announced with the metadata read a moment ago, because a deletion has to
|
|
434
|
+
// travel as a fact of its own: a device that only hears silence still
|
|
435
|
+
// holds the session, and would hand it back on the next push.
|
|
436
|
+
this.announce({
|
|
437
|
+
kind: "delete",
|
|
438
|
+
id,
|
|
439
|
+
projectId: project,
|
|
440
|
+
meta: { ...meta, gen: (meta.gen ?? 0) + 1, updatedAt: Date.now() },
|
|
441
|
+
});
|
|
442
|
+
return true;
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Every session recorded in one tree, deleted.
|
|
446
|
+
*
|
|
447
|
+
* By working directory rather than by project id, because that is what the
|
|
448
|
+
* sidebar groups by and therefore what somebody is looking at when they ask
|
|
449
|
+
* for this. Deleting one at a time is the same work either way — there is no
|
|
450
|
+
* bulk primitive underneath — but each one still announces its own tombstone,
|
|
451
|
+
* so a device syncing with this one loses exactly the same set.
|
|
452
|
+
*
|
|
453
|
+
* Returns the ids that went, so a caller holding open tabs knows which of
|
|
454
|
+
* them are now pointing at nothing.
|
|
455
|
+
*/
|
|
456
|
+
async deleteIn(cwd) {
|
|
457
|
+
const all = await this.list(Number.MAX_SAFE_INTEGER);
|
|
458
|
+
const gone = [];
|
|
459
|
+
const projects = new Set();
|
|
460
|
+
for (const meta of all) {
|
|
461
|
+
if (meta.cwd !== cwd)
|
|
462
|
+
continue;
|
|
463
|
+
const project = meta.projectId ?? (await this.projectOf(meta));
|
|
464
|
+
if (await this.delete(meta.id)) {
|
|
465
|
+
gone.push(meta.id);
|
|
466
|
+
projects.add(project);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
// The project record too, once nothing is left under it. Asked of the
|
|
470
|
+
// store rather than of the metas just read, because a session file need
|
|
471
|
+
// not carry the project id — the key it is filed under is the truth. Kept
|
|
472
|
+
// when something is left: a repository and a worktree of it share a
|
|
473
|
+
// project id, so clearing one tree's sessions can leave the other's.
|
|
474
|
+
for (const project of projects) {
|
|
475
|
+
if ((await this.kv.list(["session", project])).length > 0)
|
|
476
|
+
continue;
|
|
477
|
+
await this.kv.remove(["project", project]);
|
|
478
|
+
}
|
|
479
|
+
return gone;
|
|
480
|
+
}
|
|
481
|
+
async rename(id, title) {
|
|
482
|
+
const meta = await this.findMeta(id);
|
|
483
|
+
if (!meta)
|
|
484
|
+
return false;
|
|
485
|
+
await this.writeMeta({ ...meta, title, updatedAt: Date.now() });
|
|
486
|
+
return true;
|
|
487
|
+
}
|
|
488
|
+
/** Sessions branched from a given one. */
|
|
489
|
+
async children(id) {
|
|
490
|
+
const all = await this.list(Number.MAX_SAFE_INTEGER);
|
|
491
|
+
return all.filter((meta) => meta.forkedFrom === id);
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* Delete old sessions.
|
|
495
|
+
*
|
|
496
|
+
* Nothing reclaimed these before, so a machine used daily accumulates every
|
|
497
|
+
* transcript and archive it ever produced. Returns the ids removed.
|
|
498
|
+
*/
|
|
499
|
+
async prune(opts = {}) {
|
|
500
|
+
const { maxAgeDays, keep } = opts;
|
|
501
|
+
if (maxAgeDays === undefined && keep === undefined)
|
|
502
|
+
return [];
|
|
503
|
+
const sessions = await this.list(Number.MAX_SAFE_INTEGER);
|
|
504
|
+
// `list` is newest-first, so anything past `keep` is the oldest.
|
|
505
|
+
const cutoff = maxAgeDays === undefined ? 0 : Date.now() - maxAgeDays * 86_400_000;
|
|
506
|
+
const doomed = sessions.filter((meta, index) => {
|
|
507
|
+
if (keep !== undefined && index >= keep)
|
|
508
|
+
return true;
|
|
509
|
+
if (maxAgeDays !== undefined && meta.updatedAt < cutoff)
|
|
510
|
+
return true;
|
|
511
|
+
return false;
|
|
512
|
+
});
|
|
513
|
+
const removed = [];
|
|
514
|
+
for (const meta of doomed) {
|
|
515
|
+
// A session we cannot delete is not worth failing startup over.
|
|
516
|
+
if (await this.delete(meta.id).catch(() => false))
|
|
517
|
+
removed.push(meta.id);
|
|
518
|
+
}
|
|
519
|
+
return removed;
|
|
520
|
+
}
|
|
521
|
+
/** Rewrite the transcript wholesale — used after compaction. */
|
|
522
|
+
async replaceMessages(id, messages) {
|
|
523
|
+
await this.prepare();
|
|
524
|
+
const device = await this.device();
|
|
525
|
+
const at = Date.now();
|
|
526
|
+
const records = messages.map((message, index) => ({
|
|
527
|
+
id: messageId(),
|
|
528
|
+
seq: index + 1,
|
|
529
|
+
device,
|
|
530
|
+
at,
|
|
531
|
+
message,
|
|
532
|
+
}));
|
|
533
|
+
await this.kv.replaceLog(["message", id], records);
|
|
534
|
+
const meta = await this.findMeta(id);
|
|
535
|
+
// A rewrite is a new generation: a device holding the pre-compaction log
|
|
536
|
+
// must not merge its appends back in on top of the summary.
|
|
537
|
+
if (meta)
|
|
538
|
+
await this.writeMeta({ ...meta, gen: (meta.gen ?? 0) + 1, seq: records.length });
|
|
539
|
+
}
|
|
540
|
+
async records(id) {
|
|
541
|
+
const lines = await this.kv.readLog(["message", id]);
|
|
542
|
+
const records = [];
|
|
543
|
+
lines.forEach((line, index) => {
|
|
544
|
+
const record = asRecord(line, index);
|
|
545
|
+
if (record)
|
|
546
|
+
records.push(record);
|
|
547
|
+
});
|
|
548
|
+
return orderRecords(records);
|
|
549
|
+
}
|
|
550
|
+
async load(id) {
|
|
551
|
+
const meta = await this.findMeta(id);
|
|
552
|
+
if (!meta)
|
|
553
|
+
return undefined;
|
|
554
|
+
const records = await this.records(id);
|
|
555
|
+
return { meta, messages: records.map((record) => record.message) };
|
|
556
|
+
}
|
|
557
|
+
async list(limit = 20, opts = {}) {
|
|
558
|
+
await this.prepare();
|
|
559
|
+
const prefix = opts.projectId ? ["session", opts.projectId] : ["session"];
|
|
560
|
+
const metas = [];
|
|
561
|
+
for (const key of await this.kv.list(prefix)) {
|
|
562
|
+
const meta = await this.kv.read(key);
|
|
563
|
+
if (meta) {
|
|
564
|
+
this.located.set(meta.id, key[1]);
|
|
565
|
+
metas.push(meta);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const recent = metas.sort((a, b) => b.updatedAt - a.updatedAt).slice(0, limit);
|
|
569
|
+
// Sessions recorded before titles existed have none, and a list of
|
|
570
|
+
// timestamps and hex tells nobody which session they want. Backfill from
|
|
571
|
+
// the transcript — only for what is actually being shown.
|
|
572
|
+
await Promise.all(recent.map((meta) => this.backfillTitle(meta)));
|
|
573
|
+
return recent;
|
|
574
|
+
}
|
|
575
|
+
async backfillTitle(meta) {
|
|
576
|
+
if (meta.title)
|
|
577
|
+
return;
|
|
578
|
+
for (const record of await this.records(meta.id)) {
|
|
579
|
+
if (record.message.role !== "user")
|
|
580
|
+
continue;
|
|
581
|
+
const title = titleFromMessage(record.message);
|
|
582
|
+
if (!title)
|
|
583
|
+
continue;
|
|
584
|
+
meta.title = title;
|
|
585
|
+
// Written back so the next listing is a plain metadata read again.
|
|
586
|
+
await this.writeMeta(meta).catch(() => { });
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
}
|
|
590
|
+
/** Most recently updated session for a directory, for `--continue`. */
|
|
591
|
+
async mostRecent(cwd) {
|
|
592
|
+
const all = await this.list(50);
|
|
593
|
+
return cwd ? all.find((meta) => meta.cwd === cwd) : all[0];
|
|
594
|
+
}
|
|
595
|
+
}
|
|
596
|
+
//# sourceMappingURL=store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../src/agent/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import type { ToolFilter } from "../tools/registry.ts";
|
|
2
|
+
/**
|
|
3
|
+
* A named subagent configuration. Subagents exist to keep expensive
|
|
4
|
+
* exploration out of the main context window: the parent sees only the final
|
|
5
|
+
* message, not the dozens of tool results that produced it.
|
|
6
|
+
*/
|
|
7
|
+
export interface SubagentDefinition {
|
|
8
|
+
name: string;
|
|
9
|
+
/** Shown to the model in the `task` tool description — this is what drives selection. */
|
|
10
|
+
description: string;
|
|
11
|
+
/** Replaces the base system prompt for this subagent. */
|
|
12
|
+
systemPrompt: string;
|
|
13
|
+
/** Model alias; falls back to the parent session's model. */
|
|
14
|
+
model?: string;
|
|
15
|
+
/** Restricts which tools the subagent may call. */
|
|
16
|
+
tools?: ToolFilter;
|
|
17
|
+
/** Hard cap on turns, to bound a runaway subagent. */
|
|
18
|
+
maxTurns?: number;
|
|
19
|
+
}
|
|
20
|
+
export declare const EXPLORE_AGENT: SubagentDefinition;
|
|
21
|
+
export declare const GENERAL_AGENT: SubagentDefinition;
|
|
22
|
+
export declare const BUILTIN_SUBAGENTS: SubagentDefinition[];
|
|
23
|
+
export declare class SubagentRegistry {
|
|
24
|
+
private readonly agents;
|
|
25
|
+
constructor(definitions?: SubagentDefinition[]);
|
|
26
|
+
register(def: SubagentDefinition): this;
|
|
27
|
+
get(name: string): SubagentDefinition | undefined;
|
|
28
|
+
list(): SubagentDefinition[];
|
|
29
|
+
summaries(): Array<{
|
|
30
|
+
name: string;
|
|
31
|
+
description: string;
|
|
32
|
+
}>;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load subagents from `agents/**/*.md`, the convention opencode uses:
|
|
36
|
+
* YAML frontmatter is the configuration, the body is the system prompt.
|
|
37
|
+
*
|
|
38
|
+
* A markdown file is a better home for a subagent than a JSON config field —
|
|
39
|
+
* the prompt is the bulk of the definition, and prompts do not survive being
|
|
40
|
+
* escaped into JSON strings with any readability.
|
|
41
|
+
*/
|
|
42
|
+
export declare function loadMarkdownSubagents(cwd: string, extraDirs?: string[]): Promise<SubagentDefinition[]>;
|
|
43
|
+
/** Parse one agent markdown file. Returns undefined if it cannot be selected. */
|
|
44
|
+
export declare function parseAgentMarkdown(raw: string, fallbackName: string, prefix?: string): SubagentDefinition | undefined;
|