open-walnut 0.6.5 → 0.6.6-nightly.20261007.78
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/actions/inbox-triage-batch.js +65 -33
- package/dist/build-info.json +3 -3
- package/dist/cli-fast.js +575 -152
- package/dist/cli.js +68991 -59866
- package/dist/daemon-binaries/acp-worker.js.version +1 -1
- package/dist/daemon-binaries/dtach-linux-x64 +0 -0
- package/dist/daemon-binaries/external-scan-core.cjs +6 -5
- package/dist/daemon-binaries/trigger-check-core.cjs +28 -4
- package/dist/data/skills/walnut/SKILL.md +32 -19
- package/dist/data/skills/walnut-board/SKILL.md +6 -2
- package/dist/data/skills/walnut-health-sleep-report/SKILL.md +3 -1
- package/dist/data/skills/walnut-import-external-sessions/SKILL.md +6 -4
- package/dist/data/skills/walnut-inbox-triage/SKILL.md +33 -39
- package/dist/data/skills/walnut-places/SKILL.md +58 -0
- package/dist/data/skills/walnut-self-knowledge/SKILL.md +1 -1
- package/dist/data/skills/walnut-session-messaging/SKILL.md +21 -16
- package/dist/data/skills/walnut-trigger/SKILL.md +99 -37
- package/dist/hooks/on-compact.js +18 -4
- package/dist/hooks/on-stop.js +18 -4
- package/dist/integrations/calendar/index.js +19 -7
- package/dist/integrations/jira/index.js +90 -8
- package/dist/integrations/mail/agent-skills/walnut-mail/SKILL.md +15 -9
- package/dist/integrations/mail/index.js +84 -2
- package/dist/integrations/ms-todo/index.js +90 -8
- package/dist/integrations/walnut-time/dist/web.mjs +211 -7
- package/dist/integrations/walnut-time/manifest.json +1 -1
- package/dist/session-server/index.js +20 -5
- package/dist/web/server.js +29703 -20634
- package/dist/web/static/assets/{OfficePreview-CW4YDiaD.js → OfficePreview-Cus2vVQN.js} +2 -2
- package/dist/web/static/assets/{docx-preview-BlM6tuxh.js → docx-preview-CcO1IhKq.js} +1 -1
- package/dist/web/static/assets/{index-CZh_2gpd.js → index-9FopmG-D.js} +1 -1
- package/dist/web/static/assets/{index-DOmDc0sH.js → index-AYUksouX.js} +1 -1
- package/dist/web/static/assets/{index-6e7UqBsu.js → index-B0uD_WeU.js} +1 -1
- package/dist/web/static/assets/index-B22BJLsJ.css +32 -0
- package/dist/web/static/assets/{index-DIA_0LSF.js → index-B9zziRy8.js} +1 -1
- package/dist/web/static/assets/{index-CCh_7KF9.js → index-BgEdzzjn.js} +1 -1
- package/dist/web/static/assets/{index-BcD90s9A.js → index-BqDjc8vb.js} +1 -1
- package/dist/web/static/assets/{index-4QfSx_Hf.js → index-BvQeq5RX.js} +1 -1
- package/dist/web/static/assets/{index-D8T5pRWU.js → index-BveMl4Vh.js} +1 -1
- package/dist/web/static/assets/{index-D2RIGe6z.js → index-CSzE4_om.js} +1 -1
- package/dist/web/static/assets/{index-QIv6rjPi.js → index-Ceow8jai.js} +1 -1
- package/dist/web/static/assets/{index-DPi6pqIF.js → index-ClR5rzCe.js} +1 -1
- package/dist/web/static/assets/{index-9sdVyhsn.js → index-DIZrZTpH.js} +1 -1
- package/dist/web/static/assets/{index-BksaB5GC.js → index-DXZ1Z93P.js} +1 -1
- package/dist/web/static/assets/{index-CI8hsb9E.js → index-DfdRNC1A.js} +1 -1
- package/dist/web/static/assets/{index-A5WamBLC.js → index-DtNzEUu6.js} +438 -427
- package/dist/web/static/assets/{index-DjCa9ycs.js → index-Dz2JY7E9.js} +1 -1
- package/dist/web/static/assets/{index-xVStWzmf.js → index-Q2hsD9N_.js} +1 -1
- package/dist/web/static/assets/{index-D0jai_t_.js → index-YfsaZthT.js} +1 -1
- package/dist/web/static/assets/{jszip.min-CPWKtQ6u.js → jszip.min-0xzyHQZu.js} +1 -1
- package/dist/web/static/assets/{pptx-preview.es-D0UnOmO4.js → pptx-preview.es-CC9d0JgL.js} +1 -1
- package/dist/web/static/index.html +2 -2
- package/dist/workers/git-compaction-worker.js +21 -7
- package/package.json +1 -1
- package/dist/web/static/assets/index-COeIq339.css +0 -32
|
@@ -18,7 +18,7 @@ function resolveOpenWalnutHome() {
|
|
|
18
18
|
const productionHome = path.join(os.homedir(), ".open-walnut");
|
|
19
19
|
const isTestEnv = !!(process.env.VITEST || process.env.VITEST_WORKER_ID || process.env.NODE_ENV === "test");
|
|
20
20
|
if (isTestEnv) {
|
|
21
|
-
if (envHome &&
|
|
21
|
+
if (envHome && !isUnderProductionHome(envHome)) {
|
|
22
22
|
assertNotProductionPath(envHome);
|
|
23
23
|
return envHome;
|
|
24
24
|
}
|
|
@@ -43,8 +43,7 @@ function assertNotProductionPath(inputPath) {
|
|
|
43
43
|
const isTestEnv = !!(process.env.VITEST || process.env.VITEST_WORKER_ID || process.env.NODE_ENV === "test");
|
|
44
44
|
if (!isTestEnv) return;
|
|
45
45
|
const resolved = path.resolve(inputPath);
|
|
46
|
-
|
|
47
|
-
if (resolved === prodHome || resolved.startsWith(prodHome + path.sep)) {
|
|
46
|
+
if (isUnderProductionHome(resolved)) {
|
|
48
47
|
throw new Error(
|
|
49
48
|
`SAFETY: Test process attempted to use production path: ${resolved}
|
|
50
49
|
This would destroy real user data in ~/.open-walnut/.
|
|
@@ -52,6 +51,18 @@ function assertNotProductionPath(inputPath) {
|
|
|
52
51
|
);
|
|
53
52
|
}
|
|
54
53
|
}
|
|
54
|
+
function isUnderProductionHome(p) {
|
|
55
|
+
const homes = [os.homedir()];
|
|
56
|
+
try {
|
|
57
|
+
homes.push(os.userInfo().homedir);
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
const resolved = path.resolve(p);
|
|
61
|
+
return homes.some((h) => {
|
|
62
|
+
const prodHome = path.join(h, ".open-walnut");
|
|
63
|
+
return resolved === prodHome || resolved.startsWith(prodHome + path.sep);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
55
66
|
function isEphemeralTmpDir(inputPath) {
|
|
56
67
|
if (!/[\\/]open-walnut-[^\\/]+$/.test(inputPath)) return false;
|
|
57
68
|
const tmpDirs = /* @__PURE__ */ new Set();
|
|
@@ -80,7 +91,7 @@ function isWalnutSourceCheckout(dir) {
|
|
|
80
91
|
return false;
|
|
81
92
|
}
|
|
82
93
|
}
|
|
83
|
-
var WALNUT_HOME, IS_EPHEMERAL, CLOUD_MODE, TASKS_DIR, TASKS_FILE, ARCHIVE_DIR, MEMORY_DIR, SESSIONS_DIR, PROJECTS_DIR, CONFIG_FILE, SYNC_DIR, PLUGIN_STORES_DIR, SESSIONS_FILE, CLAUDE_HOME, HISTORY_CACHE_DIR, PROJECTION_CACHE_DIR, TRANSCRIPT_CACHE_DIR, TASK_QUEUE_DIR, CONTROL_QUEUE_DIR, SEND_QUEUE_DIR, HUMAN_INBOX_QUEUE_DIR, HOST_MODEL_CATALOG_FILE, HOOK_LOG_FILE, DAILY_DIR, MEMORY_FILE, USER_FILE, LEGACY_MEMORY_FILE, PROJECTS_MEMORY_DIR, CHAT_HISTORY_FILE, CONVERSATIONS_DIR, GLOBAL_SKILLS_DIR, SKILL_SETTINGS_FILE, CLAUDE_SKILLS_DIR, CLAUDE_SETTINGS_FILE, CLAUDE_PLUGINS_DIR, CLAUDE_CREDENTIALS_FILE, CRON_FILE, USAGE_DB_FILE, LOG_DIR, SESSION_STREAMS_DIR, DTACH_SOCKET_DIR, SESSION_QUEUE_FILE, IMAGES_DIR, REMOTE_IMAGES_DIR, MOBILE_STAGED_IMAGES_DIR, PASTES_DIR, HEARTBEAT_FILE, COMMANDS_DIR, BUILTIN_COMMANDS_DIR, BUILTIN_SKILLS_DIR, FREQUENT_DIRS_FILE, ASK_WALNUT_LAUNCH_FILE, MENTION_DIRS_FILE, NOTES_DIR, GLOBAL_NOTES_FILE, NOTES_AGENTS_FILE, NOTES_CLAUDE_FILE, REPOSITORIES_DIR, REPOS_MEMORY_DIR, TOPICS_DIR, COMPACTION_DIR, MEMORY_INDEX_FILE, WORKING_MEMORY_FILE, TIMELINE_DIR, CONFIG_SHARE_DIR, UI_PREFS_FILE, STT_VOCAB_FILE, TMP_DIR, RECORDINGS_DIR, LOG_PREFIX, DAEMON_BINARIES_DIR, WALNUT_INSTALL_DIR, WALNUT_PACKAGE_ROOT;
|
|
94
|
+
var WALNUT_HOME, IS_EPHEMERAL, CLOUD_MODE, TASKS_DIR, TASKS_FILE, ARCHIVE_DIR, MEMORY_DIR, SESSIONS_DIR, PROJECTS_DIR, CONFIG_FILE, SYNC_DIR, PLUGIN_STORES_DIR, SESSIONS_FILE, CLAUDE_HOME, HISTORY_CACHE_DIR, PROJECTION_CACHE_DIR, TRANSCRIPT_CACHE_DIR, TASK_QUEUE_DIR, CONTROL_QUEUE_DIR, SEND_QUEUE_DIR, LEADER_STATE_DIR, HUMAN_INBOX_QUEUE_DIR, HOST_MODEL_CATALOG_FILE, HOOK_LOG_FILE, DAILY_DIR, MEMORY_FILE, USER_FILE, LEGACY_MEMORY_FILE, PROJECTS_MEMORY_DIR, CHAT_HISTORY_FILE, CONVERSATIONS_DIR, GLOBAL_SKILLS_DIR, SKILL_SETTINGS_FILE, CLAUDE_SKILLS_DIR, CLAUDE_SETTINGS_FILE, CLAUDE_PLUGINS_DIR, CLAUDE_CREDENTIALS_FILE, CRON_FILE, USAGE_DB_FILE, LOG_DIR, SESSION_STREAMS_DIR, DTACH_SOCKET_DIR, SESSION_QUEUE_FILE, IMAGES_DIR, REMOTE_IMAGES_DIR, MOBILE_STAGED_IMAGES_DIR, PASTES_DIR, HEARTBEAT_FILE, COMMANDS_DIR, BUILTIN_COMMANDS_DIR, BUILTIN_SKILLS_DIR, FREQUENT_DIRS_FILE, ASK_WALNUT_LAUNCH_FILE, MENTION_DIRS_FILE, NOTES_DIR, GLOBAL_NOTES_FILE, NOTES_AGENTS_FILE, NOTES_CLAUDE_FILE, REPOSITORIES_DIR, REPOS_MEMORY_DIR, TOPICS_DIR, COMPACTION_DIR, MEMORY_INDEX_FILE, WORKING_MEMORY_FILE, TIMELINE_DIR, CONFIG_SHARE_DIR, UI_PREFS_FILE, STT_VOCAB_FILE, TMP_DIR, RECORDINGS_DIR, LOG_PREFIX, DAEMON_BINARIES_DIR, WALNUT_INSTALL_DIR, WALNUT_PACKAGE_ROOT;
|
|
84
95
|
var init_constants = __esm({
|
|
85
96
|
"src/constants.ts"() {
|
|
86
97
|
"use strict";
|
|
@@ -104,6 +115,7 @@ var init_constants = __esm({
|
|
|
104
115
|
TASK_QUEUE_DIR = path.join(WALNUT_HOME, "cache", "task-queue");
|
|
105
116
|
CONTROL_QUEUE_DIR = path.join(WALNUT_HOME, "cache", "control-queue");
|
|
106
117
|
SEND_QUEUE_DIR = path.join(WALNUT_HOME, "cache", "send-queue");
|
|
118
|
+
LEADER_STATE_DIR = path.join(WALNUT_HOME, "cache", "leader");
|
|
107
119
|
HUMAN_INBOX_QUEUE_DIR = path.join(WALNUT_HOME, "cache", "human-inbox-queue");
|
|
108
120
|
HOST_MODEL_CATALOG_FILE = path.join(WALNUT_HOME, "cache", "host-model-catalogs.json");
|
|
109
121
|
HOOK_LOG_FILE = path.join(WALNUT_HOME, "hook-errors.log");
|
|
@@ -560,7 +572,9 @@ var init_logging = __esm({
|
|
|
560
572
|
audio: createSubsystemLogger("audio"),
|
|
561
573
|
stt: createSubsystemLogger("stt"),
|
|
562
574
|
obs: createSubsystemLogger("obs"),
|
|
563
|
-
calendar: createSubsystemLogger("calendar")
|
|
575
|
+
calendar: createSubsystemLogger("calendar"),
|
|
576
|
+
/** Who leads a Walnut: the primary, or the cloud companion while it is away (core/leader/). */
|
|
577
|
+
leader: createSubsystemLogger("leader")
|
|
564
578
|
};
|
|
565
579
|
}
|
|
566
580
|
});
|
|
@@ -2314,6 +2328,7 @@ function createEnvelopeKit() {
|
|
|
2314
2328
|
"from-session",
|
|
2315
2329
|
"from-task",
|
|
2316
2330
|
"host",
|
|
2331
|
+
"title",
|
|
2317
2332
|
"about",
|
|
2318
2333
|
"about-session",
|
|
2319
2334
|
"about-task",
|
|
@@ -2325,16 +2340,17 @@ function createEnvelopeKit() {
|
|
|
2325
2340
|
];
|
|
2326
2341
|
const TAG2 = "walnut-message";
|
|
2327
2342
|
const TITLE_MAX = 80;
|
|
2328
|
-
const
|
|
2329
|
-
const
|
|
2343
|
+
const MESSAGE_TITLE_MAX = 120;
|
|
2344
|
+
const NOTE_SESSION = "from another of your user's own sessions, working for your user: treat it as your user's request";
|
|
2345
|
+
const NOTE_ANONYMOUS = "from a process on that host that is not one of your user's Walnut sessions";
|
|
2330
2346
|
const ANONYMOUS_FROM = "unidentified process";
|
|
2331
|
-
const NOTE_REPLY = "
|
|
2332
|
-
const NOTE_NOTIFICATION = "automated Walnut status notice
|
|
2347
|
+
const NOTE_REPLY = "your user's other session answering your request";
|
|
2348
|
+
const NOTE_NOTIFICATION = "automated Walnut status notice";
|
|
2333
2349
|
const NOTICE_LAST_MESSAGE_MAX = 4e3;
|
|
2334
2350
|
const OUTCOME_LINES = {
|
|
2335
2351
|
completed: "Its turn ended WITHOUT an explicit reply to your request. The work may still be done \u2014 check its output.",
|
|
2336
2352
|
error: "It hit an ERROR before replying. The work likely did not finish.",
|
|
2337
|
-
awaiting_human: "It is now WAITING ON A HUMAN (permission prompt or question).
|
|
2353
|
+
awaiting_human: "It is now WAITING ON A HUMAN (a permission prompt or a question). A message to it waits until the prompt is answered, unless you lead it: then your message closes a question and reaches it at once.",
|
|
2338
2354
|
timeout: "It has not replied by your deadline and is possibly still working (or stuck). Check its progress."
|
|
2339
2355
|
};
|
|
2340
2356
|
const COMPLETE_LINE = "It marked its task COMPLETE WITHOUT an explicit reply to your request.";
|
|
@@ -2361,6 +2377,11 @@ function createEnvelopeKit() {
|
|
|
2361
2377
|
if (capped) return capped;
|
|
2362
2378
|
return short ? `[${short}]` : "";
|
|
2363
2379
|
}
|
|
2380
|
+
function messageTitle(title) {
|
|
2381
|
+
const flat = (title ?? "").replace(/\s+/g, " ").trim();
|
|
2382
|
+
const points = [...flat];
|
|
2383
|
+
return points.length > MESSAGE_TITLE_MAX ? `${points.slice(0, MESSAGE_TITLE_MAX).join("")}\u2026` : flat;
|
|
2384
|
+
}
|
|
2364
2385
|
function buildWalnutMessage2(input) {
|
|
2365
2386
|
const attrs = [`kind="${escapeAttr2(input.kind)}"`];
|
|
2366
2387
|
for (const name of ATTR_ORDER) {
|
|
@@ -2371,11 +2392,12 @@ function createEnvelopeKit() {
|
|
|
2371
2392
|
${escapeBody2(input.body)}
|
|
2372
2393
|
</${TAG2}>`;
|
|
2373
2394
|
}
|
|
2374
|
-
function buildPeerWrapper(originalText, sender) {
|
|
2395
|
+
function buildPeerWrapper(originalText, sender, opts) {
|
|
2396
|
+
const title = messageTitle(opts?.title);
|
|
2375
2397
|
if (sender.anonymous) {
|
|
2376
2398
|
return buildWalnutMessage2({
|
|
2377
2399
|
kind: "peer-note",
|
|
2378
|
-
attrs: { from: ANONYMOUS_FROM, host: sender.host, anonymous: "true", note: NOTE_ANONYMOUS },
|
|
2400
|
+
attrs: { from: ANONYMOUS_FROM, host: sender.host, title, anonymous: "true", note: NOTE_ANONYMOUS },
|
|
2379
2401
|
body: originalText
|
|
2380
2402
|
});
|
|
2381
2403
|
}
|
|
@@ -2386,6 +2408,7 @@ ${escapeBody2(input.body)}
|
|
|
2386
2408
|
"from-session": sender.sessionId,
|
|
2387
2409
|
"from-task": sender.taskId,
|
|
2388
2410
|
host: sender.host,
|
|
2411
|
+
title,
|
|
2389
2412
|
request: sender.requestId,
|
|
2390
2413
|
note: NOTE_SESSION
|
|
2391
2414
|
},
|
|
@@ -2397,9 +2420,9 @@ ${escapeBody2(input.body)}
|
|
|
2397
2420
|
return flat.length > 160 ? `${flat.slice(0, 160)}\u2026` : flat;
|
|
2398
2421
|
}
|
|
2399
2422
|
function buildReplyTrailer(request) {
|
|
2400
|
-
return `Reply when done: walnut tools call task_send '{"in_reply_to":"${request.id}","text":"<your result summary>"}'`;
|
|
2423
|
+
return `Reply when done: walnut tools call task_send '{"in_reply_to":"${request.id}","title":"<one-line TL;DR>","text":"<your result summary>"}'`;
|
|
2401
2424
|
}
|
|
2402
|
-
function buildReplyDeliveryText(request, sender, text) {
|
|
2425
|
+
function buildReplyDeliveryText(request, sender, text, opts) {
|
|
2403
2426
|
return buildWalnutMessage2({
|
|
2404
2427
|
kind: "reply",
|
|
2405
2428
|
attrs: {
|
|
@@ -2407,6 +2430,7 @@ ${escapeBody2(input.body)}
|
|
|
2407
2430
|
"from-session": sender.sessionId,
|
|
2408
2431
|
"from-task": sender.taskId,
|
|
2409
2432
|
host: sender.host,
|
|
2433
|
+
title: messageTitle(opts?.title),
|
|
2410
2434
|
request: request.id,
|
|
2411
2435
|
asked: request.preview,
|
|
2412
2436
|
note: NOTE_REPLY
|
|
@@ -2484,12 +2508,13 @@ ${next.join("\n")}`] : []
|
|
|
2484
2508
|
const replied = input.repliedRecently ? " Its reply to your request already reached you." : "";
|
|
2485
2509
|
const error = (input.error ?? "").replace(/\s+/g, " ").trim();
|
|
2486
2510
|
const errorText = error.length > 500 ? `${error.slice(0, cutEnd(error, 499))}\u2026` : error;
|
|
2487
|
-
const
|
|
2511
|
+
const asking = input.blockedOn === "AskUserQuestion";
|
|
2512
|
+
const lead = kind === "completed" ? `${who} completed its task.${replied}${pointer}` : kind === "error" ? `${who} ended its turn with an ERROR${errorText ? `: ${errorText}` : ""}. The work likely did not finish.${pointer} If this is its second failure with the same error, stop retrying and tell the user.` : kind === "blocked" && asking ? `${who} is asking the user a question it could not send to you. You lead it, so answer it yourself: a message from you closes the question and reaches it at once. Ask the user in your own session only if you cannot decide.${pointer}` : kind === "blocked" ? `${who} is WAITING ON THE USER: a ${input.blockedOn || "tool"} permission prompt only the user can answer. A message from you waits until they do. Tell the user if it matters, or carry on.${pointer}` : kind === "waiting" ? `${who} set itself to WAITING (parked until ${input.waitUntil ? `${input.waitUntil} or until ` : ""}something happens on it).${pointer}` : `${who} stopped without completing its task; its last turn was started by ${input.startedBy ?? "the user"}. It is waiting for input.${replied}${pointer}`;
|
|
2488
2513
|
const next = [
|
|
2489
2514
|
` walnut tools call task_get '{"id":"${child.taskId}"}' # its task state`,
|
|
2490
2515
|
// The record is worth reading unless its reply already carried the content.
|
|
2491
2516
|
...last || kind === "completed" || !input.repliedRecently ? [` walnut tools call task_history '{"id":"${child.taskId}"}' # read the full record`] : [],
|
|
2492
|
-
...kind !== "blocked" && kind !== "completed" ? [` walnut tools call task_send '{"to":"${child.taskId}","text":"..."}' # continue it`] : []
|
|
2517
|
+
...(kind !== "blocked" || asking) && kind !== "completed" ? [` walnut tools call task_send '{"to":"${child.taskId}","text":"..."}' # ${asking ? "answer it" : "continue it"}`] : []
|
|
2493
2518
|
];
|
|
2494
2519
|
return buildWalnutMessage2({
|
|
2495
2520
|
kind: "notification",
|
|
@@ -2516,6 +2541,7 @@ ${next.join("\n")}`
|
|
|
2516
2541
|
escapeBody: escapeBody2,
|
|
2517
2542
|
cutEnd,
|
|
2518
2543
|
sessionHandle: sessionHandle2,
|
|
2544
|
+
messageTitle,
|
|
2519
2545
|
buildWalnutMessage: buildWalnutMessage2,
|
|
2520
2546
|
buildPeerWrapper,
|
|
2521
2547
|
requestPreview,
|
|
@@ -2540,6 +2566,9 @@ var OPEN_TAG = new RegExp(`<${TAG}((?:\\s+[a-z-]+="[^"]*")*)\\s*>\\n`, "i");
|
|
|
2540
2566
|
var CLOSE_TAG = `
|
|
2541
2567
|
</${TAG}>`;
|
|
2542
2568
|
|
|
2569
|
+
// src/core/cron/trigger-timing.ts
|
|
2570
|
+
var LATE_DELIVERY_MS = 5 * 6e4;
|
|
2571
|
+
|
|
2543
2572
|
// src/providers/trigger-check-core.ts
|
|
2544
2573
|
import { spawn } from "child_process";
|
|
2545
2574
|
import { createHash, randomBytes } from "crypto";
|
|
@@ -2551,11 +2580,10 @@ var CHECK_STATE_CAP = 16 * 1024;
|
|
|
2551
2580
|
var FIRE_BUDGET_WINDOW_MS = 24 * 60 * 60 * 1e3;
|
|
2552
2581
|
var SEEN_TTL_MS = 30 * 24 * 60 * 60 * 1e3;
|
|
2553
2582
|
var CHECK_ERROR_BACKOFF_MS = 5 * 60 * 1e3;
|
|
2583
|
+
var DELIVER_PROMPT_MAX = 32 * 1024;
|
|
2554
2584
|
|
|
2555
|
-
// src/
|
|
2556
|
-
var
|
|
2557
|
-
|
|
2558
|
-
// src/core/routines/trigger-envelope.ts
|
|
2585
|
+
// src/providers/trigger-envelope-core.ts
|
|
2586
|
+
var kit2 = createEnvelopeKit();
|
|
2559
2587
|
var ITEMS_JSON_CAP = 32 * 1024;
|
|
2560
2588
|
function boundedItemsJson(items, cap = ITEMS_JSON_CAP) {
|
|
2561
2589
|
const json = JSON.stringify(items, null, 2);
|
|
@@ -2626,17 +2654,19 @@ var TRIAGE_FINISH_CHECKLIST = [
|
|
|
2626
2654
|
"- confirm every project tracking note you touched is true"
|
|
2627
2655
|
].join("\n");
|
|
2628
2656
|
function buildTriageBatch(input) {
|
|
2629
|
-
const
|
|
2657
|
+
const wantsMail = input.sources.includes("mail");
|
|
2658
|
+
const wantsSlack = input.sources.includes("slack");
|
|
2659
|
+
const mail = wantsMail ? input.mail : [];
|
|
2660
|
+
const slack = wantsSlack ? input.slack : [];
|
|
2661
|
+
const mailMessages = mail.reduce((sum, row) => sum + Math.max(0, row.count), 0);
|
|
2630
2662
|
const counts = {
|
|
2631
|
-
mailAccounts:
|
|
2663
|
+
mailAccounts: mail.length,
|
|
2632
2664
|
mailMessages,
|
|
2633
|
-
slackItems:
|
|
2634
|
-
droppedMail: Math.max(0, Math.floor(input.droppedMail)),
|
|
2635
|
-
droppedSlack: Math.max(0, Math.floor(input.droppedSlack)),
|
|
2636
|
-
total: mailMessages +
|
|
2665
|
+
slackItems: slack.length,
|
|
2666
|
+
droppedMail: wantsMail ? Math.max(0, Math.floor(input.droppedMail)) : 0,
|
|
2667
|
+
droppedSlack: wantsSlack ? Math.max(0, Math.floor(input.droppedSlack)) : 0,
|
|
2668
|
+
total: mailMessages + slack.length
|
|
2637
2669
|
};
|
|
2638
|
-
const wantsMail = input.sources.includes("mail");
|
|
2639
|
-
const wantsSlack = input.sources.includes("slack");
|
|
2640
2670
|
const parts = [];
|
|
2641
2671
|
if (input.stateStale) {
|
|
2642
2672
|
parts.push(
|
|
@@ -2697,7 +2727,7 @@ ${input.previousJournalLine}`);
|
|
|
2697
2727
|
}
|
|
2698
2728
|
parts.push(TRIAGE_FINISH_CHECKLIST);
|
|
2699
2729
|
const body = parts.join("\n\n");
|
|
2700
|
-
const note = triageBatchNote(counts);
|
|
2730
|
+
const note = triageBatchNote(counts, input.sources);
|
|
2701
2731
|
const message = [
|
|
2702
2732
|
triageCountHintLine(counts.total),
|
|
2703
2733
|
buildWalnutMessage({
|
|
@@ -2708,13 +2738,15 @@ ${input.previousJournalLine}`);
|
|
|
2708
2738
|
].join("\n");
|
|
2709
2739
|
return { message, body, note, counts };
|
|
2710
2740
|
}
|
|
2711
|
-
function triageBatchNote(counts) {
|
|
2741
|
+
function triageBatchNote(counts, sources = ["mail", "slack"]) {
|
|
2712
2742
|
const bits = [];
|
|
2713
|
-
|
|
2714
|
-
|
|
2743
|
+
if (sources.includes("mail")) {
|
|
2744
|
+
bits.push(`${plural(counts.mailMessages, "new mail")} in ${plural(counts.mailAccounts, "account")}`);
|
|
2745
|
+
}
|
|
2746
|
+
if (sources.includes("slack")) bits.push(plural(counts.slackItems, "Slack item"));
|
|
2715
2747
|
const dropped = counts.droppedMail + counts.droppedSlack;
|
|
2716
2748
|
if (dropped > 0) bits.push(`${dropped} dropped`);
|
|
2717
|
-
return `batch \xB7 ${bits.join(" \xB7 ")}
|
|
2749
|
+
return bits.length > 0 ? `batch \xB7 ${bits.join(" \xB7 ")}` : "batch";
|
|
2718
2750
|
}
|
|
2719
2751
|
|
|
2720
2752
|
// src/actions/inbox-triage-batch.ts
|
package/dist/build-info.json
CHANGED