@valbuild/server 0.122.0 → 0.123.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/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  "./package.json": "./package.json"
17
17
  },
18
18
  "types": "dist/valbuild-server.cjs.d.ts",
19
- "version": "0.122.0",
19
+ "version": "0.123.2",
20
20
  "devDependencies": {
21
21
  "@prettier/sync": "^0.6.1",
22
22
  "@types/jest": "^30.0.0"
@@ -29,9 +29,9 @@
29
29
  "typescript": "^6.0.3",
30
30
  "zod": "^4.4.3",
31
31
  "zod-validation-error": "^5.0.0",
32
+ "@valbuild/shared": "0.123.2",
32
33
  "@valbuild/core": "0.121.0",
33
- "@valbuild/shared": "0.122.0",
34
- "@valbuild/ui": "0.122.0"
34
+ "@valbuild/ui": "0.123.2"
35
35
  },
36
36
  "engines": {
37
37
  "node": "^20.19.0 || >=22"
@@ -1,41 +0,0 @@
1
- import type { ValModules } from "@valbuild/core";
2
- import type { ValServerConfig } from "../ValServer.js";
3
- import type { ValOps } from "../ValOps.js";
4
- import type { ValToolState } from "./defineTool.js";
5
- import { type ValToolResult, type ValTools } from "./types.js";
6
- export type ValToolsOptions = ValServerConfig;
7
- /**
8
- * Val's server-side tool registry.
9
- *
10
- * This is the piece Val did not have: the Studio's chat tools are defined *and
11
- * executed in the browser*, against its client stores, so nothing here could be
12
- * re-exposed. These tools run against {@link ValOps} instead, which is what lets
13
- * an MCP server — or a stdio transport, or anything else — drive Val content
14
- * without a browser.
15
- *
16
- * Transport-agnostic on purpose: nothing under `tools/` imports an MCP SDK. A
17
- * host adapts {@link ValToolResult} at its own edge.
18
- */
19
- export declare function createValTools(valModules: ValModules, options: ValToolsOptions): ValTools;
20
- /**
21
- * The content as the caller should see it, loaded once per call.
22
- *
23
- * Pending patches are applied, because an agent looking at a project mid-edit
24
- * should see what the Studio would show rather than the last published state.
25
- *
26
- * Deliberately not cached across calls. In fs mode a save recomputes the base
27
- * sha within the same process, so a cached view would go stale silently — and
28
- * the cost of being wrong here is an agent writing a patch against content that
29
- * has already moved.
30
- *
31
- * Exported for `toolsFixture`, not for consumers: `tools/index.ts` re-exports by
32
- * name, so this stays inside the package. A test that assembled its own state
33
- * would be asserting against a view no real call ever sees.
34
- */
35
- export declare function loadState(ops: ValOps): Promise<{
36
- status: "ok";
37
- state: ValToolState;
38
- } | {
39
- status: "error";
40
- result: ValToolResult;
41
- }>;
@@ -1,69 +0,0 @@
1
- import type { Json, ModuleFilePath, PatchId, SerializedSchema } from "@valbuild/core";
2
- import type { z } from "zod";
3
- import type { ValOps, OrderedPatches, PatchAnalysis, Schemas, Sources } from "../ValOps.js";
4
- import type { ValToolContext, ValToolDefinition, ValToolErrorCode, ValToolResult } from "./types.js";
5
- /**
6
- * How a tool is written, and what it is handed.
7
- *
8
- * Tools are defined with {@link defineTool} so that the handler's `args` are
9
- * inferred from the tool's own `inputSchema`. Without that the array of tools
10
- * would have to be typed at its widest and every handler would start by
11
- * re-narrowing `unknown`, which is exactly where a tool and its schema drift
12
- * apart unnoticed.
13
- */
14
- /** Everything a tool is allowed to reach. Deliberately narrow. */
15
- export type ValToolDeps = {
16
- /**
17
- * The data layer for *this call*. In proxy mode it is authenticated as the
18
- * caller, so a tool must never reach for an ambient instance instead.
19
- */
20
- ops: ValOps;
21
- ctx: ValToolContext;
22
- /**
23
- * The content as the caller should see it: base sources with pending patches
24
- * applied, plus the schemas and the patch analysis that produced them.
25
- *
26
- * Loaded once per call and shared, because a tool that re-derived it would
27
- * both pay for it again and risk reading a different revision than the one it
28
- * validated against.
29
- */
30
- state: ValToolState;
31
- };
32
- export type ValToolState = {
33
- schemas: Schemas;
34
- serializedSchemas: Record<ModuleFilePath, SerializedSchema>;
35
- sources: Sources;
36
- patches: OrderedPatches;
37
- analysis: PatchAnalysis;
38
- /**
39
- * Pending patches that would not apply, by the module they belong to.
40
- *
41
- * A module listed here has `sources` that silently lack those changes, so its
42
- * content is not what publishing would produce. Reads still return it — it is
43
- * what the Studio would show too, and a project has to stay diagnosable — but
44
- * a write to such a module is refused, because it would be based on a state
45
- * that does not exist.
46
- */
47
- unappliedPatches: Record<ModuleFilePath, {
48
- patchId: PatchId;
49
- skipped: boolean;
50
- error: {
51
- message: string;
52
- };
53
- }[]>;
54
- };
55
- export type ValToolImpl = ValToolDefinition & {
56
- handler: (args: unknown, deps: ValToolDeps) => Promise<ValToolResult>;
57
- };
58
- /**
59
- * Declare a tool, binding its handler to its input schema.
60
- *
61
- * The handler receives already-parsed arguments: the registry validates against
62
- * `inputSchema` before calling, so a handler never sees input its schema would
63
- * have rejected.
64
- */
65
- export declare function defineTool<S extends z.ZodType>(definition: Omit<ValToolDefinition, "inputSchema"> & {
66
- inputSchema: S;
67
- }, handler: (args: z.infer<S>, deps: ValToolDeps) => Promise<ValToolResult>): ValToolImpl;
68
- export declare function ok(data: Json): ValToolResult;
69
- export declare function err(code: ValToolErrorCode, message: string): ValToolResult;
@@ -1,3 +0,0 @@
1
- export { createValTools, type ValToolsOptions } from "./createValTools.js";
2
- export { VAL_SCOPE_READ, VAL_SCOPE_WRITE, authorIdFromVerifiedSubject, } from "./types.js";
3
- export type { ValScope, ValToolAuth, ValToolContext, ValToolDefinition, ValToolDefinitionJson, ValToolErrorCode, ValToolResult, ValTools, } from "./types.js";
@@ -1,163 +0,0 @@
1
- import type { AuthorId } from "../ValOps.js";
2
- import type { Json } from "@valbuild/core";
3
- import type { z } from "zod";
4
- /**
5
- * The public surface of Val's server-side tool registry.
6
- *
7
- * Types only, deliberately: this file is the contract that the MCP hosts, the
8
- * CLI's stdio transport and the tools themselves are all written against, and
9
- * keeping it free of implementation means those can be built in any order
10
- * without one of them owning the shape.
11
- *
12
- * The design this implements is `docs/plans/mcp.md`, Part A. Two constraints
13
- * from it are load-bearing and easy to break by accident:
14
- *
15
- * 1. **Nothing here may import an MCP SDK.** That is what lets hosts other
16
- * than the template consume these tools, and it is not hypothetical
17
- * hygiene — the TypeScript SDK reorganised itself at v2.0.0, and a registry
18
- * coupled to it would have moved with it.
19
- * 2. **The result type is deliberately not MCP's `CallToolResult`.** Each host
20
- * adapts {@link ValToolResult} at its own edge, which is also where an
21
- * error becomes an in-band `isError` result the model can recover from
22
- * rather than a transport failure.
23
- */
24
- /** Why a tool call failed, in a form a host can map onto its own errors. */
25
- export type ValToolErrorCode =
26
- /** No tool of that name is registered. */
27
- "unknown-tool"
28
- /** The arguments did not satisfy the tool's `inputSchema`. */
29
- | "invalid-args"
30
- /** The path, module or key the arguments name does not exist. */
31
- | "not-found"
32
- /** The caller is not allowed to do this — wrong credential, or none. */
33
- | "forbidden"
34
- /**
35
- * The write was rejected because applying it would leave content invalid.
36
- * Nothing was stored. See `docs/plans/mcp.md` Part C on speculative
37
- * validation.
38
- */
39
- | "validation-failed"
40
- /**
41
- * Another writer moved the patch chain first. Callers may re-derive the
42
- * parent ref and retry once; the registry does that itself before
43
- * surfacing this.
44
- */
45
- | "conflict"
46
- /** The tool exists but is not available in this mode (e.g. fs vs http). */
47
- | "unsupported"
48
- /** Anything else, including an upstream failure. */
49
- | "internal";
50
- export type ValToolDefinition = {
51
- name: string;
52
- title?: string;
53
- description: string;
54
- /** zod v4 — a Standard Schema, which is what the MCP SDKs consume. */
55
- inputSchema: z.ZodType;
56
- /**
57
- * MCP tool annotations. Hints, not enforcement: a host may show them to a
58
- * user or use them to decide what to auto-approve, so they have to be
59
- * honest about what the tool does.
60
- */
61
- annotations?: {
62
- readOnlyHint?: boolean;
63
- destructiveHint?: boolean;
64
- idempotentHint?: boolean;
65
- };
66
- };
67
- /**
68
- * The same definition with `inputSchema` as JSON Schema, for hosts that want the
69
- * wire shape rather than a Standard Schema.
70
- *
71
- * Typed as whatever zod's own converter produces, so deriving it needs no cast
72
- * and no second hand-written description of the same input.
73
- */
74
- export type ValToolDefinitionJson = Omit<ValToolDefinition, "inputSchema"> & {
75
- inputSchema: ReturnType<typeof z.toJSONSchema<z.ZodType>>;
76
- };
77
- /**
78
- * How the caller was established, and there is one acceptable answer: the host
79
- * **checked a signature**.
80
- *
81
- * A union of one, deliberately. It carried a second variant — a personal access
82
- * token relayed to the backend unchecked, on the reasoning that the app cannot
83
- * resolve one and the backend can. The reasoning held; the shape did not. A
84
- * credential the host cannot check is one it also cannot refuse, so accepting
85
- * one made "a deployed endpoint that authenticates nobody" a supported
86
- * configuration, and it let a host serve these tools without ever being told
87
- * where callers should authorize. The discriminant stays so that adding a
88
- * second *verified* kind stays a one-line change at every call site.
89
- */
90
- export type ValToolAuth = {
91
- type: "verified-profile";
92
- /**
93
- * The profile the host **verified** — the `sub` of an access token whose
94
- * signature, issuer, audience and expiry were all checked against the
95
- * authorization server's published key.
96
- *
97
- * This field is why an identity field exists at all, and an earlier version
98
- * of this file argued none should. That argument was about a specific case
99
- * and stated too broadly: an id the host *asserts* on the strength of a
100
- * credential it cannot check is an unverified claim dressed as a checked one,
101
- * and that is still refused — it is why a relayed token never carried a
102
- * profile, and now cannot reach here at all. An id the host *verified*
103
- * cryptographically is a different thing, and it is the same standing the
104
- * Studio has when it re-signs a session it established itself.
105
- */
106
- profileId: AuthorId;
107
- /**
108
- * The token's granted scopes, as the authorization server issued them.
109
- *
110
- * Enforced here as well as by the backend, deliberately. Two checks on one
111
- * grant is not redundancy for its own sake: this one can refuse a write
112
- * before it is attempted, so a token that may only read never reaches the
113
- * code that builds a patch.
114
- */
115
- scopes: string[];
116
- };
117
- /**
118
- * Who is calling, established once per request by the host.
119
- *
120
- * `null` means local fs mode, where there is no credential to hold and patches
121
- * are written with no author, exactly as the Studio does locally (D.1). In
122
- * proxy mode `null` is refused rather than falling back to the app's own API
123
- * key: that key can do more than any single user, and quietly substituting it
124
- * would turn a missing credential into full access.
125
- */
126
- export type ValToolContext = {
127
- auth: ValToolAuth | null;
128
- /** Groups a run of related edits, when the host has such a notion. */
129
- sessionId: string | null;
130
- };
131
- /**
132
- * Brand a verified subject as an {@link AuthorId}.
133
- *
134
- * `AuthorId` is a branded string so that an id cannot be conjured from any
135
- * string that happens to be lying around — which is exactly the mistake this
136
- * type is guarding against. That makes one assertion unavoidable at the boundary
137
- * where a real id enters the system, so it lives here, once, with a name that
138
- * says what makes it legitimate: the caller has *verified* this subject, not
139
- * received it.
140
- *
141
- * Do not reach for this to satisfy a type. If you are holding a string you did
142
- * not verify, the honest value is `null`.
143
- */
144
- export declare function authorIdFromVerifiedSubject(subject: string): AuthorId;
145
- /** Read access. Every call needs it, the writes included. */
146
- export declare const VAL_SCOPE_READ = "val:read";
147
- /** Write access. Needed *in addition* by any tool not marked `readOnlyHint`. */
148
- export declare const VAL_SCOPE_WRITE = "val:write";
149
- export type ValScope = typeof VAL_SCOPE_READ | typeof VAL_SCOPE_WRITE;
150
- export type ValToolResult = {
151
- status: "ok";
152
- data: Json;
153
- } | {
154
- status: "error";
155
- code: ValToolErrorCode;
156
- message: string;
157
- };
158
- export type ValTools = {
159
- list(): ValToolDefinition[];
160
- listJsonSchema(): ValToolDefinitionJson[];
161
- call(name: string, args: unknown, ctx: ValToolContext): Promise<ValToolResult>;
162
- dispose(): Promise<void>;
163
- };