Skip to content

Add a silent namespaced extension bus#69

Open
KieranBond wants to merge 11 commits into
nicobailon:mainfrom
KieranBond:feat/extension-bus
Open

Add a silent namespaced extension bus#69
KieranBond wants to merge 11 commits into
nicobailon:mainfrom
KieranBond:feat/extension-bus

Conversation

@KieranBond

Copy link
Copy Markdown

Summary

  • add capability-negotiated, namespaced channels for non-conversational extension coordination
  • elect one socket-bound owner per namespace and reject stale owner-only writes
  • persist bounded opaque state with compare-and-swap revisions and backup recovery
  • synchronize capabilities registered after connection, including load-order-safe discovery
  • keep extension payloads out of Pi messages, transcripts, and agent turns

Validation

  • npm test — 94 tests pass
  • npm pack --dry-run
  • three-session iTerm smoke test using a consumer extension

Compatibility

Older clients ignore the additive broker feature list. New clients detect older brokers and do not send extension operations.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 867fce790a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread broker/broker.ts Outdated
Comment thread index.ts
Comment thread broker/broker.ts Outdated
Comment thread broker/broker.ts
Comment thread broker/extension-state.ts
const tempPath = `${statePath}.tmp.${process.pid}.${randomUUID()}`;

try {
writeFileSync(tempPath, JSON.stringify(envelope), { mode: 0o600 });

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DEFERRED] Every state commit performs synchronous write/fsync/rename/fsync on the broker event loop. Normal consumers commit rarely, but the API permits a same-user owner to stall all routing. Choosing async queued durability versus explicit commit throttling is a maintainer-level design decision.

Comment thread broker/extension-state.ts
return state;
}

commitState(namespace: string, expectedRevision: number, payload: unknown): StateCommitResult {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DEFERRED] Persisted namespaces and the in-memory state cache have no total cap or reclamation policy, allowing unbounded growth across short-lived namespace names. A global cap, TTL, or explicit deletion policy needs an upstream lifecycle decision.

Comment thread broker/broker.ts
}

// Sort by startedAt, then sessionId
candidates.sort((a, b) => {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DEFERRED] Full owner recomputation scans every namespace against every session and capability on connect/disconnect/update. The configured maxima permit a large worst case; deciding whether those bounds are acceptable or an incremental namespace index is required affects the broker design broadly.

Comment thread index.ts
Comment thread broker/broker.ts

const isCapable = recipientSession.extensions.some((ext) => ext.namespace === namespace);
if (isCapable) {
writeMessage(recipientSession.socket, {

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DEFERRED] A 64 KiB state commit is broadcast to every capable socket without a byte-aware backpressure policy, so slow consumers can accumulate significant buffered output. A bounded/coalesced queue versus disconnect-on-backlog policy is a broader broker transport decision.

Comment thread extension-api.ts
owner?: IntercomExtensionOwner;
state?: IntercomExtensionState;
};
publish(payload: unknown, options?: { audience?: "owner" | "capable"; ownerOnly?: boolean }): void;

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[DEFERRED] publish() is fire-and-forget even though the broker may reject stale authority, payload size, or capability, and generic client errors are intentionally hidden from the TUI. Adding request IDs and Promise/result semantics would materially expand the protocol and needs maintainer direction.

Comment thread index.ts Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant