@askexenow/exe-os 0.9.21 → 0.9.23
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 +17 -4
- package/dist/bin/backfill-responses.js +17 -4
- package/dist/bin/backfill-vectors.js +2 -2
- package/dist/bin/cleanup-stale-review-tasks.js +17 -4
- package/dist/bin/cli.js +378 -171
- package/dist/bin/exe-assign.js +17 -4
- package/dist/bin/exe-boot.js +2 -2
- package/dist/bin/exe-dispatch.js +17 -4
- package/dist/bin/exe-doctor.js +2 -2
- package/dist/bin/exe-export-behaviors.js +17 -4
- package/dist/bin/exe-forget.js +17 -4
- package/dist/bin/exe-gateway.js +17 -4
- package/dist/bin/exe-heartbeat.js +17 -4
- package/dist/bin/exe-kill.js +17 -4
- package/dist/bin/exe-launch-agent.js +17 -4
- package/dist/bin/exe-pending-messages.js +17 -4
- package/dist/bin/exe-pending-notifications.js +17 -4
- package/dist/bin/exe-pending-reviews.js +17 -4
- package/dist/bin/exe-review.js +17 -4
- package/dist/bin/exe-search.js +23 -8
- package/dist/bin/exe-session-cleanup.js +17 -4
- package/dist/bin/exe-start-codex.js +209 -32
- package/dist/bin/exe-start-opencode.js +17 -4
- package/dist/bin/exe-status.js +17 -4
- package/dist/bin/exe-team.js +17 -4
- package/dist/bin/git-sweep.js +17 -4
- package/dist/bin/graph-backfill.js +17 -4
- package/dist/bin/graph-export.js +17 -4
- package/dist/bin/install.js +42 -0
- package/dist/bin/intercom-check.js +17 -4
- package/dist/bin/scan-tasks.js +17 -4
- package/dist/bin/shard-migrate.js +17 -4
- package/dist/bin/update.js +187 -42
- package/dist/gateway/index.js +17 -4
- package/dist/hooks/bug-report-worker.js +793 -150
- package/dist/hooks/codex-stop-task-finalizer.js +3020 -2375
- package/dist/hooks/commit-complete.js +156 -6
- package/dist/hooks/error-recall.js +23 -8
- package/dist/hooks/ingest.js +17 -4
- package/dist/hooks/instructions-loaded.js +17 -4
- package/dist/hooks/notification.js +17 -4
- package/dist/hooks/post-compact.js +17 -4
- package/dist/hooks/post-tool-combined.js +23 -8
- package/dist/hooks/pre-compact.js +156 -8
- package/dist/hooks/pre-tool-use.js +21 -12
- package/dist/hooks/prompt-submit.js +23 -8
- package/dist/hooks/session-end.js +156 -8
- package/dist/hooks/session-start.js +23 -8
- package/dist/hooks/stop.js +306 -9
- package/dist/hooks/subagent-stop.js +306 -9
- package/dist/hooks/summary-worker.js +2 -2
- package/dist/index.js +17 -4
- package/dist/lib/exe-daemon.js +37 -14
- package/dist/lib/hybrid-search.js +23 -8
- package/dist/lib/schedules.js +2 -2
- package/dist/lib/store.js +17 -4
- package/dist/mcp/server.js +36 -10
- package/dist/runtime/index.js +17 -4
- package/dist/tui/App.js +17 -4
- package/package.json +1 -1
|
@@ -2956,8 +2956,8 @@ function getShardClient(projectName) {
|
|
|
2956
2956
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2957
2957
|
}
|
|
2958
2958
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2959
|
-
if (!safeName) {
|
|
2960
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
2959
|
+
if (!safeName || safeName === "unknown") {
|
|
2960
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2961
2961
|
}
|
|
2962
2962
|
const cached = _shards.get(safeName);
|
|
2963
2963
|
if (cached) {
|
|
@@ -3826,19 +3826,32 @@ async function flushBatch() {
|
|
|
3826
3826
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
3827
3827
|
if (isShardingEnabled2()) {
|
|
3828
3828
|
const byProject = /* @__PURE__ */ new Map();
|
|
3829
|
+
let skippedUnknown = 0;
|
|
3829
3830
|
for (const row of batch) {
|
|
3830
|
-
const proj = row.project_name
|
|
3831
|
+
const proj = row.project_name?.trim();
|
|
3832
|
+
if (!proj) {
|
|
3833
|
+
skippedUnknown++;
|
|
3834
|
+
continue;
|
|
3835
|
+
}
|
|
3831
3836
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
3832
3837
|
byProject.get(proj).push(row);
|
|
3833
3838
|
}
|
|
3839
|
+
if (skippedUnknown > 0) {
|
|
3840
|
+
process.stderr.write(
|
|
3841
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
3842
|
+
`
|
|
3843
|
+
);
|
|
3844
|
+
}
|
|
3834
3845
|
for (const [project, rows] of byProject) {
|
|
3835
3846
|
try {
|
|
3836
3847
|
const shardClient = await getReadyShardClient2(project);
|
|
3837
3848
|
const shardStmts = rows.map(buildStmt);
|
|
3838
3849
|
await shardClient.batch(shardStmts, "write");
|
|
3839
3850
|
} catch (err) {
|
|
3851
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
3852
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
3840
3853
|
process.stderr.write(
|
|
3841
|
-
`[store] Shard write failed for ${project}
|
|
3854
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
3842
3855
|
`
|
|
3843
3856
|
);
|
|
3844
3857
|
}
|
|
@@ -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;
|
|
@@ -2607,8 +2618,8 @@ function getShardClient(projectName) {
|
|
|
2607
2618
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2608
2619
|
}
|
|
2609
2620
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2610
|
-
if (!safeName) {
|
|
2611
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
2621
|
+
if (!safeName || safeName === "unknown") {
|
|
2622
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2612
2623
|
}
|
|
2613
2624
|
const cached = _shards.get(safeName);
|
|
2614
2625
|
if (cached) {
|
|
@@ -3141,7 +3152,7 @@ ${p.content}`).join("\n\n");
|
|
|
3141
3152
|
});
|
|
3142
3153
|
|
|
3143
3154
|
// src/lib/runtime-table.ts
|
|
3144
|
-
var RUNTIME_TABLE;
|
|
3155
|
+
var RUNTIME_TABLE, DEFAULT_RUNTIME;
|
|
3145
3156
|
var init_runtime_table = __esm({
|
|
3146
3157
|
"src/lib/runtime-table.ts"() {
|
|
3147
3158
|
"use strict";
|
|
@@ -3163,6 +3174,7 @@ var init_runtime_table = __esm({
|
|
|
3163
3174
|
defaultModel: "anthropic/claude-sonnet-4-6"
|
|
3164
3175
|
}
|
|
3165
3176
|
};
|
|
3177
|
+
DEFAULT_RUNTIME = "claude";
|
|
3166
3178
|
}
|
|
3167
3179
|
});
|
|
3168
3180
|
|
|
@@ -3513,6 +3525,7 @@ var installer_exports = {};
|
|
|
3513
3525
|
__export(installer_exports, {
|
|
3514
3526
|
installCodexStatusLine: () => installCodexStatusLine,
|
|
3515
3527
|
mergeCodexHooks: () => mergeCodexHooks,
|
|
3528
|
+
registerCodexMcpServer: () => registerCodexMcpServer,
|
|
3516
3529
|
runCodexInstaller: () => runCodexInstaller,
|
|
3517
3530
|
verifyCodexHooks: () => verifyCodexHooks
|
|
3518
3531
|
});
|
|
@@ -3684,11 +3697,52 @@ status_line = [${DEFAULT_CODEX_STATUS_LINE.map((s) => `"${s}"`).join(", ")}]`;
|
|
|
3684
3697
|
await writeFile5(configPath, content);
|
|
3685
3698
|
return "installed";
|
|
3686
3699
|
}
|
|
3700
|
+
async function registerCodexMcpServer(packageRoot, homeDir = os10.homedir()) {
|
|
3701
|
+
const codexDir = path13.join(homeDir, ".codex");
|
|
3702
|
+
const configPath = path13.join(codexDir, "config.toml");
|
|
3703
|
+
const serverJsPath = path13.join(packageRoot, "dist", "mcp", "server.js");
|
|
3704
|
+
await mkdir5(codexDir, { recursive: true });
|
|
3705
|
+
let content = "";
|
|
3706
|
+
if (existsSync12(configPath)) {
|
|
3707
|
+
content = await readFile5(configPath, "utf-8");
|
|
3708
|
+
}
|
|
3709
|
+
const sectionHeader = "[mcp_servers.exe-os]";
|
|
3710
|
+
const headerIndex = content.indexOf(sectionHeader);
|
|
3711
|
+
if (headerIndex !== -1) {
|
|
3712
|
+
const afterHeader = content.slice(headerIndex + sectionHeader.length);
|
|
3713
|
+
const nextSectionMatch = afterHeader.match(/\n\[(?!mcp_servers\.exe-os)/);
|
|
3714
|
+
const sectionEnd = nextSectionMatch ? headerIndex + sectionHeader.length + nextSectionMatch.index : content.length;
|
|
3715
|
+
const sectionContent = content.slice(headerIndex, sectionEnd);
|
|
3716
|
+
if (sectionContent.includes(serverJsPath)) {
|
|
3717
|
+
return "already-registered";
|
|
3718
|
+
}
|
|
3719
|
+
const newSection2 = `${sectionHeader}
|
|
3720
|
+
command = "node"
|
|
3721
|
+
args = ["${serverJsPath}"]
|
|
3722
|
+
`;
|
|
3723
|
+
content = content.slice(0, headerIndex) + newSection2 + content.slice(sectionEnd);
|
|
3724
|
+
await writeFile5(configPath, content);
|
|
3725
|
+
return "updated";
|
|
3726
|
+
}
|
|
3727
|
+
const newSection = `[mcp_servers.exe-os]
|
|
3728
|
+
command = "node"
|
|
3729
|
+
args = ["${serverJsPath}"]
|
|
3730
|
+
`;
|
|
3731
|
+
const separator = content.length > 0 && !content.endsWith("\n") ? "\n\n" : content.length > 0 ? "\n" : "";
|
|
3732
|
+
content = content + separator + newSection;
|
|
3733
|
+
await writeFile5(configPath, content);
|
|
3734
|
+
return "registered";
|
|
3735
|
+
}
|
|
3687
3736
|
async function runCodexInstaller(homeDir) {
|
|
3688
3737
|
const packageRoot = resolvePackageRoot();
|
|
3689
3738
|
const result = await mergeCodexHooks(packageRoot, homeDir);
|
|
3690
3739
|
process.stderr.write(
|
|
3691
3740
|
`[exe-os] Codex hooks: ${result.added} added, ${result.skipped} unchanged
|
|
3741
|
+
`
|
|
3742
|
+
);
|
|
3743
|
+
const mcpResult = await registerCodexMcpServer(packageRoot, homeDir);
|
|
3744
|
+
process.stderr.write(
|
|
3745
|
+
`[exe-os] Codex MCP server: ${mcpResult}
|
|
3692
3746
|
`
|
|
3693
3747
|
);
|
|
3694
3748
|
const statusResult = await installCodexStatusLine(homeDir);
|
|
@@ -3714,13 +3768,102 @@ var init_installer2 = __esm({
|
|
|
3714
3768
|
}
|
|
3715
3769
|
});
|
|
3716
3770
|
|
|
3771
|
+
// src/lib/agent-config.ts
|
|
3772
|
+
var agent_config_exports = {};
|
|
3773
|
+
__export(agent_config_exports, {
|
|
3774
|
+
AGENT_CONFIG_PATH: () => AGENT_CONFIG_PATH,
|
|
3775
|
+
DEFAULT_MODELS: () => DEFAULT_MODELS,
|
|
3776
|
+
KNOWN_RUNTIMES: () => KNOWN_RUNTIMES,
|
|
3777
|
+
RUNTIME_LABELS: () => RUNTIME_LABELS,
|
|
3778
|
+
clearAgentRuntime: () => clearAgentRuntime,
|
|
3779
|
+
getAgentRuntime: () => getAgentRuntime,
|
|
3780
|
+
loadAgentConfig: () => loadAgentConfig,
|
|
3781
|
+
saveAgentConfig: () => saveAgentConfig,
|
|
3782
|
+
setAgentRuntime: () => setAgentRuntime
|
|
3783
|
+
});
|
|
3784
|
+
import { readFileSync as readFileSync8, writeFileSync as writeFileSync7, existsSync as existsSync13 } from "fs";
|
|
3785
|
+
import path14 from "path";
|
|
3786
|
+
function loadAgentConfig() {
|
|
3787
|
+
if (!existsSync13(AGENT_CONFIG_PATH)) return {};
|
|
3788
|
+
try {
|
|
3789
|
+
return JSON.parse(readFileSync8(AGENT_CONFIG_PATH, "utf-8"));
|
|
3790
|
+
} catch {
|
|
3791
|
+
return {};
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
function saveAgentConfig(config) {
|
|
3795
|
+
const dir = path14.dirname(AGENT_CONFIG_PATH);
|
|
3796
|
+
ensurePrivateDirSync(dir);
|
|
3797
|
+
writeFileSync7(AGENT_CONFIG_PATH, JSON.stringify(config, null, 2) + "\n", "utf-8");
|
|
3798
|
+
enforcePrivateFileSync(AGENT_CONFIG_PATH);
|
|
3799
|
+
}
|
|
3800
|
+
function getAgentRuntime(agentId) {
|
|
3801
|
+
const config = loadAgentConfig();
|
|
3802
|
+
const entry = config[agentId];
|
|
3803
|
+
if (entry) return entry;
|
|
3804
|
+
const orgDefault = config["default"];
|
|
3805
|
+
if (orgDefault) return orgDefault;
|
|
3806
|
+
return { runtime: DEFAULT_RUNTIME, model: DEFAULT_MODELS[DEFAULT_RUNTIME] };
|
|
3807
|
+
}
|
|
3808
|
+
function setAgentRuntime(agentId, runtime, model, reasoning_effort) {
|
|
3809
|
+
const knownModels = KNOWN_RUNTIMES[runtime];
|
|
3810
|
+
if (!knownModels) {
|
|
3811
|
+
return {
|
|
3812
|
+
ok: false,
|
|
3813
|
+
error: `Unknown runtime "${runtime}". Valid: ${Object.keys(KNOWN_RUNTIMES).join(", ")}`
|
|
3814
|
+
};
|
|
3815
|
+
}
|
|
3816
|
+
if (!knownModels.includes(model)) {
|
|
3817
|
+
return {
|
|
3818
|
+
ok: false,
|
|
3819
|
+
error: `Unknown model "${model}" for runtime "${runtime}". Valid: ${knownModels.join(", ")}`
|
|
3820
|
+
};
|
|
3821
|
+
}
|
|
3822
|
+
const config = loadAgentConfig();
|
|
3823
|
+
const entry = { runtime, model };
|
|
3824
|
+
if (reasoning_effort) entry.reasoning_effort = reasoning_effort;
|
|
3825
|
+
config[agentId] = entry;
|
|
3826
|
+
saveAgentConfig(config);
|
|
3827
|
+
return { ok: true };
|
|
3828
|
+
}
|
|
3829
|
+
function clearAgentRuntime(agentId) {
|
|
3830
|
+
const config = loadAgentConfig();
|
|
3831
|
+
delete config[agentId];
|
|
3832
|
+
saveAgentConfig(config);
|
|
3833
|
+
}
|
|
3834
|
+
var AGENT_CONFIG_PATH, KNOWN_RUNTIMES, RUNTIME_LABELS, DEFAULT_MODELS;
|
|
3835
|
+
var init_agent_config = __esm({
|
|
3836
|
+
"src/lib/agent-config.ts"() {
|
|
3837
|
+
"use strict";
|
|
3838
|
+
init_config();
|
|
3839
|
+
init_runtime_table();
|
|
3840
|
+
init_secure_files();
|
|
3841
|
+
AGENT_CONFIG_PATH = path14.join(EXE_AI_DIR, "agent-config.json");
|
|
3842
|
+
KNOWN_RUNTIMES = {
|
|
3843
|
+
claude: ["claude-opus-4.6", "claude-opus-4", "claude-sonnet-4.6", "claude-sonnet-4", "claude-haiku-4.5"],
|
|
3844
|
+
codex: ["gpt-5.4", "gpt-5.5", "gpt-5.3-codex-spark", "o3", "o4-mini"],
|
|
3845
|
+
opencode: ["anthropic/claude-sonnet-4-6", "openai/gpt-5.4", "google/gemini-2.5-pro", "deepseek/deepseek-r3", "minimax/minimax-m2.5"]
|
|
3846
|
+
};
|
|
3847
|
+
RUNTIME_LABELS = {
|
|
3848
|
+
claude: "Claude Code (Anthropic)",
|
|
3849
|
+
codex: "Codex (OpenAI)",
|
|
3850
|
+
opencode: "OpenCode (open source)"
|
|
3851
|
+
};
|
|
3852
|
+
DEFAULT_MODELS = {
|
|
3853
|
+
claude: "claude-opus-4.6",
|
|
3854
|
+
codex: RUNTIME_TABLE.codex?.defaultModel ?? "gpt-5.4",
|
|
3855
|
+
opencode: RUNTIME_TABLE.opencode?.defaultModel ?? "anthropic/claude-sonnet-4-6"
|
|
3856
|
+
};
|
|
3857
|
+
}
|
|
3858
|
+
});
|
|
3859
|
+
|
|
3717
3860
|
// src/bin/exe-start-codex.ts
|
|
3718
3861
|
import os11 from "os";
|
|
3719
|
-
import
|
|
3862
|
+
import path15 from "path";
|
|
3720
3863
|
import {
|
|
3721
|
-
existsSync as
|
|
3722
|
-
readFileSync as
|
|
3723
|
-
writeFileSync as
|
|
3864
|
+
existsSync as existsSync14,
|
|
3865
|
+
readFileSync as readFileSync9,
|
|
3866
|
+
writeFileSync as writeFileSync8,
|
|
3724
3867
|
mkdirSync as mkdirSync7,
|
|
3725
3868
|
readdirSync as readdirSync4
|
|
3726
3869
|
} from "fs";
|
|
@@ -4038,19 +4181,32 @@ async function flushBatch() {
|
|
|
4038
4181
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4039
4182
|
if (isShardingEnabled2()) {
|
|
4040
4183
|
const byProject = /* @__PURE__ */ new Map();
|
|
4184
|
+
let skippedUnknown = 0;
|
|
4041
4185
|
for (const row of batch) {
|
|
4042
|
-
const proj = row.project_name
|
|
4186
|
+
const proj = row.project_name?.trim();
|
|
4187
|
+
if (!proj) {
|
|
4188
|
+
skippedUnknown++;
|
|
4189
|
+
continue;
|
|
4190
|
+
}
|
|
4043
4191
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
4044
4192
|
byProject.get(proj).push(row);
|
|
4045
4193
|
}
|
|
4194
|
+
if (skippedUnknown > 0) {
|
|
4195
|
+
process.stderr.write(
|
|
4196
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
4197
|
+
`
|
|
4198
|
+
);
|
|
4199
|
+
}
|
|
4046
4200
|
for (const [project, rows] of byProject) {
|
|
4047
4201
|
try {
|
|
4048
4202
|
const shardClient = await getReadyShardClient2(project);
|
|
4049
4203
|
const shardStmts = rows.map(buildStmt);
|
|
4050
4204
|
await shardClient.batch(shardStmts, "write");
|
|
4051
4205
|
} catch (err) {
|
|
4206
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
4207
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
4052
4208
|
process.stderr.write(
|
|
4053
|
-
`[store] Shard write failed for ${project}
|
|
4209
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
4054
4210
|
`
|
|
4055
4211
|
);
|
|
4056
4212
|
}
|
|
@@ -4201,12 +4357,24 @@ var BOOT_INSTRUCTIONS = `
|
|
|
4201
4357
|
---
|
|
4202
4358
|
## Boot Instructions
|
|
4203
4359
|
You have access to exe-os MCP tools for persistent memory, tasks, and team coordination.
|
|
4360
|
+
MCP tools are available under the exe-os server. Call them directly by name:
|
|
4361
|
+
- list_tasks \u2014 see your assigned work
|
|
4362
|
+
- get_task \u2014 read full task context
|
|
4363
|
+
- update_task \u2014 mark tasks in_progress or done
|
|
4364
|
+
- store_memory \u2014 persist findings for future sessions
|
|
4365
|
+
- recall_my_memory \u2014 search your past work
|
|
4366
|
+
- ask_team_memory \u2014 query a colleague's knowledge
|
|
4367
|
+
|
|
4204
4368
|
On startup: call list_tasks to check for assigned work.
|
|
4205
|
-
When done with a task: call update_task with status "done".
|
|
4206
|
-
Always call store_memory to persist important
|
|
4369
|
+
When done with a task: call update_task with status "done" and a result summary.
|
|
4370
|
+
Always call store_memory to persist important decisions.
|
|
4371
|
+
|
|
4372
|
+
\u26A0 FIRST RUN: If hooks haven't been approved yet, run /hooks in Codex and approve
|
|
4373
|
+
all exe-os hooks before starting work. Without approved hooks, memory capture
|
|
4374
|
+
and session tracking won't function.
|
|
4207
4375
|
`;
|
|
4208
4376
|
function resolveAgent(argv) {
|
|
4209
|
-
const invokedAs =
|
|
4377
|
+
const invokedAs = path15.basename(argv[1] ?? "");
|
|
4210
4378
|
if (invokedAs && invokedAs !== "exe-start-codex" && !invokedAs.endsWith(".js")) {
|
|
4211
4379
|
const agent2 = invokedAs.replace(/-codex$/, "").toLowerCase();
|
|
4212
4380
|
return { agent: agent2, passthrough: argv.slice(2) };
|
|
@@ -4232,24 +4400,24 @@ function resolveAgent(argv) {
|
|
|
4232
4400
|
return { agent, passthrough, sessionName };
|
|
4233
4401
|
}
|
|
4234
4402
|
function loadIdentity(agent) {
|
|
4235
|
-
const dir =
|
|
4236
|
-
const exact =
|
|
4237
|
-
if (
|
|
4238
|
-
const content =
|
|
4403
|
+
const dir = path15.join(os11.homedir(), ".exe-os", "identity");
|
|
4404
|
+
const exact = path15.join(dir, `${agent}.md`);
|
|
4405
|
+
if (existsSync14(exact)) {
|
|
4406
|
+
const content = readFileSync9(exact, "utf-8").trim();
|
|
4239
4407
|
if (content) return content;
|
|
4240
4408
|
}
|
|
4241
4409
|
try {
|
|
4242
4410
|
const files = readdirSync4(dir);
|
|
4243
4411
|
const match = files.find((f) => f.toLowerCase() === `${agent.toLowerCase()}.md`);
|
|
4244
4412
|
if (match) {
|
|
4245
|
-
const content =
|
|
4413
|
+
const content = readFileSync9(path15.join(dir, match), "utf-8").trim();
|
|
4246
4414
|
if (content) return content;
|
|
4247
4415
|
}
|
|
4248
4416
|
} catch {
|
|
4249
4417
|
}
|
|
4250
4418
|
try {
|
|
4251
|
-
const rosterPath =
|
|
4252
|
-
const roster = JSON.parse(
|
|
4419
|
+
const rosterPath = path15.join(os11.homedir(), ".exe-os", "exe-employees.json");
|
|
4420
|
+
const roster = JSON.parse(readFileSync9(rosterPath, "utf8"));
|
|
4253
4421
|
const emp = roster.find((e) => e.name.toLowerCase() === agent.toLowerCase());
|
|
4254
4422
|
if (emp?.systemPrompt && emp.systemPrompt.trim().length > 20) {
|
|
4255
4423
|
return emp.systemPrompt;
|
|
@@ -4259,18 +4427,18 @@ function loadIdentity(agent) {
|
|
|
4259
4427
|
return null;
|
|
4260
4428
|
}
|
|
4261
4429
|
function writePromptFile(agent, identity, behaviorsPath) {
|
|
4262
|
-
const promptDir =
|
|
4430
|
+
const promptDir = path15.join(os11.homedir(), ".exe-os", "codex-prompt");
|
|
4263
4431
|
mkdirSync7(promptDir, { recursive: true });
|
|
4264
4432
|
let prompt = identity;
|
|
4265
|
-
if (behaviorsPath &&
|
|
4266
|
-
const behaviors =
|
|
4433
|
+
if (behaviorsPath && existsSync14(behaviorsPath)) {
|
|
4434
|
+
const behaviors = readFileSync9(behaviorsPath, "utf-8").trim();
|
|
4267
4435
|
if (behaviors) {
|
|
4268
4436
|
prompt += "\n\n" + behaviors;
|
|
4269
4437
|
}
|
|
4270
4438
|
}
|
|
4271
4439
|
prompt += "\n" + BOOT_INSTRUCTIONS;
|
|
4272
|
-
const outPath =
|
|
4273
|
-
|
|
4440
|
+
const outPath = path15.join(promptDir, `${agent}.md`);
|
|
4441
|
+
writeFileSync8(outPath, prompt, "utf-8");
|
|
4274
4442
|
return outPath;
|
|
4275
4443
|
}
|
|
4276
4444
|
async function main() {
|
|
@@ -4349,8 +4517,8 @@ async function main() {
|
|
|
4349
4517
|
process.env.EXE_RUNTIME = "codex";
|
|
4350
4518
|
const empRole = (() => {
|
|
4351
4519
|
try {
|
|
4352
|
-
const emps =
|
|
4353
|
-
|
|
4520
|
+
const emps = readFileSync9(
|
|
4521
|
+
path15.join(os11.homedir(), ".exe-os", "exe-employees.json"),
|
|
4354
4522
|
"utf-8"
|
|
4355
4523
|
);
|
|
4356
4524
|
const found = JSON.parse(emps).find(
|
|
@@ -4387,14 +4555,14 @@ async function main() {
|
|
|
4387
4555
|
if (WORKTREE_ROLES.has(empRole)) {
|
|
4388
4556
|
try {
|
|
4389
4557
|
const { execSync: es } = await import("child_process");
|
|
4390
|
-
const worktreeDir =
|
|
4558
|
+
const worktreeDir = path15.join(process.cwd(), ".worktrees", worktreeName);
|
|
4391
4559
|
const branchName = `${worktreeName}/codex-${Date.now()}`;
|
|
4392
|
-
if (
|
|
4560
|
+
if (existsSync14(worktreeDir)) {
|
|
4393
4561
|
worktreePath = worktreeDir;
|
|
4394
4562
|
process.stderr.write(`[exe-start-codex] Reusing worktree at ${worktreeDir}
|
|
4395
4563
|
`);
|
|
4396
4564
|
} else {
|
|
4397
|
-
mkdirSync7(
|
|
4565
|
+
mkdirSync7(path15.dirname(worktreeDir), { recursive: true });
|
|
4398
4566
|
es(`git worktree add "${worktreeDir}" -b "${branchName}" HEAD`, {
|
|
4399
4567
|
encoding: "utf-8",
|
|
4400
4568
|
timeout: 3e4
|
|
@@ -4410,7 +4578,16 @@ async function main() {
|
|
|
4410
4578
|
);
|
|
4411
4579
|
}
|
|
4412
4580
|
}
|
|
4413
|
-
|
|
4581
|
+
let configModel;
|
|
4582
|
+
let configReasoning;
|
|
4583
|
+
try {
|
|
4584
|
+
const { getAgentRuntime: getAgentRuntime2 } = (init_agent_config(), __toCommonJS(agent_config_exports));
|
|
4585
|
+
const rtConfig = getAgentRuntime2(agent);
|
|
4586
|
+
configModel = rtConfig.model;
|
|
4587
|
+
configReasoning = rtConfig.reasoning_effort;
|
|
4588
|
+
} catch {
|
|
4589
|
+
}
|
|
4590
|
+
const effectiveModel = process.env.EXE_AGENT_MODEL ?? configModel ?? CODEX.defaultModel;
|
|
4414
4591
|
const args = [
|
|
4415
4592
|
"-m",
|
|
4416
4593
|
effectiveModel,
|
|
@@ -4418,7 +4595,7 @@ async function main() {
|
|
|
4418
4595
|
CODEX.inlineFlag,
|
|
4419
4596
|
...passthrough
|
|
4420
4597
|
];
|
|
4421
|
-
const reasoningEffort = process.env.EXE_AGENT_REASONING_EFFORT;
|
|
4598
|
+
const reasoningEffort = process.env.EXE_AGENT_REASONING_EFFORT ?? configReasoning;
|
|
4422
4599
|
if (reasoningEffort) {
|
|
4423
4600
|
args.push("-c", `model_reasoning_effort="${reasoningEffort}"`);
|
|
4424
4601
|
}
|
|
@@ -4428,7 +4605,7 @@ async function main() {
|
|
|
4428
4605
|
if (promptPath) {
|
|
4429
4606
|
args.push("-c", `model_instructions_file="${promptPath}"`);
|
|
4430
4607
|
}
|
|
4431
|
-
args.push("You are an AI employee with exe-os MCP tools. DO NOT ask for confirmation \u2014 work autonomously. Immediately: 1) Call list_tasks to see your assigned tasks. 2) Call get_task on the highest priority open task. 3) Start working on it. 4) When done, call update_task with status done and a result summary. 5) Check list_tasks again for the next task. 6) If NO open tasks remain, say 'All tasks complete. Standing by.' and STOP
|
|
4608
|
+
args.push("You are an AI employee with exe-os MCP tools (list_tasks, get_task, update_task, store_memory, recall_my_memory, ask_team_memory). DO NOT ask for confirmation \u2014 work autonomously. Immediately: 1) Call list_tasks to see your assigned tasks. 2) Call get_task on the highest priority open task. 3) Start working on it. 4) When done, call update_task with status done and a result summary. 5) Check list_tasks again for the next task. 6) If NO open tasks remain, say 'All tasks complete. Standing by.' and STOP. If MCP tools are unavailable, tell the user to run 'exe-os codex' to register them.");
|
|
4432
4609
|
process.stderr.write(
|
|
4433
4610
|
`[exe-start-codex] launching ${agent} on ${CODEX.binary} (${effectiveModel}) \u2014 interactive mode
|
|
4434
4611
|
`
|
|
@@ -2607,8 +2607,8 @@ function getShardClient(projectName) {
|
|
|
2607
2607
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2608
2608
|
}
|
|
2609
2609
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2610
|
-
if (!safeName) {
|
|
2611
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
2610
|
+
if (!safeName || safeName === "unknown") {
|
|
2611
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2612
2612
|
}
|
|
2613
2613
|
const cached = _shards.get(safeName);
|
|
2614
2614
|
if (cached) {
|
|
@@ -4100,19 +4100,32 @@ async function flushBatch() {
|
|
|
4100
4100
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
4101
4101
|
if (isShardingEnabled2()) {
|
|
4102
4102
|
const byProject = /* @__PURE__ */ new Map();
|
|
4103
|
+
let skippedUnknown = 0;
|
|
4103
4104
|
for (const row of batch) {
|
|
4104
|
-
const proj = row.project_name
|
|
4105
|
+
const proj = row.project_name?.trim();
|
|
4106
|
+
if (!proj) {
|
|
4107
|
+
skippedUnknown++;
|
|
4108
|
+
continue;
|
|
4109
|
+
}
|
|
4105
4110
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
4106
4111
|
byProject.get(proj).push(row);
|
|
4107
4112
|
}
|
|
4113
|
+
if (skippedUnknown > 0) {
|
|
4114
|
+
process.stderr.write(
|
|
4115
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
4116
|
+
`
|
|
4117
|
+
);
|
|
4118
|
+
}
|
|
4108
4119
|
for (const [project, rows] of byProject) {
|
|
4109
4120
|
try {
|
|
4110
4121
|
const shardClient = await getReadyShardClient2(project);
|
|
4111
4122
|
const shardStmts = rows.map(buildStmt);
|
|
4112
4123
|
await shardClient.batch(shardStmts, "write");
|
|
4113
4124
|
} catch (err) {
|
|
4125
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
4126
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
4114
4127
|
process.stderr.write(
|
|
4115
|
-
`[store] Shard write failed for ${project}
|
|
4128
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
4116
4129
|
`
|
|
4117
4130
|
);
|
|
4118
4131
|
}
|
package/dist/bin/exe-status.js
CHANGED
|
@@ -2945,8 +2945,8 @@ function getShardClient(projectName) {
|
|
|
2945
2945
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2946
2946
|
}
|
|
2947
2947
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2948
|
-
if (!safeName) {
|
|
2949
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
2948
|
+
if (!safeName || safeName === "unknown") {
|
|
2949
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2950
2950
|
}
|
|
2951
2951
|
const cached = _shards.get(safeName);
|
|
2952
2952
|
if (cached) {
|
|
@@ -3815,19 +3815,32 @@ async function flushBatch() {
|
|
|
3815
3815
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
3816
3816
|
if (isShardingEnabled2()) {
|
|
3817
3817
|
const byProject = /* @__PURE__ */ new Map();
|
|
3818
|
+
let skippedUnknown = 0;
|
|
3818
3819
|
for (const row of batch) {
|
|
3819
|
-
const proj = row.project_name
|
|
3820
|
+
const proj = row.project_name?.trim();
|
|
3821
|
+
if (!proj) {
|
|
3822
|
+
skippedUnknown++;
|
|
3823
|
+
continue;
|
|
3824
|
+
}
|
|
3820
3825
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
3821
3826
|
byProject.get(proj).push(row);
|
|
3822
3827
|
}
|
|
3828
|
+
if (skippedUnknown > 0) {
|
|
3829
|
+
process.stderr.write(
|
|
3830
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
3831
|
+
`
|
|
3832
|
+
);
|
|
3833
|
+
}
|
|
3823
3834
|
for (const [project, rows] of byProject) {
|
|
3824
3835
|
try {
|
|
3825
3836
|
const shardClient = await getReadyShardClient2(project);
|
|
3826
3837
|
const shardStmts = rows.map(buildStmt);
|
|
3827
3838
|
await shardClient.batch(shardStmts, "write");
|
|
3828
3839
|
} catch (err) {
|
|
3840
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
3841
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
3829
3842
|
process.stderr.write(
|
|
3830
|
-
`[store] Shard write failed for ${project}
|
|
3843
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
3831
3844
|
`
|
|
3832
3845
|
);
|
|
3833
3846
|
}
|
package/dist/bin/exe-team.js
CHANGED
|
@@ -2934,8 +2934,8 @@ function getShardClient(projectName) {
|
|
|
2934
2934
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
2935
2935
|
}
|
|
2936
2936
|
const safeName = projectName.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
2937
|
-
if (!safeName) {
|
|
2938
|
-
throw new Error(`Invalid project name for shard: "${projectName}"`);
|
|
2937
|
+
if (!safeName || safeName === "unknown") {
|
|
2938
|
+
throw new Error(`Invalid project name for shard: "${projectName}" (resolved to "${safeName}")`);
|
|
2939
2939
|
}
|
|
2940
2940
|
const cached = _shards.get(safeName);
|
|
2941
2941
|
if (cached) {
|
|
@@ -3804,19 +3804,32 @@ async function flushBatch() {
|
|
|
3804
3804
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
3805
3805
|
if (isShardingEnabled2()) {
|
|
3806
3806
|
const byProject = /* @__PURE__ */ new Map();
|
|
3807
|
+
let skippedUnknown = 0;
|
|
3807
3808
|
for (const row of batch) {
|
|
3808
|
-
const proj = row.project_name
|
|
3809
|
+
const proj = row.project_name?.trim();
|
|
3810
|
+
if (!proj) {
|
|
3811
|
+
skippedUnknown++;
|
|
3812
|
+
continue;
|
|
3813
|
+
}
|
|
3809
3814
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
3810
3815
|
byProject.get(proj).push(row);
|
|
3811
3816
|
}
|
|
3817
|
+
if (skippedUnknown > 0) {
|
|
3818
|
+
process.stderr.write(
|
|
3819
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
3820
|
+
`
|
|
3821
|
+
);
|
|
3822
|
+
}
|
|
3812
3823
|
for (const [project, rows] of byProject) {
|
|
3813
3824
|
try {
|
|
3814
3825
|
const shardClient = await getReadyShardClient2(project);
|
|
3815
3826
|
const shardStmts = rows.map(buildStmt);
|
|
3816
3827
|
await shardClient.batch(shardStmts, "write");
|
|
3817
3828
|
} catch (err) {
|
|
3829
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
3830
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
3818
3831
|
process.stderr.write(
|
|
3819
|
-
`[store] Shard write failed for ${project}
|
|
3832
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
3820
3833
|
`
|
|
3821
3834
|
);
|
|
3822
3835
|
}
|
package/dist/bin/git-sweep.js
CHANGED
|
@@ -6553,8 +6553,8 @@ function getShardClient(projectName2) {
|
|
|
6553
6553
|
throw new Error("Shard manager not initialized. Call initShardManager() first.");
|
|
6554
6554
|
}
|
|
6555
6555
|
const safeName = projectName2.replace(/[^a-zA-Z0-9_-]/g, "_");
|
|
6556
|
-
if (!safeName) {
|
|
6557
|
-
throw new Error(`Invalid project name for shard: "${projectName2}"`);
|
|
6556
|
+
if (!safeName || safeName === "unknown") {
|
|
6557
|
+
throw new Error(`Invalid project name for shard: "${projectName2}" (resolved to "${safeName}")`);
|
|
6558
6558
|
}
|
|
6559
6559
|
const cached = _shards.get(safeName);
|
|
6560
6560
|
if (cached) {
|
|
@@ -7423,19 +7423,32 @@ async function flushBatch() {
|
|
|
7423
7423
|
const { isShardingEnabled: isShardingEnabled2, getReadyShardClient: getReadyShardClient2 } = await Promise.resolve().then(() => (init_shard_manager(), shard_manager_exports));
|
|
7424
7424
|
if (isShardingEnabled2()) {
|
|
7425
7425
|
const byProject = /* @__PURE__ */ new Map();
|
|
7426
|
+
let skippedUnknown = 0;
|
|
7426
7427
|
for (const row of batch) {
|
|
7427
|
-
const proj = row.project_name
|
|
7428
|
+
const proj = row.project_name?.trim();
|
|
7429
|
+
if (!proj) {
|
|
7430
|
+
skippedUnknown++;
|
|
7431
|
+
continue;
|
|
7432
|
+
}
|
|
7428
7433
|
if (!byProject.has(proj)) byProject.set(proj, []);
|
|
7429
7434
|
byProject.get(proj).push(row);
|
|
7430
7435
|
}
|
|
7436
|
+
if (skippedUnknown > 0) {
|
|
7437
|
+
process.stderr.write(
|
|
7438
|
+
`[store] Shard skip: ${skippedUnknown} record(s) with empty project_name (kept in main DB only)
|
|
7439
|
+
`
|
|
7440
|
+
);
|
|
7441
|
+
}
|
|
7431
7442
|
for (const [project, rows] of byProject) {
|
|
7432
7443
|
try {
|
|
7433
7444
|
const shardClient = await getReadyShardClient2(project);
|
|
7434
7445
|
const shardStmts = rows.map(buildStmt);
|
|
7435
7446
|
await shardClient.batch(shardStmts, "write");
|
|
7436
7447
|
} catch (err) {
|
|
7448
|
+
const fullError = err instanceof Error ? `${err.name}: ${err.message}${err.stack ? `
|
|
7449
|
+
${err.stack.split("\n").slice(1, 3).join("\n")}` : ""}` : String(err);
|
|
7437
7450
|
process.stderr.write(
|
|
7438
|
-
`[store] Shard write failed for ${project}
|
|
7451
|
+
`[store] Shard write failed for ${project} (${rows.length} records): ${fullError}
|
|
7439
7452
|
`
|
|
7440
7453
|
);
|
|
7441
7454
|
}
|