@askexenow/exe-os 0.9.34 → 0.9.36
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/bin/backfill-conversations.js +212 -11
- package/dist/bin/backfill-responses.js +212 -11
- package/dist/bin/backfill-vectors.js +14 -3
- package/dist/bin/cleanup-stale-review-tasks.js +224 -12
- package/dist/bin/cli.js +265 -23
- package/dist/bin/exe-agent.js +1 -1
- package/dist/bin/exe-assign.js +217 -12
- package/dist/bin/exe-boot.js +25 -4
- package/dist/bin/exe-call.js +7 -5
- package/dist/bin/exe-dispatch.js +229 -13
- package/dist/bin/exe-doctor.js +14 -3
- package/dist/bin/exe-export-behaviors.js +301 -14
- package/dist/bin/exe-forget.js +245 -21
- package/dist/bin/exe-gateway.js +229 -13
- package/dist/bin/exe-heartbeat.js +224 -12
- package/dist/bin/exe-kill.js +224 -12
- package/dist/bin/exe-launch-agent.js +177 -9
- package/dist/bin/exe-link.js +8 -0
- package/dist/bin/exe-new-employee.js +26 -2
- package/dist/bin/exe-pending-messages.js +224 -12
- package/dist/bin/exe-pending-notifications.js +224 -12
- package/dist/bin/exe-pending-reviews.js +224 -12
- package/dist/bin/exe-rename.js +9 -1
- package/dist/bin/exe-review.js +224 -12
- package/dist/bin/exe-search.js +246 -21
- package/dist/bin/exe-session-cleanup.js +229 -13
- package/dist/bin/exe-start-codex.js +161 -5
- package/dist/bin/exe-start-opencode.js +172 -5
- package/dist/bin/exe-status.js +224 -12
- package/dist/bin/exe-team.js +224 -12
- package/dist/bin/git-sweep.js +229 -13
- package/dist/bin/graph-backfill.js +94 -3
- package/dist/bin/graph-export.js +224 -12
- package/dist/bin/install.js +25 -1
- package/dist/bin/intercom-check.js +229 -13
- package/dist/bin/scan-tasks.js +229 -13
- package/dist/bin/setup.js +15 -5
- package/dist/bin/shard-migrate.js +94 -3
- package/dist/gateway/index.js +229 -13
- package/dist/hooks/bug-report-worker.js +229 -13
- package/dist/hooks/codex-stop-task-finalizer.js +224 -12
- package/dist/hooks/commit-complete.js +229 -13
- package/dist/hooks/error-recall.js +246 -21
- package/dist/hooks/ingest.js +224 -12
- package/dist/hooks/instructions-loaded.js +224 -12
- package/dist/hooks/notification.js +224 -12
- package/dist/hooks/post-compact.js +224 -12
- package/dist/hooks/post-tool-combined.js +246 -21
- package/dist/hooks/pre-compact.js +229 -13
- package/dist/hooks/pre-tool-use.js +234 -18
- package/dist/hooks/prompt-submit.js +346 -23
- package/dist/hooks/session-end.js +229 -13
- package/dist/hooks/session-start.js +418 -42
- package/dist/hooks/stop.js +224 -12
- package/dist/hooks/subagent-stop.js +224 -12
- package/dist/hooks/summary-worker.js +15 -2
- package/dist/index.js +229 -13
- package/dist/lib/cloud-sync.js +8 -0
- package/dist/lib/consolidation.js +3 -1
- package/dist/lib/database.js +8 -0
- package/dist/lib/db.js +8 -0
- package/dist/lib/device-registry.js +8 -0
- package/dist/lib/employee-templates.js +7 -5
- package/dist/lib/exe-daemon.js +1776 -1433
- package/dist/lib/hybrid-search.js +246 -21
- package/dist/lib/schedules.js +14 -3
- package/dist/lib/store.js +217 -12
- package/dist/lib/tasks.js +5 -1
- package/dist/lib/tmux-routing.js +5 -1
- package/dist/mcp/server.js +331 -37
- package/dist/mcp/tools/create-task.js +5 -1
- package/dist/mcp/tools/update-task.js +5 -1
- package/dist/runtime/index.js +229 -13
- package/dist/tui/App.js +229 -13
- package/package.json +1 -1
- package/src/commands/exe/save.md +48 -0
package/dist/bin/cli.js
CHANGED
|
@@ -824,6 +824,7 @@ __export(installer_exports, {
|
|
|
824
824
|
});
|
|
825
825
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
826
826
|
import { existsSync as existsSync7, readFileSync as readFileSync5, writeFileSync as writeFileSync4, copyFileSync, mkdirSync as mkdirSync3 } from "fs";
|
|
827
|
+
import { createHash } from "crypto";
|
|
827
828
|
import path6 from "path";
|
|
828
829
|
import os5 from "os";
|
|
829
830
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -1508,7 +1509,30 @@ function setupTmux(home) {
|
|
|
1508
1509
|
return;
|
|
1509
1510
|
}
|
|
1510
1511
|
mkdirSync3(exeDir, { recursive: true });
|
|
1511
|
-
|
|
1512
|
+
if (existsSync7(exeTmuxConf)) {
|
|
1513
|
+
const currentContent = readFileSync5(exeTmuxConf, "utf8");
|
|
1514
|
+
const newContent = readFileSync5(assetPath, "utf8");
|
|
1515
|
+
const currentHash = createHash("sha256").update(currentContent).digest("hex");
|
|
1516
|
+
const newHash = createHash("sha256").update(newContent).digest("hex");
|
|
1517
|
+
if (currentHash !== newHash) {
|
|
1518
|
+
const shippedPath = path6.join(exeDir, ".tmux.conf.shipped-hash");
|
|
1519
|
+
const lastShippedHash = existsSync7(shippedPath) ? readFileSync5(shippedPath, "utf8").trim() : "";
|
|
1520
|
+
if (lastShippedHash && currentHash !== lastShippedHash) {
|
|
1521
|
+
process.stderr.write("exe-os: tmux config has user customizations \u2014 skipping overwrite\n");
|
|
1522
|
+
} else {
|
|
1523
|
+
copyFileSync(assetPath, exeTmuxConf);
|
|
1524
|
+
process.stderr.write("exe-os: tmux config updated\n");
|
|
1525
|
+
}
|
|
1526
|
+
writeFileSync4(shippedPath, newHash, "utf8");
|
|
1527
|
+
} else {
|
|
1528
|
+
process.stderr.write("exe-os: tmux config already up to date\n");
|
|
1529
|
+
}
|
|
1530
|
+
} else {
|
|
1531
|
+
copyFileSync(assetPath, exeTmuxConf);
|
|
1532
|
+
const newContent = readFileSync5(assetPath, "utf8");
|
|
1533
|
+
const newHash = createHash("sha256").update(newContent).digest("hex");
|
|
1534
|
+
writeFileSync4(path6.join(exeDir, ".tmux.conf.shipped-hash"), newHash, "utf8");
|
|
1535
|
+
}
|
|
1512
1536
|
if (existsSync7(userTmuxConf)) {
|
|
1513
1537
|
const existing = readFileSync5(userTmuxConf, "utf8");
|
|
1514
1538
|
if (!existing.includes(sourceLine)) {
|
|
@@ -3920,6 +3944,14 @@ async function ensureSchema() {
|
|
|
3920
3944
|
);
|
|
3921
3945
|
} catch {
|
|
3922
3946
|
}
|
|
3947
|
+
try {
|
|
3948
|
+
await client.execute(
|
|
3949
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
3950
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
3951
|
+
WHERE content_hash IS NOT NULL`
|
|
3952
|
+
);
|
|
3953
|
+
} catch {
|
|
3954
|
+
}
|
|
3923
3955
|
await client.executeMultiple(`
|
|
3924
3956
|
CREATE TABLE IF NOT EXISTS entities (
|
|
3925
3957
|
id TEXT PRIMARY KEY,
|
|
@@ -6794,6 +6826,197 @@ var init_state_bus = __esm({
|
|
|
6794
6826
|
}
|
|
6795
6827
|
});
|
|
6796
6828
|
|
|
6829
|
+
// src/lib/memory-write-governor.ts
|
|
6830
|
+
import { createHash as createHash2 } from "crypto";
|
|
6831
|
+
function normalizeMemoryText(text) {
|
|
6832
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
6833
|
+
}
|
|
6834
|
+
function classifyMemoryType(input) {
|
|
6835
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
6836
|
+
const tool = input.tool_name.toLowerCase();
|
|
6837
|
+
const text = input.raw_text.toLowerCase();
|
|
6838
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
6839
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
6840
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
6841
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
6842
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
6843
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
6844
|
+
return "raw";
|
|
6845
|
+
}
|
|
6846
|
+
function shouldDropMemory(text) {
|
|
6847
|
+
const normalized = normalizeMemoryText(text);
|
|
6848
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
6849
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
6850
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
6851
|
+
}
|
|
6852
|
+
return { drop: false };
|
|
6853
|
+
}
|
|
6854
|
+
function shouldSkipEmbedding(input) {
|
|
6855
|
+
const type = classifyMemoryType(input);
|
|
6856
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
6857
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
6858
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
6859
|
+
return false;
|
|
6860
|
+
}
|
|
6861
|
+
function hashMemoryContent(text) {
|
|
6862
|
+
return createHash2("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
6863
|
+
}
|
|
6864
|
+
function scopedDedupArgs(input) {
|
|
6865
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
6866
|
+
}
|
|
6867
|
+
function governMemoryRecord(record) {
|
|
6868
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
6869
|
+
const memoryType = classifyMemoryType({
|
|
6870
|
+
raw_text: normalized,
|
|
6871
|
+
agent_id: record.agent_id,
|
|
6872
|
+
project_name: record.project_name,
|
|
6873
|
+
tool_name: record.tool_name,
|
|
6874
|
+
memory_type: record.memory_type
|
|
6875
|
+
});
|
|
6876
|
+
const drop = shouldDropMemory(normalized);
|
|
6877
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
6878
|
+
raw_text: normalized,
|
|
6879
|
+
agent_id: record.agent_id,
|
|
6880
|
+
project_name: record.project_name,
|
|
6881
|
+
tool_name: record.tool_name,
|
|
6882
|
+
memory_type: memoryType
|
|
6883
|
+
});
|
|
6884
|
+
return {
|
|
6885
|
+
record: {
|
|
6886
|
+
...record,
|
|
6887
|
+
raw_text: normalized,
|
|
6888
|
+
memory_type: memoryType,
|
|
6889
|
+
vector: skipEmbedding ? null : record.vector
|
|
6890
|
+
},
|
|
6891
|
+
contentHash: hashMemoryContent(normalized),
|
|
6892
|
+
shouldDrop: drop.drop,
|
|
6893
|
+
dropReason: drop.reason,
|
|
6894
|
+
skipEmbedding,
|
|
6895
|
+
hygiene: {
|
|
6896
|
+
dedup: true,
|
|
6897
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
6898
|
+
}
|
|
6899
|
+
};
|
|
6900
|
+
}
|
|
6901
|
+
async function findScopedDuplicate(input) {
|
|
6902
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
6903
|
+
const client = getClient2();
|
|
6904
|
+
const args2 = scopedDedupArgs(input);
|
|
6905
|
+
let sql = `SELECT id FROM memories
|
|
6906
|
+
WHERE content_hash = ?
|
|
6907
|
+
AND agent_id = ?
|
|
6908
|
+
AND project_name = ?
|
|
6909
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
6910
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
6911
|
+
if (input.excludeId) {
|
|
6912
|
+
sql += " AND id != ?";
|
|
6913
|
+
args2.push(input.excludeId);
|
|
6914
|
+
}
|
|
6915
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
6916
|
+
const result = await client.execute({ sql, args: args2 });
|
|
6917
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
6918
|
+
}
|
|
6919
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
6920
|
+
try {
|
|
6921
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
6922
|
+
const client = getClient2();
|
|
6923
|
+
const current = await client.execute({
|
|
6924
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
6925
|
+
importance, timestamp
|
|
6926
|
+
FROM memories
|
|
6927
|
+
WHERE id = ?
|
|
6928
|
+
LIMIT 1`,
|
|
6929
|
+
args: [memoryId]
|
|
6930
|
+
});
|
|
6931
|
+
const row = current.rows[0];
|
|
6932
|
+
if (!row) return;
|
|
6933
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
6934
|
+
const contentHash2 = row.content_hash ? String(row.content_hash) : null;
|
|
6935
|
+
const agentId = String(row.agent_id);
|
|
6936
|
+
const projectName = String(row.project_name);
|
|
6937
|
+
if (contentHash2) {
|
|
6938
|
+
await client.execute({
|
|
6939
|
+
sql: `UPDATE memories
|
|
6940
|
+
SET status = 'deleted',
|
|
6941
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
6942
|
+
WHERE id != ?
|
|
6943
|
+
AND content_hash = ?
|
|
6944
|
+
AND agent_id = ?
|
|
6945
|
+
AND project_name = ?
|
|
6946
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
6947
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
6948
|
+
args: [memoryId, contentHash2, agentId, projectName, memoryType]
|
|
6949
|
+
});
|
|
6950
|
+
}
|
|
6951
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
6952
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
6953
|
+
const old = await client.execute({
|
|
6954
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
6955
|
+
args: [supersedesId]
|
|
6956
|
+
});
|
|
6957
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
6958
|
+
const newImportance = Number(row.importance ?? 0);
|
|
6959
|
+
await client.batch([
|
|
6960
|
+
{
|
|
6961
|
+
sql: `UPDATE memories
|
|
6962
|
+
SET status = 'archived',
|
|
6963
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
6964
|
+
WHERE id = ?`,
|
|
6965
|
+
args: [supersedesId]
|
|
6966
|
+
},
|
|
6967
|
+
{
|
|
6968
|
+
sql: `UPDATE memories
|
|
6969
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
6970
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
6971
|
+
WHERE id = ?`,
|
|
6972
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
6973
|
+
}
|
|
6974
|
+
], "write");
|
|
6975
|
+
}
|
|
6976
|
+
} catch (err) {
|
|
6977
|
+
process.stderr.write(
|
|
6978
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
6979
|
+
`
|
|
6980
|
+
);
|
|
6981
|
+
}
|
|
6982
|
+
}
|
|
6983
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
6984
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
6985
|
+
if (memoryIds.length === 0) return;
|
|
6986
|
+
const run = () => {
|
|
6987
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
6988
|
+
};
|
|
6989
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
6990
|
+
else setTimeout(run, 0);
|
|
6991
|
+
}
|
|
6992
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
6993
|
+
var init_memory_write_governor = __esm({
|
|
6994
|
+
"src/lib/memory-write-governor.ts"() {
|
|
6995
|
+
"use strict";
|
|
6996
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
6997
|
+
"decision",
|
|
6998
|
+
"adr",
|
|
6999
|
+
"behavior",
|
|
7000
|
+
"procedure"
|
|
7001
|
+
]);
|
|
7002
|
+
NOISE_DROP_PATTERNS = [
|
|
7003
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
7004
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
7005
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
7006
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
7007
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
7008
|
+
];
|
|
7009
|
+
SKIP_EMBED_PATTERNS = [
|
|
7010
|
+
/tmux capture-pane\b/i,
|
|
7011
|
+
/docker ps\b/i,
|
|
7012
|
+
/docker images\b/i,
|
|
7013
|
+
/git status\b/i,
|
|
7014
|
+
/grep .*node_modules/i,
|
|
7015
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
7016
|
+
];
|
|
7017
|
+
}
|
|
7018
|
+
});
|
|
7019
|
+
|
|
6797
7020
|
// src/lib/shard-manager.ts
|
|
6798
7021
|
var shard_manager_exports = {};
|
|
6799
7022
|
__export(shard_manager_exports, {
|
|
@@ -6958,7 +7181,8 @@ async function ensureShardSchema(client) {
|
|
|
6958
7181
|
}
|
|
6959
7182
|
for (const idx of [
|
|
6960
7183
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
6961
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
7184
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
7185
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash ON memories(content_hash, agent_id, project_name, memory_type) WHERE content_hash IS NOT NULL"
|
|
6962
7186
|
]) {
|
|
6963
7187
|
try {
|
|
6964
7188
|
await client.execute(idx);
|
|
@@ -7152,7 +7376,7 @@ var init_platform_procedures = __esm({
|
|
|
7152
7376
|
title: "Chain of command \u2014 who talks to whom",
|
|
7153
7377
|
domain: "workflow",
|
|
7154
7378
|
priority: "p0",
|
|
7155
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
7379
|
+
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
7156
7380
|
},
|
|
7157
7381
|
{
|
|
7158
7382
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -7383,7 +7607,6 @@ __export(store_exports, {
|
|
|
7383
7607
|
vectorToBlob: () => vectorToBlob,
|
|
7384
7608
|
writeMemory: () => writeMemory
|
|
7385
7609
|
});
|
|
7386
|
-
import { createHash } from "crypto";
|
|
7387
7610
|
function isBusyError2(err) {
|
|
7388
7611
|
if (err instanceof Error) {
|
|
7389
7612
|
const msg = err.message.toLowerCase();
|
|
@@ -7497,17 +7720,24 @@ async function writeMemory(record) {
|
|
|
7497
7720
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
7498
7721
|
);
|
|
7499
7722
|
}
|
|
7500
|
-
const
|
|
7501
|
-
if (
|
|
7723
|
+
const governed = governMemoryRecord(record);
|
|
7724
|
+
if (governed.shouldDrop) return;
|
|
7725
|
+
record = governed.record;
|
|
7726
|
+
const contentHash2 = governed.contentHash;
|
|
7727
|
+
const memoryType = record.memory_type ?? "raw";
|
|
7728
|
+
if (_pendingRecords.some(
|
|
7729
|
+
(r) => r.content_hash === contentHash2 && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
7730
|
+
)) {
|
|
7502
7731
|
return;
|
|
7503
7732
|
}
|
|
7504
7733
|
try {
|
|
7505
|
-
const
|
|
7506
|
-
|
|
7507
|
-
|
|
7508
|
-
|
|
7734
|
+
const existing = await findScopedDuplicate({
|
|
7735
|
+
contentHash: contentHash2,
|
|
7736
|
+
agentId: record.agent_id,
|
|
7737
|
+
projectName: record.project_name,
|
|
7738
|
+
memoryType
|
|
7509
7739
|
});
|
|
7510
|
-
if (existing
|
|
7740
|
+
if (existing) return;
|
|
7511
7741
|
} catch {
|
|
7512
7742
|
}
|
|
7513
7743
|
const dbRow = {
|
|
@@ -7538,7 +7768,7 @@ async function writeMemory(record) {
|
|
|
7538
7768
|
tier: record.tier ?? classifyTier(record),
|
|
7539
7769
|
supersedes_id: record.supersedes_id ?? null,
|
|
7540
7770
|
draft: record.draft ? 1 : 0,
|
|
7541
|
-
memory_type:
|
|
7771
|
+
memory_type: memoryType,
|
|
7542
7772
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
7543
7773
|
content_hash: contentHash2,
|
|
7544
7774
|
intent: record.intent ?? null,
|
|
@@ -7697,6 +7927,7 @@ async function flushBatch() {
|
|
|
7697
7927
|
const globalClient = getClient();
|
|
7698
7928
|
const globalStmts = batch.map(buildStmt);
|
|
7699
7929
|
await globalClient.batch(globalStmts, "write");
|
|
7930
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
7700
7931
|
_pendingRecords.splice(0, batch.length);
|
|
7701
7932
|
try {
|
|
7702
7933
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -7817,7 +8048,11 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
7817
8048
|
sql += ` AND timestamp >= ?`;
|
|
7818
8049
|
args2.push(options.since);
|
|
7819
8050
|
}
|
|
7820
|
-
if (options?.
|
|
8051
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
8052
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
8053
|
+
sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
8054
|
+
args2.push(...uniqueTypes);
|
|
8055
|
+
} else if (options?.memoryType) {
|
|
7821
8056
|
sql += ` AND memory_type = ?`;
|
|
7822
8057
|
args2.push(options.memoryType);
|
|
7823
8058
|
}
|
|
@@ -7955,6 +8190,7 @@ var init_store = __esm({
|
|
|
7955
8190
|
init_keychain();
|
|
7956
8191
|
init_config();
|
|
7957
8192
|
init_state_bus();
|
|
8193
|
+
init_memory_write_governor();
|
|
7958
8194
|
INIT_MAX_RETRIES = 3;
|
|
7959
8195
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
7960
8196
|
_pendingRecords = [];
|
|
@@ -8949,7 +9185,7 @@ __export(identity_exports, {
|
|
|
8949
9185
|
import { existsSync as existsSync16, mkdirSync as mkdirSync9, readFileSync as readFileSync11, writeFileSync as writeFileSync9 } from "fs";
|
|
8950
9186
|
import { readdirSync as readdirSync4 } from "fs";
|
|
8951
9187
|
import path17 from "path";
|
|
8952
|
-
import { createHash as
|
|
9188
|
+
import { createHash as createHash3 } from "crypto";
|
|
8953
9189
|
function ensureDir() {
|
|
8954
9190
|
if (!existsSync16(IDENTITY_DIR2)) {
|
|
8955
9191
|
mkdirSync9(IDENTITY_DIR2, { recursive: true });
|
|
@@ -8993,7 +9229,7 @@ function parseFrontmatter(raw) {
|
|
|
8993
9229
|
};
|
|
8994
9230
|
}
|
|
8995
9231
|
function contentHash(content) {
|
|
8996
|
-
return
|
|
9232
|
+
return createHash3("sha256").update(content).digest("hex").slice(0, 16);
|
|
8997
9233
|
}
|
|
8998
9234
|
function getIdentity(agentId) {
|
|
8999
9235
|
const filePath = identityPath(agentId);
|
|
@@ -12955,7 +13191,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
12955
13191
|
}
|
|
12956
13192
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
12957
13193
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
12958
|
-
|
|
13194
|
+
let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
13195
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
13196
|
+
ccModel += "[1m]";
|
|
13197
|
+
}
|
|
13198
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
12959
13199
|
}
|
|
12960
13200
|
}
|
|
12961
13201
|
let spawnCommand;
|
|
@@ -13586,8 +13826,9 @@ function personalizePrompt(prompt, templateName, actualName) {
|
|
|
13586
13826
|
return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
|
|
13587
13827
|
}
|
|
13588
13828
|
function renderClientCOOTemplate(vars) {
|
|
13829
|
+
const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
|
|
13589
13830
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
13590
|
-
const value =
|
|
13831
|
+
const value = resolved[key];
|
|
13591
13832
|
if (typeof value !== "string" || value.length === 0) {
|
|
13592
13833
|
throw new Error(
|
|
13593
13834
|
`renderClientCOOTemplate: missing required variable "${key}"`
|
|
@@ -13596,7 +13837,7 @@ function renderClientCOOTemplate(vars) {
|
|
|
13596
13837
|
}
|
|
13597
13838
|
let out = CLIENT_COO_TEMPLATE;
|
|
13598
13839
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
13599
|
-
out = out.split(`{{${key}}}`).join(
|
|
13840
|
+
out = out.split(`{{${key}}}`).join(resolved[key]);
|
|
13600
13841
|
}
|
|
13601
13842
|
if (vars.industry_context) {
|
|
13602
13843
|
out += "\n" + vars.industry_context;
|
|
@@ -14073,7 +14314,7 @@ created_by: system
|
|
|
14073
14314
|
---
|
|
14074
14315
|
## Identity
|
|
14075
14316
|
|
|
14076
|
-
You are {{agent_name}}, the
|
|
14317
|
+
You are {{agent_name}}, the {{title}} at {{company_name}}.
|
|
14077
14318
|
|
|
14078
14319
|
You are {{founder_name}}'s most reliable teammate in business \u2014 the knowledgeable older sibling who has been through it all. You have seen projects succeed and fail. You know what matters and what is noise. You do not get anxious about problems; you see them coming, stay calm, and handle them.
|
|
14079
14320
|
|
|
@@ -14160,7 +14401,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
|
|
|
14160
14401
|
CLIENT_COO_PLACEHOLDERS = [
|
|
14161
14402
|
"agent_name",
|
|
14162
14403
|
"company_name",
|
|
14163
|
-
"founder_name"
|
|
14404
|
+
"founder_name",
|
|
14405
|
+
"title"
|
|
14164
14406
|
];
|
|
14165
14407
|
}
|
|
14166
14408
|
});
|
|
@@ -14368,7 +14610,7 @@ var init_exe_rename = __esm({
|
|
|
14368
14610
|
// src/lib/model-downloader.ts
|
|
14369
14611
|
import { createWriteStream, createReadStream as createReadStream2, existsSync as existsSync26, unlinkSync as unlinkSync12, renameSync as renameSync5 } from "fs";
|
|
14370
14612
|
import { mkdir as mkdir6 } from "fs/promises";
|
|
14371
|
-
import { createHash as
|
|
14613
|
+
import { createHash as createHash4 } from "crypto";
|
|
14372
14614
|
import path32 from "path";
|
|
14373
14615
|
async function downloadModel(opts) {
|
|
14374
14616
|
const { destDir, onProgress, fetchFn = globalThis.fetch } = opts;
|
|
@@ -14396,7 +14638,7 @@ async function downloadModel(opts) {
|
|
|
14396
14638
|
throw new Error(`Download failed: HTTP ${response.status}`);
|
|
14397
14639
|
}
|
|
14398
14640
|
const contentLength = Number(response.headers.get("content-length") ?? EXPECTED_SIZE);
|
|
14399
|
-
const hash =
|
|
14641
|
+
const hash = createHash4("sha256");
|
|
14400
14642
|
const fileStream = createWriteStream(tmpPath);
|
|
14401
14643
|
const reader = response.body.getReader();
|
|
14402
14644
|
try {
|
|
@@ -14440,7 +14682,7 @@ Download attempt ${attempt} failed, retrying...
|
|
|
14440
14682
|
}
|
|
14441
14683
|
async function fileHash(filePath) {
|
|
14442
14684
|
return new Promise((resolve, reject) => {
|
|
14443
|
-
const hash =
|
|
14685
|
+
const hash = createHash4("sha256");
|
|
14444
14686
|
const stream = createReadStream2(filePath);
|
|
14445
14687
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
14446
14688
|
stream.on("end", () => resolve(hash.digest("hex")));
|
package/dist/bin/exe-agent.js
CHANGED
|
@@ -1323,7 +1323,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
1323
1323
|
title: "Chain of command \u2014 who talks to whom",
|
|
1324
1324
|
domain: "workflow",
|
|
1325
1325
|
priority: "p0",
|
|
1326
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
1326
|
+
content: "Founder -> coordinator (the executive agent, internally routed as 'COO') -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the coordinator does not bypass managers for specialist work. Specialists report to their manager. If you need cross-team info, use ask_team_memory \u2014 don't read other agents' task folders. Each level owns dispatch downward and review upward."
|
|
1327
1327
|
},
|
|
1328
1328
|
{
|
|
1329
1329
|
title: "Single dispatch path \u2014 create_task only",
|