@askexenow/exe-os 0.9.99 → 0.9.101
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/agentic-ontology-backfill.js +6 -0
- package/dist/bin/agentic-reflection-backfill.js +6 -0
- package/dist/bin/agentic-semantic-label.js +6 -0
- package/dist/bin/backfill-conversations.js +6 -0
- package/dist/bin/backfill-responses.js +6 -0
- package/dist/bin/backfill-vectors.js +6 -0
- package/dist/bin/bulk-sync-postgres.js +6 -0
- package/dist/bin/cleanup-stale-review-tasks.js +6 -0
- package/dist/bin/cli.js +35 -10
- package/dist/bin/exe-agent.js +6 -0
- package/dist/bin/exe-assign.js +6 -0
- package/dist/bin/exe-boot.js +35 -10
- package/dist/bin/exe-call.js +6 -0
- package/dist/bin/exe-cloud.js +35 -10
- package/dist/bin/exe-dispatch.js +6 -0
- package/dist/bin/exe-doctor.js +35 -10
- package/dist/bin/exe-export-behaviors.js +6 -0
- package/dist/bin/exe-forget.js +6 -0
- package/dist/bin/exe-gateway.js +6 -0
- package/dist/bin/exe-heartbeat.js +6 -0
- package/dist/bin/exe-kill.js +6 -0
- package/dist/bin/exe-launch-agent.js +6 -0
- package/dist/bin/exe-new-employee.js +6 -0
- package/dist/bin/exe-pending-messages.js +6 -0
- package/dist/bin/exe-pending-notifications.js +6 -0
- package/dist/bin/exe-pending-reviews.js +6 -0
- package/dist/bin/exe-rename.js +6 -0
- package/dist/bin/exe-review.js +6 -0
- package/dist/bin/exe-search.js +6 -0
- package/dist/bin/exe-session-cleanup.js +6 -0
- package/dist/bin/exe-start-codex.js +6 -0
- package/dist/bin/exe-start-opencode.js +6 -0
- package/dist/bin/exe-status.js +6 -0
- package/dist/bin/exe-team.js +6 -0
- package/dist/bin/git-sweep.js +6 -0
- package/dist/bin/graph-backfill.js +6 -0
- package/dist/bin/graph-export.js +6 -0
- package/dist/bin/intercom-check.js +6 -0
- package/dist/bin/scan-tasks.js +6 -0
- package/dist/bin/setup.js +35 -10
- package/dist/bin/shard-migrate.js +6 -0
- package/dist/gateway/index.js +6 -0
- package/dist/hooks/bug-report-worker.js +6 -0
- package/dist/hooks/codex-stop-task-finalizer.js +6 -0
- package/dist/hooks/commit-complete.js +6 -0
- package/dist/hooks/error-recall.js +6 -0
- package/dist/hooks/ingest.js +6 -0
- package/dist/hooks/instructions-loaded.js +6 -0
- package/dist/hooks/notification.js +6 -0
- package/dist/hooks/post-compact.js +6 -0
- package/dist/hooks/post-tool-combined.js +6 -0
- package/dist/hooks/pre-compact.js +6 -0
- package/dist/hooks/pre-tool-use.js +6 -0
- package/dist/hooks/prompt-submit.js +6 -0
- package/dist/hooks/session-end.js +6 -0
- package/dist/hooks/session-start.js +6 -0
- package/dist/hooks/stop.js +6 -0
- package/dist/hooks/subagent-stop.js +6 -0
- package/dist/hooks/summary-worker.js +35 -10
- package/dist/index.js +6 -0
- package/dist/lib/cloud-sync.js +29 -10
- package/dist/lib/employee-templates.js +6 -0
- package/dist/lib/exe-daemon.js +35 -10
- package/dist/lib/hybrid-search.js +6 -0
- package/dist/lib/keychain.js +29 -10
- package/dist/lib/schedules.js +6 -0
- package/dist/lib/store.js +6 -0
- package/dist/mcp/server.js +35 -10
- package/dist/runtime/index.js +6 -0
- package/dist/tui/App.js +35 -10
- package/package.json +1 -1
- package/src/commands/exe/setup.md +1 -1
|
@@ -3587,20 +3587,39 @@ async function getKeyStorageInfo() {
|
|
|
3587
3587
|
}
|
|
3588
3588
|
async function setMasterKey(key) {
|
|
3589
3589
|
const b64 = key.toString("base64");
|
|
3590
|
-
|
|
3591
|
-
|
|
3590
|
+
let keychainOk = false;
|
|
3591
|
+
if (macKeychainSet(b64)) {
|
|
3592
|
+
const readBack = macKeychainGet();
|
|
3593
|
+
if (readBack === b64) {
|
|
3594
|
+
keychainOk = true;
|
|
3595
|
+
} else {
|
|
3596
|
+
process.stderr.write(
|
|
3597
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
3598
|
+
);
|
|
3599
|
+
}
|
|
3600
|
+
} else if (linuxSecretSet(b64)) {
|
|
3601
|
+
const readBack = linuxSecretGet();
|
|
3602
|
+
if (readBack === b64) {
|
|
3603
|
+
keychainOk = true;
|
|
3604
|
+
} else {
|
|
3605
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
3606
|
+
}
|
|
3592
3607
|
}
|
|
3593
|
-
|
|
3594
|
-
|
|
3595
|
-
|
|
3596
|
-
|
|
3597
|
-
|
|
3598
|
-
|
|
3608
|
+
if (!keychainOk) {
|
|
3609
|
+
const keytar = await tryKeytar();
|
|
3610
|
+
if (keytar) {
|
|
3611
|
+
try {
|
|
3612
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
3613
|
+
keychainOk = true;
|
|
3614
|
+
} catch {
|
|
3615
|
+
}
|
|
3599
3616
|
}
|
|
3600
3617
|
}
|
|
3601
3618
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
3602
|
-
if (
|
|
3603
|
-
process.stderr.write("[keychain] Key stored
|
|
3619
|
+
if (keychainOk) {
|
|
3620
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
3621
|
+
} else if (fallback === "encrypted") {
|
|
3622
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
3604
3623
|
} else {
|
|
3605
3624
|
process.stderr.write(
|
|
3606
3625
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -4341,6 +4360,12 @@ var init_platform_procedures = __esm({
|
|
|
4341
4360
|
priority: "p0",
|
|
4342
4361
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
4343
4362
|
},
|
|
4363
|
+
{
|
|
4364
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
4365
|
+
domain: "architecture",
|
|
4366
|
+
priority: "p1",
|
|
4367
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
4368
|
+
},
|
|
4344
4369
|
// --- MCP is the ONLY data interface ---
|
|
4345
4370
|
{
|
|
4346
4371
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/index.js
CHANGED
|
@@ -8410,6 +8410,12 @@ var init_platform_procedures = __esm({
|
|
|
8410
8410
|
priority: "p0",
|
|
8411
8411
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
8412
8412
|
},
|
|
8413
|
+
{
|
|
8414
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
8415
|
+
domain: "architecture",
|
|
8416
|
+
priority: "p1",
|
|
8417
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
8418
|
+
},
|
|
8413
8419
|
// --- MCP is the ONLY data interface ---
|
|
8414
8420
|
{
|
|
8415
8421
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/cloud-sync.js
CHANGED
|
@@ -3480,20 +3480,39 @@ async function getKeyStorageInfo() {
|
|
|
3480
3480
|
}
|
|
3481
3481
|
async function setMasterKey(key) {
|
|
3482
3482
|
const b64 = key.toString("base64");
|
|
3483
|
-
|
|
3484
|
-
|
|
3483
|
+
let keychainOk = false;
|
|
3484
|
+
if (macKeychainSet(b64)) {
|
|
3485
|
+
const readBack = macKeychainGet();
|
|
3486
|
+
if (readBack === b64) {
|
|
3487
|
+
keychainOk = true;
|
|
3488
|
+
} else {
|
|
3489
|
+
process.stderr.write(
|
|
3490
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
3491
|
+
);
|
|
3492
|
+
}
|
|
3493
|
+
} else if (linuxSecretSet(b64)) {
|
|
3494
|
+
const readBack = linuxSecretGet();
|
|
3495
|
+
if (readBack === b64) {
|
|
3496
|
+
keychainOk = true;
|
|
3497
|
+
} else {
|
|
3498
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
3499
|
+
}
|
|
3485
3500
|
}
|
|
3486
|
-
|
|
3487
|
-
|
|
3488
|
-
|
|
3489
|
-
|
|
3490
|
-
|
|
3491
|
-
|
|
3501
|
+
if (!keychainOk) {
|
|
3502
|
+
const keytar = await tryKeytar();
|
|
3503
|
+
if (keytar) {
|
|
3504
|
+
try {
|
|
3505
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
3506
|
+
keychainOk = true;
|
|
3507
|
+
} catch {
|
|
3508
|
+
}
|
|
3492
3509
|
}
|
|
3493
3510
|
}
|
|
3494
3511
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
3495
|
-
if (
|
|
3496
|
-
process.stderr.write("[keychain] Key stored
|
|
3512
|
+
if (keychainOk) {
|
|
3513
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
3514
|
+
} else if (fallback === "encrypted") {
|
|
3515
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
3497
3516
|
} else {
|
|
3498
3517
|
process.stderr.write(
|
|
3499
3518
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -344,6 +344,12 @@ var PLATFORM_PROCEDURES = [
|
|
|
344
344
|
priority: "p0",
|
|
345
345
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
346
346
|
},
|
|
347
|
+
{
|
|
348
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
349
|
+
domain: "architecture",
|
|
350
|
+
priority: "p1",
|
|
351
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
352
|
+
},
|
|
347
353
|
// --- MCP is the ONLY data interface ---
|
|
348
354
|
{
|
|
349
355
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/exe-daemon.js
CHANGED
|
@@ -5637,20 +5637,39 @@ async function getKeyStorageInfo() {
|
|
|
5637
5637
|
}
|
|
5638
5638
|
async function setMasterKey(key) {
|
|
5639
5639
|
const b64 = key.toString("base64");
|
|
5640
|
-
|
|
5641
|
-
|
|
5640
|
+
let keychainOk = false;
|
|
5641
|
+
if (macKeychainSet(b64)) {
|
|
5642
|
+
const readBack = macKeychainGet();
|
|
5643
|
+
if (readBack === b64) {
|
|
5644
|
+
keychainOk = true;
|
|
5645
|
+
} else {
|
|
5646
|
+
process.stderr.write(
|
|
5647
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
5648
|
+
);
|
|
5649
|
+
}
|
|
5650
|
+
} else if (linuxSecretSet(b64)) {
|
|
5651
|
+
const readBack = linuxSecretGet();
|
|
5652
|
+
if (readBack === b64) {
|
|
5653
|
+
keychainOk = true;
|
|
5654
|
+
} else {
|
|
5655
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
5656
|
+
}
|
|
5642
5657
|
}
|
|
5643
|
-
|
|
5644
|
-
|
|
5645
|
-
|
|
5646
|
-
|
|
5647
|
-
|
|
5648
|
-
|
|
5658
|
+
if (!keychainOk) {
|
|
5659
|
+
const keytar = await tryKeytar();
|
|
5660
|
+
if (keytar) {
|
|
5661
|
+
try {
|
|
5662
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
5663
|
+
keychainOk = true;
|
|
5664
|
+
} catch {
|
|
5665
|
+
}
|
|
5649
5666
|
}
|
|
5650
5667
|
}
|
|
5651
5668
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
5652
|
-
if (
|
|
5653
|
-
process.stderr.write("[keychain] Key stored
|
|
5669
|
+
if (keychainOk) {
|
|
5670
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
5671
|
+
} else if (fallback === "encrypted") {
|
|
5672
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
5654
5673
|
} else {
|
|
5655
5674
|
process.stderr.write(
|
|
5656
5675
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -5976,6 +5995,12 @@ var init_platform_procedures = __esm({
|
|
|
5976
5995
|
priority: "p0",
|
|
5977
5996
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
5978
5997
|
},
|
|
5998
|
+
{
|
|
5999
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
6000
|
+
domain: "architecture",
|
|
6001
|
+
priority: "p1",
|
|
6002
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
6003
|
+
},
|
|
5979
6004
|
// --- MCP is the ONLY data interface ---
|
|
5980
6005
|
{
|
|
5981
6006
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
|
@@ -4293,6 +4293,12 @@ var init_platform_procedures = __esm({
|
|
|
4293
4293
|
priority: "p0",
|
|
4294
4294
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
4295
4295
|
},
|
|
4296
|
+
{
|
|
4297
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
4298
|
+
domain: "architecture",
|
|
4299
|
+
priority: "p1",
|
|
4300
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
4301
|
+
},
|
|
4296
4302
|
// --- MCP is the ONLY data interface ---
|
|
4297
4303
|
{
|
|
4298
4304
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/keychain.js
CHANGED
|
@@ -399,20 +399,39 @@ async function getKeyStorageInfo() {
|
|
|
399
399
|
}
|
|
400
400
|
async function setMasterKey(key) {
|
|
401
401
|
const b64 = key.toString("base64");
|
|
402
|
-
|
|
403
|
-
|
|
402
|
+
let keychainOk = false;
|
|
403
|
+
if (macKeychainSet(b64)) {
|
|
404
|
+
const readBack = macKeychainGet();
|
|
405
|
+
if (readBack === b64) {
|
|
406
|
+
keychainOk = true;
|
|
407
|
+
} else {
|
|
408
|
+
process.stderr.write(
|
|
409
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
410
|
+
);
|
|
411
|
+
}
|
|
412
|
+
} else if (linuxSecretSet(b64)) {
|
|
413
|
+
const readBack = linuxSecretGet();
|
|
414
|
+
if (readBack === b64) {
|
|
415
|
+
keychainOk = true;
|
|
416
|
+
} else {
|
|
417
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
418
|
+
}
|
|
404
419
|
}
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
420
|
+
if (!keychainOk) {
|
|
421
|
+
const keytar = await tryKeytar();
|
|
422
|
+
if (keytar) {
|
|
423
|
+
try {
|
|
424
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
425
|
+
keychainOk = true;
|
|
426
|
+
} catch {
|
|
427
|
+
}
|
|
411
428
|
}
|
|
412
429
|
}
|
|
413
430
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
414
|
-
if (
|
|
415
|
-
process.stderr.write("[keychain] Key stored
|
|
431
|
+
if (keychainOk) {
|
|
432
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
433
|
+
} else if (fallback === "encrypted") {
|
|
434
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
416
435
|
} else {
|
|
417
436
|
process.stderr.write(
|
|
418
437
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
package/dist/lib/schedules.js
CHANGED
|
@@ -3522,6 +3522,12 @@ var init_platform_procedures = __esm({
|
|
|
3522
3522
|
priority: "p0",
|
|
3523
3523
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
3524
3524
|
},
|
|
3525
|
+
{
|
|
3526
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
3527
|
+
domain: "architecture",
|
|
3528
|
+
priority: "p1",
|
|
3529
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
3530
|
+
},
|
|
3525
3531
|
// --- MCP is the ONLY data interface ---
|
|
3526
3532
|
{
|
|
3527
3533
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/lib/store.js
CHANGED
|
@@ -3522,6 +3522,12 @@ var init_platform_procedures = __esm({
|
|
|
3522
3522
|
priority: "p0",
|
|
3523
3523
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
3524
3524
|
},
|
|
3525
|
+
{
|
|
3526
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
3527
|
+
domain: "architecture",
|
|
3528
|
+
priority: "p1",
|
|
3529
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
3530
|
+
},
|
|
3525
3531
|
// --- MCP is the ONLY data interface ---
|
|
3526
3532
|
{
|
|
3527
3533
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/mcp/server.js
CHANGED
|
@@ -3994,20 +3994,39 @@ async function getKeyStorageInfo() {
|
|
|
3994
3994
|
}
|
|
3995
3995
|
async function setMasterKey(key) {
|
|
3996
3996
|
const b64 = key.toString("base64");
|
|
3997
|
-
|
|
3998
|
-
|
|
3997
|
+
let keychainOk = false;
|
|
3998
|
+
if (macKeychainSet(b64)) {
|
|
3999
|
+
const readBack = macKeychainGet();
|
|
4000
|
+
if (readBack === b64) {
|
|
4001
|
+
keychainOk = true;
|
|
4002
|
+
} else {
|
|
4003
|
+
process.stderr.write(
|
|
4004
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
4005
|
+
);
|
|
4006
|
+
}
|
|
4007
|
+
} else if (linuxSecretSet(b64)) {
|
|
4008
|
+
const readBack = linuxSecretGet();
|
|
4009
|
+
if (readBack === b64) {
|
|
4010
|
+
keychainOk = true;
|
|
4011
|
+
} else {
|
|
4012
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
4013
|
+
}
|
|
3999
4014
|
}
|
|
4000
|
-
|
|
4001
|
-
|
|
4002
|
-
|
|
4003
|
-
|
|
4004
|
-
|
|
4005
|
-
|
|
4015
|
+
if (!keychainOk) {
|
|
4016
|
+
const keytar = await tryKeytar();
|
|
4017
|
+
if (keytar) {
|
|
4018
|
+
try {
|
|
4019
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
4020
|
+
keychainOk = true;
|
|
4021
|
+
} catch {
|
|
4022
|
+
}
|
|
4006
4023
|
}
|
|
4007
4024
|
}
|
|
4008
4025
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
4009
|
-
if (
|
|
4010
|
-
process.stderr.write("[keychain] Key stored
|
|
4026
|
+
if (keychainOk) {
|
|
4027
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
4028
|
+
} else if (fallback === "encrypted") {
|
|
4029
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
4011
4030
|
} else {
|
|
4012
4031
|
process.stderr.write(
|
|
4013
4032
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
|
@@ -4942,6 +4961,12 @@ var init_platform_procedures = __esm({
|
|
|
4942
4961
|
priority: "p0",
|
|
4943
4962
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
4944
4963
|
},
|
|
4964
|
+
{
|
|
4965
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
4966
|
+
domain: "architecture",
|
|
4967
|
+
priority: "p1",
|
|
4968
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
4969
|
+
},
|
|
4945
4970
|
// --- MCP is the ONLY data interface ---
|
|
4946
4971
|
{
|
|
4947
4972
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/runtime/index.js
CHANGED
|
@@ -8170,6 +8170,12 @@ var init_platform_procedures = __esm({
|
|
|
8170
8170
|
priority: "p0",
|
|
8171
8171
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
8172
8172
|
},
|
|
8173
|
+
{
|
|
8174
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
8175
|
+
domain: "architecture",
|
|
8176
|
+
priority: "p1",
|
|
8177
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
8178
|
+
},
|
|
8173
8179
|
// --- MCP is the ONLY data interface ---
|
|
8174
8180
|
{
|
|
8175
8181
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
package/dist/tui/App.js
CHANGED
|
@@ -9141,6 +9141,12 @@ var init_platform_procedures = __esm({
|
|
|
9141
9141
|
priority: "p0",
|
|
9142
9142
|
content: "The master encryption key is stored in macOS Keychain (Secure Enclave) or Linux secret-tool \u2014 NOT as a file. There is no ~/.exe-os/master.key on modern installs. If an older install had one, it was auto-migrated to Keychain and the file deleted. Device linking uses a 24-word BIP39 recovery phrase: Device 1 runs `exe-os cloud link --show-full` in their local Terminal to reveal it, Device 2 runs `exe-os cloud` and pastes the phrase to import the key into its own Keychain, then cloud sync pulls encrypted memories. NEVER display, log, or return the recovery phrase in agent output. MCP tools are hardened \u2014 they cannot reveal it. If the user needs the phrase, tell them: 'Run exe-os cloud link --show-full in your Terminal.' If searching for master.key returns nothing, that is CORRECT \u2014 the key is in Keychain."
|
|
9143
9143
|
},
|
|
9144
|
+
{
|
|
9145
|
+
title: "Cloud endpoint is cloud.askexe.com \u2014 not askexe.com/cloud",
|
|
9146
|
+
domain: "architecture",
|
|
9147
|
+
priority: "p1",
|
|
9148
|
+
content: "All cloud API calls (auth, sync, licensing, device registry, WebSocket) go to https://cloud.askexe.com, NOT https://askexe.com/cloud. This is a Cloudflare Workers Custom Domain that bypasses the zone-level managed challenge on askexe.com. Datacenter IPs (Hetzner, AWS, etc.) get HTTP 403 on askexe.com due to Bot Fight Mode, but cloud.askexe.com routes directly to the Worker before WAF rules evaluate. If a customer reports 403/challenge errors on cloud sync: verify they are on the latest exe-os version (cloud.askexe.com endpoint). Fix: `npm install -g @askexenow/exe-os@latest`. The EXE_CLOUD_ENDPOINT env var can override the endpoint if needed."
|
|
9149
|
+
},
|
|
9144
9150
|
// --- MCP is the ONLY data interface ---
|
|
9145
9151
|
{
|
|
9146
9152
|
title: "MCP disconnect \u2014 ask the user, never work around it",
|
|
@@ -11333,20 +11339,39 @@ async function getKeyStorageInfo() {
|
|
|
11333
11339
|
}
|
|
11334
11340
|
async function setMasterKey(key) {
|
|
11335
11341
|
const b64 = key.toString("base64");
|
|
11336
|
-
|
|
11337
|
-
|
|
11342
|
+
let keychainOk = false;
|
|
11343
|
+
if (macKeychainSet(b64)) {
|
|
11344
|
+
const readBack = macKeychainGet();
|
|
11345
|
+
if (readBack === b64) {
|
|
11346
|
+
keychainOk = true;
|
|
11347
|
+
} else {
|
|
11348
|
+
process.stderr.write(
|
|
11349
|
+
"[keychain] macOS Keychain write appeared to succeed but read-back failed.\n This can happen on macOS Tahoe with new permission patterns.\n"
|
|
11350
|
+
);
|
|
11351
|
+
}
|
|
11352
|
+
} else if (linuxSecretSet(b64)) {
|
|
11353
|
+
const readBack = linuxSecretGet();
|
|
11354
|
+
if (readBack === b64) {
|
|
11355
|
+
keychainOk = true;
|
|
11356
|
+
} else {
|
|
11357
|
+
process.stderr.write("[keychain] Linux secret-tool write appeared to succeed but read-back failed.\n");
|
|
11358
|
+
}
|
|
11338
11359
|
}
|
|
11339
|
-
|
|
11340
|
-
|
|
11341
|
-
|
|
11342
|
-
|
|
11343
|
-
|
|
11344
|
-
|
|
11360
|
+
if (!keychainOk) {
|
|
11361
|
+
const keytar = await tryKeytar();
|
|
11362
|
+
if (keytar) {
|
|
11363
|
+
try {
|
|
11364
|
+
await keytar.setPassword(SERVICE, ACCOUNT, b64);
|
|
11365
|
+
keychainOk = true;
|
|
11366
|
+
} catch {
|
|
11367
|
+
}
|
|
11345
11368
|
}
|
|
11346
11369
|
}
|
|
11347
11370
|
const fallback = await writeMachineBoundFileFallback(b64);
|
|
11348
|
-
if (
|
|
11349
|
-
process.stderr.write("[keychain] Key stored
|
|
11371
|
+
if (keychainOk) {
|
|
11372
|
+
process.stderr.write("[keychain] Key stored in OS keychain (file backup also written).\n");
|
|
11373
|
+
} else if (fallback === "encrypted") {
|
|
11374
|
+
process.stderr.write("[keychain] Key stored encrypted (machine-bound file fallback).\n");
|
|
11350
11375
|
} else {
|
|
11351
11376
|
process.stderr.write(
|
|
11352
11377
|
"[keychain] WARNING: Key stored in plaintext file \u2014 no OS keychain available.\n"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@askexenow/exe-os",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.101",
|
|
4
4
|
"description": "AI employee operating system — persistent memory, task management, and multi-agent coordination for Claude Code.",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE",
|
|
6
6
|
"type": "module",
|
|
@@ -68,7 +68,7 @@ Use AskUserQuestion to ask for their Exe Cloud API key (exe_sk_...).
|
|
|
68
68
|
|
|
69
69
|
Validate the key:
|
|
70
70
|
```bash
|
|
71
|
-
curl -s "https://askexe.com/
|
|
71
|
+
curl -s "https://cloud.askexe.com/auth/verify" \
|
|
72
72
|
-H "Authorization: Bearer USER_API_KEY" | cat
|
|
73
73
|
```
|
|
74
74
|
|