@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/CHANGELOG.md +123 -0
- package/dist/declarations/src/fixHandlers.d.ts +29 -0
- package/dist/declarations/src/index.d.ts +5 -3
- package/dist/declarations/src/valServerConfig.d.ts +37 -0
- package/dist/valbuild-server.cjs.dev.js +321 -1465
- package/dist/valbuild-server.cjs.prod.js +321 -1465
- package/dist/valbuild-server.esm.js +321 -1462
- package/package.json +3 -3
- package/dist/declarations/src/tools/createValTools.d.ts +0 -41
- package/dist/declarations/src/tools/defineTool.d.ts +0 -69
- package/dist/declarations/src/tools/index.d.ts +0 -3
- package/dist/declarations/src/tools/types.d.ts +0 -163
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,128 @@
|
|
|
1
1
|
# @valbuild/server
|
|
2
2
|
|
|
3
|
+
## 0.123.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#619](https://github.com/valbuild/val/pull/619) [`8e58c34`](https://github.com/valbuild/val/commit/8e58c3495d1bf0f221a57082cb0a3045929722a1) Thanks [@freekh](https://github.com/freekh)! - Stop `val validate` reporting published remote gallery images as missing — and `--fix` deleting them
|
|
8
|
+
|
|
9
|
+
A remote gallery (`s.images({ remote: true })`) keys an uploaded entry by its
|
|
10
|
+
remote URL. Two separate checks read that key, normalised it back to the local
|
|
11
|
+
path it encodes, and then required a file to be sitting there:
|
|
12
|
+
|
|
13
|
+
- `val validate` reported _"Gallery … has tracked files that do not exist on
|
|
14
|
+
disk"_ for every published remote image;
|
|
15
|
+
- `val validate --fix` **removed the entry from the gallery**, silently deleting
|
|
16
|
+
the reference to a file that was safely on the content host.
|
|
17
|
+
|
|
18
|
+
Both were wrong for the same reason. Publishing uploads remote files to the
|
|
19
|
+
content host and copies only local ones into the working tree, so an image added
|
|
20
|
+
through the Studio — or over MCP — has no file in the repo by design. Putting one
|
|
21
|
+
there is exactly what remote storage exists to avoid.
|
|
22
|
+
|
|
23
|
+
Remote entries are now exempt from both the missing-file check and the
|
|
24
|
+
metadata-from-disk verification. Whether a remote entry is sound is
|
|
25
|
+
`image:check-remote`'s question, and it already asks it. Nothing changes for
|
|
26
|
+
local entries, or for a remote entry that does have a local file — `--fix`
|
|
27
|
+
promotes a local file to a remote ref and leaves the file where it was, and that
|
|
28
|
+
file is still counted as tracked rather than reported as untracked.
|
|
29
|
+
|
|
30
|
+
- Updated dependencies [[`04b6d4c`](https://github.com/valbuild/val/commit/04b6d4cbbecc131bbaf3c20633af9dad8c857310), [`3e93508`](https://github.com/valbuild/val/commit/3e93508b05d08b0c24947a97c6141a9ad8a3931e)]:
|
|
31
|
+
- @valbuild/shared@0.123.2
|
|
32
|
+
- @valbuild/ui@0.123.2
|
|
33
|
+
|
|
34
|
+
## 0.123.0
|
|
35
|
+
|
|
36
|
+
### Minor Changes
|
|
37
|
+
|
|
38
|
+
- [#613](https://github.com/valbuild/val/pull/613) [`c5e7dfd`](https://github.com/valbuild/val/commit/c5e7dfd12aa1371195be642e1c2fb72b6f3e3ce2) Thanks [@freekh](https://github.com/freekh)! - Val's MCP endpoint moves to its own package, and can now upload images
|
|
39
|
+
|
|
40
|
+
Everything that serves Val's content tools over MCP — the tool registry, the
|
|
41
|
+
write path behind it, the request guards and the access-token verification —
|
|
42
|
+
now lives in **`@valbuild/mcp`** instead of being split between
|
|
43
|
+
`@valbuild/server` and `@valbuild/next`.
|
|
44
|
+
|
|
45
|
+
**Nothing changes for an app that already mounts it.** `initValMcp` is still
|
|
46
|
+
exported from `@valbuild/next/server` and behaves exactly as before; it is now a
|
|
47
|
+
ten-line binding over `@valbuild/mcp`, supplying the Next version that
|
|
48
|
+
`initHandlerOptions` asks for. A host that is not Next can call
|
|
49
|
+
`initValMcp` from `@valbuild/mcp` directly.
|
|
50
|
+
|
|
51
|
+
If you built your own host on `createValTools`, import it from `@valbuild/mcp`
|
|
52
|
+
rather than `@valbuild/server`; the tool types moved with it.
|
|
53
|
+
|
|
54
|
+
## Image uploads
|
|
55
|
+
|
|
56
|
+
An agent can now add an image, with a new `upload_image` tool. It takes a path
|
|
57
|
+
to a file on the machine your app runs on, or the image inline as base64, and
|
|
58
|
+
puts it in an `s.image()` field or an `s.images()` gallery.
|
|
59
|
+
|
|
60
|
+
Uploads are converted **only where the Studio would convert them**: `encode` is
|
|
61
|
+
off unless the schema asks for it (`s.image({ encode: { type: "webp" } })`), and
|
|
62
|
+
when it does, which images are converted, how far they are scaled and when the
|
|
63
|
+
original wins are the same decisions the browser makes — the same code, now
|
|
64
|
+
shared. An upload to a schema without `encode` is stored exactly as it arrived,
|
|
65
|
+
whatever its size.
|
|
66
|
+
|
|
67
|
+
One thing the tool does that the Studio does not: it refuses an image the
|
|
68
|
+
schema's `accept` does not cover, checked on the bytes that would actually be
|
|
69
|
+
stored. The Studio does not need to — its file picker carries `accept` — and
|
|
70
|
+
validation reports a mismatch as server-repairable, so nothing downstream would
|
|
71
|
+
stop it. An agent has no picker. Note the ordering:
|
|
72
|
+
`s.image({ accept: "image/webp", encode: { type: "webp" } })` still takes a PNG,
|
|
73
|
+
because the conversion happens first and it is the result that is checked.
|
|
74
|
+
|
|
75
|
+
It is the one tool you construct yourself, because it needs an image library
|
|
76
|
+
and `sharp` ships a compiled binary per platform. Val does not put one in every
|
|
77
|
+
project that installs it, so you decide:
|
|
78
|
+
|
|
79
|
+
```sh
|
|
80
|
+
npm install sharp
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
```ts
|
|
84
|
+
import sharp from "sharp";
|
|
85
|
+
import { createValImageTools } from "@valbuild/mcp";
|
|
86
|
+
import { sharpImageProcessor } from "@valbuild/mcp/sharp";
|
|
87
|
+
|
|
88
|
+
const { valMcpAuthorize, valMcpTools } = initValMcp(valModules, config, {
|
|
89
|
+
extraTools: createValImageTools(sharpImageProcessor(sharp)),
|
|
90
|
+
});
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
Leave `extraTools` out and everything else works as before — the agent can read,
|
|
94
|
+
validate and edit content, it just cannot add an image. `sharp` is passed in
|
|
95
|
+
rather than imported, so you can supply another encoder: `ValImageProcessor` is
|
|
96
|
+
two functions, `read` and `encode`.
|
|
97
|
+
|
|
98
|
+
Remotely stored images work too — `s.image().remote()` and
|
|
99
|
+
`s.images({ remote: true })` — and they need nothing extra from the MCP client.
|
|
100
|
+
Adding one does not upload anything to Val's content host: the bytes go into the
|
|
101
|
+
patch store like any other unpublished change, and the push to
|
|
102
|
+
`remote.val.build` happens when you publish, exactly as it does for an image
|
|
103
|
+
added through the Studio. All the tool has to do first is ask the project which
|
|
104
|
+
bucket to name in the ref, and the credential for that is the one your app
|
|
105
|
+
already has — its API key when it has one, and in local development the
|
|
106
|
+
`val login` token in your project, the same one `val validate --fix` uses. If
|
|
107
|
+
you have not logged in, it says so and writes nothing.
|
|
108
|
+
|
|
109
|
+
## `npm create @valbuild` asks
|
|
110
|
+
|
|
111
|
+
The starter template now ships the MCP endpoint, and `npm create @valbuild`
|
|
112
|
+
asks whether you want it — and, if you do, whether agents should be able to
|
|
113
|
+
upload images, saying that this adds `sharp`. Both default to yes, and both can
|
|
114
|
+
be answered up front for a scripted setup:
|
|
115
|
+
|
|
116
|
+
```sh
|
|
117
|
+
pnpm create @valbuild my-app --mcp --no-image-uploads
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Patch Changes
|
|
121
|
+
|
|
122
|
+
- Updated dependencies [[`c5e7dfd`](https://github.com/valbuild/val/commit/c5e7dfd12aa1371195be642e1c2fb72b6f3e3ce2), [`53f670c`](https://github.com/valbuild/val/commit/53f670c0cf2d7a03a6d068c78b7874ce77652c2a)]:
|
|
123
|
+
- @valbuild/shared@0.123.0
|
|
124
|
+
- @valbuild/ui@0.123.0
|
|
125
|
+
|
|
3
126
|
## 0.122.0
|
|
4
127
|
|
|
5
128
|
### Minor Changes
|
|
@@ -162,6 +162,35 @@ export declare function handleRemoteGalleryFileUpload(ctx: FixHandlerContext): P
|
|
|
162
162
|
export declare function handleRemoteFileDownload(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
163
163
|
export declare function handleRemoteFileCheck(): Promise<FixHandlerResult>;
|
|
164
164
|
export declare function handleUniqueFolderCheck(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
165
|
+
/**
|
|
166
|
+
* What is out of step between a gallery's entries and its directory.
|
|
167
|
+
*
|
|
168
|
+
* Two questions, and they treat a remote entry differently — which is the whole
|
|
169
|
+
* reason this is separate from the handler around it:
|
|
170
|
+
*
|
|
171
|
+
* - **Missing**: an entry with no bytes at its local path. Asked of LOCAL
|
|
172
|
+
* entries only. A remote entry's bytes live on the content host, and nothing
|
|
173
|
+
* puts a copy in the working tree: `saveOrUploadFiles` uploads the remote
|
|
174
|
+
* descriptors and copies only the local ones into the tree, so a remote entry
|
|
175
|
+
* added through the Studio (or over MCP) has no local file by design, and
|
|
176
|
+
* demanding one would mean committing remote bytes to git — which is what
|
|
177
|
+
* remote storage exists to avoid. Whether those bytes really are on the host
|
|
178
|
+
* is a different check, `image:check-remote`, which already runs for exactly
|
|
179
|
+
* these entries.
|
|
180
|
+
* - **Untracked**: a file in the directory that no entry claims. Asked of every
|
|
181
|
+
* entry, remote included, and that is why they are normalised to their local
|
|
182
|
+
* path: `val validate --fix` promotes a local file to a remote ref and leaves
|
|
183
|
+
* the file where it was, so a remote entry can perfectly well have one.
|
|
184
|
+
*/
|
|
185
|
+
export declare function checkGalleryFiles(input: {
|
|
186
|
+
entryKeys: string[];
|
|
187
|
+
directory: string;
|
|
188
|
+
projectRoot: string;
|
|
189
|
+
fs: Pick<IValFSHost, "fileExists" | "readDirectory">;
|
|
190
|
+
}): {
|
|
191
|
+
missingTrackedFiles: string[];
|
|
192
|
+
untrackedFiles: string[];
|
|
193
|
+
};
|
|
165
194
|
export declare function handleCheckAllFiles(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
166
195
|
export declare function handleJsonValuesExtractEntry(ctx: FixHandlerContext): Promise<FixHandlerResult>;
|
|
167
196
|
/**
|
|
@@ -2,10 +2,9 @@ export { createService, Service } from "./Service.js";
|
|
|
2
2
|
export { defineExternal, ok, err, isExternalResult, EXTERNAL_RESULT, } from "./externalRecords.js";
|
|
3
3
|
export type { AdapterFor, BoundExternalRecord, ExternalAuthor, ExternalBuilder, ExternalCtx, ExternalDefinition, ExternalFile, ExternalIssue, ExternalKeyPage, ExternalRecords, ExternalResult, ExternalSearchHit, ExternalSearchPage, ExternalSort, ItemOfModule, ReadonlyRecordHasNoWrites, Returns, } from "./externalRecords.js";
|
|
4
4
|
export { createValApiRouter, createValServer, safeReadGit } from "./ValRouter.js";
|
|
5
|
-
export { createValTools } from "./tools/index.js";
|
|
6
|
-
export { VAL_SCOPE_READ, VAL_SCOPE_WRITE, authorIdFromVerifiedSubject, } from "./tools/index.js";
|
|
7
|
-
export type { ValScope, ValToolAuth, ValToolContext, ValToolDefinition, ValToolDefinitionJson, ValToolErrorCode, ValToolResult, ValTools, ValToolsOptions, } from "./tools/index.js";
|
|
8
5
|
export { initHandlerOptions, createValOps } from "./valServerConfig.js";
|
|
6
|
+
export { resolveRemoteFileAuth } from "./valServerConfig.js";
|
|
7
|
+
export type { RemoteFileAuth, ResolveRemoteFileAuthResult, } from "./valServerConfig.js";
|
|
9
8
|
export { ValModuleLoader } from "./ValModuleLoader.js";
|
|
10
9
|
export { getCompilerOptions } from "./getCompilerOptions.js";
|
|
11
10
|
export { ValSourceFileHandler } from "./ValSourceFileHandler.js";
|
|
@@ -47,6 +46,9 @@ export { formatPatchSourceError } from "./ValOps.js";
|
|
|
47
46
|
export { compareWithCapturedReport, readCapturedReport, replaySnapshot, } from "./debug/replaySnapshot.js";
|
|
48
47
|
export type { ReplayComparison, ReplayResult } from "./debug/replaySnapshot.js";
|
|
49
48
|
export type { OrderedPatches, PatchAnalysis, PatchSourceError, PreparedCommit, } from "./ValOps.js";
|
|
49
|
+
export type { ValOps } from "./ValOps.js";
|
|
50
|
+
export type { AuthorId, BinaryFileType, MetadataOfType, Schemas, Sources, } from "./ValOps.js";
|
|
51
|
+
export type { ValServerConfig } from "./ValServer.js";
|
|
50
52
|
/**
|
|
51
53
|
* The local-dev patch store, exported so the CLI's debug tooling can read a
|
|
52
54
|
* snapshot back with the same code the server uses rather than a second
|
|
@@ -81,4 +81,41 @@ type CredentialBearingUrl = "valBuildUrl" | "valContentUrl";
|
|
|
81
81
|
* internal http host today.
|
|
82
82
|
*/
|
|
83
83
|
export declare function insecureUrlWarning(name: CredentialBearingUrl, url: string): string | null;
|
|
84
|
+
/**
|
|
85
|
+
* Which credential talks to the content host about REMOTE FILES.
|
|
86
|
+
*
|
|
87
|
+
* A separate question from the one `createValOps` answers, and it has to be:
|
|
88
|
+
* `ValOps` is authenticated per caller, but remote files are project-level —
|
|
89
|
+
* looking up a project's public id and its buckets, and later pushing bytes to
|
|
90
|
+
* them, is the same operation whoever asked for it.
|
|
91
|
+
*
|
|
92
|
+
* The rule, in order:
|
|
93
|
+
*
|
|
94
|
+
* 1. The app's API key, if there is one. Proxy mode always has one; fs mode has
|
|
95
|
+
* one when `VAL_API_KEY` is set.
|
|
96
|
+
* 2. In fs mode, the developer's own `val login` token, read off disk. This is
|
|
97
|
+
* the same file `val validate --fix` reads, and it is why local remote
|
|
98
|
+
* uploads work with no configuration beyond having logged in.
|
|
99
|
+
* 3. Nothing, which is an error rather than a fallback.
|
|
100
|
+
*
|
|
101
|
+
* Lives here rather than inside `createValServer` because the MCP image tool
|
|
102
|
+
* needs the same answer, and this is the file that exists so that two callers
|
|
103
|
+
* cannot disagree about how a project is configured. A registry that decided it
|
|
104
|
+
* had no credential while the Studio in the same process had one would be a
|
|
105
|
+
* genuinely confusing afternoon.
|
|
106
|
+
*/
|
|
107
|
+
export type RemoteFileAuth = {
|
|
108
|
+
apiKey: string;
|
|
109
|
+
} | {
|
|
110
|
+
pat: string;
|
|
111
|
+
};
|
|
112
|
+
export type ResolveRemoteFileAuthResult = {
|
|
113
|
+
status: "success";
|
|
114
|
+
auth: RemoteFileAuth;
|
|
115
|
+
} | {
|
|
116
|
+
status: "error";
|
|
117
|
+
errorCode: "project-not-configured" | "pat-error";
|
|
118
|
+
message: string;
|
|
119
|
+
};
|
|
120
|
+
export declare function resolveRemoteFileAuth(options: ValServerConfig): Promise<ResolveRemoteFileAuthResult>;
|
|
84
121
|
export {};
|