Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ anchor: function watch
created: 2026-10-15T04:19:48Z
norm: '1'
sig: 01895e7ff9a47d37
body_hash: d05a924e14300999
raw_hash: 37b2264443de0c14
vouched: 2026-10-19T20:58:11Z
body_hash: fe03a4474929e917
raw_hash: c6d495788240ddb4
vouched: 2026-10-21T21:55:17Z
lines: 89-149
---

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
---
id: 01M5G7C4TB4NT55C348DMACCAP
anchor: function remember
created: 2026-10-21T21:55:13Z
norm: '1'
sig: 4f21369e4fee9b0a
body_hash: 4e1d54af62a2f1f5
raw_hash: 2f8b64877de51afc
lines: 49-54
---

only a directory.json naming the synced URL records services; ACE_DIRECTORY alone must not create the file
41 changes: 29 additions & 12 deletions apps/host/src/directory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,38 @@ type Host = { name: string; login: string; github?: string; address?: string; se

const config = join(catalog.home, "directory.json");

/** `app`, `hosted`, and `compute` are the team's web app and services, set where the directory is deployed. */
type Services = { app?: string; hosted?: string; compute?: string };
type Known = Services & { hosts: Host[]; channels: Listing[]; shares: Share[] };

/** The joined directory's URL and the services it last named. */
type Saved = Services & { url: string };

function saved(): Saved | undefined {
if (existsSync(config)) return JSON.parse(readFileSync(config, "utf8"));
}

export function url(): string | undefined {
if (process.env.ACE_DIRECTORY) return process.env.ACE_DIRECTORY;
if (existsSync(config)) return JSON.parse(readFileSync(config, "utf8")).url;
return process.env.ACE_DIRECTORY || saved()?.url;
}

/** `app`, `hosted`, and `compute` are the team's web app and services, set where the directory is deployed. */
type Known = {
hosts: Host[];
channels: Listing[];
shares: Share[];
app?: string;
hosted?: string;
compute?: string;
};
/** The services survive a restart so cloud options don't wait for the first sync, or vanish offline. */
function remembered(): Known {
const value = saved();
const base = { hosts: [], channels: [], shares: [] };
if (!value || value.url !== url()) return base;
return { ...base, app: value.app, hosted: value.hosted, compute: value.compute };
}

/** Only the joined directory's file records its services; ACE_DIRECTORY alone writes nothing. */
function remember(base: string, { app, hosted, compute }: Services) {
const value = saved();
if (value?.url !== base) return;
if (value.app === app && value.hosted === hosted && value.compute === compute) return;
writeFileSync(config, JSON.stringify({ url: base, app, hosted, compute }));
}

let known: Known = { hosts: [], channels: [], shares: [] };
let known: Known = remembered();
let synced: number | undefined;
/** The last sync's failure, kept until a sync succeeds so Settings can say what is wrong and since when. */
let error: string | undefined;
Expand Down Expand Up @@ -203,6 +219,7 @@ export function watch({ self, channels, changed, published, covered }: Options)
// Directories deployed before project access keep no shares.
answer.shares ||= [];
known = answer;
remember(base, answer);
synced = Date.now();
error = undefined;
failed = undefined;
Expand Down
2 changes: 1 addition & 1 deletion docs/data.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ it. pi-durable owns the database format, messages, runs, tool results, chats, an
| A checkout's development build | `~/.local/state/ace-dev-<hash>/channels/<id>/` |
| Opened projects | `<ACE_HOME>/projects.json` |
| Preferences on macOS | `~/Library/Application Support/Ace/settings.json` |
| Team directory URL | `<ACE_HOME>/directory.json` |
| Team directory URL and services | `<ACE_HOME>/directory.json` |
| Provider credentials and `ACE_SECRET` | OS Keychain; never in channel metadata or preferences |

`ACE_HOME` overrides the host data directory. Canary and development preferences have the same
Expand Down