@vividcodeai/embeddedcowork 0.0.3 → 0.0.5

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.
Files changed (54) hide show
  1. package/README.md +24 -24
  2. package/dist/auth/auth-store.js +2 -2
  3. package/dist/auth/manager.js +3 -3
  4. package/dist/background-processes/manager.js +1 -1
  5. package/dist/config/location.js +4 -4
  6. package/dist/opencode-config/README.md +4 -4
  7. package/dist/opencode-config/opencode.jsonc +33 -1
  8. package/dist/opencode-config/plugin/{embedcowork.ts → embeddedcowork.ts} +3 -3
  9. package/dist/opencode-config/plugin/lib/request.ts +2 -2
  10. package/dist/opencode-config.js +1 -1
  11. package/dist/plugins/handlers.js +2 -2
  12. package/dist/plugins/voice-mode.js +1 -1
  13. package/dist/runtime-paths.js +1 -1
  14. package/dist/server/__tests__/remote-proxy.test.js +3 -3
  15. package/dist/server/remote-proxy.js +2 -2
  16. package/dist/server/routes/events.js +1 -1
  17. package/dist/storage/instance-store.js +1 -1
  18. package/dist/ui/__tests__/remote-ui.test.js +1 -1
  19. package/dist/ui/remote-ui.js +2 -2
  20. package/dist/workspaces/__tests__/spawn.test.js +12 -12
  21. package/dist/workspaces/git-worktrees.js +1 -1
  22. package/dist/workspaces/manager.js +2 -2
  23. package/dist/workspaces/opencode-auth.js +1 -1
  24. package/dist/workspaces/runtime.js +1 -1
  25. package/dist/workspaces/spawn.js +1 -1
  26. package/dist/workspaces/worktree-map.js +4 -4
  27. package/package.json +2 -2
  28. package/public/assets/{ChangesTab-DFEdssRe.js → ChangesTab-C2DJXDf9.js} +2 -2
  29. package/public/assets/{DiffToolbar-CFFsbjNY.js → DiffToolbar-De-3SRCF.js} +1 -1
  30. package/public/assets/{FilesTab-DzZTwCeV.js → FilesTab-BuQ00MEc.js} +2 -2
  31. package/public/assets/{GitChangesTab-D8D157YD.js → GitChangesTab-D9bf2jkM.js} +2 -2
  32. package/public/assets/{SplitFilePanel-Civ71TMb.js → SplitFilePanel-B-3h60o2.js} +1 -1
  33. package/public/assets/{StatusTab-BzzCSXZS.js → StatusTab-D5s19fRN.js} +1 -1
  34. package/public/assets/{bundle-full-BtMSZAAD.js → bundle-full-CdNbUxmo.js} +1 -1
  35. package/public/assets/{diff-viewer-CW-3Ud61.js → diff-viewer-B1l_VZc1.js} +1 -1
  36. package/public/assets/{index-BLk2Gwi8.js → index-B2LsA7hD.js} +1 -1
  37. package/public/assets/{index-DRnrsrln.js → index-BErmCqgL.js} +1 -1
  38. package/public/assets/{index-CW9M2b5d.js → index-BKvZBimW.js} +1 -1
  39. package/public/assets/{index-DhequqTZ.js → index-BQeBs108.js} +1 -1
  40. package/public/assets/{index-_At0Dxz7.js → index-BqQARTCd.js} +1 -1
  41. package/public/assets/{index-BKkzfqNi.js → index-C9Tl2tHH.js} +2 -2
  42. package/public/assets/{index-AL8sjoID.js → index-ixx_g9gD.js} +1 -1
  43. package/public/assets/{loading-CztloVdu.js → loading-CQjaT4lJ.js} +1 -1
  44. package/public/assets/{main-CPG32lf7.js → main-C1yBw4P8.js} +8 -8
  45. package/public/assets/{markdown-B9y-GSCb.js → markdown-D5eIdNMf.js} +3 -3
  46. package/public/assets/{monaco-viewer-pWHOUbzL.js → monaco-viewer-9Byc1Kpy.js} +4 -4
  47. package/public/assets/{todo-DN0SfBX2.js → todo-uxdyLWei.js} +1 -1
  48. package/public/assets/{tool-call-D3h_ubYo.js → tool-call-C_JEoVSV.js} +3 -3
  49. package/public/assets/{unified-picker-DR7RnKXW.js → unified-picker-ePaJEYDm.js} +1 -1
  50. package/public/assets/{wrap-text-BufZr0C4.js → wrap-text-S8HH4qqP.js} +1 -1
  51. package/public/index.html +3 -3
  52. package/public/loading.html +3 -3
  53. package/public/sw.js +1 -1
  54. package/public/ui-version.json +1 -1
package/README.md CHANGED
@@ -32,13 +32,13 @@
32
32
  You can run EmbeddedCowork directly without installing it:
33
33
 
34
34
  ```sh
35
- npx @vividcode/embedcowork --launch
35
+ npx @vividcodeai/embeddedcowork --launch
36
36
  ```
37
37
 
38
38
  To list all CLI options:
39
39
 
40
40
  ```sh
41
- npx @vividcode/embedcowork --help
41
+ npx @vividcodeai/embeddedcowork --help
42
42
  ```
43
43
 
44
44
  On startup, EmbeddedCowork prints two URLs:
@@ -48,11 +48,11 @@ On startup, EmbeddedCowork prints two URLs:
48
48
 
49
49
  ### Install Globally
50
50
 
