@open-everywhere/create 0.5.0 → 0.6.0
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/README.md +1 -1
- package/package.json +3 -3
- package/src/scaffold.ts +2 -2
- package/template/agent/access/bundles.ts +6 -0
- package/template/agent/access/domain-rules.ts +18 -0
- package/template/agent/agent.ts +7 -0
- package/template/agent/email/policy.ts +40 -0
- package/template/agent/email/senders.ts +14 -0
- package/template/agent/lib/register-config.ts +12 -0
- package/template/agent/meetings/policy.ts +44 -0
- package/template/agent/model/models.ts +3 -1
- package/template/agent/model/stacks.ts +32 -1
- package/template/agent/personal-browser/policy.ts +33 -0
- package/template/agent/spend/model-pricing.ts +1 -1
- package/template/claude/skills/upgrade-open-everywhere/SKILL.md +1 -1
- package/template/gitignore +4 -0
- package/template/package.json +1 -0
- package/template/roster.config.ts +2 -2
- package/template/roster.lock.json +12 -0
- package/template/scripts/goldens/roster-plan.txt +12 -0
- package/template/scripts/ops-mcp.ts +1 -1
package/README.md
CHANGED
|
@@ -58,7 +58,7 @@ prompts. The directory must be new or empty. A fresh clone of an empty repositor
|
|
|
58
58
|
and it counts as empty: run `npx @open-everywhere/create .` inside it. The scaffold refuses a
|
|
59
59
|
directory that holds anything else. Run inside an empty clone named `my-agent`,
|
|
60
60
|
`npx @open-everywhere/create my-agent` would make `my-agent/my-agent/`, so it refuses and prints the
|
|
61
|
-
`.` command instead. To nest on purpose, create the inner directory first. The app depends on the
|
|
61
|
+
`.` command instead. To nest on purpose, create the inner directory first. The app depends on the nine `@open-everywhere/*` libraries at
|
|
62
62
|
this CLI's own version — plus this package itself, as a dev dependency, for its `check` script — and
|
|
63
63
|
on `eve` at the pin core declares; its `postinstall` applies the eve patch. Its roster mounts the launch surfaces: Slack, Notion and GitHub. The app carries `AGENTS.md`,
|
|
64
64
|
a `.mcp.json` for the `open-everywhere-ops` MCP server and the `quickstart-open-everywhere` skill,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@open-everywhere/create",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"license": "Apache-2.0",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "npx scaffold and setup check for Open Everywhere — one step engine, reported by --check for an agent-led setup.",
|
|
@@ -46,8 +46,8 @@
|
|
|
46
46
|
"test:env-pipe": "tsx scripts/env-pipe-test.ts"
|
|
47
47
|
},
|
|
48
48
|
"dependencies": {
|
|
49
|
-
"@open-everywhere/core": "0.
|
|
50
|
-
"@open-everywhere/provider-slack": "0.
|
|
49
|
+
"@open-everywhere/core": "0.6.0",
|
|
50
|
+
"@open-everywhere/provider-slack": "0.6.0",
|
|
51
51
|
"tsx": "^4.23.9"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
package/src/scaffold.ts
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// THE SCAFFOLD — `npx @open-everywhere/create <dir>` copies the quickstart app (this package's
|
|
2
2
|
// `template/` directory) into a new or empty `<dir>`, and then prints the next steps.
|
|
3
3
|
//
|
|
4
|
-
// The template is a minimal npm-consumer app: the
|
|
4
|
+
// The template is a minimal npm-consumer app: the nine `@open-everywhere/*` libraries and `eve`,
|
|
5
5
|
// a roster of the launch surfaces (Slack, Notion, GitHub), and the agent config. Every
|
|
6
6
|
// `@open-everywhere/*` dependency, `@open-everywhere/create` itself, and the versions in
|
|
7
7
|
// `roster.lock.json` carry the {@link VERSION_PLACEHOLDER}. The scaffold replaces it with this
|
|
8
|
-
// CLI's own version: all
|
|
8
|
+
// CLI's own version: all ten packages publish in lockstep, so this CLI's version IS the version
|
|
9
9
|
// of every library it installs.
|
|
10
10
|
//
|
|
11
11
|
// THREE PACKING RULES SHAPE THE TEMPLATE:
|
|
@@ -17,8 +17,10 @@ import {
|
|
|
17
17
|
type Bundle,
|
|
18
18
|
} from "@open-everywhere/core/agent/access/bundle.js";
|
|
19
19
|
import { mcpServerBindings, mcpServerBundles } from "@open-everywhere/core/agent/connections/mcp-servers.js";
|
|
20
|
+
import { domainRuleBindings, domainRuleBundles } from "@open-everywhere/core/agent/access/domain-rules.js";
|
|
20
21
|
import { loadGrantsOverlay } from "./grants.js";
|
|
21
22
|
import { MCP_SERVERS } from "./mcp-servers.js";
|
|
23
|
+
import { DOMAIN_RULES } from "./domain-rules.js";
|
|
22
24
|
import { PRE_APPROVAL_RULES } from "./pre-approval-rules.js";
|
|
23
25
|
import { loadAgentsOverlay } from "../memory/config/agents-overlay.js";
|
|
24
26
|
import { loadGroups } from "../identity/groups.js";
|
|
@@ -66,6 +68,10 @@ const bindings: Binding[] = [
|
|
|
66
68
|
// every person's OWN DM (the built-in `oe:everyone` group, or the groups the entry names). Never a channel.
|
|
67
69
|
bundles.push(...mcpServerBundles(MCP_SERVERS));
|
|
68
70
|
bindings.push(...mcpServerBindings(MCP_SERVERS));
|
|
71
|
+
// The domain rules people asked for from approval cards and an admin merged (./domain-rules.ts, OPE-2456): each
|
|
72
|
+
// domain's rules in one bundle, bound at that domain's scope only.
|
|
73
|
+
bundles.push(...domainRuleBundles(DOMAIN_RULES));
|
|
74
|
+
bindings.push(...domainRuleBindings(DOMAIN_RULES));
|
|
69
75
|
|
|
70
76
|
const overlay = loadGrantsOverlay();
|
|
71
77
|
const agentsOverlay = loadAgentsOverlay();
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Domain rules — the acts one domain's people asked to allow without a card, merged by an admin.
|
|
2
|
+
//
|
|
3
|
+
// A person in a domain room can choose "Approve, and allow things like this" on an approval card. After they confirm
|
|
4
|
+
// the rule in plain words, the agent opens a pull request that adds one line here (or widens the line for the same
|
|
5
|
+
// tool and kind of action). Nothing applies until an admin merges it. The pull request names who asked, from which
|
|
6
|
+
// card, and quotes the act.
|
|
7
|
+
//
|
|
8
|
+
// Each line is ONE JSON entry: the domain, a stable id, the rule the approval judge reads, and the structured policy
|
|
9
|
+
// the rule was written from. A rule states policy — the tool, the kind of action, the kind of object — and never one
|
|
10
|
+
// object: config load refuses a rule that names a URL, an id or a numbered item. Delete a line to remove its rule.
|
|
11
|
+
// Keep one entry per line, with a trailing comma: the agent's pull requests edit this file line by line.
|
|
12
|
+
//
|
|
13
|
+
// The full reference is docs/how-it-works/pre-approval-rules.md in the Open Everywhere repository.
|
|
14
|
+
|
|
15
|
+
import { defineDomainRules } from "@open-everywhere/core/agent/access/domain-rules.js";
|
|
16
|
+
|
|
17
|
+
export const DOMAIN_RULES = defineDomainRules([
|
|
18
|
+
]);
|
package/template/agent/agent.ts
CHANGED
|
@@ -22,6 +22,7 @@ import "./lib/register-adapters.js";
|
|
|
22
22
|
import "@open-everywhere/core/agent/access/eve-patch-probe-boot.js";
|
|
23
23
|
import { gatewayModelResolver } from "@open-everywhere/adapters/agent/model/gateway.js";
|
|
24
24
|
import { registerGatewayDreamJudge, registerGatewayFailureFacetJudge } from "@open-everywhere/adapters/agent/model/dream-judge.js";
|
|
25
|
+
import { registerGatewayMeetingModels } from "@open-everywhere/adapters/agent/model/meeting-gateway.js";
|
|
25
26
|
import { registerGatewayApprovalJudge } from "@open-everywhere/adapters/agent/model/approval-judge.js";
|
|
26
27
|
import { registerGatewayImageDescriber } from "@open-everywhere/adapters/agent/model/gateway-vision.js";
|
|
27
28
|
import { isModelUsable } from "@open-everywhere/core/agent/model/policy.js";
|
|
@@ -29,6 +30,7 @@ import {
|
|
|
29
30
|
JUDGE_MODEL,
|
|
30
31
|
PRIMARY_MODEL,
|
|
31
32
|
PRIMARY_MODEL_CONTEXT_WINDOW_TOKENS,
|
|
33
|
+
TRANSCRIPTION_ROLE,
|
|
32
34
|
UTILITY_MODEL,
|
|
33
35
|
VISION_MODEL,
|
|
34
36
|
} from "./model/models.js";
|
|
@@ -52,6 +54,11 @@ const COMPACTION_THRESHOLD_TOKENS = compactionThresholdTokens(PRIMARY_MODEL_CONT
|
|
|
52
54
|
// The background judges: memory distillation, failure facets and the auto-approval judge.
|
|
53
55
|
registerGatewayDreamJudge({ id: UTILITY_MODEL, gateway: GATEWAY_DEFAULTS });
|
|
54
56
|
registerGatewayFailureFacetJudge({ id: UTILITY_MODEL, gateway: GATEWAY_DEFAULTS });
|
|
57
|
+
|
|
58
|
+
// The meeting bot's model calls (OPE-2459): the `gateway` transcription route, and the tool-less recap
|
|
59
|
+
// completion on the same `utility` route as the dream judge. Inert until agent/meetings/policy.ts enables
|
|
60
|
+
// meetings; without this line the `gateway` route is unregistered and `meeting_join` refuses before its card.
|
|
61
|
+
registerGatewayMeetingModels({ id: UTILITY_MODEL, gateway: GATEWAY_DEFAULTS }, TRANSCRIPTION_ROLE);
|
|
55
62
|
registerGatewayApprovalJudge({ id: JUDGE_MODEL, gateway: GATEWAY_DEFAULTS });
|
|
56
63
|
|
|
57
64
|
// The image describer. Fail at boot if the org model policy forbids the vision model, rather than
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// THIS DEPLOYMENT'S EMAIL POLICY — the agent's own email address (OPE-2440). Config-as-code: a change here is a
|
|
2
|
+
// reviewed pull request. The schema and its validation are `@open-everywhere/core/agent/email/policy.js`; the
|
|
3
|
+
// operator guide is the "Email" surface page of the manual (`read_docs`).
|
|
4
|
+
//
|
|
5
|
+
// Each field is a decision about who may write to the agent:
|
|
6
|
+
// enabled — the master switch. Off refuses every inbound mail.
|
|
7
|
+
// transport — the registered transport that carries the mail ("agentmail" or "agentmail-eu" ship).
|
|
8
|
+
// orgDomains — the mail domains this org controls. Every inbox must sit on one of them (white-label: OE
|
|
9
|
+
// never hands out an address on a domain it runs), and an authenticated sender on one of
|
|
10
|
+
// them binds internal. Everyone else binds external.
|
|
11
|
+
// inboxes — `room`: mail wakes the domain whose `reach` lists `email/<domain>/<local part>`.
|
|
12
|
+
// `personal`: mail from a person declared in agent/identity/principals.ts (ids.email) wakes
|
|
13
|
+
// that person's own DM seat.
|
|
14
|
+
// allowedSenders — who may write to a room inbox: exact addresses or "*@domain". Add one by asking the agent
|
|
15
|
+
// (an approval card opens a pull request to agent/email/senders.ts) or by hand here.
|
|
16
|
+
// maxRecipients — the most addresses one reply may go to (a reply-all is limited to people allowed anyway).
|
|
17
|
+
//
|
|
18
|
+
// 🔴 NOTHING HERE IS A SECRET. The transport's API key and webhook secret live in the secret store
|
|
19
|
+
// (`oe secret set AGENTMAIL_API_KEY`, `oe secret set AGENTMAIL_WEBHOOK_SECRET`), never in this file.
|
|
20
|
+
|
|
21
|
+
import { DEFAULT_EMAIL_POLICY, registerEmailPolicy, type EmailPolicy } from "@open-everywhere/core/agent/email/policy.js";
|
|
22
|
+
import { EMAIL_SENDERS } from "./senders.js";
|
|
23
|
+
|
|
24
|
+
const emailPolicy: EmailPolicy = {
|
|
25
|
+
...DEFAULT_EMAIL_POLICY,
|
|
26
|
+
enabled: false,
|
|
27
|
+
transport: "agentmail",
|
|
28
|
+
orgDomains: [
|
|
29
|
+
// Your own mail domain(s). Example, inert while `enabled` is false:
|
|
30
|
+
// "acme.com",
|
|
31
|
+
],
|
|
32
|
+
inboxes: [
|
|
33
|
+
// Example inboxes, inert while `enabled` is false. Put the room inbox's surface key
|
|
34
|
+
// ("email/agent.acme.com/launch") in the launch domain's `reach`.
|
|
35
|
+
// { address: "launch@agent.acme.com", kind: "room", allowedSenders: ["*@acme.com"], why: "The launch team's shared inbox." },
|
|
36
|
+
// { address: "oe@agent.acme.com", kind: "personal", allowedSenders: [], why: "Each person's own chief of staff by email." },
|
|
37
|
+
],
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
registerEmailPolicy(emailPolicy, EMAIL_SENDERS);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Email senders — the allowed senders people asked to add to a room inbox, merged by an admin (OPE-2440).
|
|
2
|
+
//
|
|
3
|
+
// A person asks the agent to let someone email a room inbox. The agent posts an approval card; a tap opens a pull
|
|
4
|
+
// request that adds one line here. Nothing applies until an admin merges it. The pull request names who asked and
|
|
5
|
+
// who approved.
|
|
6
|
+
//
|
|
7
|
+
// Each line is ONE JSON entry: the room inbox, the sender (an exact address or "*@domain"), why, and the
|
|
8
|
+
// provenance. Delete a line to remove the sender. Keep one entry per line, with a trailing comma: the agent's pull
|
|
9
|
+
// requests edit this file line by line. The inbox must be a room inbox declared in ./policy.ts, or the boot fails.
|
|
10
|
+
|
|
11
|
+
import { defineEmailSenders } from "@open-everywhere/core/agent/email/policy.js";
|
|
12
|
+
|
|
13
|
+
export const EMAIL_SENDERS = defineEmailSenders([
|
|
14
|
+
]);
|
|
@@ -62,6 +62,18 @@ import "../identity/surfaces.js";
|
|
|
62
62
|
// `agent/sandbox/sandbox.ts` through this module's import and nothing else. Drop this import and the
|
|
63
63
|
// declaration is empty at bake time, so the capability silently refuses to arm.
|
|
64
64
|
import "../access/browser-hosts.js";
|
|
65
|
+
// Side effect: register this deployment's MEETING POLICY (agent/meetings/policy.ts, OPE-2459) — which
|
|
66
|
+
// meeting hosts the bot may join, the retention windows, the bot's box and the transcription route. Off
|
|
67
|
+
// unless the file enables it; a bad policy fails the boot rather than arming a bot nobody reviewed.
|
|
68
|
+
import "../meetings/policy.js";
|
|
69
|
+
// Side effect: register this deployment's EMAIL POLICY (agent/email/policy.ts, OPE-2440) — the agent's own
|
|
70
|
+
// inboxes, who may write to each, and how wide a reply may go. Off unless the file enables it; a bad policy
|
|
71
|
+
// (an inbox off the org's domains, a bare wildcard sender, a sender line naming no room inbox) fails the boot.
|
|
72
|
+
import "../email/policy.js";
|
|
73
|
+
// Side effect: register this deployment's PERSONAL BROWSER POLICY (agent/personal-browser/policy.ts, OPE-2441) —
|
|
74
|
+
// whether a person may have their own browser that keeps their logins, its box, and how long its sessions,
|
|
75
|
+
// logins, take-overs and act approvals last. Off unless the file enables it; a bad policy fails the boot.
|
|
76
|
+
import "../personal-browser/policy.js";
|
|
65
77
|
// Side effect: register the operator's per-AUTHOR trust register (identity/author-trust.ts) — the
|
|
66
78
|
// AUTHORITY plane, the sibling of the surfaces AUDIENCE plane above. Self-registering, and it must
|
|
67
79
|
// come AFTER the groups module loads (it expands `{ group: … }` members through loadGroups at
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// THIS DEPLOYMENT'S MEETING POLICY — OE's own meeting bot (OPE-2459). Config-as-code: a change here is a
|
|
2
|
+
// reviewed pull request. The schema and its validation are `@open-everywhere/core/agent/meetings/policy.js`;
|
|
3
|
+
// the operator guide is the "Meetings" page of the manual (`read_docs`).
|
|
4
|
+
//
|
|
5
|
+
// Each field is a decision about other people's meetings:
|
|
6
|
+
// enabled — the master switch. Off refuses every "join this meeting" ask.
|
|
7
|
+
// hosts — the meeting hosts the bot may join. A Teams rule lists the organiser tenants OE may
|
|
8
|
+
// join; the tenant id is read from the link and is not verified with Microsoft, so it
|
|
9
|
+
// refuses an outside link pasted as it is, not an edited one. A Meet link names no
|
|
10
|
+
// organiser, so a Meet rule must accept that in writing (`owner: "unverifiable"`).
|
|
11
|
+
// retention — how long OE keeps audio (0 = never stored) and the transcript.
|
|
12
|
+
// box — the bot image and its size. It runs on this deployment's own sandbox backend.
|
|
13
|
+
// transcription — `gateway` (audio through this deployment's AI Gateway) or `box` (text only).
|
|
14
|
+
// native — recaps from the platform's OWN transcript (Teams, Meet, Zoom), no bot (OPE-2471). Each
|
|
15
|
+
// platform block names the ORGANISATION's credential: identifiers here, the secret's value
|
|
16
|
+
// in the db credential store (`oe secret set <name>`). Off until OPE-2461 and OPE-2464 land.
|
|
17
|
+
//
|
|
18
|
+
// 🔴 NOTHING HERE IS A SECRET. A tenant id, a client id and a secret's NAME are identifiers, not credentials.
|
|
19
|
+
//
|
|
20
|
+
// To turn meetings on: build and publish the bot image (the manual's Meetings page says how), set
|
|
21
|
+
// `box.image`, add your host rules, and set `enabled: true`. Until OPE-2461 (per-row expiry for the shared
|
|
22
|
+
// store) and OPE-2464 (untrusted provenance for the recap post) land, `enabled: true` is REFUSED: the boot
|
|
23
|
+
// fails and names both tickets.
|
|
24
|
+
|
|
25
|
+
import { DEFAULT_MEETING_POLICY, registerMeetingPolicy, type MeetingPolicy } from "@open-everywhere/core/agent/meetings/policy.js";
|
|
26
|
+
|
|
27
|
+
const meetingPolicy: MeetingPolicy = {
|
|
28
|
+
...DEFAULT_MEETING_POLICY,
|
|
29
|
+
enabled: false,
|
|
30
|
+
hosts: [
|
|
31
|
+
// Example rules, inert while `enabled` is false. Replace the tenant id with your own.
|
|
32
|
+
// { platform: "meet", host: "meet.google.com", owner: "unverifiable", why: "Our team meets on Google Meet." },
|
|
33
|
+
// { platform: "teams", host: "teams.microsoft.com", tenants: ["00000000-0000-0000-0000-000000000000"], why: "Our own Teams tenant only." },
|
|
34
|
+
],
|
|
35
|
+
native: {
|
|
36
|
+
...DEFAULT_MEETING_POLICY.native,
|
|
37
|
+
// Example blocks, inert while `native.enabled` is false. See the manual's Meetings page for what each admin grants.
|
|
38
|
+
// teams: { tenants: ["00000000-0000-0000-0000-000000000000"], clientId: "00000000-0000-0000-0000-000000000000", clientSecretRef: "TEAMS_TRANSCRIPT_SECRET", why: "Our own Teams meetings." },
|
|
39
|
+
// meet: { domains: ["example.org"], serviceAccountKeyRef: "MEET_TRANSCRIPT_KEY", why: "Our own Workspace meetings." },
|
|
40
|
+
// zoom: { accountId: "<Zoom account id>", clientId: "<S2S app client id>", clientSecretRef: "ZOOM_TRANSCRIPT_SECRET", why: "Our own Zoom account." },
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
registerMeetingPolicy(meetingPolicy);
|
|
@@ -8,7 +8,7 @@ import {
|
|
|
8
8
|
} from "@open-everywhere/core/agent/model/default-model.js";
|
|
9
9
|
import { getSettings } from "@open-everywhere/core/agent/settings/settings.js";
|
|
10
10
|
import { SETTINGS_OVERRIDES } from "../settings/settings.js";
|
|
11
|
-
import { resolveStack, type ModelRole, type ModelRoleSpec, type ModelStack } from "./stacks.js";
|
|
11
|
+
import { resolveStack, resolveTranscription, type ModelRole, type ModelRoleSpec, type ModelStack } from "./stacks.js";
|
|
12
12
|
|
|
13
13
|
export type { ModelRoleSpec, ModelStack } from "./stacks.js";
|
|
14
14
|
|
|
@@ -31,6 +31,8 @@ export const MODELS = {
|
|
|
31
31
|
|
|
32
32
|
/** The alias of the stack this process resolved — for `/oe status`. */
|
|
33
33
|
export const MODEL_STACK = STACK_ALIAS;
|
|
34
|
+
/** The meeting bot's speech-to-text role: a primary and a fallback route (stacks.ts TRANSCRIPTION). */
|
|
35
|
+
export const TRANSCRIPTION_ROLE = resolveTranscription(STACK_ALIAS);
|
|
34
36
|
|
|
35
37
|
export const PRIMARY_MODEL = MODELS.primary.id;
|
|
36
38
|
export const UTILITY_MODEL = MODELS.utility.id;
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
// agent/spend/model-pricing.ts, or a USD spend cap cannot see its cost.
|
|
13
13
|
|
|
14
14
|
import type { ModelTier } from "@open-everywhere/core/agent/memory/domain.js";
|
|
15
|
+
import type { TranscriptionRoleSpec } from "@open-everywhere/adapters/agent/model/transcription-routes.js";
|
|
15
16
|
|
|
16
17
|
export type ModelRole = "primary" | "utility" | "vision" | "supervisor" | "judge";
|
|
17
18
|
|
|
@@ -35,7 +36,7 @@ export const STACKS = {
|
|
|
35
36
|
"american-closed": {
|
|
36
37
|
primary: { id: "openai/gpt-6-luna", tier: "high", contextWindowTokens: 1_050_000 },
|
|
37
38
|
utility: { id: "openai/gpt-6-luna", tier: "low", contextWindowTokens: 1_050_000 },
|
|
38
|
-
vision: { id: "google/gemini-3.
|
|
39
|
+
vision: { id: "google/gemini-3.8-flash", tier: "low", contextWindowTokens: 1_000_000 },
|
|
39
40
|
supervisor: { id: "openai/gpt-6-luna", tier: "low", contextWindowTokens: 1_050_000 },
|
|
40
41
|
judge: { id: "openai/gpt-6-luna", tier: "low", contextWindowTokens: 1_050_000 },
|
|
41
42
|
},
|
|
@@ -73,3 +74,33 @@ export function resolveStack(alias: string, overrides: StackOverrides = {}): Mod
|
|
|
73
74
|
}
|
|
74
75
|
return out;
|
|
75
76
|
}
|
|
77
|
+
|
|
78
|
+
// Speech to text for the meeting bot: a primary and a fallback route per stack, on two different providers, so
|
|
79
|
+
// one provider outage falls through to the other. A route names its transport too: the AI Gateway, DeepInfra
|
|
80
|
+
// (key: `oe secret set DEEPINFRA_API_KEY`), or your own OpenAI-compatible speech server. These defaults are
|
|
81
|
+
// pending a bake-off (`npm run bakeoff:stt` in the Open Everywhere repository).
|
|
82
|
+
export const TRANSCRIPTION = {
|
|
83
|
+
"chinese-open-weights": {
|
|
84
|
+
primary: { via: "deepinfra", id: "Qwen/Qwen3-ASR-1.7B" },
|
|
85
|
+
fallback: { via: "self-hosted", id: "Qwen/Qwen3-ASR-1.7B", baseUrl: "http://qwen3-asr:8000/v1" },
|
|
86
|
+
},
|
|
87
|
+
"american-closed": {
|
|
88
|
+
primary: { via: "gateway", id: "microsoft/mai-transcribe-2" },
|
|
89
|
+
fallback: { via: "gateway", id: "spacexai/grok-stt" },
|
|
90
|
+
},
|
|
91
|
+
} as const satisfies Record<StackAlias, TranscriptionRoleSpec>;
|
|
92
|
+
|
|
93
|
+
/** Fully local: your own speech server only. For a Docker deployment with no cloud model. */
|
|
94
|
+
export const LOCAL_TRANSCRIPTION = {
|
|
95
|
+
primary: { via: "self-hosted", id: "Qwen/Qwen3-ASR-1.7B", baseUrl: "http://qwen3-asr:8000/v1" },
|
|
96
|
+
} as const satisfies TranscriptionRoleSpec;
|
|
97
|
+
|
|
98
|
+
/** `stack` follows `models.stack`; `local` uses LOCAL_TRANSCRIPTION. */
|
|
99
|
+
export const TRANSCRIPTION_PLACEMENT: "stack" | "local" = "stack";
|
|
100
|
+
|
|
101
|
+
/** The transcription role for `alias`. Throws on an unknown alias. */
|
|
102
|
+
export function resolveTranscription(alias: string, placement: "stack" | "local" = TRANSCRIPTION_PLACEMENT): TranscriptionRoleSpec {
|
|
103
|
+
if (placement === "local") return LOCAL_TRANSCRIPTION;
|
|
104
|
+
if (!isStackAlias(alias)) throw new Error(`open-everywhere: unknown model stack "${alias}" — no transcription role`);
|
|
105
|
+
return TRANSCRIPTION[alias];
|
|
106
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// THIS DEPLOYMENT'S PERSONAL BROWSER POLICY — each person's own browser, which keeps their logins (OPE-2441).
|
|
2
|
+
// Config-as-code: a change here is a reviewed pull request. The schema and its validation are
|
|
3
|
+
// `@open-everywhere/core/agent/personal-browser/policy.js`; the operator guide is the "Personal browser" page
|
|
4
|
+
// of the manual (`read_docs`).
|
|
5
|
+
//
|
|
6
|
+
// Each field is a decision about a person's signed-in accounts:
|
|
7
|
+
// enabled — the master switch. Off refuses every use.
|
|
8
|
+
// box — the browser image and its size. It runs on this deployment's own sandbox backend: a
|
|
9
|
+
// persistent Vercel Sandbox per person, or a docker container on a named volume.
|
|
10
|
+
// `dockerNetwork` (docker only) is the network the app and the box share.
|
|
11
|
+
// sessionMinutes — the hard cap on one live session of the box.
|
|
12
|
+
// idleMinutes — the box stops after this long with nobody using or watching it. Logins stay.
|
|
13
|
+
// keepLoginsDays — how long the profile (the logins) survives with no use.
|
|
14
|
+
// takeoverMinutes — the longest a person holds the controls before they return to the agent.
|
|
15
|
+
// actGrantMinutes — how long one "let the agent click and type on this site" approval lasts.
|
|
16
|
+
//
|
|
17
|
+
// WHERE THE BROWSER MAY GO is not declared here: it reaches exactly the hosts the person's DM's egress
|
|
18
|
+
// declaration admits (agent/access — bundles and network access), the same firewall every other call uses.
|
|
19
|
+
//
|
|
20
|
+
// 🔴 NOTHING HERE IS A SECRET.
|
|
21
|
+
//
|
|
22
|
+
// To turn it on: build and publish the browser image (the manual's Personal browser page says how), set
|
|
23
|
+
// `box.image`, and set `enabled: true`. The watch page also needs the page signing key
|
|
24
|
+
// (OE_INTAKE_PAGE_SIGNING_KEY) and a public URL, which the credential intake page already uses.
|
|
25
|
+
|
|
26
|
+
import { DEFAULT_PERSONAL_BROWSER_POLICY, registerPersonalBrowserPolicy, type PersonalBrowserPolicy } from "@open-everywhere/core/agent/personal-browser/policy.js";
|
|
27
|
+
|
|
28
|
+
const personalBrowserPolicy: PersonalBrowserPolicy = {
|
|
29
|
+
...DEFAULT_PERSONAL_BROWSER_POLICY,
|
|
30
|
+
enabled: false,
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
registerPersonalBrowserPolicy(personalBrowserPolicy);
|
|
@@ -15,7 +15,7 @@ const pricing: ModelPricingTable = defineModelPricing({
|
|
|
15
15
|
// chinese-open-weights: vision.
|
|
16
16
|
"alibaba/qwen3-vl-instruct": { inPerMtok: 0.2, outPerMtok: 0.88 },
|
|
17
17
|
// american-closed: vision.
|
|
18
|
-
"google/gemini-3.
|
|
18
|
+
"google/gemini-3.8-flash": { inPerMtok: 0.75, outPerMtok: 3.75 },
|
|
19
19
|
});
|
|
20
20
|
|
|
21
21
|
assertModelPricingValid(pricing);
|
|
@@ -37,7 +37,7 @@ npm view @open-everywhere/core version
|
|
|
37
37
|
**Read the installed one, not the pin.** `oe upgrade` writes the pins before it installs, so an
|
|
38
38
|
upgrade that stopped part way leaves a manifest that names a version the app is not running.
|
|
39
39
|
|
|
40
|
-
The
|
|
40
|
+
The ten packages publish in lockstep, so one version answers for all of them. Agree the target
|
|
41
41
|
with the user before you go on. Taking the latest is the normal choice.
|
|
42
42
|
|
|
43
43
|
## 2. Read the notes between the two versions
|
package/template/gitignore
CHANGED
|
@@ -33,6 +33,7 @@ node_modules/
|
|
|
33
33
|
/agent/skills/
|
|
34
34
|
/agent/connections/
|
|
35
35
|
/agent/lib/providers.generated.ts
|
|
36
|
+
/agent/lib/app-code-fingerprint.generated.ts
|
|
36
37
|
|
|
37
38
|
# Misc
|
|
38
39
|
*.log
|
|
@@ -40,3 +41,6 @@ node_modules/
|
|
|
40
41
|
*.tsbuildinfo
|
|
41
42
|
*.pem
|
|
42
43
|
*.key
|
|
44
|
+
|
|
45
|
+
# A built Teams app package (`surface_app_package`): rebuilt from config, never committed.
|
|
46
|
+
teams-app/*.zip
|
package/template/package.json
CHANGED
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"@open-everywhere/adapters": "{{OE_VERSION}}",
|
|
27
27
|
"@open-everywhere/core": "{{OE_VERSION}}",
|
|
28
28
|
"@open-everywhere/provider-discord": "{{OE_VERSION}}",
|
|
29
|
+
"@open-everywhere/provider-email": "{{OE_VERSION}}",
|
|
29
30
|
"@open-everywhere/provider-github": "{{OE_VERSION}}",
|
|
30
31
|
"@open-everywhere/provider-linear": "{{OE_VERSION}}",
|
|
31
32
|
"@open-everywhere/provider-notion": "{{OE_VERSION}}",
|
|
@@ -29,8 +29,8 @@ export default defineRoster({
|
|
|
29
29
|
core: true,
|
|
30
30
|
adapters: true,
|
|
31
31
|
|
|
32
|
-
// One provider bundle per surface. Add a line to add a surface (`discord`, `teams
|
|
33
|
-
// are installed too), then `npx oe build --accept`.
|
|
32
|
+
// One provider bundle per surface. Add a line to add a surface (`discord`, `teams`, `linear` and
|
|
33
|
+
// `email` are installed too), then `npx oe build --accept`.
|
|
34
34
|
providers: {
|
|
35
35
|
slack: true,
|
|
36
36
|
notion: true,
|
|
@@ -22,8 +22,10 @@
|
|
|
22
22
|
"channel/control-mcp": "mounted",
|
|
23
23
|
"channel/control-read": "mounted",
|
|
24
24
|
"channel/credential-intake-page": "mounted",
|
|
25
|
+
"channel/meeting-callback": "mounted",
|
|
25
26
|
"channel/oe-oauth-callback": "mounted",
|
|
26
27
|
"channel/oe-status": "mounted",
|
|
28
|
+
"channel/personal-browser": "mounted",
|
|
27
29
|
"channel/policy-pages": "mounted",
|
|
28
30
|
"channel/test-wake": "mounted",
|
|
29
31
|
"channel/transcript-relay": "mounted",
|
|
@@ -67,11 +69,15 @@
|
|
|
67
69
|
"schedule/directory-sync": "mounted",
|
|
68
70
|
"schedule/dispatch": "mounted",
|
|
69
71
|
"schedule/dream-mode3": "mounted",
|
|
72
|
+
"schedule/meeting-sweep": "mounted",
|
|
73
|
+
"schedule/personal-browser-sweep": "mounted",
|
|
70
74
|
"schedule/tidy": "mounted",
|
|
71
75
|
"skill/scoped": "mounted",
|
|
72
76
|
"tool/add_label": "mounted",
|
|
73
77
|
"tool/add_routine_rule": "mounted",
|
|
74
78
|
"tool/agent_version": "mounted",
|
|
79
|
+
"tool/answer_domain_question": "mounted",
|
|
80
|
+
"tool/ask_domain": "mounted",
|
|
75
81
|
"tool/ask_question": "mounted",
|
|
76
82
|
"tool/ask_room": "mounted",
|
|
77
83
|
"tool/assign": "mounted",
|
|
@@ -111,15 +117,21 @@
|
|
|
111
117
|
"tool/list_routines": "mounted",
|
|
112
118
|
"tool/list_skills": "mounted",
|
|
113
119
|
"tool/list_webhooks": "mounted",
|
|
120
|
+
"tool/meeting_join": "mounted",
|
|
121
|
+
"tool/meeting_leave": "mounted",
|
|
122
|
+
"tool/meeting_recap": "mounted",
|
|
114
123
|
"tool/memory_admin_list": "mounted",
|
|
115
124
|
"tool/memory_admin_read": "mounted",
|
|
116
125
|
"tool/message_thread_seat": "mounted",
|
|
126
|
+
"tool/my_browser": "mounted",
|
|
127
|
+
"tool/my_browser_handoff": "mounted",
|
|
117
128
|
"tool/no_reply": "mounted",
|
|
118
129
|
"tool/open_pull_request": "mounted",
|
|
119
130
|
"tool/permission_fit_report": "mounted",
|
|
120
131
|
"tool/post_file": "mounted",
|
|
121
132
|
"tool/post_message": "mounted",
|
|
122
133
|
"tool/post_pr_walkthrough": "mounted",
|
|
134
|
+
"tool/propose_email_sender": "mounted",
|
|
123
135
|
"tool/propose_mcp_server": "mounted",
|
|
124
136
|
"tool/purge_memory": "mounted",
|
|
125
137
|
"tool/query_analytics": "mounted",
|
|
@@ -3,9 +3,11 @@ agent/channels/control-mcp.ts mounted @open-everywhere/core
|
|
|
3
3
|
agent/channels/control-read.ts mounted @open-everywhere/core
|
|
4
4
|
agent/channels/credential-intake-page.ts mounted @open-everywhere/core
|
|
5
5
|
agent/channels/github.ts mounted @open-everywhere/provider-github
|
|
6
|
+
agent/channels/meeting-callback.ts mounted @open-everywhere/core
|
|
6
7
|
agent/channels/notion.ts mounted @open-everywhere/provider-notion
|
|
7
8
|
agent/channels/oe-oauth-callback.ts mounted @open-everywhere/core
|
|
8
9
|
agent/channels/oe-status.ts mounted @open-everywhere/core
|
|
10
|
+
agent/channels/personal-browser.ts mounted @open-everywhere/core
|
|
9
11
|
agent/channels/policy-pages.ts mounted @open-everywhere/core
|
|
10
12
|
agent/channels/slack-commands.ts mounted @open-everywhere/provider-slack
|
|
11
13
|
agent/channels/slack-setup-page.ts mounted @open-everywhere/provider-slack
|
|
@@ -54,12 +56,16 @@ agent/schedules/audit-export.ts mounted @open-everywhere/core
|
|
|
54
56
|
agent/schedules/directory-sync.ts mounted @open-everywhere/core
|
|
55
57
|
agent/schedules/dispatch.ts mounted @open-everywhere/core
|
|
56
58
|
agent/schedules/dream-mode3.ts mounted @open-everywhere/core
|
|
59
|
+
agent/schedules/meeting-sweep.ts mounted @open-everywhere/core
|
|
57
60
|
agent/schedules/notion-ingress.ts mounted @open-everywhere/provider-notion
|
|
61
|
+
agent/schedules/personal-browser-sweep.ts mounted @open-everywhere/core
|
|
58
62
|
agent/schedules/tidy.ts mounted @open-everywhere/core
|
|
59
63
|
agent/skills/scoped.ts mounted @open-everywhere/core
|
|
60
64
|
agent/tools/add_label.ts mounted @open-everywhere/core
|
|
61
65
|
agent/tools/add_routine_rule.ts mounted @open-everywhere/core
|
|
62
66
|
agent/tools/agent_version.ts mounted @open-everywhere/core
|
|
67
|
+
agent/tools/answer_domain_question.ts mounted @open-everywhere/core
|
|
68
|
+
agent/tools/ask_domain.ts mounted @open-everywhere/core
|
|
63
69
|
agent/tools/ask_question.ts mounted @open-everywhere/core
|
|
64
70
|
agent/tools/ask_room.ts mounted @open-everywhere/core
|
|
65
71
|
agent/tools/assign.ts mounted @open-everywhere/core
|
|
@@ -101,9 +107,14 @@ agent/tools/list_repos.ts mounted @open-everywhere/core
|
|
|
101
107
|
agent/tools/list_routines.ts mounted @open-everywhere/core
|
|
102
108
|
agent/tools/list_skills.ts mounted @open-everywhere/core
|
|
103
109
|
agent/tools/list_webhooks.ts mounted @open-everywhere/core
|
|
110
|
+
agent/tools/meeting_join.ts mounted @open-everywhere/core
|
|
111
|
+
agent/tools/meeting_leave.ts mounted @open-everywhere/core
|
|
112
|
+
agent/tools/meeting_recap.ts mounted @open-everywhere/core
|
|
104
113
|
agent/tools/memory_admin_list.ts mounted @open-everywhere/core
|
|
105
114
|
agent/tools/memory_admin_read.ts mounted @open-everywhere/core
|
|
106
115
|
agent/tools/message_thread_seat.ts mounted @open-everywhere/core
|
|
116
|
+
agent/tools/my_browser_handoff.ts mounted @open-everywhere/core
|
|
117
|
+
agent/tools/my_browser.ts mounted @open-everywhere/core
|
|
107
118
|
agent/tools/no_reply.ts mounted @open-everywhere/core
|
|
108
119
|
agent/tools/notion_search.ts mounted @open-everywhere/provider-notion
|
|
109
120
|
agent/tools/open_pull_request.ts mounted @open-everywhere/core
|
|
@@ -111,6 +122,7 @@ agent/tools/permission_fit_report.ts mounted @open-everywhere/core
|
|
|
111
122
|
agent/tools/post_file.ts mounted @open-everywhere/core
|
|
112
123
|
agent/tools/post_message.ts mounted @open-everywhere/core
|
|
113
124
|
agent/tools/post_pr_walkthrough.ts mounted @open-everywhere/core
|
|
125
|
+
agent/tools/propose_email_sender.ts mounted @open-everywhere/core
|
|
114
126
|
agent/tools/propose_mcp_server.ts mounted @open-everywhere/core
|
|
115
127
|
agent/tools/purge_memory.ts mounted @open-everywhere/core
|
|
116
128
|
agent/tools/query_analytics.ts mounted @open-everywhere/core
|
|
@@ -47,5 +47,5 @@ registerSurfaceTrustPreflight();
|
|
|
47
47
|
const server = buildOpsServer();
|
|
48
48
|
await server.connect(new StdioServerTransport());
|
|
49
49
|
process.stderr.write(
|
|
50
|
-
"open-everywhere-ops MCP server ready on stdio (preflight · surface_manifest · scaffold_env · scaffold_credential_key · secret_set/list/rm)\n",
|
|
50
|
+
"open-everywhere-ops MCP server ready on stdio (preflight · surface_manifest · surface_app_package · scaffold_env · scaffold_credential_key · secret_set/list/rm)\n",
|
|
51
51
|
);
|