@cerefox/memory 0.10.3 → 0.11.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/AGENT_GUIDE.md +47 -20
- package/AGENT_QUICK_REFERENCE.md +16 -11
- package/dist/bin/cerefox.js +525 -331
- package/dist/frontend/assets/{index-DVXDQ7__.js → index-ojNhWSxm.js} +3 -3
- package/dist/frontend/assets/index-ojNhWSxm.js.map +1 -0
- package/dist/frontend/index.html +1 -1
- package/dist/server-assets/_shared/ef-meta/index.ts +1 -1
- package/dist/server-assets/_shared/mcp-tools/_projects.ts +117 -1
- package/dist/server-assets/_shared/mcp-tools/get-document.ts +6 -2
- package/dist/server-assets/_shared/mcp-tools/get-help-content.ts +6 -6
- package/dist/server-assets/_shared/mcp-tools/ingest.ts +71 -6
- package/dist/server-assets/_shared/mcp-tools/metadata-search.ts +20 -12
- package/dist/server-assets/_shared/mcp-tools/search.ts +4 -1
- package/dist/server-assets/_shared/mcp-tools/set-document-projects.ts +9 -74
- package/dist/server-assets/db/rpcs.sql +77 -11
- package/dist/server-assets/db/schema.sql +1 -1
- package/dist/server-assets/supabase/functions/cerefox-get-document/index.ts +5 -1
- package/dist/server-assets/supabase/functions/cerefox-ingest/index.ts +65 -1
- package/dist/server-assets/supabase/functions/cerefox-metadata-search/index.ts +25 -7
- package/docs/guides/access-paths.md +1 -1
- package/docs/guides/agent-coordination.md +14 -1
- package/docs/guides/cli.md +109 -6
- package/docs/guides/connect-agents.md +51 -7
- package/package.json +1 -1
- package/dist/frontend/assets/index-DVXDQ7__.js.map +0 -1
package/dist/bin/cerefox.js
CHANGED
|
@@ -7184,7 +7184,7 @@ var exports_meta = {};
|
|
|
7184
7184
|
__export(exports_meta, {
|
|
7185
7185
|
PKG_VERSION: () => PKG_VERSION
|
|
7186
7186
|
});
|
|
7187
|
-
var PKG_VERSION = "0.
|
|
7187
|
+
var PKG_VERSION = "0.11.0";
|
|
7188
7188
|
var init_meta = () => {};
|
|
7189
7189
|
|
|
7190
7190
|
// ../../node_modules/.bun/tslib@2.8.1/node_modules/tslib/tslib.js
|
|
@@ -7792,7 +7792,7 @@ var require_tslib = __commonJS((exports, module) => {
|
|
|
7792
7792
|
});
|
|
7793
7793
|
});
|
|
7794
7794
|
|
|
7795
|
-
// ../../node_modules/.bun/@supabase+functions-js@2.
|
|
7795
|
+
// ../../node_modules/.bun/@supabase+functions-js@2.108.1/node_modules/@supabase/functions-js/dist/main/helper.js
|
|
7796
7796
|
var require_helper = __commonJS((exports) => {
|
|
7797
7797
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7798
7798
|
exports.resolveFetch = undefined;
|
|
@@ -7805,7 +7805,7 @@ var require_helper = __commonJS((exports) => {
|
|
|
7805
7805
|
exports.resolveFetch = resolveFetch;
|
|
7806
7806
|
});
|
|
7807
7807
|
|
|
7808
|
-
// ../../node_modules/.bun/@supabase+functions-js@2.
|
|
7808
|
+
// ../../node_modules/.bun/@supabase+functions-js@2.108.1/node_modules/@supabase/functions-js/dist/main/types.js
|
|
7809
7809
|
var require_types = __commonJS((exports) => {
|
|
7810
7810
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7811
7811
|
exports.FunctionRegion = exports.FunctionsHttpError = exports.FunctionsRelayError = exports.FunctionsFetchError = exports.FunctionsError = undefined;
|
|
@@ -7866,7 +7866,7 @@ var require_types = __commonJS((exports) => {
|
|
|
7866
7866
|
})(FunctionRegion || (exports.FunctionRegion = FunctionRegion = {}));
|
|
7867
7867
|
});
|
|
7868
7868
|
|
|
7869
|
-
// ../../node_modules/.bun/@supabase+functions-js@2.
|
|
7869
|
+
// ../../node_modules/.bun/@supabase+functions-js@2.108.1/node_modules/@supabase/functions-js/dist/main/FunctionsClient.js
|
|
7870
7870
|
var require_FunctionsClient = __commonJS((exports) => {
|
|
7871
7871
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7872
7872
|
exports.FunctionsClient = undefined;
|
|
@@ -7979,7 +7979,7 @@ var require_FunctionsClient = __commonJS((exports) => {
|
|
|
7979
7979
|
exports.FunctionsClient = FunctionsClient;
|
|
7980
7980
|
});
|
|
7981
7981
|
|
|
7982
|
-
// ../../node_modules/.bun/@supabase+functions-js@2.
|
|
7982
|
+
// ../../node_modules/.bun/@supabase+functions-js@2.108.1/node_modules/@supabase/functions-js/dist/main/index.js
|
|
7983
7983
|
var require_main = __commonJS((exports) => {
|
|
7984
7984
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7985
7985
|
exports.FunctionRegion = exports.FunctionsRelayError = exports.FunctionsHttpError = exports.FunctionsFetchError = exports.FunctionsError = exports.FunctionsClient = undefined;
|
|
@@ -8005,7 +8005,7 @@ var require_main = __commonJS((exports) => {
|
|
|
8005
8005
|
} });
|
|
8006
8006
|
});
|
|
8007
8007
|
|
|
8008
|
-
// ../../node_modules/.bun/@supabase+postgrest-js@2.
|
|
8008
|
+
// ../../node_modules/.bun/@supabase+postgrest-js@2.108.1/node_modules/@supabase/postgrest-js/dist/index.mjs
|
|
8009
8009
|
function sleep(ms, signal) {
|
|
8010
8010
|
return new Promise((resolve) => {
|
|
8011
8011
|
if (signal === null || signal === undefined ? undefined : signal.aborted) {
|
|
@@ -8144,14 +8144,17 @@ var DEFAULT_MAX_RETRIES = 3, getRetryDelay = (attemptIndex) => Math.min(1000 * 2
|
|
|
8144
8144
|
const executeWithRetry = async () => {
|
|
8145
8145
|
let attemptCount = 0;
|
|
8146
8146
|
while (true) {
|
|
8147
|
-
const
|
|
8147
|
+
const headers = {};
|
|
8148
|
+
_this.headers.forEach((value, key) => {
|
|
8149
|
+
headers[key] = value;
|
|
8150
|
+
});
|
|
8148
8151
|
if (attemptCount > 0)
|
|
8149
|
-
|
|
8152
|
+
headers["X-Retry-Count"] = String(attemptCount);
|
|
8150
8153
|
let res$1;
|
|
8151
8154
|
try {
|
|
8152
8155
|
res$1 = await _fetch(_this.url.toString(), {
|
|
8153
8156
|
method: _this.method,
|
|
8154
|
-
headers
|
|
8157
|
+
headers,
|
|
8155
8158
|
body: JSON.stringify(_this.body, (_, value) => typeof value === "bigint" ? value.toString() : value),
|
|
8156
8159
|
signal: _this.signal
|
|
8157
8160
|
});
|
|
@@ -8562,6 +8565,9 @@ var init_dist = __esm(() => {
|
|
|
8562
8565
|
}
|
|
8563
8566
|
};
|
|
8564
8567
|
PostgrestTransformBuilder = class extends PostgrestBuilder {
|
|
8568
|
+
throwOnError() {
|
|
8569
|
+
return super.throwOnError();
|
|
8570
|
+
}
|
|
8565
8571
|
select(columns) {
|
|
8566
8572
|
let quoted = false;
|
|
8567
8573
|
const cleanedColumns = (columns !== null && columns !== undefined ? columns : "*").split("").map((c2) => {
|
|
@@ -8581,9 +8587,9 @@ var init_dist = __esm(() => {
|
|
|
8581
8587
|
this.url.searchParams.set(key, `${existingOrder ? `${existingOrder},` : ""}${column}.${ascending ? "asc" : "desc"}${nullsFirst === undefined ? "" : nullsFirst ? ".nullsfirst" : ".nullslast"}`);
|
|
8582
8588
|
return this;
|
|
8583
8589
|
}
|
|
8584
|
-
limit(
|
|
8590
|
+
limit(rows, { foreignTable, referencedTable = foreignTable } = {}) {
|
|
8585
8591
|
const key = typeof referencedTable === "undefined" ? "limit" : `${referencedTable}.limit`;
|
|
8586
|
-
this.url.searchParams.set(key, `${
|
|
8592
|
+
this.url.searchParams.set(key, `${rows}`);
|
|
8587
8593
|
return this;
|
|
8588
8594
|
}
|
|
8589
8595
|
range(from, to, { foreignTable, referencedTable = foreignTable } = {}) {
|
|
@@ -8636,14 +8642,17 @@ var init_dist = __esm(() => {
|
|
|
8636
8642
|
returns() {
|
|
8637
8643
|
return this;
|
|
8638
8644
|
}
|
|
8639
|
-
maxAffected(
|
|
8645
|
+
maxAffected(rows) {
|
|
8640
8646
|
this.headers.append("Prefer", "handling=strict");
|
|
8641
|
-
this.headers.append("Prefer", `max-affected=${
|
|
8647
|
+
this.headers.append("Prefer", `max-affected=${rows}`);
|
|
8642
8648
|
return this;
|
|
8643
8649
|
}
|
|
8644
8650
|
};
|
|
8645
8651
|
PostgrestReservedCharsRegexp = /* @__PURE__ */ new RegExp("[,()]");
|
|
8646
8652
|
PostgrestFilterBuilder = class extends PostgrestTransformBuilder {
|
|
8653
|
+
throwOnError() {
|
|
8654
|
+
return super.throwOnError();
|
|
8655
|
+
}
|
|
8647
8656
|
eq(column, value) {
|
|
8648
8657
|
this.url.searchParams.append(column, `eq.${value}`);
|
|
8649
8658
|
return this;
|
|
@@ -8807,7 +8816,7 @@ var init_dist = __esm(() => {
|
|
|
8807
8816
|
};
|
|
8808
8817
|
});
|
|
8809
8818
|
|
|
8810
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
8819
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/websocket-factory.js
|
|
8811
8820
|
var require_websocket_factory = __commonJS((exports) => {
|
|
8812
8821
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8813
8822
|
exports.WebSocketFactory = undefined;
|
|
@@ -8898,14 +8907,14 @@ Suggested solution: ${env.workaround}`;
|
|
|
8898
8907
|
exports.default = WebSocketFactory;
|
|
8899
8908
|
});
|
|
8900
8909
|
|
|
8901
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
8910
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/version.js
|
|
8902
8911
|
var require_version = __commonJS((exports) => {
|
|
8903
8912
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8904
8913
|
exports.version = undefined;
|
|
8905
|
-
exports.version = "2.
|
|
8914
|
+
exports.version = "2.108.1";
|
|
8906
8915
|
});
|
|
8907
8916
|
|
|
8908
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
8917
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/constants.js
|
|
8909
8918
|
var require_constants = __commonJS((exports) => {
|
|
8910
8919
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8911
8920
|
exports.CONNECTION_STATE = exports.TRANSPORTS = exports.CHANNEL_EVENTS = exports.CHANNEL_STATES = exports.SOCKET_STATES = exports.MAX_PUSH_BUFFER_SIZE = exports.WS_CLOSE_NORMAL = exports.DEFAULT_TIMEOUT = exports.VERSION = exports.DEFAULT_VSN = exports.VSN_2_0_0 = exports.VSN_1_0_0 = exports.DEFAULT_VERSION = undefined;
|
|
@@ -8950,7 +8959,7 @@ var require_constants = __commonJS((exports) => {
|
|
|
8950
8959
|
};
|
|
8951
8960
|
});
|
|
8952
8961
|
|
|
8953
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
8962
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/serializer.js
|
|
8954
8963
|
var require_serializer = __commonJS((exports) => {
|
|
8955
8964
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8956
8965
|
|
|
@@ -9095,7 +9104,7 @@ var require_serializer = __commonJS((exports) => {
|
|
|
9095
9104
|
exports.default = Serializer;
|
|
9096
9105
|
});
|
|
9097
9106
|
|
|
9098
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
9107
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/transformers.js
|
|
9099
9108
|
var require_transformers = __commonJS((exports) => {
|
|
9100
9109
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9101
9110
|
exports.httpEndpointURL = exports.toTimestampString = exports.toArray = exports.toJson = exports.toNumber = exports.toBoolean = exports.convertCell = exports.convertColumn = exports.convertChangeData = exports.PostgresTypes = undefined;
|
|
@@ -10642,7 +10651,7 @@ var require_phoenix_cjs = __commonJS((exports, module) => {
|
|
|
10642
10651
|
};
|
|
10643
10652
|
});
|
|
10644
10653
|
|
|
10645
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
10654
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/phoenix/presenceAdapter.js
|
|
10646
10655
|
var require_presenceAdapter = __commonJS((exports) => {
|
|
10647
10656
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10648
10657
|
var phoenix_1 = require_phoenix_cjs();
|
|
@@ -10715,7 +10724,7 @@ var require_presenceAdapter = __commonJS((exports) => {
|
|
|
10715
10724
|
}
|
|
10716
10725
|
});
|
|
10717
10726
|
|
|
10718
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
10727
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/RealtimePresence.js
|
|
10719
10728
|
var require_RealtimePresence = __commonJS((exports) => {
|
|
10720
10729
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10721
10730
|
exports.REALTIME_PRESENCE_LISTEN_EVENTS = undefined;
|
|
@@ -10740,7 +10749,7 @@ var require_RealtimePresence = __commonJS((exports) => {
|
|
|
10740
10749
|
exports.default = RealtimePresence;
|
|
10741
10750
|
});
|
|
10742
10751
|
|
|
10743
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
10752
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/lib/normalizeChannelError.js
|
|
10744
10753
|
var require_normalizeChannelError = __commonJS((exports) => {
|
|
10745
10754
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10746
10755
|
exports.normalizeChannelError = normalizeChannelError;
|
|
@@ -10763,7 +10772,7 @@ var require_normalizeChannelError = __commonJS((exports) => {
|
|
|
10763
10772
|
}
|
|
10764
10773
|
});
|
|
10765
10774
|
|
|
10766
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
10775
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/phoenix/channelAdapter.js
|
|
10767
10776
|
var require_channelAdapter = __commonJS((exports) => {
|
|
10768
10777
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10769
10778
|
var constants_1 = require_constants();
|
|
@@ -10865,7 +10874,7 @@ var require_channelAdapter = __commonJS((exports) => {
|
|
|
10865
10874
|
}
|
|
10866
10875
|
});
|
|
10867
10876
|
|
|
10868
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
10877
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/RealtimeChannel.js
|
|
10869
10878
|
var require_RealtimeChannel = __commonJS((exports) => {
|
|
10870
10879
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10871
10880
|
exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_LISTEN_TYPES = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = undefined;
|
|
@@ -11240,7 +11249,7 @@ var require_RealtimeChannel = __commonJS((exports) => {
|
|
|
11240
11249
|
exports.default = RealtimeChannel;
|
|
11241
11250
|
});
|
|
11242
11251
|
|
|
11243
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
11252
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/phoenix/socketAdapter.js
|
|
11244
11253
|
var require_socketAdapter = __commonJS((exports) => {
|
|
11245
11254
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11246
11255
|
var phoenix_1 = require_phoenix_cjs();
|
|
@@ -11353,7 +11362,7 @@ var require_socketAdapter = __commonJS((exports) => {
|
|
|
11353
11362
|
exports.default = SocketAdapter;
|
|
11354
11363
|
});
|
|
11355
11364
|
|
|
11356
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
11365
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/RealtimeClient.js
|
|
11357
11366
|
var require_RealtimeClient = __commonJS((exports) => {
|
|
11358
11367
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11359
11368
|
var tslib_1 = require_tslib();
|
|
@@ -11820,7 +11829,7 @@ var require_RealtimeClient = __commonJS((exports) => {
|
|
|
11820
11829
|
exports.default = RealtimeClient;
|
|
11821
11830
|
});
|
|
11822
11831
|
|
|
11823
|
-
// ../../node_modules/.bun/@supabase+realtime-js@2.
|
|
11832
|
+
// ../../node_modules/.bun/@supabase+realtime-js@2.108.1/node_modules/@supabase/realtime-js/dist/main/index.js
|
|
11824
11833
|
var require_main2 = __commonJS((exports) => {
|
|
11825
11834
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11826
11835
|
exports.WebSocketFactory = exports.REALTIME_CHANNEL_STATES = exports.REALTIME_SUBSCRIBE_STATES = exports.REALTIME_PRESENCE_LISTEN_EVENTS = exports.REALTIME_POSTGRES_CHANGES_LISTEN_EVENT = exports.REALTIME_LISTEN_TYPES = exports.RealtimeClient = exports.RealtimeChannel = exports.RealtimePresence = undefined;
|
|
@@ -12150,7 +12159,7 @@ var init_dist2 = __esm(() => {
|
|
|
12150
12159
|
};
|
|
12151
12160
|
});
|
|
12152
12161
|
|
|
12153
|
-
// ../../node_modules/.bun/@supabase+storage-js@2.
|
|
12162
|
+
// ../../node_modules/.bun/@supabase+storage-js@2.108.1/node_modules/@supabase/storage-js/dist/index.mjs
|
|
12154
12163
|
function _typeof2(o) {
|
|
12155
12164
|
"@babel/helpers - typeof";
|
|
12156
12165
|
return _typeof2 = typeof Symbol == "function" && typeof Symbol.iterator == "symbol" ? function(o$1) {
|
|
@@ -12458,7 +12467,7 @@ var StorageError, StorageApiError, StorageUnknownError, resolveFetch = (customFe
|
|
|
12458
12467
|
throw error;
|
|
12459
12468
|
}
|
|
12460
12469
|
}
|
|
12461
|
-
}, DEFAULT_SEARCH_OPTIONS, DEFAULT_FILE_OPTIONS, StorageFileApi, version = "2.
|
|
12470
|
+
}, DEFAULT_SEARCH_OPTIONS, DEFAULT_FILE_OPTIONS, StorageFileApi, version = "2.108.1", DEFAULT_HEADERS, StorageBucketApi, StorageAnalyticsClient, VectorIndexApi, VectorDataApi, VectorBucketApi, StorageVectorsClient, VectorBucketScope, VectorIndexScope, StorageClient;
|
|
12462
12471
|
var init_dist3 = __esm(() => {
|
|
12463
12472
|
init_dist2();
|
|
12464
12473
|
StorageError = class extends Error {
|
|
@@ -13166,14 +13175,14 @@ var init_dist3 = __esm(() => {
|
|
|
13166
13175
|
};
|
|
13167
13176
|
});
|
|
13168
13177
|
|
|
13169
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13178
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/version.js
|
|
13170
13179
|
var require_version2 = __commonJS((exports) => {
|
|
13171
13180
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13172
13181
|
exports.version = undefined;
|
|
13173
|
-
exports.version = "2.
|
|
13182
|
+
exports.version = "2.108.1";
|
|
13174
13183
|
});
|
|
13175
13184
|
|
|
13176
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13185
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/constants.js
|
|
13177
13186
|
var require_constants2 = __commonJS((exports) => {
|
|
13178
13187
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13179
13188
|
exports.JWKS_TTL = exports.BASE64URL_REGEX = exports.API_VERSIONS = exports.API_VERSION_HEADER_NAME = exports.NETWORK_FAILURE = exports.DEFAULT_HEADERS = exports.AUDIENCE = exports.STORAGE_KEY = exports.GOTRUE_URL = exports.EXPIRY_MARGIN_MS = exports.AUTO_REFRESH_TICK_THRESHOLD = exports.AUTO_REFRESH_TICK_DURATION_MS = undefined;
|
|
@@ -13200,7 +13209,7 @@ var require_constants2 = __commonJS((exports) => {
|
|
|
13200
13209
|
exports.JWKS_TTL = 10 * 60 * 1000;
|
|
13201
13210
|
});
|
|
13202
13211
|
|
|
13203
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13212
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/errors.js
|
|
13204
13213
|
var require_errors = __commonJS((exports) => {
|
|
13205
13214
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13206
13215
|
exports.AuthInvalidJwtError = exports.AuthWeakPasswordError = exports.AuthRefreshDiscardedError = exports.AuthRetryableFetchError = exports.AuthPKCECodeVerifierMissingError = exports.AuthPKCEGrantCodeExchangeError = exports.AuthImplicitGrantRedirectError = exports.AuthInvalidCredentialsError = exports.AuthInvalidTokenResponseError = exports.AuthSessionMissingError = exports.CustomAuthError = exports.AuthUnknownError = exports.AuthApiError = exports.AuthError = undefined;
|
|
@@ -13369,7 +13378,7 @@ var require_errors = __commonJS((exports) => {
|
|
|
13369
13378
|
exports.AuthInvalidJwtError = AuthInvalidJwtError;
|
|
13370
13379
|
});
|
|
13371
13380
|
|
|
13372
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13381
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/base64url.js
|
|
13373
13382
|
var require_base64url = __commonJS((exports) => {
|
|
13374
13383
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13375
13384
|
exports.byteToBase64URL = byteToBase64URL;
|
|
@@ -13557,7 +13566,7 @@ var require_base64url = __commonJS((exports) => {
|
|
|
13557
13566
|
}
|
|
13558
13567
|
});
|
|
13559
13568
|
|
|
13560
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13569
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/helpers.js
|
|
13561
13570
|
var require_helpers = __commonJS((exports) => {
|
|
13562
13571
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13563
13572
|
exports.Deferred = exports.removeItemAsync = exports.getItemAsync = exports.setItemAsync = exports.looksLikeFetchResponse = exports.resolveFetch = exports.supportsLocalStorage = exports.isBrowser = undefined;
|
|
@@ -13872,7 +13881,7 @@ var require_helpers = __commonJS((exports) => {
|
|
|
13872
13881
|
}
|
|
13873
13882
|
});
|
|
13874
13883
|
|
|
13875
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
13884
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/fetch.js
|
|
13876
13885
|
var require_fetch = __commonJS((exports) => {
|
|
13877
13886
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13878
13887
|
exports.handleError = handleError2;
|
|
@@ -14037,14 +14046,14 @@ var require_fetch = __commonJS((exports) => {
|
|
|
14037
14046
|
}
|
|
14038
14047
|
});
|
|
14039
14048
|
|
|
14040
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14049
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/types.js
|
|
14041
14050
|
var require_types2 = __commonJS((exports) => {
|
|
14042
14051
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14043
14052
|
exports.SIGN_OUT_SCOPES = undefined;
|
|
14044
14053
|
exports.SIGN_OUT_SCOPES = ["global", "local", "others"];
|
|
14045
14054
|
});
|
|
14046
14055
|
|
|
14047
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14056
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/GoTrueAdminApi.js
|
|
14048
14057
|
var require_GoTrueAdminApi = __commonJS((exports) => {
|
|
14049
14058
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14050
14059
|
var tslib_1 = require_tslib();
|
|
@@ -14491,7 +14500,7 @@ var require_GoTrueAdminApi = __commonJS((exports) => {
|
|
|
14491
14500
|
exports.default = GoTrueAdminApi;
|
|
14492
14501
|
});
|
|
14493
14502
|
|
|
14494
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14503
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/local-storage.js
|
|
14495
14504
|
var require_local_storage = __commonJS((exports) => {
|
|
14496
14505
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14497
14506
|
exports.memoryLocalStorageAdapter = memoryLocalStorageAdapter;
|
|
@@ -14510,7 +14519,7 @@ var require_local_storage = __commonJS((exports) => {
|
|
|
14510
14519
|
}
|
|
14511
14520
|
});
|
|
14512
14521
|
|
|
14513
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14522
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/locks.js
|
|
14514
14523
|
var require_locks = __commonJS((exports) => {
|
|
14515
14524
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14516
14525
|
exports.ProcessLockAcquireTimeoutError = exports.NavigatorLockAcquireTimeoutError = exports.LockAcquireTimeoutError = exports.internals = undefined;
|
|
@@ -14684,7 +14693,7 @@ var require_locks = __commonJS((exports) => {
|
|
|
14684
14693
|
}
|
|
14685
14694
|
});
|
|
14686
14695
|
|
|
14687
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14696
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/polyfills.js
|
|
14688
14697
|
var require_polyfills = __commonJS((exports) => {
|
|
14689
14698
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14690
14699
|
exports.polyfillGlobalThis = polyfillGlobalThis;
|
|
@@ -14708,7 +14717,7 @@ var require_polyfills = __commonJS((exports) => {
|
|
|
14708
14717
|
}
|
|
14709
14718
|
});
|
|
14710
14719
|
|
|
14711
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14720
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/web3/ethereum.js
|
|
14712
14721
|
var require_ethereum = __commonJS((exports) => {
|
|
14713
14722
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14714
14723
|
exports.getAddress = getAddress;
|
|
@@ -14785,7 +14794,7 @@ ${suffix}`;
|
|
|
14785
14794
|
}
|
|
14786
14795
|
});
|
|
14787
14796
|
|
|
14788
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14797
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/webauthn.errors.js
|
|
14789
14798
|
var require_webauthn_errors = __commonJS((exports) => {
|
|
14790
14799
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14791
14800
|
exports.WebAuthnUnknownError = exports.WebAuthnError = undefined;
|
|
@@ -14972,7 +14981,7 @@ var require_webauthn_errors = __commonJS((exports) => {
|
|
|
14972
14981
|
}
|
|
14973
14982
|
});
|
|
14974
14983
|
|
|
14975
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
14984
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/lib/webauthn.js
|
|
14976
14985
|
var require_webauthn = __commonJS((exports) => {
|
|
14977
14986
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14978
14987
|
exports.WebAuthnApi = exports.DEFAULT_REQUEST_OPTIONS = exports.DEFAULT_CREATION_OPTIONS = exports.webAuthnAbortService = exports.WebAuthnAbortService = exports.identifyAuthenticationError = exports.identifyRegistrationError = exports.isWebAuthnError = exports.WebAuthnError = undefined;
|
|
@@ -15426,7 +15435,7 @@ var require_webauthn = __commonJS((exports) => {
|
|
|
15426
15435
|
exports.WebAuthnApi = WebAuthnApi;
|
|
15427
15436
|
});
|
|
15428
15437
|
|
|
15429
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
15438
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/GoTrueClient.js
|
|
15430
15439
|
var require_GoTrueClient = __commonJS((exports) => {
|
|
15431
15440
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15432
15441
|
var tslib_1 = require_tslib();
|
|
@@ -16261,15 +16270,25 @@ var require_GoTrueClient = __commonJS((exports) => {
|
|
|
16261
16270
|
const endpoint = `${this.url}/resend`;
|
|
16262
16271
|
if ("email" in credentials) {
|
|
16263
16272
|
const { email, type, options } = credentials;
|
|
16273
|
+
let codeChallenge = null;
|
|
16274
|
+
let codeChallengeMethod = null;
|
|
16275
|
+
if (this.flowType === "pkce") {
|
|
16276
|
+
[codeChallenge, codeChallengeMethod] = await (0, helpers_1.getCodeChallengeAndMethod)(this.storage, this.storageKey);
|
|
16277
|
+
}
|
|
16264
16278
|
const { error } = await (0, fetch_1._request)(this.fetch, "POST", endpoint, {
|
|
16265
16279
|
headers: this.headers,
|
|
16266
16280
|
body: {
|
|
16267
16281
|
email,
|
|
16268
16282
|
type,
|
|
16269
|
-
gotrue_meta_security: { captcha_token: options === null || options === undefined ? undefined : options.captchaToken }
|
|
16283
|
+
gotrue_meta_security: { captcha_token: options === null || options === undefined ? undefined : options.captchaToken },
|
|
16284
|
+
code_challenge: codeChallenge,
|
|
16285
|
+
code_challenge_method: codeChallengeMethod
|
|
16270
16286
|
},
|
|
16271
16287
|
redirectTo: options === null || options === undefined ? undefined : options.emailRedirectTo
|
|
16272
16288
|
});
|
|
16289
|
+
if (error) {
|
|
16290
|
+
await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
16291
|
+
}
|
|
16273
16292
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
16274
16293
|
} else if ("phone" in credentials) {
|
|
16275
16294
|
const { phone, type, options } = credentials;
|
|
@@ -16288,6 +16307,7 @@ var require_GoTrueClient = __commonJS((exports) => {
|
|
|
16288
16307
|
}
|
|
16289
16308
|
throw new errors_1.AuthInvalidCredentialsError("You must provide either an email or phone number and a type");
|
|
16290
16309
|
} catch (error) {
|
|
16310
|
+
await (0, helpers_1.removeItemAsync)(this.storage, `${this.storageKey}-code-verifier`);
|
|
16291
16311
|
if ((0, errors_1.isAuthError)(error)) {
|
|
16292
16312
|
return this._returnResult({ data: { user: null, session: null }, error });
|
|
16293
16313
|
}
|
|
@@ -17002,7 +17022,7 @@ var require_GoTrueClient = __commonJS((exports) => {
|
|
|
17002
17022
|
if ((0, errors_1.isAuthRefreshDiscardedError)(error)) {
|
|
17003
17023
|
this._debug(debugName, "refresh discarded by commit guard", error);
|
|
17004
17024
|
} else {
|
|
17005
|
-
|
|
17025
|
+
this._debug(debugName, "refresh failed", error);
|
|
17006
17026
|
if (!(0, errors_1.isAuthRetryableFetchError)(error)) {
|
|
17007
17027
|
this._debug(debugName, "refresh failed with a non-retryable error, removing the session", error);
|
|
17008
17028
|
await this._removeSession();
|
|
@@ -18068,7 +18088,7 @@ var require_GoTrueClient = __commonJS((exports) => {
|
|
|
18068
18088
|
exports.default = GoTrueClient;
|
|
18069
18089
|
});
|
|
18070
18090
|
|
|
18071
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
18091
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/AuthAdminApi.js
|
|
18072
18092
|
var require_AuthAdminApi = __commonJS((exports) => {
|
|
18073
18093
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18074
18094
|
var tslib_1 = require_tslib();
|
|
@@ -18077,7 +18097,7 @@ var require_AuthAdminApi = __commonJS((exports) => {
|
|
|
18077
18097
|
exports.default = AuthAdminApi;
|
|
18078
18098
|
});
|
|
18079
18099
|
|
|
18080
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
18100
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/AuthClient.js
|
|
18081
18101
|
var require_AuthClient = __commonJS((exports) => {
|
|
18082
18102
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18083
18103
|
var tslib_1 = require_tslib();
|
|
@@ -18086,7 +18106,7 @@ var require_AuthClient = __commonJS((exports) => {
|
|
|
18086
18106
|
exports.default = AuthClient;
|
|
18087
18107
|
});
|
|
18088
18108
|
|
|
18089
|
-
// ../../node_modules/.bun/@supabase+auth-js@2.
|
|
18109
|
+
// ../../node_modules/.bun/@supabase+auth-js@2.108.1/node_modules/@supabase/auth-js/dist/main/index.js
|
|
18090
18110
|
var require_main3 = __commonJS((exports) => {
|
|
18091
18111
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
18092
18112
|
exports.processLock = exports.lockInternals = exports.NavigatorLockAcquireTimeoutError = exports.navigatorLock = exports.AuthClient = exports.AuthAdminApi = exports.GoTrueClient = exports.GoTrueAdminApi = undefined;
|
|
@@ -18116,7 +18136,7 @@ var require_main3 = __commonJS((exports) => {
|
|
|
18116
18136
|
} });
|
|
18117
18137
|
});
|
|
18118
18138
|
|
|
18119
|
-
// ../../node_modules/.bun/@supabase+supabase-js@2.
|
|
18139
|
+
// ../../node_modules/.bun/@supabase+supabase-js@2.108.1/node_modules/@supabase/supabase-js/dist/index.mjs
|
|
18120
18140
|
var exports_dist = {};
|
|
18121
18141
|
__export(exports_dist, {
|
|
18122
18142
|
createClient: () => createClient,
|
|
@@ -18377,7 +18397,7 @@ function shouldShowDeprecationWarning() {
|
|
|
18377
18397
|
return false;
|
|
18378
18398
|
return parseInt(versionMatch[1], 10) <= 18;
|
|
18379
18399
|
}
|
|
18380
|
-
var import_functions_js, import_realtime_js, import_auth_js, version2 = "2.
|
|
18400
|
+
var import_functions_js, import_realtime_js, import_auth_js, version2 = "2.108.1", JS_ENV = "", JS_RUNTIME_VERSION, _Deno$version, _process$version, _runtimeMeta, DEFAULT_HEADERS2, DEFAULT_GLOBAL_OPTIONS, DEFAULT_DB_OPTIONS, DEFAULT_AUTH_OPTIONS, DEFAULT_REALTIME_OPTIONS, DEFAULT_TRACE_PROPAGATION_OPTIONS, otelModulePromise = null, OTEL_PKG = "@opentelemetry/api", resolveFetch2 = (customFetch) => {
|
|
18381
18401
|
if (customFetch)
|
|
18382
18402
|
return (...args) => customFetch(...args);
|
|
18383
18403
|
return (...args) => fetch(...args);
|
|
@@ -24758,6 +24778,157 @@ var init_src = __esm(() => {
|
|
|
24758
24778
|
src_default = Postgres;
|
|
24759
24779
|
});
|
|
24760
24780
|
|
|
24781
|
+
// ../../_shared/mcp-tools/_utils.ts
|
|
24782
|
+
function getMaxResponseBytes() {
|
|
24783
|
+
const raw = globalThis.process?.env?.CEREFOX_MAX_RESPONSE_BYTES;
|
|
24784
|
+
if (raw === undefined || raw === "")
|
|
24785
|
+
return MAX_RESPONSE_BYTES;
|
|
24786
|
+
const n = Number.parseInt(raw, 10);
|
|
24787
|
+
return Number.isNaN(n) || n <= 0 ? MAX_RESPONSE_BYTES : n;
|
|
24788
|
+
}
|
|
24789
|
+
function getMinSearchScore() {
|
|
24790
|
+
const raw = globalThis.process?.env?.CEREFOX_MIN_SEARCH_SCORE;
|
|
24791
|
+
if (raw === undefined || raw === "")
|
|
24792
|
+
return DEFAULT_MIN_SEARCH_SCORE;
|
|
24793
|
+
const n = Number.parseFloat(raw);
|
|
24794
|
+
return Number.isNaN(n) || n < 0 || n > 1 ? DEFAULT_MIN_SEARCH_SCORE : n;
|
|
24795
|
+
}
|
|
24796
|
+
function applyByteBudget(rows, maxBytes) {
|
|
24797
|
+
const accepted = [];
|
|
24798
|
+
let usedBytes = 0;
|
|
24799
|
+
let truncated = false;
|
|
24800
|
+
for (const row of rows) {
|
|
24801
|
+
const rowBytes = new TextEncoder().encode(JSON.stringify(row)).length;
|
|
24802
|
+
if (usedBytes + rowBytes > maxBytes) {
|
|
24803
|
+
truncated = true;
|
|
24804
|
+
break;
|
|
24805
|
+
}
|
|
24806
|
+
accepted.push(row);
|
|
24807
|
+
usedBytes += rowBytes;
|
|
24808
|
+
}
|
|
24809
|
+
return { accepted, truncated, usedBytes };
|
|
24810
|
+
}
|
|
24811
|
+
function logUsage(supabase, params) {
|
|
24812
|
+
Promise.resolve(supabase.rpc("cerefox_log_usage", {
|
|
24813
|
+
p_operation: params.operation,
|
|
24814
|
+
p_access_path: params.accessPath,
|
|
24815
|
+
p_requestor: params.requestor ?? "mcp-agent",
|
|
24816
|
+
p_document_id: params.document_id ?? null,
|
|
24817
|
+
p_project_id: params.project_id ?? null,
|
|
24818
|
+
p_query_text: params.query_text ?? null,
|
|
24819
|
+
p_result_count: params.result_count ?? null,
|
|
24820
|
+
p_extra: params.extra ?? {}
|
|
24821
|
+
})).catch(() => {});
|
|
24822
|
+
}
|
|
24823
|
+
var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5;
|
|
24824
|
+
|
|
24825
|
+
// ../../_shared/mcp-tools/_projects.ts
|
|
24826
|
+
async function ensureDocumentInProject(supabase, documentId, projectName) {
|
|
24827
|
+
let projectId = null;
|
|
24828
|
+
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", projectName).limit(1);
|
|
24829
|
+
if (proj?.length) {
|
|
24830
|
+
projectId = proj[0].id;
|
|
24831
|
+
} else {
|
|
24832
|
+
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name: projectName }).select("id");
|
|
24833
|
+
projectId = newProj?.[0]?.id ?? null;
|
|
24834
|
+
}
|
|
24835
|
+
if (!projectId)
|
|
24836
|
+
return null;
|
|
24837
|
+
const { data: existing } = await supabase.from("cerefox_document_projects").select("document_id").eq("document_id", documentId).eq("project_id", projectId).limit(1);
|
|
24838
|
+
if (existing?.length)
|
|
24839
|
+
return projectId;
|
|
24840
|
+
const { error: insertErr } = await supabase.from("cerefox_document_projects").insert({ document_id: documentId, project_id: projectId });
|
|
24841
|
+
if (insertErr && !String(insertErr.message ?? "").includes("duplicate key")) {
|
|
24842
|
+
console.warn("ensureDocumentInProject: insert failed", insertErr);
|
|
24843
|
+
}
|
|
24844
|
+
return projectId;
|
|
24845
|
+
}
|
|
24846
|
+
async function setDocumentProjectsByName(supabase, documentId, projectNames) {
|
|
24847
|
+
const projectIds = [];
|
|
24848
|
+
for (const name of projectNames) {
|
|
24849
|
+
if (!name)
|
|
24850
|
+
continue;
|
|
24851
|
+
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", name).limit(1);
|
|
24852
|
+
if (proj?.length) {
|
|
24853
|
+
projectIds.push(proj[0].id);
|
|
24854
|
+
} else {
|
|
24855
|
+
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name }).select("id");
|
|
24856
|
+
if (newProj?.[0]?.id)
|
|
24857
|
+
projectIds.push(newProj[0].id);
|
|
24858
|
+
}
|
|
24859
|
+
}
|
|
24860
|
+
await supabase.from("cerefox_document_projects").delete().eq("document_id", documentId);
|
|
24861
|
+
if (projectIds.length > 0) {
|
|
24862
|
+
const rows = projectIds.map((pid) => ({ document_id: documentId, project_id: pid }));
|
|
24863
|
+
await supabase.from("cerefox_document_projects").insert(rows);
|
|
24864
|
+
}
|
|
24865
|
+
return projectIds;
|
|
24866
|
+
}
|
|
24867
|
+
async function replaceDocumentProjects(supabase, opts) {
|
|
24868
|
+
const { documentId, projectNames, author, authorType, accessPath } = opts;
|
|
24869
|
+
const seenLower = new Set;
|
|
24870
|
+
const cleanNames = [];
|
|
24871
|
+
for (const n of projectNames) {
|
|
24872
|
+
const stripped = (n ?? "").trim();
|
|
24873
|
+
if (!stripped)
|
|
24874
|
+
continue;
|
|
24875
|
+
const key = stripped.toLowerCase();
|
|
24876
|
+
if (seenLower.has(key))
|
|
24877
|
+
continue;
|
|
24878
|
+
seenLower.add(key);
|
|
24879
|
+
cleanNames.push(stripped);
|
|
24880
|
+
}
|
|
24881
|
+
const { data: doc } = await supabase.from("cerefox_documents").select("id, title").eq("id", documentId).is("deleted_at", null).limit(1);
|
|
24882
|
+
if (!doc?.length) {
|
|
24883
|
+
throw new Error(`Document not found (or soft-deleted): ${documentId}`);
|
|
24884
|
+
}
|
|
24885
|
+
const projectIds = [];
|
|
24886
|
+
for (const name of cleanNames) {
|
|
24887
|
+
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", name).limit(1);
|
|
24888
|
+
if (proj?.length) {
|
|
24889
|
+
projectIds.push(proj[0].id);
|
|
24890
|
+
} else {
|
|
24891
|
+
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name }).select("id");
|
|
24892
|
+
if (newProj?.[0]?.id)
|
|
24893
|
+
projectIds.push(newProj[0].id);
|
|
24894
|
+
}
|
|
24895
|
+
}
|
|
24896
|
+
await supabase.from("cerefox_document_projects").delete().eq("document_id", documentId);
|
|
24897
|
+
if (projectIds.length > 0) {
|
|
24898
|
+
const rows = projectIds.map((pid) => ({ document_id: documentId, project_id: pid }));
|
|
24899
|
+
await supabase.from("cerefox_document_projects").insert(rows);
|
|
24900
|
+
}
|
|
24901
|
+
try {
|
|
24902
|
+
await supabase.rpc("cerefox_create_audit_entry", {
|
|
24903
|
+
p_document_id: documentId,
|
|
24904
|
+
p_version_id: null,
|
|
24905
|
+
p_operation: "update-metadata",
|
|
24906
|
+
p_author: author,
|
|
24907
|
+
p_author_type: authorType,
|
|
24908
|
+
p_size_before: null,
|
|
24909
|
+
p_size_after: null,
|
|
24910
|
+
p_description: cleanNames.length > 0 ? `Set document projects to [${cleanNames.join(", ")}]` : "Cleared all project memberships"
|
|
24911
|
+
});
|
|
24912
|
+
} catch (err) {
|
|
24913
|
+
console.warn("replaceDocumentProjects: audit entry failed", err);
|
|
24914
|
+
}
|
|
24915
|
+
logUsage(supabase, {
|
|
24916
|
+
operation: "set-document-projects",
|
|
24917
|
+
accessPath,
|
|
24918
|
+
requestor: author,
|
|
24919
|
+
document_id: documentId,
|
|
24920
|
+
result_count: projectIds.length
|
|
24921
|
+
});
|
|
24922
|
+
return { documentTitle: doc[0].title, cleanNames, projectIds };
|
|
24923
|
+
}
|
|
24924
|
+
async function lookupProjectId(supabase, projectName) {
|
|
24925
|
+
const { data, error } = await supabase.from("cerefox_projects").select("id").ilike("name", projectName).limit(1);
|
|
24926
|
+
if (error || !data?.length)
|
|
24927
|
+
return null;
|
|
24928
|
+
return data[0].id;
|
|
24929
|
+
}
|
|
24930
|
+
var init__projects = () => {};
|
|
24931
|
+
|
|
24761
24932
|
// src/cli/util/bundled-docs.ts
|
|
24762
24933
|
import { existsSync as existsSync8, readdirSync as readdirSync3, readFileSync as readFileSync6, statSync } from "node:fs";
|
|
24763
24934
|
import { dirname as dirname3, join as join7, resolve as resolve2 } from "node:path";
|
|
@@ -39828,10 +39999,10 @@ var require_flate = __commonJS((exports) => {
|
|
|
39828
39999
|
var GenericWorker = require_GenericWorker();
|
|
39829
40000
|
var ARRAY_TYPE = USE_TYPEDARRAY ? "uint8array" : "array";
|
|
39830
40001
|
exports.magic = "\b\x00";
|
|
39831
|
-
function FlateWorker(
|
|
39832
|
-
GenericWorker.call(this, "FlateWorker/" +
|
|
40002
|
+
function FlateWorker(action18, options) {
|
|
40003
|
+
GenericWorker.call(this, "FlateWorker/" + action18);
|
|
39833
40004
|
this._pako = null;
|
|
39834
|
-
this._pakoAction =
|
|
40005
|
+
this._pakoAction = action18;
|
|
39835
40006
|
this._pakoOptions = options;
|
|
39836
40007
|
this.meta = {};
|
|
39837
40008
|
}
|
|
@@ -53732,50 +53903,6 @@ var require_cli_progress = __commonJS((exports, module) => {
|
|
|
53732
53903
|
};
|
|
53733
53904
|
});
|
|
53734
53905
|
|
|
53735
|
-
// ../../_shared/mcp-tools/_utils.ts
|
|
53736
|
-
function getMaxResponseBytes() {
|
|
53737
|
-
const raw = globalThis.process?.env?.CEREFOX_MAX_RESPONSE_BYTES;
|
|
53738
|
-
if (raw === undefined || raw === "")
|
|
53739
|
-
return MAX_RESPONSE_BYTES;
|
|
53740
|
-
const n = Number.parseInt(raw, 10);
|
|
53741
|
-
return Number.isNaN(n) || n <= 0 ? MAX_RESPONSE_BYTES : n;
|
|
53742
|
-
}
|
|
53743
|
-
function getMinSearchScore() {
|
|
53744
|
-
const raw = globalThis.process?.env?.CEREFOX_MIN_SEARCH_SCORE;
|
|
53745
|
-
if (raw === undefined || raw === "")
|
|
53746
|
-
return DEFAULT_MIN_SEARCH_SCORE;
|
|
53747
|
-
const n = Number.parseFloat(raw);
|
|
53748
|
-
return Number.isNaN(n) || n < 0 || n > 1 ? DEFAULT_MIN_SEARCH_SCORE : n;
|
|
53749
|
-
}
|
|
53750
|
-
function applyByteBudget(rows, maxBytes) {
|
|
53751
|
-
const accepted = [];
|
|
53752
|
-
let usedBytes = 0;
|
|
53753
|
-
let truncated = false;
|
|
53754
|
-
for (const row of rows) {
|
|
53755
|
-
const rowBytes = new TextEncoder().encode(JSON.stringify(row)).length;
|
|
53756
|
-
if (usedBytes + rowBytes > maxBytes) {
|
|
53757
|
-
truncated = true;
|
|
53758
|
-
break;
|
|
53759
|
-
}
|
|
53760
|
-
accepted.push(row);
|
|
53761
|
-
usedBytes += rowBytes;
|
|
53762
|
-
}
|
|
53763
|
-
return { accepted, truncated, usedBytes };
|
|
53764
|
-
}
|
|
53765
|
-
function logUsage(supabase, params) {
|
|
53766
|
-
Promise.resolve(supabase.rpc("cerefox_log_usage", {
|
|
53767
|
-
p_operation: params.operation,
|
|
53768
|
-
p_access_path: params.accessPath,
|
|
53769
|
-
p_requestor: params.requestor ?? "mcp-agent",
|
|
53770
|
-
p_document_id: params.document_id ?? null,
|
|
53771
|
-
p_project_id: params.project_id ?? null,
|
|
53772
|
-
p_query_text: params.query_text ?? null,
|
|
53773
|
-
p_result_count: params.result_count ?? null,
|
|
53774
|
-
p_extra: params.extra ?? {}
|
|
53775
|
-
})).catch(() => {});
|
|
53776
|
-
}
|
|
53777
|
-
var MAX_RESPONSE_BYTES = 200000, DEFAULT_MIN_SEARCH_SCORE = 0.5;
|
|
53778
|
-
|
|
53779
53906
|
// ../../_shared/mcp-tools/audit-log.ts
|
|
53780
53907
|
async function handler(supabase, args, ctx) {
|
|
53781
53908
|
const params = {};
|
|
@@ -53880,16 +54007,18 @@ async function handler2(supabase, args, ctx) {
|
|
|
53880
54007
|
result_count: 1
|
|
53881
54008
|
});
|
|
53882
54009
|
const label = version_id !== null ? " (archived version)" : " (current)";
|
|
53883
|
-
|
|
54010
|
+
const hashLine = row.content_hash ? `content_hash: ${row.content_hash}
|
|
53884
54011
|
|
|
53885
|
-
|
|
54012
|
+
` : "";
|
|
54013
|
+
return `# ${row.doc_title ?? "Untitled"}${label}
|
|
54014
|
+
${hashLine}${row.full_content ?? ""}`;
|
|
53886
54015
|
}
|
|
53887
54016
|
var getDocumentTool;
|
|
53888
54017
|
var init_get_document = __esm(() => {
|
|
53889
54018
|
init_types3();
|
|
53890
54019
|
getDocumentTool = {
|
|
53891
54020
|
name: "cerefox_get_document",
|
|
53892
|
-
description: "Retrieve the full reconstructed content of a document. Pass version_id to retrieve an archived version; omit it (or pass null) for the current version. Version UUIDs are returned by cerefox_list_versions.",
|
|
54021
|
+
description: "Retrieve the full reconstructed content of a document. Pass version_id to retrieve an archived version; omit it (or pass null) for the current version. Version UUIDs are returned by cerefox_list_versions. The response header includes the document's current content_hash — pass it back as expected_content_hash when updating via cerefox_ingest (optimistic concurrency).",
|
|
53893
54022
|
inputSchema: {
|
|
53894
54023
|
type: "object",
|
|
53895
54024
|
required: ["document_id"],
|
|
@@ -53910,15 +54039,23 @@ var init_get_document = __esm(() => {
|
|
|
53910
54039
|
});
|
|
53911
54040
|
|
|
53912
54041
|
// ../../_shared/mcp-tools/get-help-content.ts
|
|
53913
|
-
var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (
|
|
54042
|
+
var HELP_FULL = '# Cerefox Knowledge Base -- Agent Quick Reference\n\nCerefox is a persistent, shared knowledge base. You have **10 MCP tools** (9 of them have CLI equivalents — `cerefox_get_help` is MCP-only). For the full guide, search Cerefox for "How AI Agents Use Cerefox" or call `cerefox_get_help` to retrieve this content over MCP.\n\n## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `expected_content_hash` (**required on content updates** — see rule 9), `last_write_wins`, `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID (header includes `content_hash` — the update token) | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find or list docs by metadata, project, or time (no text query) | `metadata_filter`, `project_name` (list a project\'s docs), `updated_since`, `include_content` — **at least one** of metadata_filter/project_name/updated_since/created_since |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc\'s project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |\n\n## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Concurrency: content updates require `expected_content_hash`.** Pass the `content_hash` you read (shown by `cerefox_get_document`, `cerefox_search`, and `cerefox_metadata_search`) when updating a document. If it\'s stale you get a **conflict** — re-read the document, merge your changes into the latest content, retry with the new hash. **Never resolve a conflict by overwriting blindly** — the current content includes another writer\'s work. `last_write_wins: true` skips the check; use it ONLY when an external source of truth makes conflicts meaningless (file re-sync), never to silence a conflict.\n10. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.\n\n## Update Workflow (ID-based -- preferred)\n\n```\nsearch("topic") -> find doc [id: abc123] -> get_document(abc123) -> note its content_hash -> modify ->\ningest(title="Same Title", content="...", document_id="abc123",\n expected_content_hash="<the hash you read>", author="my-agent")\n```\n\nOn a **conflict** error: get_document again (fresh content + fresh hash) -> merge your changes -> retry with the new hash.\n\n## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc (note its hash) -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true,\n expected_content_hash="<the hash you read>", author="my-agent")\n```\n\n## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```\n\n## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --expected-content-hash "<hash>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` (list a project: `cerefox document list --project <name>`) |\n| `cerefox_set_document_projects` | `cerefox document set-projects <id> <name...> --author "<your-name>" --author-type agent` (or `--clear` to remove all) |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.\n', HELP_SECTIONS, HELP_SECTION_HEADINGS;
|
|
53914
54043
|
var init_get_help_content = __esm(() => {
|
|
53915
54044
|
HELP_SECTIONS = {
|
|
53916
|
-
Tools: "## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find docs by metadata (no text query) | `metadata_filter` (
|
|
53917
|
-
"Essential Rules": '## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.',
|
|
53918
|
-
"Update Workflow (ID-based -- preferred)":
|
|
53919
|
-
|
|
54045
|
+
Tools: "## Tools\n\n| Tool | Purpose | Key params |\n|------|---------|------------|\n| `cerefox_search` | Find documents (hybrid FTS + semantic) | `query` (required), `project_name`, `metadata_filter`, `requestor` |\n| `cerefox_ingest` | Save or update a document | `title`, `content` (required), `document_id` (update by ID), `expected_content_hash` (**required on content updates** — see rule 9), `last_write_wins`, `update_if_exists`, `project_name` (single, non-destructive add on update), `project_names` (list, destructive replace on update), `metadata`, `author` |\n| `cerefox_get_document` | Get full document by ID (header includes `content_hash` — the update token) | `document_id` (required) |\n| `cerefox_list_versions` | Version history of a document | `document_id` (required) |\n| `cerefox_metadata_search` | Find or list docs by metadata, project, or time (no text query) | `metadata_filter`, `project_name` (list a project's docs), `updated_since`, `include_content` — **at least one** of metadata_filter/project_name/updated_since/created_since |\n| `cerefox_list_metadata_keys` | Discover available metadata keys | (none required) |\n| `cerefox_list_projects` | List all projects | (none required) |\n| `cerefox_set_document_projects` | Set doc's project memberships to exactly the given list (destructive replace; metadata-only, no content change) | `document_id`, `project_names` (required) |\n| `cerefox_get_audit_log` | Query write operation history | `document_id`, `author`, `operation`, `since` |\n| `cerefox_get_help` | Retrieve Cerefox conventions (this reference) over MCP. **Call this whenever uncertain.** | `topic` (optional, case-insensitive H2 substring match) |",
|
|
54046
|
+
"Essential Rules": '## Essential Rules\n\n1. **Search before ingesting** -- check if the document exists first.\n2. **Prefer ID-based updates** -- pass `document_id` from search results for deterministic updates. Falls back to title-matching with `update_if_exists: true`.\n3. **Set `author`/`requestor`** to your name on every call (e.g., "Claude Code", "archiver"). On MCP, pass as parameters. On CLI, pass `--author`/`--author-type`/`--requestor` flags, or rely on `CEREFOX_AUTHOR_NAME`/`CEREFOX_AUTHOR_TYPE`/`CEREFOX_REQUESTOR_NAME` env vars set in the user\'s `.env`.\n4. **Use `document_id` from search results** `[id: uuid]` for get_document and list_versions.\n5. **Add metadata** -- at minimum `type` ("decision-log", "research", "design-doc") and `status` ("active", "draft").\n6. **Write structured Markdown** with H1/H2/H3 headings for good chunking and search.\n7. **Deletes are soft (recoverable); purge is web-UI-only.** If you decide to delete, surface it to the user (`I soft-deleted X — recoverable from the Cerefox web UI trash`). You cannot un-do your own delete from agent code by design.\n8. **Cross-doc links inside content**: **always use `[Text](document-uuid)`.** UUIDs are the only fully reliable link form — stable across title changes, never ambiguous, no encoding gotchas. Every `cerefox_search` result shows `[id: <uuid>]` after the title; grab it and use it. Title-based linking (`[Text](<Title With Spaces>)`) is fragile (breaks on colons, parens, ampersands, brackets — silently navigates to wrong page) — **don\'t write title-based links**; do an extra search to get the UUID instead. Repo-path forms (`[Text](docs/path.md)`) exist for repo-ingested files; don\'t construct manually. See `AGENT_GUIDE.md → Writing linkable content` for the full rule.\n9. **Concurrency: content updates require `expected_content_hash`.** Pass the `content_hash` you read (shown by `cerefox_get_document`, `cerefox_search`, and `cerefox_metadata_search`) when updating a document. If it\'s stale you get a **conflict** — re-read the document, merge your changes into the latest content, retry with the new hash. **Never resolve a conflict by overwriting blindly** — the current content includes another writer\'s work. `last_write_wins: true` skips the check; use it ONLY when an external source of truth makes conflicts meaningless (file re-sync), never to silence a conflict.\n10. **Project memberships — non-destructive by default**: on `cerefox_ingest` updates, **`project_name` (singular) is a non-destructive add** (ensures membership, preserves others). Use **`project_names` (list)** when you want to set the doc\'s full project set in one call (destructive replace). For metadata-only project changes without writing content, use **`cerefox_set_document_projects(document_id, project_names)`** — that tool is the destructive-replace contract made explicit. Never call `cerefox_set_document_projects` with a single name when you mean "add" — that would REMOVE the doc from all other projects. When in doubt, use `cerefox_ingest` with singular `project_name`.',
|
|
54047
|
+
"Update Workflow (ID-based -- preferred)": `## Update Workflow (ID-based -- preferred)
|
|
54048
|
+
|
|
54049
|
+
\`\`\`
|
|
54050
|
+
search("topic") -> find doc [id: abc123] -> get_document(abc123) -> note its content_hash -> modify ->
|
|
54051
|
+
ingest(title="Same Title", content="...", document_id="abc123",
|
|
54052
|
+
expected_content_hash="<the hash you read>", author="my-agent")
|
|
54053
|
+
\`\`\`
|
|
54054
|
+
|
|
54055
|
+
On a **conflict** error: get_document again (fresh content + fresh hash) -> merge your changes -> retry with the new hash.`,
|
|
54056
|
+
"Update Workflow (title-based -- fallback)": '## Update Workflow (title-based -- fallback)\n\n```\nsearch("topic") -> find doc (note its hash) -> modify ->\ningest(title="Same Title", content="...", update_if_exists=true,\n expected_content_hash="<the hash you read>", author="my-agent")\n```',
|
|
53920
54057
|
"Catch-Up Workflow": '## Catch-Up Workflow\n\n```\nmetadata_search(metadata_filter={"type": "decision-log"}, updated_since="2026-03-28T00:00:00Z")\n```',
|
|
53921
|
-
"CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` |\n| `cerefox_set_document_projects` |
|
|
54058
|
+
"CLI fallback (when MCP is unavailable)": '## CLI fallback (when MCP is unavailable)\n\nIf `cerefox_search` is not in your tool list, your user has likely installed the Cerefox CLI. The canonical invocation is plain **`cerefox <subcommand>`** (the TypeScript CLI, installed via `npm install -g @cerefox/memory`). It uses a resource-verb shape (`cerefox document get`, `cerefox project list`, …). The legacy Python `uv run cerefox` is now a frozen husk as of v0.9 — only `uv run cerefox mcp` still works.\n\nSame operations, same conventions. Full reference: [`docs/guides/cli.md`](docs/guides/cli.md). CLI flag names match MCP parameter names exactly (e.g. `metadata_filter` ↔ `--metadata-filter`); common flags also have single-letter short forms (`-f`, `-p`, `-c`, `-m`, `-u`, `-a`, `-r`). Use the canonical long name (what `--help` shows) or its short form — there are no long-form aliases like `--filter` or `--count`.\n\n| MCP tool | CLI |\n|---|---|\n| `cerefox_search` | `cerefox search "<q>" --requestor "<your-name>"` |\n| `cerefox_ingest` (paste) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --author "<your-name>" --author-type agent` |\n| `cerefox_ingest` (update by ID) | `printf \'...\' \\| cerefox document ingest --paste --title "<t>" --document-id "<uuid>" --expected-content-hash "<hash>" --author "<your-name>" --author-type agent` |\n| `cerefox_get_document` | `cerefox document get <id> --version-id <vid> --requestor "<your-name>"` |\n| `cerefox_list_versions` | `cerefox document version list <id> --requestor "<your-name>"` |\n| `cerefox_list_projects` | `cerefox project list --requestor "<your-name>"` |\n| `cerefox_list_metadata_keys` | `cerefox metadata keys` |\n| `cerefox_metadata_search` | `cerefox metadata search --metadata-filter \'<json>\' --requestor "<your-name>"` (list a project: `cerefox document list --project <name>`) |\n| `cerefox_set_document_projects` | `cerefox document set-projects <id> <name...> --author "<your-name>" --author-type agent` (or `--clear` to remove all) |\n| `cerefox_get_audit_log` | `cerefox audit list --requestor "<your-name>"` (add `--json` for scripted access) |\n| `cerefox_get_help` | `cerefox guides show agent-quick-reference` (or `cerefox guides list` for the full bundled-docs index) |\n\n**Set identity on every call**, exactly as you would on MCP:\n- Writes (`document ingest`, `document ingest-dir`): `--author "<your-name>" --author-type agent`\n- Reads: `--requestor "<your-name>"`\n\nOr have your user set `CEREFOX_AUTHOR_NAME` / `CEREFOX_AUTHOR_TYPE` / `CEREFOX_REQUESTOR_NAME` in their `.env` to apply defaults once.'
|
|
53922
54059
|
};
|
|
53923
54060
|
HELP_SECTION_HEADINGS = ["Tools", "Essential Rules", "Update Workflow (ID-based -- preferred)", "Update Workflow (title-based -- fallback)", "Catch-Up Workflow", "CLI fallback (when MCP is unavailable)"];
|
|
53924
54061
|
});
|
|
@@ -54137,56 +54274,22 @@ async function sha256hex(text) {
|
|
|
54137
54274
|
}
|
|
54138
54275
|
var MAX_CHUNK_CHARS = 4000;
|
|
54139
54276
|
|
|
54140
|
-
// ../../_shared/mcp-tools/
|
|
54141
|
-
|
|
54142
|
-
|
|
54143
|
-
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", projectName).limit(1);
|
|
54144
|
-
if (proj?.length) {
|
|
54145
|
-
projectId = proj[0].id;
|
|
54146
|
-
} else {
|
|
54147
|
-
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name: projectName }).select("id");
|
|
54148
|
-
projectId = newProj?.[0]?.id ?? null;
|
|
54149
|
-
}
|
|
54150
|
-
if (!projectId)
|
|
54151
|
-
return null;
|
|
54152
|
-
const { data: existing } = await supabase.from("cerefox_document_projects").select("document_id").eq("document_id", documentId).eq("project_id", projectId).limit(1);
|
|
54153
|
-
if (existing?.length)
|
|
54154
|
-
return projectId;
|
|
54155
|
-
const { error: insertErr } = await supabase.from("cerefox_document_projects").insert({ document_id: documentId, project_id: projectId });
|
|
54156
|
-
if (insertErr && !String(insertErr.message ?? "").includes("duplicate key")) {
|
|
54157
|
-
console.warn("ensureDocumentInProject: insert failed", insertErr);
|
|
54158
|
-
}
|
|
54159
|
-
return projectId;
|
|
54277
|
+
// ../../_shared/mcp-tools/ingest.ts
|
|
54278
|
+
function conflictError(documentId, expectedHash, currentHash) {
|
|
54279
|
+
return new Error(`Conflict: document ${documentId} changed since you read it ` + `(your base hash: ${expectedHash}, current hash: ${currentHash}). ` + `To resolve: (1) cerefox_get_document("${documentId}") to fetch the latest content ` + `and its content_hash, (2) merge your changes into it, (3) retry cerefox_ingest ` + `with expected_content_hash set to the new hash. Do not overwrite blindly — ` + `the current content may include another writer's work.`);
|
|
54160
54280
|
}
|
|
54161
|
-
|
|
54162
|
-
|
|
54163
|
-
|
|
54164
|
-
|
|
54165
|
-
|
|
54166
|
-
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", name).limit(1);
|
|
54167
|
-
if (proj?.length) {
|
|
54168
|
-
projectIds.push(proj[0].id);
|
|
54169
|
-
} else {
|
|
54170
|
-
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name }).select("id");
|
|
54171
|
-
if (newProj?.[0]?.id)
|
|
54172
|
-
projectIds.push(newProj[0].id);
|
|
54173
|
-
}
|
|
54281
|
+
function mapIngestRpcError(message, documentId) {
|
|
54282
|
+
if (message.includes("CEREFOX_CONFLICT")) {
|
|
54283
|
+
const current = message.match(/current hash ([0-9a-f]{64})/)?.[1] ?? "unknown";
|
|
54284
|
+
const expected = message.match(/expected hash ([0-9a-f]{64})/)?.[1] ?? "unknown";
|
|
54285
|
+
return conflictError(documentId, expected, current);
|
|
54174
54286
|
}
|
|
54175
|
-
|
|
54176
|
-
|
|
54177
|
-
|
|
54178
|
-
await supabase.from("cerefox_document_projects").insert(rows);
|
|
54287
|
+
if (message.includes("CEREFOX_TOKEN_REQUIRED")) {
|
|
54288
|
+
const current = message.match(/Current hash: ([0-9a-f]{64})/)?.[1];
|
|
54289
|
+
return new Error(`Concurrency token required: content updates need expected_content_hash — ` + `the content_hash of the version you based your edit on (returned by ` + `cerefox_get_document, cerefox_search, and cerefox_metadata_search).` + (current ? ` The document's current hash is ${current}; pass it ONLY if your edit was based on the current content.` : "") + ` If you have not read the document, read it first. To deliberately overwrite ` + `regardless of concurrent changes, pass last_write_wins=true.`);
|
|
54179
54290
|
}
|
|
54180
|
-
return
|
|
54181
|
-
}
|
|
54182
|
-
async function lookupProjectId(supabase, projectName) {
|
|
54183
|
-
const { data, error: error2 } = await supabase.from("cerefox_projects").select("id").ilike("name", projectName).limit(1);
|
|
54184
|
-
if (error2 || !data?.length)
|
|
54185
|
-
return null;
|
|
54186
|
-
return data[0].id;
|
|
54291
|
+
return new Error(`Ingest RPC failed: ${message}`);
|
|
54187
54292
|
}
|
|
54188
|
-
|
|
54189
|
-
// ../../_shared/mcp-tools/ingest.ts
|
|
54190
54293
|
async function handler4(supabase, args, ctx) {
|
|
54191
54294
|
const title = args.title?.trim();
|
|
54192
54295
|
const content = args.content;
|
|
@@ -54198,6 +54301,8 @@ async function handler4(supabase, args, ctx) {
|
|
|
54198
54301
|
const update_if_exists = args.update_if_exists ?? false;
|
|
54199
54302
|
const author = args.author ?? "mcp-agent";
|
|
54200
54303
|
const author_type = "agent";
|
|
54304
|
+
const expected_content_hash = args.expected_content_hash?.trim() || null;
|
|
54305
|
+
const last_write_wins = args.last_write_wins ?? false;
|
|
54201
54306
|
if (!title || !content?.trim()) {
|
|
54202
54307
|
throw new McpInvalidParams("title and content are required");
|
|
54203
54308
|
}
|
|
@@ -54218,7 +54323,10 @@ async function handler4(supabase, args, ctx) {
|
|
|
54218
54323
|
const existingDoc = existing[0];
|
|
54219
54324
|
if (existingDoc.content_hash === contentHash2) {
|
|
54220
54325
|
const note2 = update_if_exists ? "" : " Note: update_if_exists flag was overridden by document_id.";
|
|
54221
|
-
return `Document already up-to-date: "${existingDoc.title}" (id: ${existingDoc.id}). Content hash unchanged.${note2}`;
|
|
54326
|
+
return `Document already up-to-date: "${existingDoc.title}" (id: ${existingDoc.id}). Content hash unchanged (${contentHash2}).${note2}`;
|
|
54327
|
+
}
|
|
54328
|
+
if (!last_write_wins && expected_content_hash && expected_content_hash !== existingDoc.content_hash) {
|
|
54329
|
+
throw conflictError(existingDoc.id, expected_content_hash, existingDoc.content_hash);
|
|
54222
54330
|
}
|
|
54223
54331
|
const chunks2 = chunkMarkdown2(content);
|
|
54224
54332
|
if (chunks2.length === 0)
|
|
@@ -54247,10 +54355,12 @@ ${c2.content}`);
|
|
|
54247
54355
|
p_chunks: chunkData2,
|
|
54248
54356
|
p_author: author,
|
|
54249
54357
|
p_author_type: author_type,
|
|
54250
|
-
p_source_label: source
|
|
54358
|
+
p_source_label: source,
|
|
54359
|
+
p_expected_content_hash: expected_content_hash,
|
|
54360
|
+
p_last_write_wins: last_write_wins
|
|
54251
54361
|
});
|
|
54252
54362
|
if (ingestErr2)
|
|
54253
|
-
throw
|
|
54363
|
+
throw mapIngestRpcError(ingestErr2.message, existingDoc.id);
|
|
54254
54364
|
logUsage(supabase, {
|
|
54255
54365
|
operation: "ingest",
|
|
54256
54366
|
accessPath: ctx.accessPath,
|
|
@@ -54264,14 +54374,17 @@ ${c2.content}`);
|
|
|
54264
54374
|
await ensureDocumentInProject(supabase, existingDoc.id, project_name);
|
|
54265
54375
|
}
|
|
54266
54376
|
const note = update_if_exists ? "" : " Note: update_if_exists flag was overridden by document_id.";
|
|
54267
|
-
return `Document updated: "${title}" (id: ${existingDoc.id}), ${chunks2.length} chunk(s), ${totalChars2} chars.${note}`;
|
|
54377
|
+
return `Document updated: "${title}" (id: ${existingDoc.id}), ${chunks2.length} chunk(s), ${totalChars2} chars. New content_hash: ${contentHash2}.${note}`;
|
|
54268
54378
|
}
|
|
54269
54379
|
if (update_if_exists) {
|
|
54270
54380
|
const { data: existing } = await supabase.from("cerefox_documents").select("id, title, content_hash").eq("title", title).order("updated_at", { ascending: false }).limit(1);
|
|
54271
54381
|
if (existing?.length) {
|
|
54272
54382
|
const existingDoc = existing[0];
|
|
54273
54383
|
if (existingDoc.content_hash === contentHash2) {
|
|
54274
|
-
return `Document already up-to-date: "${existingDoc.title}" (id: ${existingDoc.id}). Content hash unchanged.`;
|
|
54384
|
+
return `Document already up-to-date: "${existingDoc.title}" (id: ${existingDoc.id}). Content hash unchanged (${contentHash2}).`;
|
|
54385
|
+
}
|
|
54386
|
+
if (!last_write_wins && expected_content_hash && expected_content_hash !== existingDoc.content_hash) {
|
|
54387
|
+
throw conflictError(existingDoc.id, expected_content_hash, existingDoc.content_hash);
|
|
54275
54388
|
}
|
|
54276
54389
|
const chunks2 = chunkMarkdown2(content);
|
|
54277
54390
|
if (chunks2.length === 0)
|
|
@@ -54300,10 +54413,12 @@ ${c2.content}`);
|
|
|
54300
54413
|
p_chunks: chunkData2,
|
|
54301
54414
|
p_author: author,
|
|
54302
54415
|
p_author_type: author_type,
|
|
54303
|
-
p_source_label: source
|
|
54416
|
+
p_source_label: source,
|
|
54417
|
+
p_expected_content_hash: expected_content_hash,
|
|
54418
|
+
p_last_write_wins: last_write_wins
|
|
54304
54419
|
});
|
|
54305
54420
|
if (ingestErr2)
|
|
54306
|
-
throw
|
|
54421
|
+
throw mapIngestRpcError(ingestErr2.message, existingDoc.id);
|
|
54307
54422
|
logUsage(supabase, {
|
|
54308
54423
|
operation: "ingest",
|
|
54309
54424
|
accessPath: ctx.accessPath,
|
|
@@ -54316,7 +54431,7 @@ ${c2.content}`);
|
|
|
54316
54431
|
} else if (project_name) {
|
|
54317
54432
|
await ensureDocumentInProject(supabase, existingDoc.id, project_name);
|
|
54318
54433
|
}
|
|
54319
|
-
return `Document updated: "${existingDoc.title}" (id: ${existingDoc.id}), ${chunks2.length} chunk(s), ${totalChars2} chars.`;
|
|
54434
|
+
return `Document updated: "${existingDoc.title}" (id: ${existingDoc.id}), ${chunks2.length} chunk(s), ${totalChars2} chars. New content_hash: ${contentHash2}.`;
|
|
54320
54435
|
}
|
|
54321
54436
|
}
|
|
54322
54437
|
const { data: hashMatch } = await supabase.from("cerefox_documents").select("id, title").eq("content_hash", contentHash2).limit(1);
|
|
@@ -54372,6 +54487,7 @@ ${c2.content}`);
|
|
|
54372
54487
|
}
|
|
54373
54488
|
var ingestTool;
|
|
54374
54489
|
var init_ingest = __esm(() => {
|
|
54490
|
+
init__projects();
|
|
54375
54491
|
init_types3();
|
|
54376
54492
|
ingestTool = {
|
|
54377
54493
|
name: "cerefox_ingest",
|
|
@@ -54400,6 +54516,14 @@ var init_ingest = __esm(() => {
|
|
|
54400
54516
|
type: "boolean",
|
|
54401
54517
|
description: "When true, update an existing document with the same title instead of creating a new one (default: false). Ignored when document_id is provided."
|
|
54402
54518
|
},
|
|
54519
|
+
expected_content_hash: {
|
|
54520
|
+
type: "string",
|
|
54521
|
+
description: "REQUIRED on content updates (optimistic concurrency): the content_hash of the document version you based your edit on, as returned by cerefox_get_document / cerefox_search / cerefox_metadata_search. If the document changed since you read it, the update fails with a conflict — re-read, merge, retry with the new hash. Not needed when creating a new document."
|
|
54522
|
+
},
|
|
54523
|
+
last_write_wins: {
|
|
54524
|
+
type: "boolean",
|
|
54525
|
+
description: "Explicitly skip the concurrency check and overwrite regardless of concurrent changes (default: false). Use ONLY when an external source of truth makes conflicts meaningless (e.g. re-syncing from files). Recorded in the audit log."
|
|
54526
|
+
},
|
|
54403
54527
|
metadata: { type: "object", description: "Arbitrary JSON metadata (optional)" },
|
|
54404
54528
|
author: {
|
|
54405
54529
|
type: "string",
|
|
@@ -54545,11 +54669,12 @@ async function handler8(supabase, args, ctx) {
|
|
|
54545
54669
|
const limit = args.limit ?? 10;
|
|
54546
54670
|
const include_content = args.include_content ?? false;
|
|
54547
54671
|
const requested_max_bytes = args.max_bytes;
|
|
54548
|
-
if (
|
|
54549
|
-
throw new McpInvalidParams("metadata_filter
|
|
54672
|
+
if (metadata_filter !== undefined && (typeof metadata_filter !== "object" || Array.isArray(metadata_filter))) {
|
|
54673
|
+
throw new McpInvalidParams("metadata_filter must be a JSON object when provided");
|
|
54550
54674
|
}
|
|
54551
|
-
|
|
54552
|
-
|
|
54675
|
+
const has_metadata = !!metadata_filter && Object.keys(metadata_filter).length > 0;
|
|
54676
|
+
if (!has_metadata && !project_name && !updated_since && !created_since) {
|
|
54677
|
+
throw new McpInvalidParams("Provide at least one of: metadata_filter, project_name, updated_since, or created_since.");
|
|
54553
54678
|
}
|
|
54554
54679
|
let projectId = null;
|
|
54555
54680
|
if (project_name) {
|
|
@@ -54560,7 +54685,7 @@ async function handler8(supabase, args, ctx) {
|
|
|
54560
54685
|
const ceiling = getMaxResponseBytes();
|
|
54561
54686
|
const max_bytes = include_content ? Math.min(requested_max_bytes ?? ceiling, ceiling) : null;
|
|
54562
54687
|
const params = {
|
|
54563
|
-
p_metadata_filter: metadata_filter,
|
|
54688
|
+
p_metadata_filter: metadata_filter ?? {},
|
|
54564
54689
|
p_project_id: projectId,
|
|
54565
54690
|
p_updated_since: updated_since ?? null,
|
|
54566
54691
|
p_created_since: created_since ?? null,
|
|
@@ -54577,17 +54702,19 @@ async function handler8(supabase, args, ctx) {
|
|
|
54577
54702
|
operation: "metadata_search",
|
|
54578
54703
|
accessPath: ctx.accessPath,
|
|
54579
54704
|
requestor: args.requestor,
|
|
54580
|
-
query_text: JSON.stringify(metadata_filter),
|
|
54705
|
+
query_text: JSON.stringify(metadata_filter ?? {}),
|
|
54581
54706
|
project_id: projectId,
|
|
54582
54707
|
result_count: rows.length
|
|
54583
54708
|
});
|
|
54584
54709
|
if (rows.length === 0)
|
|
54585
|
-
return "No documents match the
|
|
54710
|
+
return "No documents match the given criteria.";
|
|
54586
54711
|
const parts = rows.map((row) => {
|
|
54587
54712
|
const projects = row.project_names?.length ? ` | projects: ${row.project_names.join(", ")}` : "";
|
|
54588
54713
|
const meta = Object.entries(row.doc_metadata ?? {}).map(([k, v]) => `${k}=${v}`).join(", ");
|
|
54714
|
+
const hash = row.content_hash ? `
|
|
54715
|
+
hash: ${row.content_hash}` : "";
|
|
54589
54716
|
const header = `## ${row.title} [id: ${row.document_id}]
|
|
54590
|
-
` + `${meta}${projects} | ${row.total_chars} chars | ${row.review_status} | updated ${row.updated_at?.slice(0, 10) ?? "?"}`;
|
|
54717
|
+
` + `${meta}${projects} | ${row.total_chars} chars | ${row.review_status} | updated ${row.updated_at?.slice(0, 10) ?? "?"}${hash}`;
|
|
54591
54718
|
if (include_content && row.content) {
|
|
54592
54719
|
return `${header}
|
|
54593
54720
|
|
|
@@ -54603,20 +54730,20 @@ ${row.content}`;
|
|
|
54603
54730
|
}
|
|
54604
54731
|
var metadataSearchTool;
|
|
54605
54732
|
var init_metadata_search = __esm(() => {
|
|
54733
|
+
init__projects();
|
|
54606
54734
|
init_types3();
|
|
54607
54735
|
metadataSearchTool = {
|
|
54608
54736
|
name: "cerefox_metadata_search",
|
|
54609
|
-
description: "Find documents by metadata key-value criteria without a text search term. Use to discover documents tagged with specific attributes, browse by taxonomy,
|
|
54737
|
+
description: "Find or list documents by metadata key-value criteria without a text search term. Use to discover documents tagged with specific attributes, browse by taxonomy, retrieve messages/tasks by type and status, or list all documents in a project (pass project_name alone). At least one of metadata_filter, project_name, updated_since, or created_since must be supplied; results are ordered newest-updated first.",
|
|
54610
54738
|
inputSchema: {
|
|
54611
54739
|
type: "object",
|
|
54612
|
-
required: ["metadata_filter"],
|
|
54613
54740
|
properties: {
|
|
54614
54741
|
metadata_filter: {
|
|
54615
54742
|
type: "object",
|
|
54616
|
-
description: 'Key-value pairs; ALL must match (AND semantics). Example: {"type": "decision", "status": "active"}. Call cerefox_list_metadata_keys first to discover available keys.',
|
|
54743
|
+
description: 'Key-value pairs; ALL must match (AND semantics). Example: {"type": "decision", "status": "active"}. Call cerefox_list_metadata_keys first to discover available keys. Optional — omit (or pass {}) to list by project_name / time range alone.',
|
|
54617
54744
|
additionalProperties: { type: "string" }
|
|
54618
54745
|
},
|
|
54619
|
-
project_name: { type: "string", description: "Restrict to a project by name (optional)" },
|
|
54746
|
+
project_name: { type: "string", description: "Restrict to a project by name. Sufficient on its own to list that project's documents (optional)." },
|
|
54620
54747
|
updated_since: {
|
|
54621
54748
|
type: "string",
|
|
54622
54749
|
description: "ISO-8601 timestamp; only docs updated on/after (optional)"
|
|
@@ -54729,7 +54856,9 @@ async function handler9(supabase, args, ctx) {
|
|
|
54729
54856
|
const docId = row.document_id ? ` [id: ${row.document_id}]` : "";
|
|
54730
54857
|
const score = row.best_score != null ? ` (score: ${row.best_score.toFixed(3)})` : "";
|
|
54731
54858
|
const partial = row.is_partial ? ` -- partial (${row.chunk_count} of ${(row.total_chars ?? 0).toLocaleString()} chars)` : "";
|
|
54732
|
-
|
|
54859
|
+
const hash = row.content_hash ? `
|
|
54860
|
+
hash: ${row.content_hash}` : "";
|
|
54861
|
+
return `## ${title}${docId}${score}${partial}${hash}
|
|
54733
54862
|
|
|
54734
54863
|
${row.full_content ?? ""}`;
|
|
54735
54864
|
});
|
|
@@ -54747,6 +54876,7 @@ ${row.full_content ?? ""}`;
|
|
|
54747
54876
|
}
|
|
54748
54877
|
var searchTool;
|
|
54749
54878
|
var init_search = __esm(() => {
|
|
54879
|
+
init__projects();
|
|
54750
54880
|
init_types3();
|
|
54751
54881
|
searchTool = {
|
|
54752
54882
|
name: "cerefox_search",
|
|
@@ -54797,58 +54927,12 @@ async function handler10(supabase, args, ctx) {
|
|
|
54797
54927
|
if (!project_names_raw.every((n) => typeof n === "string")) {
|
|
54798
54928
|
throw new McpInvalidParams("project_names must contain only strings.");
|
|
54799
54929
|
}
|
|
54800
|
-
const
|
|
54801
|
-
|
|
54802
|
-
|
|
54803
|
-
|
|
54804
|
-
|
|
54805
|
-
|
|
54806
|
-
const key = stripped.toLowerCase();
|
|
54807
|
-
if (seenLower.has(key))
|
|
54808
|
-
continue;
|
|
54809
|
-
seenLower.add(key);
|
|
54810
|
-
cleanNames.push(stripped);
|
|
54811
|
-
}
|
|
54812
|
-
const { data: doc } = await supabase.from("cerefox_documents").select("id, title").eq("id", document_id).is("deleted_at", null).limit(1);
|
|
54813
|
-
if (!doc?.length) {
|
|
54814
|
-
throw new Error(`Document not found (or soft-deleted): ${document_id}`);
|
|
54815
|
-
}
|
|
54816
|
-
const projectIds = [];
|
|
54817
|
-
for (const name of cleanNames) {
|
|
54818
|
-
const { data: proj } = await supabase.from("cerefox_projects").select("id").ilike("name", name).limit(1);
|
|
54819
|
-
if (proj?.length) {
|
|
54820
|
-
projectIds.push(proj[0].id);
|
|
54821
|
-
} else {
|
|
54822
|
-
const { data: newProj } = await supabase.from("cerefox_projects").insert({ name }).select("id");
|
|
54823
|
-
if (newProj?.[0]?.id)
|
|
54824
|
-
projectIds.push(newProj[0].id);
|
|
54825
|
-
}
|
|
54826
|
-
}
|
|
54827
|
-
await supabase.from("cerefox_document_projects").delete().eq("document_id", document_id);
|
|
54828
|
-
if (projectIds.length > 0) {
|
|
54829
|
-
const rows = projectIds.map((pid) => ({ document_id, project_id: pid }));
|
|
54830
|
-
await supabase.from("cerefox_document_projects").insert(rows);
|
|
54831
|
-
}
|
|
54832
|
-
try {
|
|
54833
|
-
await supabase.rpc("cerefox_create_audit_entry", {
|
|
54834
|
-
p_document_id: document_id,
|
|
54835
|
-
p_version_id: null,
|
|
54836
|
-
p_operation: "update-metadata",
|
|
54837
|
-
p_author: author,
|
|
54838
|
-
p_author_type: "agent",
|
|
54839
|
-
p_size_before: null,
|
|
54840
|
-
p_size_after: null,
|
|
54841
|
-
p_description: cleanNames.length > 0 ? `Set document projects to [${cleanNames.join(", ")}]` : "Cleared all project memberships"
|
|
54842
|
-
});
|
|
54843
|
-
} catch (err) {
|
|
54844
|
-
console.warn("set-document-projects: audit entry failed", err);
|
|
54845
|
-
}
|
|
54846
|
-
logUsage(supabase, {
|
|
54847
|
-
operation: "set-document-projects",
|
|
54848
|
-
accessPath: ctx.accessPath,
|
|
54849
|
-
requestor: author,
|
|
54850
|
-
document_id,
|
|
54851
|
-
result_count: projectIds.length
|
|
54930
|
+
const { cleanNames, projectIds } = await replaceDocumentProjects(supabase, {
|
|
54931
|
+
documentId: document_id,
|
|
54932
|
+
projectNames: project_names_raw,
|
|
54933
|
+
author,
|
|
54934
|
+
authorType: "agent",
|
|
54935
|
+
accessPath: ctx.accessPath
|
|
54852
54936
|
});
|
|
54853
54937
|
if (cleanNames.length === 0) {
|
|
54854
54938
|
return `Cleared all project memberships for document ${document_id}. ` + "The document no longer belongs to any project.";
|
|
@@ -54860,6 +54944,7 @@ async function handler10(supabase, args, ctx) {
|
|
|
54860
54944
|
}
|
|
54861
54945
|
var setDocumentProjectsTool;
|
|
54862
54946
|
var init_set_document_projects = __esm(() => {
|
|
54947
|
+
init__projects();
|
|
54863
54948
|
init_types3();
|
|
54864
54949
|
setDocumentProjectsTool = {
|
|
54865
54950
|
name: "cerefox_set_document_projects",
|
|
@@ -54965,6 +55050,7 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
54965
55050
|
topic: doc.topic
|
|
54966
55051
|
},
|
|
54967
55052
|
update_if_exists: true,
|
|
55053
|
+
last_write_wins: true,
|
|
54968
55054
|
project_name: project,
|
|
54969
55055
|
author,
|
|
54970
55056
|
author_type: authorType
|
|
@@ -54983,11 +55069,11 @@ async function runSyncSelfDocs(options = {}) {
|
|
|
54983
55069
|
printTable(outcomes.filter((o) => o.status === "error").map((o) => ({ topic: o.topic, error: o.detail.slice(0, 100) })));
|
|
54984
55070
|
}
|
|
54985
55071
|
}
|
|
54986
|
-
async function
|
|
55072
|
+
async function action20(options) {
|
|
54987
55073
|
await runSyncSelfDocs(options);
|
|
54988
55074
|
}
|
|
54989
55075
|
function registerSyncSelfDocs(program2) {
|
|
54990
|
-
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(
|
|
55076
|
+
program2.command("sync-self-docs").description("Ingest bundled Cerefox docs under the _cerefox-self-docs project.").option("--dry-run", "List what would be ingested without writing.").option("--project <name>", "Override the target project name.", "_cerefox-self-docs").action(action20);
|
|
54991
55077
|
}
|
|
54992
55078
|
var init_sync_self_docs = __esm(() => {
|
|
54993
55079
|
init_cli_core();
|
|
@@ -70458,6 +70544,43 @@ function registerDocumentRestore(parent) {
|
|
|
70458
70544
|
parent.command("restore").description("Restore a soft-deleted document from the trash (inverse of `document delete`).").argument("<document-id>", "UUID of the soft-deleted document.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action11);
|
|
70459
70545
|
}
|
|
70460
70546
|
|
|
70547
|
+
// src/cli/commands/document-set-projects.ts
|
|
70548
|
+
init_cli_core();
|
|
70549
|
+
init__projects();
|
|
70550
|
+
init_client();
|
|
70551
|
+
async function action12(documentId, projectNames, options) {
|
|
70552
|
+
const names = projectNames ?? [];
|
|
70553
|
+
if (options.clear && names.length > 0) {
|
|
70554
|
+
throw userError("Pass either project names or --clear, not both.", "Use --clear on its own to remove the document from all projects.");
|
|
70555
|
+
}
|
|
70556
|
+
if (!options.clear && names.length === 0) {
|
|
70557
|
+
throw userError("No project names given.", "Pass one or more project names, or --clear to remove all memberships.");
|
|
70558
|
+
}
|
|
70559
|
+
const author = resolveAuthor(options.author);
|
|
70560
|
+
const authorType = resolveAuthorType(options.authorType);
|
|
70561
|
+
if (author === "unknown") {
|
|
70562
|
+
warn("No --author / CEREFOX_AUTHOR_NAME set — audit log will record this as 'unknown'.");
|
|
70563
|
+
}
|
|
70564
|
+
const client = getClient();
|
|
70565
|
+
const { documentTitle, cleanNames } = await replaceDocumentProjects(client.raw, {
|
|
70566
|
+
documentId,
|
|
70567
|
+
projectNames: names,
|
|
70568
|
+
author,
|
|
70569
|
+
authorType,
|
|
70570
|
+
accessPath: "cli"
|
|
70571
|
+
});
|
|
70572
|
+
if (cleanNames.length === 0) {
|
|
70573
|
+
println(c.green(`✓ Cleared all project memberships for "${documentTitle}" (id: ${documentId}).`));
|
|
70574
|
+
return;
|
|
70575
|
+
}
|
|
70576
|
+
println(c.green(`✓ Set ${cleanNames.length} project membership(s) for "${documentTitle}" (id: ${documentId}).`));
|
|
70577
|
+
println(c.dim(` Projects: ${cleanNames.join(", ")}`));
|
|
70578
|
+
println(c.dim(" This REPLACED the previous set — any project not listed is no longer associated."));
|
|
70579
|
+
}
|
|
70580
|
+
function registerDocumentSetProjects(parent) {
|
|
70581
|
+
parent.command("set-projects").description("Replace a document's project memberships with exactly the given set (or --clear to remove all).").argument("<document-id>", "UUID of the document.").argument("[project-names...]", "Project names to set (created if missing). Omit and pass --clear to remove all.").option("--clear", "Remove the document from all projects.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action12);
|
|
70582
|
+
}
|
|
70583
|
+
|
|
70461
70584
|
// src/cli/commands/guides.ts
|
|
70462
70585
|
init_cli_core();
|
|
70463
70586
|
init_bundled_docs();
|
|
@@ -70505,7 +70628,7 @@ function registerGuides(parent) {
|
|
|
70505
70628
|
// src/cli/commands/project-create.ts
|
|
70506
70629
|
init_cli_core();
|
|
70507
70630
|
init_client();
|
|
70508
|
-
async function
|
|
70631
|
+
async function action13(name, options) {
|
|
70509
70632
|
const trimmed = name.trim();
|
|
70510
70633
|
if (!trimmed)
|
|
70511
70634
|
throw userError("Project name is required.");
|
|
@@ -70517,14 +70640,14 @@ async function action12(name, options) {
|
|
|
70517
70640
|
println(c.green(`✓ Created project "${data.name}" (id: ${data.id}).`));
|
|
70518
70641
|
}
|
|
70519
70642
|
function registerProjectCreate(parent) {
|
|
70520
|
-
parent.command("create").description("Create a new (empty) project.").argument("<name>", "Project name (must be unique).").option("--description <text>", "Optional project description.").action(
|
|
70643
|
+
parent.command("create").description("Create a new (empty) project.").argument("<name>", "Project name (must be unique).").option("--description <text>", "Optional project description.").action(action13);
|
|
70521
70644
|
}
|
|
70522
70645
|
|
|
70523
70646
|
// src/cli/commands/project-edit.ts
|
|
70524
70647
|
init_cli_core();
|
|
70525
70648
|
init_client();
|
|
70526
70649
|
var UUID_RE2 = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
70527
|
-
async function
|
|
70650
|
+
async function action14(target, options) {
|
|
70528
70651
|
const update = {};
|
|
70529
70652
|
if (options.name !== undefined) {
|
|
70530
70653
|
const n = options.name.trim();
|
|
@@ -70551,7 +70674,7 @@ async function action13(target, options) {
|
|
|
70551
70674
|
println(c.green(`✓ Updated project "${data.name}" (id: ${data.id}).`));
|
|
70552
70675
|
}
|
|
70553
70676
|
function registerProjectEdit(parent) {
|
|
70554
|
-
parent.command("edit").description("Rename a project and/or change its description.").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--name <new-name>", "New project name.").option("--description <text>", "New project description.").action(
|
|
70677
|
+
parent.command("edit").description("Rename a project and/or change its description.").argument("<name-or-id>", "Project name (exact match) or UUID.").option("--name <new-name>", "New project name.").option("--description <text>", "New project description.").action(action14);
|
|
70555
70678
|
}
|
|
70556
70679
|
|
|
70557
70680
|
// src/cli/commands/version-archive.ts
|
|
@@ -73974,7 +74097,7 @@ import { homedir as homedir5 } from "node:os";
|
|
|
73974
74097
|
import { join as join8 } from "node:path";
|
|
73975
74098
|
|
|
73976
74099
|
// ../../_shared/ef-meta/index.ts
|
|
73977
|
-
var EF_VERSION = "0.
|
|
74100
|
+
var EF_VERSION = "0.11.0";
|
|
73978
74101
|
|
|
73979
74102
|
// src/cli/util/checks.ts
|
|
73980
74103
|
init_config();
|
|
@@ -74539,7 +74662,7 @@ function symbol(status) {
|
|
|
74539
74662
|
return cErr.dim("ℹ");
|
|
74540
74663
|
}
|
|
74541
74664
|
}
|
|
74542
|
-
async function
|
|
74665
|
+
async function action15(options) {
|
|
74543
74666
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
74544
74667
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
74545
74668
|
const results = await runAllChecks({
|
|
@@ -74596,13 +74719,13 @@ async function action14(options) {
|
|
|
74596
74719
|
}
|
|
74597
74720
|
}
|
|
74598
74721
|
function registerDoctor(program2) {
|
|
74599
|
-
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(
|
|
74722
|
+
program2.command("doctor").description("Run diagnostic checks against the installed Cerefox.").option("--json", "Emit machine-readable JSON (no colours, structured output).").action(action15);
|
|
74600
74723
|
}
|
|
74601
74724
|
|
|
74602
74725
|
// src/cli/commands/get-audit-log.ts
|
|
74603
74726
|
init_cli_core();
|
|
74604
74727
|
init_client();
|
|
74605
|
-
async function
|
|
74728
|
+
async function action16(options) {
|
|
74606
74729
|
const limit = parsePositiveInt(options.limit, "--limit", 50);
|
|
74607
74730
|
const client = getClient();
|
|
74608
74731
|
const data = await client.rpc("cerefox_list_audit_entries", {
|
|
@@ -74640,14 +74763,14 @@ async function action15(options) {
|
|
|
74640
74763
|
})));
|
|
74641
74764
|
}
|
|
74642
74765
|
function registerGetAuditLog(program2) {
|
|
74643
|
-
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
74766
|
+
program2.command("get-audit-log").description("Query the audit log with optional filters.").option("-d, --document-id <uuid>", "Filter by document.").option("-a, --author <name>", "Filter by author.").option("-o, --operation <type>", "Filter by operation: create, update-content, update-metadata, delete, restore.").option("--since <iso>", "Lower-bound ISO timestamp.").option("--until <iso>", "Upper-bound ISO timestamp.").option("-l, --limit <n>", "Maximum entries (max 200).", "50").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action16);
|
|
74644
74767
|
}
|
|
74645
74768
|
|
|
74646
74769
|
// src/cli/commands/get-doc.ts
|
|
74647
74770
|
init_cli_core();
|
|
74648
74771
|
init_cli_core();
|
|
74649
74772
|
init_client();
|
|
74650
|
-
async function
|
|
74773
|
+
async function action17(documentId, options) {
|
|
74651
74774
|
const client = getClient();
|
|
74652
74775
|
const rows = await client.rpc("cerefox_get_document", {
|
|
74653
74776
|
p_document_id: documentId,
|
|
@@ -74673,11 +74796,14 @@ async function action16(documentId, options) {
|
|
|
74673
74796
|
}
|
|
74674
74797
|
println(c.bold(`# ${doc.doc_title}`));
|
|
74675
74798
|
println(c.dim(`[${doc.document_id}] · chunks: ${doc.chunk_count} · chars: ${doc.total_chars}` + (doc.is_archived ? " · archived" : "") + (doc.version_id ? ` · version: ${doc.version_id}` : "")));
|
|
74799
|
+
if (doc.content_hash) {
|
|
74800
|
+
println(c.dim(`content_hash: ${doc.content_hash}`));
|
|
74801
|
+
}
|
|
74676
74802
|
println("");
|
|
74677
74803
|
println(doc.full_content);
|
|
74678
74804
|
}
|
|
74679
74805
|
function registerGetDoc(program2) {
|
|
74680
|
-
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
74806
|
+
program2.command("get-doc").description("Retrieve the full content of a document by ID.").argument("<document-id>", "UUID of the document.").option("--version-id <uuid>", "Specific archived version (default: current).").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action17);
|
|
74681
74807
|
}
|
|
74682
74808
|
|
|
74683
74809
|
// src/cli/commands/ingest.ts
|
|
@@ -74932,6 +75058,47 @@ async function resolveProjectIds(input, getOrCreateProject) {
|
|
|
74932
75058
|
}
|
|
74933
75059
|
return [];
|
|
74934
75060
|
}
|
|
75061
|
+
// src/ingestion/types.ts
|
|
75062
|
+
class ConcurrencyConflictError extends Error {
|
|
75063
|
+
documentId;
|
|
75064
|
+
currentHash;
|
|
75065
|
+
constructor(documentId, currentHash, message) {
|
|
75066
|
+
super(message);
|
|
75067
|
+
this.name = "ConcurrencyConflictError";
|
|
75068
|
+
this.documentId = documentId;
|
|
75069
|
+
this.currentHash = currentHash;
|
|
75070
|
+
}
|
|
75071
|
+
}
|
|
75072
|
+
|
|
75073
|
+
class ConcurrencyTokenRequiredError extends Error {
|
|
75074
|
+
constructor(message) {
|
|
75075
|
+
super(message);
|
|
75076
|
+
this.name = "ConcurrencyTokenRequiredError";
|
|
75077
|
+
}
|
|
75078
|
+
}
|
|
75079
|
+
var DEFAULT_PIPELINE_SETTINGS = {
|
|
75080
|
+
maxChunkChars: 4000,
|
|
75081
|
+
minChunkChars: 100,
|
|
75082
|
+
versionRetentionHours: 48,
|
|
75083
|
+
versionCleanupEnabled: true
|
|
75084
|
+
};
|
|
75085
|
+
function loadPipelineSettings() {
|
|
75086
|
+
const env4 = globalThis.process?.env ?? {};
|
|
75087
|
+
const intMin = (raw, def, min) => {
|
|
75088
|
+
if (raw === undefined || raw === "")
|
|
75089
|
+
return def;
|
|
75090
|
+
const n = Number.parseInt(raw, 10);
|
|
75091
|
+
return Number.isNaN(n) || n < min ? def : n;
|
|
75092
|
+
};
|
|
75093
|
+
const bool = (raw, def) => raw === undefined || raw === "" ? def : !/^(false|0|no|off)$/i.test(raw.trim());
|
|
75094
|
+
return {
|
|
75095
|
+
maxChunkChars: intMin(env4.CEREFOX_MAX_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.maxChunkChars, 1),
|
|
75096
|
+
minChunkChars: intMin(env4.CEREFOX_MIN_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.minChunkChars, 0),
|
|
75097
|
+
versionRetentionHours: intMin(env4.CEREFOX_VERSION_RETENTION_HOURS, DEFAULT_PIPELINE_SETTINGS.versionRetentionHours, 0),
|
|
75098
|
+
versionCleanupEnabled: bool(env4.CEREFOX_VERSION_CLEANUP_ENABLED, DEFAULT_PIPELINE_SETTINGS.versionCleanupEnabled)
|
|
75099
|
+
};
|
|
75100
|
+
}
|
|
75101
|
+
|
|
74935
75102
|
// src/ingestion/client-bridge.ts
|
|
74936
75103
|
class IngestionDbBridge {
|
|
74937
75104
|
supabase;
|
|
@@ -74984,9 +75151,22 @@ class IngestionDbBridge {
|
|
|
74984
75151
|
params.p_retention_hours = args.retentionHours;
|
|
74985
75152
|
if (args.cleanupEnabled !== undefined)
|
|
74986
75153
|
params.p_cleanup_enabled = args.cleanupEnabled;
|
|
75154
|
+
if (args.documentId !== null) {
|
|
75155
|
+
params.p_expected_content_hash = args.expectedContentHash ?? null;
|
|
75156
|
+
params.p_last_write_wins = args.lastWriteWins ?? false;
|
|
75157
|
+
}
|
|
74987
75158
|
const { data, error: error2 } = await this.supabase.rpc("cerefox_ingest_document", params);
|
|
74988
|
-
if (error2)
|
|
74989
|
-
|
|
75159
|
+
if (error2) {
|
|
75160
|
+
const msg = error2.message ?? JSON.stringify(error2);
|
|
75161
|
+
if (msg.includes("CEREFOX_CONFLICT")) {
|
|
75162
|
+
const current = msg.match(/current hash ([0-9a-f]{64})/)?.[1] ?? null;
|
|
75163
|
+
throw new ConcurrencyConflictError(args.documentId ?? "", current, msg);
|
|
75164
|
+
}
|
|
75165
|
+
if (msg.includes("CEREFOX_TOKEN_REQUIRED")) {
|
|
75166
|
+
throw new ConcurrencyTokenRequiredError(msg);
|
|
75167
|
+
}
|
|
75168
|
+
throw new Error(msg);
|
|
75169
|
+
}
|
|
74990
75170
|
if (Array.isArray(data) && data.length > 0) {
|
|
74991
75171
|
return data[0];
|
|
74992
75172
|
}
|
|
@@ -75091,30 +75271,6 @@ async function fileToMarkdown(filename, data) {
|
|
|
75091
75271
|
return data.toString("utf8");
|
|
75092
75272
|
}
|
|
75093
75273
|
|
|
75094
|
-
// src/ingestion/types.ts
|
|
75095
|
-
var DEFAULT_PIPELINE_SETTINGS = {
|
|
75096
|
-
maxChunkChars: 4000,
|
|
75097
|
-
minChunkChars: 100,
|
|
75098
|
-
versionRetentionHours: 48,
|
|
75099
|
-
versionCleanupEnabled: true
|
|
75100
|
-
};
|
|
75101
|
-
function loadPipelineSettings() {
|
|
75102
|
-
const env4 = globalThis.process?.env ?? {};
|
|
75103
|
-
const intMin = (raw, def, min) => {
|
|
75104
|
-
if (raw === undefined || raw === "")
|
|
75105
|
-
return def;
|
|
75106
|
-
const n = Number.parseInt(raw, 10);
|
|
75107
|
-
return Number.isNaN(n) || n < min ? def : n;
|
|
75108
|
-
};
|
|
75109
|
-
const bool = (raw, def) => raw === undefined || raw === "" ? def : !/^(false|0|no|off)$/i.test(raw.trim());
|
|
75110
|
-
return {
|
|
75111
|
-
maxChunkChars: intMin(env4.CEREFOX_MAX_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.maxChunkChars, 1),
|
|
75112
|
-
minChunkChars: intMin(env4.CEREFOX_MIN_CHUNK_CHARS, DEFAULT_PIPELINE_SETTINGS.minChunkChars, 0),
|
|
75113
|
-
versionRetentionHours: intMin(env4.CEREFOX_VERSION_RETENTION_HOURS, DEFAULT_PIPELINE_SETTINGS.versionRetentionHours, 0),
|
|
75114
|
-
versionCleanupEnabled: bool(env4.CEREFOX_VERSION_CLEANUP_ENABLED, DEFAULT_PIPELINE_SETTINGS.versionCleanupEnabled)
|
|
75115
|
-
};
|
|
75116
|
-
}
|
|
75117
|
-
|
|
75118
75274
|
// src/ingestion/pipeline.ts
|
|
75119
75275
|
class IngestionPipeline {
|
|
75120
75276
|
db;
|
|
@@ -75141,7 +75297,9 @@ class IngestionPipeline {
|
|
|
75141
75297
|
updateExisting = false,
|
|
75142
75298
|
documentId,
|
|
75143
75299
|
author = "unknown",
|
|
75144
|
-
authorType = "user"
|
|
75300
|
+
authorType = "user",
|
|
75301
|
+
expectedContentHash,
|
|
75302
|
+
lastWriteWins = false
|
|
75145
75303
|
} = opts;
|
|
75146
75304
|
const listFormProvided = projectIds !== undefined && projectIds !== null || projectNames !== undefined && projectNames !== null;
|
|
75147
75305
|
const getOrCreate = (name) => this.db.getOrCreateProject(name);
|
|
@@ -75162,7 +75320,9 @@ class IngestionPipeline {
|
|
|
75162
75320
|
projectIds: fullSetResolved,
|
|
75163
75321
|
metadata,
|
|
75164
75322
|
author,
|
|
75165
|
-
authorType
|
|
75323
|
+
authorType,
|
|
75324
|
+
expectedContentHash,
|
|
75325
|
+
lastWriteWins
|
|
75166
75326
|
});
|
|
75167
75327
|
if (!listFormProvided && (projectId || projectName)) {
|
|
75168
75328
|
const singular = await resolveProjectIds({ projectId, projectName }, getOrCreate);
|
|
@@ -75197,7 +75357,9 @@ class IngestionPipeline {
|
|
|
75197
75357
|
projectIds: fullSetResolved,
|
|
75198
75358
|
metadata,
|
|
75199
75359
|
author,
|
|
75200
|
-
authorType
|
|
75360
|
+
authorType,
|
|
75361
|
+
expectedContentHash,
|
|
75362
|
+
lastWriteWins
|
|
75201
75363
|
});
|
|
75202
75364
|
if (!listFormProvided && (projectId || projectName)) {
|
|
75203
75365
|
const singular = await resolveProjectIds({ projectId, projectName }, getOrCreate);
|
|
@@ -75283,7 +75445,9 @@ ${c2.content}`);
|
|
|
75283
75445
|
projectIds,
|
|
75284
75446
|
metadata,
|
|
75285
75447
|
author = "unknown",
|
|
75286
|
-
authorType = "user"
|
|
75448
|
+
authorType = "user",
|
|
75449
|
+
expectedContentHash,
|
|
75450
|
+
lastWriteWins = false
|
|
75287
75451
|
} = opts;
|
|
75288
75452
|
const existing = await this.db.getDocumentById(documentId);
|
|
75289
75453
|
if (!existing) {
|
|
@@ -75292,6 +75456,9 @@ ${c2.content}`);
|
|
|
75292
75456
|
const newHash = contentHash(text);
|
|
75293
75457
|
const contentUnchanged = newHash === existing.content_hash;
|
|
75294
75458
|
if (!contentUnchanged) {
|
|
75459
|
+
if (!lastWriteWins && expectedContentHash && expectedContentHash !== existing.content_hash) {
|
|
75460
|
+
throw new ConcurrencyConflictError(documentId, existing.content_hash, `CEREFOX_CONFLICT: document ${documentId} changed since it was read ` + `(expected hash ${expectedContentHash}, current hash ${existing.content_hash}). ` + `Re-read the document, merge your changes, and retry with the new hash.`);
|
|
75461
|
+
}
|
|
75295
75462
|
const collision = await this.db.getDocumentByHash(newHash);
|
|
75296
75463
|
if (collision && collision.id !== documentId) {
|
|
75297
75464
|
throw new Error(`Identical content already exists as document ${JSON.stringify(collision.title)}. ` + "Edit that document or change the content before saving.");
|
|
@@ -75392,7 +75559,9 @@ ${c2.content}`);
|
|
|
75392
75559
|
authorType,
|
|
75393
75560
|
sourceLabel: source,
|
|
75394
75561
|
retentionHours: this.settings.versionRetentionHours,
|
|
75395
|
-
cleanupEnabled: this.settings.versionCleanupEnabled
|
|
75562
|
+
cleanupEnabled: this.settings.versionCleanupEnabled,
|
|
75563
|
+
expectedContentHash: expectedContentHash ?? null,
|
|
75564
|
+
lastWriteWins
|
|
75396
75565
|
});
|
|
75397
75566
|
let finalProjectIds;
|
|
75398
75567
|
if (newProjectIds !== null) {
|
|
@@ -75455,7 +75624,7 @@ async function readContent(path, paste) {
|
|
|
75455
75624
|
const titleFromPath = basename2(path, extname3(path));
|
|
75456
75625
|
return { content, titleFromPath };
|
|
75457
75626
|
}
|
|
75458
|
-
async function
|
|
75627
|
+
async function action18(path, options) {
|
|
75459
75628
|
const { content, titleFromPath } = await readContent(path, Boolean(options.paste));
|
|
75460
75629
|
const title = options.title ?? titleFromPath;
|
|
75461
75630
|
if (!title || title.trim() === "") {
|
|
@@ -75497,7 +75666,9 @@ async function action17(path, options) {
|
|
|
75497
75666
|
updateExisting: Boolean(options.updateIfExists),
|
|
75498
75667
|
documentId: options.documentId ?? null,
|
|
75499
75668
|
author,
|
|
75500
|
-
authorType
|
|
75669
|
+
authorType,
|
|
75670
|
+
expectedContentHash: options.expectedContentHash ?? null,
|
|
75671
|
+
lastWriteWins: Boolean(options.lastWriteWins)
|
|
75501
75672
|
}) : await pipeline.ingestText({
|
|
75502
75673
|
text: content,
|
|
75503
75674
|
title,
|
|
@@ -75508,7 +75679,9 @@ async function action17(path, options) {
|
|
|
75508
75679
|
updateExisting: Boolean(options.updateIfExists),
|
|
75509
75680
|
documentId: options.documentId ?? null,
|
|
75510
75681
|
author,
|
|
75511
|
-
authorType
|
|
75682
|
+
authorType,
|
|
75683
|
+
expectedContentHash: options.expectedContentHash ?? null,
|
|
75684
|
+
lastWriteWins: Boolean(options.lastWriteWins)
|
|
75512
75685
|
});
|
|
75513
75686
|
let verb;
|
|
75514
75687
|
if (result.action === "created") {
|
|
@@ -75527,7 +75700,7 @@ async function action17(path, options) {
|
|
|
75527
75700
|
}
|
|
75528
75701
|
}
|
|
75529
75702
|
function registerIngest(program2) {
|
|
75530
|
-
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(
|
|
75703
|
+
program2.command("ingest").description("Ingest a file (or stdin paste) into the knowledge base.").argument("[path]", "Path to the file to ingest. Omit when using --paste.").option("--paste", "Read content from stdin instead of a file.").option("-t, --title <title>", "Document title (required with --paste; defaults to filename without extension).").option("-p, --project-name <name>", "Single project membership (non-destructive on update).").option("-P, --project-names <names>", "Comma-separated full project membership set (destructive replace on update).").option("-m, --metadata <json>", "JSON metadata object.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-i, --document-id <uuid>", "Update a specific document by UUID (overrides --update-if-exists).").option("--expected-content-hash <sha256>", "Optimistic-concurrency token: the content_hash of the version this edit is based on (shown by `document get` / `search`). Required on content updates unless --last-write-wins.").option("--last-write-wins", "Skip the concurrency check and overwrite regardless of concurrent changes (recorded in the audit log).").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").action(action18);
|
|
75531
75704
|
}
|
|
75532
75705
|
|
|
75533
75706
|
// src/cli/commands/ingest-dir.ts
|
|
@@ -75563,7 +75736,7 @@ function walk(dir, extensions) {
|
|
|
75563
75736
|
}
|
|
75564
75737
|
return files;
|
|
75565
75738
|
}
|
|
75566
|
-
async function
|
|
75739
|
+
async function action19(dir, options) {
|
|
75567
75740
|
const extensions = new Set((options.extensions ?? ".md,.txt").split(",").map((e) => e.trim().toLowerCase()).map((e) => e.startsWith(".") ? e : "." + e).filter((e) => e.length > 0));
|
|
75568
75741
|
const files = walk(dir, extensions);
|
|
75569
75742
|
if (files.length === 0) {
|
|
@@ -75609,7 +75782,8 @@ async function action18(dir, options) {
|
|
|
75609
75782
|
metadata,
|
|
75610
75783
|
updateExisting: Boolean(options.updateIfExists),
|
|
75611
75784
|
author,
|
|
75612
|
-
authorType
|
|
75785
|
+
authorType,
|
|
75786
|
+
lastWriteWins: true
|
|
75613
75787
|
});
|
|
75614
75788
|
outcomes.push({
|
|
75615
75789
|
file,
|
|
@@ -75636,7 +75810,7 @@ async function action18(dir, options) {
|
|
|
75636
75810
|
}
|
|
75637
75811
|
}
|
|
75638
75812
|
function registerIngestDir(program2) {
|
|
75639
|
-
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(
|
|
75813
|
+
program2.command("ingest-dir").description("Recursively ingest a directory of markdown / text files.").argument("<dir>", "Root directory to walk.").option("-p, --project-name <name>", "Project membership for all ingested docs.").option("-m, --metadata <json>", "JSON metadata applied to every doc.").option("--source <label>", "Origin label (default: cli).", "cli").option("-u, --update-if-exists", "Update an existing doc with the same title.").option("-a, --author <name>", "Caller identity (audit log).").option("--author-type <type>", "'user' or 'agent' (default: user).", "user").option("-e, --extensions <list>", "Comma-separated file extensions to ingest.", ".md,.txt").action(action19);
|
|
75640
75814
|
}
|
|
75641
75815
|
|
|
75642
75816
|
// src/cli/commands/init.ts
|
|
@@ -75966,7 +76140,7 @@ function writeAnswersTo(target, answers) {
|
|
|
75966
76140
|
}
|
|
75967
76141
|
}
|
|
75968
76142
|
}
|
|
75969
|
-
async function
|
|
76143
|
+
async function action21(options) {
|
|
75970
76144
|
const homeEnv = join10(homedir6(), USER_STATE_DIR_NAME, ".env");
|
|
75971
76145
|
const cwdEnv = join10(process.cwd(), ".env");
|
|
75972
76146
|
const explicitDir = (process.env.CEREFOX_CONFIG_DIR ?? "").trim();
|
|
@@ -76075,13 +76249,13 @@ async function action20(options) {
|
|
|
76075
76249
|
await postWriteLifecycle(target, options);
|
|
76076
76250
|
}
|
|
76077
76251
|
function registerInit(program2) {
|
|
76078
|
-
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(
|
|
76252
|
+
program2.command("init").description("Interactive first-run setup (config, schema deploy stub, optional MCP wiring).").option("-c, --config <file>", "Non-interactive mode: read answers from a JSON file.").option("--force", "Overwrite existing configuration without prompting.").option("--skip-schema", "Skip the schema deploy step.").option("--skip-self-docs", "Skip the bundled self-doc ingest.").option("--skip-agent-config", "Skip the optional MCP agent wiring.").action(action21);
|
|
76079
76253
|
}
|
|
76080
76254
|
|
|
76081
76255
|
// src/cli/commands/list-docs.ts
|
|
76082
76256
|
init_cli_core();
|
|
76083
76257
|
init_client();
|
|
76084
|
-
async function
|
|
76258
|
+
async function action22(options) {
|
|
76085
76259
|
const deleted = !!options.deleted;
|
|
76086
76260
|
const limit = parsePositiveInt(options.limit, "--limit", 100);
|
|
76087
76261
|
const client = getClient();
|
|
@@ -76141,13 +76315,13 @@ async function action21(options) {
|
|
|
76141
76315
|
}));
|
|
76142
76316
|
}
|
|
76143
76317
|
function registerListDocs(program2) {
|
|
76144
|
-
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--deleted", "List soft-deleted (trashed) documents instead of active ones.").option("--json", "Emit machine-readable JSON.").action(
|
|
76318
|
+
program2.command("list-docs").description("List documents in the knowledge base.").option("-p, --project <name>", "Filter to a specific project.").option("-l, --limit <n>", "Maximum docs to return.", "100").option("--deleted", "List soft-deleted (trashed) documents instead of active ones.").option("--json", "Emit machine-readable JSON.").action(action22);
|
|
76145
76319
|
}
|
|
76146
76320
|
|
|
76147
76321
|
// src/cli/commands/list-metadata-keys.ts
|
|
76148
76322
|
init_cli_core();
|
|
76149
76323
|
init_client();
|
|
76150
|
-
async function
|
|
76324
|
+
async function action23(options) {
|
|
76151
76325
|
const client = getClient();
|
|
76152
76326
|
const data = await client.rpc("cerefox_list_metadata_keys");
|
|
76153
76327
|
if (data === null) {
|
|
@@ -76175,13 +76349,13 @@ async function action22(options) {
|
|
|
76175
76349
|
})));
|
|
76176
76350
|
}
|
|
76177
76351
|
function registerListMetadataKeys(program2) {
|
|
76178
|
-
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
76352
|
+
program2.command("list-metadata-keys").description("List all metadata keys with document counts and example values.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action23);
|
|
76179
76353
|
}
|
|
76180
76354
|
|
|
76181
76355
|
// src/cli/commands/list-projects.ts
|
|
76182
76356
|
init_cli_core();
|
|
76183
76357
|
init_client();
|
|
76184
|
-
async function
|
|
76358
|
+
async function action24(options) {
|
|
76185
76359
|
const client = getClient();
|
|
76186
76360
|
const { data, error: error2 } = await client.raw.from("cerefox_projects").select("id, name, description, created_at").order("name", { ascending: true });
|
|
76187
76361
|
if (error2) {
|
|
@@ -76210,13 +76384,13 @@ async function action23(options) {
|
|
|
76210
76384
|
})), "(no projects)");
|
|
76211
76385
|
}
|
|
76212
76386
|
function registerListProjects(program2) {
|
|
76213
|
-
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
76387
|
+
program2.command("list-projects").description("List all projects in the knowledge base.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action24);
|
|
76214
76388
|
}
|
|
76215
76389
|
|
|
76216
76390
|
// src/cli/commands/list-versions.ts
|
|
76217
76391
|
init_cli_core();
|
|
76218
76392
|
init_client();
|
|
76219
|
-
async function
|
|
76393
|
+
async function action25(documentId, options) {
|
|
76220
76394
|
const client = getClient();
|
|
76221
76395
|
const data = await client.rpc("cerefox_list_document_versions", {
|
|
76222
76396
|
p_document_id: documentId
|
|
@@ -76257,7 +76431,7 @@ async function action24(documentId, options) {
|
|
|
76257
76431
|
})));
|
|
76258
76432
|
}
|
|
76259
76433
|
function registerListVersions(program2) {
|
|
76260
|
-
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
76434
|
+
program2.command("list-versions").description("List archived versions of a document.").argument("<document-id>", "UUID of the document.").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action25);
|
|
76261
76435
|
}
|
|
76262
76436
|
|
|
76263
76437
|
// src/cli/commands/mcp.ts
|
|
@@ -76272,7 +76446,7 @@ function registerMcp(program2) {
|
|
|
76272
76446
|
// src/cli/commands/metadata-search.ts
|
|
76273
76447
|
init_cli_core();
|
|
76274
76448
|
init_client();
|
|
76275
|
-
async function
|
|
76449
|
+
async function action26(options) {
|
|
76276
76450
|
const metadataFilter = parseJsonObjectArg(options.metadataFilter, "--metadata-filter");
|
|
76277
76451
|
if (!metadataFilter || Object.keys(metadataFilter).length === 0) {
|
|
76278
76452
|
throw userError("--metadata-filter is required and must be a non-empty JSON object.", `Example: --metadata-filter '{"type":"decision-log"}'.`);
|
|
@@ -76335,7 +76509,7 @@ async function action25(options) {
|
|
|
76335
76509
|
}
|
|
76336
76510
|
}
|
|
76337
76511
|
function registerMetadataSearch(program2) {
|
|
76338
|
-
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(
|
|
76512
|
+
program2.command("metadata-search").description("Find documents by metadata criteria (no text query).").requiredOption("-f, --metadata-filter <json>", "JSON object; only docs whose metadata contains ALL pairs are returned.").option("-p, --project-name <name>", "Filter to a specific project.").option("--updated-since <iso>", "Only docs updated on/after this ISO timestamp.").option("--created-since <iso>", "Only docs created on/after this ISO timestamp.").option("--include-content", "Include full document text in results.").option("-l, --limit <n>", "Maximum docs to return.", "10").option("--max-bytes <n>", "Response size budget in bytes (with --include-content).", "200000").option("-r, --requestor <name>", "Agent / user name (usage log).").option("--json", "Emit machine-readable JSON.").action(action26);
|
|
76339
76513
|
}
|
|
76340
76514
|
|
|
76341
76515
|
// src/cli/commands/reindex.ts
|
|
@@ -76343,7 +76517,7 @@ init_dist4();
|
|
|
76343
76517
|
init_cli_core();
|
|
76344
76518
|
init_config();
|
|
76345
76519
|
var DEFAULT_MODEL = "text-embedding-3-small";
|
|
76346
|
-
async function
|
|
76520
|
+
async function action27(options) {
|
|
76347
76521
|
const settings = loadSettings();
|
|
76348
76522
|
if (!settings.supabaseUrl || !settings.supabaseKey) {
|
|
76349
76523
|
throw userError("Supabase credentials not configured — run `cerefox init` first.");
|
|
@@ -76422,7 +76596,7 @@ ${c2.content}`;
|
|
|
76422
76596
|
}
|
|
76423
76597
|
}
|
|
76424
76598
|
function registerReindex(program2) {
|
|
76425
|
-
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(
|
|
76599
|
+
program2.command("reindex").description("Re-embed existing document chunks (v0.7+).").option("--all", "Reindex every chunk regardless of embedder.").option("--batch <n>", "Chunks per OpenAI batch call. Capped at 96 internally.", "32").option("--dry-run", "Show counts without re-embedding.").option("-i, --document-id <uuid>", "Limit reindex to a single document.").action(action27);
|
|
76426
76600
|
}
|
|
76427
76601
|
|
|
76428
76602
|
// src/cli/commands/restore.ts
|
|
@@ -76452,7 +76626,7 @@ function resolveBackupFile(target) {
|
|
|
76452
76626
|
}
|
|
76453
76627
|
return join11(path, candidates[0].name);
|
|
76454
76628
|
}
|
|
76455
|
-
async function
|
|
76629
|
+
async function action28(target, options) {
|
|
76456
76630
|
const file = resolveBackupFile(target);
|
|
76457
76631
|
let payload;
|
|
76458
76632
|
try {
|
|
@@ -76508,7 +76682,7 @@ async function action27(target, options) {
|
|
|
76508
76682
|
}
|
|
76509
76683
|
}
|
|
76510
76684
|
function registerRestore(program2) {
|
|
76511
|
-
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(
|
|
76685
|
+
program2.command("restore").description("Restore a JSON-snapshot backup into the knowledge base.").argument("<snapshot>", "Backup file (or directory; most recent is picked) produced by `cerefox backup`.").option("--dry-run", "Print what would be restored without writing.").option("-p, --project-name <name>", "Reserved for future use; currently ignored (project memberships ride along with each doc's metadata).").action(action28);
|
|
76512
76686
|
}
|
|
76513
76687
|
|
|
76514
76688
|
// src/cli/commands/search.ts
|
|
@@ -76533,7 +76707,7 @@ async function embedQuery(query) {
|
|
|
76533
76707
|
}
|
|
76534
76708
|
|
|
76535
76709
|
// src/cli/commands/search.ts
|
|
76536
|
-
async function
|
|
76710
|
+
async function action29(query, options) {
|
|
76537
76711
|
if (!query || query.trim() === "") {
|
|
76538
76712
|
throw userError("Empty query.");
|
|
76539
76713
|
}
|
|
@@ -76655,10 +76829,12 @@ async function action28(query, options) {
|
|
|
76655
76829
|
println(c.bold(`## ${title}${docId}${score}${counts}${kind}`));
|
|
76656
76830
|
const bestMatch = doc2.best_chunk_heading_path?.length ? doc2.best_chunk_heading_path.join(" › ") : null;
|
|
76657
76831
|
const updated = doc2.doc_updated_at ? doc2.doc_updated_at.slice(0, 10) : null;
|
|
76658
|
-
|
|
76832
|
+
const hash = doc2.content_hash ? `hash: ${doc2.content_hash}` : null;
|
|
76833
|
+
if (bestMatch || updated || hash) {
|
|
76659
76834
|
const bits = [
|
|
76660
76835
|
bestMatch ? `best match: ${bestMatch}` : null,
|
|
76661
|
-
updated ? `updated ${updated}` : null
|
|
76836
|
+
updated ? `updated ${updated}` : null,
|
|
76837
|
+
hash
|
|
76662
76838
|
].filter(Boolean);
|
|
76663
76839
|
println(c.dim(` ${bits.join(" · ")}`));
|
|
76664
76840
|
}
|
|
@@ -76685,7 +76861,7 @@ async function action28(query, options) {
|
|
|
76685
76861
|
}
|
|
76686
76862
|
}
|
|
76687
76863
|
function registerSearch(program2) {
|
|
76688
|
-
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold (default: CEREFOX_MIN_SEARCH_SCORE or 0.5).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(
|
|
76864
|
+
program2.command("search").description("Search the knowledge base (hybrid FTS + semantic).").argument("<query>", "Natural-language search query.").option("-c, --match-count <n>", "Maximum number of documents to return.", "5").option("-p, --project-name <name>", "Filter results to a specific project.").option("-f, --metadata-filter <json>", "JSON containment filter; only docs whose metadata contains ALL pairs are returned.").option("--mode <mode>", "Search mode: docs (default), hybrid, fts.", "docs").option("--alpha <float>", "Semantic weight 0..1 (default: 0.7).", "0.7").option("--min-score <float>", "Minimum cosine similarity threshold (default: CEREFOX_MIN_SEARCH_SCORE or 0.5).").option("--max-bytes <n>", "Response size budget in bytes (default: CEREFOX_MAX_RESPONSE_BYTES or 200000).").option("-r, --requestor <name>", "Agent / user name (recorded in usage log).").option("--json", "Emit machine-readable JSON instead of the default text.").option("--only-metadata", "List matching docs (id, score, chunks, chars, partial/full) WITHOUT their content — like the web UI's collapsed result list. Grab a [id:…] then `cerefox document get <id>`.").action(action29);
|
|
76689
76865
|
}
|
|
76690
76866
|
|
|
76691
76867
|
// src/cli/commands/self-update.ts
|
|
@@ -76732,7 +76908,7 @@ async function fetchLatestVersion() {
|
|
|
76732
76908
|
}
|
|
76733
76909
|
return body.version;
|
|
76734
76910
|
}
|
|
76735
|
-
async function
|
|
76911
|
+
async function action30(options) {
|
|
76736
76912
|
let target;
|
|
76737
76913
|
try {
|
|
76738
76914
|
target = options.version ?? await fetchLatestVersion();
|
|
@@ -76784,7 +76960,7 @@ async function action29(options) {
|
|
|
76784
76960
|
}
|
|
76785
76961
|
function registerSelfUpdate(program2) {
|
|
76786
76962
|
const desc = "Upgrade Cerefox in place. Alias: `cerefox upgrade`.";
|
|
76787
|
-
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(
|
|
76963
|
+
const declaration = (cmd) => cmd.description(desc).option("--check", "Print current vs latest; do nothing.").option("--yes", "Non-interactive (skip confirmation).").option("--version <version>", "Pin a specific version (e.g. 0.5.1 or 0.6.0-rc.1).").action(action30);
|
|
76788
76964
|
declaration(program2.command("self-update"));
|
|
76789
76965
|
declaration(program2.command("upgrade"));
|
|
76790
76966
|
}
|
|
@@ -76803,7 +76979,7 @@ function symbol2(status) {
|
|
|
76803
76979
|
return cErr.dim("ℹ");
|
|
76804
76980
|
}
|
|
76805
76981
|
}
|
|
76806
|
-
async function
|
|
76982
|
+
async function action31(options) {
|
|
76807
76983
|
const useSpinner = !options.json && process.stderr.isTTY;
|
|
76808
76984
|
const spinner = useSpinner ? ora({ text: "Starting checks…", spinner: "dots", stream: process.stderr }).start() : null;
|
|
76809
76985
|
const results = await runFastChecks({
|
|
@@ -76824,7 +77000,7 @@ async function action30(options) {
|
|
|
76824
77000
|
}
|
|
76825
77001
|
}
|
|
76826
77002
|
function registerStatus(program2) {
|
|
76827
|
-
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(
|
|
77003
|
+
program2.command("status").description("Quick sanity check (fast subset of `cerefox doctor`).").option("--json", "Emit machine-readable JSON.").action(action31);
|
|
76828
77004
|
}
|
|
76829
77005
|
|
|
76830
77006
|
// src/cli/program.ts
|
|
@@ -76833,15 +77009,15 @@ init_sync_self_docs();
|
|
|
76833
77009
|
// src/cli/commands/web.ts
|
|
76834
77010
|
init_cli_core();
|
|
76835
77011
|
|
|
76836
|
-
// ../../node_modules/.bun/@hono+node-server@2.0.4+
|
|
77012
|
+
// ../../node_modules/.bun/@hono+node-server@2.0.4+8bc17dcb8a4189a6/node_modules/@hono/node-server/dist/constants-BLSFu_RU.mjs
|
|
76837
77013
|
var X_ALREADY_SENT = "x-hono-already-sent";
|
|
76838
77014
|
|
|
76839
|
-
// ../../node_modules/.bun/@hono+node-server@2.0.4+
|
|
77015
|
+
// ../../node_modules/.bun/@hono+node-server@2.0.4+8bc17dcb8a4189a6/node_modules/@hono/node-server/dist/index.mjs
|
|
76840
77016
|
import { STATUS_CODES, createServer } from "node:http";
|
|
76841
77017
|
import { Http2ServerRequest, constants } from "node:http2";
|
|
76842
77018
|
import { Readable } from "node:stream";
|
|
76843
77019
|
|
|
76844
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
77020
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/helper/websocket/index.js
|
|
76845
77021
|
var WSContext = class {
|
|
76846
77022
|
#init;
|
|
76847
77023
|
constructor(init) {
|
|
@@ -76889,7 +77065,7 @@ var defineWebSocketHelper = (handler11) => {
|
|
|
76889
77065
|
};
|
|
76890
77066
|
};
|
|
76891
77067
|
|
|
76892
|
-
// ../../node_modules/.bun/@hono+node-server@2.0.4+
|
|
77068
|
+
// ../../node_modules/.bun/@hono+node-server@2.0.4+8bc17dcb8a4189a6/node_modules/@hono/node-server/dist/index.mjs
|
|
76893
77069
|
var RequestError = class extends Error {
|
|
76894
77070
|
constructor(message, options) {
|
|
76895
77071
|
super(message, options);
|
|
@@ -78023,7 +78199,7 @@ var serve = (options, listeningListener) => {
|
|
|
78023
78199
|
return server;
|
|
78024
78200
|
};
|
|
78025
78201
|
|
|
78026
|
-
// ../../node_modules/.bun/@hono+node-server@2.0.4+
|
|
78202
|
+
// ../../node_modules/.bun/@hono+node-server@2.0.4+8bc17dcb8a4189a6/node_modules/@hono/node-server/dist/utils/stream.mjs
|
|
78027
78203
|
import { Readable as Readable2 } from "node:stream";
|
|
78028
78204
|
import { versions as versions2 } from "node:process";
|
|
78029
78205
|
var pr54206Applied = () => {
|
|
@@ -78089,7 +78265,7 @@ var createStreamBody = (stream, useNativeReadableToWeb = useReadableToWeb) => {
|
|
|
78089
78265
|
});
|
|
78090
78266
|
};
|
|
78091
78267
|
|
|
78092
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78268
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/mime.js
|
|
78093
78269
|
var getMimeType = (filename, mimes = baseMimes) => {
|
|
78094
78270
|
const regexp = /\.([a-zA-Z0-9]+?)$/;
|
|
78095
78271
|
const match = filename.match(regexp);
|
|
@@ -78158,7 +78334,7 @@ var _baseMimes = {
|
|
|
78158
78334
|
};
|
|
78159
78335
|
var baseMimes = _baseMimes;
|
|
78160
78336
|
|
|
78161
|
-
// ../../node_modules/.bun/@hono+node-server@2.0.4+
|
|
78337
|
+
// ../../node_modules/.bun/@hono+node-server@2.0.4+8bc17dcb8a4189a6/node_modules/@hono/node-server/dist/serve-static.mjs
|
|
78162
78338
|
import { createReadStream, existsSync as existsSync12, statSync as statSync5 } from "node:fs";
|
|
78163
78339
|
import { join as join12 } from "node:path";
|
|
78164
78340
|
var COMPRESSIBLE_CONTENT_TYPE_REGEX = /^\s*(?:text\/[^;\s]+|application\/(?:javascript|json|xml|xml-dtd|ecmascript|dart|postscript|rtf|tar|toml|vnd\.dart|vnd\.ms-fontobject|vnd\.ms-opentype|wasm|x-httpd-php|x-javascript|x-ns-proxy-autoconfig|x-sh|x-tar|x-virtualbox-hdd|x-virtualbox-ova|x-virtualbox-ovf|x-virtualbox-vbox|x-virtualbox-vdi|x-virtualbox-vhd|x-virtualbox-vmdk|x-www-form-urlencoded)|font\/(?:otf|ttf)|image\/(?:bmp|vnd\.adobe\.photoshop|vnd\.microsoft\.icon|vnd\.ms-dds|x-icon|x-ms-bmp)|message\/rfc822|model\/gltf-binary|x-shader\/x-fragment|x-shader\/x-vertex|[^;\s]+?\+(?:json|text|xml|yaml))(?:[;\s]|$)/i;
|
|
@@ -78274,7 +78450,7 @@ import { existsSync as existsSync16 } from "node:fs";
|
|
|
78274
78450
|
import { readFileSync as readFileSync15 } from "node:fs";
|
|
78275
78451
|
import { join as join16 } from "node:path";
|
|
78276
78452
|
|
|
78277
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78453
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/compose.js
|
|
78278
78454
|
var compose = (middleware, onError, onNotFound) => {
|
|
78279
78455
|
return (context, next) => {
|
|
78280
78456
|
let index = -1;
|
|
@@ -78318,10 +78494,10 @@ var compose = (middleware, onError, onNotFound) => {
|
|
|
78318
78494
|
};
|
|
78319
78495
|
};
|
|
78320
78496
|
|
|
78321
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78497
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/request/constants.js
|
|
78322
78498
|
var GET_MATCH_RESULT = /* @__PURE__ */ Symbol();
|
|
78323
78499
|
|
|
78324
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78500
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/body.js
|
|
78325
78501
|
var parseBody = async (request, options = /* @__PURE__ */ Object.create(null)) => {
|
|
78326
78502
|
const { all = false, dot = false } = options;
|
|
78327
78503
|
const headers = request instanceof HonoRequest ? request.raw.headers : request.headers;
|
|
@@ -78392,7 +78568,7 @@ var handleParsingNestedValues = (form, key, value) => {
|
|
|
78392
78568
|
});
|
|
78393
78569
|
};
|
|
78394
78570
|
|
|
78395
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78571
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/url.js
|
|
78396
78572
|
var splitPath = (path) => {
|
|
78397
78573
|
const paths = path.split("/");
|
|
78398
78574
|
if (paths[0] === "") {
|
|
@@ -78592,7 +78768,7 @@ var getQueryParams = (url, key) => {
|
|
|
78592
78768
|
};
|
|
78593
78769
|
var decodeURIComponent_ = decodeURIComponent;
|
|
78594
78770
|
|
|
78595
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78771
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/request.js
|
|
78596
78772
|
var tryDecodeURIComponent = (str) => tryDecode2(str, decodeURIComponent_);
|
|
78597
78773
|
var HonoRequest = class {
|
|
78598
78774
|
raw;
|
|
@@ -78706,7 +78882,7 @@ var HonoRequest = class {
|
|
|
78706
78882
|
}
|
|
78707
78883
|
};
|
|
78708
78884
|
|
|
78709
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78885
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/html.js
|
|
78710
78886
|
var HtmlEscapedCallbackPhase = {
|
|
78711
78887
|
Stringify: 1,
|
|
78712
78888
|
BeforeStream: 2,
|
|
@@ -78744,7 +78920,7 @@ var resolveCallback = async (str, phase, preserveCallbacks, context, buffer2) =>
|
|
|
78744
78920
|
}
|
|
78745
78921
|
};
|
|
78746
78922
|
|
|
78747
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
78923
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/context.js
|
|
78748
78924
|
var TEXT_PLAIN = "text/plain; charset=UTF-8";
|
|
78749
78925
|
var setDefaultContentType = (contentType2, headers) => {
|
|
78750
78926
|
return {
|
|
@@ -78911,7 +79087,7 @@ var Context = class {
|
|
|
78911
79087
|
};
|
|
78912
79088
|
};
|
|
78913
79089
|
|
|
78914
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79090
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router.js
|
|
78915
79091
|
var METHOD_NAME_ALL = "ALL";
|
|
78916
79092
|
var METHOD_NAME_ALL_LOWERCASE = "all";
|
|
78917
79093
|
var METHODS = ["get", "post", "put", "delete", "options", "patch"];
|
|
@@ -78919,10 +79095,10 @@ var MESSAGE_MATCHER_IS_ALREADY_BUILT = "Can not add a route since the matcher is
|
|
|
78919
79095
|
var UnsupportedPathError = class extends Error {
|
|
78920
79096
|
};
|
|
78921
79097
|
|
|
78922
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79098
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/constants.js
|
|
78923
79099
|
var COMPOSED_HANDLER = "__COMPOSED_HANDLER";
|
|
78924
79100
|
|
|
78925
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79101
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/hono-base.js
|
|
78926
79102
|
var notFoundHandler = (c2) => {
|
|
78927
79103
|
return c2.text("404 Not Found", 404);
|
|
78928
79104
|
};
|
|
@@ -79146,7 +79322,7 @@ var Hono = class _Hono {
|
|
|
79146
79322
|
};
|
|
79147
79323
|
};
|
|
79148
79324
|
|
|
79149
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79325
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/matcher.js
|
|
79150
79326
|
var emptyParam = [];
|
|
79151
79327
|
function match(method, path) {
|
|
79152
79328
|
const matchers = this.buildAllMatchers();
|
|
@@ -79167,7 +79343,7 @@ function match(method, path) {
|
|
|
79167
79343
|
return match2(method, path);
|
|
79168
79344
|
}
|
|
79169
79345
|
|
|
79170
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79346
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/node.js
|
|
79171
79347
|
var LABEL_REG_EXP_STR = "[^/]+";
|
|
79172
79348
|
var ONLY_WILDCARD_REG_EXP_STR = ".*";
|
|
79173
79349
|
var TAIL_WILDCARD_REG_EXP_STR = "(?:|/.*)";
|
|
@@ -79271,7 +79447,7 @@ var Node = class _Node {
|
|
|
79271
79447
|
}
|
|
79272
79448
|
};
|
|
79273
79449
|
|
|
79274
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79450
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/trie.js
|
|
79275
79451
|
var Trie = class {
|
|
79276
79452
|
#context = { varIndex: 0 };
|
|
79277
79453
|
#root = new Node;
|
|
@@ -79327,7 +79503,7 @@ var Trie = class {
|
|
|
79327
79503
|
}
|
|
79328
79504
|
};
|
|
79329
79505
|
|
|
79330
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79506
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/router.js
|
|
79331
79507
|
var nullMatcher = [/^$/, [], /* @__PURE__ */ Object.create(null)];
|
|
79332
79508
|
var wildcardRegExpCache = /* @__PURE__ */ Object.create(null);
|
|
79333
79509
|
function buildWildcardRegExp(path) {
|
|
@@ -79492,7 +79668,7 @@ var RegExpRouter = class {
|
|
|
79492
79668
|
}
|
|
79493
79669
|
};
|
|
79494
79670
|
|
|
79495
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79671
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/reg-exp-router/prepared-router.js
|
|
79496
79672
|
var PreparedRegExpRouter = class {
|
|
79497
79673
|
name = "PreparedRegExpRouter";
|
|
79498
79674
|
#matchers;
|
|
@@ -79564,7 +79740,7 @@ var PreparedRegExpRouter = class {
|
|
|
79564
79740
|
match = match;
|
|
79565
79741
|
};
|
|
79566
79742
|
|
|
79567
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79743
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/smart-router/router.js
|
|
79568
79744
|
var SmartRouter = class {
|
|
79569
79745
|
name = "SmartRouter";
|
|
79570
79746
|
#routers = [];
|
|
@@ -79619,7 +79795,7 @@ var SmartRouter = class {
|
|
|
79619
79795
|
}
|
|
79620
79796
|
};
|
|
79621
79797
|
|
|
79622
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79798
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/trie-router/node.js
|
|
79623
79799
|
var emptyParams = /* @__PURE__ */ Object.create(null);
|
|
79624
79800
|
var hasChildren = (children) => {
|
|
79625
79801
|
for (const _ in children) {
|
|
@@ -79788,7 +79964,7 @@ var Node2 = class _Node2 {
|
|
|
79788
79964
|
}
|
|
79789
79965
|
};
|
|
79790
79966
|
|
|
79791
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79967
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/router/trie-router/router.js
|
|
79792
79968
|
var TrieRouter = class {
|
|
79793
79969
|
name = "TrieRouter";
|
|
79794
79970
|
#node;
|
|
@@ -79810,7 +79986,7 @@ var TrieRouter = class {
|
|
|
79810
79986
|
}
|
|
79811
79987
|
};
|
|
79812
79988
|
|
|
79813
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79989
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/hono.js
|
|
79814
79990
|
var Hono2 = class extends Hono {
|
|
79815
79991
|
constructor(options = {}) {
|
|
79816
79992
|
super(options);
|
|
@@ -79820,7 +79996,7 @@ var Hono2 = class extends Hono {
|
|
|
79820
79996
|
}
|
|
79821
79997
|
};
|
|
79822
79998
|
|
|
79823
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
79999
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/utils/color.js
|
|
79824
80000
|
function getColorEnabled() {
|
|
79825
80001
|
const { process: process10, Deno: Deno2 } = globalThis;
|
|
79826
80002
|
const isNoColor = typeof Deno2?.noColor === "boolean" ? Deno2.noColor : process10 !== undefined ? "NO_COLOR" in process10?.env : false;
|
|
@@ -79839,7 +80015,7 @@ async function getColorEnabledAsync() {
|
|
|
79839
80015
|
return !isNoColor;
|
|
79840
80016
|
}
|
|
79841
80017
|
|
|
79842
|
-
// ../../node_modules/.bun/hono@4.12.
|
|
80018
|
+
// ../../node_modules/.bun/hono@4.12.25/node_modules/hono/dist/middleware/logger/index.js
|
|
79843
80019
|
var humanize = (times) => {
|
|
79844
80020
|
const [delimiter, separator] = [",", "."];
|
|
79845
80021
|
const orderTimes = times.map((v) => v.replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1" + delimiter));
|
|
@@ -80728,6 +80904,7 @@ function registerDocumentReadRoutes(app, ctx) {
|
|
|
80728
80904
|
created_at: meta ? meta.created_at ?? null : null,
|
|
80729
80905
|
updated_at: meta ? meta.updated_at ?? null : null,
|
|
80730
80906
|
deleted_at: meta ? meta.deleted_at ?? null : null,
|
|
80907
|
+
content_hash: meta ? meta.content_hash ?? null : null,
|
|
80731
80908
|
versions: versions3.map((v) => ({
|
|
80732
80909
|
version_id: v.version_id,
|
|
80733
80910
|
version_number: v.version_number,
|
|
@@ -80890,10 +81067,26 @@ function registerDocumentWriteRoutes(app, ctx) {
|
|
|
80890
81067
|
projectIds: Array.isArray(body.project_ids) ? body.project_ids : undefined,
|
|
80891
81068
|
metadata: Object.keys(metadata).length > 0 ? metadata : undefined,
|
|
80892
81069
|
author: "web-ui",
|
|
80893
|
-
authorType: "user"
|
|
81070
|
+
authorType: "user",
|
|
81071
|
+
expectedContentHash: typeof body.expected_content_hash === "string" ? body.expected_content_hash : null
|
|
80894
81072
|
});
|
|
80895
81073
|
return c2.json({ success: true, reindexed: result.reindexed });
|
|
80896
81074
|
} catch (err) {
|
|
81075
|
+
if (err instanceof ConcurrencyConflictError) {
|
|
81076
|
+
return c2.json({
|
|
81077
|
+
success: false,
|
|
81078
|
+
error: "conflict",
|
|
81079
|
+
message: "This document changed while you were editing it (another writer saved a newer version). Open it again in a new tab, merge your changes, and save from there.",
|
|
81080
|
+
current_hash: err.currentHash
|
|
81081
|
+
}, 409);
|
|
81082
|
+
}
|
|
81083
|
+
if (err instanceof ConcurrencyTokenRequiredError) {
|
|
81084
|
+
return c2.json({
|
|
81085
|
+
success: false,
|
|
81086
|
+
error: "expected_content_hash required",
|
|
81087
|
+
message: err.message
|
|
81088
|
+
}, 400);
|
|
81089
|
+
}
|
|
80897
81090
|
return c2.json({
|
|
80898
81091
|
success: false,
|
|
80899
81092
|
error: err instanceof Error ? err.message : String(err)
|
|
@@ -82048,6 +82241,7 @@ Learn more:
|
|
|
82048
82241
|
moveInto(document2, registerDeleteDoc, "delete");
|
|
82049
82242
|
registerDocumentRestore(document2);
|
|
82050
82243
|
registerDocumentEdit(document2);
|
|
82244
|
+
registerDocumentSetProjects(document2);
|
|
82051
82245
|
moveInto(document2, registerIngest, "ingest");
|
|
82052
82246
|
moveInto(document2, registerIngestDir, "ingest-dir");
|
|
82053
82247
|
const documentVersion = document2.command("version").description("Document versions: list, archive, unarchive.");
|