@opengeni/api-router 2.13.0-canary.0 → 2.13.0-canary.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app.js +1 -1
- package/dist/{chunk-BJWHVMOL.js → chunk-K2NU4KRK.js} +3165 -3662
- package/dist/{chunk-BJWHVMOL.js.map → chunk-K2NU4KRK.js.map} +1 -1
- package/dist/index.js +5 -4
- package/dist/index.js.map +1 -1
- package/dist/integrations/github-lens-connect.d.ts +2 -2
- package/dist/integrations/slack-interactions.d.ts +1 -1
- package/dist/mcp/documents.d.ts +5 -13
- package/dist/mcp/files.d.ts +2 -2
- package/dist/mcp/first-party-tool-permissions.d.ts +36 -0
- package/dist/mcp/knowledge-entries.d.ts +5 -0
- package/dist/mcp/server.d.ts +4 -4
- package/dist/routes/host-mcp-resolvers.d.ts +3 -0
- package/dist/routes/knowledge.d.ts +3 -0
- package/dist/sandbox-file-artifacts.d.ts +6 -2
- package/dist/workspace-state-projection.d.ts +3 -5
- package/dist/workspace-tool-gateway.d.ts +2 -1
- package/package.json +19 -19
- package/src/access-grant-rls.ts +13 -1
- package/src/app.ts +4 -11
- package/src/codemode.ts +4 -8
- package/src/index.ts +4 -3
- package/src/integrations/atlassian.ts +31 -28
- package/src/integrations/google-drive.ts +33 -30
- package/src/integrations/marketplace-plugin.ts +1 -1
- package/src/integrations/provider-oauth.ts +11 -2
- package/src/mcp/documents.ts +57 -428
- package/src/mcp/files.ts +76 -58
- package/src/mcp/first-party-tool-permissions.ts +9 -0
- package/src/mcp/knowledge-entries.ts +276 -0
- package/src/mcp/server.ts +7 -361
- package/src/routes/company-brain.ts +58 -107
- package/src/routes/documents.ts +78 -294
- package/src/routes/files.ts +68 -3
- package/src/routes/host-mcp-resolvers.ts +41 -0
- package/src/routes/knowledge.ts +386 -0
- package/src/routes/organization-memberships.ts +33 -0
- package/src/routes/scheduled-tasks.ts +9 -1
- package/src/routes/sessions.ts +20 -3
- package/src/routes/skill-content.ts +8 -2
- package/src/routes/video-generation.ts +7 -5
- package/src/routes/workspace-learning.ts +12 -82
- package/src/routes/workspace-state.ts +34 -25
- package/src/routes/workspaces.ts +20 -10
- package/src/sandbox-file-artifacts.ts +54 -2
- package/src/scheduled-task-deletion.ts +3 -2
- package/src/workspace-state-projection.ts +18 -148
- package/src/workspace-tool-gateway.ts +14 -25
- package/dist/mcp/company-brain-governed-writes.d.ts +0 -26
- package/dist/mcp/remember.d.ts +0 -28
- package/src/mcp/company-brain-governed-writes.ts +0 -271
- package/src/mcp/remember.ts +0 -191
|
@@ -1,271 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
3
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE,
|
|
4
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_STYLE,
|
|
5
|
-
AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
6
|
-
AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE,
|
|
7
|
-
PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS,
|
|
8
|
-
PREFERENCE_REGISTRY_STABLE_KEY_MAX_CHARS,
|
|
9
|
-
PREFERENCE_REGISTRY_TITLE_MAX_CHARS,
|
|
10
|
-
WorkspaceInstructionPolicyTarget,
|
|
11
|
-
type CompanyBrainGovernedWriteAttempt,
|
|
12
|
-
} from "@opengeni/contracts";
|
|
13
|
-
import { createCompanyBrainLearningPolicyRouter } from "@opengeni/core";
|
|
14
|
-
import { PreferenceRegistryStableKeyConflictError, type Database } from "@opengeni/db";
|
|
15
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
|
-
import * as z from "zod/v4";
|
|
17
|
-
|
|
18
|
-
type JsonResult = (value: unknown) => {
|
|
19
|
-
content: { type: "text"; text: string }[];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
const reason = z.string().trim().min(1).max(4_096);
|
|
23
|
-
const evidence = {
|
|
24
|
-
operationId: z.string().uuid(),
|
|
25
|
-
claimId: z.string().uuid(),
|
|
26
|
-
evidenceId: z.string().uuid(),
|
|
27
|
-
};
|
|
28
|
-
const taskNotePromotion = {
|
|
29
|
-
operationId: z.string().uuid(),
|
|
30
|
-
noteId: z.string().uuid(),
|
|
31
|
-
expectedNoteVersion: z.literal(1),
|
|
32
|
-
entityType: z
|
|
33
|
-
.string()
|
|
34
|
-
.trim()
|
|
35
|
-
.min(1)
|
|
36
|
-
.max(96)
|
|
37
|
-
.regex(/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/),
|
|
38
|
-
normalizedKey: z.string().trim().min(1).max(512),
|
|
39
|
-
displayName: z.string().trim().min(1).max(512),
|
|
40
|
-
predicateKey: z
|
|
41
|
-
.string()
|
|
42
|
-
.trim()
|
|
43
|
-
.min(1)
|
|
44
|
-
.max(128)
|
|
45
|
-
.regex(/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/),
|
|
46
|
-
confidenceBps: z.number().int().min(0).max(10_000),
|
|
47
|
-
reason,
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
export type RegisterCompanyBrainGovernedWriteToolsInput = {
|
|
51
|
-
server: McpServer;
|
|
52
|
-
db: Database;
|
|
53
|
-
attempt: CompanyBrainGovernedWriteAttempt;
|
|
54
|
-
authorize: () => Promise<void>;
|
|
55
|
-
json: JsonResult;
|
|
56
|
-
router?: Pick<ReturnType<typeof createCompanyBrainLearningPolicyRouter>, "write">;
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Register explicit proposal-only Company Brain tools. The signed host attempt
|
|
61
|
-
* owns tenant/session authority and the exact evidence id owns the learning
|
|
62
|
-
* policy source override. Tool input cannot select scope, active authority, or
|
|
63
|
-
* another policy source.
|
|
64
|
-
*/
|
|
65
|
-
export function registerCompanyBrainGovernedWriteTools(
|
|
66
|
-
input: RegisterCompanyBrainGovernedWriteToolsInput,
|
|
67
|
-
): void {
|
|
68
|
-
const router = input.router ?? createCompanyBrainLearningPolicyRouter({ db: input.db });
|
|
69
|
-
const writeResult = async (write: () => ReturnType<typeof router.write>) => {
|
|
70
|
-
try {
|
|
71
|
-
return input.json(await write());
|
|
72
|
-
} catch (error) {
|
|
73
|
-
if (error instanceof PreferenceRegistryStableKeyConflictError) {
|
|
74
|
-
return input.json({
|
|
75
|
-
status: "not_proposed",
|
|
76
|
-
code: "preference_stable_key_conflict",
|
|
77
|
-
message: error.message,
|
|
78
|
-
});
|
|
79
|
-
}
|
|
80
|
-
throw error;
|
|
81
|
-
}
|
|
82
|
-
};
|
|
83
|
-
input.server.registerTool(
|
|
84
|
-
"knowledge_propose",
|
|
85
|
-
{
|
|
86
|
-
description:
|
|
87
|
-
"Propose one existing evidence-backed workspace Knowledge claim through the frozen learning policy. Off creates nothing; Suggest and Automatic both create a proposal that only the human Knowledge review lifecycle can accept.",
|
|
88
|
-
inputSchema: { ...evidence, reason },
|
|
89
|
-
},
|
|
90
|
-
async (request) => {
|
|
91
|
-
await input.authorize();
|
|
92
|
-
return writeResult(() =>
|
|
93
|
-
router.write({
|
|
94
|
-
attempt: input.attempt,
|
|
95
|
-
request: { kind: "propose_knowledge", ...request },
|
|
96
|
-
}),
|
|
97
|
-
);
|
|
98
|
-
},
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
input.server.registerTool(
|
|
102
|
-
"knowledge_correct",
|
|
103
|
-
{
|
|
104
|
-
description:
|
|
105
|
-
"Propose an evidence-backed replacement for another workspace Knowledge claim. The old claim remains in immutable history and the correction never widens scope.",
|
|
106
|
-
inputSchema: { ...evidence, replacesClaimId: z.string().uuid(), reason },
|
|
107
|
-
},
|
|
108
|
-
async (request) => {
|
|
109
|
-
await input.authorize();
|
|
110
|
-
return writeResult(() =>
|
|
111
|
-
router.write({
|
|
112
|
-
attempt: input.attempt,
|
|
113
|
-
request: { kind: "correct_knowledge", ...request },
|
|
114
|
-
}),
|
|
115
|
-
);
|
|
116
|
-
},
|
|
117
|
-
);
|
|
118
|
-
|
|
119
|
-
input.server.registerTool(
|
|
120
|
-
"task_note_promote_knowledge",
|
|
121
|
-
{
|
|
122
|
-
description:
|
|
123
|
-
"Promote one still-active note from this exact root task tree into a normalized workspace Knowledge proposal. The immutable note bytes remain source evidence; this never activates the claim or widens it to personal/organization scope.",
|
|
124
|
-
inputSchema: taskNotePromotion,
|
|
125
|
-
},
|
|
126
|
-
async (request) => {
|
|
127
|
-
await input.authorize();
|
|
128
|
-
return writeResult(() =>
|
|
129
|
-
router.write({
|
|
130
|
-
attempt: input.attempt,
|
|
131
|
-
request: { kind: "promote_task_note_knowledge", ...request },
|
|
132
|
-
}),
|
|
133
|
-
);
|
|
134
|
-
},
|
|
135
|
-
);
|
|
136
|
-
|
|
137
|
-
input.server.registerTool(
|
|
138
|
-
"task_note_promote_instruction_policy",
|
|
139
|
-
{
|
|
140
|
-
description:
|
|
141
|
-
"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. " +
|
|
142
|
-
`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. ` +
|
|
143
|
-
"Off creates nothing; Require approval keeps the proposal inactive; Autonomous may activate an eligible proposal through the governed instruction lifecycle with an undoable receipt. This never widens scope.",
|
|
144
|
-
inputSchema: {
|
|
145
|
-
...taskNotePromotion,
|
|
146
|
-
target: WorkspaceInstructionPolicyTarget,
|
|
147
|
-
expectedCurrentRevisionId: z.string().uuid().nullable(),
|
|
148
|
-
expectedActivationVersion: z.number().int().nonnegative(),
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
async (request) => {
|
|
152
|
-
await input.authorize();
|
|
153
|
-
return writeResult(() =>
|
|
154
|
-
router.write({
|
|
155
|
-
attempt: input.attempt,
|
|
156
|
-
request: { kind: "promote_task_note_instruction_policy", ...request },
|
|
157
|
-
}),
|
|
158
|
-
);
|
|
159
|
-
},
|
|
160
|
-
);
|
|
161
|
-
|
|
162
|
-
input.server.registerTool(
|
|
163
|
-
"task_note_promote_preference",
|
|
164
|
-
{
|
|
165
|
-
description:
|
|
166
|
-
"Legacy Skill promotion entry point. Returns a redirect without changing the note or writing a Skill. Read the note, then use skill_save for reusable guidance governed directly by Learning mode. Read opengeni-skills with skill_read for instructions.",
|
|
167
|
-
inputSchema: {
|
|
168
|
-
...taskNotePromotion,
|
|
169
|
-
stableKey: z.string().trim().min(1).max(PREFERENCE_REGISTRY_STABLE_KEY_MAX_CHARS),
|
|
170
|
-
title: z.string().trim().min(1).max(PREFERENCE_REGISTRY_TITLE_MAX_CHARS),
|
|
171
|
-
description: z
|
|
172
|
-
.string()
|
|
173
|
-
.trim()
|
|
174
|
-
.min(1)
|
|
175
|
-
.max(PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS),
|
|
176
|
-
precedenceRank: z.number().int().min(-1_000).max(1_000).optional().default(0),
|
|
177
|
-
conflictStrategy: z
|
|
178
|
-
.enum(["override", "merge", "reject", "inform"])
|
|
179
|
-
.optional()
|
|
180
|
-
.default("override"),
|
|
181
|
-
conflictsWith: z.array(z.string().min(1)).max(32).optional().default([]),
|
|
182
|
-
expiresAt: z.string().datetime({ offset: true }).nullable().optional().default(null),
|
|
183
|
-
},
|
|
184
|
-
},
|
|
185
|
-
async () => {
|
|
186
|
-
await input.authorize();
|
|
187
|
-
return input.json({
|
|
188
|
-
status: "not_saved",
|
|
189
|
-
code: "use_skill_save",
|
|
190
|
-
message: "Read the task note, then use skill_save. The note has not been changed.",
|
|
191
|
-
});
|
|
192
|
-
},
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
input.server.registerTool(
|
|
196
|
-
"instruction_policy_propose",
|
|
197
|
-
{
|
|
198
|
-
description:
|
|
199
|
-
"Materialize an evidence-backed workspace instruction-policy proposal. " +
|
|
200
|
-
`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} ` +
|
|
201
|
-
"Off creates nothing; Require approval keeps the proposal inactive; Autonomous may activate an eligible proposal through the governed instruction lifecycle with an undoable receipt.",
|
|
202
|
-
inputSchema: {
|
|
203
|
-
...evidence,
|
|
204
|
-
target: WorkspaceInstructionPolicyTarget,
|
|
205
|
-
content: z
|
|
206
|
-
.string()
|
|
207
|
-
.trim()
|
|
208
|
-
.min(1)
|
|
209
|
-
.max(
|
|
210
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
211
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_TOO_LONG_MESSAGE,
|
|
212
|
-
),
|
|
213
|
-
expectedCurrentRevisionId: z.string().uuid().nullable(),
|
|
214
|
-
expectedActivationVersion: z.number().int().nonnegative(),
|
|
215
|
-
reason,
|
|
216
|
-
},
|
|
217
|
-
},
|
|
218
|
-
async (request) => {
|
|
219
|
-
await input.authorize();
|
|
220
|
-
return writeResult(() =>
|
|
221
|
-
router.write({
|
|
222
|
-
attempt: input.attempt,
|
|
223
|
-
request: { kind: "propose_instruction_policy", ...request },
|
|
224
|
-
}),
|
|
225
|
-
);
|
|
226
|
-
},
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
input.server.registerTool(
|
|
230
|
-
"preference_propose",
|
|
231
|
-
{
|
|
232
|
-
description:
|
|
233
|
-
"Legacy Skill proposal entry point. Returns a redirect without writing. Use skill_read to read opengeni-skills, then discover skill_save for shared Skill file changes governed directly by Learning mode.",
|
|
234
|
-
inputSchema: {
|
|
235
|
-
...evidence,
|
|
236
|
-
stableKey: z.string().trim().min(1).max(PREFERENCE_REGISTRY_STABLE_KEY_MAX_CHARS),
|
|
237
|
-
title: z.string().trim().min(1).max(PREFERENCE_REGISTRY_TITLE_MAX_CHARS),
|
|
238
|
-
description: z
|
|
239
|
-
.string()
|
|
240
|
-
.trim()
|
|
241
|
-
.min(1)
|
|
242
|
-
.max(PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS),
|
|
243
|
-
content: z
|
|
244
|
-
.string()
|
|
245
|
-
.trim()
|
|
246
|
-
.min(1)
|
|
247
|
-
.max(
|
|
248
|
-
AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
249
|
-
AGENT_AUTHORED_PREFERENCE_CONTENT_TOO_LONG_MESSAGE,
|
|
250
|
-
),
|
|
251
|
-
precedenceRank: z.number().int().min(-1_000).max(1_000).optional().default(0),
|
|
252
|
-
conflictStrategy: z
|
|
253
|
-
.enum(["override", "merge", "reject", "inform"])
|
|
254
|
-
.optional()
|
|
255
|
-
.default("override"),
|
|
256
|
-
conflictsWith: z.array(z.string().min(1)).max(32).optional().default([]),
|
|
257
|
-
expiresAt: z.string().datetime({ offset: true }).nullable().optional().default(null),
|
|
258
|
-
reason,
|
|
259
|
-
},
|
|
260
|
-
},
|
|
261
|
-
async () => {
|
|
262
|
-
await input.authorize();
|
|
263
|
-
return input.json({
|
|
264
|
-
status: "not_saved",
|
|
265
|
-
code: "use_skill_save",
|
|
266
|
-
message:
|
|
267
|
-
"Use skill_save for Skill changes. This legacy entry point made no durable change.",
|
|
268
|
-
});
|
|
269
|
-
},
|
|
270
|
-
);
|
|
271
|
-
}
|
package/src/mcp/remember.ts
DELETED
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
3
|
-
AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
4
|
-
AGENT_AUTHORED_REMEMBER_CONTENT_TOO_LONG_MESSAGE,
|
|
5
|
-
PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS,
|
|
6
|
-
PREFERENCE_REGISTRY_TITLE_MAX_CHARS,
|
|
7
|
-
REMEMBER_CONTENT_MAX_CHARS,
|
|
8
|
-
WorkspaceInstructionPolicyTarget,
|
|
9
|
-
agentAuthoredDurableTextTooLongMessage,
|
|
10
|
-
type CompanyBrainGovernedWriteAttempt,
|
|
11
|
-
type RememberLane,
|
|
12
|
-
} from "@opengeni/contracts";
|
|
13
|
-
import { RememberError, createRememberRouter } from "@opengeni/core";
|
|
14
|
-
import { PreferenceRegistryStableKeyConflictError, type Database } from "@opengeni/db";
|
|
15
|
-
import type { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
16
|
-
import * as z from "zod/v4";
|
|
17
|
-
|
|
18
|
-
type JsonResult = (value: unknown) => {
|
|
19
|
-
content: { type: "text"; text: string }[];
|
|
20
|
-
};
|
|
21
|
-
|
|
22
|
-
export type RegisterRememberToolsInput = {
|
|
23
|
-
server: McpServer;
|
|
24
|
-
db: Database;
|
|
25
|
-
attempt: CompanyBrainGovernedWriteAttempt;
|
|
26
|
-
authorize: () => Promise<void>;
|
|
27
|
-
json: JsonResult;
|
|
28
|
-
router?: Pick<ReturnType<typeof createRememberRouter>, "remember" | "confirm">;
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Per-lane budgets. The flat MCP input schema cannot vary `content` by lane, so
|
|
33
|
-
* it carries the widest lane (Knowledge) and the handler rejects an over-budget
|
|
34
|
-
* prompt-composed lane with the actionable message before anything durable is
|
|
35
|
-
* written. The contract enforces the same bounds for every other caller.
|
|
36
|
-
*/
|
|
37
|
-
const laneContentMaxChars: Record<RememberLane, number> = {
|
|
38
|
-
instruction_policy: AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS,
|
|
39
|
-
preference: AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS,
|
|
40
|
-
knowledge: REMEMBER_CONTENT_MAX_CHARS,
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
const laneFields = {
|
|
44
|
-
operationId: z.string().uuid(),
|
|
45
|
-
content: z
|
|
46
|
-
.string()
|
|
47
|
-
.trim()
|
|
48
|
-
.min(1)
|
|
49
|
-
// The widest lane, because one flat schema serves all three. Carry the
|
|
50
|
-
// lane-aware guidance in the message so an over-long rule is not refused
|
|
51
|
-
// with a generic bound that points at the wrong number.
|
|
52
|
-
.max(REMEMBER_CONTENT_MAX_CHARS, AGENT_AUTHORED_REMEMBER_CONTENT_TOO_LONG_MESSAGE)
|
|
53
|
-
.describe(
|
|
54
|
-
`The exact thing to remember, in the user's words. Budgets by lane: instruction_policy at most ${AGENT_AUTHORED_INSTRUCTION_POLICY_CONTENT_MAX_CHARS} characters because it is composed into the prompt of every session it applies to, preference at most ${AGENT_AUTHORED_PREFERENCE_CONTENT_MAX_CHARS} (its short descriptor is what is composed; the content is retrieved on demand), knowledge at most ${REMEMBER_CONTENT_MAX_CHARS}.`,
|
|
55
|
-
),
|
|
56
|
-
reason: z.string().trim().min(1).max(4_096),
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Explicit user-directed remember. Content becomes exact task-note evidence,
|
|
61
|
-
* promotion runs through the frozen workspace learning policy, and activation
|
|
62
|
-
* is either automatic (instruction under Automatic mode) or requires exactly one
|
|
63
|
-
* bound human confirmation through the built-in `request_human_input` tool.
|
|
64
|
-
* Tool input cannot select scope beyond the workspace, active authority, or
|
|
65
|
-
* another learning-policy source.
|
|
66
|
-
*/
|
|
67
|
-
export function registerRememberTools(input: RegisterRememberToolsInput): void {
|
|
68
|
-
const router = input.router ?? createRememberRouter({ db: input.db });
|
|
69
|
-
input.server.registerTool(
|
|
70
|
-
"remember",
|
|
71
|
-
{
|
|
72
|
-
description:
|
|
73
|
-
"Create governed durable knowledge or a mandatory workspace instruction. Skills now use skill_save; the legacy preference lane returns a redirect without writing. When memory_save is available, use it for ordinary durable facts, decisions, incidents, bug fixes, and confirmed outcomes; 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=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. Do not copy one item into multiple lanes. ` +
|
|
75
|
-
"Under Autonomous learning, an eligible workspace instruction may activate immediately through its governed lifecycle. Under Require approval, 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
|
-
inputSchema: {
|
|
77
|
-
lane: z.enum(["preference", "instruction_policy", "knowledge"]),
|
|
78
|
-
...laneFields,
|
|
79
|
-
stableKey: z
|
|
80
|
-
.string()
|
|
81
|
-
.trim()
|
|
82
|
-
.min(1)
|
|
83
|
-
.max(128)
|
|
84
|
-
.regex(/^[a-z0-9](?:[a-z0-9._-]*[a-z0-9])?$/)
|
|
85
|
-
.optional(),
|
|
86
|
-
title: z.string().trim().min(1).max(PREFERENCE_REGISTRY_TITLE_MAX_CHARS).optional(),
|
|
87
|
-
description: z
|
|
88
|
-
.string()
|
|
89
|
-
.trim()
|
|
90
|
-
.min(1)
|
|
91
|
-
.max(PREFERENCE_REGISTRY_DESCRIPTOR_DESCRIPTION_MAX_CHARS)
|
|
92
|
-
.optional(),
|
|
93
|
-
target: WorkspaceInstructionPolicyTarget.optional(),
|
|
94
|
-
subject: z.string().trim().min(1).max(512).optional(),
|
|
95
|
-
},
|
|
96
|
-
},
|
|
97
|
-
async (request) => {
|
|
98
|
-
await input.authorize();
|
|
99
|
-
const { lane, operationId, content, reason } = request;
|
|
100
|
-
if (lane === "preference")
|
|
101
|
-
return input.json({
|
|
102
|
-
status: "not_remembered",
|
|
103
|
-
code: "use_skill_save",
|
|
104
|
-
message:
|
|
105
|
-
"Skills use the shared file lifecycle. Read opengeni-skills with skill_read, then discover skill_save. No Knowledge evidence or confirmation question is needed for Skill edits.",
|
|
106
|
-
});
|
|
107
|
-
if (lane !== "knowledge" && content.length > laneContentMaxChars[lane]) {
|
|
108
|
-
return input.json({
|
|
109
|
-
status: "not_remembered",
|
|
110
|
-
code: "content_too_long",
|
|
111
|
-
message: agentAuthoredDurableTextTooLongMessage({
|
|
112
|
-
kind: lane,
|
|
113
|
-
actualChars: content.length,
|
|
114
|
-
}),
|
|
115
|
-
});
|
|
116
|
-
}
|
|
117
|
-
const base = { operationId, content, reason, scope: "workspace" as const };
|
|
118
|
-
const rememberRequest =
|
|
119
|
-
lane === "instruction_policy"
|
|
120
|
-
? { ...base, lane, target: request.target }
|
|
121
|
-
: { ...base, lane, subject: request.subject ?? content.slice(0, 80) };
|
|
122
|
-
try {
|
|
123
|
-
return input.json(
|
|
124
|
-
await router.remember({ attempt: input.attempt, request: rememberRequest }),
|
|
125
|
-
);
|
|
126
|
-
} catch (error) {
|
|
127
|
-
if (error instanceof PreferenceRegistryStableKeyConflictError) {
|
|
128
|
-
return input.json({
|
|
129
|
-
status: "not_remembered",
|
|
130
|
-
code: "preference_stable_key_conflict",
|
|
131
|
-
message: error.message,
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
throw error;
|
|
135
|
-
}
|
|
136
|
-
},
|
|
137
|
-
);
|
|
138
|
-
|
|
139
|
-
input.server.registerTool(
|
|
140
|
-
"remember_confirm",
|
|
141
|
-
{
|
|
142
|
-
description:
|
|
143
|
-
"Complete a `remember` that returned status=confirmation_required after the human answered the bound `request_human_input` question. For preference/instruction_policy pass proposalId and learning.receiptId (as decisionReceiptId) from that receipt; for knowledge pass claimId. Always pass the requestId returned by request_human_input. Activation only succeeds when the exact initiating human answered Save on this turn; confirmed knowledge is materialized into searchable Memory from the exact approved text.",
|
|
144
|
-
inputSchema: {
|
|
145
|
-
operationId: z.string().uuid(),
|
|
146
|
-
proposalId: z.string().uuid().optional(),
|
|
147
|
-
decisionReceiptId: z.string().uuid().optional(),
|
|
148
|
-
claimId: z.string().uuid().optional(),
|
|
149
|
-
humanInputRequestId: z.string().uuid(),
|
|
150
|
-
},
|
|
151
|
-
},
|
|
152
|
-
async (request) => {
|
|
153
|
-
await input.authorize();
|
|
154
|
-
const confirmRequest =
|
|
155
|
-
request.proposalId && request.decisionReceiptId
|
|
156
|
-
? {
|
|
157
|
-
target: "proposal" as const,
|
|
158
|
-
operationId: request.operationId,
|
|
159
|
-
proposalId: request.proposalId,
|
|
160
|
-
decisionReceiptId: request.decisionReceiptId,
|
|
161
|
-
humanInputRequestId: request.humanInputRequestId,
|
|
162
|
-
}
|
|
163
|
-
: request.claimId
|
|
164
|
-
? {
|
|
165
|
-
target: "knowledge_claim" as const,
|
|
166
|
-
operationId: request.operationId,
|
|
167
|
-
claimId: request.claimId,
|
|
168
|
-
humanInputRequestId: request.humanInputRequestId,
|
|
169
|
-
}
|
|
170
|
-
: null;
|
|
171
|
-
if (!confirmRequest) {
|
|
172
|
-
return input.json({
|
|
173
|
-
status: "not_confirmed",
|
|
174
|
-
code: "invalid_target",
|
|
175
|
-
message:
|
|
176
|
-
"Pass proposalId + decisionReceiptId (preference/instruction_policy) or claimId (knowledge).",
|
|
177
|
-
});
|
|
178
|
-
}
|
|
179
|
-
try {
|
|
180
|
-
return input.json(
|
|
181
|
-
await router.confirm({ attempt: input.attempt, request: confirmRequest }),
|
|
182
|
-
);
|
|
183
|
-
} catch (error) {
|
|
184
|
-
if (error instanceof RememberError) {
|
|
185
|
-
return input.json({ status: "not_confirmed", code: error.code, message: error.message });
|
|
186
|
-
}
|
|
187
|
-
throw error;
|
|
188
|
-
}
|
|
189
|
-
},
|
|
190
|
-
);
|
|
191
|
-
}
|