@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/index.js
CHANGED
|
@@ -3086,6 +3086,14 @@ async function ensureSchema() {
|
|
|
3086
3086
|
);
|
|
3087
3087
|
} catch {
|
|
3088
3088
|
}
|
|
3089
|
+
try {
|
|
3090
|
+
await client.execute(
|
|
3091
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
3092
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
3093
|
+
WHERE content_hash IS NOT NULL`
|
|
3094
|
+
);
|
|
3095
|
+
} catch {
|
|
3096
|
+
}
|
|
3089
3097
|
await client.executeMultiple(`
|
|
3090
3098
|
CREATE TABLE IF NOT EXISTS entities (
|
|
3091
3099
|
id TEXT PRIMARY KEY,
|
|
@@ -6688,7 +6696,11 @@ function spawnEmployee(employeeName, exeSession, projectDir, opts) {
|
|
|
6688
6696
|
}
|
|
6689
6697
|
if (!useExeAgent && !useCodex && !useOpencode && !useBinSymlink) {
|
|
6690
6698
|
if (agentRtConfig.runtime === "claude" && agentRtConfig.model) {
|
|
6691
|
-
|
|
6699
|
+
let ccModel = agentRtConfig.model.replace(/(\d+)\.(\d+)/g, "$1-$2");
|
|
6700
|
+
if (/claude-(opus|sonnet)-4-[6-9]/.test(ccModel) && !ccModel.includes("[1m]")) {
|
|
6701
|
+
ccModel += "[1m]";
|
|
6702
|
+
}
|
|
6703
|
+
envPrefix = `${envPrefix} ANTHROPIC_MODEL=${ccModel}`;
|
|
6692
6704
|
}
|
|
6693
6705
|
}
|
|
6694
6706
|
let spawnCommand;
|
|
@@ -7002,6 +7014,197 @@ var init_keychain = __esm({
|
|
|
7002
7014
|
}
|
|
7003
7015
|
});
|
|
7004
7016
|
|
|
7017
|
+
// src/lib/memory-write-governor.ts
|
|
7018
|
+
import { createHash } from "crypto";
|
|
7019
|
+
function normalizeMemoryText(text) {
|
|
7020
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
7021
|
+
}
|
|
7022
|
+
function classifyMemoryType(input) {
|
|
7023
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
7024
|
+
const tool = input.tool_name.toLowerCase();
|
|
7025
|
+
const text = input.raw_text.toLowerCase();
|
|
7026
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
7027
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
7028
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
7029
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
7030
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
7031
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
7032
|
+
return "raw";
|
|
7033
|
+
}
|
|
7034
|
+
function shouldDropMemory(text) {
|
|
7035
|
+
const normalized = normalizeMemoryText(text);
|
|
7036
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
7037
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
7038
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
7039
|
+
}
|
|
7040
|
+
return { drop: false };
|
|
7041
|
+
}
|
|
7042
|
+
function shouldSkipEmbedding(input) {
|
|
7043
|
+
const type = classifyMemoryType(input);
|
|
7044
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
7045
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
7046
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
7047
|
+
return false;
|
|
7048
|
+
}
|
|
7049
|
+
function hashMemoryContent(text) {
|
|
7050
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
7051
|
+
}
|
|
7052
|
+
function scopedDedupArgs(input) {
|
|
7053
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
7054
|
+
}
|
|
7055
|
+
function governMemoryRecord(record) {
|
|
7056
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
7057
|
+
const memoryType = classifyMemoryType({
|
|
7058
|
+
raw_text: normalized,
|
|
7059
|
+
agent_id: record.agent_id,
|
|
7060
|
+
project_name: record.project_name,
|
|
7061
|
+
tool_name: record.tool_name,
|
|
7062
|
+
memory_type: record.memory_type
|
|
7063
|
+
});
|
|
7064
|
+
const drop = shouldDropMemory(normalized);
|
|
7065
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
7066
|
+
raw_text: normalized,
|
|
7067
|
+
agent_id: record.agent_id,
|
|
7068
|
+
project_name: record.project_name,
|
|
7069
|
+
tool_name: record.tool_name,
|
|
7070
|
+
memory_type: memoryType
|
|
7071
|
+
});
|
|
7072
|
+
return {
|
|
7073
|
+
record: {
|
|
7074
|
+
...record,
|
|
7075
|
+
raw_text: normalized,
|
|
7076
|
+
memory_type: memoryType,
|
|
7077
|
+
vector: skipEmbedding ? null : record.vector
|
|
7078
|
+
},
|
|
7079
|
+
contentHash: hashMemoryContent(normalized),
|
|
7080
|
+
shouldDrop: drop.drop,
|
|
7081
|
+
dropReason: drop.reason,
|
|
7082
|
+
skipEmbedding,
|
|
7083
|
+
hygiene: {
|
|
7084
|
+
dedup: true,
|
|
7085
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
7086
|
+
}
|
|
7087
|
+
};
|
|
7088
|
+
}
|
|
7089
|
+
async function findScopedDuplicate(input) {
|
|
7090
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
7091
|
+
const client = getClient2();
|
|
7092
|
+
const args = scopedDedupArgs(input);
|
|
7093
|
+
let sql = `SELECT id FROM memories
|
|
7094
|
+
WHERE content_hash = ?
|
|
7095
|
+
AND agent_id = ?
|
|
7096
|
+
AND project_name = ?
|
|
7097
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
7098
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
7099
|
+
if (input.excludeId) {
|
|
7100
|
+
sql += " AND id != ?";
|
|
7101
|
+
args.push(input.excludeId);
|
|
7102
|
+
}
|
|
7103
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
7104
|
+
const result = await client.execute({ sql, args });
|
|
7105
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
7106
|
+
}
|
|
7107
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
7108
|
+
try {
|
|
7109
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
7110
|
+
const client = getClient2();
|
|
7111
|
+
const current = await client.execute({
|
|
7112
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
7113
|
+
importance, timestamp
|
|
7114
|
+
FROM memories
|
|
7115
|
+
WHERE id = ?
|
|
7116
|
+
LIMIT 1`,
|
|
7117
|
+
args: [memoryId]
|
|
7118
|
+
});
|
|
7119
|
+
const row = current.rows[0];
|
|
7120
|
+
if (!row) return;
|
|
7121
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
7122
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
7123
|
+
const agentId = String(row.agent_id);
|
|
7124
|
+
const projectName = String(row.project_name);
|
|
7125
|
+
if (contentHash) {
|
|
7126
|
+
await client.execute({
|
|
7127
|
+
sql: `UPDATE memories
|
|
7128
|
+
SET status = 'deleted',
|
|
7129
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
7130
|
+
WHERE id != ?
|
|
7131
|
+
AND content_hash = ?
|
|
7132
|
+
AND agent_id = ?
|
|
7133
|
+
AND project_name = ?
|
|
7134
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
7135
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
7136
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
7137
|
+
});
|
|
7138
|
+
}
|
|
7139
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
7140
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
7141
|
+
const old = await client.execute({
|
|
7142
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
7143
|
+
args: [supersedesId]
|
|
7144
|
+
});
|
|
7145
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
7146
|
+
const newImportance = Number(row.importance ?? 0);
|
|
7147
|
+
await client.batch([
|
|
7148
|
+
{
|
|
7149
|
+
sql: `UPDATE memories
|
|
7150
|
+
SET status = 'archived',
|
|
7151
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
7152
|
+
WHERE id = ?`,
|
|
7153
|
+
args: [supersedesId]
|
|
7154
|
+
},
|
|
7155
|
+
{
|
|
7156
|
+
sql: `UPDATE memories
|
|
7157
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
7158
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
7159
|
+
WHERE id = ?`,
|
|
7160
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
7161
|
+
}
|
|
7162
|
+
], "write");
|
|
7163
|
+
}
|
|
7164
|
+
} catch (err) {
|
|
7165
|
+
process.stderr.write(
|
|
7166
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
7167
|
+
`
|
|
7168
|
+
);
|
|
7169
|
+
}
|
|
7170
|
+
}
|
|
7171
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
7172
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
7173
|
+
if (memoryIds.length === 0) return;
|
|
7174
|
+
const run = () => {
|
|
7175
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
7176
|
+
};
|
|
7177
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
7178
|
+
else setTimeout(run, 0);
|
|
7179
|
+
}
|
|
7180
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
7181
|
+
var init_memory_write_governor = __esm({
|
|
7182
|
+
"src/lib/memory-write-governor.ts"() {
|
|
7183
|
+
"use strict";
|
|
7184
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
7185
|
+
"decision",
|
|
7186
|
+
"adr",
|
|
7187
|
+
"behavior",
|
|
7188
|
+
"procedure"
|
|
7189
|
+
]);
|
|
7190
|
+
NOISE_DROP_PATTERNS = [
|
|
7191
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
7192
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
7193
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
7194
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
7195
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
7196
|
+
];
|
|
7197
|
+
SKIP_EMBED_PATTERNS = [
|
|
7198
|
+
/tmux capture-pane\b/i,
|
|
7199
|
+
/docker ps\b/i,
|
|
7200
|
+
/docker images\b/i,
|
|
7201
|
+
/git status\b/i,
|
|
7202
|
+
/grep .*node_modules/i,
|
|
7203
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
7204
|
+
];
|
|
7205
|
+
}
|
|
7206
|
+
});
|
|
7207
|
+
|
|
7005
7208
|
// src/lib/shard-manager.ts
|
|
7006
7209
|
var shard_manager_exports = {};
|
|
7007
7210
|
__export(shard_manager_exports, {
|
|
@@ -7166,7 +7369,8 @@ async function ensureShardSchema(client) {
|
|
|
7166
7369
|
}
|
|
7167
7370
|
for (const idx of [
|
|
7168
7371
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
7169
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
7372
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
7373
|
+
"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"
|
|
7170
7374
|
]) {
|
|
7171
7375
|
try {
|
|
7172
7376
|
await client.execute(idx);
|
|
@@ -7360,7 +7564,7 @@ var init_platform_procedures = __esm({
|
|
|
7360
7564
|
title: "Chain of command \u2014 who talks to whom",
|
|
7361
7565
|
domain: "workflow",
|
|
7362
7566
|
priority: "p0",
|
|
7363
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
7567
|
+
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."
|
|
7364
7568
|
},
|
|
7365
7569
|
{
|
|
7366
7570
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -7591,7 +7795,6 @@ __export(store_exports, {
|
|
|
7591
7795
|
vectorToBlob: () => vectorToBlob,
|
|
7592
7796
|
writeMemory: () => writeMemory
|
|
7593
7797
|
});
|
|
7594
|
-
import { createHash } from "crypto";
|
|
7595
7798
|
function isBusyError2(err) {
|
|
7596
7799
|
if (err instanceof Error) {
|
|
7597
7800
|
const msg = err.message.toLowerCase();
|
|
@@ -7705,17 +7908,24 @@ async function writeMemory(record) {
|
|
|
7705
7908
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
7706
7909
|
);
|
|
7707
7910
|
}
|
|
7708
|
-
const
|
|
7709
|
-
if (
|
|
7911
|
+
const governed = governMemoryRecord(record);
|
|
7912
|
+
if (governed.shouldDrop) return;
|
|
7913
|
+
record = governed.record;
|
|
7914
|
+
const contentHash = governed.contentHash;
|
|
7915
|
+
const memoryType = record.memory_type ?? "raw";
|
|
7916
|
+
if (_pendingRecords.some(
|
|
7917
|
+
(r) => r.content_hash === contentHash && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
7918
|
+
)) {
|
|
7710
7919
|
return;
|
|
7711
7920
|
}
|
|
7712
7921
|
try {
|
|
7713
|
-
const
|
|
7714
|
-
|
|
7715
|
-
|
|
7716
|
-
|
|
7922
|
+
const existing = await findScopedDuplicate({
|
|
7923
|
+
contentHash,
|
|
7924
|
+
agentId: record.agent_id,
|
|
7925
|
+
projectName: record.project_name,
|
|
7926
|
+
memoryType
|
|
7717
7927
|
});
|
|
7718
|
-
if (existing
|
|
7928
|
+
if (existing) return;
|
|
7719
7929
|
} catch {
|
|
7720
7930
|
}
|
|
7721
7931
|
const dbRow = {
|
|
@@ -7746,7 +7956,7 @@ async function writeMemory(record) {
|
|
|
7746
7956
|
tier: record.tier ?? classifyTier(record),
|
|
7747
7957
|
supersedes_id: record.supersedes_id ?? null,
|
|
7748
7958
|
draft: record.draft ? 1 : 0,
|
|
7749
|
-
memory_type:
|
|
7959
|
+
memory_type: memoryType,
|
|
7750
7960
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
7751
7961
|
content_hash: contentHash,
|
|
7752
7962
|
intent: record.intent ?? null,
|
|
@@ -7905,6 +8115,7 @@ async function flushBatch() {
|
|
|
7905
8115
|
const globalClient = getClient();
|
|
7906
8116
|
const globalStmts = batch.map(buildStmt);
|
|
7907
8117
|
await globalClient.batch(globalStmts, "write");
|
|
8118
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
7908
8119
|
_pendingRecords.splice(0, batch.length);
|
|
7909
8120
|
try {
|
|
7910
8121
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -8025,7 +8236,11 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
8025
8236
|
sql += ` AND timestamp >= ?`;
|
|
8026
8237
|
args.push(options.since);
|
|
8027
8238
|
}
|
|
8028
|
-
if (options?.
|
|
8239
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
8240
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
8241
|
+
sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
8242
|
+
args.push(...uniqueTypes);
|
|
8243
|
+
} else if (options?.memoryType) {
|
|
8029
8244
|
sql += ` AND memory_type = ?`;
|
|
8030
8245
|
args.push(options.memoryType);
|
|
8031
8246
|
}
|
|
@@ -8163,6 +8378,7 @@ var init_store = __esm({
|
|
|
8163
8378
|
init_keychain();
|
|
8164
8379
|
init_config();
|
|
8165
8380
|
init_state_bus();
|
|
8381
|
+
init_memory_write_governor();
|
|
8166
8382
|
INIT_MAX_RETRIES = 3;
|
|
8167
8383
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
8168
8384
|
_pendingRecords = [];
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -2021,6 +2021,14 @@ async function ensureSchema() {
|
|
|
2021
2021
|
);
|
|
2022
2022
|
} catch {
|
|
2023
2023
|
}
|
|
2024
|
+
try {
|
|
2025
|
+
await client.execute(
|
|
2026
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2027
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2028
|
+
WHERE content_hash IS NOT NULL`
|
|
2029
|
+
);
|
|
2030
|
+
} catch {
|
|
2031
|
+
}
|
|
2024
2032
|
await client.executeMultiple(`
|
|
2025
2033
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2026
2034
|
id TEXT PRIMARY KEY,
|
|
@@ -550,7 +550,6 @@ import { randomUUID } from "crypto";
|
|
|
550
550
|
// src/lib/store.ts
|
|
551
551
|
init_memory();
|
|
552
552
|
init_database();
|
|
553
|
-
import { createHash } from "crypto";
|
|
554
553
|
|
|
555
554
|
// src/lib/keychain.ts
|
|
556
555
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
@@ -611,6 +610,9 @@ var StateBus = class {
|
|
|
611
610
|
};
|
|
612
611
|
var orgBus = new StateBus();
|
|
613
612
|
|
|
613
|
+
// src/lib/memory-write-governor.ts
|
|
614
|
+
import { createHash } from "crypto";
|
|
615
|
+
|
|
614
616
|
// src/lib/store.ts
|
|
615
617
|
function vectorToBlob(vector) {
|
|
616
618
|
const f32 = vector instanceof Float32Array ? vector : new Float32Array(vector);
|
package/dist/lib/database.js
CHANGED
|
@@ -1937,6 +1937,14 @@ async function ensureSchema() {
|
|
|
1937
1937
|
);
|
|
1938
1938
|
} catch {
|
|
1939
1939
|
}
|
|
1940
|
+
try {
|
|
1941
|
+
await client.execute(
|
|
1942
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
1943
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
1944
|
+
WHERE content_hash IS NOT NULL`
|
|
1945
|
+
);
|
|
1946
|
+
} catch {
|
|
1947
|
+
}
|
|
1940
1948
|
await client.executeMultiple(`
|
|
1941
1949
|
CREATE TABLE IF NOT EXISTS entities (
|
|
1942
1950
|
id TEXT PRIMARY KEY,
|
package/dist/lib/db.js
CHANGED
|
@@ -1937,6 +1937,14 @@ async function ensureSchema() {
|
|
|
1937
1937
|
);
|
|
1938
1938
|
} catch {
|
|
1939
1939
|
}
|
|
1940
|
+
try {
|
|
1941
|
+
await client.execute(
|
|
1942
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
1943
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
1944
|
+
WHERE content_hash IS NOT NULL`
|
|
1945
|
+
);
|
|
1946
|
+
} catch {
|
|
1947
|
+
}
|
|
1940
1948
|
await client.executeMultiple(`
|
|
1941
1949
|
CREATE TABLE IF NOT EXISTS entities (
|
|
1942
1950
|
id TEXT PRIMARY KEY,
|
|
@@ -1966,6 +1966,14 @@ async function ensureSchema() {
|
|
|
1966
1966
|
);
|
|
1967
1967
|
} catch {
|
|
1968
1968
|
}
|
|
1969
|
+
try {
|
|
1970
|
+
await client.execute(
|
|
1971
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
1972
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
1973
|
+
WHERE content_hash IS NOT NULL`
|
|
1974
|
+
);
|
|
1975
|
+
} catch {
|
|
1976
|
+
}
|
|
1969
1977
|
await client.executeMultiple(`
|
|
1970
1978
|
CREATE TABLE IF NOT EXISTS entities (
|
|
1971
1979
|
id TEXT PRIMARY KEY,
|
|
@@ -167,7 +167,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
167
167
|
title: "Chain of command \u2014 who talks to whom",
|
|
168
168
|
domain: "workflow",
|
|
169
169
|
priority: "p0",
|
|
170
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
170
|
+
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."
|
|
171
171
|
},
|
|
172
172
|
{
|
|
173
173
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -811,7 +811,7 @@ created_by: system
|
|
|
811
811
|
---
|
|
812
812
|
## Identity
|
|
813
813
|
|
|
814
|
-
You are {{agent_name}}, the
|
|
814
|
+
You are {{agent_name}}, the {{title}} at {{company_name}}.
|
|
815
815
|
|
|
816
816
|
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.
|
|
817
817
|
|
|
@@ -898,11 +898,13 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
|
|
|
898
898
|
var CLIENT_COO_PLACEHOLDERS = [
|
|
899
899
|
"agent_name",
|
|
900
900
|
"company_name",
|
|
901
|
-
"founder_name"
|
|
901
|
+
"founder_name",
|
|
902
|
+
"title"
|
|
902
903
|
];
|
|
903
904
|
function renderClientCOOTemplate(vars) {
|
|
905
|
+
const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
|
|
904
906
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
905
|
-
const value =
|
|
907
|
+
const value = resolved[key];
|
|
906
908
|
if (typeof value !== "string" || value.length === 0) {
|
|
907
909
|
throw new Error(
|
|
908
910
|
`renderClientCOOTemplate: missing required variable "${key}"`
|
|
@@ -911,7 +913,7 @@ function renderClientCOOTemplate(vars) {
|
|
|
911
913
|
}
|
|
912
914
|
let out = CLIENT_COO_TEMPLATE;
|
|
913
915
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
914
|
-
out = out.split(`{{${key}}}`).join(
|
|
916
|
+
out = out.split(`{{${key}}}`).join(resolved[key]);
|
|
915
917
|
}
|
|
916
918
|
if (vars.industry_context) {
|
|
917
919
|
out += "\n" + vars.industry_context;
|