@open-everywhere/create 0.1.4

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 (82) hide show
  1. package/LICENSE +201 -0
  2. package/NOTICE +21 -0
  3. package/README.md +69 -0
  4. package/bin/create-open-everywhere.js +57 -0
  5. package/package.json +57 -0
  6. package/src/cli.ts +241 -0
  7. package/src/deploy-probe.ts +99 -0
  8. package/src/engine.ts +106 -0
  9. package/src/env-file.ts +53 -0
  10. package/src/scaffold.ts +188 -0
  11. package/src/steps/build-deploy.ts +78 -0
  12. package/src/steps/database.ts +85 -0
  13. package/src/steps/env-checklist.ts +55 -0
  14. package/src/steps/index.ts +49 -0
  15. package/src/steps/prerequisites.ts +50 -0
  16. package/src/steps/repo.ts +69 -0
  17. package/src/steps/roster.ts +111 -0
  18. package/src/steps/slack.ts +74 -0
  19. package/src/steps/vercel.ts +40 -0
  20. package/src/steps/verify.ts +119 -0
  21. package/src/version.ts +20 -0
  22. package/template/.env.example +58 -0
  23. package/template/.mcp.json +8 -0
  24. package/template/AGENTS.md +62 -0
  25. package/template/CLAUDE.md +1 -0
  26. package/template/README.md +87 -0
  27. package/template/agent/access/access-requests.ts +69 -0
  28. package/template/agent/access/browser-hosts.ts +28 -0
  29. package/template/agent/access/bundles.ts +78 -0
  30. package/template/agent/access/connector-credentials.ts +74 -0
  31. package/template/agent/access/credential-bindings.generated.ts +17 -0
  32. package/template/agent/access/credential-bindings.ts +28 -0
  33. package/template/agent/access/grants.generated.ts +18 -0
  34. package/template/agent/access/grants.ts +30 -0
  35. package/template/agent/access/network-access.ts +32 -0
  36. package/template/agent/agent.ts +125 -0
  37. package/template/agent/blob/hosting.ts +42 -0
  38. package/template/agent/identity/authors.ts +79 -0
  39. package/template/agent/identity/groups-overlay.ts +24 -0
  40. package/template/agent/identity/groups.generated.ts +17 -0
  41. package/template/agent/identity/groups.ts +84 -0
  42. package/template/agent/identity/principals.ts +37 -0
  43. package/template/agent/identity/surfaces.ts +48 -0
  44. package/template/agent/instructions/access.ts +11 -0
  45. package/template/agent/instructions.md +295 -0
  46. package/template/agent/instrumentation.ts +6 -0
  47. package/template/agent/lib/memory-grants.ts +52 -0
  48. package/template/agent/lib/register-adapters.ts +286 -0
  49. package/template/agent/lib/register-config.ts +185 -0
  50. package/template/agent/memory/config/agents-overlay.ts +26 -0
  51. package/template/agent/memory/config/agents.generated.ts +21 -0
  52. package/template/agent/memory/config/domains/dm.ts +10 -0
  53. package/template/agent/memory/config/domains/index.ts +125 -0
  54. package/template/agent/memory/config/domains/org.ts +27 -0
  55. package/template/agent/memory/config/domains.ts +165 -0
  56. package/template/agent/model/models.ts +60 -0
  57. package/template/agent/model/policy.ts +19 -0
  58. package/template/agent/model/stacks.ts +75 -0
  59. package/template/agent/plugins/generated/index.ts +13 -0
  60. package/template/agent/plugins/registry.ts +16 -0
  61. package/template/agent/plugins/skill-content.ts +13 -0
  62. package/template/agent/roles/roles.ts +146 -0
  63. package/template/agent/routines/collectors.ts +89 -0
  64. package/template/agent/sandbox/backend-select.ts +16 -0
  65. package/template/agent/sandbox/sandbox.ts +242 -0
  66. package/template/agent/sandbox/workspace/.keep +6 -0
  67. package/template/agent/settings/settings.ts +19 -0
  68. package/template/agent/spend/budgets.ts +25 -0
  69. package/template/agent/spend/checkpoints.ts +51 -0
  70. package/template/agent/spend/model-pricing.ts +25 -0
  71. package/template/agent/webhooks/hooks-overlay.ts +34 -0
  72. package/template/agent/webhooks/hooks.generated.ts +17 -0
  73. package/template/agent/webhooks/hooks.ts +133 -0
  74. package/template/claude/skills/quickstart-open-everywhere/SKILL.md +167 -0
  75. package/template/claude/skills/upgrade-open-everywhere/SKILL.md +160 -0
  76. package/template/gitignore +42 -0
  77. package/template/package.json +62 -0
  78. package/template/roster.config.ts +39 -0
  79. package/template/roster.lock.json +182 -0
  80. package/template/scripts/env-pipe.mjs +74 -0
  81. package/template/scripts/ops-mcp.ts +35 -0
  82. package/template/tsconfig.json +23 -0
