@askexenow/exe-os 0.9.2 → 0.9.3

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/cli.js CHANGED
@@ -1322,20 +1322,39 @@ function setupGhostty(home) {
1322
1322
  const configPath = path5.join(configDir, "config");
1323
1323
  const backupPath = path5.join(configDir, "config.backup");
1324
1324
  mkdirSync3(configDir, { recursive: true });
1325
+ const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1326
+ const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1327
+ const assetContent = readFileSync4(assetPath, "utf8").trim();
1328
+ const markedSection = `${START_MARKER}
1329
+ ${assetContent}
1330
+ ${END_MARKER}`;
1325
1331
  if (existsSync5(configPath)) {
1326
1332
  const existing = readFileSync4(configPath, "utf8");
1327
- if (existing.includes("Exe OS")) {
1328
- copyFileSync(assetPath, configPath);
1333
+ if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1334
+ const before = existing.slice(0, existing.indexOf(START_MARKER));
1335
+ const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1336
+ writeFileSync3(configPath, `${before}${markedSection}${after}`);
1337
+ } else if (existing.includes("Exe OS")) {
1338
+ if (!existsSync5(backupPath)) {
1339
+ copyFileSync(configPath, backupPath);
1340
+ process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1341
+ `);
1342
+ }
1343
+ writeFileSync3(configPath, `${markedSection}
1344
+ `);
1329
1345
  } else {
1330
1346
  if (!existsSync5(backupPath)) {
1331
1347
  copyFileSync(configPath, backupPath);
1332
1348
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1333
1349
  `);
1334
1350
  }
1335
- copyFileSync(assetPath, configPath);
1351
+ writeFileSync3(configPath, `${markedSection}
1352
+
1353
+ ${existing}`);
1336
1354
  }
1337
1355
  } else {
1338
- copyFileSync(assetPath, configPath);
1356
+ writeFileSync3(configPath, `${markedSection}
1357
+ `);
1339
1358
  }
1340
1359
  process.stderr.write("exe-os: Ghostty config installed\n");
1341
1360
  }
@@ -1735,20 +1735,39 @@ function setupGhostty(home) {
1735
1735
  const configPath = path9.join(configDir, "config");
1736
1736
  const backupPath = path9.join(configDir, "config.backup");
1737
1737
  mkdirSync6(configDir, { recursive: true });
1738
+ const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1739
+ const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1740
+ const assetContent = readFileSync8(assetPath, "utf8").trim();
1741
+ const markedSection = `${START_MARKER}
1742
+ ${assetContent}
1743
+ ${END_MARKER}`;
1738
1744
  if (existsSync9(configPath)) {
1739
1745
  const existing = readFileSync8(configPath, "utf8");
1740
- if (existing.includes("Exe OS")) {
1741
- copyFileSync(assetPath, configPath);
1746
+ if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1747
+ const before = existing.slice(0, existing.indexOf(START_MARKER));
1748
+ const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1749
+ writeFileSync6(configPath, `${before}${markedSection}${after}`);
1750
+ } else if (existing.includes("Exe OS")) {
1751
+ if (!existsSync9(backupPath)) {
1752
+ copyFileSync(configPath, backupPath);
1753
+ process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1754
+ `);
1755
+ }
1756
+ writeFileSync6(configPath, `${markedSection}
1757
+ `);
1742
1758
  } else {
1743
1759
  if (!existsSync9(backupPath)) {
1744
1760
  copyFileSync(configPath, backupPath);
1745
1761
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1746
1762
  `);
1747
1763
  }
1748
- copyFileSync(assetPath, configPath);
1764
+ writeFileSync6(configPath, `${markedSection}
1765
+
1766
+ ${existing}`);
1749
1767
  }
1750
1768
  } else {
1751
- copyFileSync(assetPath, configPath);
1769
+ writeFileSync6(configPath, `${markedSection}
1770
+ `);
1752
1771
  }
1753
1772
  process.stderr.write("exe-os: Ghostty config installed\n");
1754
1773
  }
