openryoko 2026.5.8 → 2026.5.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/dist/package.json +1 -1
  2. package/dist/src/connectors/slack/__tests__/agents-canvas.test.d.ts +2 -0
  3. package/dist/src/connectors/slack/__tests__/agents-canvas.test.d.ts.map +1 -0
  4. package/dist/src/connectors/slack/__tests__/agents-canvas.test.js +191 -0
  5. package/dist/src/connectors/slack/__tests__/agents-canvas.test.js.map +1 -0
  6. package/dist/src/connectors/slack/__tests__/goal-extractor.test.d.ts +2 -0
  7. package/dist/src/connectors/slack/__tests__/goal-extractor.test.d.ts.map +1 -0
  8. package/dist/src/connectors/slack/__tests__/goal-extractor.test.js +129 -0
  9. package/dist/src/connectors/slack/__tests__/goal-extractor.test.js.map +1 -0
  10. package/dist/src/connectors/slack/agents-canvas.d.ts +59 -0
  11. package/dist/src/connectors/slack/agents-canvas.d.ts.map +1 -0
  12. package/dist/src/connectors/slack/agents-canvas.js +372 -0
  13. package/dist/src/connectors/slack/agents-canvas.js.map +1 -0
  14. package/dist/src/connectors/slack/goal-extractor.d.ts +67 -0
  15. package/dist/src/connectors/slack/goal-extractor.d.ts.map +1 -0
  16. package/dist/src/connectors/slack/goal-extractor.js +302 -0
  17. package/dist/src/connectors/slack/goal-extractor.js.map +1 -0
  18. package/dist/src/connectors/slack/index.d.ts +15 -0
  19. package/dist/src/connectors/slack/index.d.ts.map +1 -1
  20. package/dist/src/connectors/slack/index.js +78 -0
  21. package/dist/src/connectors/slack/index.js.map +1 -1
  22. package/dist/src/engines/claude.d.ts +11 -0
  23. package/dist/src/engines/claude.d.ts.map +1 -1
  24. package/dist/src/engines/claude.js +75 -13
  25. package/dist/src/engines/claude.js.map +1 -1
  26. package/dist/src/gateway/api.d.ts.map +1 -1
  27. package/dist/src/gateway/api.js +20 -0
  28. package/dist/src/gateway/api.js.map +1 -1
  29. package/dist/src/gateway/server.d.ts.map +1 -1
  30. package/dist/src/gateway/server.js +61 -2
  31. package/dist/src/gateway/server.js.map +1 -1
  32. package/dist/src/sessions/context.js +20 -2
  33. package/dist/src/sessions/context.js.map +1 -1
  34. package/dist/src/sessions/manager.d.ts.map +1 -1
  35. package/dist/src/sessions/manager.js +15 -1
  36. package/dist/src/sessions/manager.js.map +1 -1
  37. package/dist/src/shared/types.d.ts +21 -0
  38. package/dist/src/shared/types.d.ts.map +1 -1
  39. package/dist/web/404.html +1 -1
  40. package/dist/web/__next.__PAGE__.txt +2 -2
  41. package/dist/web/__next._full.txt +3 -3
  42. package/dist/web/__next._head.txt +1 -1
  43. package/dist/web/__next._index.txt +2 -2
  44. package/dist/web/__next._tree.txt +2 -2
  45. package/dist/web/_next/static/chunks/{0y3uv64m1qh.k.js → 012aakl34ff5a.js} +2 -2
  46. package/dist/web/_next/static/chunks/{0j4uz-g9x1_~s.js → 0a2uy1kw.~j~c.js} +1 -1
  47. package/dist/web/_next/static/chunks/{0v51a3blij~j6.js → 0agxgztb0b~.7.js} +2 -2
  48. package/dist/web/_next/static/chunks/{1645~4k0qcst0.js → 0g6xt.91k~0bc.js} +2 -2
  49. package/dist/web/_next/static/chunks/{16zc7-yv7supr.js → 0jzw1gpuag8bc.js} +2 -2
  50. package/dist/web/_next/static/chunks/0kceasmxfr3s1.js +1 -0
  51. package/dist/web/_next/static/chunks/{0wv0qjh9tuqx~.js → 0lkp92-ovteta.js} +2 -2
  52. package/dist/web/_next/static/chunks/{1621s_jgljr1_.js → 0msmlzd_~uk0y.js} +2 -2
  53. package/dist/web/_next/static/chunks/{00yn.jp4tr9l6.js → 0z5lzlvft9.4o.js} +2 -2
  54. package/dist/web/_next/static/chunks/103zsy0q9psfj.css +1 -0
  55. package/dist/web/_next/static/chunks/{0ma0h4_2c8y9y.js → 12m97bwrg1tuu.js} +2 -2
  56. package/dist/web/_not-found/__next._full.txt +2 -2
  57. package/dist/web/_not-found/__next._head.txt +1 -1
  58. package/dist/web/_not-found/__next._index.txt +2 -2
  59. package/dist/web/_not-found/__next._not-found.__PAGE__.txt +1 -1
  60. package/dist/web/_not-found/__next._not-found.txt +1 -1
  61. package/dist/web/_not-found/__next._tree.txt +2 -2
  62. package/dist/web/_not-found.html +1 -1
  63. package/dist/web/_not-found.txt +2 -2
  64. package/dist/web/chat/__next._full.txt +3 -3
  65. package/dist/web/chat/__next._head.txt +1 -1
  66. package/dist/web/chat/__next._index.txt +2 -2
  67. package/dist/web/chat/__next._tree.txt +2 -2
  68. package/dist/web/chat/__next.chat.__PAGE__.txt +2 -2
  69. package/dist/web/chat/__next.chat.txt +1 -1
  70. package/dist/web/chat.html +1 -1
  71. package/dist/web/chat.txt +3 -3
  72. package/dist/web/cron/__next._full.txt +3 -3
  73. package/dist/web/cron/__next._head.txt +1 -1
  74. package/dist/web/cron/__next._index.txt +2 -2
  75. package/dist/web/cron/__next._tree.txt +2 -2
  76. package/dist/web/cron/__next.cron.__PAGE__.txt +2 -2
  77. package/dist/web/cron/__next.cron.txt +1 -1
  78. package/dist/web/cron.html +1 -1
  79. package/dist/web/cron.txt +3 -3
  80. package/dist/web/index.html +1 -1
  81. package/dist/web/index.txt +3 -3
  82. package/dist/web/kanban/__next._full.txt +3 -3
  83. package/dist/web/kanban/__next._head.txt +1 -1
  84. package/dist/web/kanban/__next._index.txt +2 -2
  85. package/dist/web/kanban/__next._tree.txt +2 -2
  86. package/dist/web/kanban/__next.kanban.__PAGE__.txt +2 -2
  87. package/dist/web/kanban/__next.kanban.txt +1 -1
  88. package/dist/web/kanban.html +1 -1
  89. package/dist/web/kanban.txt +3 -3
  90. package/dist/web/logs/__next._full.txt +3 -3
  91. package/dist/web/logs/__next._head.txt +1 -1
  92. package/dist/web/logs/__next._index.txt +2 -2
  93. package/dist/web/logs/__next._tree.txt +2 -2
  94. package/dist/web/logs/__next.logs.__PAGE__.txt +2 -2
  95. package/dist/web/logs/__next.logs.txt +1 -1
  96. package/dist/web/logs.html +2 -2
  97. package/dist/web/logs.txt +3 -3
  98. package/dist/web/org/__next._full.txt +3 -3
  99. package/dist/web/org/__next._head.txt +1 -1
  100. package/dist/web/org/__next._index.txt +2 -2
  101. package/dist/web/org/__next._tree.txt +2 -2
  102. package/dist/web/org/__next.org.__PAGE__.txt +2 -2
  103. package/dist/web/org/__next.org.txt +1 -1
  104. package/dist/web/org.html +1 -1
  105. package/dist/web/org.txt +3 -3
  106. package/dist/web/sessions/__next._full.txt +2 -2
  107. package/dist/web/sessions/__next._head.txt +1 -1
  108. package/dist/web/sessions/__next._index.txt +2 -2
  109. package/dist/web/sessions/__next._tree.txt +2 -2
  110. package/dist/web/sessions/__next.sessions.__PAGE__.txt +1 -1
  111. package/dist/web/sessions/__next.sessions.txt +1 -1
  112. package/dist/web/sessions.html +1 -1
  113. package/dist/web/sessions.txt +2 -2
  114. package/dist/web/settings/__next._full.txt +3 -3
  115. package/dist/web/settings/__next._head.txt +1 -1
  116. package/dist/web/settings/__next._index.txt +2 -2
  117. package/dist/web/settings/__next._tree.txt +2 -2
  118. package/dist/web/settings/__next.settings.__PAGE__.txt +2 -2
  119. package/dist/web/settings/__next.settings.txt +1 -1
  120. package/dist/web/settings.html +1 -1
  121. package/dist/web/settings.txt +3 -3
  122. package/dist/web/skills/__next._full.txt +3 -3
  123. package/dist/web/skills/__next._head.txt +1 -1
  124. package/dist/web/skills/__next._index.txt +2 -2
  125. package/dist/web/skills/__next._tree.txt +2 -2
  126. package/dist/web/skills/__next.skills.__PAGE__.txt +2 -2
  127. package/dist/web/skills/__next.skills.txt +1 -1
  128. package/dist/web/skills.html +1 -1
  129. package/dist/web/skills.txt +3 -3
  130. package/package.json +1 -1
  131. package/dist/web/_next/static/chunks/05uy~i7wsbsn3.js +0 -1
  132. package/dist/web/_next/static/chunks/0bj62gv2pext..css +0 -1
  133. package/dist/web/dev/logs/next-development.log +0 -5
  134. /package/dist/web/_next/static/{VBjMXtz9-pIo9izqNT-iu → 2gkySyM5UoStZGUIrVpRy}/_buildManifest.js +0 -0
  135. /package/dist/web/_next/static/{VBjMXtz9-pIo9izqNT-iu → 2gkySyM5UoStZGUIrVpRy}/_clientMiddlewareManifest.js +0 -0
  136. /package/dist/web/_next/static/{VBjMXtz9-pIo9izqNT-iu → 2gkySyM5UoStZGUIrVpRy}/_ssgManifest.js +0 -0
