heyio 0.15.0 → 0.16.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/copilot/scheduler.js +23 -14
- package/dist/copilot/tools.js +15 -0
- package/dist/tui/index.js +64 -0
- package/package.json +1 -1
|
@@ -16,6 +16,8 @@ import { delegateToAgent } from "./agents.js";
|
|
|
16
16
|
import { nextRun } from "./cron.js";
|
|
17
17
|
import { notifyBackground } from "../notify.js";
|
|
18
18
|
import { startScheduleRun, completeScheduleRun, failScheduleRun } from "../store/schedule-runs.js";
|
|
19
|
+
import { createInboxEntry } from "../store/inbox.js";
|
|
20
|
+
import { shouldRouteToInbox } from "./tools.js";
|
|
19
21
|
const TICK_MS = 30_000;
|
|
20
22
|
const AGENDA_BLOCKS = {
|
|
21
23
|
triage: `**Triage**
|
|
@@ -80,20 +82,27 @@ async function fireSchedule(schedule) {
|
|
|
80
82
|
});
|
|
81
83
|
try {
|
|
82
84
|
await delegateToAgent(squad.slug, prompt, (_taskId, result) => {
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
85
|
+
if (shouldRouteToInbox(prompt)) {
|
|
86
|
+
createInboxEntry(`[${squad.slug}] ${schedule.name}`, result);
|
|
87
|
+
console.error(`[io] Schedule ${schedule.id} result routed to inbox`);
|
|
88
|
+
completeScheduleRun(run.id, 0);
|
|
89
|
+
}
|
|
90
|
+
else {
|
|
91
|
+
void notifyBackground({
|
|
92
|
+
source: {
|
|
93
|
+
type: "squad-schedule",
|
|
94
|
+
scheduleId: schedule.id,
|
|
95
|
+
squadSlug: squad.slug,
|
|
96
|
+
scheduleName: schedule.name,
|
|
97
|
+
},
|
|
98
|
+
title: `${squad.name}: ${schedule.name}`,
|
|
99
|
+
text: result,
|
|
100
|
+
}).then((notifyResult) => {
|
|
101
|
+
completeScheduleRun(run.id, notifyResult.id);
|
|
102
|
+
}).catch((err) => {
|
|
103
|
+
failScheduleRun(run.id, err instanceof Error ? err.message : String(err));
|
|
104
|
+
});
|
|
105
|
+
}
|
|
97
106
|
});
|
|
98
107
|
}
|
|
99
108
|
catch (err) {
|
package/dist/copilot/tools.js
CHANGED
|
@@ -5,6 +5,7 @@ import { readFileSync, writeFileSync, readdirSync, statSync, existsSync, mkdirSy
|
|
|
5
5
|
import { join, dirname, resolve } from "path";
|
|
6
6
|
import { homedir } from "os";
|
|
7
7
|
import { UNIVERSES } from "./universes.js";
|
|
8
|
+
import { createInboxEntry } from "../store/inbox.js";
|
|
8
9
|
import { validateCron, nextRun } from "./cron.js";
|
|
9
10
|
import { createIoSchedule, deleteIoSchedule, getIoSchedule, listIoSchedules, setIoScheduleEnabled, updateIoScheduleNextRun, } from "../store/io-schedules.js";
|
|
10
11
|
import { runIoScheduleNow } from "./io-scheduler.js";
|
|
@@ -228,6 +229,16 @@ function shellEnv() {
|
|
|
228
229
|
env.HOME = homedir();
|
|
229
230
|
return env;
|
|
230
231
|
}
|
|
232
|
+
export function shouldRouteToInbox(taskDescription) {
|
|
233
|
+
const lower = taskDescription.toLowerCase();
|
|
234
|
+
return (lower.includes("io inbox") ||
|
|
235
|
+
lower.includes("io-inbox") ||
|
|
236
|
+
lower.includes("send to inbox") ||
|
|
237
|
+
lower.includes("to the inbox") ||
|
|
238
|
+
lower.includes("result: \"io-inbox\"") ||
|
|
239
|
+
lower.includes("not github or telegram") ||
|
|
240
|
+
lower.includes("not telegram"));
|
|
241
|
+
}
|
|
231
242
|
export function createTools(deps) {
|
|
232
243
|
const wikiRead = defineTool("wiki_read", {
|
|
233
244
|
description: "Read a page from IO's knowledge base wiki. Path is relative to the wiki root (e.g., 'pages/preferences/editor.md').",
|
|
@@ -387,6 +398,10 @@ export function createTools(deps) {
|
|
|
387
398
|
try {
|
|
388
399
|
const taskId = await deps.delegateToAgent(slug, task, (id, result) => {
|
|
389
400
|
console.error(`[io] Agent task ${id} completed for squad ${slug}`);
|
|
401
|
+
if (shouldRouteToInbox(task)) {
|
|
402
|
+
createInboxEntry(`[${slug}] Task result`, result);
|
|
403
|
+
console.error(`[io] Task ${id} result routed to inbox`);
|
|
404
|
+
}
|
|
390
405
|
}, agent);
|
|
391
406
|
const agentLabel = agent ? `agent "${agent}" in squad "${slug}"` : `squad "${slug}"`;
|
|
392
407
|
const warningPrefix = coverage.warning
|
package/dist/tui/index.js
CHANGED
|
@@ -2,6 +2,7 @@ import { createInterface } from "readline";
|
|
|
2
2
|
import { listRecentTasks, getTask } from "../store/tasks.js";
|
|
3
3
|
import { getTaskEvents } from "../copilot/agents.js";
|
|
4
4
|
import { summarize } from "../copilot/event-summary.js";
|
|
5
|
+
import { listInboxEntries, deleteInboxEntry, countInboxEntries, } from "../store/inbox.js";
|
|
5
6
|
let messageHandler;
|
|
6
7
|
export function setMessageHandler(handler) {
|
|
7
8
|
messageHandler = handler;
|
|
@@ -14,6 +15,9 @@ Type a message to chat. Commands:
|
|
|
14
15
|
/status — show status
|
|
15
16
|
/activity [id|N] — show summarized activity for a task (default: most recent)
|
|
16
17
|
/verbose — toggle verbose mode (raw event detail in /activity)
|
|
18
|
+
/inbox — list inbox entries
|
|
19
|
+
/inbox delete <id> — delete an inbox entry by ID
|
|
20
|
+
/inbox clear — delete all inbox entries
|
|
17
21
|
/quit — exit
|
|
18
22
|
`;
|
|
19
23
|
let verbose = false;
|
|
@@ -124,6 +128,24 @@ function renderActivity(taskIdArg) {
|
|
|
124
128
|
}
|
|
125
129
|
}
|
|
126
130
|
}
|
|
131
|
+
function renderInbox() {
|
|
132
|
+
const entries = listInboxEntries();
|
|
133
|
+
if (entries.length === 0) {
|
|
134
|
+
console.log("\u2705 Inbox is empty.");
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
console.log(`\u2705 Inbox (${entries.length} ${entries.length === 1 ? "entry" : "entries"})`);
|
|
138
|
+
console.log("\u2500".repeat(60));
|
|
139
|
+
for (const entry of entries) {
|
|
140
|
+
const ts = new Date(entry.created_at).toLocaleString();
|
|
141
|
+
console.log(`[${entry.id}] ${entry.title} \u2014 ${ts}`);
|
|
142
|
+
const preview = entry.body.length > 200 ? entry.body.slice(0, 200) + "\u2026" : entry.body;
|
|
143
|
+
for (const line of preview.split(/\r?\n/)) {
|
|
144
|
+
console.log(` ${line}`);
|
|
145
|
+
}
|
|
146
|
+
console.log("");
|
|
147
|
+
}
|
|
148
|
+
}
|
|
127
149
|
function clearLine() {
|
|
128
150
|
process.stdout.write("\r\x1b[K");
|
|
129
151
|
}
|
|
@@ -150,7 +172,11 @@ export async function startTui() {
|
|
|
150
172
|
process.exit(0);
|
|
151
173
|
}
|
|
152
174
|
if (trimmed === "/status") {
|
|
175
|
+
const inboxCount = countInboxEntries();
|
|
153
176
|
console.log(`[io] Uptime: ${Math.floor(process.uptime())}s`);
|
|
177
|
+
if (inboxCount > 0) {
|
|
178
|
+
console.log(`[io] \u2705 Inbox: ${inboxCount} ${inboxCount === 1 ? "entry" : "entries"}`);
|
|
179
|
+
}
|
|
154
180
|
rl.prompt();
|
|
155
181
|
return;
|
|
156
182
|
}
|
|
@@ -171,6 +197,44 @@ export async function startTui() {
|
|
|
171
197
|
rl.prompt();
|
|
172
198
|
return;
|
|
173
199
|
}
|
|
200
|
+
if (trimmed === "/inbox" || trimmed.startsWith("/inbox ")) {
|
|
201
|
+
const sub = trimmed.slice("/inbox".length).trim();
|
|
202
|
+
try {
|
|
203
|
+
if (sub === "") {
|
|
204
|
+
renderInbox();
|
|
205
|
+
}
|
|
206
|
+
else if (sub === "clear") {
|
|
207
|
+
const entries = listInboxEntries();
|
|
208
|
+
let deleted = 0;
|
|
209
|
+
for (const entry of entries) {
|
|
210
|
+
if (deleteInboxEntry(entry.id))
|
|
211
|
+
deleted++;
|
|
212
|
+
}
|
|
213
|
+
console.log(`[io] Cleared ${deleted} inbox ${deleted === 1 ? "entry" : "entries"}.`);
|
|
214
|
+
}
|
|
215
|
+
else if (sub.startsWith("delete ")) {
|
|
216
|
+
const rawId = sub.slice("delete ".length).trim();
|
|
217
|
+
const id = Number.parseInt(rawId, 10);
|
|
218
|
+
if (Number.isNaN(id)) {
|
|
219
|
+
console.log(`[io] Invalid ID: "${rawId}". Usage: /inbox delete <id>`);
|
|
220
|
+
}
|
|
221
|
+
else if (deleteInboxEntry(id)) {
|
|
222
|
+
console.log(`[io] Deleted inbox entry #${id}.`);
|
|
223
|
+
}
|
|
224
|
+
else {
|
|
225
|
+
console.log(`[io] Inbox entry #${id} not found.`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
console.log(`[io] Unknown inbox subcommand: "${sub}". Try /inbox, /inbox delete <id>, or /inbox clear.`);
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
catch (err) {
|
|
233
|
+
console.error(`[io] /inbox failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
234
|
+
}
|
|
235
|
+
rl.prompt();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
174
238
|
if (!messageHandler) {
|
|
175
239
|
console.log("[io] No message handler registered.");
|
|
176
240
|
rl.prompt();
|