@askexenow/exe-os 0.9.111 → 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 +62 -12
- package/dist/bin/agentic-reflection-backfill.js +37 -2
- package/dist/bin/agentic-semantic-label.js +37 -2
- package/dist/bin/backfill-conversations.js +61 -11
- package/dist/bin/backfill-responses.js +62 -12
- package/dist/bin/backfill-vectors.js +37 -2
- package/dist/bin/bulk-sync-postgres.js +63 -13
- package/dist/bin/cleanup-stale-review-tasks.js +83 -16
- package/dist/bin/cli.js +312 -80
- package/dist/bin/exe-agent-config.js +7 -1
- package/dist/bin/exe-agent.js +29 -3
- package/dist/bin/exe-assign.js +62 -12
- package/dist/bin/exe-boot.js +500 -151
- package/dist/bin/exe-call.js +46 -5
- package/dist/bin/exe-cloud.js +101 -16
- package/dist/bin/exe-dispatch.js +827 -27
- package/dist/bin/exe-doctor.js +61 -11
- package/dist/bin/exe-export-behaviors.js +67 -14
- package/dist/bin/exe-forget.js +62 -12
- package/dist/bin/exe-gateway.js +147 -27
- package/dist/bin/exe-heartbeat.js +83 -16
- package/dist/bin/exe-kill.js +62 -12
- package/dist/bin/exe-launch-agent.js +83 -15
- package/dist/bin/exe-new-employee.js +176 -8
- package/dist/bin/exe-pending-messages.js +83 -16
- package/dist/bin/exe-pending-notifications.js +83 -16
- package/dist/bin/exe-pending-reviews.js +83 -16
- package/dist/bin/exe-rename.js +62 -12
- package/dist/bin/exe-review.js +62 -12
- package/dist/bin/exe-search.js +62 -12
- package/dist/bin/exe-session-cleanup.js +949 -149
- package/dist/bin/exe-settings.js +10 -4
- package/dist/bin/exe-start-codex.js +537 -248
- package/dist/bin/exe-start-opencode.js +547 -168
- package/dist/bin/exe-status.js +83 -16
- package/dist/bin/exe-support.js +1 -1
- package/dist/bin/exe-team.js +62 -12
- package/dist/bin/git-sweep.js +827 -27
- package/dist/bin/graph-backfill.js +62 -12
- package/dist/bin/graph-export.js +62 -12
- package/dist/bin/install.js +62 -4
- package/dist/bin/intercom-check.js +949 -149
- package/dist/bin/pre-publish.js +14 -2
- package/dist/bin/scan-tasks.js +827 -27
- package/dist/bin/setup.js +99 -14
- package/dist/bin/shard-migrate.js +62 -12
- package/dist/bin/stack-update.js +1 -1
- package/dist/bin/update.js +3 -3
- package/dist/gateway/index.js +586 -26
- package/dist/hooks/bug-report-worker.js +586 -26
- package/dist/hooks/codex-stop-task-finalizer.js +977 -143
- package/dist/hooks/commit-complete.js +827 -27
- package/dist/hooks/error-recall.js +62 -12
- package/dist/hooks/ingest.js +4579 -249
- package/dist/hooks/instructions-loaded.js +62 -12
- package/dist/hooks/notification.js +62 -12
- package/dist/hooks/post-compact.js +83 -16
- package/dist/hooks/post-tool-combined.js +83 -16
- package/dist/hooks/pre-compact.js +907 -107
- package/dist/hooks/pre-tool-use.js +98 -16
- package/dist/hooks/prompt-submit.js +596 -30
- package/dist/hooks/session-end.js +909 -112
- package/dist/hooks/session-start.js +112 -17
- package/dist/hooks/stop.js +82 -15
- package/dist/hooks/subagent-stop.js +83 -16
- package/dist/hooks/summary-worker.js +81 -8
- package/dist/index.js +595 -29
- package/dist/lib/agent-config.js +16 -1
- package/dist/lib/cloud-sync.js +45 -1
- package/dist/lib/consolidation.js +16 -1
- package/dist/lib/database.js +23 -0
- package/dist/lib/db.js +23 -0
- package/dist/lib/device-registry.js +23 -0
- package/dist/lib/employee-templates.js +30 -4
- package/dist/lib/employees.js +16 -1
- package/dist/lib/exe-daemon.js +482 -52
- package/dist/lib/hybrid-search.js +62 -12
- package/dist/lib/license.js +3 -3
- package/dist/lib/messaging.js +21 -4
- package/dist/lib/schedules.js +37 -2
- package/dist/lib/skill-learning.js +910 -41
- package/dist/lib/status-brief.js +14 -1
- package/dist/lib/store.js +62 -12
- package/dist/lib/tasks.js +843 -93
- package/dist/lib/tmux-routing.js +766 -16
- package/dist/mcp/server.js +238 -41
- package/dist/mcp/tools/create-task.js +525 -15
- 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 +840 -93
- package/dist/runtime/index.js +913 -107
- package/dist/tui/App.js +227 -58
- package/package.json +1 -1
|
@@ -1951,6 +1951,13 @@ async function ensureSchema() {
|
|
|
1951
1951
|
} catch (e) {
|
|
1952
1952
|
logCatchDebug("migration", e);
|
|
1953
1953
|
}
|
|
1954
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
1955
|
+
try {
|
|
1956
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
1957
|
+
} catch (e) {
|
|
1958
|
+
logCatchDebug("migration", e);
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1954
1961
|
try {
|
|
1955
1962
|
await client.execute({
|
|
1956
1963
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3167,6 +3174,22 @@ async function ensureSchema() {
|
|
|
3167
3174
|
} catch (e) {
|
|
3168
3175
|
logCatchDebug("migration", e);
|
|
3169
3176
|
}
|
|
3177
|
+
try {
|
|
3178
|
+
await client.execute({
|
|
3179
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3180
|
+
args: []
|
|
3181
|
+
});
|
|
3182
|
+
} catch (e) {
|
|
3183
|
+
logCatchDebug("migration", e);
|
|
3184
|
+
}
|
|
3185
|
+
try {
|
|
3186
|
+
await client.execute({
|
|
3187
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3188
|
+
args: []
|
|
3189
|
+
});
|
|
3190
|
+
} catch (e) {
|
|
3191
|
+
logCatchDebug("migration", e);
|
|
3192
|
+
}
|
|
3170
3193
|
}
|
|
3171
3194
|
async function disposeDatabase() {
|
|
3172
3195
|
if (_walCheckpointTimer) {
|
|
@@ -3733,11 +3756,17 @@ var init_platform_procedures = __esm({
|
|
|
3733
3756
|
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."
|
|
3734
3757
|
},
|
|
3735
3758
|
{
|
|
3736
|
-
title: "
|
|
3759
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
3737
3760
|
domain: "workflow",
|
|
3738
3761
|
priority: "p1",
|
|
3739
3762
|
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."
|
|
3740
3763
|
},
|
|
3764
|
+
{
|
|
3765
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
3766
|
+
domain: "identity",
|
|
3767
|
+
priority: "p0",
|
|
3768
|
+
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."
|
|
3769
|
+
},
|
|
3741
3770
|
{
|
|
3742
3771
|
title: "Single dispatch path \u2014 create_task only",
|
|
3743
3772
|
domain: "workflow",
|
|
@@ -3771,6 +3800,12 @@ var init_platform_procedures = __esm({
|
|
|
3771
3800
|
priority: "p0",
|
|
3772
3801
|
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."
|
|
3773
3802
|
},
|
|
3803
|
+
{
|
|
3804
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
3805
|
+
domain: "security",
|
|
3806
|
+
priority: "p0",
|
|
3807
|
+
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."
|
|
3808
|
+
},
|
|
3774
3809
|
{
|
|
3775
3810
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
3776
3811
|
domain: "support",
|
|
@@ -3922,7 +3957,7 @@ var init_platform_procedures = __esm({
|
|
|
3922
3957
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
3923
3958
|
domain: "tool-use",
|
|
3924
3959
|
priority: "p0",
|
|
3925
|
-
content: 'exe-os MCP tools
|
|
3960
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
3926
3961
|
},
|
|
3927
3962
|
{
|
|
3928
3963
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -4056,10 +4091,24 @@ function stableId(memoryId, type, content) {
|
|
|
4056
4091
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
4057
4092
|
}
|
|
4058
4093
|
function cleanText(text) {
|
|
4059
|
-
|
|
4060
|
-
|
|
4061
|
-
|
|
4062
|
-
|
|
4094
|
+
let cleaned = text.replace(
|
|
4095
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
4096
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
4097
|
+
);
|
|
4098
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
4099
|
+
return cleaned;
|
|
4100
|
+
}
|
|
4101
|
+
function splitSegments(text) {
|
|
4102
|
+
const cleaned = cleanText(text);
|
|
4103
|
+
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);
|
|
4104
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4105
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
4106
|
+
if (lines.length > 0) return lines;
|
|
4107
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4108
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
4109
|
+
}
|
|
4110
|
+
}
|
|
4111
|
+
return segments;
|
|
4063
4112
|
}
|
|
4064
4113
|
function inferCardType(sentence, toolName) {
|
|
4065
4114
|
const lower = sentence.toLowerCase();
|
|
@@ -4091,12 +4140,12 @@ function predicateFor(type) {
|
|
|
4091
4140
|
}
|
|
4092
4141
|
}
|
|
4093
4142
|
function extractMemoryCards(row) {
|
|
4094
|
-
const
|
|
4143
|
+
const segments = splitSegments(row.raw_text);
|
|
4095
4144
|
const cards = [];
|
|
4096
|
-
for (const sentence of
|
|
4145
|
+
for (const sentence of segments) {
|
|
4097
4146
|
const type = inferCardType(sentence, row.tool_name);
|
|
4098
4147
|
const subject = extractSubject(sentence, row.agent_id);
|
|
4099
|
-
const content = sentence.length >
|
|
4148
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
4100
4149
|
cards.push({
|
|
4101
4150
|
id: stableId(row.id, type, content),
|
|
4102
4151
|
memory_id: row.id,
|
|
@@ -4192,13 +4241,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
4192
4241
|
last_accessed: String(row.timestamp)
|
|
4193
4242
|
}));
|
|
4194
4243
|
}
|
|
4195
|
-
var MAX_CARDS_PER_MEMORY,
|
|
4244
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
4196
4245
|
var init_memory_cards = __esm({
|
|
4197
4246
|
"src/lib/memory-cards.ts"() {
|
|
4198
4247
|
"use strict";
|
|
4199
4248
|
init_database();
|
|
4200
|
-
MAX_CARDS_PER_MEMORY =
|
|
4201
|
-
|
|
4249
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
4250
|
+
MAX_SEGMENT_CHARS = 500;
|
|
4251
|
+
MIN_SEGMENT_CHARS = 20;
|
|
4202
4252
|
}
|
|
4203
4253
|
});
|
|
4204
4254
|
|
|
@@ -1947,6 +1947,13 @@ async function ensureSchema() {
|
|
|
1947
1947
|
} catch (e) {
|
|
1948
1948
|
logCatchDebug("migration", e);
|
|
1949
1949
|
}
|
|
1950
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
1951
|
+
try {
|
|
1952
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
1953
|
+
} catch (e) {
|
|
1954
|
+
logCatchDebug("migration", e);
|
|
1955
|
+
}
|
|
1956
|
+
}
|
|
1950
1957
|
try {
|
|
1951
1958
|
await client.execute({
|
|
1952
1959
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3163,6 +3170,22 @@ async function ensureSchema() {
|
|
|
3163
3170
|
} catch (e) {
|
|
3164
3171
|
logCatchDebug("migration", e);
|
|
3165
3172
|
}
|
|
3173
|
+
try {
|
|
3174
|
+
await client.execute({
|
|
3175
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3176
|
+
args: []
|
|
3177
|
+
});
|
|
3178
|
+
} catch (e) {
|
|
3179
|
+
logCatchDebug("migration", e);
|
|
3180
|
+
}
|
|
3181
|
+
try {
|
|
3182
|
+
await client.execute({
|
|
3183
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3184
|
+
args: []
|
|
3185
|
+
});
|
|
3186
|
+
} catch (e) {
|
|
3187
|
+
logCatchDebug("migration", e);
|
|
3188
|
+
}
|
|
3166
3189
|
}
|
|
3167
3190
|
async function disposeDatabase() {
|
|
3168
3191
|
if (_walCheckpointTimer) {
|
|
@@ -3729,11 +3752,17 @@ var init_platform_procedures = __esm({
|
|
|
3729
3752
|
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."
|
|
3730
3753
|
},
|
|
3731
3754
|
{
|
|
3732
|
-
title: "
|
|
3755
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
3733
3756
|
domain: "workflow",
|
|
3734
3757
|
priority: "p1",
|
|
3735
3758
|
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."
|
|
3736
3759
|
},
|
|
3760
|
+
{
|
|
3761
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
3762
|
+
domain: "identity",
|
|
3763
|
+
priority: "p0",
|
|
3764
|
+
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."
|
|
3765
|
+
},
|
|
3737
3766
|
{
|
|
3738
3767
|
title: "Single dispatch path \u2014 create_task only",
|
|
3739
3768
|
domain: "workflow",
|
|
@@ -3767,6 +3796,12 @@ var init_platform_procedures = __esm({
|
|
|
3767
3796
|
priority: "p0",
|
|
3768
3797
|
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."
|
|
3769
3798
|
},
|
|
3799
|
+
{
|
|
3800
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
3801
|
+
domain: "security",
|
|
3802
|
+
priority: "p0",
|
|
3803
|
+
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."
|
|
3804
|
+
},
|
|
3770
3805
|
{
|
|
3771
3806
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
3772
3807
|
domain: "support",
|
|
@@ -3918,7 +3953,7 @@ var init_platform_procedures = __esm({
|
|
|
3918
3953
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
3919
3954
|
domain: "tool-use",
|
|
3920
3955
|
priority: "p0",
|
|
3921
|
-
content: 'exe-os MCP tools
|
|
3956
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
3922
3957
|
},
|
|
3923
3958
|
{
|
|
3924
3959
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -1811,6 +1811,13 @@ async function ensureSchema() {
|
|
|
1811
1811
|
} catch (e) {
|
|
1812
1812
|
logCatchDebug("migration", e);
|
|
1813
1813
|
}
|
|
1814
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
1815
|
+
try {
|
|
1816
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
1817
|
+
} catch (e) {
|
|
1818
|
+
logCatchDebug("migration", e);
|
|
1819
|
+
}
|
|
1820
|
+
}
|
|
1814
1821
|
try {
|
|
1815
1822
|
await client.execute({
|
|
1816
1823
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3027,6 +3034,22 @@ async function ensureSchema() {
|
|
|
3027
3034
|
} catch (e) {
|
|
3028
3035
|
logCatchDebug("migration", e);
|
|
3029
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
|
+
}
|
|
3030
3053
|
}
|
|
3031
3054
|
async function disposeDatabase() {
|
|
3032
3055
|
if (_walCheckpointTimer) {
|
|
@@ -3901,11 +3924,17 @@ var init_platform_procedures = __esm({
|
|
|
3901
3924
|
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."
|
|
3902
3925
|
},
|
|
3903
3926
|
{
|
|
3904
|
-
title: "
|
|
3927
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
3905
3928
|
domain: "workflow",
|
|
3906
3929
|
priority: "p1",
|
|
3907
3930
|
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."
|
|
3908
3931
|
},
|
|
3932
|
+
{
|
|
3933
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
3934
|
+
domain: "identity",
|
|
3935
|
+
priority: "p0",
|
|
3936
|
+
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."
|
|
3937
|
+
},
|
|
3909
3938
|
{
|
|
3910
3939
|
title: "Single dispatch path \u2014 create_task only",
|
|
3911
3940
|
domain: "workflow",
|
|
@@ -3939,6 +3968,12 @@ var init_platform_procedures = __esm({
|
|
|
3939
3968
|
priority: "p0",
|
|
3940
3969
|
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."
|
|
3941
3970
|
},
|
|
3971
|
+
{
|
|
3972
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
3973
|
+
domain: "security",
|
|
3974
|
+
priority: "p0",
|
|
3975
|
+
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."
|
|
3976
|
+
},
|
|
3942
3977
|
{
|
|
3943
3978
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
3944
3979
|
domain: "support",
|
|
@@ -4090,7 +4125,7 @@ var init_platform_procedures = __esm({
|
|
|
4090
4125
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
4091
4126
|
domain: "tool-use",
|
|
4092
4127
|
priority: "p0",
|
|
4093
|
-
content: 'exe-os MCP tools
|
|
4128
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
4094
4129
|
},
|
|
4095
4130
|
{
|
|
4096
4131
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -4224,10 +4259,24 @@ function stableId(memoryId, type, content) {
|
|
|
4224
4259
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
4225
4260
|
}
|
|
4226
4261
|
function cleanText(text) {
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
4230
|
-
|
|
4262
|
+
let cleaned = text.replace(
|
|
4263
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
4264
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
4265
|
+
);
|
|
4266
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
4267
|
+
return cleaned;
|
|
4268
|
+
}
|
|
4269
|
+
function splitSegments(text) {
|
|
4270
|
+
const cleaned = cleanText(text);
|
|
4271
|
+
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);
|
|
4272
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4273
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
4274
|
+
if (lines.length > 0) return lines;
|
|
4275
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4276
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
4277
|
+
}
|
|
4278
|
+
}
|
|
4279
|
+
return segments;
|
|
4231
4280
|
}
|
|
4232
4281
|
function inferCardType(sentence, toolName) {
|
|
4233
4282
|
const lower = sentence.toLowerCase();
|
|
@@ -4259,12 +4308,12 @@ function predicateFor(type) {
|
|
|
4259
4308
|
}
|
|
4260
4309
|
}
|
|
4261
4310
|
function extractMemoryCards(row) {
|
|
4262
|
-
const
|
|
4311
|
+
const segments = splitSegments(row.raw_text);
|
|
4263
4312
|
const cards = [];
|
|
4264
|
-
for (const sentence of
|
|
4313
|
+
for (const sentence of segments) {
|
|
4265
4314
|
const type = inferCardType(sentence, row.tool_name);
|
|
4266
4315
|
const subject = extractSubject(sentence, row.agent_id);
|
|
4267
|
-
const content = sentence.length >
|
|
4316
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
4268
4317
|
cards.push({
|
|
4269
4318
|
id: stableId(row.id, type, content),
|
|
4270
4319
|
memory_id: row.id,
|
|
@@ -4360,13 +4409,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
4360
4409
|
last_accessed: String(row.timestamp)
|
|
4361
4410
|
}));
|
|
4362
4411
|
}
|
|
4363
|
-
var MAX_CARDS_PER_MEMORY,
|
|
4412
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
4364
4413
|
var init_memory_cards = __esm({
|
|
4365
4414
|
"src/lib/memory-cards.ts"() {
|
|
4366
4415
|
"use strict";
|
|
4367
4416
|
init_database();
|
|
4368
|
-
MAX_CARDS_PER_MEMORY =
|
|
4369
|
-
|
|
4417
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
4418
|
+
MAX_SEGMENT_CHARS = 500;
|
|
4419
|
+
MIN_SEGMENT_CHARS = 20;
|
|
4370
4420
|
}
|
|
4371
4421
|
});
|
|
4372
4422
|
|
|
@@ -5120,7 +5170,7 @@ import { jwtVerify, importSPKI } from "jose";
|
|
|
5120
5170
|
var LICENSE_PATH = path8.join(EXE_AI_DIR, "license.key");
|
|
5121
5171
|
var CACHE_PATH = path8.join(EXE_AI_DIR, "license-cache.json");
|
|
5122
5172
|
var DEVICE_ID_PATH = path8.join(EXE_AI_DIR, "device-id");
|
|
5123
|
-
var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
5173
|
+
var API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
5124
5174
|
|
|
5125
5175
|
// src/lib/cloud-sync.ts
|
|
5126
5176
|
init_config();
|
|
@@ -2037,6 +2037,13 @@ async function ensureSchema() {
|
|
|
2037
2037
|
} catch (e) {
|
|
2038
2038
|
logCatchDebug("migration", e);
|
|
2039
2039
|
}
|
|
2040
|
+
for (const col of ["created_by_agent TEXT", "created_by_device TEXT", "source_session_id TEXT"]) {
|
|
2041
|
+
try {
|
|
2042
|
+
await client.execute({ sql: `ALTER TABLE behaviors ADD COLUMN ${col}`, args: [] });
|
|
2043
|
+
} catch (e) {
|
|
2044
|
+
logCatchDebug("migration", e);
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2040
2047
|
try {
|
|
2041
2048
|
await client.execute({
|
|
2042
2049
|
sql: `ALTER TABLE tasks ADD COLUMN blocked_by TEXT`,
|
|
@@ -3253,6 +3260,22 @@ async function ensureSchema() {
|
|
|
3253
3260
|
} catch (e) {
|
|
3254
3261
|
logCatchDebug("migration", e);
|
|
3255
3262
|
}
|
|
3263
|
+
try {
|
|
3264
|
+
await client.execute({
|
|
3265
|
+
sql: `ALTER TABLE memories ADD COLUMN visibility TEXT DEFAULT 'private'`,
|
|
3266
|
+
args: []
|
|
3267
|
+
});
|
|
3268
|
+
} catch (e) {
|
|
3269
|
+
logCatchDebug("migration", e);
|
|
3270
|
+
}
|
|
3271
|
+
try {
|
|
3272
|
+
await client.execute({
|
|
3273
|
+
sql: `ALTER TABLE memories ADD COLUMN strength REAL DEFAULT 1.0`,
|
|
3274
|
+
args: []
|
|
3275
|
+
});
|
|
3276
|
+
} catch (e) {
|
|
3277
|
+
logCatchDebug("migration", e);
|
|
3278
|
+
}
|
|
3256
3279
|
}
|
|
3257
3280
|
async function disposeDatabase() {
|
|
3258
3281
|
if (_walCheckpointTimer) {
|
|
@@ -4376,11 +4399,17 @@ var init_platform_procedures = __esm({
|
|
|
4376
4399
|
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."
|
|
4377
4400
|
},
|
|
4378
4401
|
{
|
|
4379
|
-
title: "
|
|
4402
|
+
title: "Orchestration phase guidance \u2014 recommend, never trap",
|
|
4380
4403
|
domain: "workflow",
|
|
4381
4404
|
priority: "p1",
|
|
4382
4405
|
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."
|
|
4383
4406
|
},
|
|
4407
|
+
{
|
|
4408
|
+
title: "Routing slot vs display title \u2014 internal 'coo' is plumbing, not your name",
|
|
4409
|
+
domain: "identity",
|
|
4410
|
+
priority: "p0",
|
|
4411
|
+
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."
|
|
4412
|
+
},
|
|
4384
4413
|
{
|
|
4385
4414
|
title: "Single dispatch path \u2014 create_task only",
|
|
4386
4415
|
domain: "workflow",
|
|
@@ -4414,6 +4443,12 @@ var init_platform_procedures = __esm({
|
|
|
4414
4443
|
priority: "p0",
|
|
4415
4444
|
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."
|
|
4416
4445
|
},
|
|
4446
|
+
{
|
|
4447
|
+
title: "Destructive operations \u2014 mandatory reviewer gate",
|
|
4448
|
+
domain: "security",
|
|
4449
|
+
priority: "p0",
|
|
4450
|
+
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."
|
|
4451
|
+
},
|
|
4417
4452
|
{
|
|
4418
4453
|
title: "Customer patch triage \u2014 upstream bug vs customization",
|
|
4419
4454
|
domain: "support",
|
|
@@ -4565,7 +4600,7 @@ var init_platform_procedures = __esm({
|
|
|
4565
4600
|
title: "MCP tool dispatch \u2014 all tools use action parameter",
|
|
4566
4601
|
domain: "tool-use",
|
|
4567
4602
|
priority: "p0",
|
|
4568
|
-
content: 'exe-os MCP tools
|
|
4603
|
+
content: 'exe-os MCP tools use consolidated action-based dispatch by default (19 tools). Call domain tools with an action parameter: memory(action="recall"), task(action="create"), config(action="list_employees"), etc. Legacy mode (108 separate tools like recall_my_memory, create_task) is still available via EXE_MCP_TOOL_SURFACE=legacy but will be removed in a future version. If you see specific tool names, call them directly \u2014 both surfaces are identical. Consolidated is the default and recommended surface.'
|
|
4569
4604
|
},
|
|
4570
4605
|
{
|
|
4571
4606
|
title: "MCP tools \u2014 memory, decision, and search",
|
|
@@ -4699,10 +4734,24 @@ function stableId(memoryId, type, content) {
|
|
|
4699
4734
|
return createHash2("sha256").update(`${memoryId}:${type}:${content}`).digest("hex").slice(0, 32);
|
|
4700
4735
|
}
|
|
4701
4736
|
function cleanText(text) {
|
|
4702
|
-
|
|
4703
|
-
|
|
4704
|
-
|
|
4705
|
-
|
|
4737
|
+
let cleaned = text.replace(
|
|
4738
|
+
/```(\w*)\n(.*?)(?:\n[\s\S]*?)```/g,
|
|
4739
|
+
(_m, lang, firstLine) => `[code${lang ? `:${lang}` : ""}] ${firstLine.trim()}`
|
|
4740
|
+
);
|
|
4741
|
+
cleaned = cleaned.replace(/<[^>]+>/g, " ").replace(/\s+/g, " ").trim();
|
|
4742
|
+
return cleaned;
|
|
4743
|
+
}
|
|
4744
|
+
function splitSegments(text) {
|
|
4745
|
+
const cleaned = cleanText(text);
|
|
4746
|
+
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);
|
|
4747
|
+
if (segments.length === 0 && cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4748
|
+
const lines = cleaned.split(/\n+/).map((l) => l.trim()).filter((l) => l.length >= MIN_SEGMENT_CHARS && l.length <= MAX_SEGMENT_CHARS);
|
|
4749
|
+
if (lines.length > 0) return lines;
|
|
4750
|
+
if (cleaned.length >= MIN_SEGMENT_CHARS) {
|
|
4751
|
+
return [cleaned.slice(0, MAX_SEGMENT_CHARS)];
|
|
4752
|
+
}
|
|
4753
|
+
}
|
|
4754
|
+
return segments;
|
|
4706
4755
|
}
|
|
4707
4756
|
function inferCardType(sentence, toolName) {
|
|
4708
4757
|
const lower = sentence.toLowerCase();
|
|
@@ -4734,12 +4783,12 @@ function predicateFor(type) {
|
|
|
4734
4783
|
}
|
|
4735
4784
|
}
|
|
4736
4785
|
function extractMemoryCards(row) {
|
|
4737
|
-
const
|
|
4786
|
+
const segments = splitSegments(row.raw_text);
|
|
4738
4787
|
const cards = [];
|
|
4739
|
-
for (const sentence of
|
|
4788
|
+
for (const sentence of segments) {
|
|
4740
4789
|
const type = inferCardType(sentence, row.tool_name);
|
|
4741
4790
|
const subject = extractSubject(sentence, row.agent_id);
|
|
4742
|
-
const content = sentence.length >
|
|
4791
|
+
const content = sentence.length > MAX_SEGMENT_CHARS ? `${sentence.slice(0, MAX_SEGMENT_CHARS - 1)}\u2026` : sentence;
|
|
4743
4792
|
cards.push({
|
|
4744
4793
|
id: stableId(row.id, type, content),
|
|
4745
4794
|
memory_id: row.id,
|
|
@@ -4835,13 +4884,14 @@ Source memory: ${String(row.source_ref ?? row.memory_id)}`,
|
|
|
4835
4884
|
last_accessed: String(row.timestamp)
|
|
4836
4885
|
}));
|
|
4837
4886
|
}
|
|
4838
|
-
var MAX_CARDS_PER_MEMORY,
|
|
4887
|
+
var MAX_CARDS_PER_MEMORY, MAX_SEGMENT_CHARS, MIN_SEGMENT_CHARS;
|
|
4839
4888
|
var init_memory_cards = __esm({
|
|
4840
4889
|
"src/lib/memory-cards.ts"() {
|
|
4841
4890
|
"use strict";
|
|
4842
4891
|
init_database();
|
|
4843
|
-
MAX_CARDS_PER_MEMORY =
|
|
4844
|
-
|
|
4892
|
+
MAX_CARDS_PER_MEMORY = 8;
|
|
4893
|
+
MAX_SEGMENT_CHARS = 500;
|
|
4894
|
+
MIN_SEGMENT_CHARS = 20;
|
|
4845
4895
|
}
|
|
4846
4896
|
});
|
|
4847
4897
|
|
|
@@ -6076,7 +6126,7 @@ var init_license = __esm({
|
|
|
6076
6126
|
LICENSE_PATH = path11.join(EXE_AI_DIR, "license.key");
|
|
6077
6127
|
CACHE_PATH = path11.join(EXE_AI_DIR, "license-cache.json");
|
|
6078
6128
|
DEVICE_ID_PATH = path11.join(EXE_AI_DIR, "device-id");
|
|
6079
|
-
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://askexe.com
|
|
6129
|
+
API_BASE = process.env.EXE_CLOUD_ENDPOINT ?? "https://cloud.askexe.com";
|
|
6080
6130
|
}
|
|
6081
6131
|
});
|
|
6082
6132
|
|
|
@@ -6129,6 +6179,18 @@ function extractRootExe(name) {
|
|
|
6129
6179
|
const parts = name.split("-").filter(Boolean);
|
|
6130
6180
|
return parts.length > 0 ? parts[parts.length - 1] : null;
|
|
6131
6181
|
}
|
|
6182
|
+
function registerParentExe(sessionKey, parentExe, dispatchedBy) {
|
|
6183
|
+
if (!existsSync14(SESSION_CACHE)) {
|
|
6184
|
+
mkdirSync7(SESSION_CACHE, { recursive: true });
|
|
6185
|
+
}
|
|
6186
|
+
const rootExe = extractRootExe(parentExe) ?? parentExe;
|
|
6187
|
+
const filePath = path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`);
|
|
6188
|
+
writeFileSync6(filePath, JSON.stringify({
|
|
6189
|
+
parentExe: rootExe,
|
|
6190
|
+
dispatchedBy: dispatchedBy || rootExe,
|
|
6191
|
+
registeredAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
6192
|
+
}));
|
|
6193
|
+
}
|
|
6132
6194
|
function getParentExe(sessionKey) {
|
|
6133
6195
|
try {
|
|
6134
6196
|
const data = JSON.parse(readFileSync9(path14.join(SESSION_CACHE, `parent-exe-${sessionKey}.json`), "utf8"));
|
|
@@ -6138,11 +6200,12 @@ function getParentExe(sessionKey) {
|
|
|
6138
6200
|
}
|
|
6139
6201
|
}
|
|
6140
6202
|
function resolveExeSession() {
|
|
6203
|
+
if (process.env.EXE_SESSION_NAME) {
|
|
6204
|
+
const fromEnv = extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
6205
|
+
if (fromEnv) return fromEnv;
|
|
6206
|
+
}
|
|
6141
6207
|
const mySession = getMySession();
|
|
6142
6208
|
if (!mySession) {
|
|
6143
|
-
if (process.env.EXE_SESSION_NAME) {
|
|
6144
|
-
return extractRootExe(process.env.EXE_SESSION_NAME) ?? process.env.EXE_SESSION_NAME;
|
|
6145
|
-
}
|
|
6146
6209
|
return null;
|
|
6147
6210
|
}
|
|
6148
6211
|
const fromSessionName = extractRootExe(mySession);
|
|
@@ -6157,6 +6220,10 @@ function resolveExeSession() {
|
|
|
6157
6220
|
`[tmux-routing] WARN: cache says "${fromCache}" but session name says "${fromSessionName}". Trusting session name.
|
|
6158
6221
|
`
|
|
6159
6222
|
);
|
|
6223
|
+
try {
|
|
6224
|
+
registerParentExe(key, fromSessionName);
|
|
6225
|
+
} catch {
|
|
6226
|
+
}
|
|
6160
6227
|
candidate = fromSessionName;
|
|
6161
6228
|
} else {
|
|
6162
6229
|
candidate = fromCache;
|