@@ -0,0 +1,160 @@
1
+ ---
2
+ name: upgrade-open-everywhere
3
+ description: Upgrade this Open Everywhere app to a newer release — read the release notes between the installed and the target version, run `oe upgrade`, review the roster.lock.json diff, open a pull request, and confirm the deployment after it ships. Use when the user wants to upgrade, update, or take a new version of Open Everywhere, or asks what is in a newer release.
4
+ ---
5
+
6
+ # Upgrade Open Everywhere
7
+
8
+ One procedure, two drivers. You run it here, in a checkout of this app. The agent runs the same
9
+ steps on itself, in its own sandbox, against this same repository. Nothing below differs between
10
+ the two.
11
+
12
+ The procedure is `npx oe upgrade`. It is deterministic: it reads the release record that ships
13
+ inside `@open-everywhere/core`, bumps every package together, installs, applies the config
14
+ codemods the notes name, rebuilds the roster and proves the tree still builds.
15
+
16
+ ## Golden rules
17
+
18
+ - **`oe upgrade` writes and installs.** Show the command, get a yes, then run it. `--plan` writes
19
+ nothing, so run that first, every time.
20
+ - **Never merge the pull request yourself.** An admin merges it, and the merge deploys.
21
+ - **Never hand-edit `roster.lock.json`.** `oe build --accept` writes it. Your job is to READ the
22
+ diff: every line is a capability decision, and a new tool that nobody looked at is how an
23
+ upgrade quietly widens what the agent can do.
24
+ - **Never edit `UPGRADING.md`.** It is generated from `upgrading.json` beside it.
25
+ - **No secret reaches the chat, the branch or the pull request.** An upgrade never needs one. A
26
+ release that adds an env NAME tells the admin to set the value in the deployment's environment.
27
+ - Every command runs from this directory (the app root).
28
+
29
+ ## 1. Where you are, and where you are going
30
+
31
+ ```
32
+ node -p "require('./node_modules/@open-everywhere/core/package.json').version" # installed
33
+ node -p "require('./package.json').dependencies['@open-everywhere/core']" # pinned
34
+ npm view @open-everywhere/core version # latest published
35
+ ```
36
+
37
+ **Read the installed one, not the pin.** `oe upgrade` writes the pins before it installs, so an
38
+ upgrade that stopped part way leaves a manifest that names a version the app is not running.
39
+
40
+ The nine packages publish in lockstep, so one version answers for all of them. Agree the target
41
+ with the user before you go on. Taking the latest is the normal choice.
42
+
43
+ ## 2. Read the notes between the two versions
44
+
45
+ ```
46
+ npx oe upgrade --to <target> --plan
47
+ ```
48
+
49
+ It prints the window — every release above the installed version, up to the target — and writes
50
+ nothing. Each entry names:
51
+
52
+ | Field | What it means for this deployment |
53
+ | --- | --- |
54
+ | BREAKING | behaviour that changes. Read it before anything else. |
55
+ | CONFIG | a change to this app's own config files. A codemod applies some; the rest are yours. |
56
+ | ENV + / ENV - | an env NAME the deployment starts or stops needing. The admin sets the value. |
57
+ | MANUAL | a step outside the files — a dashboard change, a URL to re-paste, a key to rotate. |
58
+
59
+ The installed copy of the record cannot know about a release published after it, so `--plan`
60
+ says plainly which crossed versions it has no entry for. The full window is printed again in
61
+ step 3, after the install puts the target's own copy on disk. The same text is in
62
+ `node_modules/@open-everywhere/core/UPGRADING.md`.
63
+
64
+ **Stop and ask the user** when the window holds a breaking change, an env change or a manual step.
65
+ Those are decisions, not steps.
66
+
67
+ ## 3. Run the upgrade
68
+
69
+ ```
70
+ npx oe upgrade --to <target>
71
+ ```
72
+
73
+ In order, and it stops at the first step that fails:
74
+
75
+ 1. bump every `@open-everywhere/*` package to the target, renaming a dependency on the retired
76
+ unscoped `create-open-everywhere` to `@open-everywhere/create` as it goes;
77
+ 2. pin `eve` to the version the target core declares as its peer;
78
+ 3. `npm install` — its `postinstall` runs `oe-eve-patch`, which the app refuses to boot without;
79
+ 4. run the config codemods the target's notes name, and print the migrations that are yours;
80
+ 5. `oe build --accept` — this rewrites `roster.lock.json`;
81
+ 6. `npm run typecheck`;
82
+ 7. `npm run build`.
83
+
84
+ A failed step prints which one and leaves the tree where it stopped. Fix the cause and run
85
+ `oe upgrade` again: it RESUMES, from whichever step stopped it.
86
+
87
+ It can do that because it writes `.open-everywhere/upgrade-resume.json` just BEFORE the install
88
+ and deletes it only when the run completes. Before, not after: a failing `npm install` can still
89
+ leave the new packages on disk, because npm writes the tree first and runs `postinstall` after.
90
+ That file records the version the run started from, so the retry reads the SAME release notes,
91
+ runs the same codemods and takes the same refusals — a retry never quietly forgets a migration
92
+ you still owe. The directory is gitignored, so the marker never reaches a pull request, and it
93
+ survives `rm -rf node_modules && npm ci`.
94
+
95
+ Never delete the marker to make `oe upgrade` say there is nothing to do. It is the only record
96
+ that a run began taking the target and never proved the tree.
97
+
98
+ **If it refuses with "the release notes name codemods this CLI does not hold":** the codemod ships
99
+ in a newer core than the one you are running. Upgrade in ONE step to a version that holds it, or
100
+ apply those migrations by hand. Do not work around the refusal — it exists because a half-applied
101
+ migration that reports success is worse than a stop.
102
+
103
+ ## 4. Review the diff
104
+
105
+ ```
106
+ git diff roster.lock.json
107
+ git diff package.json
108
+ git status
109
+ ```
110
+
111
+ Read `roster.lock.json` line by line. A new mounted tool, channel, schedule or connection is a new
112
+ thing the agent can do. If a line surprises you, say so to the user before the pull request — this
113
+ is the review surface, and it is the only one.
114
+
115
+ Then run the app's own checks once more if anything above was fixed by hand:
116
+ `npm run typecheck && npm run build`.
117
+
118
+ ## 5. Open a pull request
119
+
120
+ Commit on a branch, never on the default branch. The body carries:
121
+
122
+ - the versions: `<installed> → <target>`, and the `eve` pin;
123
+ - the release-note window, as `oe upgrade` printed it;
124
+ - what changed in `roster.lock.json`, in your own words;
125
+ - **the env names the deployment needs before this merges**, names only;
126
+ - the manual steps, and who does each one.
127
+
128
+ Then stop. The admin reviews the lock diff and merges. The merge deploys.
129
+
130
+ ## 6. Confirm the deployment after it ships
131
+
132
+ A green build is not a working deployment.
133
+
134
+ **The status endpoint is not built yet.** OPE-2230 adds one: an unauthenticated, non-sensitive
135
+ JSON route that reports the deployment's version, whether the database is reachable and which
136
+ provider it uses, the sandbox backend, whether egress is enforced, whether the model route
137
+ answers, and the Slack posture. That ticket proposes `GET /eve/v1/oe/status`. Do not assume the
138
+ route exists, and never read some other route as if it were this one. Check the deployment's own
139
+ routes first; when the endpoint is there, read it and report each field, in this order:
140
+
141
+ 1. **version** — it reads the target. If it still reads the old version, the deploy has not
142
+ finished, or it failed. Nothing below is meaningful until this matches.
143
+ 2. **database reachable**, and the provider it names.
144
+ 3. **sandbox backend**, and **egress enforced**.
145
+ 4. **model route answers.**
146
+ 5. **Slack** — credentials present, workspace installed, events verified.
147
+
148
+ **Until that endpoint ships**, confirm what you can and say plainly what you could not:
149
+
150
+ - the deploy finished, from the host's own deployment log;
151
+ - `npx @open-everywhere/create --check --json --host https://<host>` — its `build-deploy` step
152
+ passes only on the deployed Slack route's own `401 unauthorized`, which proves boot and
153
+ routing;
154
+ - Slack's **Event Subscriptions** still shows **Verified**.
155
+
156
+ A fact that went from good to bad across the upgrade is the upgrade's fault until proven
157
+ otherwise: say so, and offer to roll the pull request back rather than patching forward on a live
158
+ deployment.
159
+
160
+ Last, ask the user to send the app a direct message. An answer is the only proof that holds.
@@ -0,0 +1,42 @@
1
+ # Dependencies
2
+ node_modules/
3
+
4
+ # Secrets. Keep .env.example: it carries variable names only.
5
+ # `.env*` and `.vercel` are the exact lines the Vercel CLI adds, so `vercel link` leaves this file alone.
6
+ .env*
7
+ !.env.example
8
+
9
+ # The Vercel project link
10
+ .vercel
11
+
12
+ # eve build output and local durable state
13
+ .eve/
14
+ .output/
15
+ .workflow-data/
16
+
17
+ # Local stores: the embedded operational database, the memory store, the wizard state
18
+ .open-everywhere-data/
19
+ .open-everywhere-data.lock
20
+ *.pglite.lock
21
+ .open-everywhere-memory/
22
+ .open-everywhere/
23
+ *.sqlite3
24
+ *.sqlite3-wal
25
+ *.sqlite3-shm
26
+
27
+ # The eve slot tree is `oe build` output, generated from roster.config.ts + roster.lock.json.
28
+ # Commit those two files, never the tree.
29
+ /agent/tools/
30
+ /agent/channels/
31
+ /agent/hooks/
32
+ /agent/schedules/
33
+ /agent/skills/
34
+ /agent/connections/
35
+ /agent/lib/providers.generated.ts
36
+
37
+ # Misc
38
+ *.log
39
+ .DS_Store
40
+ *.tsbuildinfo
41
+ *.pem
42
+ *.key
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "{{APP_NAME}}",
3
+ "version": "0.1.0",
4
+ "private": true,
5
+ "type": "module",
6
+ "engines": {
7
+ "node": "24.x"
8
+ },
9
+ "scripts": {
10
+ "postinstall": "oe-eve-patch",
11
+ "oe:build": "oe build",
12
+ "predev": "oe build",
13
+ "dev": "eve dev",
14
+ "prebuild": "oe build",
15
+ "build": "eve build",
16
+ "prestart": "oe build",
17
+ "start": "eve start",
18
+ "pretypecheck": "oe build",
19
+ "typecheck": "tsc --noEmit -p tsconfig.json",
20
+ "check": "create-open-everywhere --check",
21
+ "ops": "node --import tsx scripts/ops-mcp.ts",
22
+ "env:pipe": "node scripts/env-pipe.mjs"
23
+ },
24
+ "dependencies": {
25
+ "@modelcontextprotocol/sdk": "^1.29.0",
26
+ "@open-everywhere/adapters": "{{OE_VERSION}}",
27
+ "@open-everywhere/core": "{{OE_VERSION}}",
28
+ "@open-everywhere/provider-discord": "{{OE_VERSION}}",
29
+ "@open-everywhere/provider-github": "{{OE_VERSION}}",
30
+ "@open-everywhere/provider-linear": "{{OE_VERSION}}",
31
+ "@open-everywhere/provider-notion": "{{OE_VERSION}}",
32
+ "@open-everywhere/provider-slack": "{{OE_VERSION}}",
33
+ "@open-everywhere/provider-teams": "{{OE_VERSION}}",
34
+ "eve": "0.54.3",
35
+ "just-bash": "^3.1.0"
36
+ },
37
+ "devDependencies": {
38
+ "@open-everywhere/create": "{{OE_VERSION}}",
39
+ "@types/node": "^24.0.0",
40
+ "tsx": "^4.23.9",
41
+ "typescript": "^7.0.2"
42
+ },
43
+ "overrides": {
44
+ "zod": "4.5.4",
45
+ "@agent-browser/eve": {
46
+ "zod": "4.5.4"
47
+ },
48
+ "eve": {
49
+ "undici": "8.11.2",
50
+ "@ai-sdk/provider-utils": {
51
+ "undici": "7.30.0"
52
+ }
53
+ },
54
+ "guarded-fetch": {
55
+ "undici": "7.30.0"
56
+ }
57
+ },
58
+ "allowScripts": {
59
+ "esbuild": true,
60
+ "@mongodb-js/zstd": true
61
+ }
62
+ }
@@ -0,0 +1,39 @@
1
+ import { defineRoster } from "@open-everywhere/core/agent/scaffold/roster-config.js";
2
+
3
+ // THE ROSTER — what this agent can do. `oe build` reads this file and roster.lock.json, and writes
4
+ // the eve slot tree (agent/tools/, agent/channels/, agent/hooks/, …). The tree is build output and
5
+ // is not committed. This file and the lock are committed: they are the review surface.
6
+ //
7
+ // The lock is the REVIEWED roll-call. When an upgrade adds a contribution, `oe build` refuses until
8
+ // you decide about it here, then `npx oe build --accept` records the decision. Review the
9
+ // roster.lock.json diff like any other code change.
10
+ //
11
+ // `oe build` loads this file with Node's native type stripping, so keep it ERASABLE syntax only: no
12
+ // `enum`, no `namespace`, and `import type` for type-only imports.
13
+
14
+ export default defineRoster({
15
+ // eve's BUILT-INS. Absence KEEPS a built-in. Every line here takes a capability AWAY.
16
+ framework: {
17
+ disable: {
18
+ // Core re-provides these four per session grain (task sessions mount them, standing seats do
19
+ // not). The sentinel is what makes that provision authoritative: a dynamic tool can only
20
+ // shadow a static built-in, never remove it.
21
+ bash: "re-provided per session grain by core (tools/sandbox_tools.ts)",
22
+ read_file: "re-provided per session grain by core (tools/sandbox_tools.ts)",
23
+ web_fetch: "re-provided per session grain by core (tools/sandbox_tools.ts)",
24
+ write_file: "re-provided per session grain by core (tools/sandbox_tools.ts)",
25
+ },
26
+ },
27
+
28
+ // The portable runtime and the reference Vercel adapters: mount everything they offer.
29
+ core: true,
30
+ adapters: true,
31
+
32
+ // One provider bundle per surface. Add a line to add a surface (`discord`, `teams` and `linear`
33
+ // are installed too), then `npx oe build --accept`.
34
+ providers: {
35
+ slack: true,
36
+ notion: true,
37
+ github: true,
38
+ },
39
+ });
@@ -0,0 +1,182 @@
1
+ {
2
+ "schemaVersion": 1,
3
+ "generator": 1,
4
+ "framework": {
5
+ "bash": "disabled",
6
+ "read_file": "disabled",
7
+ "web_fetch": "disabled",
8
+ "write_file": "disabled"
9
+ },
10
+ "packages": {
11
+ "@open-everywhere/adapters": {
12
+ "version": "{{OE_VERSION}}",
13
+ "contributions": {
14
+ "hook/sandbox-lifecycle": "mounted",
15
+ "tool/extend_workspace_time": "mounted"
16
+ }
17
+ },
18
+ "@open-everywhere/core": {
19
+ "version": "{{OE_VERSION}}",
20
+ "contributions": {
21
+ "channel/aws-sso-callback": "mounted",
22
+ "channel/control-mcp": "mounted",
23
+ "channel/control-read": "mounted",
24
+ "channel/credential-intake-page": "mounted",
25
+ "channel/oe-oauth-callback": "mounted",
26
+ "channel/oe-status": "mounted",
27
+ "channel/policy-pages": "mounted",
28
+ "channel/test-wake": "mounted",
29
+ "channel/transcript-relay": "mounted",
30
+ "channel/unified": "mounted",
31
+ "channel/webhook-reveal-page": "mounted",
32
+ "channel/webhooks": "mounted",
33
+ "connection/notion": "mounted",
34
+ "hook/approval-raised": "mounted",
35
+ "hook/approval-settlement": "mounted",
36
+ "hook/binding-bridge": "mounted",
37
+ "hook/connector-audit": "mounted",
38
+ "hook/egress": "mounted",
39
+ "hook/eve-patch-gate": "mounted",
40
+ "hook/fire-carriage": "mounted",
41
+ "hook/fire-toolset": "mounted",
42
+ "hook/job-posture": "mounted",
43
+ "hook/lean-seat": "mounted",
44
+ "hook/learn": "mounted",
45
+ "hook/link-claim": "mounted",
46
+ "hook/log-flush": "mounted",
47
+ "hook/loop-breaker": "mounted",
48
+ "hook/memory": "mounted",
49
+ "hook/native-input-audit": "mounted",
50
+ "hook/own-account-ask": "mounted",
51
+ "hook/requester-identity": "mounted",
52
+ "hook/requester-messages": "mounted",
53
+ "hook/routine-outcome": "mounted",
54
+ "hook/routine-silence": "mounted",
55
+ "hook/session-park": "mounted",
56
+ "hook/spawn-taint": "mounted",
57
+ "hook/spend": "mounted",
58
+ "hook/stall-guard": "mounted",
59
+ "hook/telemetry": "mounted",
60
+ "hook/turn-anchor": "mounted",
61
+ "hook/wake-accounting-turn": "mounted",
62
+ "hook/wake-turn-start": "mounted",
63
+ "hook/window-routing": "mounted",
64
+ "schedule/directory-sync": "mounted",
65
+ "schedule/dispatch": "mounted",
66
+ "schedule/dream-mode3": "mounted",
67
+ "schedule/tidy": "mounted",
68
+ "skill/scoped": "mounted",
69
+ "tool/add_label": "mounted",
70
+ "tool/add_routine_rule": "mounted",
71
+ "tool/agent_version": "mounted",
72
+ "tool/assign": "mounted",
73
+ "tool/aws": "mounted",
74
+ "tool/browser_tools": "mounted",
75
+ "tool/cancel_routine": "mounted",
76
+ "tool/capture_events": "mounted",
77
+ "tool/check_pr_status": "mounted",
78
+ "tool/checkout_repo": "mounted",
79
+ "tool/clear_connector_override": "mounted",
80
+ "tool/clear_spend_limit": "mounted",
81
+ "tool/complete_job": "mounted",
82
+ "tool/complete_thread": "mounted",
83
+ "tool/confirm_link": "mounted",
84
+ "tool/connector": "mounted",
85
+ "tool/create_agent": "mounted",
86
+ "tool/create_routine": "mounted",
87
+ "tool/create_skill": "mounted",
88
+ "tool/create_ticket": "mounted",
89
+ "tool/declare_webhook": "mounted",
90
+ "tool/delete_skill": "mounted",
91
+ "tool/describe_image": "mounted",
92
+ "tool/dm_person": "mounted",
93
+ "tool/edit_reply": "mounted",
94
+ "tool/edit_routine": "mounted",
95
+ "tool/enable_routine": "mounted",
96
+ "tool/explain_permission": "mounted",
97
+ "tool/get_pr_feedback": "mounted",
98
+ "tool/grant_tools": "mounted",
99
+ "tool/halt": "mounted",
100
+ "tool/link_identity": "mounted",
101
+ "tool/list_recent_events": "mounted",
102
+ "tool/list_repos": "mounted",
103
+ "tool/list_routines": "mounted",
104
+ "tool/list_skills": "mounted",
105
+ "tool/list_webhooks": "mounted",
106
+ "tool/memory_admin_list": "mounted",
107
+ "tool/memory_admin_read": "mounted",
108
+ "tool/message_thread_seat": "mounted",
109
+ "tool/no_reply": "mounted",
110
+ "tool/open_pull_request": "mounted",
111
+ "tool/permission_fit_report": "mounted",
112
+ "tool/post_file": "mounted",
113
+ "tool/post_message": "mounted",
114
+ "tool/post_pr_walkthrough": "mounted",
115
+ "tool/purge_memory": "mounted",
116
+ "tool/query_analytics": "mounted",
117
+ "tool/react": "mounted",
118
+ "tool/read_channel": "mounted",
119
+ "tool/read_docs": "mounted",
120
+ "tool/read_file_upload": "mounted",
121
+ "tool/read_routine_transcript": "mounted",
122
+ "tool/read_thread": "mounted",
123
+ "tool/read_thread_seat": "mounted",
124
+ "tool/read_webhook_history": "mounted",
125
+ "tool/read_work_channel": "mounted",
126
+ "tool/read_work_thread": "mounted",
127
+ "tool/record_follow_up": "mounted",
128
+ "tool/record_job_state": "mounted",
129
+ "tool/record_watch_state": "mounted",
130
+ "tool/remove_routine_rule": "mounted",
131
+ "tool/reply": "mounted",
132
+ "tool/report_run_failed": "mounted",
133
+ "tool/request_access": "mounted",
134
+ "tool/request_credential_grant": "mounted",
135
+ "tool/resume": "mounted",
136
+ "tool/revoke_connector": "mounted",
137
+ "tool/revoke_credential_grant": "mounted",
138
+ "tool/revoke_routine_permissions": "mounted",
139
+ "tool/rotate_webhook": "mounted",
140
+ "tool/run_routine_now": "mounted",
141
+ "tool/sandbox_tools": "mounted",
142
+ "tool/search": "mounted",
143
+ "tool/session_cost": "mounted",
144
+ "tool/set_dm_delivery": "mounted",
145
+ "tool/set_spend_limit": "mounted",
146
+ "tool/set_state": "mounted",
147
+ "tool/spawn_thread_session": "mounted",
148
+ "tool/spend_report": "mounted",
149
+ "tool/stand_down": "mounted",
150
+ "tool/subscribe_pr": "mounted",
151
+ "tool/unlink_identity": "mounted",
152
+ "tool/update_status": "mounted",
153
+ "tool/usage_report": "mounted",
154
+ "tool/walk_pr": "mounted"
155
+ }
156
+ },
157
+ "@open-everywhere/provider-github": {
158
+ "version": "{{OE_VERSION}}",
159
+ "contributions": {
160
+ "channel/github": "mounted"
161
+ }
162
+ },
163
+ "@open-everywhere/provider-notion": {
164
+ "version": "{{OE_VERSION}}",
165
+ "contributions": {
166
+ "channel/notion": "mounted",
167
+ "schedule/notion-ingress": "mounted",
168
+ "tool/notion_search": "mounted",
169
+ "tool/read_notion_comments": "mounted",
170
+ "tool/read_notion_page": "mounted"
171
+ }
172
+ },
173
+ "@open-everywhere/provider-slack": {
174
+ "version": "{{OE_VERSION}}",
175
+ "contributions": {
176
+ "channel/slack": "mounted",
177
+ "channel/slack-commands": "mounted",
178
+ "channel/slack-setup-page": "mounted"
179
+ }
180
+ }
181
+ }
182
+ }
@@ -0,0 +1,74 @@
1
+ // Write one value to stdout for a pipe, so it reaches `vercel env add` without being printed:
2
+ //
3
+ // npm run -s env:pipe -- SLACK_BOT_TOKEN | npx vercel env add SLACK_BOT_TOKEN production
4
+ // npm run -s env:pipe -- OE_PUBLIC_BASE_URL=https://agent.example.com | npx vercel env add OE_PUBLIC_BASE_URL production
5
+ //
6
+ // `NAME` reads NAME from .env.local in the current directory. `NAME=value` writes that literal value.
7
+ // The value goes out with no trailing newline, because a stored newline becomes part of the value.
8
+ //
9
+ // ALWAYS pipe it straight into `vercel env add`. Never run it bare. It writes only to a PIPE: a
10
+ // terminal, a file or anything else is refused. That is not a guarantee that no person or agent sees
11
+ // the value. An agent's shell and Git Bash's mintty terminal both connect stdout to a pipe, so a bare
12
+ // run there passes this check and prints the value. The pipe into `vercel env add` is what keeps it
13
+ // out of sight.
14
+ //
15
+ // It reads only .env.local, never the shell's own environment, so a variable that happens to be
16
+ // exported in this shell is never sent by mistake. It parses the file with `node:util` parseEnv, the
17
+ // parser eve uses for .env.local, so quotes, `export ` prefixes and ` # comment` tails are
18
+ // stripped exactly as the running app strips them.
19
+
20
+ import { fstatSync, readFileSync } from "node:fs";
21
+ import { join } from "node:path";
22
+ import { parseEnv } from "node:util";
23
+
24
+ const arg = process.argv[2];
25
+ if (arg === undefined || process.argv.length > 3) {
26
+ console.error("usage: npm run -s env:pipe -- <NAME | NAME=value> | npx vercel env add <NAME> production");
27
+ process.exit(2);
28
+ }
29
+ // What counts as a pipe, per platform:
30
+ // • a FIFO — what a shell `|` gives on Linux and macOS (`isFIFO()`);
31
+ // • a socket — what Node's own `spawn(…, { stdio: "pipe" })` gives on Linux and macOS (a
32
+ // socketpair), so a parent process that reads the value directly is a pipe too;
33
+ // • on Windows, a named pipe. Node reports it with the POSIX S_IFIFO bits in `mode`, but
34
+ // `fs.constants.S_IFIFO` is undefined there, so `isFIFO()` answers false. Only on Windows
35
+ // are the mode bits read by hand.
36
+ const S_IFMT = 0o170000;
37
+ const S_IFIFO = 0o010000;
38
+ let isPipe = false;
39
+ try {
40
+ const st = fstatSync(1);
41
+ isPipe = st.isFIFO() || st.isSocket() || (process.platform === "win32" && (st.mode & S_IFMT) === S_IFIFO);
42
+ } catch {
43
+ isPipe = false;
44
+ }
45
+ if (!isPipe) {
46
+ console.error("env:pipe writes a secret value, so it writes only to a pipe. Pipe it straight into `npx vercel env add <NAME> production`.");
47
+ process.exit(2);
48
+ }
49
+
50
+ const eq = arg.indexOf("=");
51
+ const name = eq >= 0 ? arg.slice(0, eq) : arg;
52
+ if (!/^[A-Z][A-Z0-9_]*$/.test(name)) {
53
+ console.error(`env:pipe: "${name}" is not an environment variable name`);
54
+ process.exit(2);
55
+ }
56
+
57
+ let value;
58
+ if (eq >= 0) {
59
+ value = arg.slice(eq + 1);
60
+ } else {
61
+ let text;
62
+ try {
63
+ text = readFileSync(join(process.cwd(), ".env.local"), "utf8");
64
+ } catch {
65
+ console.error("env:pipe: no .env.local in this directory");
66
+ process.exit(1);
67
+ }
68
+ value = parseEnv(text)[name];
69
+ }
70
+ if (value === undefined || value === "") {
71
+ console.error(`env:pipe: ${name} has no value${eq >= 0 ? "" : " in .env.local"}`);
72
+ process.exit(1);
73
+ }
74
+ process.stdout.write(value);
@@ -0,0 +1,35 @@
1
+ // The ops / setup MCP server for this app, on stdio. `.mcp.json` registers it as
2
+ // `open-everywhere-ops`, so a coding agent opened in this directory (Claude Code, for one) can
3
+ // read setup status, write `.env.local` values and load secrets into the credential store.
4
+ //
5
+ // Core's server is provider-blind: each surface's app manifest and preflight checks register from
6
+ // its provider bundle. Register the bundles this app's roster mounts, then serve.
7
+ //
8
+ // stdout IS the MCP transport. Diagnostics go to stderr.
9
+
10
+ import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
11
+ import { buildOpsServer } from "@open-everywhere/core/agent/ops/server.js";
12
+ import { registerSlackOps } from "@open-everywhere/provider-slack/agent/ops.js";
13
+ import { registerGithubOps } from "@open-everywhere/provider-github/agent/ops.js";
14
+ import { registerSurfaceTrustPreflight } from "@open-everywhere/core/agent/identity/trust-preflight.js";
15
+ import { importAppModule, resolveAppRoot } from "@open-everywhere/core/agent/scaffold/app-root.js";
16
+
17
+ // The app root: `OE_APP_ROOT`, else the nearest directory above the working directory that holds
18
+ // package.json and agent/agent.ts.
19
+ const APP_ROOT = resolveAppRoot();
20
+ // Populate the trust register BEFORE the trust preflight registers: an empty register would report
21
+ // every surface with traffic as undeclared.
22
+ await importAppModule("agent/identity/surfaces.ts", APP_ROOT);
23
+
24
+ registerSlackOps();
25
+ registerGithubOps();
26
+ // Added a surface to roster.config.ts? Register its ops arm too:
27
+ // import { registerTeamsOps } from "@open-everywhere/provider-teams/agent/ops.js";
28
+ // import { registerDiscordOps } from "@open-everywhere/provider-discord/agent/ops.js";
29
+ registerSurfaceTrustPreflight();
30
+
31
+ const server = buildOpsServer();
32
+ await server.connect(new StdioServerTransport());
33
+ process.stderr.write(
34
+ "open-everywhere-ops MCP server ready on stdio (preflight · surface_manifest · scaffold_env · scaffold_credential_key · secret_set/list/rm)\n",
35
+ );
@@ -0,0 +1,23 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2023",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": [
7
+ "ES2023"
8
+ ],
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "noEmit": true,
13
+ "resolveJsonModule": true,
14
+ "types": [
15
+ "node"
16
+ ]
17
+ },
18
+ "include": [
19
+ "agent/**/*.ts",
20
+ "scripts/**/*.ts",
21
+ "roster.config.ts"
22
+ ]
23
+ }