@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
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
4
|
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
5
7
|
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
6
8
|
}) : x)(function(x) {
|
|
@@ -14,6 +16,15 @@ var __export = (target, all) => {
|
|
|
14
16
|
for (var name in all)
|
|
15
17
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
16
18
|
};
|
|
19
|
+
var __copyProps = (to, from, except, desc) => {
|
|
20
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
21
|
+
for (let key of __getOwnPropNames(from))
|
|
22
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
23
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
24
|
+
}
|
|
25
|
+
return to;
|
|
26
|
+
};
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
17
28
|
|
|
18
29
|
// src/types/memory.ts
|
|
19
30
|
var EMBEDDING_DIM;
|
|
@@ -118,6 +129,21 @@ var init_secure_files = __esm({
|
|
|
118
129
|
});
|
|
119
130
|
|
|
120
131
|
// src/lib/config.ts
|
|
132
|
+
var config_exports = {};
|
|
133
|
+
__export(config_exports, {
|
|
134
|
+
CONFIG_MIGRATIONS: () => CONFIG_MIGRATIONS,
|
|
135
|
+
CONFIG_PATH: () => CONFIG_PATH,
|
|
136
|
+
CURRENT_CONFIG_VERSION: () => CURRENT_CONFIG_VERSION,
|
|
137
|
+
DB_PATH: () => DB_PATH,
|
|
138
|
+
EXE_AI_DIR: () => EXE_AI_DIR,
|
|
139
|
+
LEGACY_LANCE_PATH: () => LEGACY_LANCE_PATH,
|
|
140
|
+
MODELS_DIR: () => MODELS_DIR,
|
|
141
|
+
loadConfig: () => loadConfig,
|
|
142
|
+
loadConfigFrom: () => loadConfigFrom,
|
|
143
|
+
loadConfigSync: () => loadConfigSync,
|
|
144
|
+
migrateConfig: () => migrateConfig,
|
|
145
|
+
saveConfig: () => saveConfig
|
|
146
|
+
});
|
|
121
147
|
import { readFile, writeFile } from "fs/promises";
|
|
122
148
|
import { readFileSync, existsSync as existsSync2, renameSync } from "fs";
|
|
123
149
|
import path from "path";
|
|
@@ -221,6 +247,46 @@ async function loadConfig() {
|
|
|
221
247
|
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
222
248
|
}
|
|
223
249
|
}
|
|
250
|
+
function loadConfigSync() {
|
|
251
|
+
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
252
|
+
const configPath = path.join(dir, "config.json");
|
|
253
|
+
if (!existsSync2(configPath)) {
|
|
254
|
+
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
255
|
+
}
|
|
256
|
+
try {
|
|
257
|
+
const raw = readFileSync(configPath, "utf-8");
|
|
258
|
+
let parsed = JSON.parse(raw);
|
|
259
|
+
parsed = migrateLegacyConfig(parsed);
|
|
260
|
+
const { config: migratedCfg } = migrateConfig(parsed);
|
|
261
|
+
normalizeScalingRoadmap(migratedCfg);
|
|
262
|
+
normalizeSessionLifecycle(migratedCfg);
|
|
263
|
+
normalizeAutoUpdate(migratedCfg);
|
|
264
|
+
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db"), ...migratedCfg };
|
|
265
|
+
} catch {
|
|
266
|
+
return { ...DEFAULT_CONFIG, dbPath: path.join(dir, "memories.db") };
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
async function saveConfig(config) {
|
|
270
|
+
const dir = process.env.EXE_OS_DIR ?? process.env.EXE_MEM_DIR ?? EXE_AI_DIR;
|
|
271
|
+
await ensurePrivateDir(dir);
|
|
272
|
+
const configPath = path.join(dir, "config.json");
|
|
273
|
+
await writeFile(configPath, JSON.stringify(config, null, 2) + "\n");
|
|
274
|
+
await enforcePrivateFile(configPath);
|
|
275
|
+
}
|
|
276
|
+
async function loadConfigFrom(configPath) {
|
|
277
|
+
const raw = await readFile(configPath, "utf-8");
|
|
278
|
+
try {
|
|
279
|
+
let parsed = JSON.parse(raw);
|
|
280
|
+
parsed = migrateLegacyConfig(parsed);
|
|
281
|
+
const { config: migratedCfg } = migrateConfig(parsed);
|
|
282
|
+
normalizeScalingRoadmap(migratedCfg);
|
|
283
|
+
normalizeSessionLifecycle(migratedCfg);
|
|
284
|
+
normalizeAutoUpdate(migratedCfg);
|
|
285
|
+
return { ...DEFAULT_CONFIG, ...migratedCfg };
|
|
286
|
+
} catch {
|
|
287
|
+
return { ...DEFAULT_CONFIG };
|
|
288
|
+
}
|
|
289
|
+
}
|
|
224
290
|
var EXE_AI_DIR, DB_PATH, MODELS_DIR, CONFIG_PATH, LEGACY_LANCE_PATH, CURRENT_CONFIG_VERSION, DEFAULT_CONFIG, CONFIG_MIGRATIONS;
|
|
225
291
|
var init_config = __esm({
|
|
226
292
|
"src/lib/config.ts"() {
|
|
@@ -2407,6 +2473,14 @@ async function ensureSchema() {
|
|
|
2407
2473
|
);
|
|
2408
2474
|
} catch {
|
|
2409
2475
|
}
|
|
2476
|
+
try {
|
|
2477
|
+
await client.execute(
|
|
2478
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2479
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2480
|
+
WHERE content_hash IS NOT NULL`
|
|
2481
|
+
);
|
|
2482
|
+
} catch {
|
|
2483
|
+
}
|
|
2410
2484
|
await client.executeMultiple(`
|
|
2411
2485
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2412
2486
|
id TEXT PRIMARY KEY,
|
|
@@ -3076,7 +3150,8 @@ async function ensureShardSchema(client) {
|
|
|
3076
3150
|
}
|
|
3077
3151
|
for (const idx of [
|
|
3078
3152
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
3079
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
3153
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
3154
|
+
"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"
|
|
3080
3155
|
]) {
|
|
3081
3156
|
try {
|
|
3082
3157
|
await client.execute(idx);
|
|
@@ -3270,7 +3345,7 @@ var init_platform_procedures = __esm({
|
|
|
3270
3345
|
title: "Chain of command \u2014 who talks to whom",
|
|
3271
3346
|
domain: "workflow",
|
|
3272
3347
|
priority: "p0",
|
|
3273
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
3348
|
+
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."
|
|
3274
3349
|
},
|
|
3275
3350
|
{
|
|
3276
3351
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -3521,8 +3596,9 @@ function personalizePrompt(prompt, templateName, actualName) {
|
|
|
3521
3596
|
return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
|
|
3522
3597
|
}
|
|
3523
3598
|
function renderClientCOOTemplate(vars) {
|
|
3599
|
+
const resolved = { ...vars, title: vars.title || "Chief Operating Officer" };
|
|
3524
3600
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
3525
|
-
const value =
|
|
3601
|
+
const value = resolved[key];
|
|
3526
3602
|
if (typeof value !== "string" || value.length === 0) {
|
|
3527
3603
|
throw new Error(
|
|
3528
3604
|
`renderClientCOOTemplate: missing required variable "${key}"`
|
|
@@ -3531,7 +3607,7 @@ function renderClientCOOTemplate(vars) {
|
|
|
3531
3607
|
}
|
|
3532
3608
|
let out = CLIENT_COO_TEMPLATE;
|
|
3533
3609
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
3534
|
-
out = out.split(`{{${key}}}`).join(
|
|
3610
|
+
out = out.split(`{{${key}}}`).join(resolved[key]);
|
|
3535
3611
|
}
|
|
3536
3612
|
if (vars.industry_context) {
|
|
3537
3613
|
out += "\n" + vars.industry_context;
|
|
@@ -4008,7 +4084,7 @@ created_by: system
|
|
|
4008
4084
|
---
|
|
4009
4085
|
## Identity
|
|
4010
4086
|
|
|
4011
|
-
You are {{agent_name}}, the
|
|
4087
|
+
You are {{agent_name}}, the {{title}} at {{company_name}}.
|
|
4012
4088
|
|
|
4013
4089
|
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.
|
|
4014
4090
|
|
|
@@ -4095,7 +4171,8 @@ All memory, tasks, behaviors, documents, and wiki content belonging to {{company
|
|
|
4095
4171
|
CLIENT_COO_PLACEHOLDERS = [
|
|
4096
4172
|
"agent_name",
|
|
4097
4173
|
"company_name",
|
|
4098
|
-
"founder_name"
|
|
4174
|
+
"founder_name",
|
|
4175
|
+
"title"
|
|
4099
4176
|
];
|
|
4100
4177
|
}
|
|
4101
4178
|
});
|
|
@@ -4368,7 +4445,6 @@ import { spawnSync } from "child_process";
|
|
|
4368
4445
|
// src/lib/store.ts
|
|
4369
4446
|
init_memory();
|
|
4370
4447
|
init_database();
|
|
4371
|
-
import { createHash } from "crypto";
|
|
4372
4448
|
|
|
4373
4449
|
// src/lib/keychain.ts
|
|
4374
4450
|
import { readFile as readFile3, writeFile as writeFile3, unlink, mkdir as mkdir3, chmod as chmod2 } from "fs/promises";
|
|
@@ -4601,6 +4677,88 @@ var StateBus = class {
|
|
|
4601
4677
|
};
|
|
4602
4678
|
var orgBus = new StateBus();
|
|
4603
4679
|
|
|
4680
|
+
// src/lib/memory-write-governor.ts
|
|
4681
|
+
import { createHash } from "crypto";
|
|
4682
|
+
var HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
4683
|
+
"decision",
|
|
4684
|
+
"adr",
|
|
4685
|
+
"behavior",
|
|
4686
|
+
"procedure"
|
|
4687
|
+
]);
|
|
4688
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
4689
|
+
try {
|
|
4690
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
4691
|
+
const client = getClient2();
|
|
4692
|
+
const current = await client.execute({
|
|
4693
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
4694
|
+
importance, timestamp
|
|
4695
|
+
FROM memories
|
|
4696
|
+
WHERE id = ?
|
|
4697
|
+
LIMIT 1`,
|
|
4698
|
+
args: [memoryId]
|
|
4699
|
+
});
|
|
4700
|
+
const row = current.rows[0];
|
|
4701
|
+
if (!row) return;
|
|
4702
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
4703
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
4704
|
+
const agentId = String(row.agent_id);
|
|
4705
|
+
const projectName = String(row.project_name);
|
|
4706
|
+
if (contentHash) {
|
|
4707
|
+
await client.execute({
|
|
4708
|
+
sql: `UPDATE memories
|
|
4709
|
+
SET status = 'deleted',
|
|
4710
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
4711
|
+
WHERE id != ?
|
|
4712
|
+
AND content_hash = ?
|
|
4713
|
+
AND agent_id = ?
|
|
4714
|
+
AND project_name = ?
|
|
4715
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
4716
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
4717
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
4718
|
+
});
|
|
4719
|
+
}
|
|
4720
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
4721
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
4722
|
+
const old = await client.execute({
|
|
4723
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
4724
|
+
args: [supersedesId]
|
|
4725
|
+
});
|
|
4726
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
4727
|
+
const newImportance = Number(row.importance ?? 0);
|
|
4728
|
+
await client.batch([
|
|
4729
|
+
{
|
|
4730
|
+
sql: `UPDATE memories
|
|
4731
|
+
SET status = 'archived',
|
|
4732
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
4733
|
+
WHERE id = ?`,
|
|
4734
|
+
args: [supersedesId]
|
|
4735
|
+
},
|
|
4736
|
+
{
|
|
4737
|
+
sql: `UPDATE memories
|
|
4738
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
4739
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
4740
|
+
WHERE id = ?`,
|
|
4741
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
4742
|
+
}
|
|
4743
|
+
], "write");
|
|
4744
|
+
}
|
|
4745
|
+
} catch (err) {
|
|
4746
|
+
process.stderr.write(
|
|
4747
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
4748
|
+
`
|
|
4749
|
+
);
|
|
4750
|
+
}
|
|
4751
|
+
}
|
|
4752
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
4753
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
4754
|
+
if (memoryIds.length === 0) return;
|
|
4755
|
+
const run = () => {
|
|
4756
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
4757
|
+
};
|
|
4758
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
4759
|
+
else setTimeout(run, 0);
|
|
4760
|
+
}
|
|
4761
|
+
|
|
4604
4762
|
// src/lib/store.ts
|
|
4605
4763
|
var INIT_MAX_RETRIES = 3;
|
|
4606
4764
|
var INIT_RETRY_DELAY_MS = 1e3;
|
|
@@ -4800,6 +4958,7 @@ async function flushBatch() {
|
|
|
4800
4958
|
const globalClient = getClient();
|
|
4801
4959
|
const globalStmts = batch.map(buildStmt);
|
|
4802
4960
|
await globalClient.batch(globalStmts, "write");
|
|
4961
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4803
4962
|
_pendingRecords.splice(0, batch.length);
|
|
4804
4963
|
try {
|
|
4805
4964
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -4911,7 +5070,16 @@ var BEHAVIORS_EXPORT_DIR = path9.join(
|
|
|
4911
5070
|
"behaviors-export"
|
|
4912
5071
|
);
|
|
4913
5072
|
var STALE_EXPORT_AGE_MS = 60 * 60 * 1e3;
|
|
4914
|
-
var
|
|
5073
|
+
var DEFAULT_BEHAVIOR_LIMIT = 30;
|
|
5074
|
+
function getBehaviorLimit() {
|
|
5075
|
+
try {
|
|
5076
|
+
const { loadConfigSync: loadConfigSync2 } = (init_config(), __toCommonJS(config_exports));
|
|
5077
|
+
const cfg = loadConfigSync2();
|
|
5078
|
+
return cfg.behaviorExportLimit ?? DEFAULT_BEHAVIOR_LIMIT;
|
|
5079
|
+
} catch {
|
|
5080
|
+
return DEFAULT_BEHAVIOR_LIMIT;
|
|
5081
|
+
}
|
|
5082
|
+
}
|
|
4915
5083
|
function sweepStaleBehaviorExports(now = Date.now()) {
|
|
4916
5084
|
if (!existsSync9(BEHAVIORS_EXPORT_DIR)) return;
|
|
4917
5085
|
let entries;
|
|
@@ -4965,7 +5133,7 @@ function exportFilePath(agentId, projectName, sessionKey) {
|
|
|
4965
5133
|
async function exportBehaviorsForAgent(agentId, projectName, sessionKey) {
|
|
4966
5134
|
mkdirSync3(BEHAVIORS_EXPORT_DIR, { recursive: true });
|
|
4967
5135
|
sweepStaleBehaviorExports();
|
|
4968
|
-
const behaviors = await listBehaviors(agentId, projectName,
|
|
5136
|
+
const behaviors = await listBehaviors(agentId, projectName, getBehaviorLimit());
|
|
4969
5137
|
if (behaviors.length === 0) return null;
|
|
4970
5138
|
const body = renderBehaviorExport(behaviors);
|
|
4971
5139
|
const target = exportFilePath(agentId, projectName, sessionKey);
|
package/dist/bin/exe-link.js
CHANGED
|
@@ -2542,6 +2542,14 @@ async function ensureSchema() {
|
|
|
2542
2542
|
);
|
|
2543
2543
|
} catch {
|
|
2544
2544
|
}
|
|
2545
|
+
try {
|
|
2546
|
+
await client.execute(
|
|
2547
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2548
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2549
|
+
WHERE content_hash IS NOT NULL`
|
|
2550
|
+
);
|
|
2551
|
+
} catch {
|
|
2552
|
+
}
|
|
2545
2553
|
await client.executeMultiple(`
|
|
2546
2554
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2547
2555
|
id TEXT PRIMARY KEY,
|
|
@@ -1266,6 +1266,7 @@ __export(installer_exports, {
|
|
|
1266
1266
|
});
|
|
1267
1267
|
import { readFile as readFile3, writeFile as writeFile3, mkdir as mkdir3, readdir } from "fs/promises";
|
|
1268
1268
|
import { existsSync as existsSync11, readFileSync as readFileSync9, writeFileSync as writeFileSync7, copyFileSync, mkdirSync as mkdirSync6 } from "fs";
|
|
1269
|
+
import { createHash as createHash2 } from "crypto";
|
|
1269
1270
|
import path11 from "path";
|
|
1270
1271
|
import os7 from "os";
|
|
1271
1272
|
import { execSync as execSync2 } from "child_process";
|
|
@@ -1950,7 +1951,30 @@ function setupTmux(home) {
|
|
|
1950
1951
|
return;
|
|
1951
1952
|
}
|
|
1952
1953
|
mkdirSync6(exeDir, { recursive: true });
|
|
1953
|
-
|
|
1954
|
+
if (existsSync11(exeTmuxConf)) {
|
|
1955
|
+
const currentContent = readFileSync9(exeTmuxConf, "utf8");
|
|
1956
|
+
const newContent = readFileSync9(assetPath, "utf8");
|
|
1957
|
+
const currentHash = createHash2("sha256").update(currentContent).digest("hex");
|
|
1958
|
+
const newHash = createHash2("sha256").update(newContent).digest("hex");
|
|
1959
|
+
if (currentHash !== newHash) {
|
|
1960
|
+
const shippedPath = path11.join(exeDir, ".tmux.conf.shipped-hash");
|
|
1961
|
+
const lastShippedHash = existsSync11(shippedPath) ? readFileSync9(shippedPath, "utf8").trim() : "";
|
|
1962
|
+
if (lastShippedHash && currentHash !== lastShippedHash) {
|
|
1963
|
+
process.stderr.write("exe-os: tmux config has user customizations \u2014 skipping overwrite\n");
|
|
1964
|
+
} else {
|
|
1965
|
+
copyFileSync(assetPath, exeTmuxConf);
|
|
1966
|
+
process.stderr.write("exe-os: tmux config updated\n");
|
|
1967
|
+
}
|
|
1968
|
+
writeFileSync7(shippedPath, newHash, "utf8");
|
|
1969
|
+
} else {
|
|
1970
|
+
process.stderr.write("exe-os: tmux config already up to date\n");
|
|
1971
|
+
}
|
|
1972
|
+
} else {
|
|
1973
|
+
copyFileSync(assetPath, exeTmuxConf);
|
|
1974
|
+
const newContent = readFileSync9(assetPath, "utf8");
|
|
1975
|
+
const newHash = createHash2("sha256").update(newContent).digest("hex");
|
|
1976
|
+
writeFileSync7(path11.join(exeDir, ".tmux.conf.shipped-hash"), newHash, "utf8");
|
|
1977
|
+
}
|
|
1954
1978
|
if (existsSync11(userTmuxConf)) {
|
|
1955
1979
|
const existing = readFileSync9(userTmuxConf, "utf8");
|
|
1956
1980
|
if (!existing.includes(sourceLine)) {
|
|
@@ -2243,7 +2267,7 @@ var PLATFORM_PROCEDURES = [
|
|
|
2243
2267
|
title: "Chain of command \u2014 who talks to whom",
|
|
2244
2268
|
domain: "workflow",
|
|
2245
2269
|
priority: "p0",
|
|
2246
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
2270
|
+
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."
|
|
2247
2271
|
},
|
|
2248
2272
|
{
|
|
2249
2273
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -2298,6 +2298,14 @@ async function ensureSchema() {
|
|
|
2298
2298
|
);
|
|
2299
2299
|
} catch {
|
|
2300
2300
|
}
|
|
2301
|
+
try {
|
|
2302
|
+
await client.execute(
|
|
2303
|
+
`CREATE INDEX IF NOT EXISTS idx_memories_scoped_content_hash
|
|
2304
|
+
ON memories(content_hash, agent_id, project_name, memory_type)
|
|
2305
|
+
WHERE content_hash IS NOT NULL`
|
|
2306
|
+
);
|
|
2307
|
+
} catch {
|
|
2308
|
+
}
|
|
2301
2309
|
await client.executeMultiple(`
|
|
2302
2310
|
CREATE TABLE IF NOT EXISTS entities (
|
|
2303
2311
|
id TEXT PRIMARY KEY,
|
|
@@ -3452,6 +3460,197 @@ var init_state_bus = __esm({
|
|
|
3452
3460
|
}
|
|
3453
3461
|
});
|
|
3454
3462
|
|
|
3463
|
+
// src/lib/memory-write-governor.ts
|
|
3464
|
+
import { createHash } from "crypto";
|
|
3465
|
+
function normalizeMemoryText(text) {
|
|
3466
|
+
return text.replace(/\r\n/g, "\n").replace(/[ \t]+$/gm, "").replace(/\n{4,}/g, "\n\n\n").trim();
|
|
3467
|
+
}
|
|
3468
|
+
function classifyMemoryType(input) {
|
|
3469
|
+
if (input.memory_type && input.memory_type.trim()) return input.memory_type.trim();
|
|
3470
|
+
const tool = input.tool_name.toLowerCase();
|
|
3471
|
+
const text = input.raw_text.toLowerCase();
|
|
3472
|
+
if (tool.includes("store_decision") || tool.includes("decision")) return "decision";
|
|
3473
|
+
if (tool.includes("commit") || text.includes("adr-") || text.includes("architectural decision")) return "adr";
|
|
3474
|
+
if (tool.includes("store_behavior") || tool.includes("behavior")) return "behavior";
|
|
3475
|
+
if (tool.includes("global_procedure") || text.includes("organization-wide procedures")) return "procedure";
|
|
3476
|
+
if (tool.includes("send_whatsapp") || tool.includes("conversation")) return "conversation";
|
|
3477
|
+
if (tool === "store_memory" || tool === "manual") return "observation";
|
|
3478
|
+
return "raw";
|
|
3479
|
+
}
|
|
3480
|
+
function shouldDropMemory(text) {
|
|
3481
|
+
const normalized = normalizeMemoryText(text);
|
|
3482
|
+
if (normalized.length < 10) return { drop: true, reason: "too_short" };
|
|
3483
|
+
if (NOISE_DROP_PATTERNS.some((pattern) => pattern.test(normalized))) {
|
|
3484
|
+
return { drop: true, reason: "known_boilerplate_noise" };
|
|
3485
|
+
}
|
|
3486
|
+
return { drop: false };
|
|
3487
|
+
}
|
|
3488
|
+
function shouldSkipEmbedding(input) {
|
|
3489
|
+
const type = classifyMemoryType(input);
|
|
3490
|
+
if (HIGH_VALUE_SUPERSESSION_TYPES.has(type)) return false;
|
|
3491
|
+
if (type === "raw" && input.raw_text.length > 2e4) return true;
|
|
3492
|
+
if (SKIP_EMBED_PATTERNS.some((pattern) => pattern.test(input.raw_text))) return true;
|
|
3493
|
+
return false;
|
|
3494
|
+
}
|
|
3495
|
+
function hashMemoryContent(text) {
|
|
3496
|
+
return createHash("sha256").update(normalizeMemoryText(text)).digest("hex");
|
|
3497
|
+
}
|
|
3498
|
+
function scopedDedupArgs(input) {
|
|
3499
|
+
return [input.contentHash, input.agentId, input.projectName, input.memoryType];
|
|
3500
|
+
}
|
|
3501
|
+
function governMemoryRecord(record) {
|
|
3502
|
+
const normalized = normalizeMemoryText(record.raw_text);
|
|
3503
|
+
const memoryType = classifyMemoryType({
|
|
3504
|
+
raw_text: normalized,
|
|
3505
|
+
agent_id: record.agent_id,
|
|
3506
|
+
project_name: record.project_name,
|
|
3507
|
+
tool_name: record.tool_name,
|
|
3508
|
+
memory_type: record.memory_type
|
|
3509
|
+
});
|
|
3510
|
+
const drop = shouldDropMemory(normalized);
|
|
3511
|
+
const skipEmbedding = shouldSkipEmbedding({
|
|
3512
|
+
raw_text: normalized,
|
|
3513
|
+
agent_id: record.agent_id,
|
|
3514
|
+
project_name: record.project_name,
|
|
3515
|
+
tool_name: record.tool_name,
|
|
3516
|
+
memory_type: memoryType
|
|
3517
|
+
});
|
|
3518
|
+
return {
|
|
3519
|
+
record: {
|
|
3520
|
+
...record,
|
|
3521
|
+
raw_text: normalized,
|
|
3522
|
+
memory_type: memoryType,
|
|
3523
|
+
vector: skipEmbedding ? null : record.vector
|
|
3524
|
+
},
|
|
3525
|
+
contentHash: hashMemoryContent(normalized),
|
|
3526
|
+
shouldDrop: drop.drop,
|
|
3527
|
+
dropReason: drop.reason,
|
|
3528
|
+
skipEmbedding,
|
|
3529
|
+
hygiene: {
|
|
3530
|
+
dedup: true,
|
|
3531
|
+
supersession: HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)
|
|
3532
|
+
}
|
|
3533
|
+
};
|
|
3534
|
+
}
|
|
3535
|
+
async function findScopedDuplicate(input) {
|
|
3536
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3537
|
+
const client = getClient2();
|
|
3538
|
+
const args = scopedDedupArgs(input);
|
|
3539
|
+
let sql = `SELECT id FROM memories
|
|
3540
|
+
WHERE content_hash = ?
|
|
3541
|
+
AND agent_id = ?
|
|
3542
|
+
AND project_name = ?
|
|
3543
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3544
|
+
AND COALESCE(status, 'active') != 'deleted'`;
|
|
3545
|
+
if (input.excludeId) {
|
|
3546
|
+
sql += " AND id != ?";
|
|
3547
|
+
args.push(input.excludeId);
|
|
3548
|
+
}
|
|
3549
|
+
sql += " ORDER BY timestamp DESC LIMIT 1";
|
|
3550
|
+
const result = await client.execute({ sql, args });
|
|
3551
|
+
return result.rows[0]?.id ? String(result.rows[0].id) : null;
|
|
3552
|
+
}
|
|
3553
|
+
async function runPostWriteMemoryHygiene(memoryId) {
|
|
3554
|
+
try {
|
|
3555
|
+
const { getClient: getClient2 } = await Promise.resolve().then(() => (init_database(), database_exports));
|
|
3556
|
+
const client = getClient2();
|
|
3557
|
+
const current = await client.execute({
|
|
3558
|
+
sql: `SELECT id, agent_id, project_name, memory_type, content_hash, supersedes_id,
|
|
3559
|
+
importance, timestamp
|
|
3560
|
+
FROM memories
|
|
3561
|
+
WHERE id = ?
|
|
3562
|
+
LIMIT 1`,
|
|
3563
|
+
args: [memoryId]
|
|
3564
|
+
});
|
|
3565
|
+
const row = current.rows[0];
|
|
3566
|
+
if (!row) return;
|
|
3567
|
+
const memoryType = String(row.memory_type ?? "raw");
|
|
3568
|
+
const contentHash = row.content_hash ? String(row.content_hash) : null;
|
|
3569
|
+
const agentId = String(row.agent_id);
|
|
3570
|
+
const projectName = String(row.project_name);
|
|
3571
|
+
if (contentHash) {
|
|
3572
|
+
await client.execute({
|
|
3573
|
+
sql: `UPDATE memories
|
|
3574
|
+
SET status = 'deleted',
|
|
3575
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3576
|
+
WHERE id != ?
|
|
3577
|
+
AND content_hash = ?
|
|
3578
|
+
AND agent_id = ?
|
|
3579
|
+
AND project_name = ?
|
|
3580
|
+
AND COALESCE(memory_type, 'raw') = ?
|
|
3581
|
+
AND COALESCE(status, 'active') = 'active'`,
|
|
3582
|
+
args: [memoryId, contentHash, agentId, projectName, memoryType]
|
|
3583
|
+
});
|
|
3584
|
+
}
|
|
3585
|
+
const supersedesId = row.supersedes_id ? String(row.supersedes_id) : null;
|
|
3586
|
+
if (supersedesId && HIGH_VALUE_SUPERSESSION_TYPES.has(memoryType)) {
|
|
3587
|
+
const old = await client.execute({
|
|
3588
|
+
sql: `SELECT importance FROM memories WHERE id = ? LIMIT 1`,
|
|
3589
|
+
args: [supersedesId]
|
|
3590
|
+
});
|
|
3591
|
+
const oldImportance = Number(old.rows[0]?.importance ?? 0);
|
|
3592
|
+
const newImportance = Number(row.importance ?? 0);
|
|
3593
|
+
await client.batch([
|
|
3594
|
+
{
|
|
3595
|
+
sql: `UPDATE memories
|
|
3596
|
+
SET status = 'archived',
|
|
3597
|
+
outcome = COALESCE(outcome, 'superseded')
|
|
3598
|
+
WHERE id = ?`,
|
|
3599
|
+
args: [supersedesId]
|
|
3600
|
+
},
|
|
3601
|
+
{
|
|
3602
|
+
sql: `UPDATE memories
|
|
3603
|
+
SET importance = MAX(COALESCE(importance, 5), ?),
|
|
3604
|
+
parent_memory_id = COALESCE(parent_memory_id, ?)
|
|
3605
|
+
WHERE id = ?`,
|
|
3606
|
+
args: [Math.max(oldImportance, newImportance), supersedesId, memoryId]
|
|
3607
|
+
}
|
|
3608
|
+
], "write");
|
|
3609
|
+
}
|
|
3610
|
+
} catch (err) {
|
|
3611
|
+
process.stderr.write(
|
|
3612
|
+
`[memory-governor] post-write hygiene failed for ${memoryId}: ${err instanceof Error ? err.message : String(err)}
|
|
3613
|
+
`
|
|
3614
|
+
);
|
|
3615
|
+
}
|
|
3616
|
+
}
|
|
3617
|
+
function schedulePostWriteMemoryHygiene(memoryIds) {
|
|
3618
|
+
if (process.env.EXE_SKIP_MEMORY_HYGIENE === "1") return;
|
|
3619
|
+
if (memoryIds.length === 0) return;
|
|
3620
|
+
const run = () => {
|
|
3621
|
+
void Promise.all(memoryIds.map((id) => runPostWriteMemoryHygiene(id)));
|
|
3622
|
+
};
|
|
3623
|
+
if (typeof setImmediate === "function") setImmediate(run);
|
|
3624
|
+
else setTimeout(run, 0);
|
|
3625
|
+
}
|
|
3626
|
+
var HIGH_VALUE_SUPERSESSION_TYPES, NOISE_DROP_PATTERNS, SKIP_EMBED_PATTERNS;
|
|
3627
|
+
var init_memory_write_governor = __esm({
|
|
3628
|
+
"src/lib/memory-write-governor.ts"() {
|
|
3629
|
+
"use strict";
|
|
3630
|
+
HIGH_VALUE_SUPERSESSION_TYPES = /* @__PURE__ */ new Set([
|
|
3631
|
+
"decision",
|
|
3632
|
+
"adr",
|
|
3633
|
+
"behavior",
|
|
3634
|
+
"procedure"
|
|
3635
|
+
]);
|
|
3636
|
+
NOISE_DROP_PATTERNS = [
|
|
3637
|
+
/^\s*\[📋\s+\d+\s+reviews?\s+pending\b/im,
|
|
3638
|
+
/^\s*<system-reminder>[\s\S]*?<\/system-reminder>\s*$/im,
|
|
3639
|
+
/^\s*The UserPromptSubmit hook checks the DB for new tasks/im,
|
|
3640
|
+
/^\s*Intercom is a speedup, not delivery/im,
|
|
3641
|
+
/^\s*Context bar reads as USAGE not remaining/im
|
|
3642
|
+
];
|
|
3643
|
+
SKIP_EMBED_PATTERNS = [
|
|
3644
|
+
/tmux capture-pane\b/i,
|
|
3645
|
+
/docker ps\b/i,
|
|
3646
|
+
/docker images\b/i,
|
|
3647
|
+
/git status\b/i,
|
|
3648
|
+
/grep .*node_modules/i,
|
|
3649
|
+
/npm (install|ci)\b[\s\S]*(added \d+ packages|audited \d+ packages)/i
|
|
3650
|
+
];
|
|
3651
|
+
}
|
|
3652
|
+
});
|
|
3653
|
+
|
|
3455
3654
|
// src/lib/shard-manager.ts
|
|
3456
3655
|
var shard_manager_exports = {};
|
|
3457
3656
|
__export(shard_manager_exports, {
|
|
@@ -3616,7 +3815,8 @@ async function ensureShardSchema(client) {
|
|
|
3616
3815
|
}
|
|
3617
3816
|
for (const idx of [
|
|
3618
3817
|
"CREATE INDEX IF NOT EXISTS idx_memories_tier ON memories(tier)",
|
|
3619
|
-
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL"
|
|
3818
|
+
"CREATE INDEX IF NOT EXISTS idx_memories_supersedes ON memories(supersedes_id) WHERE supersedes_id IS NOT NULL",
|
|
3819
|
+
"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"
|
|
3620
3820
|
]) {
|
|
3621
3821
|
try {
|
|
3622
3822
|
await client.execute(idx);
|
|
@@ -3810,7 +4010,7 @@ var init_platform_procedures = __esm({
|
|
|
3810
4010
|
title: "Chain of command \u2014 who talks to whom",
|
|
3811
4011
|
domain: "workflow",
|
|
3812
4012
|
priority: "p0",
|
|
3813
|
-
content: "Founder -> COO -> CTO/CMO. CTO -> engineers. CMO -> content production. Never skip levels: the
|
|
4013
|
+
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."
|
|
3814
4014
|
},
|
|
3815
4015
|
{
|
|
3816
4016
|
title: "Single dispatch path \u2014 create_task only",
|
|
@@ -4041,7 +4241,6 @@ __export(store_exports, {
|
|
|
4041
4241
|
vectorToBlob: () => vectorToBlob,
|
|
4042
4242
|
writeMemory: () => writeMemory
|
|
4043
4243
|
});
|
|
4044
|
-
import { createHash } from "crypto";
|
|
4045
4244
|
function isBusyError2(err) {
|
|
4046
4245
|
if (err instanceof Error) {
|
|
4047
4246
|
const msg = err.message.toLowerCase();
|
|
@@ -4155,17 +4354,24 @@ async function writeMemory(record) {
|
|
|
4155
4354
|
`Expected ${EMBEDDING_DIM}-dim vector, got ${record.vector.length}`
|
|
4156
4355
|
);
|
|
4157
4356
|
}
|
|
4158
|
-
const
|
|
4159
|
-
if (
|
|
4357
|
+
const governed = governMemoryRecord(record);
|
|
4358
|
+
if (governed.shouldDrop) return;
|
|
4359
|
+
record = governed.record;
|
|
4360
|
+
const contentHash = governed.contentHash;
|
|
4361
|
+
const memoryType = record.memory_type ?? "raw";
|
|
4362
|
+
if (_pendingRecords.some(
|
|
4363
|
+
(r) => r.content_hash === contentHash && r.agent_id === record.agent_id && r.project_name === record.project_name && (r.memory_type ?? "raw") === memoryType
|
|
4364
|
+
)) {
|
|
4160
4365
|
return;
|
|
4161
4366
|
}
|
|
4162
4367
|
try {
|
|
4163
|
-
const
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4368
|
+
const existing = await findScopedDuplicate({
|
|
4369
|
+
contentHash,
|
|
4370
|
+
agentId: record.agent_id,
|
|
4371
|
+
projectName: record.project_name,
|
|
4372
|
+
memoryType
|
|
4167
4373
|
});
|
|
4168
|
-
if (existing
|
|
4374
|
+
if (existing) return;
|
|
4169
4375
|
} catch {
|
|
4170
4376
|
}
|
|
4171
4377
|
const dbRow = {
|
|
@@ -4196,7 +4402,7 @@ async function writeMemory(record) {
|
|
|
4196
4402
|
tier: record.tier ?? classifyTier(record),
|
|
4197
4403
|
supersedes_id: record.supersedes_id ?? null,
|
|
4198
4404
|
draft: record.draft ? 1 : 0,
|
|
4199
|
-
memory_type:
|
|
4405
|
+
memory_type: memoryType,
|
|
4200
4406
|
trajectory: record.trajectory ? JSON.stringify(record.trajectory) : null,
|
|
4201
4407
|
content_hash: contentHash,
|
|
4202
4408
|
intent: record.intent ?? null,
|
|
@@ -4355,6 +4561,7 @@ async function flushBatch() {
|
|
|
4355
4561
|
const globalClient = getClient();
|
|
4356
4562
|
const globalStmts = batch.map(buildStmt);
|
|
4357
4563
|
await globalClient.batch(globalStmts, "write");
|
|
4564
|
+
schedulePostWriteMemoryHygiene(batch.map((row) => row.id));
|
|
4358
4565
|
_pendingRecords.splice(0, batch.length);
|
|
4359
4566
|
try {
|
|
4360
4567
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
@@ -4475,7 +4682,11 @@ async function searchMemories(queryVector, agentId, options) {
|
|
|
4475
4682
|
sql += ` AND timestamp >= ?`;
|
|
4476
4683
|
args.push(options.since);
|
|
4477
4684
|
}
|
|
4478
|
-
if (options?.
|
|
4685
|
+
if (options?.memoryTypes && options.memoryTypes.length > 0) {
|
|
4686
|
+
const uniqueTypes = [...new Set(options.memoryTypes)];
|
|
4687
|
+
sql += ` AND memory_type IN (${uniqueTypes.map(() => "?").join(",")})`;
|
|
4688
|
+
args.push(...uniqueTypes);
|
|
4689
|
+
} else if (options?.memoryType) {
|
|
4479
4690
|
sql += ` AND memory_type = ?`;
|
|
4480
4691
|
args.push(options.memoryType);
|
|
4481
4692
|
}
|
|
@@ -4613,6 +4824,7 @@ var init_store = __esm({
|
|
|
4613
4824
|
init_keychain();
|
|
4614
4825
|
init_config();
|
|
4615
4826
|
init_state_bus();
|
|
4827
|
+
init_memory_write_governor();
|
|
4616
4828
|
INIT_MAX_RETRIES = 3;
|
|
4617
4829
|
INIT_RETRY_DELAY_MS = 1e3;
|
|
4618
4830
|
_pendingRecords = [];
|