51
- Or install it globally to use the `embedcowork` command:
51
+ Or install it globally to use the `embeddedcowork` command:
52
52
 
53
53
  ```sh
54
- npm install -g @vividcode/embedcowork
55
- embedcowork --launch
54
+ npm install -g @vividcodeai/embeddedcowork
55
+ embeddedcowork --launch
56
56
  ```
57
57
 
58
58
  ### Install Locally (per-project)
@@ -60,11 +60,11 @@ embedcowork --launch
60
60
  If you prefer to install EmbeddedCowork into a project and run the local binary:
61
61
 
62
62
  ```sh
63
- npm install @vividcode/embedcowork
64
- npx embedcowork --launch
63
+ npm install @vividcodeai/embeddedcowork
64
+ npx embeddedcowork --launch
65
65
  ```
66
66
 
67
- (`npx embedcowork ...` will use `./node_modules/.bin/embedcowork` when present.)
67
+ (`npx embeddedcowork ...` will use `./node_modules/.bin/embeddedcowork` when present.)
68
68
 
69
69
  ### Common Flags
70
70
 
@@ -81,16 +81,16 @@ You can configure the server using flags or environment variables:
81
81
  | `--tls-ca <path>` | `CLI_TLS_CA` | Optional CA chain/bundle (PEM) |
82
82
  | `--tlsSANs <list>` | `CLI_TLS_SANS` | Additional TLS SANs (comma-separated) |
83
83
  | `--host <addr>` | `CLI_HOST` | Interface to bind (default 127.0.0.1) |
84
- | `--workspace-root <path>` | `CLI_WORKSPACE_ROOT` | Restricts the root path where new workspaces can be opened. Git worktrees are created in `.embedcowork/worktrees` inside the project folder. |
84
+ | `--workspace-root <path>` | `CLI_WORKSPACE_ROOT` | Restricts the root path where new workspaces can be opened. Git worktrees are created in `.embeddedcowork/worktrees` inside the project folder. |
85
85
  | `--unrestricted-root` | `CLI_UNRESTRICTED_ROOT` | Allow full-filesystem browsing |
86
86
  | `--config <path>` | `CLI_CONFIG` | Config file location |
87
87
  | `--launch` | `CLI_LAUNCH` | Open the UI in a Chromium-based browser |
88
88
  | `--log-level <level>` | `CLI_LOG_LEVEL` | Logging level (trace, debug, info, warn, error) |
89
89
  | `--log-destination <path>` | `CLI_LOG_DESTINATION` | Log destination file (defaults to stdout) |
90
- | `--username <username>` | `EMBEDCOWORK_SERVER_USERNAME` | Username for EmbeddedCowork's internal auth (default `embedcowork`) |
91
- | `--password <password>` | `EMBEDCOWORK_SERVER_PASSWORD` | Password for EmbeddedCowork's internal auth |
92
- | `--generate-token` | `EMBEDCOWORK_GENERATE_TOKEN` | Emit a one-time local bootstrap token for desktop flows |
93
- | `--dangerously-skip-auth` | `EMBEDCOWORK_SKIP_AUTH` | Disable EmbeddedCowork's internal auth (use only behind a trusted perimeter) |
90
+ | `--username <username>` | `EMBEDDEDCOWORK_SERVER_USERNAME` | Username for EmbeddedCowork's internal auth (default `embeddedcowork`) |
91
+ | `--password <password>` | `EMBEDDEDCOWORK_SERVER_PASSWORD` | Password for EmbeddedCowork's internal auth |
92
+ | `--generate-token` | `EMBEDDEDCOWORK_GENERATE_TOKEN` | Emit a one-time local bootstrap token for desktop flows |
93
+ | `--dangerously-skip-auth` | `EMBEDDEDCOWORK_SKIP_AUTH` | Disable EmbeddedCowork's internal auth (use only behind a trusted perimeter) |
94
94
  | `--ui-dir <path>` | `CLI_UI_DIR` | Directory containing the built UI bundle |
95
95
  | `--ui-dev-server <url>` | `CLI_UI_DEV_SERVER` | Proxy UI requests to a running dev server (requires `--https=false --http=true`) |
96
96
  | `--ui-no-update` | `CLI_UI_NO_UPDATE` | Disable remote UI updates |
@@ -102,15 +102,15 @@ You can configure the server using flags or environment variables:
102
102
  If you want the latest bleeding-edge builds (published as GitHub pre-releases), use the dev package:
103
103
 
104
104
  ```sh
105
- npx @vividcode/embedcowork-dev --launch
105
+ npx @vividcodeai/embeddedcowork-dev --launch
106
106
  ```
107
107
 
108
108
  These environment variables control how EmbeddedCowork checks for dev updates:
109
109
 
110
110
  | Env Variable | Description |
111
111
  |-------------|-------------|
112
- | `EMBEDCOWORK_UPDATE_CHANNEL` | Update channel (use `dev` to enable dev build update checks) |
113
- | `EMBEDCOWORK_GITHUB_REPO` | GitHub repo used for dev release checks (default `VividCodeAI/EmbeddedCowork`) |
112
+ | `EMBEDDEDCOWORK_UPDATE_CHANNEL` | Update channel (use `dev` to enable dev build update checks) |
113
+ | `EMBEDDEDCOWORK_GITHUB_REPO` | GitHub repo used for dev release checks (default `VividCodeAI/EmbeddedCowork`) |
114
114
 
115
115
  ### HTTP vs HTTPS
116
116
 
@@ -118,13 +118,13 @@ These environment variables control how EmbeddedCowork checks for dev updates:
118
118
  - To run plain HTTP only (useful for development):
