opencode-workspace-mailbox 0.0.0-stage → 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/LICENSE +21 -0
- package/README.md +347 -2
- package/dist/config.d.ts +32 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/discovery.d.ts +41 -0
- package/dist/discovery.js +101 -0
- package/dist/discovery.js.map +1 -0
- package/dist/hash.d.ts +6 -0
- package/dist/hash.js +11 -0
- package/dist/hash.js.map +1 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +537 -0
- package/dist/index.js.map +1 -0
- package/dist/mailbox.d.ts +35 -0
- package/dist/mailbox.js +80 -0
- package/dist/mailbox.js.map +1 -0
- package/dist/parser.d.ts +17 -0
- package/dist/parser.js +78 -0
- package/dist/parser.js.map +1 -0
- package/dist/paths.d.ts +8 -0
- package/dist/paths.js +34 -0
- package/dist/paths.js.map +1 -0
- package/dist/prompt.d.ts +3 -0
- package/dist/prompt.js +15 -0
- package/dist/prompt.js.map +1 -0
- package/dist/state.d.ts +27 -0
- package/dist/state.js +94 -0
- package/dist/state.js.map +1 -0
- package/dist/store.d.ts +34 -0
- package/dist/store.js +55 -0
- package/dist/store.js.map +1 -0
- package/package.json +46 -4
- package/src/config.ts +133 -0
- package/src/discovery.ts +133 -0
- package/src/hash.ts +12 -0
- package/src/index.ts +589 -0
- package/src/mailbox.ts +105 -0
- package/src/parser.ts +103 -0
- package/src/paths.ts +38 -0
- package/src/prompt.ts +20 -0
- package/src/state.ts +119 -0
- package/src/store.ts +91 -0
package/dist/hash.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hash.js","sourceRoot":"","sources":["../src/hash.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAExC,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,EAAE,CAAA;AAChE,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,KAAsD;IAChF,MAAM,MAAM,GAAG,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,CAAA;IAC7C,MAAM,KAAK,GAAG,gBAAgB,CAAC,KAAK,CAAC,KAAK,CAAC,CAAA;IAC3C,MAAM,IAAI,GAAG,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;IACzC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,GAAG,MAAM,KAAK,KAAK,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAA;AAC/F,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { type Plugin } from "@opencode-ai/plugin";
|
|
2
|
+
import { normalizeConfig, type MailboxConfig, type NormalizedConfig } from "./config.js";
|
|
3
|
+
import { discoverTier, routeRecipient, type TierContext } from "./discovery.js";
|
|
4
|
+
import { messageHash, normalizeForHash } from "./hash.js";
|
|
5
|
+
import { type AckRequest, type AckResult, type ReadResult, type SendRequest, type SendResult } from "./mailbox.js";
|
|
6
|
+
import { assertInside, isSafeRecipient, mailboxFile, PathSafetyError, resolveInside } from "./paths.js";
|
|
7
|
+
import { isOpen, parseMailbox, type MailboxMessage } from "./parser.js";
|
|
8
|
+
import { buildCapNotice, buildIdlePrompt } from "./prompt.js";
|
|
9
|
+
import { emptyState, StateStore, type MailboxState, type SessionState } from "./state.js";
|
|
10
|
+
import { createFileStore, type MailboxStore } from "./store.js";
|
|
11
|
+
/**
|
|
12
|
+
* opencode-workspace-mailbox plugin entry — makes a session aware of its per-project
|
|
13
|
+
* mailbox and auto-handles OPEN messages on idle, with loop guards.
|
|
14
|
+
*
|
|
15
|
+
* On the `session.idle` event we read the project's mailbox file, find OPEN
|
|
16
|
+
* messages we have not yet prompted for (and did not write ourselves), and —
|
|
17
|
+
* subject to a per-human-turn round cap and a cooldown — dispatch a single
|
|
18
|
+
* prompt asking the agent to handle them. The message is appended-only; the
|
|
19
|
+
* only permitted edit is flipping a `**Status:**` line to DONE via the
|
|
20
|
+
* `mailbox_ack` tool.
|
|
21
|
+
*/
|
|
22
|
+
export declare const server: Plugin;
|
|
23
|
+
export { normalizeConfig, parseMailbox, isOpen, messageHash, normalizeForHash, isSafeRecipient, resolveInside, assertInside, mailboxFile, PathSafetyError, emptyState, StateStore, buildIdlePrompt, buildCapNotice, discoverTier, routeRecipient, createFileStore, };
|
|
24
|
+
export type { NormalizedConfig, MailboxConfig, MailboxMessage, SendRequest, SendResult, ReadResult, AckRequest, AckResult, SessionState, MailboxState, TierContext, MailboxStore, };
|
|
25
|
+
declare const _default: {
|
|
26
|
+
id: string;
|
|
27
|
+
server: Plugin;
|
|
28
|
+
};
|
|
29
|
+
export default _default;
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,537 @@
|
|
|
1
|
+
import { tool } from "@opencode-ai/plugin";
|
|
2
|
+
import { existsSync, readdirSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { normalizeConfig } from "./config.js";
|
|
5
|
+
import { discoverTier, routeRecipient } from "./discovery.js";
|
|
6
|
+
import { messageHash, normalizeForHash } from "./hash.js";
|
|
7
|
+
import { assertInside, isSafeRecipient, mailboxFile, PathSafetyError, resolveInside } from "./paths.js";
|
|
8
|
+
import { isOpen, parseMailbox } from "./parser.js";
|
|
9
|
+
import { buildCapNotice, buildIdlePrompt } from "./prompt.js";
|
|
10
|
+
import { emptyState, StateStore } from "./state.js";
|
|
11
|
+
import { createFileStore } from "./store.js";
|
|
12
|
+
/**
|
|
13
|
+
* opencode-workspace-mailbox plugin entry — makes a session aware of its per-project
|
|
14
|
+
* mailbox and auto-handles OPEN messages on idle, with loop guards.
|
|
15
|
+
*
|
|
16
|
+
* On the `session.idle` event we read the project's mailbox file, find OPEN
|
|
17
|
+
* messages we have not yet prompted for (and did not write ourselves), and —
|
|
18
|
+
* subject to a per-human-turn round cap and a cooldown — dispatch a single
|
|
19
|
+
* prompt asking the agent to handle them. The message is appended-only; the
|
|
20
|
+
* only permitted edit is flipping a `**Status:**` line to DONE via the
|
|
21
|
+
* `mailbox_ack` tool.
|
|
22
|
+
*/
|
|
23
|
+
export const server = async (input, options) => {
|
|
24
|
+
const cfg = normalizeConfig(options, input.directory);
|
|
25
|
+
const store = new StateStore(cfg.stateFile);
|
|
26
|
+
const { client } = input;
|
|
27
|
+
// Tier is derived from the folder tree unless the config pins a mailboxDir.
|
|
28
|
+
const tier = cfg.explicitMailboxDir
|
|
29
|
+
? discoverTier(input.directory, { mailboxDir: cfg.mailboxDir, project: cfg.project })
|
|
30
|
+
: discoverTier(input.directory);
|
|
31
|
+
// One store per mailbox directory; the backend is swappable behind MailboxStore.
|
|
32
|
+
const stores = new Map();
|
|
33
|
+
function storeFor(dir) {
|
|
34
|
+
const key = path.resolve(dir);
|
|
35
|
+
let found = stores.get(key);
|
|
36
|
+
if (!found) {
|
|
37
|
+
found = createFileStore(key);
|
|
38
|
+
stores.set(key, found);
|
|
39
|
+
}
|
|
40
|
+
return found;
|
|
41
|
+
}
|
|
42
|
+
const own = () => storeFor(tier.mailboxDir);
|
|
43
|
+
// Dynamic discovery creates the inboxes a tier is supposed to have.
|
|
44
|
+
try {
|
|
45
|
+
own().ensure(tier.project);
|
|
46
|
+
if (tier.tier === "account" && tier.rootMailboxDir && tier.accountName) {
|
|
47
|
+
storeFor(tier.rootMailboxDir).ensure(tier.accountName);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.error(`[opencode-workspace-mailbox] inbox bootstrap failed: ${String(error)}`);
|
|
52
|
+
}
|
|
53
|
+
const MAX_ENTRIES = 500;
|
|
54
|
+
/**
|
|
55
|
+
* How long a plugin-dispatched prompt stays "pending" while waiting for its
|
|
56
|
+
* own `chat.message` echo. A prompt that never arrives must not suppress the
|
|
57
|
+
* idle handler forever.
|
|
58
|
+
*/
|
|
59
|
+
const PENDING_TTL_MS = 120_000;
|
|
60
|
+
const pendingPluginPrompts = new Map();
|
|
61
|
+
function pendingCount(sessionID) {
|
|
62
|
+
const entry = pendingPluginPrompts.get(sessionID);
|
|
63
|
+
if (!entry)
|
|
64
|
+
return 0;
|
|
65
|
+
if (Date.now() - entry.at > PENDING_TTL_MS) {
|
|
66
|
+
pendingPluginPrompts.delete(sessionID);
|
|
67
|
+
return 0;
|
|
68
|
+
}
|
|
69
|
+
return entry.count;
|
|
70
|
+
}
|
|
71
|
+
function recordHashes(list, hashes) {
|
|
72
|
+
for (const hash of hashes) {
|
|
73
|
+
if (!list.includes(hash))
|
|
74
|
+
list.push(hash);
|
|
75
|
+
}
|
|
76
|
+
if (list.length > MAX_ENTRIES)
|
|
77
|
+
list.splice(0, list.length - MAX_ENTRIES);
|
|
78
|
+
}
|
|
79
|
+
function dispatchPrompt(sessionID, text) {
|
|
80
|
+
pendingPluginPrompts.set(sessionID, { count: pendingCount(sessionID) + 1, at: Date.now() });
|
|
81
|
+
const body = { parts: [{ type: "text", text }] };
|
|
82
|
+
const promise = client.session.promptAsync
|
|
83
|
+
? client.session.promptAsync({ path: { id: sessionID }, body })
|
|
84
|
+
: client.session.prompt({ path: { id: sessionID }, body });
|
|
85
|
+
promise.catch((error) => {
|
|
86
|
+
const remaining = pendingCount(sessionID);
|
|
87
|
+
if (remaining > 0)
|
|
88
|
+
pendingPluginPrompts.set(sessionID, { count: remaining - 1, at: Date.now() });
|
|
89
|
+
console.error(`[opencode-workspace-mailbox] prompt dispatch failed: ${String(error)}`);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function notify(sessionID, message) {
|
|
93
|
+
try {
|
|
94
|
+
const promise = client.tui.showToast({ body: { message, variant: "info" } });
|
|
95
|
+
promise.catch(() => { });
|
|
96
|
+
}
|
|
97
|
+
catch {
|
|
98
|
+
// best-effort; never break the session over a toast
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const sessions = new Map();
|
|
102
|
+
/** Prefix applied to every session this plugin creates, so other instances can spot it. */
|
|
103
|
+
const SPAWN_TITLE_PREFIX = "mailbox:";
|
|
104
|
+
function track(sessionID, busy, title) {
|
|
105
|
+
if (!sessionID)
|
|
106
|
+
return;
|
|
107
|
+
const entry = sessions.get(sessionID) ?? { lastSeen: 0, busy: false };
|
|
108
|
+
entry.lastSeen = Date.now();
|
|
109
|
+
if (busy !== undefined)
|
|
110
|
+
entry.busy = busy;
|
|
111
|
+
if (title)
|
|
112
|
+
entry.title = title;
|
|
113
|
+
sessions.set(sessionID, entry);
|
|
114
|
+
}
|
|
115
|
+
function restoreBudget(sessionID) {
|
|
116
|
+
const state = store.read();
|
|
117
|
+
const session = state.sessions[sessionID] ?? { autoRounds: 0, lastPromptAt: 0 };
|
|
118
|
+
session.autoRounds = 0;
|
|
119
|
+
session.noticeKey = undefined;
|
|
120
|
+
state.sessions[sessionID] = session;
|
|
121
|
+
store.write(state);
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Shared decision path for both triggers: the idle transition and the poll
|
|
125
|
+
* timer. `poll` additionally refuses to interrupt a busy session.
|
|
126
|
+
*/
|
|
127
|
+
async function consider(sessionID, source) {
|
|
128
|
+
if (!cfg.enabled)
|
|
129
|
+
return;
|
|
130
|
+
if (pendingCount(sessionID) > 0)
|
|
131
|
+
return;
|
|
132
|
+
if (source === "poll" && sessions.get(sessionID)?.busy)
|
|
133
|
+
return;
|
|
134
|
+
const open = own().listOpen(tier.project);
|
|
135
|
+
const state = store.read();
|
|
136
|
+
const session = state.sessions[sessionID] ?? { autoRounds: 0, lastPromptAt: 0 };
|
|
137
|
+
if (open.length === 0) {
|
|
138
|
+
// Inbox drained — a later delivery starts with a full budget.
|
|
139
|
+
if (session.autoRounds !== 0 || session.noticeKey !== undefined) {
|
|
140
|
+
session.autoRounds = 0;
|
|
141
|
+
session.noticeKey = undefined;
|
|
142
|
+
state.sessions[sessionID] = session;
|
|
143
|
+
store.write(state);
|
|
144
|
+
}
|
|
145
|
+
return;
|
|
146
|
+
}
|
|
147
|
+
const fresh = open.filter((m) => !state.prompted.includes(m.hash) && !state.ownWrites.includes(m.hash));
|
|
148
|
+
if (fresh.length === 0)
|
|
149
|
+
return;
|
|
150
|
+
if (session.autoRounds >= cfg.maxAutoRounds) {
|
|
151
|
+
// One notice per distinct pending set: repeated triggers must not turn
|
|
152
|
+
// into a toast loop.
|
|
153
|
+
const noticeKey = fresh
|
|
154
|
+
.map((m) => m.hash)
|
|
155
|
+
.sort()
|
|
156
|
+
.join(",");
|
|
157
|
+
if (session.noticeKey === noticeKey)
|
|
158
|
+
return;
|
|
159
|
+
const now = Date.now();
|
|
160
|
+
if (session.noticeKey !== undefined && now - (session.lastNoticeAt ?? 0) < cfg.cooldownMs)
|
|
161
|
+
return;
|
|
162
|
+
session.noticeKey = noticeKey;
|
|
163
|
+
session.lastNoticeAt = now;
|
|
164
|
+
state.sessions[sessionID] = session;
|
|
165
|
+
store.write(state);
|
|
166
|
+
notify(sessionID, buildCapNotice(tier.project, fresh.length, cfg.maxAutoRounds));
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
if (Date.now() - session.lastPromptAt < cfg.cooldownMs)
|
|
170
|
+
return;
|
|
171
|
+
recordHashes(state.prompted, fresh.map((m) => m.hash));
|
|
172
|
+
session.autoRounds += 1;
|
|
173
|
+
session.lastPromptAt = Date.now();
|
|
174
|
+
session.noticeKey = undefined;
|
|
175
|
+
state.sessions[sessionID] = session;
|
|
176
|
+
store.write(state);
|
|
177
|
+
dispatchPrompt(sessionID, buildIdlePrompt(tier.project, fresh));
|
|
178
|
+
}
|
|
179
|
+
/** The most recently active session that is not mid-turn, if any. */
|
|
180
|
+
function wakeTarget() {
|
|
181
|
+
let best;
|
|
182
|
+
for (const [id, entry] of sessions) {
|
|
183
|
+
if (entry.busy)
|
|
184
|
+
continue;
|
|
185
|
+
if (!best || entry.lastSeen > best.at)
|
|
186
|
+
best = { id, at: entry.lastSeen };
|
|
187
|
+
}
|
|
188
|
+
return best?.id;
|
|
189
|
+
}
|
|
190
|
+
async function poll() {
|
|
191
|
+
if (!cfg.enabled)
|
|
192
|
+
return;
|
|
193
|
+
const sessionID = wakeTarget();
|
|
194
|
+
if (!sessionID)
|
|
195
|
+
return;
|
|
196
|
+
try {
|
|
197
|
+
await consider(sessionID, "poll");
|
|
198
|
+
}
|
|
199
|
+
catch (error) {
|
|
200
|
+
console.error(`[opencode-workspace-mailbox] poll error: ${String(error)}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
// Opt-in wake path: an idle transition only fires on a *change*, so a session
|
|
204
|
+
// that is already idle would never notice a message written by another
|
|
205
|
+
// project. The timer makes delivery independent of session transitions.
|
|
206
|
+
let timer;
|
|
207
|
+
if (cfg.wake) {
|
|
208
|
+
timer = setInterval(() => {
|
|
209
|
+
void poll();
|
|
210
|
+
}, cfg.pollMs);
|
|
211
|
+
timer.unref?.();
|
|
212
|
+
}
|
|
213
|
+
function sameDirectory(candidate) {
|
|
214
|
+
if (!candidate)
|
|
215
|
+
return false;
|
|
216
|
+
const rel = path.relative(path.resolve(input.directory), path.resolve(candidate));
|
|
217
|
+
return rel === "";
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* A resumed session emits no creation event, so seed the registry from the
|
|
221
|
+
* server once at startup. `lastSeen` uses each session's own update time, so a
|
|
222
|
+
* stale session can never outrank one that is actually in use.
|
|
223
|
+
*/
|
|
224
|
+
async function seedSessions() {
|
|
225
|
+
if (!cfg.wake)
|
|
226
|
+
return;
|
|
227
|
+
try {
|
|
228
|
+
const result = await client.session.list({ query: { directory: input.directory } });
|
|
229
|
+
const list = result.data;
|
|
230
|
+
for (const entry of list ?? []) {
|
|
231
|
+
if (!entry?.id || !sameDirectory(entry.directory))
|
|
232
|
+
continue;
|
|
233
|
+
if (sessions.has(entry.id))
|
|
234
|
+
continue;
|
|
235
|
+
sessions.set(entry.id, { lastSeen: entry.time?.updated ?? 0, busy: false, title: entry.title });
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
catch {
|
|
239
|
+
// Session registry unavailable — chat.message and idle events still
|
|
240
|
+
// register sessions as they are used.
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
void seedSessions();
|
|
244
|
+
/**
|
|
245
|
+
* Recipient directory for spawn-on-send: an explicit `projectDirs` entry first,
|
|
246
|
+
* then the workspace root itself for `workspace`, then a sibling of `mailboxDir`.
|
|
247
|
+
* Anything unresolvable is a documented no-op, never a guess.
|
|
248
|
+
*/
|
|
249
|
+
/** Bounded search for a child directory by basename (buckets like `tools/<repo>`). */
|
|
250
|
+
function findChildDir(root, name, depth = 3) {
|
|
251
|
+
if (!existsSync(root))
|
|
252
|
+
return undefined;
|
|
253
|
+
const target = name.toLowerCase();
|
|
254
|
+
const skip = new Set(["node_modules", "dist", "build", "bin", "obj", "target", "out"]);
|
|
255
|
+
const queue = [{ dir: root, level: 0 }];
|
|
256
|
+
while (queue.length > 0) {
|
|
257
|
+
const current = queue.shift();
|
|
258
|
+
if (current.level > 0 && path.basename(current.dir).toLowerCase() === target)
|
|
259
|
+
return current.dir;
|
|
260
|
+
if (current.level >= depth)
|
|
261
|
+
continue;
|
|
262
|
+
let entries;
|
|
263
|
+
try {
|
|
264
|
+
entries = readdirSync(current.dir, { withFileTypes: true });
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
continue;
|
|
268
|
+
}
|
|
269
|
+
for (const entry of entries) {
|
|
270
|
+
if (!entry.isDirectory())
|
|
271
|
+
continue;
|
|
272
|
+
if (entry.name.startsWith(".") || skip.has(entry.name.toLowerCase()))
|
|
273
|
+
continue;
|
|
274
|
+
queue.push({ dir: path.join(current.dir, entry.name), level: current.level + 1 });
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return undefined;
|
|
278
|
+
}
|
|
279
|
+
function resolveProjectDir(to) {
|
|
280
|
+
const mapped = cfg.projectDirs[to];
|
|
281
|
+
if (mapped)
|
|
282
|
+
return mapped;
|
|
283
|
+
const tierRoot = path.dirname(path.resolve(tier.mailboxDir));
|
|
284
|
+
if (to === "workspace")
|
|
285
|
+
return existsSync(tierRoot) ? tierRoot : undefined;
|
|
286
|
+
// Escalating to an account spawns that account's directory, not a sibling file.
|
|
287
|
+
if (tier.rootDir && to !== tier.project) {
|
|
288
|
+
const account = path.join(tier.rootDir, to);
|
|
289
|
+
if (existsSync(account))
|
|
290
|
+
return account;
|
|
291
|
+
}
|
|
292
|
+
const sibling = path.join(tierRoot, to);
|
|
293
|
+
if (existsSync(sibling))
|
|
294
|
+
return sibling;
|
|
295
|
+
// Bucket layouts: `<account>/tools/<repo>`, `<account>/labs/<repo>`, ...
|
|
296
|
+
return findChildDir(tierRoot, to);
|
|
297
|
+
}
|
|
298
|
+
async function findSession(directory) {
|
|
299
|
+
try {
|
|
300
|
+
const result = await client.session.list({ query: { directory } });
|
|
301
|
+
const list = result.data ?? [];
|
|
302
|
+
const wanted = path.resolve(directory);
|
|
303
|
+
const candidates = list.filter((entry) => entry.id && entry.directory && path.relative(wanted, path.resolve(entry.directory)) === "");
|
|
304
|
+
if (candidates.length === 0)
|
|
305
|
+
return undefined;
|
|
306
|
+
candidates.sort((a, b) => (b.time?.updated ?? 0) - (a.time?.updated ?? 0));
|
|
307
|
+
return candidates[0].id;
|
|
308
|
+
}
|
|
309
|
+
catch {
|
|
310
|
+
return undefined;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Create a session in the recipient's directory. Guards, in order: feature
|
|
315
|
+
* flag, self-send, cascade (a session this plugin spawned never spawns),
|
|
316
|
+
* duplicate message, cooldown, per-turn cap, then directory resolution.
|
|
317
|
+
*/
|
|
318
|
+
async function maybeSpawn(sessionID, to, hash) {
|
|
319
|
+
if (!cfg.spawnOnSend)
|
|
320
|
+
return { spawned: false, detail: "spawnOnSend is off" };
|
|
321
|
+
if (to === tier.project)
|
|
322
|
+
return { spawned: false, detail: "recipient is this project" };
|
|
323
|
+
const state = store.read();
|
|
324
|
+
const currentTitle = sessions.get(sessionID)?.title;
|
|
325
|
+
if (currentTitle?.startsWith(SPAWN_TITLE_PREFIX) || state.spawnedSessions.includes(sessionID)) {
|
|
326
|
+
return { spawned: false, detail: "loop guard: this session was spawned" };
|
|
327
|
+
}
|
|
328
|
+
if (state.spawnedHashes.includes(hash)) {
|
|
329
|
+
return { spawned: false, detail: "already spawned for this message" };
|
|
330
|
+
}
|
|
331
|
+
const now = Date.now();
|
|
332
|
+
if (now - (state.lastSpawnAt ?? 0) < cfg.spawnCooldownMs) {
|
|
333
|
+
return { spawned: false, detail: `spawn cooldown (${cfg.spawnCooldownMs} ms)` };
|
|
334
|
+
}
|
|
335
|
+
const session = state.sessions[sessionID] ?? { autoRounds: 0, lastPromptAt: 0 };
|
|
336
|
+
if ((session.spawnsThisTurn ?? 0) >= cfg.maxSpawnsPerTurn) {
|
|
337
|
+
return { spawned: false, detail: `max ${cfg.maxSpawnsPerTurn} spawn(s) per turn reached` };
|
|
338
|
+
}
|
|
339
|
+
const directory = resolveProjectDir(to);
|
|
340
|
+
if (!directory) {
|
|
341
|
+
return { spawned: false, detail: `no directory known for "${to}" (set projectDirs)` };
|
|
342
|
+
}
|
|
343
|
+
const existing = await findSession(directory);
|
|
344
|
+
if (existing)
|
|
345
|
+
return { spawned: false, detail: `session already exists (${existing})` };
|
|
346
|
+
try {
|
|
347
|
+
const created = await client.session.create({
|
|
348
|
+
query: { directory },
|
|
349
|
+
body: { title: `${SPAWN_TITLE_PREFIX} ${to}` },
|
|
350
|
+
});
|
|
351
|
+
const id = created.data?.id;
|
|
352
|
+
if (!id)
|
|
353
|
+
return { spawned: false, detail: "session.create returned no id" };
|
|
354
|
+
session.spawnsThisTurn = (session.spawnsThisTurn ?? 0) + 1;
|
|
355
|
+
state.sessions[sessionID] = session;
|
|
356
|
+
state.lastSpawnAt = now;
|
|
357
|
+
recordHashes(state.spawnedSessions, [id]);
|
|
358
|
+
recordHashes(state.spawnedHashes, [hash]);
|
|
359
|
+
store.write(state);
|
|
360
|
+
track(id, false, `${SPAWN_TITLE_PREFIX} ${to}`);
|
|
361
|
+
return { spawned: true, detail: `spawned session ${id} in ${directory}` };
|
|
362
|
+
}
|
|
363
|
+
catch (error) {
|
|
364
|
+
return { spawned: false, detail: `session.create failed: ${String(error)}` };
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
return {
|
|
368
|
+
event: async ({ event }) => {
|
|
369
|
+
if (!cfg.enabled)
|
|
370
|
+
return;
|
|
371
|
+
try {
|
|
372
|
+
if (event.type === "session.idle") {
|
|
373
|
+
track(event.properties.sessionID, false);
|
|
374
|
+
await consider(event.properties.sessionID, "idle");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
377
|
+
if (event.type === "session.status") {
|
|
378
|
+
track(event.properties.sessionID, event.properties.status.type !== "idle");
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
if (event.type === "session.created" || event.type === "session.updated") {
|
|
382
|
+
const info = event.properties.info;
|
|
383
|
+
if (info?.id && sameDirectory(info.directory))
|
|
384
|
+
track(info.id, undefined, info.title);
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
catch (error) {
|
|
388
|
+
console.error(`[opencode-workspace-mailbox] event handler error: ${String(error)}`);
|
|
389
|
+
}
|
|
390
|
+
},
|
|
391
|
+
dispose: async () => {
|
|
392
|
+
if (timer) {
|
|
393
|
+
clearInterval(timer);
|
|
394
|
+
timer = undefined;
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
"chat.message": async ({ sessionID }) => {
|
|
398
|
+
try {
|
|
399
|
+
track(sessionID);
|
|
400
|
+
const count = pendingCount(sessionID);
|
|
401
|
+
if (count > 0) {
|
|
402
|
+
pendingPluginPrompts.set(sessionID, { count: count - 1, at: Date.now() });
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
const state = store.read();
|
|
406
|
+
state.sessions[sessionID] = { autoRounds: 0, lastPromptAt: 0 };
|
|
407
|
+
store.write(state);
|
|
408
|
+
}
|
|
409
|
+
catch (error) {
|
|
410
|
+
console.error(`[opencode-workspace-mailbox] chat.message handler error: ${String(error)}`);
|
|
411
|
+
}
|
|
412
|
+
},
|
|
413
|
+
tool: {
|
|
414
|
+
mailbox_read: tool({
|
|
415
|
+
description: "Read the OPEN mailbox messages for a project. Returns each message's header, hash, " +
|
|
416
|
+
"topic, and body so the agent can decide how to handle them. Pass a `project` to read a " +
|
|
417
|
+
"different recipient, or omit it to read the current project.",
|
|
418
|
+
args: {
|
|
419
|
+
project: tool.schema
|
|
420
|
+
.string()
|
|
421
|
+
.optional()
|
|
422
|
+
.describe("Project/recipient name (lowercase kebab-case). Defaults to the current project."),
|
|
423
|
+
},
|
|
424
|
+
async execute(args) {
|
|
425
|
+
const project = args.project ?? tier.project;
|
|
426
|
+
if (!isSafeRecipient(project)) {
|
|
427
|
+
return { title: "mailbox_read", output: `Invalid project name "${project}": must be lowercase kebab-case.` };
|
|
428
|
+
}
|
|
429
|
+
const route = routeRecipient(project, tier);
|
|
430
|
+
const target = storeFor(route.mailboxDir);
|
|
431
|
+
const open = target.listOpen(route.project);
|
|
432
|
+
if (open.length === 0) {
|
|
433
|
+
return { title: "mailbox_read", output: `No OPEN messages for ${project}.`, metadata: { count: 0 } };
|
|
434
|
+
}
|
|
435
|
+
const file = mailboxFile(route.mailboxDir, route.project);
|
|
436
|
+
const lines = open.map((m) => `### ${m.header}\nHash: ${m.hash}\nTopic: ${m.topic}\n\n${m.body}`);
|
|
437
|
+
const output = `${project} (${file}): ${open.length} OPEN message(s)\n\n${lines.join("\n\n")}`;
|
|
438
|
+
return { title: "mailbox_read", output, metadata: { count: open.length } };
|
|
439
|
+
},
|
|
440
|
+
}),
|
|
441
|
+
mailbox_send: tool({
|
|
442
|
+
description: "Append a message to a recipient's mailbox file. Creates the recipient file if it does " +
|
|
443
|
+
"not exist. The message is appended (never rewrites history); by default it is OPEN.",
|
|
444
|
+
args: {
|
|
445
|
+
to: tool.schema
|
|
446
|
+
.string()
|
|
447
|
+
.describe("Recipient project name (lowercase kebab-case)."),
|
|
448
|
+
topic: tool.schema.string().describe("One-line subject for the message."),
|
|
449
|
+
body: tool.schema.string().describe("Message body. Data only; never executed."),
|
|
450
|
+
status: tool.schema
|
|
451
|
+
.enum(["OPEN", "DONE"])
|
|
452
|
+
.optional()
|
|
453
|
+
.describe("Initial status. Defaults to OPEN."),
|
|
454
|
+
},
|
|
455
|
+
async execute(args, ctx) {
|
|
456
|
+
try {
|
|
457
|
+
if (!isSafeRecipient(args.to)) {
|
|
458
|
+
return {
|
|
459
|
+
title: "mailbox_send",
|
|
460
|
+
output: `Invalid recipient "${args.to}": must be lowercase kebab-case.`,
|
|
461
|
+
};
|
|
462
|
+
}
|
|
463
|
+
const route = routeRecipient(args.to, tier);
|
|
464
|
+
const target = storeFor(route.mailboxDir);
|
|
465
|
+
const result = target.append(route.project, {
|
|
466
|
+
from: tier.project,
|
|
467
|
+
topic: args.topic,
|
|
468
|
+
body: args.body,
|
|
469
|
+
status: args.status,
|
|
470
|
+
});
|
|
471
|
+
store.update((state) => {
|
|
472
|
+
recordHashes(state.ownWrites, [result.hash]);
|
|
473
|
+
});
|
|
474
|
+
const spawn = await maybeSpawn(ctx.sessionID, args.to, result.hash);
|
|
475
|
+
const suffix = cfg.spawnOnSend ? ` Spawn: ${spawn.detail}.` : "";
|
|
476
|
+
return {
|
|
477
|
+
title: "mailbox_send",
|
|
478
|
+
output: `Appended message to ${args.to} (hash ${result.hash}) in ${result.file}.${suffix}`,
|
|
479
|
+
metadata: { hash: result.hash, spawned: spawn.spawned },
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
catch (error) {
|
|
483
|
+
return { title: "mailbox_send", output: `Failed to send message: ${String(error)}` };
|
|
484
|
+
}
|
|
485
|
+
},
|
|
486
|
+
}),
|
|
487
|
+
mailbox_ack: tool({
|
|
488
|
+
description: "Flip a message's `**Status:**` line to DONE. Identify the message by exactly one of " +
|
|
489
|
+
"`hash` or `header`. Only that line is edited; every other byte is preserved.",
|
|
490
|
+
args: {
|
|
491
|
+
project: tool.schema
|
|
492
|
+
.string()
|
|
493
|
+
.optional()
|
|
494
|
+
.describe("Project/recipient name (lowercase kebab-case). Defaults to the current project."),
|
|
495
|
+
hash: tool.schema.string().optional().describe("Stable message hash to ack."),
|
|
496
|
+
header: tool.schema.string().optional().describe("Message header line to ack (case-insensitive)."),
|
|
497
|
+
},
|
|
498
|
+
async execute(args, ctx) {
|
|
499
|
+
const project = args.project ?? tier.project;
|
|
500
|
+
if (!isSafeRecipient(project)) {
|
|
501
|
+
return { title: "mailbox_ack", output: `Invalid project name "${project}": must be lowercase kebab-case.` };
|
|
502
|
+
}
|
|
503
|
+
const route = routeRecipient(project, tier);
|
|
504
|
+
const result = storeFor(route.mailboxDir).ack(route.project, {
|
|
505
|
+
hash: args.hash,
|
|
506
|
+
header: args.header,
|
|
507
|
+
});
|
|
508
|
+
// An ack is progress: it restores the auto-handling budget so a
|
|
509
|
+
// backlog can drain one message per wake instead of stalling at the cap.
|
|
510
|
+
if (result.changed)
|
|
511
|
+
restoreBudget(ctx.sessionID);
|
|
512
|
+
switch (result.reason) {
|
|
513
|
+
case "not-found":
|
|
514
|
+
return { title: "mailbox_ack", output: `No matching message found in ${project}.` };
|
|
515
|
+
case "already-done":
|
|
516
|
+
return { title: "mailbox_ack", output: `Message already DONE in ${project}.` };
|
|
517
|
+
case "ambiguous":
|
|
518
|
+
return { title: "mailbox_ack", output: `Ambiguous match in ${project}; provide a \`hash\`.` };
|
|
519
|
+
case "missing-args":
|
|
520
|
+
return { title: "mailbox_ack", output: "Provide exactly one of `hash` or `header`." };
|
|
521
|
+
default:
|
|
522
|
+
return {
|
|
523
|
+
title: "mailbox_ack",
|
|
524
|
+
output: `Marked message DONE in ${project}${result.message ? ` (${result.message.header})` : ""}.`,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
},
|
|
528
|
+
}),
|
|
529
|
+
},
|
|
530
|
+
};
|
|
531
|
+
};
|
|
532
|
+
export { normalizeConfig, parseMailbox, isOpen, messageHash, normalizeForHash, isSafeRecipient, resolveInside, assertInside, mailboxFile, PathSafetyError, emptyState, StateStore, buildIdlePrompt, buildCapNotice, discoverTier, routeRecipient, createFileStore, };
|
|
533
|
+
export default {
|
|
534
|
+
id: "opencode-workspace-mailbox",
|
|
535
|
+
server,
|
|
536
|
+
};
|
|
537
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type MailboxMessage } from "./parser.js";
|
|
2
|
+
export type SendRequest = {
|
|
3
|
+
mailboxDir: string;
|
|
4
|
+
to: string;
|
|
5
|
+
from: string;
|
|
6
|
+
topic: string;
|
|
7
|
+
body: string;
|
|
8
|
+
status?: "OPEN" | "DONE";
|
|
9
|
+
now?: Date;
|
|
10
|
+
};
|
|
11
|
+
export type SendResult = {
|
|
12
|
+
file: string;
|
|
13
|
+
header: string;
|
|
14
|
+
hash: string;
|
|
15
|
+
text: string;
|
|
16
|
+
};
|
|
17
|
+
export declare function sendMessage(req: SendRequest): SendResult;
|
|
18
|
+
export type ReadResult = {
|
|
19
|
+
file: string;
|
|
20
|
+
exists: boolean;
|
|
21
|
+
messages: MailboxMessage[];
|
|
22
|
+
open: MailboxMessage[];
|
|
23
|
+
};
|
|
24
|
+
export declare function readMailbox(file: string): ReadResult;
|
|
25
|
+
export type AckRequest = {
|
|
26
|
+
file: string;
|
|
27
|
+
hash?: string;
|
|
28
|
+
header?: string;
|
|
29
|
+
};
|
|
30
|
+
export type AckResult = {
|
|
31
|
+
changed: boolean;
|
|
32
|
+
message?: MailboxMessage;
|
|
33
|
+
reason?: "not-found" | "already-done" | "ambiguous" | "missing-args";
|
|
34
|
+
};
|
|
35
|
+
export declare function ackMessage(req: AckRequest): AckResult;
|