@askexenow/exe-os 0.9.112 → 0.9.113
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/README.md +9 -7
- package/dist/bin/agentic-ontology-backfill.js +54 -11
- package/dist/bin/agentic-reflection-backfill.js +29 -1
- package/dist/bin/agentic-semantic-label.js +29 -1
- package/dist/bin/backfill-conversations.js +53 -10
- package/dist/bin/backfill-responses.js +54 -11
- package/dist/bin/backfill-vectors.js +29 -1
- package/dist/bin/bulk-sync-postgres.js +55 -12
- package/dist/bin/cleanup-stale-review-tasks.js +75 -15
- package/dist/bin/cli.js +293 -76
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +28 -2
- package/dist/bin/exe-assign.js +54 -11
- package/dist/bin/exe-boot.js +481 -147
- package/dist/bin/exe-call.js +45 -4
- package/dist/bin/exe-cloud.js +93 -15
- package/dist/bin/exe-dispatch.js +369 -24
- package/dist/bin/exe-doctor.js +53 -10
- package/dist/bin/exe-export-behaviors.js +54 -11
- package/dist/bin/exe-forget.js +54 -11
- package/dist/bin/exe-gateway.js +128 -23
- package/dist/bin/exe-heartbeat.js +75 -15
- package/dist/bin/exe-kill.js +54 -11
- package/dist/bin/exe-launch-agent.js +70 -12
- package/dist/bin/exe-new-employee.js +175 -7
- package/dist/bin/exe-pending-messages.js +75 -15
- package/dist/bin/exe-pending-notifications.js +75 -15
- package/dist/bin/exe-pending-reviews.js +75 -15
- package/dist/bin/exe-rename.js +54 -11
- package/dist/bin/exe-review.js +54 -11
- package/dist/bin/exe-search.js +54 -11
- package/dist/bin/exe-session-cleanup.js +491 -146
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +524 -245
- package/dist/bin/exe-start-opencode.js +534 -165
- package/dist/bin/exe-status.js +75 -15
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +54 -11
- package/dist/bin/git-sweep.js +369 -24
- package/dist/bin/graph-backfill.js +54 -11
- package/dist/bin/graph-export.js +54 -11
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +491 -146
- package/dist/bin/pre-publish.js +13 -1
- package/dist/bin/scan-tasks.js +369 -24
- package/dist/bin/setup.js +91 -13
- package/dist/bin/shard-migrate.js +54 -11
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +128 -23
- package/dist/hooks/bug-report-worker.js +128 -23
- package/dist/hooks/codex-stop-task-finalizer.js +512 -140
- package/dist/hooks/commit-complete.js +369 -24
- package/dist/hooks/error-recall.js +54 -11
- package/dist/hooks/ingest.js +4575 -252
- package/dist/hooks/instructions-loaded.js +54 -11
- package/dist/hooks/notification.js +54 -11
- package/dist/hooks/post-compact.js +75 -15
- package/dist/hooks/post-tool-combined.js +75 -15
- package/dist/hooks/pre-compact.js +449 -104
- package/dist/hooks/pre-tool-use.js +90 -15
- package/dist/hooks/prompt-submit.js +129 -24
- package/dist/hooks/session-end.js +451 -109
- package/dist/hooks/session-start.js +104 -16
- package/dist/hooks/stop.js +74 -14
- package/dist/hooks/subagent-stop.js +75 -15
- package/dist/hooks/summary-worker.js +73 -7
- package/dist/index.js +128 -23
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +38 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +16 -0
- package/dist/lib/db.js +16 -0
- package/dist/lib/device-registry.js +16 -0
- package/dist/lib/employee-templates.js +29 -3
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +268 -42
- package/dist/lib/hybrid-search.js +54 -11
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +29 -1
- package/dist/lib/skill-learning.js +458 -70
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +54 -11
- package/dist/lib/tasks.js +393 -91
- package/dist/lib/tmux-routing.js +316 -14
- package/dist/mcp/server.js +169 -30
- package/dist/mcp/tools/create-task.js +75 -13
- package/dist/mcp/tools/deactivate-behavior.js +33 -24
- package/dist/mcp/tools/list-tasks.js +21 -4
- package/dist/mcp/tools/send-message.js +21 -4
- package/dist/mcp/tools/update-task.js +390 -91
- package/dist/runtime/index.js +446 -101
- package/dist/tui/App.js +208 -54
- package/package.json +1 -1
package/dist/bin/setup.js
CHANGED
|
@@ -1713,7 +1713,7 @@ async function assertVpsLicense(opts) {
|
|
|
1713
1713
|
}
|
|
1714
1714
|
if (!transientFailure) {
|
|
1715
1715
|
throw new Error(
|
|
1716
|
-
"License validation failed: unknown backend state. Restore network connectivity to https://askexe.com
|
|
1716
|
+
"License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
|
|
1717
1717
|
);
|
|
1718
1718
|
}
|
|
1719
1719
|
const fresh = await getCachedLicense();
|
|
@@ -1750,7 +1750,7 @@ async function assertVpsLicense(opts) {
|
|
|
1750
1750
|
} catch {
|
|
1751
1751
|
}
|
|
1752
1752
|
throw new Error(
|
|
1753
|
-
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com
|
|
1753
|
+
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://cloud.askexe.com and retry. This VPS image refuses to boot after the offline grace window.`
|
|
1754
1754
|
);
|
|
1755
1755
|
}
|
|
1756
1756
|
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
@@ -1782,7 +1782,7 @@ var init_license = __esm({
|
|
|
1782
1782
|
LICENSE_PATH = path6.join(EXE_AI_DIR, "license.key");
|
|
1783
1783
|
CACHE_PATH = path6.join(EXE_AI_DIR, "license-cache.json");
|
|
1784
1784
|
DEVICE_ID_PATH = path6.join(EXE_AI_DIR, "device-id");
|
|
1785
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
1785
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
1786
1786
|
RETRY_DELAY_MS = 500;
|
|
1787
1787
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
1788
1788
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|
|
@@ -1964,6 +1964,7 @@ __export(agent_config_exports, {
|
|
|
1964
1964
|
getAgentRuntime: () => getAgentRuntime,
|
|
1965
1965
|
loadAgentConfig: () => loadAgentConfig,
|
|
1966
1966
|
saveAgentConfig: () => saveAgentConfig,
|
|
1967
|
+
setAgentMcps: () => setAgentMcps,
|
|
1967
1968
|
setAgentRuntime: () => setAgentRuntime
|
|
1968
1969
|
});
|
|
1969
1970
|
import { readFileSync as readFileSync5, writeFileSync as writeFileSync3, existsSync as existsSync8 } from "fs";
|
|
@@ -1990,7 +1991,7 @@ function getAgentRuntime(agentId) {
|
|
|
1990
1991
|
if (orgDefault) return orgDefault;
|
|
1991
1992
|
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
1992
1993
|
}
|
|
1993
|
-
function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
|
|
1994
|
+
function setAgentRuntime(agentId, runtime, model, reasoning_effort, mcps) {
|
|
1994
1995
|
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
1995
1996
|
if (!knownModels) {
|
|
1996
1997
|
return {
|
|
@@ -2005,12 +2006,26 @@ function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
|
|
|
2005
2006
|
};
|
|
2006
2007
|
}
|
|
2007
2008
|
const config = loadAgentConfig();
|
|
2009
|
+
const existing = config[agentId];
|
|
2008
2010
|
const entry = { runtime, model };
|
|
2009
2011
|
if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
|
|
2012
|
+
if (mcps !== void 0) {
|
|
2013
|
+
entry.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
2014
|
+
} else if (existing?.mcps) {
|
|
2015
|
+
entry.mcps = existing.mcps;
|
|
2016
|
+
}
|
|
2010
2017
|
config[agentId] = entry;
|
|
2011
2018
|
saveAgentConfig(config);
|
|
2012
2019
|
return { ok: true };
|
|
2013
2020
|
}
|
|
2021
|
+
function setAgentMcps(agentId, mcps) {
|
|
2022
|
+
const config = loadAgentConfig();
|
|
2023
|
+
const existing = config[agentId] ?? getAgentRuntime(agentId);
|
|
2024
|
+
existing.mcps = mcps.includes("exe-os") ? mcps : ["exe-os", ...mcps];
|
|
2025
|
+
config[agentId] = existing;
|
|
2026
|
+
saveAgentConfig(config);
|
|
2027
|
+
return { ok: true };
|
|
2028
|
+
}
|
|
2014
2029
|
function clearAgentRuntime(agentId) {
|
|
2015
2030
|
const config = loadAgentConfig();
|
|
2016
2031
|
delete config[agentId];
|
|
@@ -4673,6 +4688,22 @@ async function ensureSchema() {
|
|
|
4673
4688
|
} catch (e) {
|
|
4674
4689
|
logCatchDebug("migration", e);
|
|
4675
4690
|
}
|
|
4691
|
+
try {
|
|
4692
|
+
await client.execute({
|
|
4693
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
4694
|
+
args: []
|
|
4695
|
+
});
|
|
4696
|
+
} catch (e) {
|
|
4697
|
+
logCatchDebug("migration", e);
|
|
4698
|
+
}
|
|
4699
|
+
try {
|
|
4700
|
+
await client.execute({
|
|
4701
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
4702
|
+
args: []
|
|
4703
|
+
});
|
|
4704
|
+
} catch (e) {
|
|
4705
|
+
logCatchDebug("migration", e);
|
|
4706
|
+
}
|
|
4676
4707
|
}
|
|
4677
4708
|
async function disposeDatabase() {
|
|
4678
4709
|
if (_walCheckpointTimer) {
|
|
@@ -5516,6 +5547,27 @@ async function cloudSync(config) {
|
|
|
5516
5547
|
if (stmts.length > 0) await client.batch(stmts, "write");
|
|
5517
5548
|
pulled = pullResult.records.length;
|
|
5518
5549
|
} else {
|
|
5550
|
+
try {
|
|
5551
|
+
const incomingIds = pullResult.records.map((r) => sqlSafe(r.id));
|
|
5552
|
+
if (incomingIds.length > 0) {
|
|
5553
|
+
const ph = incomingIds.map(() => "?").join(",");
|
|
5554
|
+
const existing = await client.execute({
|
|
5555
|
+
sql: `SELECT id, version, timestamp FROM memories WHERE id IN (${ph})`,
|
|
5556
|
+
args: incomingIds
|
|
5557
|
+
});
|
|
5558
|
+
const localMap = new Map(existing.rows.map((r) => [String(r.id), r]));
|
|
5559
|
+
for (const rec of pullResult.records) {
|
|
5560
|
+
const local = localMap.get(String(rec.id));
|
|
5561
|
+
if (local && Number(local.version) > 0 && Number(local.version) !== Number(rec.version ?? 0)) {
|
|
5562
|
+
process.stderr.write(
|
|
5563
|
+
`[cloud-sync] CONFLICT: memory ${String(rec.id).slice(0, 8)} \u2014 local v${local.version} vs remote v${rec.version ?? 0}. Remote wins (LWW).
|
|
5564
|
+
`
|
|
5565
|
+
);
|
|
5566
|
+
}
|
|
5567
|
+
}
|
|
5568
|
+
}
|
|
5569
|
+
} catch {
|
|
5570
|
+
}
|
|
5519
5571
|
const stmts = pullResult.records.map((rec) => ({
|
|
5520
5572
|
sql: `INSERT OR REPLACE INTO memories
|
|
5521
5573
|
(id, agent_id, agent_role, session_id, timestamp,
|
|
@@ -6752,11 +6804,17 @@ var init_platform_procedures = __esm({
|
|
|
6752
6804
|
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."
|
|
6753
6805
|
},
|
|
6754
6806
|
{
|
|
6755
|
-
title: "
|
|
6807
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
6756
6808
|
domain: "workflow",
|
|
6757
6809
|
priority: "p1",
|
|
6758
6810
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
6759
6811
|
},
|
|
6812
|
+
{
|
|
6813
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
6814
|
+
domain: "identity",
|
|
6815
|
+
priority: "p0",
|
|
6816
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
6817
|
+
},
|
|
6760
6818
|
{
|
|
6761
6819
|
title: "Single dispatch path \u2014 create_task only",
|
|
6762
6820
|
domain: "workflow",
|
|
@@ -6790,6 +6848,12 @@ var init_platform_procedures = __esm({
|
|
|
6790
6848
|
priority: "p0",
|
|
6791
6849
|
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
|
|
6792
6850
|
},
|
|
6851
|
+
{
|
|
6852
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
6853
|
+
domain: "security",
|
|
6854
|
+
priority: "p0",
|
|
6855
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
6856
|
+
},
|
|
6793
6857
|
{
|
|
6794
6858
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
6795
6859
|
domain: "support",
|
|
@@ -7035,9 +7099,23 @@ __export(employee_templates_exports, {
|
|
|
7035
7099
|
function getSessionPrompt(storedPrompt) {
|
|
7036
7100
|
const markerIndex = storedPrompt.indexOf(PROCEDURES_MARKER);
|
|
7037
7101
|
const withoutProcedures = markerIndex >= 0 ? storedPrompt.slice(0, markerIndex).trimEnd() : storedPrompt;
|
|
7102
|
+
let titlePrefix = "";
|
|
7103
|
+
const frontmatterMatch = withoutProcedures.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
7104
|
+
if (frontmatterMatch) {
|
|
7105
|
+
const titleMatch = frontmatterMatch[1].match(/^title:\s*(.+)$/m);
|
|
7106
|
+
const roleMatch = frontmatterMatch[1].match(/^role:\s*(.+)$/m);
|
|
7107
|
+
if (titleMatch) {
|
|
7108
|
+
const title = titleMatch[1].trim();
|
|
7109
|
+
const role = roleMatch ? roleMatch[1].trim() : "";
|
|
7110
|
+
if (title && role && title.toLowerCase() !== role.toLowerCase()) {
|
|
7111
|
+
titlePrefix = `## Your Identity
|
|
7112
|
+
You are **${title}** (specialist). `;
|
|
7113
|
+
}
|
|
7114
|
+
}
|
|
7115
|
+
}
|
|
7038
7116
|
const rolePrompt = withoutProcedures.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, "").replace(/<!--[\s\S]*?-->/g, "").trimStart();
|
|
7039
7117
|
const globalBlock = getGlobalProceduresBlock();
|
|
7040
|
-
return `${globalBlock}${rolePrompt}
|
|
7118
|
+
return `${globalBlock}${titlePrefix}${rolePrompt}
|
|
7041
7119
|
${BASE_OPERATING_PROCEDURES}`;
|
|
7042
7120
|
}
|
|
7043
7121
|
function buildCustomEmployeePrompt(name, role) {
|
|
@@ -7056,7 +7134,7 @@ function personalizePrompt(prompt, templateName, actualName) {
|
|
|
7056
7134
|
return prompt.replace(new RegExp(`\\bYou are ${escaped}\\b`, "g"), `You are ${actualName}`);
|
|
7057
7135
|
}
|
|
7058
7136
|
function renderClientCOOTemplate(vars) {
|
|
7059
|
-
const resolved = { ...vars, title: vars.title || "Chief
|
|
7137
|
+
const resolved = { ...vars, title: vars.title || "Chief of Staff" };
|
|
7060
7138
|
for (const key of CLIENT_COO_PLACEHOLDERS) {
|
|
7061
7139
|
const value = resolved[key];
|
|
7062
7140
|
if (typeof value !== "string" || value.length === 0) {
|
|
@@ -8745,7 +8823,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8745
8823
|
log("");
|
|
8746
8824
|
const apiKey = await ask(rl, "Cloud API key (starts with exe_sk_): ");
|
|
8747
8825
|
if (apiKey && apiKey.startsWith("exe_sk_")) {
|
|
8748
|
-
const cloudEndpoint = "https://askexe.com
|
|
8826
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
8749
8827
|
const cloudCfg = { apiKey, endpoint: cloudEndpoint };
|
|
8750
8828
|
const earlyConfig = await loadConfig();
|
|
8751
8829
|
earlyConfig.cloud = cloudCfg;
|
|
@@ -8845,7 +8923,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8845
8923
|
log("");
|
|
8846
8924
|
const existingKey = await ask(rl, "Paste your Exe OS license key, or press Enter to start as a free user: ");
|
|
8847
8925
|
if (existingKey && existingKey.startsWith("exe_sk_")) {
|
|
8848
|
-
const cloudEndpoint = "https://askexe.com
|
|
8926
|
+
const cloudEndpoint = "https://cloud.askexe.com";
|
|
8849
8927
|
try {
|
|
8850
8928
|
const { loadDeviceId: loadDeviceId2 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
8851
8929
|
const deviceId = loadDeviceId2();
|
|
@@ -8870,7 +8948,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8870
8948
|
}
|
|
8871
8949
|
} catch {
|
|
8872
8950
|
log("Could not validate key \u2014 saving it and proceeding.");
|
|
8873
|
-
cloudConfig = { apiKey: existingKey, endpoint: "https://askexe.com
|
|
8951
|
+
cloudConfig = { apiKey: existingKey, endpoint: "https://cloud.askexe.com" };
|
|
8874
8952
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
8875
8953
|
saveLicense3(existingKey);
|
|
8876
8954
|
mirrorLicenseKey3(existingKey);
|
|
@@ -8882,7 +8960,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8882
8960
|
const deviceId = loadDeviceId2();
|
|
8883
8961
|
let res;
|
|
8884
8962
|
try {
|
|
8885
|
-
res = await fetch("https://askexe.com/
|
|
8963
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
8886
8964
|
method: "POST",
|
|
8887
8965
|
headers: { "Content-Type": "application/json" },
|
|
8888
8966
|
body: JSON.stringify({ deviceId }),
|
|
@@ -8890,7 +8968,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8890
8968
|
});
|
|
8891
8969
|
} catch {
|
|
8892
8970
|
await new Promise((r) => setTimeout(r, 500));
|
|
8893
|
-
res = await fetch("https://askexe.com/
|
|
8971
|
+
res = await fetch("https://cloud.askexe.com/auth/auto-provision", {
|
|
8894
8972
|
method: "POST",
|
|
8895
8973
|
headers: { "Content-Type": "application/json" },
|
|
8896
8974
|
body: JSON.stringify({ deviceId }),
|
|
@@ -8900,7 +8978,7 @@ async function runSetupWizard(opts = {}) {
|
|
|
8900
8978
|
if (res.ok) {
|
|
8901
8979
|
const data = await res.json();
|
|
8902
8980
|
if (data.apiKey) {
|
|
8903
|
-
cloudConfig = { apiKey: data.apiKey, endpoint: "https://askexe.com
|
|
8981
|
+
cloudConfig = { apiKey: data.apiKey, endpoint: "https://cloud.askexe.com" };
|
|
8904
8982
|
const { saveLicense: saveLicense3, mirrorLicenseKey: mirrorLicenseKey3 } = await Promise.resolve().then(() => (init_license(), license_exports));
|
|
8905
8983
|
saveLicense3(data.apiKey);
|
|
8906
8984
|
mirrorLicenseKey3(data.apiKey);
|
|
@@ -3034,6 +3034,22 @@ async function ensureSchema() {
|
|
|
3034
3034
|
} catch (e) {
|
|
3035
3035
|
logCatchDebug("migration", e);
|
|
3036
3036
|
}
|
|
3037
|
+
try {
|
|
3038
|
+
await client.execute({
|
|
3039
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3040
|
+
args: []
|
|
3041
|
+
});
|
|
3042
|
+
} catch (e) {
|
|
3043
|
+
logCatchDebug("migration", e);
|
|
3044
|
+
}
|
|
3045
|
+
try {
|
|
3046
|
+
await client.execute({
|
|
3047
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3048
|
+
args: []
|
|
3049
|
+
});
|
|
3050
|
+
} catch (e) {
|
|
3051
|
+
logCatchDebug("migration", e);
|
|
3052
|
+
}
|
|
3037
3053
|
}
|
|
3038
3054
|
async function disposeDatabase() {
|
|
3039
3055
|
if (_walCheckpointTimer) {
|
|
@@ -3600,11 +3616,17 @@ var init_platform_procedures = __esm({
|
|
|
3600
3616
|
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."
|
|
3601
3617
|
},
|
|
3602
3618
|
{
|
|
3603
|
-
title: "
|
|
3619
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
3604
3620
|
domain: "workflow",
|
|
3605
3621
|
priority: "p1",
|
|
3606
3622
|
content: "New customers start best in Phase 1: founder \u2194 coordinator/Chief of Staff, building company context. Suggest Phase 2 executives when domain work repeats; suggest Phase 3 parallel execution only when review/permission gates are ready. This is guidance, not a blocker: users may jump phases anytime. Never overwrite their phase, role titles, identities, or custom org design."
|
|
3607
3623
|
},
|
|
3624
|
+
{
|
|
3625
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
3626
|
+
domain: "identity",
|
|
3627
|
+
priority: "p0",
|
|
3628
|
+
content: "These procedures reference 'COO' as a shorthand for the coordinator role. This is an INTERNAL routing slot used by exe-os code (chain-of-command checks, dispatch logic, session detection). It is NOT your display title. Your actual title comes from your identity file's `title:` field \u2014 that is what you use externally: introductions, sign-offs, team comms, and any user-facing text. If your identity says `title: AI Chief of Staff`, you are the AI Chief of Staff. The routing slot stays `role: coo` for code compatibility \u2014 never rename it, but also never introduce yourself as 'COO' unless your identity file explicitly says so. The founder chose your title; respect it."
|
|
3629
|
+
},
|
|
3608
3630
|
{
|
|
3609
3631
|
title: "Single dispatch path \u2014 create_task only",
|
|
3610
3632
|
domain: "workflow",
|
|
@@ -3638,6 +3660,12 @@ var init_platform_procedures = __esm({
|
|
|
3638
3660
|
priority: "p0",
|
|
3639
3661
|
content: "NEVER: (1) Access the database directly \u2014 it's SQLCipher encrypted, always fails. Use MCP tools only. (2) Manually spawn tmux sessions \u2014 create_task handles it. (3) Run git checkout main \u2014 agents work in worktrees. (4) Modify another agent's in-progress task. (5) Push to remote \u2014 the COO reviews and pushes. (6) Skip update_task(done) \u2014 it's the ONLY way your work gets reviewed. (7) Run git init."
|
|
3640
3662
|
},
|
|
3663
|
+
{
|
|
3664
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
3665
|
+
domain: "security",
|
|
3666
|
+
priority: "p0",
|
|
3667
|
+
content: "Before ANY destructive operation (delete, remove, overwrite, drop, reset, force-push, truncate), you MUST: (1) Have your full task spec accessible \u2014 if you cannot read it, STOP and report to your reviewer. Never improvise destructive actions. (2) Confirm with your reviewer (assigned_by or COO) before executing. (3) If the task spec explicitly authorizes the operation, proceed \u2014 but log it. Violation = immediate task failure. This applies to ALL agents regardless of role."
|
|
3668
|
+
},
|
|
3641
3669
|
{
|
|
3642
3670
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
3643
3671
|
domain: "support",
|
|
@@ -3923,10 +3951,24 @@ function stableId(memoryId, type, content) {
|
|
|
3923
3951
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
3924
3952
|
}
|
|
3925
3953
|
function cleanText(text) {
|
|
3926
|
-
|
|
3927
|
-
|
|
3928
|
-
|
|
3929
|
-
|
|
3954
|
+
let cleaned = text.replace(
|
|
3955
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
3956
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
3957
|
+
);
|
|
3958
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
3959
|
+
return cleaned;
|
|
3960
|
+
}
|
|
3961
|
+
function splitSegments(text) {
|
|
3962
|
+
const cleaned = cleanText(text);
|
|
3963
|
+
const segments = cleaned.split(/(?<=[.!?:;])\s+|\n{2,}|(?<=\))\s+(?=[A-Z])|\s*[|│]\s*/).map((s) => s.trim()).filter((s) => s.length >= MIN_SEGMENT_CHARS && s.length <= MAX_SEGMENT_CHARS);
|
|
3964
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
3965
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
3966
|
+
if (lines.length > 0) return lines;
|
|
3967
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
3968
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
3969
|
+
}
|
|
3970
|
+
}
|
|
3971
|
+
return segments;
|
|
3930
3972
|
}
|
|
3931
3973
|
function inferCardType(sentence, toolName) {
|
|
3932
3974
|
const lower = sentence.toLowerCase();
|
|
@@ -3958,12 +4000,12 @@ function predicateFor(type) {
|
|
|
3958
4000
|
}
|
|
3959
4001
|
}
|
|
3960
4002
|
function extractMemoryCards(row) {
|
|
3961
|
-
const
|
|
4003
|
+
const segments = splitSegments(row.raw_text);
|
|
3962
4004
|
const cards = [];
|
|
3963
|
-
for (const sentence of
|
|
4005
|
+
for (const sentence of segments) {
|
|
3964
4006
|
const type = inferCardType(sentence, row.tool_name);
|
|
3965
4007
|
const subject = extractSubject(sentence, row.agent_id);
|
|
3966
|
-
const content = sentence.length >
|
|
4008
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
3967
4009
|
cards.push({
|
|
3968
4010
|
id: stableId(row.id, type, content),
|
|
3969
4011
|
memory_id: row.id,
|
|
@@ -4059,13 +4101,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
4059
4101
|
last_accessed: String(row.timestamp)
|
|
4060
4102
|
}));
|
|
4061
4103
|
}
|
|
4062
|
-
var MAX_CARDS_PER_MEMORY,
|
|
4104
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
4063
4105
|
var init_memory_cards = __esm({
|
|
4064
4106
|
"src/lib/memory-cards.ts"() {
|
|
4065
4107
|
"use strict";
|
|
4066
4108
|
init_database();
|
|
4067
|
-
MAX_CARDS_PER_MEMORY =
|
|
4068
|
-
|
|
4109
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
4110
|
+
MAX_SEGMENT_CHARS = 500;
|
|
4111
|
+
MIN_SEGMENT_CHARS = 20;
|
|
4069
4112
|
}
|
|
4070
4113
|
});
|
|
4071
4114
|
|
package/dist/bin/stack-update.js
CHANGED
|
@@ -140,7 +140,7 @@ var DEFAULT_CONFIG = {
|
|
|
140
140
|
var LICENSE_PATH = path2.join(EXE_AI_DIR, "license.key");
|
|
141
141
|
var CACHE_PATH = path2.join(EXE_AI_DIR, "license-cache.json");
|
|
142
142
|
var DEVICE_ID_PATH = path2.join(EXE_AI_DIR, "device-id");
|
|
143
|
-
var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
143
|
+
var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
144
144
|
function loadLicense() {
|
|
145
145
|
try {
|
|
146
146
|
if (!existsSync3(LICENSE_PATH)) return null;
|
package/dist/bin/update.js
CHANGED
|
@@ -491,7 +491,7 @@ async function assertVpsLicense(opts) {
|
|
|
491
491
|
}
|
|
492
492
|
if (!transientFailure) {
|
|
493
493
|
throw new Error(
|
|
494
|
-
"License validation failed: unknown backend state. Restore network connectivity to https://askexe.com
|
|
494
|
+
"License validation failed: unknown backend state. Restore network connectivity to https://cloud.askexe.com and retry."
|
|
495
495
|
);
|
|
496
496
|
}
|
|
497
497
|
const fresh = await getCachedLicense();
|
|
@@ -528,7 +528,7 @@ async function assertVpsLicense(opts) {
|
|
|
528
528
|
} catch {
|
|
529
529
|
}
|
|
530
530
|
throw new Error(
|
|
531
|
-
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://askexe.com
|
|
531
|
+
`License validation unreachable for more than ${graceDays} days. Restore network connectivity to https://cloud.askexe.com and retry. This VPS image refuses to boot after the offline grace window.`
|
|
532
532
|
);
|
|
533
533
|
}
|
|
534
534
|
function startLicenseRevalidation(intervalMs = 36e5) {
|
|
@@ -560,7 +560,7 @@ var init_license = __esm({
|
|
|
560
560
|
LICENSE_PATH = path4.join(EXE_AI_DIR, "license.key");
|
|
561
561
|
CACHE_PATH = path4.join(EXE_AI_DIR, "license-cache.json");
|
|
562
562
|
DEVICE_ID_PATH = path4.join(EXE_AI_DIR, "device-id");
|
|
563
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
563
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
564
564
|
RETRY_DELAY_MS = 500;
|
|
565
565
|
LICENSE_PUBLIC_KEY_PEM = `-----BEGIN PUBLIC KEY-----
|
|
566
566
|
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEeHztAMOpR/ZMh+rWuOASjEZ54CGY
|