119
119
 
120
120
  ```sh
121
- embedcowork --https=false --http=true
121
+ embeddedcowork --https=false --http=true
122
122
  ```
123
123
 
124
124
  - To run both HTTPS (for remote) and HTTP loopback (for desktop):
125
125
 
126
126
  ```sh
127
- embedcowork --https=true --http=true
127
+ embeddedcowork --https=true --http=true
128
128
  ```
129
129
 
130
130
  ### Remote Access Binding Rules
@@ -139,19 +139,19 @@ embedcowork --https=true --http=true
139
139
 
140
140
  If `--https=true` and you do not provide `--tls-key/--tls-cert`, EmbeddedCowork generates a local certificate automatically under your config directory:
141
141
 
142
- - `~/.config/embedcowork/tls/ca-cert.pem`
143
- - `~/.config/embedcowork/tls/server-cert.pem`
142
+ - `~/.config/embeddedcowork/tls/ca-cert.pem`
143
+ - `~/.config/embeddedcowork/tls/server-cert.pem`
144
144
 
145
145
  Certificates are valid for about 30 days and rotate automatically on startup when needed. You can add extra SANs via:
146
146
 
147
147
  ```sh
148
- embedcowork --tlsSANs "localhost,127.0.0.1,my-hostname,192.168.1.10"
148
+ embeddedcowork --tlsSANs "localhost,127.0.0.1,my-hostname,192.168.1.10"
149
149
  ```
150
150
 
151
151
  ### Authentication
152
152
 
153
153
  - Default behavior: EmbeddedCowork requires a login (username/password) and stores a session cookie in the browser.
154
- - `--dangerously-skip-auth` / `EMBEDCOWORK_SKIP_AUTH=true` disables the login prompt and treats all requests as authenticated.
154
+ - `--dangerously-skip-auth` / `EMBEDDEDCOWORK_SKIP_AUTH=true` disables the login prompt and treats all requests as authenticated.
155
155
  Use this only when access is already protected by another layer (SSO proxy, VPN, Coder workspace auth, etc.).
156
156
  If you bind to `0.0.0.0` while skipping auth, anyone who can reach the port can access the API.
157
157
 
@@ -169,5 +169,5 @@ When running as a server EmbeddedCowork can also be installed as a PWA from any
169
169
 
170
170
  ### Data Storage
171
171
 
172
- - **Config**: `~/.config/embedcowork/config.json`
173
- - **Instance Data**: `~/.config/embedcowork/instances` (chat history, etc.)
172
+ - **Config**: `~/.config/embeddedcowork/config.json`
173
+ - **Instance Data**: `~/.config/embeddedcowork/instances` (chat history, etc.)
@@ -68,7 +68,7 @@ export class AuthStore {
68
68
  this.logger.debug({ authFilePath: this.authFilePath }, "No auth file present; bootstrap-only mode enabled");
69
69
  return;
70
70
  }
71
- throw new Error(`No server password configured. Create ${this.authFilePath} or start with --password / EMBEDCOWORK_SERVER_PASSWORD.`);
71
+ throw new Error(`No server password configured. Create ${this.authFilePath} or start with --password / EMBEDDEDCOWORK_SERVER_PASSWORD.`);
72
72
  }