@@ -1123,20 +1123,39 @@ function setupGhostty(home) {
1123
1123
  const configPath = path5.join(configDir, "config");
1124
1124
  const backupPath = path5.join(configDir, "config.backup");
1125
1125
  mkdirSync3(configDir, { recursive: true });
1126
+ const START_MARKER = "# \u2500\u2500 exe-os:ghostty-start \u2500\u2500";
1127
+ const END_MARKER = "# \u2500\u2500 exe-os:ghostty-end \u2500\u2500";
1128
+ const assetContent = readFileSync4(assetPath, "utf8").trim();
1129
+ const markedSection = `${START_MARKER}
1130
+ ${assetContent}
1131
+ ${END_MARKER}`;
1126
1132
  if (existsSync5(configPath)) {
1127
1133
  const existing = readFileSync4(configPath, "utf8");
1128
- if (existing.includes("Exe OS")) {
1129
- copyFileSync(assetPath, configPath);
1134
+ if (existing.includes(START_MARKER) && existing.includes(END_MARKER)) {
1135
+ const before = existing.slice(0, existing.indexOf(START_MARKER));
1136
+ const after = existing.slice(existing.indexOf(END_MARKER) + END_MARKER.length);
1137
+ writeFileSync3(configPath, `${before}${markedSection}${after}`);
1138
+ } else if (existing.includes("Exe OS")) {
1139
+ if (!existsSync5(backupPath)) {
1140
+ copyFileSync(configPath, backupPath);
1141
+ process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1142
+ `);
1143
+ }
1144
+ writeFileSync3(configPath, `${markedSection}
1145
+ `);
1130
1146
  } else {
1131
1147
  if (!existsSync5(backupPath)) {
1132
1148
  copyFileSync(configPath, backupPath);
1133
1149
  process.stderr.write(`exe-os: backed up existing Ghostty config to ${backupPath}
1134
1150
  `);
1135
1151
  }
1136
- copyFileSync(assetPath, configPath);
1152
+ writeFileSync3(configPath, `${markedSection}
1153
+
1154
+ ${existing}`);
1137
1155
  }
1138
1156
  } else {
1139
- copyFileSync(assetPath, configPath);
1157
+ writeFileSync3(configPath, `${markedSection}
1158
+ `);
1140
1159
  }
1141
1160
  process.stderr.write("exe-os: Ghostty config installed\n");
1142
1161
  }
@@ -15240,17 +15240,20 @@ async function insertProcedures(procedures, timestamp, options) {
15240
15240
  }
15241
15241
  async function replaceBehaviorsAndProcedures(behaviors, procedures, timestamp) {
15242
15242
  const client = getClient();
15243
- await client.execute({
15244
- sql: "UPDATE behaviors SET active = 0, updated_at = ? WHERE active = 1",
15245
- args: [timestamp]
15246
- });
15247
- await client.execute({
15248
- sql: "UPDATE global_procedures SET active = 0, updated_at = ? WHERE active = 1",
15249
- args: [timestamp]
15243
+ const existingBehaviors = await client.execute({
15244
+ sql: "SELECT agent_id, content FROM behaviors WHERE active = 1",
15245
+ args: []
15250
15246
  });
15247
+ const existingBehaviorKeys = new Set(
15248
+ existingBehaviors.rows.map((row) => `${String(row.agent_id)}::${String(row.content)}`)
15249
+ );
15250
+ const newBehaviors = behaviors.filter(
15251
+ (b) => !existingBehaviorKeys.has(`${b.agent_id}::${b.content}`)
15252
+ );
15253
+ const existingProcedureTitles = await getActiveProcedureTitles();
15251
15254
  return {
15252
- behaviors: await insertBehaviors(behaviors, timestamp),
15253
- procedures: await insertProcedures(procedures, timestamp)
15255
+ behaviors: await insertBehaviors(newBehaviors, timestamp),
15256
+ procedures: await insertProcedures(procedures, timestamp, { skipTitles: existingProcedureTitles })
15254
15257
  };
15255
15258
  }
15256
15259
  async function mergeRosterEntries(importedRoster, timestamp) {
@@ -15286,10 +15289,16 @@ async function replaceRosterEntries(importedRoster, timestamp) {
15286
15289
  }
15287
15290
  async function importIdentities(identities, updatedBy) {
15288
15291
  const entries = Object.entries(identities);
15292
+ let imported = 0;
15289
15293
  for (const [agentId, content] of entries) {
15294
+ const existing = getIdentity(agentId);
15295
+ if (existing?.raw) {
15296
+ continue;
15297
+ }
15290
15298
  await updateIdentity(agentId, content, updatedBy);
15299
+ imported += 1;
15291
15300
  }
15292
- return entries.length;
15301
+ return imported;
15293
15302
  }
15294
15303
  async function getActiveProcedureTitles() {
15295
15304
  const client = getClient();
@@ -15458,19 +15467,32 @@ function registerExportOrchestration(server2) {
15458
15467
  import { readFileSync as readFileSync19 } from "fs";
15459
15468
  import { z as z39 } from "zod";
15460
15469
  init_store();
15470
+ init_active_agent();
15471
+ init_employees();
15461
15472
  function registerImportOrchestration(server2) {
15462
15473
  server2.registerTool(
15463
15474
  "import_orchestration",
15464
15475
  {
15465
15476
  title: "Import Orchestration",
15466
- description: "Import roster, identities, behaviors, and procedures from an orchestration package.",
15477
+ description: "Import roster, identities, behaviors, and procedures from an orchestration package. Restricted to coordinator/founder.",
15467
15478
  inputSchema: {
15468
15479
  package_path: z39.string().describe("Path to the orchestration package JSON file"),
15469
- merge_strategy: z39.enum(["replace", "merge"]).default("merge").describe("How to apply the package: replace existing data or merge additively")
15480
+ merge_strategy: z39.enum(["replace", "merge"]).default("merge").describe("How to apply the package: both strategies are additive-only \u2014 existing data is never deleted or overwritten")
15470
15481
  }
15471
15482
  },
15472
15483
  async ({ package_path, merge_strategy }) => {
15473
15484
  try {
15485
+ const caller = getActiveAgent();
15486
+ const allowed = canCoordinate(caller.agentId, caller.agentRole);
15487
+ if (!allowed) {
15488
+ return {
15489
+ content: [{
15490
+ type: "text",
15491
+ text: `Permission denied. Only the coordinator or founder sessions can import orchestration packages. You are "${caller.agentId}".`
15492
+ }],
15493
+ isError: true
15494
+ };
15495
+ }
15474
15496
  await initStore();
15475
15497
  const raw = readFileSync19(package_path, "utf-8");
15476
15498
  const pkg = validatePackage(JSON.parse(raw));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@askexenow/exe-os",
3
- "version": "0.9.2",
3
+ "version": "0.9.3",
4
4
  "description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
5
5
  "license": "CC-BY-NC-4.0",
6
6
  "type": "module",