granttap-mcp 0.8.90 → 0.8.91
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/apps/bridge/src/host/session-keys.ts +2 -1
- package/apps/bridge/src/mesh/knowledge/README.md +8 -0
- package/apps/bridge/src/mesh/knowledge/read.ts +65 -0
- package/apps/bridge/src/mesh/knowledge/runtime-read.ts +49 -0
- package/apps/bridge/src/monitor/handlers/inbound.ts +3 -0
- package/apps/bridge/src/policy/governed-projects.ts +1 -1
- package/apps/bridge/src/task-routing/admission/index.ts +2 -1
- package/apps/mcp/src/desktop/engine-bridge.ts +1 -0
- package/apps/mcp/src/desktop/operations/index.ts +2 -0
- package/cursor-plugin/README.md +1 -1
- package/cursor-plugin/mcp.json +1 -1
- package/cursor-plugin/stdio-bootstrap.cjs +1 -1
- package/package.json +2 -2
- package/packages/protocol/messages/approval-questions/index.ts +1 -1
- package/packages/protocol/messages/mesh/knowledge/refresh.ts +44 -0
- package/packages/protocol/messages/sessions/index.ts +2 -2
- package/packages/protocol/schema.ts +4 -0
|
@@ -8,6 +8,7 @@ import type {
|
|
|
8
8
|
MeshEvent,
|
|
9
9
|
MeshSnapshot,
|
|
10
10
|
MeshInvocationPage,
|
|
11
|
+
ProjectKnowledgePage,
|
|
11
12
|
Payload,
|
|
12
13
|
ProjectPolicyPayload,
|
|
13
14
|
Role,
|
|
@@ -53,7 +54,7 @@ export async function sendMeshPayload(
|
|
|
53
54
|
|
|
54
55
|
export async function sendProjectPayload(
|
|
55
56
|
client: RelayClient,
|
|
56
|
-
payload: ProjectPolicyPayload | MeshClaimReleaseResult | MeshInvocationPage,
|
|
57
|
+
payload: ProjectPolicyPayload | MeshClaimReleaseResult | MeshInvocationPage | ProjectKnowledgePage,
|
|
57
58
|
to: Role | "all" = "phone",
|
|
58
59
|
options: SendOptions = {},
|
|
59
60
|
): Promise<void> {
|
|
@@ -12,3 +12,11 @@ Engine validates its scope. The phone may replay the same ID after a lost reply.
|
|
|
12
12
|
This is not a migration of old chats into verified knowledge.
|
|
13
13
|
|
|
14
14
|
GrantTap Commercial Source License.
|
|
15
|
+
|
|
16
|
+
`read.ts` is the bounded Project evidence read: Memory and the invocation journal
|
|
17
|
+
run in parallel with independent deadlines. Calls may belong to older Tasks
|
|
18
|
+
outside the current phone snapshot. A failed source leaves the other source
|
|
19
|
+
available. Whole records are omitted to fit the encrypted frame budget; record
|
|
20
|
+
content is never shortened. `runtime-read.ts` exposes this read over local Mac
|
|
21
|
+
IPC and an authenticated, requester-scoped Project relay response. It does not
|
|
22
|
+
rescan provider chats or rebuild architecture.
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { MeshSnapshot, ProjectKnowledgeRecord } from "../../../../../packages/protocol/schema";
|
|
2
|
+
import { ProjectKnowledgePage, ProjectKnowledgeQuery } from "../../../../../packages/protocol/messages/mesh/knowledge/refresh";
|
|
3
|
+
import type { InvocationHistoryPage } from "../../engine/protocol/engine-invocation-protocol";
|
|
4
|
+
import { activeProjectKnowledge, supersededProjectKnowledgeIds } from "./active";
|
|
5
|
+
|
|
6
|
+
export type KnowledgeReadDependencies = {
|
|
7
|
+
snapshot: (projectId: string) => MeshSnapshot | undefined;
|
|
8
|
+
memory: (projectId: string) => Promise<ProjectKnowledgeRecord[] | undefined>;
|
|
9
|
+
history: (projectId: string) => Promise<InvocationHistoryPage | undefined>;
|
|
10
|
+
endpointId: string;
|
|
11
|
+
now: () => number;
|
|
12
|
+
timeoutMs?: number;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export async function readProjectKnowledge(
|
|
16
|
+
query: ProjectKnowledgeQuery, dependencies: KnowledgeReadDependencies,
|
|
17
|
+
): Promise<ProjectKnowledgePage | undefined> {
|
|
18
|
+
if (!ProjectKnowledgeQuery.safeParse(query).success) return undefined;
|
|
19
|
+
const snapshot = dependencies.snapshot(query.projectId);
|
|
20
|
+
if (!snapshot || snapshot.projectId !== query.projectId) return undefined;
|
|
21
|
+
const timeout = dependencies.timeoutMs ?? 2_000;
|
|
22
|
+
let [memory, history] = await Promise.all([
|
|
23
|
+
boundedSource(() => dependencies.memory(query.projectId), timeout),
|
|
24
|
+
boundedSource(() => dependencies.history(query.projectId), timeout),
|
|
25
|
+
]);
|
|
26
|
+
if (memory?.some(record => record.projectId !== query.projectId || record.visibility !== "project")) {
|
|
27
|
+
memory = undefined;
|
|
28
|
+
}
|
|
29
|
+
if (history?.events.some(row => row.event.project_id !== query.projectId)) history = undefined;
|
|
30
|
+
const records = memory ?? [];
|
|
31
|
+
const knowledge = activeProjectKnowledge(query.projectId, records)
|
|
32
|
+
.sort((a, b) => b.recordedAt - a.recordedAt).slice(0, 32);
|
|
33
|
+
const invocations = (history?.events ?? []).slice(-32);
|
|
34
|
+
const page: ProjectKnowledgePage = {
|
|
35
|
+
type: "mesh.knowledge.page", sessionId: query.projectId, projectId: query.projectId,
|
|
36
|
+
requestId: query.requestId, sourceEndpointId: dependencies.endpointId,
|
|
37
|
+
memoryAvailability: memory ? "ready" : "unavailable",
|
|
38
|
+
invocationAvailability: history ? "ready" : "unavailable",
|
|
39
|
+
knowledge, invocations,
|
|
40
|
+
supersededKnowledgeRecordIds: supersededProjectKnowledgeIds(query.projectId, records),
|
|
41
|
+
incomplete: records.length > knowledge.length || history?.has_older === true
|
|
42
|
+
|| history?.has_more === true,
|
|
43
|
+
generatedAt: dependencies.now(),
|
|
44
|
+
};
|
|
45
|
+
// Keep encrypted frames below the transport limit without shortening a fact.
|
|
46
|
+
while (Buffer.byteLength(JSON.stringify(page)) > 128 * 1_024
|
|
47
|
+
&& (knowledge.length > 0 || invocations.length > 0)) {
|
|
48
|
+
const oldestRecord = knowledge.at(-1)?.recordedAt ?? Infinity;
|
|
49
|
+
const oldestCall = invocations[0]?.event.occurred_at ?? Infinity;
|
|
50
|
+
if (oldestRecord <= oldestCall) knowledge.pop();
|
|
51
|
+
else invocations.shift();
|
|
52
|
+
page.incomplete = true;
|
|
53
|
+
}
|
|
54
|
+
return ProjectKnowledgePage.parse(page);
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
async function boundedSource<T>(read: () => Promise<T>, timeoutMs: number): Promise<T | undefined> {
|
|
58
|
+
let timer: ReturnType<typeof setTimeout> | undefined;
|
|
59
|
+
try {
|
|
60
|
+
return await Promise.race([Promise.resolve().then(read), new Promise<undefined>(resolve => {
|
|
61
|
+
timer = setTimeout(() => resolve(undefined), timeoutMs);
|
|
62
|
+
})]);
|
|
63
|
+
} catch { return undefined; }
|
|
64
|
+
finally { if (timer) clearTimeout(timer); }
|
|
65
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { join } from "node:path";
|
|
2
|
+
import type { RelayClient } from "../../../../../packages/core/relay-client";
|
|
3
|
+
import { ProjectKnowledgeQuery } from "../../../../../packages/protocol/messages/mesh/knowledge/refresh";
|
|
4
|
+
import { configDir } from "../../config/runtime/paths";
|
|
5
|
+
import { EngineClient } from "../../engine/runtime/engine-client";
|
|
6
|
+
import { engineFeatureEnabled } from "../../engine/runtime/engine-supervisor";
|
|
7
|
+
import { projectKnowledge } from "../../engine/runtime/engine-memory";
|
|
8
|
+
import { sendProjectPayload } from "../../host/session-keys";
|
|
9
|
+
import { computerId } from "../identity/computer";
|
|
10
|
+
import { localMeshStore } from "../local-remote/local";
|
|
11
|
+
import { readProjectKnowledge } from "./read";
|
|
12
|
+
|
|
13
|
+
const engine = new EngineClient({ socketPath: join(configDir(), "engine.sock") });
|
|
14
|
+
|
|
15
|
+
export async function currentProjectKnowledge(query: ProjectKnowledgeQuery) {
|
|
16
|
+
return readProjectKnowledge(query, {
|
|
17
|
+
snapshot: projectId => localMeshStore().snapshot(projectId),
|
|
18
|
+
endpointId: computerId(), now: Date.now,
|
|
19
|
+
memory: projectId => projectKnowledge(projectId),
|
|
20
|
+
history: async projectId => {
|
|
21
|
+
if (!engineFeatureEnabled()) return undefined;
|
|
22
|
+
const result = await engine.request({ operation: "invocation.history",
|
|
23
|
+
input: { project_id: projectId, tail: true, limit: 32 } }, { timeoutMs: 1_000 });
|
|
24
|
+
return result.operation === "invocation.history" ? result.page : undefined;
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export async function handleProjectKnowledgeQuery(
|
|
30
|
+
client: RelayClient, query: ProjectKnowledgeQuery, peerPublicKey?: string,
|
|
31
|
+
): Promise<boolean> {
|
|
32
|
+
if (!peerPublicKey) return false;
|
|
33
|
+
const page = await currentProjectKnowledge(query);
|
|
34
|
+
if (!page) return false;
|
|
35
|
+
if (page.memoryAvailability === "ready") {
|
|
36
|
+
localMeshStore().cacheKnowledge(page.projectId, page.knowledge);
|
|
37
|
+
}
|
|
38
|
+
await sendProjectPayload(client, page, "phone", {
|
|
39
|
+
peerPublicKey, ttlMs: 15_000, reliable: false,
|
|
40
|
+
}).catch(() => {});
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function desktopProjectKnowledge(input: unknown) {
|
|
45
|
+
const value = input as { project_id?: unknown; request_id?: unknown } | undefined;
|
|
46
|
+
const query = ProjectKnowledgeQuery.safeParse({ type: "mesh.knowledge.query",
|
|
47
|
+
projectId: value?.project_id, sessionId: value?.project_id, requestId: value?.request_id });
|
|
48
|
+
return query.success ? currentProjectKnowledge(query.data) : undefined;
|
|
49
|
+
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
} from "../../mesh/runtime";
|
|
19
19
|
import { releaseClaimByPerson, releaseResult } from "../../mesh/admin";
|
|
20
20
|
import { handleInvocationQuery } from "../../engine/invocation/query";
|
|
21
|
+
import { handleProjectKnowledgeQuery } from "../../mesh/knowledge/runtime-read";
|
|
21
22
|
import { applyPairingJoin } from "../../pairing";
|
|
22
23
|
import { recordPhoneSeen } from "../../pairing/presence";
|
|
23
24
|
import { handleProjectPolicySet } from "../../project-policy/runtime";
|
|
@@ -123,6 +124,8 @@ export async function handleMonitorMessage(
|
|
|
123
124
|
const accepted = requestProjectCapability(payload);
|
|
124
125
|
if (accepted) void publish().catch(() => {});
|
|
125
126
|
return accepted;
|
|
127
|
+
} else if (payload.type === "mesh.knowledge.query" && loadRuntimeConfig().meshEnabled) {
|
|
128
|
+
return handleProjectKnowledgeQuery(client, payload, input.peerPublicKey);
|
|
126
129
|
} else if (payload.type === "mesh.invocation.query" && loadRuntimeConfig().meshEnabled) {
|
|
127
130
|
return handleInvocationQuery(client, payload);
|
|
128
131
|
} else if ((payload.type === "mesh.event" || payload.type === "mesh.snapshot")
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
+
import { TaskRoutingNeeds } from '../../../../../packages/protocol/task-resources';
|
|
2
3
|
import { loadConfig, loadRuntimeConfig, machineConfigPath } from '../../config';
|
|
3
4
|
import { applyNetworkRoute } from '../../device-network/settings';
|
|
4
5
|
import { scanSessions } from '../../sessions';
|
|
@@ -14,7 +15,7 @@ import { observedRoutingSession } from '../observed-turn';
|
|
|
14
15
|
|
|
15
16
|
export const OffloadInput = z.object({ action: z.enum(['request', 'cancel', 'status']).optional(),
|
|
16
17
|
operationId: z.string().trim().min(1).max(128).optional(),
|
|
17
|
-
requirements:
|
|
18
|
+
requirements: TaskRoutingNeeds.partial().extend({ reason: RoutingRequirementsInput.shape.reason }).optional() }).strict();
|
|
18
19
|
export type OffloadArguments = z.infer<typeof OffloadInput>;
|
|
19
20
|
type Proof = { sessionId: string; provider: RoutingRequestSource['provider'] };
|
|
20
21
|
type Ports = { store: RoutingRequests; enabled: () => boolean;
|
|
@@ -21,6 +21,7 @@ export const DESKTOP_OPERATIONS = new Set([
|
|
|
21
21
|
"desktop.machine_load", "desktop.capability_usage", "desktop.task_image", "desktop.task_workspace",
|
|
22
22
|
"desktop.installed_skills", "desktop.policy_status", "desktop.policy_set", "desktop.project_auto_accept",
|
|
23
23
|
"desktop.mesh_snapshots",
|
|
24
|
+
"desktop.project_knowledge",
|
|
24
25
|
"desktop.task_send", "desktop.task_queue", "desktop.transfer_continue", "desktop.task_control", "desktop.task_preferences",
|
|
25
26
|
"desktop.task_handoff",
|
|
26
27
|
"desktop.project_transport",
|
|
@@ -20,6 +20,7 @@ import { desktopTaskHandoff } from "../delivery/task-handoff";
|
|
|
20
20
|
import { desktopTaskCreate } from "../delivery/task-create";
|
|
21
21
|
import { desktopMeshCreate } from "../delivery/mesh-create";
|
|
22
22
|
import { desktopInvocationHistory } from "../invocation";
|
|
23
|
+
import { desktopProjectKnowledge } from "../../../../bridge/src/mesh/knowledge/runtime-read";
|
|
23
24
|
import { desktopUsage } from "../projection/usage";
|
|
24
25
|
import { desktopInstalledSkills } from "../projection/installed-skills";
|
|
25
26
|
import type { DesktopControllerEnrollment } from "../pairing";
|
|
@@ -74,6 +75,7 @@ export function desktopReadOperation(input: {
|
|
|
74
75
|
if (operation === "desktop.invocation_history") {
|
|
75
76
|
return desktopInvocationHistory(queryInput, engine, storePath);
|
|
76
77
|
}
|
|
78
|
+
if (operation === "desktop.project_knowledge") return desktopProjectKnowledge(queryInput);
|
|
77
79
|
if (operation === "desktop.project") {
|
|
78
80
|
return Promise.resolve(desktopMeshProject(queryInput, storePath));
|
|
79
81
|
}
|
package/cursor-plugin/README.md
CHANGED
|
@@ -10,7 +10,7 @@ keeps each phone response tied to the exact originating chat and prompt.
|
|
|
10
10
|
Install the supported CLI on this computer, then run:
|
|
11
11
|
|
|
12
12
|
```bash
|
|
13
|
-
npm install -g granttap-mcp@0.8.
|
|
13
|
+
npm install -g granttap-mcp@0.8.91
|
|
14
14
|
granttap setup
|
|
15
15
|
granttap status
|
|
16
16
|
```
|
package/cursor-plugin/mcp.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"command": "node",
|
|
5
5
|
"args": [
|
|
6
6
|
"-e",
|
|
7
|
-
"\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.
|
|
7
|
+
"\"use strict\";\n\n// Cursor may start this MCP from any cwd. Execute JavaScript entry points with\n// Node itself: Windows batch shims require shell quoting that differs by host.\nconst { spawn } = require(\"node:child_process\");\nconst { existsSync } = require(\"node:fs\");\nconst { delimiter, dirname, join } = require(\"node:path\");\n\nconst PACKAGE = \"granttap-mcp@0.8.91\";\nconst dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === \"1\";\nconst platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM\n ? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;\nconst nodeRoot = dryRun && process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT\n ? process.env.GRANTTAP_BOOTSTRAP_NODE_ROOT : dirname(process.execPath);\nconst pathRoots = (process.env.PATH || \"\").split(delimiter).filter(Boolean);\nconst appData = process.env.APPDATA;\nconst roots = [nodeRoot, ...pathRoots, ...(appData ? [join(appData, \"npm\")] : [])];\nconst first = (paths) => paths.find((path) => existsSync(path));\n\nfunction launch() {\n if (platform !== \"win32\") {\n const installed = first(roots.map((root) => join(root, \"granttap-mcp\")));\n if (installed) return { command: installed, args: [] };\n const npx = first(roots.map((root) => join(root, \"npx\"))) || \"npx\";\n return { command: npx, args: [\"-y\", PACKAGE] };\n }\n const installed = first(roots.map((root) =>\n join(root, \"node_modules\", \"granttap-mcp\", \"bin\", \"granttap-mcp.mjs\")));\n if (installed) return { command: process.execPath, args: [installed] };\n const npx = first(roots.map((root) =>\n join(root, \"node_modules\", \"npm\", \"bin\", \"npx-cli.js\")));\n if (npx) return { command: process.execPath, args: [npx, \"-y\", PACKAGE] };\n throw new Error(\"Node.js/npm 22.13.0+ is required on this Windows device. Install npm and retry GrantTap.\");\n}\n\nlet target;\ntry { target = launch(); }\ncatch (error) {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n}\n\nif (dryRun) {\n process.stdout.write(JSON.stringify(target));\n process.exit(0);\n}\n\nconst child = spawn(target.command, target.args, { stdio: \"inherit\", windowsHide: true });\nchild.on(\"error\", (error) => {\n process.stderr.write(`[granttap] ${error.message}\\n`);\n process.exit(1);\n});\nchild.on(\"exit\", (code, signal) => {\n if (signal && platform !== \"win32\") {\n try { process.kill(process.pid, signal); } catch { process.exit(code ?? 1); }\n return;\n }\n process.exit(code ?? 1);\n});\n"
|
|
8
8
|
]
|
|
9
9
|
}
|
|
10
10
|
}
|
|
@@ -7,7 +7,7 @@ const { spawn } = require("node:child_process");
|
|
|
7
7
|
const { existsSync } = require("node:fs");
|
|
8
8
|
const { delimiter, dirname, join } = require("node:path");
|
|
9
9
|
|
|
10
|
-
const PACKAGE = "granttap-mcp@0.8.
|
|
10
|
+
const PACKAGE = "granttap-mcp@0.8.91";
|
|
11
11
|
const dryRun = process.env.GRANTTAP_BOOTSTRAP_DRY_RUN === "1";
|
|
12
12
|
const platform = dryRun && process.env.GRANTTAP_BOOTSTRAP_PLATFORM
|
|
13
13
|
? process.env.GRANTTAP_BOOTSTRAP_PLATFORM : process.platform;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "granttap-mcp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.91",
|
|
4
4
|
"description": "Commercial computer runtime connecting local coding agents to GrantTap on Mac, iPhone, iPad and Apple Watch.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"tsx": "^4.23.4",
|
|
43
43
|
"tweetnacl": "^1.0.3",
|
|
44
44
|
"ws": "^8.18.0",
|
|
45
|
-
"zod": "
|
|
45
|
+
"zod": "4.6.7"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@types/express": "^5.0.3",
|
|
@@ -15,7 +15,7 @@ export function questionAnswers(questions: z.infer<typeof ApprovalQuestions> | u
|
|
|
15
15
|
note: string | null | undefined): Record<string, string> | undefined {
|
|
16
16
|
if (!questions || !note || note.length > 20_000) return undefined;
|
|
17
17
|
try {
|
|
18
|
-
const answers = z.record(z.string().trim().min(1).max(4_000)).parse(JSON.parse(note));
|
|
18
|
+
const answers = z.record(z.string(), z.string().trim().min(1).max(4_000)).parse(JSON.parse(note));
|
|
19
19
|
if (Object.keys(answers).length !== questions.length
|
|
20
20
|
|| questions.some(item => !Object.hasOwn(answers, item.question))) return undefined;
|
|
21
21
|
return answers;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { z } from "zod";
|
|
2
|
+
import { Identifier } from "../endpoint";
|
|
3
|
+
import { MeshInvocationEvent } from "../invocations";
|
|
4
|
+
import { ProjectKnowledgeRecord } from "./index";
|
|
5
|
+
|
|
6
|
+
const Sequence = z.number().int().nonnegative().safe();
|
|
7
|
+
export const ProjectKnowledgeQuery = z.object({
|
|
8
|
+
type: z.literal("mesh.knowledge.query"),
|
|
9
|
+
sessionId: Identifier, projectId: Identifier, requestId: Identifier,
|
|
10
|
+
}).strict().refine(value => value.sessionId === value.projectId, "Project scope mismatch");
|
|
11
|
+
export type ProjectKnowledgeQuery = z.infer<typeof ProjectKnowledgeQuery>;
|
|
12
|
+
|
|
13
|
+
/** One bounded Project read; no architecture rebuild or per-Task fan-out. */
|
|
14
|
+
export const ProjectKnowledgePage = z.object({
|
|
15
|
+
type: z.literal("mesh.knowledge.page"),
|
|
16
|
+
sessionId: Identifier, projectId: Identifier, requestId: Identifier,
|
|
17
|
+
sourceEndpointId: Identifier,
|
|
18
|
+
memoryAvailability: z.enum(["ready", "unavailable"]),
|
|
19
|
+
invocationAvailability: z.enum(["ready", "unavailable"]),
|
|
20
|
+
knowledge: z.array(ProjectKnowledgeRecord).max(32),
|
|
21
|
+
supersededKnowledgeRecordIds: z.array(Identifier).max(128),
|
|
22
|
+
invocations: z.array(z.object({ sequence: Sequence, event: MeshInvocationEvent }).strict()).max(32),
|
|
23
|
+
incomplete: z.boolean(), generatedAt: Sequence,
|
|
24
|
+
}).strict().superRefine((value, ctx) => {
|
|
25
|
+
let previous = 0;
|
|
26
|
+
const seenCalls = new Set<string>();
|
|
27
|
+
const orderedCalls = value.invocations.every(row => {
|
|
28
|
+
const valid = row.sequence > previous && !seenCalls.has(row.event.event_id);
|
|
29
|
+
previous = row.sequence;
|
|
30
|
+
seenCalls.add(row.event.event_id);
|
|
31
|
+
return valid;
|
|
32
|
+
});
|
|
33
|
+
if (!orderedCalls
|
|
34
|
+
|| new Set(value.knowledge.map(row => row.recordId)).size !== value.knowledge.length
|
|
35
|
+
|| new Set(value.supersededKnowledgeRecordIds).size !== value.supersededKnowledgeRecordIds.length
|
|
36
|
+
|| value.sessionId !== value.projectId
|
|
37
|
+
|| value.knowledge.some(record => record.projectId !== value.projectId || record.visibility !== "project")
|
|
38
|
+
|| value.invocations.some(row => row.event.project_id !== value.projectId)
|
|
39
|
+
|| value.memoryAvailability === "unavailable" && value.knowledge.length > 0
|
|
40
|
+
|| value.invocationAvailability === "unavailable" && value.invocations.length > 0) {
|
|
41
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message: "Knowledge source or Project scope mismatch" });
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
export type ProjectKnowledgePage = z.infer<typeof ProjectKnowledgePage>;
|
|
@@ -149,8 +149,8 @@ export const SessionsStatus = z.object({
|
|
|
149
149
|
gatingEnabled: z.boolean().optional(),
|
|
150
150
|
excludedSessions: z.array(z.string()).optional(),
|
|
151
151
|
autoAcceptDefault: AutoAcceptLevel.optional(),
|
|
152
|
-
autoAcceptBySession: z.record(AutoAcceptLevel).optional(),
|
|
153
|
-
autoAcceptByProject: z.record(AutoAcceptLevel).optional(),
|
|
152
|
+
autoAcceptBySession: z.record(z.string(), AutoAcceptLevel).optional(),
|
|
153
|
+
autoAcceptByProject: z.record(z.string(), AutoAcceptLevel).optional(),
|
|
154
154
|
autoAcceptPaused: z.boolean().optional(),
|
|
155
155
|
providerSettings: ProviderRuntimeSettings.optional(),
|
|
156
156
|
meshEnabled: z.boolean().optional(),
|
|
@@ -45,6 +45,7 @@ import { PairingJoin } from "./messages/pairing-join";
|
|
|
45
45
|
import { ControllerPairOffer, ControllerPairRequest } from "./messages/device/controller-pairing";
|
|
46
46
|
import { AccountMachineLink } from "./messages/device/account-machine-link";
|
|
47
47
|
import { KnowledgeWrite, KnowledgeWriteResult } from "./messages/mesh/knowledge/write";
|
|
48
|
+
import { ProjectKnowledgeQuery, ProjectKnowledgePage } from "./messages/mesh/knowledge/refresh";
|
|
48
49
|
import { MeshInvocationPage, MeshInvocationQuery } from "./messages/mesh/invocations";
|
|
49
50
|
import {
|
|
50
51
|
ProjectPolicyAck,
|
|
@@ -82,6 +83,7 @@ export * from "./messages/pairing-join";
|
|
|
82
83
|
export * from "./messages/device/controller-pairing";
|
|
83
84
|
export * from "./messages/device/account-machine-link";
|
|
84
85
|
export * from "./messages/mesh/knowledge/write";
|
|
86
|
+
export * from "./messages/mesh/knowledge/refresh";
|
|
85
87
|
export * from "./messages/mesh";
|
|
86
88
|
export * from "./messages/mesh/invocations";
|
|
87
89
|
export * from "./messages/primitives";
|
|
@@ -165,6 +167,8 @@ export const Payload = z.union([
|
|
|
165
167
|
ProjectCapabilityRequestSet,
|
|
166
168
|
MeshInvocationQuery,
|
|
167
169
|
MeshInvocationPage,
|
|
170
|
+
ProjectKnowledgeQuery,
|
|
171
|
+
ProjectKnowledgePage,
|
|
168
172
|
MeshEndpointPolicy,
|
|
169
173
|
ProjectPolicySet,
|
|
170
174
|
ProjectPolicyStatus,
|