@opengeni/api-router 2.5.0 → 2.6.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 (59) hide show
  1. package/dist/app.js +1 -1
  2. package/dist/auth/managed-auth-attempt-context.d.ts +5 -1
  3. package/dist/auth/managed-auth.d.ts +24 -1
  4. package/dist/{chunk-QESX7HDK.js → chunk-XTLI3CBH.js} +2236 -387
  5. package/dist/chunk-XTLI3CBH.js.map +1 -0
  6. package/dist/http/sse.d.ts +9 -0
  7. package/dist/index.js +104 -4
  8. package/dist/index.js.map +1 -1
  9. package/dist/interaction-metrics.d.ts +2 -0
  10. package/dist/mcp/company-brain-governed-writes.d.ts +1 -1
  11. package/dist/mcp/company-profile-agent-admin.d.ts +6 -6
  12. package/dist/mcp/remember.d.ts +2 -2
  13. package/dist/mcp/server.d.ts +1 -0
  14. package/dist/mcp/session-view.d.ts +1 -0
  15. package/dist/mcp/session-wait.d.ts +19 -0
  16. package/dist/routes/api-keys.d.ts +2 -0
  17. package/dist/routes/browser-sessions.d.ts +1 -0
  18. package/dist/routes/computer-sessions.d.ts +12 -0
  19. package/dist/routes/managed-auth-session-sets.d.ts +7 -0
  20. package/dist/routes/workspaces.d.ts +1 -1
  21. package/dist/sandbox/metrics-ingestion.d.ts +16 -0
  22. package/dist/workspace-delete-observability.d.ts +10 -0
  23. package/package.json +15 -15
  24. package/src/app.ts +172 -20
  25. package/src/auth/managed-auth-attempt-context.ts +40 -3
  26. package/src/auth/managed-auth-session-adapter.ts +1 -0
  27. package/src/auth/managed-auth.ts +164 -4
  28. package/src/http/sse.ts +279 -45
  29. package/src/integrations/oauth-client.ts +8 -1
  30. package/src/integrations/provider-oauth.ts +12 -2
  31. package/src/interaction-metrics.ts +30 -0
  32. package/src/mcp/company-brain-governed-writes.ts +38 -23
  33. package/src/mcp/company-profile-agent-admin.ts +7 -7
  34. package/src/mcp/remember.ts +19 -8
  35. package/src/mcp/server.ts +318 -26
  36. package/src/mcp/session-wait.ts +56 -8
  37. package/src/routes/api-integrations.ts +2 -2
  38. package/src/routes/api-keys.ts +149 -7
  39. package/src/routes/browser-sessions.ts +10 -2
  40. package/src/routes/capabilities.ts +3 -3
  41. package/src/routes/codex.ts +483 -74
  42. package/src/routes/company-profile.ts +64 -0
  43. package/src/routes/computer-sessions.ts +103 -1
  44. package/src/routes/integration-facets.ts +8 -5
  45. package/src/routes/interaction-resources.ts +7 -1
  46. package/src/routes/managed-auth-session-sets.ts +199 -2
  47. package/src/routes/organization-memberships.ts +28 -8
  48. package/src/routes/packs.ts +5 -5
  49. package/src/routes/plugins.ts +2 -2
  50. package/src/routes/scheduled-tasks.ts +9 -0
  51. package/src/routes/sessions.ts +3 -6
  52. package/src/routes/skills.ts +3 -3
  53. package/src/routes/workspaces.ts +293 -54
  54. package/src/sandbox/channel-a.ts +10 -4
  55. package/src/sandbox/machines.ts +13 -6
  56. package/src/sandbox/metrics-ingestion.ts +157 -3
  57. package/src/sandbox/viewer.ts +20 -1
  58. package/src/workspace-delete-observability.ts +75 -0
  59. package/dist/chunk-QESX7HDK.js.map +0 -1