73
73
  validateCredentials(username, password) {
74
74
  const auth = this.load();
@@ -82,7 +82,7 @@ export class AuthStore {
82
82
  }
83
83
  setPassword(params) {
84
84
  if (this.overrideAuth) {
85
- throw new Error("Server password is provided via CLI/env and cannot be changed while running. Restart without --password / EMBEDCOWORK_SERVER_PASSWORD to use auth.json.");
85
+ throw new Error("Server password is provided via CLI/env and cannot be changed while running. Restart without --password / EMBEDDEDCOWORK_SERVER_PASSWORD to use auth.json.");
86
86
  }
87
87
  const current = this.load();
88
88
  if (!current) {
@@ -3,9 +3,9 @@ import { AuthStore } from "./auth-store";
3
3
  import { TokenManager } from "./token-manager";
4
4
  import { SessionManager } from "./session-manager";
5
5
  import { isLoopbackAddress, parseCookies } from "./http-auth";
6
- export const BOOTSTRAP_TOKEN_STDOUT_PREFIX = "EMBEDCOWORK_BOOTSTRAP_TOKEN:";
7
- export const DEFAULT_AUTH_USERNAME = "embedcowork";
8
- export const DEFAULT_AUTH_COOKIE_NAME = "embedcowork_session";
6
+ export const BOOTSTRAP_TOKEN_STDOUT_PREFIX = "EMBEDDEDCOWORK_BOOTSTRAP_TOKEN:";
7
+ export const DEFAULT_AUTH_USERNAME = "embeddedcowork";
8
+ export const DEFAULT_AUTH_COOKIE_NAME = "embeddedcowork_session";
9
9
  export class AuthManager {
10
10
  constructor(init, logger) {
11
11
  this.init = init;
@@ -2,7 +2,7 @@ import { spawn, spawnSync } from "child_process";
2
2
  import { createWriteStream, existsSync, promises as fs } from "fs";
3
3
  import path from "path";
4
4
  import { randomBytes } from "crypto";
5
- const ROOT_DIR = ".embedcowork/background_processes";
5
+ const ROOT_DIR = ".embeddedcowork/background_processes";
6
6
  const INDEX_FILE = "index.json";
7
7
  const OUTPUT_FILE = "output.txt";
8
8
  const STOP_TIMEOUT_MS = 2000;
@@ -17,13 +17,13 @@ function isJsonPath(filePath) {
17
17
  * Resolve EmbeddedCowork's config location into a stable base directory + derived file paths.
18
18
  *
19
19
  * Supported inputs:
20
- * - Directory: "~/.config/embedcowork"
21
- * - YAML file: "~/.config/embedcowork/config.yaml" (or any *.yml/*.yaml)
22
- * - Legacy JSON file: "~/.config/embedcowork/config.json"
20
+ * - Directory: "~/.config/embeddedcowork"
21
+ * - YAML file: "~/.config/embeddedcowork/config.yaml" (or any *.yml/*.yaml)
22
+ * - Legacy JSON file: "~/.config/embeddedcowork/config.json"
23
23
  */
24
24
  export function resolveConfigLocation(raw) {
25
25
  const trimmed = (raw ?? "").trim();
26
- const fallback = "~/.config/embedcowork/config.json";
26
+ const fallback = "~/.config/embeddedcowork/config.json";
27
27
  const input = trimmed.length > 0 ? trimmed : fallback;
28
28
  const resolvedInput = resolvePath(input);
29
29
  if (isYamlPath(resolvedInput)) {
@@ -4,13 +4,13 @@
4
4
  Template config + plugins injected into every OpenCode instance that EmbeddedCowork launches. It provides an EmbeddedCowork bridge plugin for local event exchange between the CLI server and opencode.
5
5
 
6
6
  ## What it is
7
- A packaged config directory that EmbeddedCowork copies into `~/.config/embedcowork/opencode-config` for production builds or uses directly in dev. OpenCode autoloads any `plugin/*.ts` or `plugin/*.js` from this directory.
7
+ A packaged config directory that EmbeddedCowork copies into `~/.config/embeddedcowork/opencode-config` for production builds or uses directly in dev. OpenCode autoloads any `plugin/*.ts` or `plugin/*.js` from this directory.
8
8
 
9
9
  ## How it works
10
10
  - EmbeddedCowork sets `OPENCODE_CONFIG_DIR` when spawning each opencode instance (`packages/server/src/workspaces/manager.ts`).
11
11
  - This template is synced from `packages/opencode-config` (`packages/server/src/opencode-config.ts`, `packages/server/scripts/copy-opencode-config.mjs`).
12
- - OpenCode autoloads plugins from `plugin/` (`packages/opencode-config/plugin/embedcowork.ts`).
13
- - The `EmbeddedCoworkPlugin` reads `EMBEDCOWORK_INSTANCE_ID` + `EMBEDCOWORK_BASE_URL`, connects to `GET /workspaces/:id/plugin/events`, and posts to `POST /workspaces/:id/plugin/event` (`packages/opencode-config/plugin/lib/client.ts`).
12
+ - OpenCode autoloads plugins from `plugin/` (`packages/opencode-config/plugin/embeddedcowork.ts`).
13
+ - The `EmbeddedCoworkPlugin` reads `EMBEDDEDCOWORK_INSTANCE_ID` + `EMBEDDEDCOWORK_BASE_URL`, connects to `GET /workspaces/:id/plugin/events`, and posts to `POST /workspaces/:id/plugin/event` (`packages/opencode-config/plugin/lib/client.ts`).
14
14
  - The server exposes the plugin routes and maps events into the UI SSE pipeline (`packages/server/src/server/routes/plugin.ts`, `packages/server/src/plugins/handlers.ts`).
15
15
 
16
16
  ## Expectations
@@ -25,7 +25,7 @@ A packaged config directory that EmbeddedCowork copies into `~/.config/embedcowo
25
25
  - Promote stable event shapes and version tags once the protocol settles.
26
26
 
27
27
  ## Pointers
28
- - Plugin entry: `packages/opencode-config/plugin/embedcowork.ts`
28
+ - Plugin entry: `packages/opencode-config/plugin/embeddedcowork.ts`
29
29
  - Plugin client: `packages/opencode-config/plugin/lib/client.ts`
30
30
  - Plugin server routes: `packages/server/src/server/routes/plugin.ts`
31
31
  - Plugin event handling: `packages/server/src/plugins/handlers.ts`
@@ -1,3 +1,35 @@
1
1
  {
2
- "$schema": "https://opencode.ai/config.json"
2
+ "$schema": "https://opencode.ai/config.json",
3
+ "mcp": {
4
+ "embedded-xLink-mcp": {
5
+ "type": "local",
6
+ "command": [
7
+ "npx",
8
+ "-y",
9
+ "@vividcodeai/embedded-xlink-mcp"
10
+ ],
11
+ "enabled": false,
12
+ "environment": {}
13
+ },
14
+ "embedded-serial-mcp": {
15
+ "type": "local",
16
+ "command": [
17
+ "npx",
18
+ "-y",
19
+ "@vividcodeai/embedded-serial-mcp"
20
+ ],
21
+ "enabled": false,
22
+ "environment": {}
23
+ },
24
+ "embedded-gdb-mcp": {
25
+ "type": "local",
26
+ "command": [
27
+ "npx",
28
+ "-y",
29
+ "@vividcodeai/embedded-gdb-mcp"
30
+ ],
31
+ "enabled": false,
32
+ "environment": {}
33
+ },
34
+ },
3
35
  }
@@ -10,9 +10,9 @@ export async function EmbeddedCoworkPlugin(input: PluginInput) {
10
10
  const backgroundProcessTools = createBackgroundProcessTools(config, { baseDir: input.directory })
11
11
 
12
12
  await client.startEvents((event) => {
13
- if (event.type === "embedcowork.ping") {
13
+ if (event.type === "embeddedcowork.ping") {
14
14
  void client.postEvent({
15
- type: "embedcowork.pong",
15
+ type: "embeddedcowork.pong",
16
16
  properties: {
17
17
  ts: Date.now(),
18
18
  pingTs: (event.properties as any)?.ts,
@@ -21,7 +21,7 @@ export async function EmbeddedCoworkPlugin(input: PluginInput) {
21
21
  return
22
22
  }
23
23
 
24
- if (event.type === "embedcowork.voiceMode") {
24
+ if (event.type === "embeddedcowork.voiceMode") {
25
25
  voiceModeEnabled = Boolean((event.properties as { enabled?: unknown } | undefined)?.enabled)
26
26
  }
27
27
  })
@@ -14,8 +14,8 @@ export type EmbeddedCoworkConfig = {
14
14
 
15
15
  export function getEmbeddedCoworkConfig(): EmbeddedCoworkConfig {
16
16
  return {
17
- instanceId: requireEnv("EMBEDCOWORK_INSTANCE_ID"),
18
- baseUrl: requireEnv("EMBEDCOWORK_BASE_URL"),
17
+ instanceId: requireEnv("EMBEDDEDCOWORK_INSTANCE_ID"),
18
+ baseUrl: requireEnv("EMBEDDEDCOWORK_BASE_URL"),
19
19
  }
20
20
  }
21
21
 
@@ -3,7 +3,7 @@ import { createLogger } from "./logger";
3
3
  import { resolveOpencodeTemplateDir } from "./runtime-paths";
4
4
  const log = createLogger({ component: "opencode-config" });
5
5
  const templateDir = resolveOpencodeTemplateDir(import.meta.url);
6
- const isDevBuild = Boolean(process.env.EMBEDCOWORK_DEV ?? process.env.CLI_UI_DEV_SERVER);
6
+ const isDevBuild = Boolean(process.env.EMBEDDEDCOWORK_DEV ?? process.env.CLI_UI_DEV_SERVER);
7
7
  export function getOpencodeConfigDir() {
8
8
  if (!existsSync(templateDir)) {
9
9
  throw new Error(`EmbeddedCowork Opencode config template missing at ${templateDir}`);
@@ -1,6 +1,6 @@
1
1
  export function handlePluginEvent(workspaceId, event, deps) {
2
2
  switch (event.type) {
3
- case "embedcowork.pong":
3
+ case "embeddedcowork.pong":
4
4
  deps.logger.debug({ workspaceId, properties: event.properties }, "Plugin pong received");
5
5
  return;
6
6
  default:
@@ -9,7 +9,7 @@ export function handlePluginEvent(workspaceId, event, deps) {
9
9
  }
10
10
  export function buildPingEvent() {
11
11
  return {
12
- type: "embedcowork.ping",
12
+ type: "embeddedcowork.ping",
13
13
  properties: {
14
14
  ts: Date.now(),
15
15
  },
@@ -66,7 +66,7 @@ export class VoiceModeManager {
66
66
  }
67
67
  function buildVoiceModeEvent(enabled) {
68
68
  return {
69
- type: "embedcowork.voiceMode",
69
+ type: "embeddedcowork.voiceMode",
70
70
  properties: {
71
71
  enabled,
72
72
  formatVersion: "v1",
@@ -24,7 +24,7 @@ export function getPackagedDistDir() {
24
24
  }
25
25
  export function resolveServerPackageRoot(importMetaUrl) {
26
26
  const moduleDir = safeModuleDir(importMetaUrl);
27
- const configuredRoot = process.env.EMBEDCOWORK_SERVER_ROOT?.trim();
27
+ const configuredRoot = process.env.EMBEDDEDCOWORK_SERVER_ROOT?.trim();
28
28
  const candidates = [
29
29
  configuredRoot ? path.resolve(configuredRoot) : null,
30
30
  moduleDir ? path.resolve(moduleDir, "..") : null,
@@ -7,7 +7,7 @@ import path from "node:path";
7
7
  import { Agent, fetch } from "undici";
8
8
  import { RemoteProxySessionManager } from "../remote-proxy";
9
9
  import { resolveHttpsOptions } from "../tls";
10
- const sharedTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "embedcowork-remote-proxy-test-"));
10
+ const sharedTempDir = fs.mkdtempSync(path.join(os.tmpdir(), "embeddedcowork-remote-proxy-test-"));
11
11
  const sharedTls = resolveHttpsOptions({
12
12
  enabled: true,
13
13
  configDir: sharedTempDir,
@@ -38,7 +38,7 @@ describe("RemoteProxySessionManager", () => {
38
38
  const session2 = await createSession(manager, `${upstreamBaseUrl}/base`);
39
39
  const blocked = await proxyFetch(`${session1.proxyOrigin}/status`);
40
40
  assert.equal(blocked.status, 403);
41
- const wrongTokenResponse = await proxyFetch(`${session1.proxyOrigin}/__embedcowork/api/auth/token`, {
41
+ const wrongTokenResponse = await proxyFetch(`${session1.proxyOrigin}/__embeddedcowork/api/auth/token`, {
42
42
  method: "POST",
43
43
  headers: { "content-type": "application/json" },
44
44
  body: JSON.stringify({ token: session2.token }),
@@ -148,7 +148,7 @@ async function createSession(manager, baseUrl) {
148
148
  };
149
149
  }
150
150
  async function activateSession(session) {
151
- const response = await proxyFetch(`${session.proxyOrigin}/__embedcowork/api/auth/token`, {
151
+ const response = await proxyFetch(`${session.proxyOrigin}/__embeddedcowork/api/auth/token`, {
152
152
  method: "POST",
153
153
  headers: { "content-type": "application/json" },
154
154
  body: JSON.stringify({ token: session.token }),
@@ -4,8 +4,8 @@ import { Readable } from "stream";
4
4
  import { pipeline } from "stream/promises";
5
5
  import { Agent, fetch } from "undici";
6
6
  const LOOPBACK_HOST = "127.0.0.1";
7
- const BOOTSTRAP_PAGE_PATH = "/__embedcowork/auth/token";
8
- const BOOTSTRAP_EXCHANGE_PATH = "/__embedcowork/api/auth/token";
7
+ const BOOTSTRAP_PAGE_PATH = "/__embeddedcowork/auth/token";
8
+ const BOOTSTRAP_EXCHANGE_PATH = "/__embeddedcowork/api/auth/token";
9
9
  const SESSION_IDLE_TTL_MS = 30 * 60000;
10
10
  export class RemoteProxySessionManager {
11
11
  constructor(options) {
@@ -30,7 +30,7 @@ export function registerEventRoutes(app, deps) {
30
30
  const unsubscribe = deps.eventBus.onEvent(send);
31
31
  const heartbeat = setInterval(() => {
32
32
  const ping = { ts: Date.now() };
33
- reply.raw.write(`event: embedcowork.client.ping\ndata: ${JSON.stringify(ping)}\n\n`);
33
+ reply.raw.write(`event: embeddedcowork.client.ping\ndata: ${JSON.stringify(ping)}\n\n`);
34
34
  }, 15000);
35
35
  let closed = false;
36
36
  const close = () => {
@@ -7,7 +7,7 @@ const DEFAULT_INSTANCE_DATA = {
7
7
  agentModelSelections: {},
8
8
  };
9
9
  export class InstanceStore {
10
- constructor(baseDir = path.join(os.homedir(), ".config", "embedcowork", "instances")) {
10
+ constructor(baseDir = path.join(os.homedir(), ".config", "embeddedcowork", "instances")) {
11
11
  this.instancesDir = baseDir;
12
12
  fs.mkdirSync(this.instancesDir, { recursive: true });
13
13
  }
@@ -16,7 +16,7 @@ const noopLogger = {
16
16
  };
17
17
  let tempRoot;
18
18
  beforeEach(() => {
19
- tempRoot = mkdtempSync(path.join(os.tmpdir(), "embedcowork-ui-test-"));
19
+ tempRoot = mkdtempSync(path.join(os.tmpdir(), "embeddedcowork-ui-test-"));
20
20
  });
21
21
  afterEach(() => {
22
22
  rmSync(tempRoot, { recursive: true, force: true });
@@ -6,7 +6,7 @@ import path from "path";
6
6
  import { Readable } from "stream";
7
7
  import { fetch } from "undici";
8
8
  import yauzl from "yauzl";
9
- const DEFAULT_MANIFEST_URL = "https://ui.embedcowork.vividcode.ai/version.json";
9
+ const DEFAULT_MANIFEST_URL = "https://ui.embeddedcowork.vividcode.ai/version.json";
10
10
  const MANIFEST_TIMEOUT_MS = 5000;
11
11
  const ZIP_TIMEOUT_MS = 30000;
12
12
  export async function resolveUi(options) {
@@ -139,7 +139,7 @@ function resolveUiCacheRoot(configDir) {
139
139
  if (configDir) {
140
140
  return path.join(configDir, "ui");
141
141
  }
142
- return path.join(os.homedir(), ".config", "embedcowork", "ui");
142
+ return path.join(os.homedir(), ".config", "embeddedcowork", "ui");
143
143
  }
144
144
  async function resolveFromCacheOrBundled(args) {
145
145
  const bestLocal = await pickBestLocalUi({
@@ -35,10 +35,10 @@ describe("buildWindowsSpawnSpec", () => {
35
35
  cwd: String.raw `\\wsl.localhost\Ubuntu\home\dev\workspace`,
36
36
  env: {
37
37
  OPENCODE_CONFIG_DIR: String.raw `C:\Users\dev\AppData\Roaming\EmbeddedCowork\opencode-config`,
38
- EMBEDCOWORK_INSTANCE_ID: "workspace-123",
38
+ EMBEDDEDCOWORK_INSTANCE_ID: "workspace-123",
39
39
  OPENCODE_SERVER_PASSWORD: "secret",
40
40
  },
41
- propagateEnvKeys: ["OPENCODE_CONFIG_DIR", "EMBEDCOWORK_INSTANCE_ID", "OPENCODE_SERVER_PASSWORD"],
41
+ propagateEnvKeys: ["OPENCODE_CONFIG_DIR", "EMBEDDEDCOWORK_INSTANCE_ID", "OPENCODE_SERVER_PASSWORD"],
42
42
  });
43
43
  assert.equal(spec.command, "wsl.exe");
44
44
  assert.deepEqual(spec.args, [
@@ -53,17 +53,17 @@ describe("buildWindowsSpawnSpec", () => {
53
53
  "0",
54
54
  ]);
55
55
  assert.equal(spec.cwd, undefined);
56
- assert.equal(spec.env?.WSLENV, "OPENCODE_CONFIG_DIR/p:EMBEDCOWORK_INSTANCE_ID:OPENCODE_SERVER_PASSWORD");
56
+ assert.equal(spec.env?.WSLENV, "OPENCODE_CONFIG_DIR/p:EMBEDDEDCOWORK_INSTANCE_ID:OPENCODE_SERVER_PASSWORD");
57
57
  });
58
58
  it("upgrades existing WSLENV path entries to include /p", () => {
59
59
  const spec = buildWindowsSpawnSpec(String.raw `\\wsl.localhost\Ubuntu\home\dev\.opencode\bin\opencode`, ["serve"], {
60
60
  env: {
61
61
  OPENCODE_CONFIG_DIR: String.raw `C:\Users\dev\AppData\Roaming\EmbeddedCowork\opencode-config`,
62
- WSLENV: "OPENCODE_CONFIG_DIR:EMBEDCOWORK_INSTANCE_ID/u",
62
+ WSLENV: "OPENCODE_CONFIG_DIR:EMBEDDEDCOWORK_INSTANCE_ID/u",
63
63
  },
64
- propagateEnvKeys: ["OPENCODE_CONFIG_DIR", "EMBEDCOWORK_INSTANCE_ID"],
64
+ propagateEnvKeys: ["OPENCODE_CONFIG_DIR", "EMBEDDEDCOWORK_INSTANCE_ID"],
65
65
  });
66
- assert.equal(spec.env?.WSLENV, "OPENCODE_CONFIG_DIR/p:EMBEDCOWORK_INSTANCE_ID/u");
66
+ assert.equal(spec.env?.WSLENV, "OPENCODE_CONFIG_DIR/p:EMBEDDEDCOWORK_INSTANCE_ID/u");
67
67
  });
68
68
  it("propagates inherited known path variables even when they are not explicitly requested", () => {
69
69
  const spec = buildWindowsSpawnSpec(String.raw `\\wsl.localhost\Ubuntu\home\dev\.opencode\bin\opencode`, ["serve"], {
@@ -85,7 +85,7 @@ describe("buildWindowsSpawnSpec", () => {
85
85
  "sh",
86
86
  "-lc",
87
87
  'cd "$(wslpath -au "$1")" && shift && exec "$@"',
88
- "embedcowork-wsl-launch",
88
+ "embeddedcowork-wsl-launch",
89
89
  String.raw `C:\Users\dev\workspace`,
90
90
  "/home/dev/.opencode/bin/opencode",
91
91
  "serve",
@@ -105,7 +105,7 @@ describe("buildWindowsSpawnSpec", () => {
105
105
  "sh",
106
106
  "-lc",
107
107
  'cd "$(wslpath -au "$1")" && shift && exec "$@"',
108
- "embedcowork-wsl-launch",
108
+ "embeddedcowork-wsl-launch",
109
109
  String.raw `\\server\share\workspace`,
110
110
  "/home/dev/.opencode/bin/opencode",
111
111
  "serve",
@@ -114,7 +114,7 @@ describe("buildWindowsSpawnSpec", () => {
114
114
  it("can wrap WSL launches to emit the Linux PID marker", () => {
115
115
  const spec = buildWindowsSpawnSpec(String.raw `\\wsl.localhost\Ubuntu\home\dev\.opencode\bin\opencode`, ["serve"], {
116
116
  cwd: String.raw `\\wsl.localhost\Ubuntu\home\dev\workspace`,
117
- wslPidMarker: "__EMBEDCOWORK_WSL_PID__:",
117
+ wslPidMarker: "__EMBEDDEDCOWORK_WSL_PID__:",
118
118
  });
119
119
  assert.equal(spec.command, "wsl.exe");
120
120
  assert.deepEqual(spec.args, [
@@ -123,13 +123,13 @@ describe("buildWindowsSpawnSpec", () => {
123
123
  "--exec",
124
124
  "sh",
125
125
  "-lc",
126
- `printf '%s%s\\n' '__EMBEDCOWORK_WSL_PID__:' "$$" && cd "$1" && shift && exec "$@"`,
127
- "embedcowork-wsl-launch",
126
+ `printf '%s%s\\n' '__EMBEDDEDCOWORK_WSL_PID__:' "$$" && cd "$1" && shift && exec "$@"`,
127
+ "embeddedcowork-wsl-launch",
128
128
  "/home/dev/workspace",
129
129
  "/home/dev/.opencode/bin/opencode",
130
130
  "serve",
131
131
  ]);
132
- assert.equal(spec.wsl?.pidMarker, "__EMBEDCOWORK_WSL_PID__:");
132
+ assert.equal(spec.wsl?.pidMarker, "__EMBEDDEDCOWORK_WSL_PID__:");
133
133
  });
134
134
  it("builds the WSL kill command for tracked Linux PIDs", () => {
135
135
  const spec = buildWslSignalSpec("Ubuntu", 4321, "SIGTERM");
@@ -163,7 +163,7 @@ export async function createManagedWorktree(params) {
163
163
  .replace(/^-+|-+$/g, "");
164
164
  return normalized || "worktree";
165
165
  };
166
- const worktreesDir = path.join(repoRoot, ".embedcowork", "worktrees");
166
+ const worktreesDir = path.join(repoRoot, ".embeddedcowork", "worktrees");
167
167
  const targetDir = path.join(worktreesDir, sanitizeDirName(branch));
168
168
  await fsp.mkdir(worktreesDir, { recursive: true });
169
169
  try {
@@ -139,8 +139,8 @@ export class WorkspaceManager {
139
139
  const environment = {
140
140
  ...userEnvironment,
141
141
  OPENCODE_CONFIG_DIR: this.opencodeConfigDir,
142
- EMBEDCOWORK_INSTANCE_ID: id,
143
- EMBEDCOWORK_BASE_URL: this.options.getServerBaseUrl(),
142
+ EMBEDDEDCOWORK_INSTANCE_ID: id,
143
+ EMBEDDEDCOWORK_BASE_URL: this.options.getServerBaseUrl(),
144
144
  ...(this.options.nodeExtraCaCertsPath ? { NODE_EXTRA_CA_CERTS: this.options.nodeExtraCaCertsPath } : {}),
145
145
  [OPENCODE_SERVER_USERNAME_ENV]: opencodeUsername,
146
146
  [OPENCODE_SERVER_PASSWORD_ENV]: opencodePassword,
@@ -1,7 +1,7 @@
1
1
  import crypto from "node:crypto";
2
2
  export const OPENCODE_SERVER_USERNAME_ENV = "OPENCODE_SERVER_USERNAME";
3
3
  export const OPENCODE_SERVER_PASSWORD_ENV = "OPENCODE_SERVER_PASSWORD";
4
- export const DEFAULT_OPENCODE_USERNAME = "embedcowork";
4
+ export const DEFAULT_OPENCODE_USERNAME = "embeddedcowork";
5
5
  export function generateOpencodeServerPassword() {
6
6
  return crypto.randomBytes(32).toString("base64url");
7
7
  }
@@ -3,7 +3,7 @@ import { existsSync, statSync } from "fs";
3
3
  import path from "path";
4
4
  import { buildSpawnSpec, buildWslSignalSpec } from "./spawn";
5
5
  const SENSITIVE_ENV_KEY = /(PASSWORD|TOKEN|SECRET)/i;
6
- const WSL_PID_MARKER = "__EMBEDCOWORK_WSL_PID__:";
6
+ const WSL_PID_MARKER = "__EMBEDDEDCOWORK_WSL_PID__:";
7
7
  function redactEnvironment(env) {
8
8
  const redacted = {};
9
9
  for (const [key, value] of Object.entries(env)) {
@@ -139,7 +139,7 @@ function buildWslSpawnSpec(wslPath, args, options) {
139
139
  }
140
140
  if (shouldWrapWithShell) {
141
141
  const launchScript = buildWslLaunchScript(workingDirectory ?? undefined, options.wslPidMarker);
142
- wslArgs.push("--exec", "sh", "-lc", launchScript, "embedcowork-wsl-launch");
142
+ wslArgs.push("--exec", "sh", "-lc", launchScript, "embeddedcowork-wsl-launch");
143
143
  if (workingDirectory) {
144
144
  wslArgs.push(workingDirectory.path);
145
145
  }
@@ -8,7 +8,7 @@ const DEFAULT_MAP = {
8
8
  parentSessionWorktreeSlug: {},
9
9
  };
10
10
  function getMapPath(repoRoot) {
11
- return path.join(repoRoot, ".embedcowork", "worktreeMap.json");
11
+ return path.join(repoRoot, ".embeddedcowork", "worktreeMap.json");
12
12
  }
13
13
  function getGitExcludePath(repoRoot) {
14
14
  return path.join(repoRoot, ".git", "info", "exclude");
@@ -22,8 +22,8 @@ async function ensureGitExclude(repoRoot, logger) {
22
22
  return;
23
23
  }
24
24
  const entries = [
25
- ".embedcowork/worktrees/",
26
- ".embedcowork/worktreeMap.json",
25
+ ".embeddedcowork/worktrees/",
26
+ ".embeddedcowork/worktreeMap.json",
27
27
  ];
28
28
  let existing = "";
29
29
  try {
@@ -42,7 +42,7 @@ async function ensureGitExclude(repoRoot, logger) {
42
42
  if (missing.length === 0) {
43
43
  return;
44
44
  }
45
- const header = existing.includes("# embedcowork") ? "" : (existing.trim() ? "\n" : "") + "# embedcowork\n";
45
+ const header = existing.includes("# embeddedcowork") ? "" : (existing.trim() ? "\n" : "") + "# embeddedcowork\n";
46
46
  const suffix = missing.map((e) => `${e}\n`).join("");
47
47
  await fsp.writeFile(excludePath, `${existing}${header}${suffix}`, "utf-8");
48
48
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vividcodeai/embeddedcowork",
3
- "version": "0.0.3",
3
+ "version": "0.0.5",
4
4
  "description": "EmbeddedCowork Server",
5
5
  "license": "MIT",
6
6
  "author": {
@@ -27,7 +27,7 @@
27
27
  "build:ui": "npm run build --prefix ../ui",
28
28
  "prepare-ui": "node ./scripts/copy-ui-dist.mjs",
29
29
  "prepare-config": "node ./scripts/copy-opencode-config.mjs",
30
- "dev": "cross-env EMBEDCOWORK_DEV=1 EMBEDCOWORK_SERVER_PASSWORD=embedcowork-dev CLI_UI_DEV_SERVER=http://localhost:3000 CLI_HTTPS=false CLI_HTTP=true tsx src/index.ts",
30
+ "dev": "cross-env EMBEDDEDCOWORK_DEV=1 EMBEDDEDCOWORK_SERVER_PASSWORD=embeddedcowork-dev CLI_UI_DEV_SERVER=http://localhost:3000 CLI_HTTPS=false CLI_HTTP=true tsx src/index.ts",
31
31
  "typecheck": "tsc --noEmit -p tsconfig.json"
32
32
  },
33
33
  "dependencies": {