@telepath-computer/autofile 0.0.0-stage → 0.4.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.
@@ -0,0 +1,111 @@
1
+ /** Derives MCP resources from public Autofile records and type declarations. */
2
+ import { AutofileError } from "./index.js";
3
+ const typeNamePattern = /^[a-z][a-z0-9-]*$/u;
4
+ const typeUriPattern = /^autofile:\/\/\/_types\/([a-z][a-z0-9-]*)$/u;
5
+ const recordUriPattern = /^autofile:\/\/\/[a-z][a-z0-9-]*\/[a-z0-9][a-z0-9-]*$/u;
6
+ const blobUriPattern = /^autofile:\/\/\/_blobs\/[^/]+$/u;
7
+ /** Builds resource operations using only the public library interface. */
8
+ export function buildResources(autofile) {
9
+ async function listResources() {
10
+ const resources = [];
11
+ for (const declaration of await autofile.types.list()) {
12
+ resources.push(...await listTypeResources(declaration.type));
13
+ }
14
+ return resources.sort(compareResources);
15
+ }
16
+ async function getResourceMetadata(uri) {
17
+ const type = typeUriPattern.exec(uri)?.[1];
18
+ if (type !== undefined) {
19
+ const declaration = await readable(() => autofile.types.get(type));
20
+ return declaration === undefined ? undefined : declarationResource(declaration);
21
+ }
22
+ if (!recordUriPattern.test(uri))
23
+ return undefined;
24
+ const record = await readable(() => autofile.records.get(uri));
25
+ return record === undefined ? undefined : recordResource(record);
26
+ }
27
+ async function listTypeResources(type) {
28
+ if (!typeNamePattern.test(type))
29
+ return [];
30
+ const declaration = await readable(() => autofile.types.get(type));
31
+ if (declaration === undefined)
32
+ return [];
33
+ const resources = [declarationResource(declaration)];
34
+ let cursor;
35
+ do {
36
+ const page = await readable(() => autofile.records.find({ type, limit: 200, cursor }));
37
+ if (page === undefined)
38
+ break;
39
+ resources.push(...page.records.map(recordResource));
40
+ // Queries exclude records that fail schema validation. A direct public
41
+ // read can still return them, including the problems needed to repair them.
42
+ for (const { uri } of page.unreadable) {
43
+ const record = await readable(() => autofile.records.get(uri));
44
+ if (record !== undefined)
45
+ resources.push(recordResource(record));
46
+ }
47
+ cursor = page.cursor;
48
+ } while (cursor !== undefined);
49
+ return resources.sort(compareResources);
50
+ }
51
+ async function readResource(uri) {
52
+ if (blobUriPattern.test(uri)) {
53
+ const blob = await autofile.blobs.get(uri);
54
+ return blob === undefined ? undefined : {
55
+ uri, mimeType: blob.mimeType, blob: Buffer.from(blob.bytes).toString("base64"),
56
+ };
57
+ }
58
+ const type = typeUriPattern.exec(uri)?.[1];
59
+ const document = type !== undefined
60
+ ? await readable(() => autofile.types.get(type))
61
+ : recordUriPattern.test(uri)
62
+ ? await readable(() => autofile.records.get(uri))
63
+ : undefined;
64
+ if (document === undefined)
65
+ return undefined;
66
+ return { uri, mimeType: "application/json", text: serialize(document) };
67
+ }
68
+ return { listResources, getResourceMetadata, listTypeResources, readResource };
69
+ }
70
+ /** Checks addresses that can occur in an MCP resource-list cursor. */
71
+ export function isResourceUri(uri) {
72
+ return typeUriPattern.test(uri) || recordUriPattern.test(uri);
73
+ }
74
+ function declarationResource(declaration) {
75
+ return {
76
+ uri: declaration.uri,
77
+ name: `Type: ${declaration.type}`,
78
+ mimeType: "application/json",
79
+ description: declaration.description,
80
+ ...(declaration.title === undefined ? {} : { title: declaration.title }),
81
+ };
82
+ }
83
+ function recordResource(record) {
84
+ return {
85
+ uri: record.uri,
86
+ name: `${record.type}: ${record.key}`,
87
+ mimeType: "application/json",
88
+ ...(record.title === undefined ? {} : { title: record.title }),
89
+ };
90
+ }
91
+ function serialize(value) {
92
+ return `${JSON.stringify(value, (_key, item) => {
93
+ if (typeof item !== "object" || item === null || Array.isArray(item))
94
+ return item;
95
+ return Object.fromEntries(Object.entries(item).sort(([left], [right]) => (left < right ? -1 : left > right ? 1 : 0)));
96
+ }, 2)}\n`;
97
+ }
98
+ function compareResources(left, right) {
99
+ return left.uri < right.uri ? -1 : left.uri > right.uri ? 1 : 0;
100
+ }
101
+ async function readable(read) {
102
+ try {
103
+ return await read();
104
+ }
105
+ catch (error) {
106
+ if (error instanceof AutofileError)
107
+ return undefined;
108
+ throw error;
109
+ }
110
+ }
111
+ //# sourceMappingURL=mcp-resources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-resources.js","sourceRoot":"","sources":["../src/mcp-resources.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,113 @@
1
+ /** Translates the library operations into the existing MCP tool result shapes. */
2
+ import { type Autofile, type JsonObject, type RecordQuery } from "./index.js";
3
+ import { type UploadBlobInput, type UploadBlobOptions } from "./mcp-upload.js";
4
+ export type { UploadBlobInput } from "./mcp-upload.js";
5
+ /** One reason a tool request was refused. */
6
+ export interface StoreError {
7
+ uri?: string;
8
+ message: string;
9
+ }
10
+ /** The MCP refusal body, before protocol formatting. */
11
+ export interface Refusal {
12
+ errors: StoreError[];
13
+ }
14
+ /** Arguments to find_records. */
15
+ export type FindRecordsInput = RecordQuery;
16
+ /** Arguments to get_record. */
17
+ export interface GetRecordInput {
18
+ uri: string;
19
+ }
20
+ /** Arguments to create_record. */
21
+ export interface CreateRecordInput {
22
+ type: string;
23
+ key?: string;
24
+ record: JsonObject;
25
+ }
26
+ /** Arguments to update_record. */
27
+ export interface UpdateRecordInput {
28
+ uri: string;
29
+ patch: JsonObject;
30
+ }
31
+ /** Arguments to delete_record. */
32
+ export interface DeleteRecordInput {
33
+ uri: string;
34
+ }
35
+ /** Arguments to get_type. */
36
+ export interface GetTypeInput {
37
+ type: string;
38
+ }
39
+ /** Arguments to create_type. */
40
+ export interface CreateTypeInput {
41
+ type: string;
42
+ description: string;
43
+ schema: JsonObject;
44
+ titleField?: string;
45
+ title?: string;
46
+ }
47
+ /** Arguments to update_type. */
48
+ export interface UpdateTypeInput {
49
+ type: string;
50
+ description?: string;
51
+ schema?: JsonObject;
52
+ titleField?: string | null;
53
+ title?: string | null;
54
+ }
55
+ /** Arguments to delete_type. */
56
+ export interface DeleteTypeInput {
57
+ type: string;
58
+ }
59
+ /** A successful MCP write names the changed resource. */
60
+ export interface UriResult {
61
+ uri: string;
62
+ }
63
+ /** A page returned by find_records. */
64
+ export interface FindRecordsResult {
65
+ records: RecordResult[];
66
+ errors: StoreError[];
67
+ cursor?: string;
68
+ }
69
+ /** The record envelope exposed by MCP tools. */
70
+ export interface RecordResult extends UriResult {
71
+ title?: string;
72
+ createdAt: string;
73
+ updatedAt: string;
74
+ value: JsonObject;
75
+ error?: string;
76
+ }
77
+ /** A declaration summary returned by list_types. */
78
+ export interface TypeSummary extends UriResult {
79
+ type: string;
80
+ description: string;
81
+ title?: string;
82
+ }
83
+ /** The list_types result body. */
84
+ export interface ListTypesResult {
85
+ types: TypeSummary[];
86
+ }
87
+ /** A full declaration returned by get_type. */
88
+ export interface TypeResult extends UriResult {
89
+ description: string;
90
+ schema: JsonObject;
91
+ titleField?: string;
92
+ title?: string;
93
+ }
94
+ /** A successful type update also reports records invalid under its schema. */
95
+ export interface UpdateTypeResult extends UriResult {
96
+ errors: StoreError[];
97
+ }
98
+ /** Plain tool handlers used by the protocol boundary. */
99
+ export interface Tools {
100
+ findRecords(input: FindRecordsInput): Promise<FindRecordsResult | Refusal>;
101
+ getRecord(input: GetRecordInput): Promise<RecordResult | Refusal>;
102
+ createRecord(input: CreateRecordInput): Promise<UriResult | Refusal>;
103
+ updateRecord(input: UpdateRecordInput): Promise<UriResult | Refusal>;
104
+ uploadBlob(input: UploadBlobInput, options?: UploadBlobOptions): Promise<UriResult | Refusal>;
105
+ deleteRecord(input: DeleteRecordInput): Promise<UriResult | Refusal>;
106
+ listTypes(input: Record<string, never>): Promise<ListTypesResult>;
107
+ getType(input: GetTypeInput): Promise<TypeResult | Refusal>;
108
+ createType(input: CreateTypeInput): Promise<UriResult | Refusal>;
109
+ updateType(input: UpdateTypeInput): Promise<UpdateTypeResult | Refusal>;
110
+ deleteType(input: DeleteTypeInput): Promise<UriResult | Refusal>;
111
+ }
112
+ /** Builds tool handlers that use the class for every store operation. */
113
+ export declare function buildTools(autofile: Autofile): Tools;
@@ -0,0 +1,89 @@
1
+ /** Translates the library operations into the existing MCP tool result shapes. */
2
+ import { AutofileError } from "./index.js";
3
+ import { uploadBlob } from "./mcp-upload.js";
4
+ /** Builds tool handlers that use the class for every store operation. */
5
+ export function buildTools(autofile) {
6
+ return {
7
+ findRecords: (input) => withRefusal(async () => {
8
+ const result = await autofile.records.find(input);
9
+ return {
10
+ records: result.records.map(recordResult),
11
+ errors: result.unreadable,
12
+ ...(result.cursor === undefined ? {} : { cursor: result.cursor }),
13
+ };
14
+ }),
15
+ getRecord: ({ uri }) => withRefusal(async () => {
16
+ const record = await autofile.records.get(uri);
17
+ if (record === undefined) {
18
+ // The library returns undefined for either missing part of this address;
19
+ // MCP has always named the missing declaration when the type is absent.
20
+ const type = uri.slice("autofile:///".length).split("/")[0];
21
+ if (await autofile.types.get(type) === undefined) {
22
+ return { errors: [{ uri: `autofile:///_types/${type}`, message: "type does not exist" }] };
23
+ }
24
+ return { errors: [{ uri, message: "record does not exist" }] };
25
+ }
26
+ return recordResult(record);
27
+ }),
28
+ createRecord: ({ type, record, key }) => withRefusal(async () => {
29
+ const created = await autofile.records.create(type, record, { key });
30
+ return { uri: created.uri };
31
+ }),
32
+ updateRecord: ({ uri, patch }) => withRefusal(async () => {
33
+ const updated = await autofile.records.update(uri, patch);
34
+ return { uri: updated.uri };
35
+ }),
36
+ uploadBlob: (input, options = {}) => withRefusal(() => uploadBlob(autofile, input, options)),
37
+ deleteRecord: ({ uri }) => withRefusal(async () => {
38
+ await autofile.records.delete(uri);
39
+ return { uri };
40
+ }),
41
+ async listTypes() {
42
+ const declarations = await autofile.types.list();
43
+ return {
44
+ types: declarations.map(({ uri, type, description, title }) => ({
45
+ uri, type, description,
46
+ ...(title === undefined ? {} : { title }),
47
+ })),
48
+ };
49
+ },
50
+ getType: ({ type }) => withRefusal(async () => {
51
+ const declaration = await autofile.types.get(type);
52
+ if (declaration === undefined) {
53
+ return { errors: [{ uri: `autofile:///_types/${type}`, message: "type does not exist" }] };
54
+ }
55
+ const { type: _type, ...result } = declaration;
56
+ return result;
57
+ }),
58
+ createType: ({ type, ...declaration }) => withRefusal(async () => {
59
+ const created = await autofile.types.create(type, declaration);
60
+ return { uri: created.uri };
61
+ }),
62
+ updateType: ({ type, ...changes }) => withRefusal(async () => {
63
+ const updated = await autofile.types.update(type, changes);
64
+ return { uri: updated.uri, errors: updated.problems ?? [] };
65
+ }),
66
+ deleteType: ({ type }) => withRefusal(async () => {
67
+ await autofile.types.delete(type);
68
+ return { uri: `autofile:///_types/${type}` };
69
+ }),
70
+ };
71
+ }
72
+ function recordResult(record) {
73
+ const { type: _type, key: _key, problems = [], ...result } = record;
74
+ return {
75
+ ...result,
76
+ ...(problems.length === 0 ? {} : { error: problems.map(({ message }) => message).join("; ") }),
77
+ };
78
+ }
79
+ async function withRefusal(operation) {
80
+ try {
81
+ return await operation();
82
+ }
83
+ catch (error) {
84
+ if (error instanceof AutofileError)
85
+ return { errors: error.problems };
86
+ throw error;
87
+ }
88
+ }
89
+ //# sourceMappingURL=mcp-tools.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-tools.js","sourceRoot":"","sources":["../src/mcp-tools.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /** Validates MCP upload sources and reads local files only for stdio requests. */
2
+ import { type Autofile } from "./index.js";
3
+ /** Arguments to upload_blob; exactly one source is required. */
4
+ export interface UploadBlobInput {
5
+ base64?: string;
6
+ path?: string;
7
+ mediaType?: string;
8
+ }
9
+ /** Local file access is granted only by the stdio transport. */
10
+ export interface UploadBlobOptions {
11
+ allowLocalPaths?: boolean;
12
+ }
13
+ /** Uploads decoded bytes through the library's public blob operation. */
14
+ export declare function uploadBlob(autofile: Autofile, input: UploadBlobInput, options: UploadBlobOptions): Promise<{
15
+ uri: string;
16
+ }>;
@@ -0,0 +1,81 @@
1
+ /** Validates MCP upload sources and reads local files only for stdio requests. */
2
+ import { constants } from "node:fs";
3
+ import { open } from "node:fs/promises";
4
+ import { isAbsolute } from "node:path";
5
+ import { lookup as lookupMimeType } from "mime-types";
6
+ import { AutofileError } from "./index.js";
7
+ // Bound transport decoding and file reads before handing bytes to the library.
8
+ const MAX_UPLOAD_BYTES = 7_340_032;
9
+ /** Uploads decoded bytes through the library's public blob operation. */
10
+ export async function uploadBlob(autofile, input, options) {
11
+ if ((input.base64 === undefined) === (input.path === undefined)) {
12
+ refuse("supply exactly one of base64 or path");
13
+ }
14
+ if (input.path !== undefined) {
15
+ if (options.allowLocalPaths !== true)
16
+ refuse("local paths are accepted only over stdio, not HTTP");
17
+ if (!isAbsolute(input.path))
18
+ refuse("local upload path must be absolute");
19
+ const mediaType = input.mediaType ?? (lookupMimeType(input.path) || "application/octet-stream");
20
+ let bytes;
21
+ try {
22
+ bytes = await readUpload(input.path);
23
+ }
24
+ catch (error) {
25
+ if (error instanceof AutofileError)
26
+ throw error;
27
+ return refuse("local upload source cannot be read");
28
+ }
29
+ return { uri: await autofile.blobs.put(bytes, mediaType) };
30
+ }
31
+ if (input.mediaType === undefined)
32
+ refuse("mediaType is required for base64 uploads");
33
+ const base64 = input.base64;
34
+ // Buffer's base64 decoder silently ignores invalid characters and accepts
35
+ // incomplete padding. Check syntax and the round trip to reject both those
36
+ // forms and nonzero unused bits in the final sextet.
37
+ if (base64.length % 4 !== 0 || !/^[A-Za-z0-9+/]*={0,2}$/u.test(base64)) {
38
+ refuse("base64 must be canonical base64");
39
+ }
40
+ const padding = base64.endsWith("==") ? 2 : base64.endsWith("=") ? 1 : 0;
41
+ const size = base64.length / 4 * 3 - padding;
42
+ if (size > MAX_UPLOAD_BYTES)
43
+ refuseSize(size);
44
+ const bytes = Buffer.from(base64, "base64");
45
+ if (bytes.toString("base64") !== base64)
46
+ refuse("base64 must be canonical base64");
47
+ return { uri: await autofile.blobs.put(bytes, input.mediaType) };
48
+ }
49
+ async function readUpload(path) {
50
+ // Nonblocking opens and a regular-file check keep devices, sockets and pipes
51
+ // from hanging a request. The extra byte also detects growth after stat.
52
+ const file = await open(path, constants.O_RDONLY | constants.O_NONBLOCK);
53
+ try {
54
+ const details = await file.stat();
55
+ if (!details.isFile())
56
+ refuse("local upload source must be a regular file");
57
+ if (details.size > MAX_UPLOAD_BYTES)
58
+ refuseSize(details.size);
59
+ const buffer = Buffer.alloc(MAX_UPLOAD_BYTES + 1);
60
+ let length = 0;
61
+ while (length < buffer.length) {
62
+ const { bytesRead } = await file.read(buffer, length, buffer.length - length, null);
63
+ if (bytesRead === 0)
64
+ break;
65
+ length += bytesRead;
66
+ }
67
+ if (length > MAX_UPLOAD_BYTES)
68
+ refuseSize(length);
69
+ return buffer.subarray(0, length);
70
+ }
71
+ finally {
72
+ await file.close();
73
+ }
74
+ }
75
+ function refuseSize(size) {
76
+ return refuse(`blob is ${String(size)} bytes; limit is ${String(MAX_UPLOAD_BYTES)} bytes`);
77
+ }
78
+ function refuse(message) {
79
+ throw new AutofileError([{ message }]);
80
+ }
81
+ //# sourceMappingURL=mcp-upload.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-upload.js","sourceRoot":"","sources":["../src/mcp-upload.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /** Derives MCP resource-list hints from the changes published by Autofile. */
2
+ import type { Autofile, ChangeEvent } from "./index.js";
3
+ import { type Resources } from "./mcp-resources.js";
4
+ /** One resource update and whether the batch changed the MCP resource list. */
5
+ export interface ResourceChange extends ChangeEvent {
6
+ listChanged: boolean;
7
+ }
8
+ /** Resource updates coalesced by the underlying Autofile watcher. */
9
+ export interface ResourceChangeBatch {
10
+ changes: ResourceChange[];
11
+ listChanged: boolean;
12
+ }
13
+ /** An MCP subscription to the store's shared watcher. */
14
+ export interface ResourceWatcher {
15
+ close(): Promise<void>;
16
+ }
17
+ /** Watches MCP metadata using the instance's existing change subscription API. */
18
+ export declare function watchResources(store: Autofile, onChange: (batch: ResourceChangeBatch) => void | Promise<void>, onError: (error: Error) => void, resources?: Resources): Promise<ResourceWatcher>;
@@ -0,0 +1,165 @@
1
+ /** Derives MCP resource-list hints from the changes published by Autofile. */
2
+ import { buildResources } from "./mcp-resources.js";
3
+ const readFailed = Symbol("read failed");
4
+ const unknownMetadata = Symbol("unknown metadata");
5
+ /** Watches MCP metadata using the instance's existing change subscription API. */
6
+ export async function watchResources(store, onChange, onError, resources = buildResources(store)) {
7
+ const cache = new Map();
8
+ let pending = Promise.resolve();
9
+ let initializing = true;
10
+ const initialChanges = [];
11
+ let unsubscribe;
12
+ try {
13
+ unsubscribe = await store.watch((changes) => {
14
+ if (initializing) {
15
+ initialChanges.push(...changes);
16
+ return;
17
+ }
18
+ return enqueue(changes);
19
+ }, { onError });
20
+ for (const resource of await resources.listResources()) {
21
+ cache.set(resource.uri, resourceMetadata(resource));
22
+ }
23
+ initializing = false;
24
+ if (initialChanges.length > 0)
25
+ await enqueue(initialChanges);
26
+ }
27
+ catch (error) {
28
+ await unsubscribe?.();
29
+ throw error;
30
+ }
31
+ let closing;
32
+ return { close: () => closing ??= closeWatcher() };
33
+ function enqueue(changes) {
34
+ const batch = new Map();
35
+ for (const { uri, kind } of changes)
36
+ addEvent(batch, uri, kind);
37
+ pending = pending.then(() => processBatch(batch))
38
+ .catch((error) => onError(toError(error)));
39
+ return pending;
40
+ }
41
+ async function processBatch(batch) {
42
+ const before = new Set(cache.keys());
43
+ const supplied = new Map();
44
+ const failedUris = new Set();
45
+ let focusedReadFailed = false;
46
+ const markReadFailed = (uri) => {
47
+ focusedReadFailed = true;
48
+ failedUris.add(uri);
49
+ cache.set(uri, unknownMetadata);
50
+ };
51
+ let metadataChanged = false;
52
+ const affectedTypes = new Set();
53
+ for (const uri of batch.keys()) {
54
+ const type = declarationType(uri);
55
+ if (type === undefined || affectedTypes.has(type) || failedUris.has(uri))
56
+ continue;
57
+ affectedTypes.add(type);
58
+ const declarationUri = `autofile:///_types/${type}`;
59
+ const recordPrefix = `autofile:///${type}/`;
60
+ const listed = await readSafely(() => resources.listTypeResources(type));
61
+ if (listed === readFailed) {
62
+ const affectedUris = new Set([...cache.keys(), ...batch.keys()]);
63
+ for (const scopedUri of affectedUris) {
64
+ if (scopedUri !== declarationUri && !scopedUri.startsWith(recordPrefix))
65
+ continue;
66
+ markReadFailed(scopedUri);
67
+ }
68
+ continue;
69
+ }
70
+ const current = new Map(listed.map((resource) => [resource.uri, resource]));
71
+ const scope = new Set(current.keys());
72
+ for (const cachedUri of cache.keys()) {
73
+ if (cachedUri === declarationUri || cachedUri.startsWith(recordPrefix)) {
74
+ scope.add(cachedUri);
75
+ }
76
+ }
77
+ for (const scopedUri of scope) {
78
+ const wasListed = cache.has(scopedUri);
79
+ const isListed = current.has(scopedUri);
80
+ if (scopedUri.startsWith(recordPrefix)
81
+ && wasListed !== isListed
82
+ && !batch.has(scopedUri)) {
83
+ addEvent(batch, scopedUri, isListed ? "created" : "deleted");
84
+ }
85
+ metadataChanged = updateCache(cache, scopedUri, current.get(scopedUri))
86
+ || metadataChanged;
87
+ }
88
+ for (const [currentUri, resource] of current)
89
+ supplied.set(currentUri, resource);
90
+ }
91
+ for (const uri of [...batch.keys()]) {
92
+ if (declarationType(uri) !== undefined)
93
+ continue;
94
+ if (failedUris.has(uri))
95
+ continue;
96
+ const resource = supplied.get(uri)
97
+ ?? await readSafely(() => resources.getResourceMetadata(uri));
98
+ if (resource === readFailed) {
99
+ markReadFailed(uri);
100
+ continue;
101
+ }
102
+ metadataChanged = updateCache(cache, uri, resource) || metadataChanged;
103
+ }
104
+ for (const uri of batch.keys()) {
105
+ if (!before.has(uri) && !cache.has(uri) && !failedUris.has(uri))
106
+ batch.delete(uri);
107
+ }
108
+ const listChanged = focusedReadFailed
109
+ || metadataChanged
110
+ || [...batch.values()].some((event) => event.membershipChanged);
111
+ const changes = [...batch.entries()].map(([uri, event]) => ({
112
+ uri,
113
+ kind: event.lastEvent,
114
+ listChanged,
115
+ }));
116
+ if (changes.length > 0 || listChanged)
117
+ await onChange({ changes, listChanged });
118
+ }
119
+ async function closeWatcher() {
120
+ await unsubscribe?.();
121
+ await pending;
122
+ }
123
+ async function readSafely(read) {
124
+ try {
125
+ return await read();
126
+ }
127
+ catch (error) {
128
+ onError(toError(error));
129
+ return readFailed;
130
+ }
131
+ }
132
+ }
133
+ function addEvent(batch, uri, event) {
134
+ const existing = batch.get(uri);
135
+ if (existing === undefined) {
136
+ batch.set(uri, { membershipChanged: event !== "changed", lastEvent: event });
137
+ }
138
+ else {
139
+ existing.membershipChanged ||= event !== "changed";
140
+ existing.lastEvent = event;
141
+ }
142
+ }
143
+ function updateCache(cache, uri, resource) {
144
+ const previous = cache.get(uri);
145
+ const next = resource === undefined ? undefined : resourceMetadata(resource);
146
+ if (next === undefined)
147
+ cache.delete(uri);
148
+ else
149
+ cache.set(uri, next);
150
+ return previous === unknownMetadata
151
+ || previous?.title !== next?.title
152
+ || previous?.description !== next?.description
153
+ || (previous === undefined) !== (next === undefined);
154
+ }
155
+ function resourceMetadata(resource) {
156
+ return { title: resource.title, description: resource.description };
157
+ }
158
+ function declarationType(uri) {
159
+ const match = /^autofile:\/\/\/_types\/([a-z][a-z0-9-]*)$/u.exec(uri);
160
+ return match?.[1];
161
+ }
162
+ function toError(error) {
163
+ return error instanceof Error ? error : new Error(String(error));
164
+ }
165
+ //# sourceMappingURL=mcp-watch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-watch.js","sourceRoot":"","sources":["../src/mcp-watch.ts"],"names":[],"mappings":"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"}