@opengeni/api-router 0.17.0 → 0.21.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/dist/app.js +1 -1
- package/dist/{chunk-MWBF2GXL.js → chunk-5EEC7Q6C.js} +852 -111
- package/dist/chunk-5EEC7Q6C.js.map +1 -0
- package/dist/codex-realtime.d.ts +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/integrations/google-drive.d.ts +16 -1
- package/dist/mcp/documents.d.ts +3 -3
- package/dist/workspace-state-projection.d.ts +29 -1
- package/package.json +11 -11
- package/src/app.ts +33 -2
- package/src/codex-realtime.ts +4 -0
- package/src/index.ts +3 -2
- package/src/integrations/google-drive.ts +385 -20
- package/src/mcp/documents.ts +49 -27
- package/src/routes/connections.ts +61 -9
- package/src/routes/documents.ts +134 -43
- package/src/routes/workspace-instruction-policies.ts +118 -0
- package/src/routes/workspace-state.ts +46 -1
- package/src/workspace-state-projection.ts +203 -4
- package/dist/chunk-MWBF2GXL.js.map +0 -1
|
@@ -2,11 +2,14 @@ import {
|
|
|
2
2
|
WORKSPACE_STATE_MAX_BASES,
|
|
3
3
|
WORKSPACE_STATE_MAX_TOPICS,
|
|
4
4
|
WORKSPACE_STATE_TOPIC_MAX_CHARS,
|
|
5
|
+
WorkspaceStateQuery,
|
|
5
6
|
WorkspaceStateResponse,
|
|
6
7
|
} from "@opengeni/contracts";
|
|
7
8
|
import { hasPermission, requireAccessGrant, type ApiRouteDeps } from "@opengeni/core";
|
|
8
9
|
import {
|
|
9
10
|
getWorkspace,
|
|
11
|
+
getCurrentPreferenceRegistryGovernanceMetadata,
|
|
12
|
+
getWorkspaceStateAcceptedAttemptGovernance,
|
|
10
13
|
listWorkspaceStateMemoryRecords,
|
|
11
14
|
listWorkspaceInstructionPolicyRevisions,
|
|
12
15
|
} from "@opengeni/db";
|
|
@@ -19,11 +22,12 @@ import { projectWorkspaceState } from "../workspace-state-projection";
|
|
|
19
22
|
export function registerWorkspaceStateRoutes(app: Hono, deps: ApiRouteDeps): void {
|
|
20
23
|
app.get("/v1/workspaces/:workspaceId/workspace-state", async (context) => {
|
|
21
24
|
const workspaceId = context.req.param("workspaceId");
|
|
25
|
+
const query = WorkspaceStateQuery.parse(context.req.query());
|
|
22
26
|
const grant = await requireAccessGrant(context, deps, workspaceId, "workspace:read");
|
|
23
27
|
const generatedAt = new Date().toISOString();
|
|
24
28
|
const canInspectKnowledge = hasPermission(grant.permissions, "documents:search");
|
|
25
29
|
|
|
26
|
-
const [workspace, policies, knowledge] = await Promise.all([
|
|
30
|
+
const [workspace, policies, knowledge, attemptGovernance] = await Promise.all([
|
|
27
31
|
getWorkspace(deps.db, workspaceId),
|
|
28
32
|
listWorkspaceInstructionPolicyRevisions(deps.db, workspaceId, { limit: 1 }),
|
|
29
33
|
canInspectKnowledge
|
|
@@ -40,6 +44,46 @@ export function registerWorkspaceStateRoutes(app: Hono, deps: ApiRouteDeps): voi
|
|
|
40
44
|
return { documents, memories };
|
|
41
45
|
})()
|
|
42
46
|
: Promise.resolve(null),
|
|
47
|
+
query.attemptId
|
|
48
|
+
? getWorkspaceStateAcceptedAttemptGovernance(deps.db, {
|
|
49
|
+
accountId: grant.accountId,
|
|
50
|
+
workspaceId,
|
|
51
|
+
subjectId: grant.subjectId,
|
|
52
|
+
attemptId: query.attemptId,
|
|
53
|
+
}).then(async (snapshot) => {
|
|
54
|
+
if (!snapshot) return { status: "unavailable" as const };
|
|
55
|
+
const currentPreferences = await getCurrentPreferenceRegistryGovernanceMetadata(
|
|
56
|
+
deps.db,
|
|
57
|
+
{
|
|
58
|
+
workspaceId,
|
|
59
|
+
subjectId: grant.subjectId,
|
|
60
|
+
},
|
|
61
|
+
);
|
|
62
|
+
return {
|
|
63
|
+
status: "available" as const,
|
|
64
|
+
attemptId: snapshot.attemptId,
|
|
65
|
+
executionGeneration: snapshot.executionGeneration,
|
|
66
|
+
acceptedAt: snapshot.acceptedAt,
|
|
67
|
+
policySnapshot: snapshot.policySnapshot,
|
|
68
|
+
preferenceSnapshot: snapshot.preferenceSnapshot
|
|
69
|
+
? {
|
|
70
|
+
id: snapshot.preferenceSnapshot.id,
|
|
71
|
+
descriptorHash: snapshot.preferenceSnapshot.descriptorHash,
|
|
72
|
+
descriptors: snapshot.preferenceSnapshot.descriptors.map((descriptor) => ({
|
|
73
|
+
id: descriptor.id,
|
|
74
|
+
revisionId: descriptor.revisionId,
|
|
75
|
+
contentHash: descriptor.contentHash,
|
|
76
|
+
activeVersion: descriptor.activeVersion,
|
|
77
|
+
scope: descriptor.scope,
|
|
78
|
+
})),
|
|
79
|
+
truncated: snapshot.preferenceSnapshot.truncated,
|
|
80
|
+
createdAt: snapshot.preferenceSnapshot.createdAt,
|
|
81
|
+
}
|
|
82
|
+
: null,
|
|
83
|
+
currentPreferences,
|
|
84
|
+
};
|
|
85
|
+
})
|
|
86
|
+
: Promise.resolve(null),
|
|
43
87
|
]);
|
|
44
88
|
|
|
45
89
|
if (!workspace) {
|
|
@@ -54,6 +98,7 @@ export function registerWorkspaceStateRoutes(app: Hono, deps: ApiRouteDeps): voi
|
|
|
54
98
|
workspaceAgentInstructions: workspace.agentInstructions,
|
|
55
99
|
policies,
|
|
56
100
|
knowledge,
|
|
101
|
+
attemptGovernance,
|
|
57
102
|
}),
|
|
58
103
|
),
|
|
59
104
|
);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import {
|
|
2
3
|
KnowledgeMemoryKind,
|
|
3
4
|
KnowledgeMemoryStatus,
|
|
@@ -10,6 +11,8 @@ import {
|
|
|
10
11
|
WORKSPACE_STATE_TOPIC_MAX_CHARS,
|
|
11
12
|
WorkspaceStateResponse,
|
|
12
13
|
type WorkspaceInstructionPolicyListResponse,
|
|
14
|
+
type WorkspaceInstructionPolicySnapshot,
|
|
15
|
+
type WorkspaceStateGovernanceDriftStatus,
|
|
13
16
|
type WorkspaceStateGap,
|
|
14
17
|
type WorkspaceStateMemoryKindCounts,
|
|
15
18
|
type WorkspaceStateMemoryStatusCounts,
|
|
@@ -23,14 +26,213 @@ type KnowledgeProjectionInput = {
|
|
|
23
26
|
memories: WorkspaceStateMemoryRecord[];
|
|
24
27
|
};
|
|
25
28
|
|
|
29
|
+
type PreferenceGovernanceIdentity = {
|
|
30
|
+
id: string;
|
|
31
|
+
revisionId: string;
|
|
32
|
+
contentHash: string;
|
|
33
|
+
activeVersion: number;
|
|
34
|
+
scope: "organization" | "workspace" | "user";
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
type AttemptGovernanceProjectionInput =
|
|
38
|
+
| { status: "unavailable" }
|
|
39
|
+
| {
|
|
40
|
+
status: "available";
|
|
41
|
+
attemptId: string;
|
|
42
|
+
executionGeneration: number;
|
|
43
|
+
acceptedAt: string;
|
|
44
|
+
policySnapshot: WorkspaceInstructionPolicySnapshot | null;
|
|
45
|
+
preferenceSnapshot: {
|
|
46
|
+
id: string;
|
|
47
|
+
descriptorHash: string;
|
|
48
|
+
descriptors: PreferenceGovernanceIdentity[];
|
|
49
|
+
truncated: boolean;
|
|
50
|
+
createdAt: string;
|
|
51
|
+
} | null;
|
|
52
|
+
currentPreferences: {
|
|
53
|
+
descriptors: PreferenceGovernanceIdentity[];
|
|
54
|
+
truncated: boolean;
|
|
55
|
+
};
|
|
56
|
+
};
|
|
57
|
+
|
|
26
58
|
export type WorkspaceStateProjectionInput = {
|
|
27
59
|
workspaceId: string;
|
|
28
60
|
generatedAt: string;
|
|
29
61
|
workspaceAgentInstructions: string | null;
|
|
30
62
|
policies: WorkspaceInstructionPolicyListResponse;
|
|
31
63
|
knowledge: KnowledgeProjectionInput | null;
|
|
64
|
+
attemptGovernance?: AttemptGovernanceProjectionInput | null;
|
|
32
65
|
};
|
|
33
66
|
|
|
67
|
+
function hashIdentities(values: readonly string[]): string {
|
|
68
|
+
return createHash("sha256").update(values.join("\n"), "utf8").digest("hex");
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function policyTargetKey(value: { kind: string; scope: string; roleKey: string | null }): string {
|
|
72
|
+
return `${value.kind}:${value.scope}:${value.roleKey ?? ""}`;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function policyTargetKeysForRole(policyRole: string | null): Set<string> {
|
|
76
|
+
const keys = new Set(["charter:global:", "policy:global:"]);
|
|
77
|
+
if (policyRole !== null) keys.add(`policy:role:${policyRole}`);
|
|
78
|
+
return keys;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function policyIdentity(value: {
|
|
82
|
+
kind: string;
|
|
83
|
+
scope: string;
|
|
84
|
+
roleKey: string | null;
|
|
85
|
+
revisionId: string;
|
|
86
|
+
contentHash: string;
|
|
87
|
+
activationVersion: number;
|
|
88
|
+
}): string {
|
|
89
|
+
return `${policyTargetKey(value)}:${value.revisionId}:${value.contentHash}:${value.activationVersion}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
function preferenceIdentity(value: PreferenceGovernanceIdentity): string {
|
|
93
|
+
return `${value.scope}:${value.id}:${value.revisionId}:${value.contentHash}:${value.activeVersion}`;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
function classifyIdentityDrift(
|
|
97
|
+
snapshotIdentities: readonly string[],
|
|
98
|
+
currentIdentities: readonly string[],
|
|
99
|
+
snapshotKeys: readonly string[],
|
|
100
|
+
currentKeys: readonly string[],
|
|
101
|
+
): "identical" | "changed" | "superseded" {
|
|
102
|
+
if (snapshotIdentities.join("\n") === currentIdentities.join("\n")) return "identical";
|
|
103
|
+
return snapshotKeys.join("\n") === currentKeys.join("\n") ? "superseded" : "changed";
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function overallDriftStatus(
|
|
107
|
+
policy: WorkspaceStateGovernanceDriftStatus,
|
|
108
|
+
preferences: WorkspaceStateGovernanceDriftStatus,
|
|
109
|
+
): WorkspaceStateGovernanceDriftStatus {
|
|
110
|
+
for (const status of ["unavailable", "truncated", "missing", "changed", "superseded"] as const) {
|
|
111
|
+
if (policy === status || preferences === status) return status;
|
|
112
|
+
}
|
|
113
|
+
return "identical";
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
function attemptGovernanceProjection(input: WorkspaceStateProjectionInput) {
|
|
117
|
+
const governance = input.attemptGovernance ?? null;
|
|
118
|
+
if (governance === null) return { status: "not_requested" as const };
|
|
119
|
+
if (governance.status === "unavailable") {
|
|
120
|
+
return {
|
|
121
|
+
status: "unavailable" as const,
|
|
122
|
+
reason: "attempt_not_found_or_not_authorized" as const,
|
|
123
|
+
driftStatus: "unavailable" as const,
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
const policySnapshot = governance.policySnapshot;
|
|
128
|
+
let policyStatus: WorkspaceStateGovernanceDriftStatus = "missing";
|
|
129
|
+
let policySnapshotHash: string | null = null;
|
|
130
|
+
let policyCurrentHash: string | null = null;
|
|
131
|
+
let policySnapshotTargetCount = 0;
|
|
132
|
+
let policyCurrentTargetCount = 0;
|
|
133
|
+
if (policySnapshot) {
|
|
134
|
+
const snapshotEntries = [...policySnapshot.entries].sort((left, right) =>
|
|
135
|
+
policyTargetKey(left).localeCompare(policyTargetKey(right)),
|
|
136
|
+
);
|
|
137
|
+
const snapshotKeys = snapshotEntries.map(policyTargetKey);
|
|
138
|
+
const relevantTargetKeys = policyTargetKeysForRole(policySnapshot.policyRole);
|
|
139
|
+
const currentEntries = input.policies.activeHeads
|
|
140
|
+
.filter((head) => relevantTargetKeys.has(policyTargetKey(head)))
|
|
141
|
+
.sort((left, right) => policyTargetKey(left).localeCompare(policyTargetKey(right)));
|
|
142
|
+
const snapshotIdentities = snapshotEntries.map(policyIdentity);
|
|
143
|
+
const currentIdentities = currentEntries.map(policyIdentity);
|
|
144
|
+
const currentKeys = currentEntries.map(policyTargetKey);
|
|
145
|
+
policyStatus = classifyIdentityDrift(
|
|
146
|
+
snapshotIdentities,
|
|
147
|
+
currentIdentities,
|
|
148
|
+
snapshotKeys,
|
|
149
|
+
currentKeys,
|
|
150
|
+
);
|
|
151
|
+
policySnapshotHash = hashIdentities(snapshotIdentities);
|
|
152
|
+
policyCurrentHash = hashIdentities(currentIdentities);
|
|
153
|
+
policySnapshotTargetCount = snapshotEntries.length;
|
|
154
|
+
policyCurrentTargetCount = currentEntries.length;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const preferenceSnapshot = governance.preferenceSnapshot;
|
|
158
|
+
const currentPreferences = [...governance.currentPreferences.descriptors].sort((left, right) =>
|
|
159
|
+
preferenceIdentity(left).localeCompare(preferenceIdentity(right)),
|
|
160
|
+
);
|
|
161
|
+
let preferenceStatus: WorkspaceStateGovernanceDriftStatus = "missing";
|
|
162
|
+
let preferenceSnapshotHash: string | null = null;
|
|
163
|
+
const currentPreferenceIdentities = currentPreferences.map(preferenceIdentity);
|
|
164
|
+
const currentPreferenceHash = hashIdentities(currentPreferenceIdentities);
|
|
165
|
+
let snapshotPreferenceCount = 0;
|
|
166
|
+
let snapshotPreferenceTruncated = false;
|
|
167
|
+
if (preferenceSnapshot) {
|
|
168
|
+
const snapshotPreferences = [...preferenceSnapshot.descriptors].sort((left, right) =>
|
|
169
|
+
preferenceIdentity(left).localeCompare(preferenceIdentity(right)),
|
|
170
|
+
);
|
|
171
|
+
const snapshotPreferenceIdentities = snapshotPreferences.map(preferenceIdentity);
|
|
172
|
+
const snapshotPreferenceKeys = snapshotPreferences.map((descriptor) => descriptor.id).sort();
|
|
173
|
+
const currentPreferenceKeys = currentPreferences.map((descriptor) => descriptor.id).sort();
|
|
174
|
+
preferenceSnapshotHash = hashIdentities(snapshotPreferenceIdentities);
|
|
175
|
+
snapshotPreferenceCount = snapshotPreferences.length;
|
|
176
|
+
snapshotPreferenceTruncated = preferenceSnapshot.truncated;
|
|
177
|
+
preferenceStatus =
|
|
178
|
+
preferenceSnapshot.truncated || governance.currentPreferences.truncated
|
|
179
|
+
? "truncated"
|
|
180
|
+
: classifyIdentityDrift(
|
|
181
|
+
snapshotPreferenceIdentities,
|
|
182
|
+
currentPreferenceIdentities,
|
|
183
|
+
snapshotPreferenceKeys,
|
|
184
|
+
currentPreferenceKeys,
|
|
185
|
+
);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
return {
|
|
189
|
+
status: "available" as const,
|
|
190
|
+
attemptId: governance.attemptId,
|
|
191
|
+
executionGeneration: governance.executionGeneration,
|
|
192
|
+
acceptedAt: governance.acceptedAt,
|
|
193
|
+
policySnapshot: policySnapshot
|
|
194
|
+
? {
|
|
195
|
+
status: "available" as const,
|
|
196
|
+
id: policySnapshot.id,
|
|
197
|
+
createdAt: policySnapshot.createdAt,
|
|
198
|
+
entryHash: policySnapshot.entryHash,
|
|
199
|
+
policyRole: policySnapshot.policyRole,
|
|
200
|
+
roleSource: policySnapshot.roleSource,
|
|
201
|
+
entries: policySnapshot.entries,
|
|
202
|
+
}
|
|
203
|
+
: { status: "missing" as const },
|
|
204
|
+
preferenceSnapshot: preferenceSnapshot
|
|
205
|
+
? {
|
|
206
|
+
status: "available" as const,
|
|
207
|
+
id: preferenceSnapshot.id,
|
|
208
|
+
createdAt: preferenceSnapshot.createdAt,
|
|
209
|
+
descriptorHash: preferenceSnapshot.descriptorHash,
|
|
210
|
+
descriptorCount: preferenceSnapshot.descriptors.length,
|
|
211
|
+
truncated: preferenceSnapshot.truncated,
|
|
212
|
+
}
|
|
213
|
+
: { status: "missing" as const },
|
|
214
|
+
drift: {
|
|
215
|
+
overall: overallDriftStatus(policyStatus, preferenceStatus),
|
|
216
|
+
policy: {
|
|
217
|
+
status: policyStatus,
|
|
218
|
+
snapshotHash: policySnapshotHash,
|
|
219
|
+
currentHash: policyCurrentHash,
|
|
220
|
+
snapshotTargetCount: policySnapshotTargetCount,
|
|
221
|
+
currentTargetCount: policyCurrentTargetCount,
|
|
222
|
+
},
|
|
223
|
+
preferences: {
|
|
224
|
+
status: preferenceStatus,
|
|
225
|
+
snapshotHash: preferenceSnapshotHash,
|
|
226
|
+
currentHash: currentPreferenceHash,
|
|
227
|
+
snapshotDescriptorCount: snapshotPreferenceCount,
|
|
228
|
+
currentDescriptorCount: currentPreferences.length,
|
|
229
|
+
snapshotTruncated: snapshotPreferenceTruncated,
|
|
230
|
+
currentTruncated: governance.currentPreferences.truncated,
|
|
231
|
+
},
|
|
232
|
+
},
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
|
|
34
236
|
function emptyMemoryStatusCounts(): WorkspaceStateMemoryStatusCounts {
|
|
35
237
|
return Object.fromEntries(
|
|
36
238
|
KnowledgeMemoryStatus.options.map((status) => [status, 0]),
|
|
@@ -227,10 +429,7 @@ export function projectWorkspaceState(
|
|
|
227
429
|
generatedAt: input.generatedAt,
|
|
228
430
|
truth: {
|
|
229
431
|
current: { source: "read_time_projection", capturedAt: input.generatedAt },
|
|
230
|
-
|
|
231
|
-
status: "not_captured",
|
|
232
|
-
reason: "workspace_instruction_policy_snapshot_not_implemented",
|
|
233
|
-
},
|
|
432
|
+
attemptGovernance: attemptGovernanceProjection(input),
|
|
234
433
|
},
|
|
235
434
|
policy: policyProjection(input),
|
|
236
435
|
knowledge: input.knowledge
|