@chibitek/chibi 0.1.161 → 0.1.162
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/assets/{abnfDiagram-O67JEVCF-Bb-Unz3V.js → abnfDiagram-O67JEVCF-D0_WX2x_.js} +1 -1
- package/dist/assets/{arc-HBMH7B4K.js → arc-lzBXqTbJ.js} +1 -1
- package/dist/assets/{architectureDiagram-NJMV4G6O-CYwkb2PE.js → architectureDiagram-NJMV4G6O-KQZbO2M3.js} +1 -1
- package/dist/assets/{blockDiagram-BEXU5L5S-DPYYNxBH.js → blockDiagram-BEXU5L5S-zb3pW64Y.js} +1 -1
- package/dist/assets/{c4Diagram-YGBWAQC7-DZ9hKDlA.js → c4Diagram-YGBWAQC7-CADaXczd.js} +1 -1
- package/dist/assets/channel-Br57lm8F.js +1 -0
- package/dist/assets/{chunk-2Q5K7J3B-OKrUlts6.js → chunk-2Q5K7J3B-DJP27cEp.js} +1 -1
- package/dist/assets/{chunk-3FUC2YCW-Tuur0lqz.js → chunk-3FUC2YCW-Cp9Z7Ybl.js} +2 -2
- package/dist/assets/{chunk-5VM5RSS4-BL8QOZeP.js → chunk-5VM5RSS4-DjXxom_0.js} +1 -1
- package/dist/assets/{chunk-GTNCS2PH-DMi8-ixt.js → chunk-GTNCS2PH-DpEJ08zA.js} +1 -1
- package/dist/assets/{chunk-GWA4HPMP-Dd7yNJ0G.js → chunk-GWA4HPMP-CQ4Kadr-.js} +1 -1
- package/dist/assets/{chunk-JWPE2WC7-g2dOoIMX.js → chunk-JWPE2WC7-CwXmVMdh.js} +1 -1
- package/dist/assets/{chunk-NETBCI7D-Cum7feOh.js → chunk-NETBCI7D-Vl_kib_R.js} +1 -1
- package/dist/assets/{chunk-WEXAMYUT-BzCC1jc4.js → chunk-WEXAMYUT-BhAVbfJe.js} +1 -1
- package/dist/assets/{chunk-XXDRQBXY-Ck63jUMo.js → chunk-XXDRQBXY-s1a4nKQE.js} +1 -1
- package/dist/assets/{classDiagram-v2-NBCMYWYE-DFSuRVMZ.js → classDiagram-v2-NBCMYWYE-DeGQSNky.js} +1 -1
- package/dist/assets/{cose-bilkent-JH36ORCC-CegRj_kY.js → cose-bilkent-JH36ORCC-D5sUHYFG.js} +1 -1
- package/dist/assets/{cynefin-OW5HDTMX-cZS_kt1A.js → cynefin-OW5HDTMX-DmTvN9T2.js} +1 -1
- package/dist/assets/{cynefinDiagram-VND7K2PF-DfQa9Rht.js → cynefinDiagram-VND7K2PF-Cqtt1jCF.js} +1 -1
- package/dist/assets/{dagre-6A5THRUB-DJ9qftJu.js → dagre-6A5THRUB-DRZKkSJg.js} +1 -1
- package/dist/assets/{diagram-22UHCM2B-KXUGUahJ.js → diagram-22UHCM2B-1od4dKOU.js} +1 -1
- package/dist/assets/{diagram-3UASUU5V-BudCYrCp.js → diagram-3UASUU5V-D3_yCQOJ.js} +1 -1
- package/dist/assets/{diagram-ATOU4E4O-Du2O03NS.js → diagram-ATOU4E4O-D9UgsVGC.js} +1 -1
- package/dist/assets/{diagram-CDSNMT55-DXybXGYf.js → diagram-CDSNMT55-DMxsJ_X5.js} +1 -1
- package/dist/assets/{diagram-MLGK6HIB-DfrknXGE.js → diagram-MLGK6HIB-CK47Pp3D.js} +1 -1
- package/dist/assets/{diagram-MPIPVDR6-C29FmaJm.js → diagram-MPIPVDR6-D0axYDk-.js} +1 -1
- package/dist/assets/{ebnfDiagram-ZINNZB2B-BF9wS0Nz.js → ebnfDiagram-ZINNZB2B-hkbV8j2o.js} +1 -1
- package/dist/assets/{elk-276RUBZZ-B2Fah1VF.js → elk-276RUBZZ-DL9jncwy.js} +1 -1
- package/dist/assets/{erDiagram-OPXOYQCR-Di3q4bpF.js → erDiagram-OPXOYQCR-etb_6SR6.js} +1 -1
- package/dist/assets/{flowDiagram-KWPJA3E3-D1UiqwbF.js → flowDiagram-KWPJA3E3-4Dgg4I8f.js} +1 -1
- package/dist/assets/{ganttDiagram-FUAMR5RP-BjZqMt7o.js → ganttDiagram-FUAMR5RP-DRBB4AaO.js} +1 -1
- package/dist/assets/{gitGraphDiagram-X574FWY7-DiZtdip7.js → gitGraphDiagram-X574FWY7-CzgKN-tE.js} +1 -1
- package/dist/assets/{index-dbQveHan.js → index-BT2giPxq.js} +1 -1
- package/dist/assets/{index-XFwW09vd.js → index-fHtcwzVK.js} +179 -179
- package/dist/assets/{infoDiagram-VRGFBTTK-BJUJCgio.js → infoDiagram-VRGFBTTK-DwpjLCMe.js} +1 -1
- package/dist/assets/{ishikawaDiagram-OU5B5YK6-BX0XdHUx.js → ishikawaDiagram-OU5B5YK6-H-CWnU1-.js} +1 -1
- package/dist/assets/{journeyDiagram-ZHPQQLJL-Bg904IIx.js → journeyDiagram-ZHPQQLJL-CY-oDrpq.js} +1 -1
- package/dist/assets/{kanban-definition-PNTS6WVX-hkZMFMHZ.js → kanban-definition-PNTS6WVX-DMGIKH3g.js} +1 -1
- package/dist/assets/{linear-Bh29RTbQ.js → linear-BHhtTLK8.js} +1 -1
- package/dist/assets/{mermaid.core-aqB1jW_w.js → mermaid.core-BWK_Ui3n.js} +5 -5
- package/dist/assets/{mindmap-definition-NLK3R4M7-D5GMV-Zd.js → mindmap-definition-NLK3R4M7-Cc17hw2c.js} +1 -1
- package/dist/assets/{pegDiagram-GJSIUBJH-7_wFtkFH.js → pegDiagram-GJSIUBJH-BqFjUBJK.js} +1 -1
- package/dist/assets/{pieDiagram-5QR66LMP-DXtZBQ4f.js → pieDiagram-5QR66LMP-ikmgTCa3.js} +1 -1
- package/dist/assets/{quadrantDiagram-O4NWA36T-C1v3ydTF.js → quadrantDiagram-O4NWA36T-CC3s5Dsc.js} +1 -1
- package/dist/assets/{railroadDiagram-XR7U4H2S-CLmhiOXg.js → railroadDiagram-XR7U4H2S-Dtwf869F.js} +1 -1
- package/dist/assets/{requirementDiagram-PLB6GJNP-BKxI2rh_.js → requirementDiagram-PLB6GJNP-C5p7AgwQ.js} +1 -1
- package/dist/assets/{sankeyDiagram-IPEJSGJF-gKK-Qs7b.js → sankeyDiagram-IPEJSGJF-8NKN770X.js} +1 -1
- package/dist/assets/{sequenceDiagram-PO4LG4MO-BT94Uowp.js → sequenceDiagram-PO4LG4MO-DQucgrWO.js} +1 -1
- package/dist/assets/{sizeCapture-INFHLROL-RDJL6sCM.js → sizeCapture-INFHLROL-Cxmcj9Nl.js} +1 -1
- package/dist/assets/{stateDiagram-v2-GCMORJYK-DqHMzv-J.js → stateDiagram-v2-GCMORJYK-DEdvHXnJ.js} +1 -1
- package/dist/assets/{swimlanes-2SLR337P-B-NN0ql6.js → swimlanes-2SLR337P-BOGePqj1.js} +1 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BSe9TZ6t.js +8 -0
- package/dist/assets/{timeline-definition-EJHVYXUP-C51S9tpN.js → timeline-definition-EJHVYXUP-DfpRxJgE.js} +1 -1
- package/dist/assets/{usecaseDiagram-POWQR4AR-DyfNMmhq.js → usecaseDiagram-POWQR4AR-BOmQFDT4.js} +1 -1
- package/dist/assets/{vennDiagram-UO4OBE2U-D924r33S.js → vennDiagram-UO4OBE2U-84pfbvUi.js} +1 -1
- package/dist/assets/{wardleyDiagram-VNRHLVJA-DXSfsjUr.js → wardleyDiagram-VNRHLVJA-Cbxnw8ip.js} +1 -1
- package/dist/assets/{xychartDiagram-PMCCYNJV-mYX9tnBU.js → xychartDiagram-PMCCYNJV-BLiz8vqY.js} +1 -1
- package/dist/index.html +1 -1
- package/dist-server/connector-proxy.js +205 -0
- package/dist-server/container-mcp.js +7 -6
- package/dist-server/index.js +1150 -921
- package/dist-server/openmausbot.js +7 -6
- package/dist-server/pair-cli.js +7 -6
- package/dist-server/server/composio.js +1051 -0
- package/dist-server/server/config.js +6 -6
- package/dist-server/server/connector-proxy.js +249 -0
- package/dist-server/server/index.js +4 -2
- package/dist-server/server/mcp-public-registry.js +325 -0
- package/dist-server/server/routine-mochii-sync.js +252 -0
- package/dist-server/shared/connector-availability.js +12 -0
- package/dist-server/vps-container-mcp.js +7 -6
- package/package.json +1 -1
- package/dist/assets/channel-Nx85fHZ4.js +0 -1
- package/dist/assets/swimlanesDiagram-TC7HE7FX-BO2gR34z.js +0 -8
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
// Mirrors each routine into one private Mochii task: its schedule and next
|
|
2
|
+
// run on the task, and every finished run as a comment. Off unless the
|
|
3
|
+
// install sets features.routineMochiiSync, and it needs the configured
|
|
4
|
+
// `mochii` MCP server, which acts as the signed-in person, so each person's
|
|
5
|
+
// routines land in their own Mochii as their own private tasks.
|
|
6
|
+
//
|
|
7
|
+
// Fail closed: a new task is first created with a content-free title. Only
|
|
8
|
+
// when Mochii answers that it is private and keyed to this routine (the
|
|
9
|
+
// create contract: is_private, idempotency_key, replayed) does routine
|
|
10
|
+
// content follow. An older Mochii that ignores the contract gets its stray
|
|
11
|
+
// task deleted, and sync pauses for a few hours before checking again.
|
|
12
|
+
//
|
|
13
|
+
// No outbox: the routines and their run receipts are already on disk, so each
|
|
14
|
+
// pass compares them with what Mochii has confirmed (routine-mochii-sync.json)
|
|
15
|
+
// and sends the difference. A failed pass is simply retried on the next one.
|
|
16
|
+
import { existsSync, readFileSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { writeFileAtomic } from "./atomic.js";
|
|
19
|
+
import { customMcpServers } from "./config.js";
|
|
20
|
+
import { nexusClientFor, NexusUnavailableError } from "./nexus-memory/client.js";
|
|
21
|
+
import { scheduleText } from "./routine-requests.js";
|
|
22
|
+
const PASS_EVERY_MS = 5 * 60_000;
|
|
23
|
+
const POKE_DELAY_MS = 3_000;
|
|
24
|
+
const BLOCK_MS = 6 * 60 * 60_000;
|
|
25
|
+
/** Runs already finished when a routine is first mirrored: only the latest few become comments. */
|
|
26
|
+
const BACKFILL_RUNS = 5;
|
|
27
|
+
const MAX_COMMENT_CHARS = 4_000;
|
|
28
|
+
const FINISHED = new Set(["completed", "failed", "cancelled", "missed"]);
|
|
29
|
+
const PROBE_TITLE = "Atomic routine";
|
|
30
|
+
export function routineMochiiSyncEnabled(cfg) {
|
|
31
|
+
return cfg.features?.routineMochiiSync === true && Boolean(customMcpServers(cfg).mochii);
|
|
32
|
+
}
|
|
33
|
+
export const idempotencyKey = (routineId) => `atomic-routine:${routineId}`;
|
|
34
|
+
function record(value) {
|
|
35
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
36
|
+
}
|
|
37
|
+
export function taskTitle(routine) {
|
|
38
|
+
return `Routine: ${routine.name}${routine.enabled ? "" : " (paused)"}`;
|
|
39
|
+
}
|
|
40
|
+
export function taskDescription(routine, bot, timeZone) {
|
|
41
|
+
const next = routine.enabled && routine.nextRunAt != null ? new Date(routine.nextRunAt).toISOString() : "none";
|
|
42
|
+
return [
|
|
43
|
+
"Managed by Atomic. Edits made here are replaced on the next sync.",
|
|
44
|
+
"",
|
|
45
|
+
`Bot: ${bot ?? routine.botId}`,
|
|
46
|
+
`Schedule: ${scheduleText(routine.schedule, timeZone)}`,
|
|
47
|
+
`Status: ${routine.enabled ? "active" : "paused"}`,
|
|
48
|
+
`Next run: ${next}`,
|
|
49
|
+
"",
|
|
50
|
+
"Prompt:",
|
|
51
|
+
routine.prompt,
|
|
52
|
+
].join("\n");
|
|
53
|
+
}
|
|
54
|
+
export function runComment(run) {
|
|
55
|
+
const when = new Date(run.finishedAt ?? run.scheduledFor).toISOString();
|
|
56
|
+
const body = (run.status === "failed" ? run.error ?? run.output : run.output ?? run.error)?.trim();
|
|
57
|
+
const clipped = body && body.length > MAX_COMMENT_CHARS ? `${body.slice(0, MAX_COMMENT_CHARS)}\n\n(cut short; the full report is in Atomic)` : body;
|
|
58
|
+
return `Run ${run.status} · ${when}${run.manual ? " · started by hand" : ""}${clipped ? `\n\n${clipped}` : ""}`;
|
|
59
|
+
}
|
|
60
|
+
export class RoutineMochiiSync {
|
|
61
|
+
path;
|
|
62
|
+
now;
|
|
63
|
+
state;
|
|
64
|
+
client = null;
|
|
65
|
+
clientKey = "";
|
|
66
|
+
running = null;
|
|
67
|
+
poked;
|
|
68
|
+
timer;
|
|
69
|
+
deps;
|
|
70
|
+
constructor(deps) {
|
|
71
|
+
this.deps = deps;
|
|
72
|
+
this.path = join(deps.dataDir, "routine-mochii-sync.json");
|
|
73
|
+
this.now = deps.now ?? Date.now;
|
|
74
|
+
this.state = this.load();
|
|
75
|
+
}
|
|
76
|
+
static start(deps) {
|
|
77
|
+
const sync = new RoutineMochiiSync(deps);
|
|
78
|
+
sync.start();
|
|
79
|
+
return sync;
|
|
80
|
+
}
|
|
81
|
+
start() {
|
|
82
|
+
this.timer ??= setInterval(() => void this.pass(), PASS_EVERY_MS);
|
|
83
|
+
this.timer.unref?.();
|
|
84
|
+
this.poke();
|
|
85
|
+
}
|
|
86
|
+
stop() {
|
|
87
|
+
clearInterval(this.timer);
|
|
88
|
+
clearTimeout(this.poked);
|
|
89
|
+
this.timer = undefined;
|
|
90
|
+
void this.client?.close();
|
|
91
|
+
this.client = null;
|
|
92
|
+
}
|
|
93
|
+
/** A run changed: sync soon rather than waiting for the next pass. */
|
|
94
|
+
poke() {
|
|
95
|
+
if (this.poked || !routineMochiiSyncEnabled(this.deps.config()))
|
|
96
|
+
return;
|
|
97
|
+
this.poked = setTimeout(() => {
|
|
98
|
+
this.poked = undefined;
|
|
99
|
+
void this.pass();
|
|
100
|
+
}, POKE_DELAY_MS);
|
|
101
|
+
this.poked.unref?.();
|
|
102
|
+
}
|
|
103
|
+
status() {
|
|
104
|
+
return {
|
|
105
|
+
enabled: routineMochiiSyncEnabled(this.deps.config()),
|
|
106
|
+
mirrored: Object.keys(this.state.tasks).length,
|
|
107
|
+
blockedUntil: this.state.blockedUntil ?? null,
|
|
108
|
+
blockedReason: this.state.blockedReason ?? null,
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
/** One reconcile pass; concurrent callers share it. */
|
|
112
|
+
pass() {
|
|
113
|
+
this.running ??= this.reconcile()
|
|
114
|
+
.catch((error) => this.log(`pass stopped: ${error instanceof Error ? error.message : String(error)}`))
|
|
115
|
+
.finally(() => { this.running = null; });
|
|
116
|
+
return this.running;
|
|
117
|
+
}
|
|
118
|
+
async reconcile() {
|
|
119
|
+
const cfg = this.deps.config();
|
|
120
|
+
if (!routineMochiiSyncEnabled(cfg))
|
|
121
|
+
return;
|
|
122
|
+
if (this.state.blockedUntil && this.now() < this.state.blockedUntil)
|
|
123
|
+
return;
|
|
124
|
+
const client = this.clientFor(cfg);
|
|
125
|
+
if (!client)
|
|
126
|
+
return;
|
|
127
|
+
const routines = this.deps.listRoutines();
|
|
128
|
+
const runs = this.deps.listRuns();
|
|
129
|
+
for (const routine of routines) {
|
|
130
|
+
const mine = runs.filter((run) => run.routineId === routine.id && FINISHED.has(run.status));
|
|
131
|
+
try {
|
|
132
|
+
if (!(await this.mirror(client, routine, mine)))
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
catch (error) {
|
|
136
|
+
if (error instanceof NexusUnavailableError)
|
|
137
|
+
throw error;
|
|
138
|
+
this.log(`routine ${routine.id}: ${error instanceof Error ? error.message : String(error)}`);
|
|
139
|
+
// The task is gone from Mochii: forget it so the next pass creates it again.
|
|
140
|
+
if (/not found|404/i.test(String(error)))
|
|
141
|
+
this.forget(routine.id);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const live = new Set(routines.map((routine) => routine.id));
|
|
145
|
+
for (const [routineId, mirrored] of Object.entries(this.state.tasks)) {
|
|
146
|
+
if (live.has(routineId))
|
|
147
|
+
continue;
|
|
148
|
+
try {
|
|
149
|
+
await client.call("update_task", { id: mirrored.taskId, status: "cancelled" });
|
|
150
|
+
await client.call("add_comment", { task_id: mirrored.taskId, content: "This routine was deleted in Atomic." });
|
|
151
|
+
}
|
|
152
|
+
catch (error) {
|
|
153
|
+
if (error instanceof NexusUnavailableError)
|
|
154
|
+
throw error;
|
|
155
|
+
}
|
|
156
|
+
this.forget(routineId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
/** False when Mochii failed the privacy check: stop the whole pass. */
|
|
160
|
+
async mirror(client, routine, finished) {
|
|
161
|
+
let mirrored = this.state.tasks[routine.id];
|
|
162
|
+
if (!mirrored) {
|
|
163
|
+
const taskId = await this.createPrivate(client, routine.id);
|
|
164
|
+
if (!taskId)
|
|
165
|
+
return false;
|
|
166
|
+
const byAge = [...finished].sort((a, b) => (a.finishedAt ?? a.scheduledFor) - (b.finishedAt ?? b.scheduledFor));
|
|
167
|
+
mirrored = { taskId, fingerprint: "", runs: byAge.slice(0, -BACKFILL_RUNS).map((run) => run.id) };
|
|
168
|
+
this.state.tasks[routine.id] = mirrored;
|
|
169
|
+
this.save();
|
|
170
|
+
}
|
|
171
|
+
const title = taskTitle(routine);
|
|
172
|
+
const description = taskDescription(routine, this.deps.botName(routine.botId), this.deps.timeZone());
|
|
173
|
+
const due = routine.enabled && routine.nextRunAt != null ? new Date(routine.nextRunAt).toISOString() : undefined;
|
|
174
|
+
const fingerprint = JSON.stringify([title, description, due]);
|
|
175
|
+
if (fingerprint !== mirrored.fingerprint) {
|
|
176
|
+
await client.call("update_task", { id: mirrored.taskId, title, description, status: "pending", ...(due ? { due_date: due } : {}) });
|
|
177
|
+
mirrored.fingerprint = fingerprint;
|
|
178
|
+
this.save();
|
|
179
|
+
}
|
|
180
|
+
const posted = new Set(mirrored.runs);
|
|
181
|
+
const fresh = finished
|
|
182
|
+
.filter((run) => !posted.has(run.id))
|
|
183
|
+
.sort((a, b) => (a.finishedAt ?? a.scheduledFor) - (b.finishedAt ?? b.scheduledFor));
|
|
184
|
+
for (const run of fresh) {
|
|
185
|
+
await client.call("add_comment", { task_id: mirrored.taskId, content: runComment(run) });
|
|
186
|
+
mirrored.runs.push(run.id);
|
|
187
|
+
this.save();
|
|
188
|
+
}
|
|
189
|
+
const kept = new Set(finished.map((run) => run.id));
|
|
190
|
+
if (mirrored.runs.some((id) => !kept.has(id))) {
|
|
191
|
+
mirrored.runs = mirrored.runs.filter((id) => kept.has(id));
|
|
192
|
+
this.save();
|
|
193
|
+
}
|
|
194
|
+
return true;
|
|
195
|
+
}
|
|
196
|
+
/** Creates (or, after a crash, gets back) the routine's task with a content-free title. */
|
|
197
|
+
async createPrivate(client, routineId) {
|
|
198
|
+
const key = idempotencyKey(routineId);
|
|
199
|
+
const body = await client.call("create_task", { title: PROBE_TITLE, is_private: true, idempotency_key: key });
|
|
200
|
+
const task = record(body.data);
|
|
201
|
+
const taskId = typeof task?.id === "string" ? task.id : null;
|
|
202
|
+
if (taskId && task?.is_private === true && task.idempotency_key === key && typeof body.replayed === "boolean")
|
|
203
|
+
return taskId;
|
|
204
|
+
if (taskId && task?.is_private !== true) {
|
|
205
|
+
await client.call("delete_task", { id: taskId }).catch((error) => this.log(`could not remove a non-private task ${taskId}: ${String(error)}`));
|
|
206
|
+
}
|
|
207
|
+
this.state.blockedUntil = this.now() + BLOCK_MS;
|
|
208
|
+
this.state.blockedReason = "Mochii does not support private routine tasks yet";
|
|
209
|
+
this.save();
|
|
210
|
+
this.log(`${this.state.blockedReason}; nothing was sent, checking again later`);
|
|
211
|
+
return null;
|
|
212
|
+
}
|
|
213
|
+
forget(routineId) {
|
|
214
|
+
delete this.state.tasks[routineId];
|
|
215
|
+
this.save();
|
|
216
|
+
}
|
|
217
|
+
clientFor(cfg) {
|
|
218
|
+
if (this.deps.clientFor)
|
|
219
|
+
return (this.client ??= this.deps.clientFor(cfg));
|
|
220
|
+
const spec = customMcpServers(cfg).mochii;
|
|
221
|
+
const key = JSON.stringify(spec ?? null);
|
|
222
|
+
if (key !== this.clientKey) {
|
|
223
|
+
void this.client?.close();
|
|
224
|
+
this.client = nexusClientFor(spec);
|
|
225
|
+
this.clientKey = key;
|
|
226
|
+
}
|
|
227
|
+
return this.client;
|
|
228
|
+
}
|
|
229
|
+
load() {
|
|
230
|
+
try {
|
|
231
|
+
if (existsSync(this.path)) {
|
|
232
|
+
const parsed = record(JSON.parse(readFileSync(this.path, "utf8")));
|
|
233
|
+
if (parsed && record(parsed.tasks))
|
|
234
|
+
return parsed;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
catch (error) {
|
|
238
|
+
this.log(`ignoring unreadable ${this.path}: ${String(error)}`);
|
|
239
|
+
}
|
|
240
|
+
return { tasks: {} };
|
|
241
|
+
}
|
|
242
|
+
save() {
|
|
243
|
+
if (this.state.blockedUntil && this.now() >= this.state.blockedUntil) {
|
|
244
|
+
delete this.state.blockedUntil;
|
|
245
|
+
delete this.state.blockedReason;
|
|
246
|
+
}
|
|
247
|
+
writeFileAtomic(this.path, JSON.stringify(this.state, null, 2));
|
|
248
|
+
}
|
|
249
|
+
log(message) {
|
|
250
|
+
(this.deps.log ?? ((line) => console.warn(`[routine-mochii-sync] ${line}`)))(message);
|
|
251
|
+
}
|
|
252
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
const MANAGED_CUSTOM_AUTH_TOOLKITS = new Set(["twitter", "x"]);
|
|
2
|
+
/**
|
|
3
|
+
* Some Composio toolkits no longer include provider-managed credentials.
|
|
4
|
+
* The official OpenMausBot broker cannot offer those connections until its
|
|
5
|
+
* project owns the corresponding OAuth app. Self-hosted Composio projects can
|
|
6
|
+
* still supply their own auth config, so keep this restriction mode-specific.
|
|
7
|
+
*/
|
|
8
|
+
export function managedConnectorUnavailableReason(mode, slug) {
|
|
9
|
+
if (mode !== "managed" || !MANAGED_CUSTOM_AUTH_TOOLKITS.has(slug.trim().toLowerCase()))
|
|
10
|
+
return null;
|
|
11
|
+
return "Twitter/X needs your own X Developer app and Composio auth config. Use self-hosted connected apps for now.";
|
|
12
|
+
}
|
|
@@ -16870,18 +16870,19 @@ var featureConfigSchema = external_exports.object({
|
|
|
16870
16870
|
* marketplace checks) and personal skills (~/.agents/skills,
|
|
16871
16871
|
* $CODEX_HOME/skills). */
|
|
16872
16872
|
codexUserMcp: external_exports.boolean().optional(),
|
|
16873
|
-
/** LLM-generated titles for new bot threads. Off until explicitly
|
|
16874
|
-
*
|
|
16875
|
-
* snippet in place — see llmThreadTitlesEnabled. */
|
|
16873
|
+
/** LLM-generated titles for new bot threads. Off until explicitly enabled; a one-shot
|
|
16874
|
+
* that fails or answers junk leaves the first-message snippet in place — see llmThreadTitlesEnabled. */
|
|
16876
16875
|
llmThreadTitles: external_exports.boolean().optional(),
|
|
16877
|
-
/** Small internal jobs (thread titles) run on Apple Intelligence on this
|
|
16878
|
-
|
|
16879
|
-
|
|
16876
|
+
/** Small internal jobs (thread titles) run on Apple Intelligence on this Mac when available. On unless false. */
|
|
16877
|
+
onDeviceHelpers: external_exports.boolean().optional(),
|
|
16878
|
+
/** Mirror routines into private Mochii tasks (server/routine-mochii-sync.ts). Off unless true; no Settings toggle. */
|
|
16879
|
+
routineMochiiSync: external_exports.boolean().optional()
|
|
16880
16880
|
});
|
|
16881
16881
|
var addonsConfigSchema = external_exports.object(
|
|
16882
16882
|
Object.fromEntries(ADDONS.map((addon) => [addon.id, external_exports.boolean().optional()]))
|
|
16883
16883
|
).strict();
|
|
16884
16884
|
var setupProgressSchema = external_exports.object({
|
|
16885
|
+
foundationRoles: external_exports.array(external_exports.enum(["assistant", "inbox", "research", "coder", "community", "ops"])).max(3).optional(),
|
|
16885
16886
|
picks: external_exports.array(external_exports.string().trim().min(1).max(40)).max(20).optional(),
|
|
16886
16887
|
chibitek: external_exports.boolean().optional(),
|
|
16887
16888
|
steps: external_exports.record(external_exports.string().trim().min(1).max(60), external_exports.enum(["done", "skipped"])).refine((steps) => Object.keys(steps).length <= 60, "too many setup steps").optional(),
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import{U as a,C as n}from"./mermaid.core-aqB1jW_w.js";const t=(r,o)=>a.lang.round(n.parse(r)[o]);export{t as c};
|
|
@@ -1,8 +0,0 @@
|
|
|
1
|
-
import{c as r,s as e}from"./flowDiagram-KWPJA3E3-D1UiqwbF.js";import{_ as a}from"./mermaid.core-aqB1jW_w.js";import"./chunk-5VM5RSS4-BL8QOZeP.js";import"./chunk-XXDRQBXY-Ck63jUMo.js";import"./chunk-WEXAMYUT-BzCC1jc4.js";import"./chunk-GWA4HPMP-Dd7yNJ0G.js";import"./channel-Nx85fHZ4.js";import"./index-XFwW09vd.js";var o=a(t=>`${e(t)}
|
|
2
|
-
.swimlane.cluster:not([data-color-id]) rect {
|
|
3
|
-
stroke: ${t.clusterBorder} !important;
|
|
4
|
-
}
|
|
5
|
-
[data-look="neo"].cluster rect {
|
|
6
|
-
filter: none;
|
|
7
|
-
}
|
|
8
|
-
`,"getStyles"),s=o,u=r({styles:s});export{u as diagram};
|