@@ -1,9 +1,10 @@
1
1
  import {
2
- AGENT_AUTHORED_DURABLE_TEXT_STYLE,
3
2
  AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
4
3
  AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE,
4
+ AGENT_AUTHORED_INSTRUCTION_POLICY_STYLE,
5
5
  AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
6
6
  AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE,
7
+ AGENT_AUTHORED_SKILL_STYLE,
7
8
  PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS,
8
9
  PREFERENCE_REGISTRY_STABLE_KEY_MAX_CHARS,
9
10
  PREFERENCE_REGISTRY_TITLE_MAX_CHARS,
@@ -11,7 +12,7 @@ import {
11
12
  type CompanyBrainGovernedWriteAttempt,
12
13
  } from "@opengeni/contracts";
13
14
  import { createCompanyBrainLearningPolicyRouter } from "@opengeni/core";
14
- import type { Database } from "@opengeni/db";
15
+ import { PreferenceRegistryStableKeyConflictError, type Database } from "@opengeni/db";
15
16
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
17
  import * as z from "zod/v4";
17
18
 
@@ -66,6 +67,20 @@ export function registerCompanyBrainGovernedWriteTools(
66
67
  input: RegisterCompanyBrainGovernedWriteToolsInput,
67
68
  ): void {
68
69
  const router = input.router ?? createCompanyBrainLearningPolicyRouter({ db: input.db });
70
+ const writeResult = async (write: () => ReturnType<typeof router.write>) => {
71
+ try {
72
+ return input.json(await write());
73
+ } catch (error) {
74
+ if (error instanceof PreferenceRegistryStableKeyConflictError) {
75
+ return input.json({
76
+ status: "not_proposed",
77
+ code: "preference_stable_key_conflict",
78
+ message: error.message,
79
+ });
80
+ }
81
+ throw error;
82
+ }
83
+ };
69
84
  input.server.registerTool(
70
85
  "knowledge_propose",
71
86
  {
@@ -75,8 +90,8 @@ export function registerCompanyBrainGovernedWriteTools(
75
90
  },
76
91
  async (request) => {
77
92
  await input.authorize();
78
- return input.json(
79
- await router.write({
93
+ return writeResult(() =>
94
+ router.write({
80
95
  attempt: input.attempt,
81
96
  request: { kind: "propose_knowledge", ...request },
82
97
  }),
@@ -93,8 +108,8 @@ export function registerCompanyBrainGovernedWriteTools(
93
108
  },
94
109
  async (request) => {
95
110
  await input.authorize();
96
- return input.json(
97
- await router.write({
111
+ return writeResult(() =>
112
+ router.write({
98
113
  attempt: input.attempt,
99
114
  request: { kind: "correct_knowledge", ...request },
100
115
  }),
@@ -111,8 +126,8 @@ export function registerCompanyBrainGovernedWriteTools(
111
126
  },
112
127
  async (request) => {
113
128
  await input.authorize();
114
- return input.json(
115
- await router.write({
129
+ return writeResult(() =>
130
+ router.write({
116
131
  attempt: input.attempt,
117
132
  request: { kind: "promote_task_note_knowledge", ...request },
118
133
  }),
@@ -124,9 +139,9 @@ export function registerCompanyBrainGovernedWriteTools(
124
139
  "task_note_promote_instruction_policy",
125
140
  {
126
141
  description:
127
- "Atomically promote one still-active note from this exact root task tree into an inactive workspace instruction-policy draft. The note bytes remain exact evidence and draft content. " +
128
- `Use this only for a universal always-on rule, never for an incident, fact, decision, outcome, or conditional procedure. Once a human activates the draft, those bytes are composed verbatim into the prompt of every session the target applies to, so a note over ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters is rejected here rather than truncated: write a fresh minimal imperative note instead of promoting a long working note. ` +
129
- "The frozen learning policy records a decision receipt, but mandatory policy still requires human activation even under Automatic; this never widens scope.",
142
+ "Atomically promote one still-active note from this exact root task tree into a workspace instruction-policy proposal. The note bytes remain exact evidence and draft content. " +
143
+ `Use this only for a universal always-on rule, never for an incident, fact, decision, outcome, or conditional procedure. Once active, those bytes are composed verbatim into the prompt of every session the target applies to, so a note over ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters is rejected here rather than truncated: write a fresh minimal imperative note instead of promoting a long working note. ` +
144
+ "Off creates nothing; Review first keeps the proposal inactive; Autonomous may activate an eligible proposal through the governed instruction lifecycle with an undoable receipt. This never widens scope.",
130
145
  inputSchema: {
131
146
  ...taskNotePromotion,
132
147
  target: WorkspaceInstructionPolicyTarget,
@@ -136,8 +151,8 @@ export function registerCompanyBrainGovernedWriteTools(
136
151
  },
137
152
  async (request) => {
138
153
  await input.authorize();
139
- return input.json(
140
- await router.write({
154
+ return writeResult(() =>
155
+ router.write({
141
156
  attempt: input.attempt,
142
157
  request: { kind: "promote_task_note_instruction_policy", ...request },
143
158
  }),
@@ -172,8 +187,8 @@ export function registerCompanyBrainGovernedWriteTools(
172
187
  },
173
188
  async (request) => {
174
189
  await input.authorize();
175
- return input.json(
176
- await router.write({
190
+ return writeResult(() =>
191
+ router.write({
177
192
  attempt: input.attempt,
178
193
  request: { kind: "promote_task_note_preference", ...request },
179
194
  }),
@@ -185,9 +200,9 @@ export function registerCompanyBrainGovernedWriteTools(
185
200
  "instruction_policy_propose",
186
201
  {
187
202
  description:
188
- "Materialize an evidence-backed inactive workspace instruction-policy draft. " +
189
- `Use this only for a minimal universal rule, never for an incident, fact, decision, outcome, or conditional procedure. Once a human activates it, this content is composed verbatim into the prompt of every session the target applies to (every session in this workspace for a global charter or policy, every session bound to the role for a role policy), so keep it under ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters. ${AGENT_AUTHORED_DURABLE_TEXT_STYLE} ` +
190
- "The frozen learning policy records a decision receipt, but this tool cannot activate mandatory behavior, including when learning mode is Automatic; a human must activate the draft.",
203
+ "Materialize an evidence-backed workspace instruction-policy proposal. " +
204
+ `Use this only for a minimal universal rule, never for an incident, fact, decision, outcome, or conditional procedure. Once active, this content is composed verbatim into the prompt of every session the target applies to (every session in this workspace for a global charter or policy, every session bound to the role for a role policy), so keep it under ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters. ${AGENT_AUTHORED_INSTRUCTION_POLICY_STYLE} ` +
205
+ "Off creates nothing; Review first keeps the proposal inactive; Autonomous may activate an eligible proposal through the governed instruction lifecycle with an undoable receipt.",
191
206
  inputSchema: {
192
207
  ...evidence,
193
208
  target: WorkspaceInstructionPolicyTarget,
@@ -206,8 +221,8 @@ export function registerCompanyBrainGovernedWriteTools(
206
221
  },
207
222
  async (request) => {
208
223
  await input.authorize();
209
- return input.json(
210
- await router.write({
224
+ return writeResult(() =>
225
+ router.write({
211
226
  attempt: input.attempt,
212
227
  request: { kind: "propose_instruction_policy", ...request },
213
228
  }),
@@ -220,7 +235,7 @@ export function registerCompanyBrainGovernedWriteTools(
220
235
  {
221
236
  description:
222
237
  "Materialize an evidence-backed workspace Skill proposal in the structured preference authority. Use this only for reusable conditional how-to guidance, never for an incident, fact, decision, outcome, or universal always-on rule. " +
223
- `Its short title and description are what get composed into every session prompt; the content is retrieved on demand, so its length is retrieval cost rather than standing prompt cost. Keep the content under ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} characters. ${AGENT_AUTHORED_DURABLE_TEXT_STYLE} ` +
238
+ `Its short title and description are what get composed into every session prompt; the content is retrieved on demand, so its length is retrieval cost rather than standing prompt cost. Keep the content under ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} characters. ${AGENT_AUTHORED_SKILL_STYLE} ` +
224
239
  "Under Suggest it stays inactive for human review; under Automatic an eligible decision is activated through the governed preference lifecycle with an undoable receipt. It never creates mandatory authority.",
225
240
  inputSchema: {
226
241
  ...evidence,
@@ -251,8 +266,8 @@ export function registerCompanyBrainGovernedWriteTools(
251
266
  },
252
267
  async (request) => {
253
268
  await input.authorize();
254
- return input.json(
255
- await router.write({
269
+ return writeResult(() =>
270
+ router.write({
256
271
  attempt: input.attempt,
257
272
  request: { kind: "propose_preference", ...request },
258
273
  }),
@@ -109,12 +109,12 @@ function boundedIssueMessage(error: z.ZodError): string {
109
109
  }
110
110
 
111
111
  /**
112
- * Register the explicit owner-confirmed organization profile path. This is
113
- * administration, not derived learning: workspace learning mode is never
114
- * consulted, the initiating human must be the organization's active owner (the
115
- * same authority as the manual `account:admin` route), and the proposal cannot
116
- * become active without the exact bound human-input response returned by the
117
- * first call.
112
+ * Register the organization profile administration path. This is not derived
113
+ * workspace learning: the initiating human must be the organization's active
114
+ * owner (the same authority as the manual `account:admin` route). The separate
115
+ * organization policy either blocks the proposal, keeps the exact bound
116
+ * human-confirmation path, or permits immediate activation through the native
117
+ * company-profile lifecycle.
118
118
  */
119
119
  export function registerCompanyProfileAgentAdminTools(
120
120
  input: RegisterCompanyProfileAgentAdminToolsInput,
@@ -127,7 +127,7 @@ export function registerCompanyProfileAgentAdminTools(
127
127
  "Prepare the organization's small, stable identity: identity says who the organization is, and mission says why it exists. " +
128
128
  "Once activated, both fields are mandatory prompt context in every root session for the whole organization, so use one plain descriptive statement per field with no products, customers, goals, constraints, procedures, or marketing copy. Those details belong in organization-scoped Documents and are retrieved only when relevant. " +
129
129
  `Each field is bounded to ${AGENT_AUTHORED_COMPANY_PROFILE_SCALAR_MAX_CHARS} characters for agent-authored proposals. ` +
130
- "This creates only an immutable inactive proposal for the exact live turn initiated by the organization owner and does not use workspace learning policy. The receipt returns the exact `humanInput` payload; call `request_human_input` with it verbatim, then call `company_profile_confirm` with the returned requestId.",
130
+ "This is independent of workspace learning policy and follows the organization owner's Agent-managed identity mode. Off creates nothing. Review first returns status=confirmation_required with the exact `humanInput` payload; call `request_human_input` with it verbatim, then call `company_profile_confirm` with the returned requestId. Autonomous may return status=activated immediately after exact live-owner, stale-head, and compare-and-swap checks; do not ask for another confirmation in that case.",
131
131
  inputSchema: {
132
132
  operationId: z.string().uuid(),
133
133
  identity: scalar,
@@ -11,7 +11,7 @@ import {
11
11
  type RememberLane,
12
12
  } from "@opengeni/contracts";
13
13
  import { RememberError, createRememberRouter } from "@opengeni/core";
14
- import type { Database } from "@opengeni/db";
14
+ import { PreferenceRegistryStableKeyConflictError, type Database } from "@opengeni/db";
15
15
  import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
16
16
  import * as z from "zod/v4";
17
17
 
@@ -59,7 +59,7 @@ const laneFields = {
59
59
  /**
60
60
  * Explicit user-directed remember. Content becomes exact task-note evidence,
61
61
  * promotion runs through the frozen workspace learning policy, and activation
62
- * is either automatic (preference under Automatic mode) or requires exactly one
62
+ * is either automatic (Skill or instruction under Automatic mode) or requires exactly one
63
63
  * bound human confirmation through the built-in `request_human_input` tool.
64
64
  * Tool input cannot select scope beyond the workspace, active authority, or
65
65
  * another learning-policy source.
@@ -70,9 +70,9 @@ export function registerRememberTools(input: RegisterRememberToolsInput): void {
70
70
  "remember",
71
71
  {
72
72
  description:
73
- "Durably remember something the user explicitly asked to keep for this workspace. Route by purpose: lane=knowledge for a fact, decision, incident, bug fix, or outcome that should become searchable Memory; lane=preference creates a Skill for reusable conditional how-to guidance; lane=instruction_policy is only for a universal always/never rule that should apply to nearly every task. " +
74
- `Write the instruction lane as the shortest complete rule, at most ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters and normally 1-3 imperative sentences, with no numbered steps, examples, rationale, or restated defaults. Keep a Skill under ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} characters; only its one-sentence descriptor is composed and the full instructions are retrieved on demand. Do not copy one item into multiple lanes. ` +
75
- "Under Automatic learning a Skill may activate immediately; otherwise the receipt returns status=confirmation_required with the exact `humanInput` payload: call `request_human_input` with it verbatim, then call `remember_confirm` with the returned requestId. Workspace instructions and Memory always need that confirmation. Do not use this for facts you merely inferred; use knowledge_propose or task notes for those. Confirmed lane=knowledge content keeps its reviewed claim provenance and materializes its exact approved text into Memory for later `memory_search` retrieval.",
73
+ "Create governed durable knowledge, a Skill, or a mandatory workspace instruction. When the agent-only memory_save tool is available, use it instead for ordinary durable facts, decisions, incidents, bug fixes, and confirmed outcomes; those Memory writes are autonomous and independent of Learning mode. Use lane=knowledge only when memory_save is unavailable and the user explicitly requests reviewed workspace knowledge; lane=preference creates a Skill for reusable conditional how-to guidance; lane=instruction_policy is only for a universal always/never rule that should apply to nearly every task. " +
74
+ `Write the instruction lane as the shortest complete rule, at most ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters and normally 1-3 imperative sentences, with no numbered steps, examples, rationale, or restated defaults. Keep a Skill under ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} characters with one clear trigger and outcome, only the necessary steps, checks, and exceptions, and a one-sentence descriptor. Do not copy one item into multiple lanes. ` +
75
+ "Under Autonomous learning, an eligible Skill or workspace instruction may activate immediately through its governed lifecycle. Under Review first, it remains inactive and the receipt returns status=confirmation_required with the exact `humanInput` payload: call `request_human_input` with it verbatim, then call `remember_confirm` with the returned requestId. Off creates no governed change. Reviewed Knowledge always needs confirmation. Do not use lane=knowledge for facts you merely inferred; use memory_save when available, otherwise knowledge_propose or task notes. Confirmed lane=knowledge content keeps its reviewed claim provenance and materializes its exact approved text into Memory for later `memory_search` retrieval.",
76
76
  inputSchema: {
77
77
  lane: z.enum(["preference", "instruction_policy", "knowledge"]),
78
78
  ...laneFields,
@@ -120,9 +120,20 @@ export function registerRememberTools(input: RegisterRememberToolsInput): void {
120
120
  : lane === "instruction_policy"
121
121
  ? { ...base, lane, target: request.target }
122
122
  : { ...base, lane, subject: request.subject ?? content.slice(0, 80) };
123
- return input.json(
124
- await router.remember({ attempt: input.attempt, request: rememberRequest }),
125
- );
123
+ try {
124
+ return input.json(
125
+ await router.remember({ attempt: input.attempt, request: rememberRequest }),
126
+ );
127
+ } catch (error) {
128
+ if (error instanceof PreferenceRegistryStableKeyConflictError) {
129
+ return input.json({
130
+ status: "not_remembered",
131
+ code: "preference_stable_key_conflict",
132
+ message: error.message,
133
+ });
134
+ }
135
+ throw error;
136
+ }
126
137
  },
127
138
  );
128
139