@@ -0,0 +1,372 @@
1
+ /**
2
+ * Agents View for Slack — a self-updating Canvas that mirrors OpenRyoko's
3
+ * current sessions, inspired by Claude Code v2.1.139's `claude agents`.
4
+ *
5
+ * Data source: OpenRyoko's own session registry (SQLite via `listSessions()`).
6
+ * NOT `~/.claude/daemon/roster.json` — that file is populated only by
7
+ * `claude --bg` background sessions, and OpenRyoko currently spawns one-shot
8
+ * `claude -p` sessions, so its sessions never appear there.
9
+ *
10
+ * Lifecycle: started by SlackConnector when `agentsCanvas.enabled === true`.
11
+ * Polls the session registry every `pollIntervalMs` (default 30s), renders
12
+ * a Markdown summary, and pushes it into a single Slack Canvas. The canvas
13
+ * is created on first run and reused afterwards; its ID is persisted under
14
+ * `${JINN_HOME}/.agents-canvas-state.json`.
15
+ */
16
+ import fs from "node:fs";
17
+ import path from "node:path";
18
+ import { listSessions } from "../../sessions/registry.js";
19
+ import { JINN_HOME } from "../../shared/paths.js";
20
+ import { logger } from "../../shared/logger.js";
21
+ const STATE_FILE = path.join(JINN_HOME, ".agents-canvas-state.json");
22
+ const DEFAULT_TITLE = "Ryoko Agents View";
23
+ const DEFAULT_POLL_MS = 30_000;
24
+ const MIN_POLL_MS = 5_000;
25
+ const DEFAULT_MAX_PER_GROUP = 10;
26
+ /** Map a Session.status to its presentation group. */
27
+ function groupOf(s) {
28
+ switch (s.status) {
29
+ case "running":
30
+ return "running";
31
+ case "waiting":
32
+ return "waiting";
33
+ case "interrupted":
34
+ return "interrupted";
35
+ case "error":
36
+ return "error";
37
+ case "idle":
38
+ default:
39
+ return "idle";
40
+ }
41
+ }
42
+ function groupSessions(sessions) {
43
+ const out = {
44
+ running: [],
45
+ waiting: [],
46
+ interrupted: [],
47
+ error: [],
48
+ idle: [],
49
+ };
50
+ for (const s of sessions) {
51
+ out[groupOf(s)].push(s);
52
+ }
53
+ return out;
54
+ }
55
+ /** Round a millisecond duration into "Xm" / "Xh" / "Xd" — never longer than 5 chars. */
56
+ function formatAge(fromIso, nowMs) {
57
+ const t = Date.parse(fromIso);
58
+ if (!Number.isFinite(t))
59
+ return "?";
60
+ const diffMs = Math.max(0, nowMs - t);
61
+ const mins = Math.floor(diffMs / 60_000);
62
+ if (mins < 1)
63
+ return "now";
64
+ if (mins < 60)
65
+ return `${mins}m`;
66
+ const hours = Math.floor(mins / 60);
67
+ if (hours < 24)
68
+ return `${hours}h`;
69
+ const days = Math.floor(hours / 24);
70
+ return `${days}d`;
71
+ }
72
+ /**
73
+ * Make a user-controlled string safe to embed in the Canvas Markdown body.
74
+ * Strips control characters and newlines (which would break list items) and
75
+ * defangs Slack mention / link syntax + Markdown emphasis characters that
76
+ * could otherwise turn a session title into an @channel ping or a heading.
77
+ */
78
+ // Built via new RegExp so the source text is plain ASCII — embedding raw
79
+ // control bytes in a regex literal trips some editor / tool pipelines.
80
+ const CANVAS_CONTROL_CHARS_RE = new RegExp("[\\u0000-\\u001f\\u007f]", "g");
81
+ function escapeForCanvas(input) {
82
+ const stripped = input.replace(CANVAS_CONTROL_CHARS_RE, " ").replace(/\s+/g, " ").trim();
83
+ return (stripped
84
+ // Slack user / channel / group / link mentions: <@U…>, <#C…>, <#C…|name>, <!subteam^…>, <!here>, <!channel>, <!everyone>, <http…>, <mailto:…>.
85
+ // Strip the entire <…> shell so the residue cannot be parsed by
86
+ // Slack's renderer as a mention. We replace with a neutral placeholder
87
+ // for entity-like forms and keep visible link text for the rest.
88
+ .replace(/<!(channel|here|everyone)>/gi, "($1)")
89
+ .replace(/<!subteam\^[^>]*?\|([^>]*)>/g, "$1")
90
+ .replace(/<!subteam\^[^>]*>/g, "(group)")
91
+ .replace(/<@[UW][^>|]*\|([^>]*)>/g, "$1")
92
+ .replace(/<@[UW][^>]*>/g, "(user)")
93
+ .replace(/<#[CDG][^>|]*\|([^>]*)>/g, "#$1")
94
+ .replace(/<#[CDG][^>]*>/g, "(channel)")
95
+ // Generic <url|label> link — keep the human label
96
+ .replace(/<([^<>]*?)\|([^<>]*?)>/g, "$2")
97
+ // Anything else inside <…> — strip the brackets to prevent residual parsing
98
+ .replace(/<([^<>]*)>/g, "$1")
99
+ // Bare @channel / @here / @everyone (no angle brackets) — zero-width space split
100
+ .replace(/(^|[^A-Za-z0-9_])@(channel|here|everyone)\b/gi, "$1@\u200b$2")
101
+ // Markdown emphasis / code / heading / blockquote / table / strikethrough characters — escape so they render literally
102
+ .replace(/([*_`~>#|\\\[\]])/g, "\\$1"));
103
+ }
104
+ function safeTitle(s) {
105
+ const raw = (s.title || s.sessionKey || s.id || "untitled");
106
+ const escaped = escapeForCanvas(raw);
107
+ return escaped.length > 80 ? escaped.slice(0, 77) + "…" : escaped;
108
+ }
109
+ function locationOf(s) {
110
+ const parts = [];
111
+ if (s.connector)
112
+ parts.push(escapeForCanvas(s.connector));
113
+ if (s.source && s.source !== s.connector)
114
+ parts.push(escapeForCanvas(s.source));
115
+ if (s.employee)
116
+ parts.push("@" + escapeForCanvas(s.employee));
117
+ return parts.join(" · ");
118
+ }
119
+ function renderSessionLine(s, nowMs) {
120
+ const title = safeTitle(s);
121
+ const age = formatAge(s.lastActivity, nowMs);
122
+ const loc = locationOf(s);
123
+ const meta = loc ? ` _(${loc})_` : "";
124
+ return `- **${title}**${meta} — ${age}`;
125
+ }
126
+ const GROUP_HEADERS = [
127
+ { key: "running", emoji: "🟢", label: "Running" },
128
+ { key: "waiting", emoji: "🟡", label: "Waiting on you" },
129
+ { key: "error", emoji: "🔴", label: "Errored" },
130
+ { key: "interrupted", emoji: "⏸️", label: "Interrupted (resumable)" },
131
+ { key: "idle", emoji: "✅", label: "Recently idle" },
132
+ ];
133
+ /**
134
+ * Pure renderer. Exported so it can be unit-tested without spawning a Slack
135
+ * client. `nowMs` is injectable for deterministic snapshots.
136
+ */
137
+ export function renderCanvasMarkdown(sessions, opts = {}) {
138
+ const title = opts.title || DEFAULT_TITLE;
139
+ const nowMs = opts.nowMs ?? Date.now();
140
+ const maxPerGroup = Math.max(1, opts.maxPerGroup ?? DEFAULT_MAX_PER_GROUP);
141
+ const grouped = groupSessions(sessions);
142
+ const lines = [];
143
+ lines.push(`# ${title}`);
144
+ lines.push("");
145
+ const total = sessions.length;
146
+ const updated = new Date(nowMs).toISOString().replace("T", " ").slice(0, 16) + " UTC";
147
+ lines.push(`_${total} session${total === 1 ? "" : "s"} · updated ${updated}_`);
148
+ lines.push("");
149
+ let wroteAny = false;
150
+ for (const { key, emoji, label } of GROUP_HEADERS) {
151
+ const bucket = grouped[key];
152
+ if (bucket.length === 0)
153
+ continue;
154
+ wroteAny = true;
155
+ lines.push(`## ${emoji} ${label} (${bucket.length})`);
156
+ const shown = bucket.slice(0, maxPerGroup);
157
+ for (const s of shown) {
158
+ lines.push(renderSessionLine(s, nowMs));
159
+ }
160
+ if (bucket.length > shown.length) {
161
+ lines.push(`- _…and ${bucket.length - shown.length} more_`);
162
+ }
163
+ lines.push("");
164
+ }
165
+ if (!wroteAny) {
166
+ lines.push("_No active sessions._");
167
+ lines.push("");
168
+ }
169
+ return lines.join("\n").trimEnd() + "\n";
170
+ }
171
+ function loadState() {
172
+ try {
173
+ const raw = fs.readFileSync(STATE_FILE, "utf8");
174
+ const parsed = JSON.parse(raw);
175
+ if (parsed && typeof parsed === "object")
176
+ return parsed;
177
+ }
178
+ catch { /* missing or unreadable → fresh state */ }
179
+ return {};
180
+ }
181
+ function saveState(state) {
182
+ try {
183
+ fs.mkdirSync(path.dirname(STATE_FILE), { recursive: true });
184
+ fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2), "utf8");
185
+ }
186
+ catch (err) {
187
+ logger.warn(`[agents-canvas] failed to persist state: ${err}`);
188
+ }
189
+ }
190
+ /**
191
+ * Manages the lifecycle of the Agents View canvas: periodically polls the
192
+ * session registry, renders Markdown, and pushes it to Slack.
193
+ */
194
+ export class AgentsCanvasUpdater {
195
+ timer = null;
196
+ inflight = false;
197
+ stopped = false;
198
+ canvasId = null;
199
+ lastMarkdown = null;
200
+ client;
201
+ config;
202
+ constructor(app, config) {
203
+ this.client = app.client;
204
+ this.config = {
205
+ enabled: config.enabled !== false,
206
+ channelId: config.channelId,
207
+ title: config.title || DEFAULT_TITLE,
208
+ pollIntervalMs: Math.max(MIN_POLL_MS, config.pollIntervalMs ?? DEFAULT_POLL_MS),
209
+ maxPerGroup: config.maxPerGroup ?? DEFAULT_MAX_PER_GROUP,
210
+ };
211
+ const persisted = loadState();
212
+ if (persisted.canvasId && persisted.channelId === this.config.channelId) {
213
+ this.canvasId = persisted.canvasId;
214
+ }
215
+ }
216
+ start() {
217
+ if (!this.config.enabled) {
218
+ logger.info("[agents-canvas] disabled by config");
219
+ return;
220
+ }
221
+ if (this.timer)
222
+ return; // already running — make start() idempotent
223
+ this.stopped = false;
224
+ logger.info(`[agents-canvas] starting (interval=${this.config.pollIntervalMs}ms, channel=${this.config.channelId || "standalone"})`);
225
+ // Kick off an immediate update so the canvas reflects current state at boot.
226
+ void this.tick();
227
+ this.timer = setInterval(() => {
228
+ void this.tick();
229
+ }, this.config.pollIntervalMs);
230
+ }
231
+ stop() {
232
+ this.stopped = true;
233
+ if (this.timer) {
234
+ clearInterval(this.timer);
235
+ this.timer = null;
236
+ }
237
+ }
238
+ async tick() {
239
+ if (this.inflight || this.stopped)
240
+ return;
241
+ this.inflight = true;
242
+ try {
243
+ const sessions = listSessions();
244
+ const markdown = renderCanvasMarkdown(sessions, {
245
+ title: this.config.title,
246
+ maxPerGroup: this.config.maxPerGroup,
247
+ });
248
+ // Skip no-op updates to spare Slack API calls + avoid edit churn.
249
+ if (markdown === this.lastMarkdown)
250
+ return;
251
+ // stop() may have fired while we were rendering — bail before any I/O.
252
+ if (this.stopped)
253
+ return;
254
+ await this.publish(markdown);
255
+ this.lastMarkdown = markdown;
256
+ }
257
+ catch (err) {
258
+ logger.warn(`[agents-canvas] tick failed: ${err}`);
259
+ }
260
+ finally {
261
+ this.inflight = false;
262
+ }
263
+ }
264
+ async publish(markdown) {
265
+ if (!this.canvasId) {
266
+ await this.createCanvas(markdown);
267
+ return;
268
+ }
269
+ try {
270
+ await this.editCanvas(this.canvasId, markdown);
271
+ }
272
+ catch (err) {
273
+ logger.warn(`[agents-canvas] edit failed, will try recreating: ${err}`);
274
+ // The persisted canvas may have been deleted by the user; drop the ID
275
+ // and let the next tick re-create it.
276
+ this.canvasId = null;
277
+ saveState({ canvasId: undefined, channelId: this.config.channelId });
278
+ }
279
+ }
280
+ async createCanvas(markdown) {
281
+ const documentContent = { type: "markdown", markdown };
282
+ if (this.config.channelId) {
283
+ try {
284
+ const res = await this.client.apiCall("conversations.canvases.create", {
285
+ channel_id: this.config.channelId,
286
+ document_content: documentContent,
287
+ title: this.config.title,
288
+ });
289
+ const canvasId = extractCanvasId(res);
290
+ if (!canvasId) {
291
+ throw new Error(`conversations.canvases.create returned no canvas_id: ${JSON.stringify(res).slice(0, 200)}`);
292
+ }
293
+ this.canvasId = canvasId;
294
+ }
295
+ catch (err) {
296
+ // If the channel already has a Canvas (created previously by us, by
297
+ // another instance, or manually), Slack returns `channel_canvas_already_exists`.
298
+ // Recover by reading the existing canvas id from conversations.info and
299
+ // editing that one instead of bailing out.
300
+ if (isChannelCanvasAlreadyExistsError(err)) {
301
+ const existingId = await this.fetchExistingChannelCanvasId(this.config.channelId);
302
+ if (!existingId) {
303
+ throw err;
304
+ }
305
+ logger.info(`[agents-canvas] adopting existing channel canvas ${existingId}`);
306
+ this.canvasId = existingId;
307
+ await this.editCanvas(existingId, markdown);
308
+ }
309
+ else {
310
+ throw err;
311
+ }
312
+ }
313
+ }
314
+ else {
315
+ const res = await this.client.apiCall("canvases.create", {
316
+ title: this.config.title,
317
+ document_content: documentContent,
318
+ });
319
+ const canvasId = extractCanvasId(res);
320
+ if (!canvasId) {
321
+ throw new Error(`canvases.create returned no canvas_id: ${JSON.stringify(res).slice(0, 200)}`);
322
+ }
323
+ this.canvasId = canvasId;
324
+ }
325
+ saveState({ canvasId: this.canvasId, channelId: this.config.channelId });
326
+ logger.info(`[agents-canvas] created canvas ${this.canvasId}`);
327
+ }
328
+ async fetchExistingChannelCanvasId(channelId) {
329
+ try {
330
+ const info = await this.client.apiCall("conversations.info", { channel: channelId });
331
+ const channel = info.channel;
332
+ const properties = channel?.properties;
333
+ const canvas = properties?.canvas;
334
+ const id = canvas?.file_id ?? canvas?.id;
335
+ return typeof id === "string" && id ? id : null;
336
+ }
337
+ catch (err) {
338
+ logger.warn(`[agents-canvas] failed to fetch existing channel canvas: ${err}`);
339
+ return null;
340
+ }
341
+ }
342
+ async editCanvas(canvasId, markdown) {
343
+ await this.client.apiCall("canvases.edit", {
344
+ canvas_id: canvasId,
345
+ changes: [
346
+ {
347
+ operation: "replace",
348
+ document_content: { type: "markdown", markdown },
349
+ },
350
+ ],
351
+ });
352
+ }
353
+ }
354
+ function extractCanvasId(res) {
355
+ const direct = res.canvas_id;
356
+ if (typeof direct === "string" && direct)
357
+ return direct;
358
+ const canvas = res.canvas;
359
+ if (canvas && typeof canvas.id === "string")
360
+ return canvas.id;
361
+ return null;
362
+ }
363
+ function isChannelCanvasAlreadyExistsError(err) {
364
+ if (!err || typeof err !== "object")
365
+ return false;
366
+ const data = err.data;
367
+ if (data?.error === "channel_canvas_already_exists")
368
+ return true;
369
+ const msg = err instanceof Error ? err.message : String(err);
370
+ return /channel_canvas_already_exists/.test(msg);
371
+ }
372
+ //# sourceMappingURL=agents-canvas.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agents-canvas.js","sourceRoot":"","sources":["../../../../src/connectors/slack/agents-canvas.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Natural-language `/goal` extraction for Slack messages.
3
+ *
4
+ * Lives outside the triage path on purpose: triage = "should we respond at
5
+ * all" (only meaningful when ambient noise might NOT be for us). When the
6
+ * message clearly IS for us (DM / @-mention / DM-equivalent / triage→reply),
7
+ * triage is bypassed but we still want to recognise autonomous-completion
8
+ * intent and prefix `/goal <cond>` to the engine prompt so Claude Code's
9
+ * v2.1.139 Stop hook keeps the session working until the goal holds.
10
+ *
11
+ * Two stages keep latency and cost down:
12
+ *
13
+ * 1. `hasGoalIntent` — deterministic keyword gate. Burns no LLM credits.
14
+ * Catches the common JP / EN "keep going until done" phrasings.
15
+ * 2. `extractGoalCondition` — only fires when (1) matches. Spawns Haiku
16
+ * via the Claude Code CLI with a tight prompt and a hard timeout.
17
+ * On any failure (timeout, unparseable output, slash-prefix rejection)
18
+ * it returns `null` and the caller pretends nothing happened.
19
+ *
20
+ * All sanitisation lives in `parseGoalExtractionResult` so it is unit-
21
+ * testable without spawning a subprocess.
22
+ */
23
+ import { spawn } from "node:child_process";
24
+ /**
25
+ * Cheap, deterministic gate. Returns false for messages that obviously do
26
+ * not warrant a goal-extraction LLM call (too short, already prefixed with
27
+ * `/goal`, etc.). Returns true otherwise — the Haiku call is the source of
28
+ * truth on whether a condition can actually be distilled, and its parser
29
+ * (`parseGoalExtractionResult`) rejects sentinels / vague output.
30
+ *
31
+ * Replaced an earlier keyword regex approach that missed natural phrasings
32
+ * like "数字1から3までを別々のターンで出して完了と書いたら止まる" — keyword
33
+ * matching is fundamentally fragile for free-form Japanese.
34
+ */
35
+ export declare function shouldExtractGoal(text: string): boolean;
36
+ /**
37
+ * @deprecated Retained for back-compat in case external callers imported
38
+ * the keyword-gate API. Now an alias for {@link shouldExtractGoal}.
39
+ */
40
+ export declare function hasGoalIntent(text: string): boolean;
41
+ export declare function buildGoalExtractionPrompt(messageText: string): string;
42
+ /**
43
+ * Parse Haiku's response into a sanitised condition, or null if no usable
44
+ * condition was returned. Sanitisation:
45
+ * - strip control characters, collapse whitespace
46
+ * - reject leading `/` (would smuggle a second slash command)
47
+ * - reject obviously vague placeholders
48
+ * - hard cap on length
49
+ */
50
+ export declare function parseGoalExtractionResult(raw: string): string | null;
51
+ export interface ExtractGoalOptions {
52
+ /** Binary to invoke — defaults to "claude" */
53
+ bin?: string;
54
+ /** Model to call — defaults to claude-haiku-4-5 */
55
+ model?: string;
56
+ /** Hard timeout before giving up (ms). Defaults to 15s. */
57
+ timeoutMs?: number;
58
+ /** Override the spawner (for tests) */
59
+ spawnImpl?: typeof spawn;
60
+ }
61
+ /**
62
+ * Extract a `/goal` condition from a user's message. Returns null on any
63
+ * failure — the caller should treat this as "don't inject /goal" and move
64
+ * on. Never throws.
65
+ */
66
+ export declare function extractGoalCondition(messageText: string, options?: ExtractGoalOptions): Promise<string | null>;
67
+ //# sourceMappingURL=goal-extractor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"goal-extractor.d.ts","sourceRoot":"","sources":["../../../../src/connectors/slack/goal-extractor.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAiB3C;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAKvD;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEnD;AAQD,wBAAgB,yBAAyB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAgFrE;AAWD;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsCpE;AAMD,MAAM,WAAW,kBAAkB;IACjC,8CAA8C;IAC9C,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,mDAAmD;IACnD,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,uCAAuC;IACvC,SAAS,CAAC,EAAE,OAAO,KAAK,CAAC;CAC1B;AAUD;;;;GAIG;AACH,wBAAsB,oBAAoB,CACxC,WAAW,EAAE,MAAM,EACnB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAgBxB"}