symbiot 0.55.1 → 0.55.2
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/CHANGELOG.md +12 -0
- package/README.md +128 -47
- package/agents.mjs +136 -6
- package/guard.mjs +6 -2
- package/handback.mjs +2 -2
- package/handover.mjs +14 -3
- package/home.mjs +183 -33
- package/lanes.mjs +6 -6
- package/marketing.mjs +130 -0
- package/mind.mjs +9 -9
- package/package.json +4 -3
- package/reports.mjs +3 -3
- package/scan.mjs +9 -2
- package/server.mjs +22 -11
- package/tasks.mjs +14 -10
- package/ui.mjs +297 -125
- package/watch.mjs +5 -5
- package/writeups.mjs +3 -3
package/watch.mjs
CHANGED
|
@@ -32,7 +32,7 @@ import { resolveProvider, write } from "./ai.mjs";
|
|
|
32
32
|
import { handoffCmd, runHandoff, runningHandoff } from "./agents.mjs";
|
|
33
33
|
import { linksIn, peekLinks, peekLine } from "./peek.mjs";
|
|
34
34
|
import { converse, actNow, actIn, taskIn } from "./mind.mjs";
|
|
35
|
-
import {
|
|
35
|
+
import { laneMap } from "./scan.mjs";
|
|
36
36
|
import { maybeCustomer } from "./post.mjs";
|
|
37
37
|
|
|
38
38
|
const WATCH_FILE = join(CONFIG_DIR, "watch.json");
|
|
@@ -320,7 +320,7 @@ function cardLinks(w, recent, question) {
|
|
|
320
320
|
const own = hostOf(w.url), host = (u) => { try { return new URL(u).hostname.replace(/^www\./, ""); } catch { return ""; } };
|
|
321
321
|
return [...linksIn(question), ...recent.flatMap((n) => linksIn(n.text))].filter((u) => host(u) && host(u) !== own);
|
|
322
322
|
}
|
|
323
|
-
async function boardChat(id, question, { hours = 72, now = Date.now(), ask = write, look = peekLinks, run = actNow, lanes = () => { try { return
|
|
323
|
+
async function boardChat(id, question, { hours = 72, now = Date.now(), ask = write, look = peekLinks, run = actNow, lanes = () => { try { return laneMap(); } catch { return {}; } } } = {}) {
|
|
324
324
|
question = String(question || "").trim().slice(0, 2000);
|
|
325
325
|
const d = loadWatch(), w = d.watches.find((x) => x.id === id); if (!w) return { error: `No watch ${id}.` };
|
|
326
326
|
if (!question) return { error: "empty" };
|
|
@@ -528,7 +528,7 @@ function draftReply(id, { run = runHandoff } = {}) {
|
|
|
528
528
|
// it runs by itself, in the background: an editor, or Orca's tab, can't (and Orca's tab wouldn't carry SYMBIOT_DRAFT)
|
|
529
529
|
if (!/\{prompt\}/.test(tmpl) || /orca-ide/.test(tmpl)) return { error: "Drafting runs your agent in the background, so it needs an agent that makes changes by itself (Settings → Handoff: Claude Code, Codex, Gemini or Aider), not an editor or an Orca tab." };
|
|
530
530
|
const dir = join(DRAFTS_DIR, n.id);
|
|
531
|
-
if (runningHandoff(dir)) return { error: "Your agent is still drafting this one. It's
|
|
531
|
+
if (runningHandoff(dir)) return { error: "Your agent is still drafting this one. It's on the Workdesk." };
|
|
532
532
|
try {
|
|
533
533
|
// your mail or chats, and the agent's log of them: yours only, like watch.json
|
|
534
534
|
mkdirSync(join(dir, ".symbiot"), { recursive: true, mode: 0o700 }); try { chmodSync(DRAFTS_DIR, 0o700); } catch {}
|
|
@@ -537,7 +537,7 @@ function draftReply(id, { run = runHandoff } = {}) {
|
|
|
537
537
|
} catch (e) { return { error: "Couldn't write the brief: " + ((e && e.message) || e) }; }
|
|
538
538
|
const e = run(dir, { force: true }); // a click on Draft a reply asks for a run, even after one stopped on a question
|
|
539
539
|
if (!e) return { error: "Your agent didn't start. Check its command in Settings → Handoff." };
|
|
540
|
-
if (e.busy) return { error: "Your agent is still drafting this one. It's
|
|
540
|
+
if (e.busy) return { error: "Your agent is still drafting this one. It's on the Workdesk." };
|
|
541
541
|
const d2 = loadWatch(), n2 = d2.news.find((x) => x.id === id); if (n2) { n2.drafted = Date.now(); saveWatch(d2); }
|
|
542
542
|
return { ok: true, job: e.id, dir, ...(chat ? { chat: true } : {}), ...(social ? { social: true } : {}) };
|
|
543
543
|
}
|
|
@@ -550,7 +550,7 @@ async function openChat(id, { open = signIn } = {}) {
|
|
|
550
550
|
const d = loadWatch(), n = d.news.find((x) => x.id === id); if (!n) return { error: "That message isn't under Watching any more." };
|
|
551
551
|
const w = d.watches.find((x) => x.id === n.watch);
|
|
552
552
|
if (!w || !isChat(w.url)) return { error: "Open in WhatsApp is for a WhatsApp chat." };
|
|
553
|
-
if (runningHandoff(join(DRAFTS_DIR, n.id))) return { error: "Your agent is still typing the reply. Open WhatsApp once it's done: the
|
|
553
|
+
if (runningHandoff(join(DRAFTS_DIR, n.id))) return { error: "Your agent is still typing the reply. Open WhatsApp once it's done: the Workdesk shows when." };
|
|
554
554
|
return open(w.url);
|
|
555
555
|
}
|
|
556
556
|
|
package/writeups.mjs
CHANGED
|
@@ -7,7 +7,7 @@ import { VERSION, loadConfig, saveConfig, loadTasks, saveTasks, sh, repoState }
|
|
|
7
7
|
import { resolveProvider, write } from "./ai.mjs";
|
|
8
8
|
import { detectMailSources, mailActivity } from "./mail.mjs";
|
|
9
9
|
import { waitingOn, newsSince } from "./watch.mjs";
|
|
10
|
-
import { me, authorship, authorArgs, readmeInfo, repoShape, houseRules, reportFooter, expandRoot, commits, openWork, detectFolder,
|
|
10
|
+
import { me, authorship, authorArgs, readmeInfo, repoShape, houseRules, reportFooter, expandRoot, commits, openWork, detectFolder, laneMap, discoveredRepos } from "./scan.mjs";
|
|
11
11
|
import { taskType, workingChanges, workingDiff, changelogEntry } from "./tasks.mjs";
|
|
12
12
|
import { converse, actNow, actIn, taskIn } from "./mind.mjs";
|
|
13
13
|
|
|
@@ -131,7 +131,7 @@ async function taskChat(id, question) {
|
|
|
131
131
|
if (!it) return { error: "not found" };
|
|
132
132
|
if (!question) return { error: "empty" };
|
|
133
133
|
if (!resolveProvider()) return { error: "not-connected" };
|
|
134
|
-
const path = it.repo ?
|
|
134
|
+
const path = it.repo ? laneMap()[it.repo] : "";
|
|
135
135
|
const ctx = [];
|
|
136
136
|
if (path) {
|
|
137
137
|
const isGit = existsSync(join(path, ".git"));
|
|
@@ -151,7 +151,7 @@ async function taskChat(id, question) {
|
|
|
151
151
|
(ctx.length ? "\n\n" + ctx.join("\n\n") : path ? "" : "\n\n(no repo attached: answer from the task text alone)");
|
|
152
152
|
// "do it" here works on the task's repo the way Send to repos does: the request
|
|
153
153
|
// joins the repo's tasks and the agent starts there; with no repo, in a run of its own
|
|
154
|
-
const lanes =
|
|
154
|
+
const lanes = laneMap(), mine = path ? it.repo : "";
|
|
155
155
|
const agent = async (req, known, repo) => {
|
|
156
156
|
const lane = repo || mine;
|
|
157
157
|
return lane ? actIn(req, lane, { map: lanes, known, title: it.text.slice(0, 60), context: `Their task: ${it.text}` }) : actNow(req, { title: it.text.slice(0, 60), context: `Their task: ${it.text}`, known });
|