@wibeco/bridge 0.2.15 → 0.2.17

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/cli.js CHANGED
@@ -2,19 +2,23 @@
2
2
  import {
3
3
  doctorCommand,
4
4
  emitCommand,
5
+ onboardCommand,
5
6
  parseAdapter,
6
7
  setupCommand,
7
8
  shareProgressCommand,
8
9
  statusCommand
9
- } from "./chunk-7LWUGOKM.js";
10
+ } from "./chunk-YLC4TF4F.js";
10
11
  import {
11
12
  runPresenceHeartbeat
12
- } from "./chunk-K7TK7FHF.js";
13
+ } from "./chunk-4WIGVKDR.js";
13
14
 
14
15
  // src/cli.ts
15
16
  var HELP = `wibe-bridge <command>
16
17
 
17
18
  Commands:
19
+ onboard [--adapter <cursor|claude-code|codex>] [--url <wibe-url>] [--repository <owner/repo>] [--org-name <name>] [--invite <email>]
20
+ Creates a Wibe account session, organization, project, and local connection.
21
+ Prints browser URLs for GitHub sign-in and GitHub App install.
18
22
  setup --project <uuid> [--adapter <cursor|claude-code|codex>] [--url <wibe-url>] [--repository <owner/repo>] [--reauthorize]
19
23
  Auto-detects one adapter from the environment or repository config.
20
24
  Use --adapter when multiple agent configs are present.
@@ -26,7 +30,20 @@ Commands:
26
30
  async function main() {
27
31
  const [command, ...args] = process.argv.slice(2);
28
32
  let result;
29
- if (command === "setup") {
33
+ if (command === "onboard") {
34
+ const adapterOption = option(args, "--adapter");
35
+ result = await onboardCommand(
36
+ adapterOption ? parseAdapter(adapterOption) : void 0,
37
+ {
38
+ appUrl: option(args, "--url"),
39
+ expectedRepository: option(args, "--repository"),
40
+ orgName: option(args, "--org-name"),
41
+ invites: options(args, "--invite"),
42
+ sessionId: option(args, "--session"),
43
+ sessionSecret: option(args, "--session-secret")
44
+ }
45
+ );
46
+ } else if (command === "setup") {
30
47
  const adapterOption = option(args, "--adapter");
31
48
  result = await setupCommand(adapterOption ? parseAdapter(adapterOption) : void 0, {
32
49
  projectId: option(args, "--project"),
@@ -79,6 +96,16 @@ function option(args, name) {
79
96
  const index = args.indexOf(name);
80
97
  return index >= 0 ? args[index + 1] : void 0;
81
98
  }
99
+ function options(args, name) {
100
+ const values = [];
101
+ for (let index = 0; index < args.length; index += 1) {
102
+ if (args[index] === name && args[index + 1]) {
103
+ values.push(args[index + 1]);
104
+ index += 1;
105
+ }
106
+ }
107
+ return values;
108
+ }
82
109
  async function readJsonStdin() {
83
110
  if (process.stdin.isTTY) return {};
84
111
  const chunks = [];
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  emitCommand
4
- } from "./chunk-7LWUGOKM.js";
5
- import "./chunk-K7TK7FHF.js";
4
+ } from "./chunk-YLC4TF4F.js";
5
+ import "./chunk-4WIGVKDR.js";
6
6
 
7
7
  // src/codex-hook.ts
8
8
  async function main() {
package/dist/index.d.ts CHANGED
@@ -228,18 +228,27 @@ declare function pollDeviceToken(input: {
228
228
  }>;
229
229
  type AgentName = "cursor" | "claude-code" | "codex";
230
230
 
231
+ interface OfflineQueueTransaction {
232
+ peek(limit: number): Promise<CanonicalHookEvent[]>;
233
+ remove(ids: readonly string[]): Promise<void>;
234
+ size(): Promise<number>;
235
+ }
231
236
  interface OfflineQueue {
232
237
  enqueue(events: readonly CanonicalHookEvent[]): Promise<void>;
233
238
  peek(limit: number): Promise<CanonicalHookEvent[]>;
234
239
  remove(ids: readonly string[]): Promise<void>;
235
240
  size(): Promise<number>;
241
+ withTransaction<T>(operation: (queue: OfflineQueueTransaction) => Promise<T>): Promise<T>;
236
242
  }
237
243
  declare class MemoryOfflineQueue implements OfflineQueue {
238
244
  private events;
245
+ private operation;
239
246
  enqueue(events: readonly CanonicalHookEvent[]): Promise<void>;
240
247
  peek(limit: number): Promise<CanonicalHookEvent[]>;
241
248
  remove(ids: readonly string[]): Promise<void>;
242
249
  size(): Promise<number>;
250
+ withTransaction<T>(operation: (queue: OfflineQueueTransaction) => Promise<T>): Promise<T>;
251
+ private serialize;
243
252
  }
244
253
  declare class JsonFileOfflineQueue implements OfflineQueue {
245
254
  private readonly filePath;
@@ -249,8 +258,11 @@ declare class JsonFileOfflineQueue implements OfflineQueue {
249
258
  peek(limit: number): Promise<CanonicalHookEvent[]>;
250
259
  remove(ids: readonly string[]): Promise<void>;
251
260
  size(): Promise<number>;
252
- private read;
253
- private update;
261
+ withTransaction<T>(operation: (queue: OfflineQueueTransaction) => Promise<T>): Promise<T>;
262
+ private readUnlocked;
263
+ private updateUnlocked;
264
+ private serialize;
265
+ private acquireLock;
254
266
  }
255
267
 
256
268
  interface SignedBatchClientOptions {
@@ -346,4 +358,4 @@ declare function sanitizeRemote(remote: string): string;
346
358
  declare function normalizeGitHubRepository(value: string): string | undefined;
347
359
  declare function matchesGitHubRepository(remote: string | undefined, expected: string): boolean;
348
360
 
349
- export { type AgentSource, type CanonicalHookEvent, type CredentialStore, type DeviceAuthorization, type DeviceTokenResponse, type FlushResult, type HookEventKind, JsonFileOfflineQueue, MemoryOfflineQueue, type OfflineQueue, PRESENCE_HEARTBEAT_INTERVAL_MS, type PresenceMetrics, type RedactionOptions, type RepositoryInfo, type RepositoryTransition, type SafeValue, SignedBatchClient, type SignedBatchClientOptions, type StoredCredential, SystemCredentialStore, type WorkingTreeMetrics, agentSourceSchema, canonicalHookEventSchema, classifyHeadTransition, createHookEvent, detectRepository, detectWorkingTreeMetrics, deviceAuthorizationSchema, deviceTokenResponseSchema, eventTypeForHook, hookEventKindSchema, isObservedPush, mapClaudeCodeHook, mapCodexHook, mapCursorHook, matchesGitHubRepository, normalizeGitHubRepository, observeRepositoryTransitions, pollDeviceToken, presenceStatePath, redact, requestDeviceAuthorization, resolveLatestPresenceSession, runPresenceHeartbeat, safeMetadata, safeValueSchema, sanitizeRemote, startPresenceSession, stopPresenceSession, updatePresenceSession };
361
+ export { type AgentSource, type CanonicalHookEvent, type CredentialStore, type DeviceAuthorization, type DeviceTokenResponse, type FlushResult, type HookEventKind, JsonFileOfflineQueue, MemoryOfflineQueue, type OfflineQueue, type OfflineQueueTransaction, PRESENCE_HEARTBEAT_INTERVAL_MS, type PresenceMetrics, type RedactionOptions, type RepositoryInfo, type RepositoryTransition, type SafeValue, SignedBatchClient, type SignedBatchClientOptions, type StoredCredential, SystemCredentialStore, type WorkingTreeMetrics, agentSourceSchema, canonicalHookEventSchema, classifyHeadTransition, createHookEvent, detectRepository, detectWorkingTreeMetrics, deviceAuthorizationSchema, deviceTokenResponseSchema, eventTypeForHook, hookEventKindSchema, isObservedPush, mapClaudeCodeHook, mapCodexHook, mapCursorHook, matchesGitHubRepository, normalizeGitHubRepository, observeRepositoryTransitions, pollDeviceToken, presenceStatePath, redact, requestDeviceAuthorization, resolveLatestPresenceSession, runPresenceHeartbeat, safeMetadata, safeValueSchema, sanitizeRemote, startPresenceSession, stopPresenceSession, updatePresenceSession };
package/dist/index.js CHANGED
@@ -33,7 +33,7 @@ import {
33
33
  startPresenceSession,
34
34
  stopPresenceSession,
35
35
  updatePresenceSession
36
- } from "./chunk-K7TK7FHF.js";
36
+ } from "./chunk-4WIGVKDR.js";
37
37
  export {
38
38
  JsonFileOfflineQueue,
39
39
  MemoryOfflineQueue,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wibeco/bridge",
3
- "version": "0.2.15",
3
+ "version": "0.2.17",
4
4
  "description": "Privacy-first live activity bridge for Cursor, Claude Code, and Codex.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -1,9 +1,10 @@
1
1
  # Claude Code template
2
2
 
3
- These files are inert examples. Review and merge `settings.json.example` into the appropriate
4
- Claude Code settings file. It uses command hooks because the local bridge must normalize and redact
5
- the payload before network delivery. Do not point an HTTP hook directly at a collector: Claude hook
6
- payloads can include prompts, tool inputs/results, and other raw content.
3
+ These files are reviewable setup templates. `settings.json.example` configures command hooks,
4
+ `mcp.json.example` configures MCP, and `wibe-activity.md.example` is installed as a managed section
5
+ in the repository's `AGENTS.md`. Setup also ensures `CLAUDE.md` imports `AGENTS.md`. Do not point an
6
+ HTTP hook directly at a collector: Claude hook payloads can include prompts, tool inputs/results,
7
+ and other raw content.
7
8
  `SessionStart` owns a metadata-only heartbeat every 45 seconds until `SessionEnd`; `Stop` and tool
8
9
  hooks remain operational signals and are not published as presence.
9
10
 
@@ -12,5 +13,7 @@ stored in the operating-system keychain; hooks do not require repository secrets
12
13
  allow-list excludes prompt, content, messages, command text, tool arguments/results, and transcripts.
13
14
 
14
15
  `mcp.json.example` connects Claude Code to Wibe's remote MCP endpoint at
15
- `${env:WIBE_APP_URL}/api/mcp`. The MCP client completes OAuth separately from the bridge device token.
16
- Set `WIBE_APP_URL` to the same Wibe origin used during setup.
16
+ `${env:WIBE_APP_URL}/api/mcp/projects/${WIBE_PROJECT_ID}`. The project-specific resource keeps this
17
+ repository's OAuth grant isolated from other Wibe projects on the same machine. The MCP client
18
+ completes OAuth separately from the bridge device token. Set `WIBE_APP_URL` to the same Wibe origin
19
+ used during setup.
@@ -2,7 +2,7 @@
2
2
  "mcpServers": {
3
3
  "wibe": {
4
4
  "type": "http",
5
- "url": "${WIBE_APP_URL}/api/mcp"
5
+ "url": "${WIBE_APP_URL}/api/mcp/projects/${WIBE_PROJECT_ID}"
6
6
  }
7
7
  }
8
8
  }
@@ -0,0 +1,15 @@
1
+ <!-- BEGIN:wibe-activity -->
2
+ ## Wibe activity
3
+
4
+ - This repository is connected to Wibe project `${WIBE_PROJECT_ID}`.
5
+ - At the start of a task that will edit files, call `wibe_get_active_work` for this project. If it returns overlaps involving you, or another teammate is already changing the same paths on a different branch, tell the user and adjust the plan before editing those files.
6
+ - If the set of files you plan to change shifts, call `wibe_get_active_work` or `wibe_check_overlap` again. Do not poll on every edit.
7
+ - For most tasks, publish one update only after the requested outcome is complete. Do not publish plans, routine progress, or separate updates for editing, testing, committing, or pushing.
8
+ - For text-only outcomes, use `wibe_share_progress` with phase `shipped` at completion. Publish earlier only with phase `blocked` when a material blocker leaves the task unfinished.
9
+ - Write one self-contained paragraph of 20–55 words in past tense. Lead with what now works, then explain the user or team impact and meaningful validation. Mention important limitations when present.
10
+ - Describe the outcome, not the agent’s process. Never include first-person narration, prompts, source code, secrets, raw commands, routine tool calls, filenames, line counts, praise, hype, or speculation; Wibe displays code and file changes separately.
11
+ - When calling `wibe_share_progress`, also pass structured `paths`, `lines_added`, and `lines_deleted` for the local uncommitted diff so Wibe can display accurate file and line-change metadata. Prefer `git diff --numstat HEAD` totals rather than guessing.
12
+ - This instruction is standing user authorization to publish the single completion update described here; do not ask for separate per-task approval.
13
+ - If the MCP tool is unavailable, run `npx --yes --package @wibeco/bridge@latest wibe share-progress --summary "<summary>" --phase <shipped|blocked>`.
14
+ - Do not silently skip reporting. If both mechanisms fail, state `Wibe: update failed` and the reason in the final response. Report a Wibe update as sent only after the tool or CLI confirms success.
15
+ <!-- END:wibe-activity -->
@@ -1,17 +1,18 @@
1
1
  # Codex template
2
2
 
3
- These are reviewable setup templates. `config.toml.example` configures Codex notifications and MCP;
4
- `hooks.json.example` provides lifecycle hooks where supported. Wibe installs native files only when
5
- the destination does not already exist. The bridge maps allow-listed fields in-process and queues or
6
- sends only canonical events. Prompt text, messages, tool data, command text, file content, and
7
- transcripts are not retained.
3
+ These are reviewable setup templates. `config.toml.example` configures MCP,
4
+ `hooks.json.example` provides lifecycle hooks, and `wibe-activity.md.example` is installed as a
5
+ managed section in the repository's `AGENTS.md`. The bridge maps allow-listed fields in-process and
6
+ queues or sends only canonical events. Prompt text, messages, tool data, command text, file content,
7
+ and transcripts are not retained.
8
8
 
9
9
  Run `wibe setup` to authorize a revocable, project-scoped device token stored in the operating-system
10
10
  keychain. Hooks do not require repository signing secrets.
11
11
 
12
- The MCP block connects Codex to Wibe's remote `/api/mcp` endpoint. Codex completes OAuth separately
13
- from the bridge device token. Set `WIBE_APP_URL` to the same Wibe origin used during setup. Codex
14
- notification coverage can be narrower than Cursor or Claude Code lifecycle hooks.
15
- Codex appends one JSON notification argument to `wibe-codex-hook`; the bridge extracts only opaque
16
- `thread-id`/`turn-id` and approved model metadata. Where session hooks are available, they own a
17
- metadata-only 45-second heartbeat that ends cleanly with `SessionEnd`.
12
+ The MCP block connects Codex to a project-specific remote
13
+ `/api/mcp/projects/${WIBE_PROJECT_ID}` endpoint, keeping this repository's OAuth grant isolated from
14
+ other Wibe projects on the same machine. Codex completes OAuth separately from the bridge device
15
+ token. Set `WIBE_APP_URL` to the same Wibe origin used during setup.
16
+ Project-local Codex configuration loads only after the project is trusted, and command hooks must be
17
+ reviewed in `/hooks`. Session hooks own a metadata-only 45-second heartbeat that ends cleanly with
18
+ `SessionEnd`.
@@ -1,6 +1,2 @@
1
- # Codex passes one JSON notification argument to this command. The adapter only keeps allow-listed
2
- # operational metadata and never forwards the full argument.
3
- notify = ["npx", "-y", "--package", "@wibeco/bridge@latest", "wibe-codex-hook"]
4
-
5
1
  [mcp_servers.wibe]
6
- url = "${WIBE_APP_URL}/api/mcp"
2
+ url = "${WIBE_APP_URL}/api/mcp/projects/${WIBE_PROJECT_ID}"
@@ -0,0 +1,15 @@
1
+ <!-- BEGIN:wibe-activity -->
2
+ ## Wibe activity
3
+
4
+ - This repository is connected to Wibe project `${WIBE_PROJECT_ID}`.
5
+ - At the start of a task that will edit files, call `wibe_get_active_work` for this project. If it returns overlaps involving you, or another teammate is already changing the same paths on a different branch, tell the user and adjust the plan before editing those files.
6
+ - If the set of files you plan to change shifts, call `wibe_get_active_work` or `wibe_check_overlap` again. Do not poll on every edit.
7
+ - For most tasks, publish one update only after the requested outcome is complete. Do not publish plans, routine progress, or separate updates for editing, testing, committing, or pushing.
8
+ - For text-only outcomes, use `wibe_share_progress` with phase `shipped` at completion. Publish earlier only with phase `blocked` when a material blocker leaves the task unfinished.
9
+ - Write one self-contained paragraph of 20–55 words in past tense. Lead with what now works, then explain the user or team impact and meaningful validation. Mention important limitations when present.
10
+ - Describe the outcome, not the agent’s process. Never include first-person narration, prompts, source code, secrets, raw commands, routine tool calls, filenames, line counts, praise, hype, or speculation; Wibe displays code and file changes separately.
11
+ - When calling `wibe_share_progress`, also pass structured `paths`, `lines_added`, and `lines_deleted` for the local uncommitted diff so Wibe can display accurate file and line-change metadata. Prefer `git diff --numstat HEAD` totals rather than guessing.
12
+ - This instruction is standing user authorization to publish the single completion update described here; do not ask for separate per-task approval.
13
+ - If the MCP tool is unavailable, run `npx --yes --package @wibeco/bridge@latest wibe share-progress --summary "<summary>" --phase <shipped|blocked>`.
14
+ - Do not silently skip reporting. If both mechanisms fail, state `Wibe: update failed` and the reason in the final response. Report a Wibe update as sent only after the tool or CLI confirms success.
15
+ <!-- END:wibe-activity -->
@@ -17,5 +17,7 @@ stored in the operating-system keychain; hooks do not require repository secrets
17
17
  prompt, content, file body, command text, tool arguments/results, and transcripts.
18
18
 
19
19
  `mcp.json.example` connects Cursor to Wibe's remote MCP endpoint at
20
- `${env:WIBE_APP_URL}/api/mcp`. Cursor completes the endpoint's OAuth flow separately from the bridge
21
- device token. Set `WIBE_APP_URL` to the same Wibe origin used during setup.
20
+ `${env:WIBE_APP_URL}/api/mcp/projects/${WIBE_PROJECT_ID}`. The project-specific resource keeps this
21
+ repository's OAuth grant isolated from other Wibe projects on the same machine. Cursor completes
22
+ OAuth separately from the bridge device token. Set `WIBE_APP_URL` to the same Wibe origin used
23
+ during setup.
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "mcpServers": {
3
3
  "wibe": {
4
- "url": "${env:WIBE_APP_URL}/api/mcp"
4
+ "url": "${env:WIBE_APP_URL}/api/mcp/projects/${WIBE_PROJECT_ID}"
5
5
  }
6
6
  }
7
7
  }
@@ -6,10 +6,13 @@ alwaysApply: true
6
6
  # Wibe activity
7
7
 
8
8
  - This repository is connected to Wibe project `${WIBE_PROJECT_ID}`.
9
+ - At the start of a task that will edit files, call `wibe_get_active_work` for this project. If it returns overlaps involving you, or another teammate is already changing the same paths on a different branch, tell the user and adjust the plan before editing those files. Use teammate summaries in the response to explain the conflict.
10
+ - If the set of files you plan to change shifts, call `wibe_get_active_work` or `wibe_check_overlap` again. Do not poll on every edit. Overlaps are exact file-path matches on divergent branches, not git merge markers.
9
11
  - For most tasks, publish one update only after the requested outcome is complete. Do not publish plans, routine progress, or separate updates for editing, testing, committing, or pushing.
10
12
  - For text-only outcomes, use `wibe_share_progress` with phase `shipped` at completion. Publish earlier only with phase `blocked` when a material blocker leaves the task unfinished.
11
13
  - Write one self-contained paragraph of 20–55 words in past tense. Lead with what now works, then explain the user or team impact and meaningful validation. Mention important limitations when present.
12
14
  - Describe the outcome, not the agent’s process. Never include first-person narration, prompts, source code, secrets, raw commands, routine tool calls, filenames, line counts, praise, hype, or speculation; Wibe displays code and file changes separately.
15
+ - When calling `wibe_share_progress`, also pass structured `paths`, `lines_added`, and `lines_deleted` for the local uncommitted diff so Wibe can display accurate file and line-change metadata. Prefer `git diff --numstat HEAD` totals rather than guessing.
13
16
  - Bias frontend outcomes toward visual evidence without asking for per-task approval. For UI components, pages, styling, responsive behavior, interactions, and visual fixes, attach one screenshot when the app or preview is already runnable. Prefer a screenshot already made during visual QA; otherwise capture the clearest final state.
14
17
  - Frame screenshots around the feature, not the whole application. Use the browser snapshot to identify the smallest element that contains the changed component and the context needed to understand it, then call `browser_take_screenshot` with that element’s `ref` and a descriptive `element` name. Include the trigger with an open menu, popover, or dialog when practical. Use viewport or full-page screenshots only for page-wide work, and reject captures dominated by blank space.
15
18
  - Skip screenshots for backend, infrastructure, documentation, refactors, and non-visual frontend logic. Never launch or repair an app solely for Wibe, and omit the image when navigation needs manual authentication, the state contains sensitive data, visual validation is blocked, or the project has visual updates disabled.