@kb-labs/core-state-daemon 2.117.0 → 2.118.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.
Files changed (3) hide show
  1. package/dist/bin.cjs +1315 -2162
  2. package/dist/bin.cjs.map +1 -1
  3. package/package.json +11 -11
package/dist/bin.cjs CHANGED
@@ -3577,6 +3577,52 @@ function createSocketPath(id) {
3577
3577
  }
3578
3578
  return `/tmp/kb-${id}.sock`;
3579
3579
  }
3580
+ function createDocumentDatabaseProxy(transport) {
3581
+ return new DocumentDatabaseProxy(transport);
3582
+ }
3583
+ function createKVStoreProxy(transport) {
3584
+ return new KVStoreProxy(transport);
3585
+ }
3586
+ function createCacheProxy(transport) {
3587
+ return new CacheProxy(transport);
3588
+ }
3589
+ function createConfigProxy(transport) {
3590
+ return new ConfigProxy(transport);
3591
+ }
3592
+ function createVectorStoreProxy(transport) {
3593
+ return new VectorStoreProxy(transport);
3594
+ }
3595
+ function createInvokeProxy(transport) {
3596
+ return new InvokeProxy(transport);
3597
+ }
3598
+ function defineIPCOperations() {
3599
+ return (operations) => operations;
3600
+ }
3601
+ function createIPCAdapterRoutes() {
3602
+ const routes = {};
3603
+ for (const slot of Object.keys(platformAdapterTransportPolicy)) {
3604
+ const policy = platformAdapterTransportPolicy[slot];
3605
+ if (!("adapter" in policy)) {
3606
+ continue;
3607
+ }
3608
+ if (routes[policy.adapter] !== void 0) {
3609
+ throw new Error(`Duplicate IPC adapter route '${policy.adapter}'`);
3610
+ }
3611
+ routes[policy.adapter] = slot;
3612
+ }
3613
+ return Object.freeze(routes);
3614
+ }
3615
+ function resolveIPCAdapter(platform2, adapterType) {
3616
+ const slot = IPC_ADAPTER_ROUTES[adapterType];
3617
+ if (!slot) {
3618
+ throw new Error(`Adapter '${adapterType}' is not exposed over IPC`);
3619
+ }
3620
+ const adapter = platform2[slot];
3621
+ if (adapter === void 0) {
3622
+ throw new Error(`Adapter '${adapterType}' is not configured for IPC`);
3623
+ }
3624
+ return adapter;
3625
+ }
3580
3626
  function toSerializableError(error) {
3581
3627
  const serialized = serialize(error);
3582
3628
  if (serialized && typeof serialized === "object" && "__type" in serialized && serialized.__type === "Error") {
@@ -3637,14 +3683,14 @@ function createProxyPlatform(options) {
3637
3683
  const { transport } = options;
3638
3684
  const logger = options.logger ?? new LoggerProxy(transport);
3639
3685
  const processExecutor = new ProcessExecutorProxy(transport);
3640
- const cache = new CacheProxy(transport);
3686
+ const cache = platformAdapterTransportPolicy.cache.proxy(transport);
3641
3687
  const llm = new LLMProxy(transport);
3642
3688
  const embeddings = new EmbeddingsProxy(transport);
3643
- const vectorStore = new VectorStoreProxy(transport);
3689
+ const vectorStore = platformAdapterTransportPolicy.vectorStore.proxy(transport);
3644
3690
  const storage = new StorageProxy(transport);
3645
- const documentDatabase = new DocumentDatabaseProxy(transport);
3646
- const kvStore = new KVStoreProxy(transport);
3647
- const config = new ConfigProxy(transport);
3691
+ const documentDatabase = platformAdapterTransportPolicy.documentDatabase.proxy(transport);
3692
+ const kvStore = platformAdapterTransportPolicy.kvStore.proxy(transport);
3693
+ const config = platformAdapterTransportPolicy.config.proxy(transport);
3648
3694
  const eventBus = new EventBusProxy(transport);
3649
3695
  const analytics = {
3650
3696
  track: async () => {
@@ -3654,10 +3700,7 @@ function createProxyPlatform(options) {
3654
3700
  flush: async () => {
3655
3701
  }
3656
3702
  };
3657
- const invoke = {
3658
- call: async () => ({ success: false, error: "Invoke not available in proxy context" }),
3659
- isAvailable: async () => false
3660
- };
3703
+ const invoke = platformAdapterTransportPolicy.invoke.proxy(transport);
3661
3704
  const logs = {
3662
3705
  query: async () => ({ logs: [], total: 0, hasMore: false, source: "buffer" }),
3663
3706
  getById: async () => null,
@@ -3684,7 +3727,7 @@ function createProxyPlatform(options) {
3684
3727
  processExecutor
3685
3728
  };
3686
3729
  }
3687
- var BulkTransferHelper, DEFAULT_SOCKET_PATH, UnixSocketServer, IPCServer, ChildIPCServer, TransportError, TimeoutError, CircuitOpenError, OPERATION_TIMEOUTS, IPCTransport, UnixSocketTransport, RemoteAdapter, CacheProxy, LLMProxy, EmbeddingsProxy, VectorStoreProxy, StorageProxy, DocumentDatabaseProxy, stripSignal, KVStoreProxy, stripSignal2, ConfigProxy, EventBusProxy, LoggerProxy, PROCESS_RPC_GRACE_MS, CONTROL_RPC_TIMEOUT_MS, MAX_TIMER_MS, ProcessExecutorProxy;
3730
+ var BulkTransferHelper, DEFAULT_SOCKET_PATH, RemoteAdapter, DocumentDatabaseProxy, stripSignal, KVStoreProxy, stripSignal2, CacheProxy, ConfigProxy, VectorStoreProxy, InvokeProxy, documentDatabaseIPCOperations, kvStoreIPCOperations, cacheIPCOperations, configIPCOperations, vectorStoreIPCOperations, invokeIPCOperations, platformAdapterTransportPolicy, IPC_ADAPTER_ROUTES, UnixSocketServer, IPCServer, ChildIPCServer, TransportError, TimeoutError, CircuitOpenError, OPERATION_TIMEOUTS, IPCTransport, UnixSocketTransport, LLMProxy, EmbeddingsProxy, StorageProxy, EventBusProxy, LoggerProxy, PROCESS_RPC_GRACE_MS, CONTROL_RPC_TIMEOUT_MS, MAX_TIMER_MS, ProcessExecutorProxy;
3688
3731
  var init_dist5 = __esm({
3689
3732
  "../../../core/ipc/dist/index.js"() {
3690
3733
  init_serializable();
@@ -3801,300 +3844,881 @@ var init_dist5 = __esm({
3801
3844
  }
3802
3845
  });
3803
3846
  DEFAULT_SOCKET_PATH = createSocketPath(`ipc-${process.pid}`);
3804
- UnixSocketServer = class {
3847
+ RemoteAdapter = class {
3805
3848
  /**
3806
- * Create a Unix Socket server.
3849
+ * Create a remote adapter proxy.
3807
3850
  *
3808
- * @param platform - Platform container with real adapters
3809
- * @param config - Server configuration
3810
- */
3811
- constructor(platform2, config = {}) {
3812
- this.platform = platform2;
3813
- this.socketPath = config.socketPath ?? DEFAULT_SOCKET_PATH;
3814
- this.authToken = config.authToken;
3815
- }
3816
- platform;
3817
- server = null;
3818
- clients = /* @__PURE__ */ new Set();
3819
- socketPath;
3820
- authToken;
3821
- started = false;
3822
- /**
3823
- * Get the socket path.
3824
- * Used by parent process to pass to child processes via env var.
3851
+ * @param adapterName - Name of the adapter (e.g., 'vectorStore', 'cache')
3852
+ * @param transport - Transport layer for IPC communication
3853
+ * @param context - Optional execution context for tracing/debugging
3825
3854
  */
3826
- getSocketPath() {
3827
- return this.socketPath;
3855
+ constructor(adapterName, transport, context) {
3856
+ this.adapterName = adapterName;
3857
+ this.transport = transport;
3858
+ this.context = context;
3828
3859
  }
3860
+ adapterName;
3861
+ transport;
3862
+ context;
3829
3863
  /**
3830
- * Start listening for connections.
3864
+ * Set execution context for this adapter.
3865
+ * Context is included in all subsequent adapter calls for tracing/debugging.
3866
+ *
3867
+ * @param context - Execution context (traceId, pluginId, sessionId, etc.)
3868
+ *
3869
+ * @example
3870
+ * ```typescript
3871
+ * proxy.setContext({
3872
+ * traceId: 'trace-abc',
3873
+ * pluginId: '@kb-labs/mind',
3874
+ * sessionId: 'session-xyz',
3875
+ * });
3876
+ * ```
3831
3877
  */
3832
- async start() {
3833
- BulkTransferHelper.registerSignalHandlers();
3834
- if (fs5__namespace.existsSync(this.socketPath)) {
3835
- fs5__namespace.unlinkSync(this.socketPath);
3836
- }
3837
- return new Promise((resolve6, reject) => {
3838
- this.server = net__namespace.createServer((socket) => {
3839
- this.handleClient(socket);
3840
- });
3841
- this.server.on("error", (error) => {
3842
- reject(error);
3843
- });
3844
- this.server.listen(this.socketPath, () => {
3845
- fs5__namespace.chmodSync(this.socketPath, 438);
3846
- this.started = true;
3847
- this.platform.logger.debug("UnixSocketServer started listening for adapter calls");
3848
- resolve6();
3849
- });
3850
- });
3878
+ setContext(context) {
3879
+ this.context = context;
3851
3880
  }
3852
3881
  /**
3853
- * Handle new client connection.
3882
+ * Get current execution context.
3854
3883
  */
3855
- handleClient(socket) {
3856
- this.clients.add(socket);
3857
- let buffer = "";
3858
- socket.on("data", (data) => {
3859
- buffer += data.toString("utf8");
3860
- let newlineIndex;
3861
- while ((newlineIndex = buffer.indexOf("\n")) !== -1) {
3862
- const line = buffer.slice(0, newlineIndex);
3863
- buffer = buffer.slice(newlineIndex + 1);
3864
- if (line.trim().length === 0) {
3865
- continue;
3866
- }
3867
- try {
3868
- const call = JSON.parse(line);
3869
- this.handleCall(socket, call);
3870
- } catch (error) {
3871
- this.platform.logger.warn("UnixSocketServer: failed to parse message", { error });
3872
- }
3873
- }
3874
- });
3875
- socket.on("close", () => {
3876
- this.clients.delete(socket);
3877
- });
3878
- socket.on("error", (error) => {
3879
- this.platform.logger.warn("UnixSocketServer: client socket error", { error });
3880
- this.clients.delete(socket);
3881
- });
3884
+ getContext() {
3885
+ return this.context;
3882
3886
  }
3883
3887
  /**
3884
- * Handle adapter call from client.
3888
+ * Call a method on the remote adapter (in parent process).
3889
+ *
3890
+ * This method:
3891
+ * 1. Generates a unique request ID
3892
+ * 2. Serializes the method arguments
3893
+ * 3. Sends the call via transport
3894
+ * 4. Waits for response
3895
+ * 5. Deserializes and returns the result (or throws error)
3896
+ *
3897
+ * @param method - Method name to call on the adapter
3898
+ * @param args - Method arguments (will be serialized)
3899
+ * @param timeout - Optional timeout in milliseconds (overrides transport default)
3900
+ * @returns Promise resolving to deserialized result
3901
+ * @throws Error if remote method throws or communication fails
3902
+ *
3903
+ * @example
3904
+ * ```typescript
3905
+ * // In VectorStoreProxy.search():
3906
+ * return this.callRemote('search', [query, limit, filter]);
3907
+ *
3908
+ * // With custom timeout for bulk operations:
3909
+ * return this.callRemote('upsert', [vectors], 120000); // 2 min timeout
3910
+ * ```
3885
3911
  */
3886
- async handleCall(socket, call) {
3887
- const callAuthToken = call.context?.authToken;
3888
- if (this.authToken && callAuthToken !== this.authToken) {
3889
- const response = {
3890
- type: "adapter:response",
3891
- requestId: call.requestId,
3892
- error: toSerializableError(new Error("Unauthorized IPC call: invalid auth token"))
3893
- };
3894
- socket.write(JSON.stringify(response) + "\n", "utf8");
3895
- return;
3896
- }
3897
- if (call.version !== IPC_PROTOCOL_VERSION) {
3898
- this.platform.logger.warn("UnixSocketServer: protocol version mismatch", {
3899
- received: call.version,
3900
- expected: IPC_PROTOCOL_VERSION,
3901
- adapter: call.adapter,
3902
- method: call.method,
3903
- note: "Child process may be using outdated protocol. Consider rebuilding."
3904
- });
3912
+ async callRemote(method, args, timeout) {
3913
+ const requestId = crypto.randomUUID();
3914
+ const call = {
3915
+ version: IPC_PROTOCOL_VERSION,
3916
+ // Protocol version for backward compatibility
3917
+ type: "adapter:call",
3918
+ requestId,
3919
+ adapter: this.adapterName,
3920
+ method,
3921
+ args: args.map((arg) => serialize(arg)),
3922
+ timeout,
3923
+ // Optional timeout for this specific call
3924
+ context: this.context
3925
+ // Include execution context for tracing/debugging
3926
+ };
3927
+ const response = await this.transport.send(call);
3928
+ if (response.error) {
3929
+ throw deserialize(response.error);
3905
3930
  }
3906
- if (call.context) {
3907
- this.platform.logger.debug("UnixSocketServer: adapter call", {
3908
- version: call.version,
3909
- traceId: call.context.traceId,
3910
- pluginId: call.context.pluginId,
3911
- sessionId: call.context.sessionId,
3912
- tenantId: call.context.tenantId,
3913
- adapter: call.adapter,
3914
- method: call.method
3915
- });
3931
+ if (response.result === void 0) {
3932
+ return void 0;
3916
3933
  }
3917
- try {
3918
- const adapter = this.getAdapter(call.adapter);
3919
- if (adapter === null || typeof adapter !== "object" && typeof adapter !== "function") {
3920
- throw new Error(`Adapter '${call.adapter}' is not callable`);
3921
- }
3922
- const method = Reflect.get(adapter, call.method);
3923
- if (typeof method !== "function") {
3924
- throw new Error(
3925
- `Method '${call.method}' not found on adapter '${call.adapter}'. Available methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(adapter)).join(", ")}`
3926
- );
3927
- }
3928
- const args = await Promise.all(
3929
- call.args.map(async (arg) => {
3930
- const deserialized = deserialize(arg);
3931
- if (BulkTransferHelper.isBulkTransfer(deserialized)) {
3932
- return BulkTransferHelper.deserialize(deserialized);
3933
- }
3934
- return deserialized;
3935
- })
3936
- );
3937
- const result = await method.apply(adapter, args);
3938
- let serializedResult;
3939
- if (result !== void 0 && result !== null && typeof result === "object") {
3940
- const resultJson = JSON.stringify(result);
3941
- if (resultJson.length > 1e6) {
3942
- const transfer = await BulkTransferHelper.serialize(result, {
3943
- maxInlineSize: 1e6,
3944
- tempDir: process.env.KB_TEMP_DIR ?? os__namespace.tmpdir()
3945
- });
3946
- serializedResult = serialize(transfer);
3947
- } else {
3948
- serializedResult = serialize(result);
3949
- }
3950
- } else {
3951
- serializedResult = serialize(result);
3952
- }
3953
- const response = {
3954
- type: "adapter:response",
3955
- requestId: call.requestId,
3956
- result: serializedResult
3957
- };
3958
- const message = JSON.stringify(response) + "\n";
3959
- socket.write(message, "utf8");
3960
- } catch (error) {
3961
- const response = {
3962
- type: "adapter:response",
3963
- requestId: call.requestId,
3964
- error: toSerializableError(error)
3965
- };
3966
- const message = JSON.stringify(response) + "\n";
3967
- socket.write(message, "utf8");
3968
- const cause = error instanceof Error ? error.message : String(error);
3969
- this.platform.logger.error(
3970
- `UnixSocketServer: ${call.adapter}.${call.method} failed \u2014 ${cause}`,
3971
- error instanceof Error ? error : new Error(String(error)),
3972
- { adapter: call.adapter, method: call.method }
3973
- );
3934
+ const result = deserialize(response.result);
3935
+ if (BulkTransferHelper.isBulkTransfer(result)) {
3936
+ return BulkTransferHelper.deserialize(result);
3974
3937
  }
3938
+ return result;
3975
3939
  }
3976
3940
  /**
3977
- * Get adapter instance from platform container.
3978
- *
3979
- * @param name - Adapter name (e.g., 'vectorStore', 'cache')
3980
- * @returns Adapter instance
3981
- * @throws Error if adapter not found
3941
+ * Get the adapter name this proxy represents.
3982
3942
  */
3983
- getAdapter(name) {
3984
- switch (name) {
3985
- case "vectorStore":
3986
- return this.platform.vectorStore;
3987
- case "cache":
3988
- return this.platform.cache;
3989
- case "config":
3990
- return this.platform.config;
3991
- case "llm":
3992
- return this.platform.llm;
3993
- case "embeddings":
3994
- return this.platform.embeddings;
3995
- case "storage":
3996
- return this.platform.storage;
3997
- case "logger":
3998
- return this.platform.logger;
3999
- case "analytics":
4000
- return this.platform.analytics;
4001
- case "eventBus":
4002
- return this.platform.eventBus;
4003
- case "processExecutor":
4004
- if (!this.platform.processExecutor) {
4005
- throw new Error("Governed process executor is not configured on execution host");
4006
- }
4007
- return this.platform.processExecutor;
4008
- case "invoke":
4009
- return this.platform.invoke;
4010
- default:
4011
- throw new Error(
4012
- `Unknown adapter: '${name}'. Valid adapters: vectorStore, cache, config, llm, embeddings, storage, logger, analytics, eventBus, invoke, processExecutor`
4013
- );
4014
- }
3943
+ getAdapterName() {
3944
+ return this.adapterName;
4015
3945
  }
4016
3946
  /**
4017
- * Stop server and close all connections.
3947
+ * Get the transport used by this proxy.
3948
+ * Useful for advanced use cases (e.g., checking if transport is closed).
4018
3949
  */
4019
- async close() {
4020
- if (!this.started) {
4021
- return;
4022
- }
4023
- for (const client of this.clients) {
4024
- client.destroy();
4025
- }
4026
- this.clients.clear();
4027
- if (this.server) {
4028
- await new Promise((resolve6) => {
4029
- this.server.close(() => {
4030
- resolve6();
4031
- });
4032
- });
4033
- this.server = null;
4034
- }
4035
- if (fs5__namespace.existsSync(this.socketPath)) {
4036
- fs5__namespace.unlinkSync(this.socketPath);
4037
- }
4038
- this.started = false;
4039
- this.platform.logger.debug("UnixSocketServer stopped listening for adapter calls");
3950
+ getTransport() {
3951
+ return this.transport;
3952
+ }
3953
+ };
3954
+ DocumentDatabaseProxy = class extends RemoteAdapter {
3955
+ constructor(transport) {
3956
+ super("database.document", transport);
3957
+ }
3958
+ async find(collection, filter, options) {
3959
+ return await this.callRemote("find", [collection, filter, stripSignal(options)]);
3960
+ }
3961
+ // eslint-disable-next-line require-yield
3962
+ async *findStream(_collection, _filter, _options) {
3963
+ throw new Error(
3964
+ "findStream() is not supported over IPC. Use bounded find({ limit }) and paginate explicitly."
3965
+ );
3966
+ }
3967
+ async findById(collection, id, _options) {
3968
+ return await this.callRemote("findById", [collection, id]);
3969
+ }
3970
+ async count(collection, filter, _options) {
3971
+ return await this.callRemote("count", [collection, filter]);
3972
+ }
3973
+ async insertOne(collection, doc, _options) {
3974
+ return await this.callRemote("insertOne", [collection, doc]);
3975
+ }
3976
+ async insertMany(collection, docs, _options) {
3977
+ return await this.callRemote("insertMany", [collection, docs]);
3978
+ }
3979
+ async updateOne(collection, filter, update, options) {
3980
+ return await this.callRemote("updateOne", [
3981
+ collection,
3982
+ filter,
3983
+ update,
3984
+ { upsert: options?.upsert }
3985
+ ]);
3986
+ }
3987
+ async updateMany(collection, filter, update, _options) {
3988
+ return await this.callRemote("updateMany", [collection, filter, update]);
3989
+ }
3990
+ async updateById(collection, id, update, _options) {
3991
+ return await this.callRemote("updateById", [collection, id, update]);
3992
+ }
3993
+ async deleteMany(collection, filter, _options) {
3994
+ return await this.callRemote("deleteMany", [collection, filter]);
3995
+ }
3996
+ async deleteById(collection, id, _options) {
3997
+ return await this.callRemote("deleteById", [collection, id]);
3998
+ }
3999
+ async bulkWrite(collection, ops, _options) {
4000
+ return await this.callRemote("bulkWrite", [collection, ops]);
4001
+ }
4002
+ async transaction(_fn) {
4003
+ throw new Error(
4004
+ "transaction() is not supported over IPC. Collect your writes into a single bulkWrite() instead."
4005
+ );
4006
+ }
4007
+ async ensureCollection(name, options) {
4008
+ await this.callRemote("ensureCollection", [name, options]);
4009
+ }
4010
+ async ping() {
4011
+ return await this.callRemote("ping", []);
4012
+ }
4013
+ async close(options) {
4014
+ await this.callRemote("close", [options]);
4015
+ }
4016
+ };
4017
+ stripSignal = (options) => {
4018
+ if (!options) {
4019
+ return void 0;
4020
+ }
4021
+ const { signal: _signal, ...rest } = options;
4022
+ return rest;
4023
+ };
4024
+ KVStoreProxy = class extends RemoteAdapter {
4025
+ constructor(transport) {
4026
+ super("database.kv", transport);
4027
+ }
4028
+ async get(key, _options) {
4029
+ return await this.callRemote("get", [key]);
4030
+ }
4031
+ async getMany(keys, _options) {
4032
+ return await this.callRemote("getMany", [keys]);
4033
+ }
4034
+ async set(key, value, options) {
4035
+ return await this.callRemote("set", [key, value, stripSignal2(options)]);
4036
+ }
4037
+ async setMany(entries, _options) {
4038
+ await this.callRemote("setMany", [entries]);
4039
+ }
4040
+ async setIfNotExists(key, value, options) {
4041
+ return await this.callRemote("setIfNotExists", [key, value, stripSignal2(options)]);
4042
+ }
4043
+ async delete(key, _options) {
4044
+ return await this.callRemote("delete", [key]);
4045
+ }
4046
+ async exists(key, _options) {
4047
+ return await this.callRemote("exists", [key]);
4048
+ }
4049
+ async cas(key, expected, next, options) {
4050
+ return await this.callRemote("cas", [key, expected, next, stripSignal2(options)]);
4051
+ }
4052
+ async incr(key, delta, options) {
4053
+ return await this.callRemote("incr", [key, delta, stripSignal2(options)]);
4054
+ }
4055
+ async ttl(key) {
4056
+ return await this.callRemote("ttl", [key]);
4057
+ }
4058
+ async expire(key, ttlMs) {
4059
+ return await this.callRemote("expire", [key, ttlMs]);
4060
+ }
4061
+ async persist(key) {
4062
+ return await this.callRemote("persist", [key]);
4063
+ }
4064
+ // eslint-disable-next-line require-yield
4065
+ async *scan(_prefix, _options) {
4066
+ throw new Error("scan() is not supported over IPC. Use bounded getMany() with an explicit key list.");
4067
+ }
4068
+ async ping() {
4069
+ return await this.callRemote("ping", []);
4070
+ }
4071
+ async close(options) {
4072
+ await this.callRemote("close", [options]);
4073
+ }
4074
+ };
4075
+ stripSignal2 = (options) => {
4076
+ if (!options) {
4077
+ return void 0;
4040
4078
  }
4079
+ const { signal: _signal, ...rest } = options;
4080
+ return rest;
4081
+ };
4082
+ CacheProxy = class extends RemoteAdapter {
4041
4083
  /**
4042
- * Check if server is started.
4084
+ * Create a cache proxy.
4085
+ *
4086
+ * @param transport - IPC transport to communicate with parent
4043
4087
  */
4044
- isStarted() {
4045
- return this.started;
4088
+ constructor(transport) {
4089
+ super("cache", transport);
4046
4090
  }
4047
- };
4048
- IPCServer = class {
4049
4091
  /**
4050
- * Create an IPC server.
4092
+ * Get a value from cache.
4051
4093
  *
4052
- * @param platform - Platform container with real adapters
4094
+ * @param key - Cache key
4095
+ * @returns Cached value or null if not found/expired
4053
4096
  */
4054
- constructor(platform2) {
4055
- this.platform = platform2;
4056
- this.messageHandler = this.handleMessage.bind(this);
4097
+ async get(key) {
4098
+ return await this.callRemote("get", [key]);
4057
4099
  }
4058
- platform;
4059
- messageHandler;
4060
- started = false;
4061
4100
  /**
4062
- * Start listening for IPC messages.
4101
+ * Set a value in cache.
4063
4102
  *
4064
- * Call this in the parent process (CLI bin) after initPlatform().
4065
- * The server will handle all adapter calls from child processes.
4103
+ * @param key - Cache key
4104
+ * @param value - Value to cache
4105
+ * @param ttl - Time to live in milliseconds (optional)
4106
+ */
4107
+ async set(key, value, ttl) {
4108
+ await this.callRemote("set", [key, value, ttl]);
4109
+ }
4110
+ /**
4111
+ * Delete a value from cache.
4066
4112
  *
4067
- * @throws Error if already started
4068
- * @throws Error if not running in parent process with IPC
4113
+ * @param key - Cache key
4069
4114
  */
4070
- start() {
4071
- if (this.started) {
4072
- throw new Error("IPCServer already started");
4073
- }
4074
- if (typeof process.on !== "function") {
4075
- throw new Error("IPCServer requires Node.js process object");
4076
- }
4077
- process.on("message", this.messageHandler);
4078
- this.started = true;
4079
- this.platform.logger.debug("IPCServer started listening for adapter calls");
4115
+ async delete(key) {
4116
+ await this.callRemote("delete", [key]);
4080
4117
  }
4081
4118
  /**
4082
- * Stop listening for IPC messages.
4119
+ * Clear cache entries matching a pattern.
4083
4120
  *
4084
- * Removes the message listener. Pending calls will not receive responses.
4121
+ * @param pattern - Glob pattern (e.g., 'user:*')
4085
4122
  */
4086
- stop() {
4087
- if (!this.started) {
4088
- return;
4089
- }
4090
- process.off("message", this.messageHandler);
4091
- this.started = false;
4092
- this.platform.logger.debug("IPCServer stopped listening for adapter calls");
4123
+ async clear(pattern) {
4124
+ await this.callRemote("clear", [pattern]);
4093
4125
  }
4094
4126
  /**
4095
- * Handle incoming IPC message.
4127
+ * Add member to sorted set with score.
4096
4128
  *
4097
- * Validates message format, executes adapter call, and sends response.
4129
+ * @param key - Sorted set key
4130
+ * @param score - Numeric score (typically timestamp)
4131
+ * @param member - Member to add
4132
+ */
4133
+ async zadd(key, score, member) {
4134
+ await this.callRemote("zadd", [key, score, member]);
4135
+ }
4136
+ /**
4137
+ * Get members from sorted set by score range.
4138
+ *
4139
+ * @param key - Sorted set key
4140
+ * @param min - Minimum score (inclusive)
4141
+ * @param max - Maximum score (inclusive)
4142
+ * @returns Array of members in score order
4143
+ */
4144
+ async zrangebyscore(key, min, max) {
4145
+ return await this.callRemote("zrangebyscore", [key, min, max]);
4146
+ }
4147
+ /**
4148
+ * Remove member from sorted set.
4149
+ *
4150
+ * @param key - Sorted set key
4151
+ * @param member - Member to remove
4152
+ */
4153
+ async zrem(key, member) {
4154
+ await this.callRemote("zrem", [key, member]);
4155
+ }
4156
+ /**
4157
+ * Set key-value pair only if key does not exist (atomic operation).
4158
+ *
4159
+ * @param key - Cache key
4160
+ * @param value - Value to set
4161
+ * @param ttl - Time to live in milliseconds (optional)
4162
+ * @returns true if value was set, false if key already exists
4163
+ */
4164
+ async setIfNotExists(key, value, ttl) {
4165
+ return await this.callRemote("setIfNotExists", [key, value, ttl]);
4166
+ }
4167
+ };
4168
+ ConfigProxy = class extends RemoteAdapter {
4169
+ /**
4170
+ * Create a config proxy.
4171
+ *
4172
+ * @param transport - IPC transport to communicate with parent
4173
+ */
4174
+ constructor(transport) {
4175
+ super("config", transport);
4176
+ }
4177
+ /**
4178
+ * Get product-specific configuration.
4179
+ *
4180
+ * @param productId - Product identifier (e.g., 'mind', 'workflow', 'plugins')
4181
+ * @param profileId - Profile identifier (defaults to 'default' or KB_PROFILE env var)
4182
+ * @returns Promise resolving to product-specific config or undefined
4183
+ *
4184
+ * @example
4185
+ * ```typescript
4186
+ * const mindConfig = await config.getConfig('mind');
4187
+ * if (mindConfig?.scopes) {
4188
+ * // Use scopes
4189
+ * }
4190
+ * ```
4191
+ */
4192
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4193
+ async getConfig(productId, profileId) {
4194
+ return this.callRemote("getConfig", [productId, profileId]);
4195
+ }
4196
+ /**
4197
+ * Get raw kb.config.json data.
4198
+ *
4199
+ * @returns Promise resolving to raw config object or undefined
4200
+ *
4201
+ * @example
4202
+ * ```typescript
4203
+ * const rawConfig = await config.getRawConfig();
4204
+ * if (rawConfig) {
4205
+ * const allProfiles = rawConfig.profiles;
4206
+ * }
4207
+ * ```
4208
+ */
4209
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4210
+ async getRawConfig() {
4211
+ return this.callRemote("getRawConfig", []);
4212
+ }
4213
+ };
4214
+ VectorStoreProxy = class _VectorStoreProxy extends RemoteAdapter {
4215
+ // Timeout for bulk operations that may trigger IPC backpressure
4216
+ static BULK_OPERATION_TIMEOUT = 12e4;
4217
+ // 2 minutes
4218
+ // BulkTransfer configuration
4219
+ bulkTransferOptions = {
4220
+ maxInlineSize: 1e6,
4221
+ // 1MB threshold
4222
+ tempDir: process.env.KB_TEMP_DIR ?? os.tmpdir()
4223
+ };
4224
+ /**
4225
+ * Create a vector store proxy.
4226
+ *
4227
+ * @param transport - IPC transport to communicate with parent
4228
+ */
4229
+ constructor(transport) {
4230
+ super("vectorStore", transport);
4231
+ }
4232
+ /**
4233
+ * Search for similar vectors.
4234
+ *
4235
+ * @param query - Query embedding vector
4236
+ * @param limit - Maximum number of results
4237
+ * @param filter - Optional metadata filter
4238
+ * @returns Promise resolving to search results
4239
+ */
4240
+ async search(query, limit, filter, namespace) {
4241
+ return await this.callRemote("search", [query, limit, filter, namespace]);
4242
+ }
4243
+ /**
4244
+ * Insert or update vectors.
4245
+ * Uses BulkTransfer for large payloads to avoid IPC backpressure.
4246
+ *
4247
+ * @param vectors - Vector records to upsert
4248
+ */
4249
+ async upsert(vectors, namespace) {
4250
+ const transfer = await BulkTransferHelper.serialize(vectors, this.bulkTransferOptions);
4251
+ await this.callRemote("upsert", [transfer, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
4252
+ }
4253
+ /**
4254
+ * Delete vectors by IDs.
4255
+ * Uses extended timeout for bulk deletions.
4256
+ *
4257
+ * @param ids - Vector IDs to delete
4258
+ */
4259
+ async delete(ids, namespace) {
4260
+ await this.callRemote("delete", [ids, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
4261
+ }
4262
+ /**
4263
+ * Count total vectors in collection.
4264
+ *
4265
+ * @returns Promise resolving to vector count
4266
+ */
4267
+ async count(namespace) {
4268
+ return await this.callRemote("count", [namespace]);
4269
+ }
4270
+ /**
4271
+ * Get vectors by IDs.
4272
+ * IDs argument is usually small, passed directly through IPC.
4273
+ * Uses BulkTransfer only for large result sets.
4274
+ *
4275
+ * @param ids - Vector IDs to retrieve
4276
+ * @returns Promise resolving to vector records
4277
+ */
4278
+ async get(ids, namespace) {
4279
+ const resultTransfer = await this.callRemote("get", [ids, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
4280
+ if (BulkTransferHelper.isBulkTransfer(resultTransfer)) {
4281
+ return BulkTransferHelper.deserialize(resultTransfer);
4282
+ }
4283
+ return resultTransfer;
4284
+ }
4285
+ /**
4286
+ * Query vectors by metadata filter.
4287
+ * Filter argument is small, passed directly through IPC.
4288
+ * Uses BulkTransfer only for potentially large result sets.
4289
+ *
4290
+ * @param filter - Metadata filter to apply
4291
+ * @returns Promise resolving to matching vector records
4292
+ */
4293
+ async query(filter, namespace) {
4294
+ const resultTransfer = await this.callRemote("query", [filter, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
4295
+ if (BulkTransferHelper.isBulkTransfer(resultTransfer)) {
4296
+ return BulkTransferHelper.deserialize(resultTransfer);
4297
+ }
4298
+ return resultTransfer;
4299
+ }
4300
+ };
4301
+ InvokeProxy = class extends RemoteAdapter {
4302
+ constructor(transport) {
4303
+ super("invoke", transport);
4304
+ }
4305
+ async call(request) {
4306
+ return await this.callRemote("call", [request]);
4307
+ }
4308
+ async isAvailable(pluginId, command) {
4309
+ return await this.callRemote("isAvailable", [pluginId, command]);
4310
+ }
4311
+ };
4312
+ documentDatabaseIPCOperations = defineIPCOperations()({
4313
+ find: "unary",
4314
+ findStream: "stream",
4315
+ findById: "unary",
4316
+ count: "unary",
4317
+ insertOne: "unary",
4318
+ insertMany: "unary",
4319
+ updateOne: "unary",
4320
+ updateMany: "unary",
4321
+ updateById: "unary",
4322
+ deleteMany: "unary",
4323
+ deleteById: "unary",
4324
+ bulkWrite: "unary",
4325
+ transaction: "interactive",
4326
+ ensureCollection: "unary",
4327
+ ping: "unary",
4328
+ close: "unary"
4329
+ });
4330
+ kvStoreIPCOperations = defineIPCOperations()({
4331
+ get: "unary",
4332
+ getMany: "unary",
4333
+ set: "unary",
4334
+ setMany: "unary",
4335
+ setIfNotExists: "unary",
4336
+ delete: "unary",
4337
+ exists: "unary",
4338
+ cas: "unary",
4339
+ incr: "unary",
4340
+ ttl: "unary",
4341
+ expire: "unary",
4342
+ persist: "unary",
4343
+ scan: "stream",
4344
+ ping: "unary",
4345
+ close: "unary"
4346
+ });
4347
+ cacheIPCOperations = defineIPCOperations()({
4348
+ get: "unary",
4349
+ set: "unary",
4350
+ delete: "unary",
4351
+ clear: "unary",
4352
+ zadd: "unary",
4353
+ zrangebyscore: "unary",
4354
+ zrem: "unary",
4355
+ setIfNotExists: "unary"
4356
+ });
4357
+ configIPCOperations = defineIPCOperations()({
4358
+ getConfig: "unary",
4359
+ getRawConfig: "unary"
4360
+ });
4361
+ vectorStoreIPCOperations = defineIPCOperations()({
4362
+ search: "unary",
4363
+ upsert: "unary",
4364
+ delete: "unary",
4365
+ count: "unary",
4366
+ get: "unary",
4367
+ query: "unary"
4368
+ });
4369
+ invokeIPCOperations = defineIPCOperations()({
4370
+ call: "unary",
4371
+ isAvailable: "unary"
4372
+ });
4373
+ platformAdapterTransportPolicy = {
4374
+ logger: {
4375
+ mode: "migration",
4376
+ adapter: "logger",
4377
+ reason: "LoggerProxy is wired but still has fire-and-forget delivery semantics."
4378
+ },
4379
+ analytics: {
4380
+ mode: "migration",
4381
+ adapter: "analytics",
4382
+ reason: "Optional read and source-management operations need a capability-aware IPC design."
4383
+ },
4384
+ vectorStore: {
4385
+ mode: "ipc",
4386
+ adapter: "vectorStore",
4387
+ operations: vectorStoreIPCOperations,
4388
+ proxy: createVectorStoreProxy
4389
+ },
4390
+ llm: {
4391
+ mode: "migration",
4392
+ adapter: "llm",
4393
+ reason: "Streaming currently degrades to a completion over IPC."
4394
+ },
4395
+ embeddings: {
4396
+ mode: "migration",
4397
+ adapter: "embeddings",
4398
+ reason: "The dimensions property requires out-of-band initialization in the proxy."
4399
+ },
4400
+ cache: {
4401
+ mode: "ipc",
4402
+ adapter: "cache",
4403
+ operations: cacheIPCOperations,
4404
+ proxy: createCacheProxy
4405
+ },
4406
+ config: {
4407
+ mode: "ipc",
4408
+ adapter: "config",
4409
+ operations: configIPCOperations,
4410
+ proxy: createConfigProxy
4411
+ },
4412
+ storage: {
4413
+ mode: "migration",
4414
+ adapter: "storage",
4415
+ reason: "Node streams are not serializable over the current IPC protocol."
4416
+ },
4417
+ eventBus: {
4418
+ mode: "migration",
4419
+ adapter: "eventBus",
4420
+ reason: "Subscriptions use a dedicated push-message protocol."
4421
+ },
4422
+ invoke: {
4423
+ mode: "ipc",
4424
+ adapter: "invoke",
4425
+ operations: invokeIPCOperations,
4426
+ proxy: createInvokeProxy
4427
+ },
4428
+ documentDatabase: {
4429
+ mode: "ipc",
4430
+ adapter: "database.document",
4431
+ operations: documentDatabaseIPCOperations,
4432
+ proxy: createDocumentDatabaseProxy
4433
+ },
4434
+ kvStore: {
4435
+ mode: "ipc",
4436
+ adapter: "database.kv",
4437
+ operations: kvStoreIPCOperations,
4438
+ proxy: createKVStoreProxy
4439
+ },
4440
+ logs: {
4441
+ mode: "local-only",
4442
+ reason: "Log queries are intentionally unavailable to worker processes."
4443
+ },
4444
+ artifacts: {
4445
+ mode: "migration",
4446
+ adapter: "artifacts",
4447
+ reason: "Artifacts have a wire route but no worker proxy yet."
4448
+ },
4449
+ snapshotManager: {
4450
+ mode: "local-only",
4451
+ reason: "Snapshot lifecycle is owned by the execution host."
4452
+ },
4453
+ notifier: {
4454
+ mode: "local-only",
4455
+ reason: "Notifications are emitted by the host after worker execution."
4456
+ },
4457
+ processExecutor: {
4458
+ mode: "migration",
4459
+ adapter: "processExecutor",
4460
+ reason: "Existing proxy must be moved to a checked operation inventory."
4461
+ },
4462
+ serviceTransport: {
4463
+ mode: "local-only",
4464
+ reason: "Service transport is a platform-internal adapter and never enters plugin context."
4465
+ }
4466
+ };
4467
+ IPC_ADAPTER_ROUTES = createIPCAdapterRoutes();
4468
+ UnixSocketServer = class {
4469
+ /**
4470
+ * Create a Unix Socket server.
4471
+ *
4472
+ * @param platform - Platform container with real adapters
4473
+ * @param config - Server configuration
4474
+ */
4475
+ constructor(platform2, config = {}) {
4476
+ this.platform = platform2;
4477
+ this.socketPath = config.socketPath ?? DEFAULT_SOCKET_PATH;
4478
+ this.authToken = config.authToken;
4479
+ }
4480
+ platform;
4481
+ server = null;
4482
+ clients = /* @__PURE__ */ new Set();
4483
+ socketPath;
4484
+ authToken;
4485
+ started = false;
4486
+ /**
4487
+ * Get the socket path.
4488
+ * Used by parent process to pass to child processes via env var.
4489
+ */
4490
+ getSocketPath() {
4491
+ return this.socketPath;
4492
+ }
4493
+ /**
4494
+ * Start listening for connections.
4495
+ */
4496
+ async start() {
4497
+ BulkTransferHelper.registerSignalHandlers();
4498
+ if (fs5__namespace.existsSync(this.socketPath)) {
4499
+ fs5__namespace.unlinkSync(this.socketPath);
4500
+ }
4501
+ return new Promise((resolve6, reject) => {
4502
+ this.server = net__namespace.createServer((socket) => {
4503
+ this.handleClient(socket);
4504
+ });
4505
+ this.server.on("error", (error) => {
4506
+ reject(error);
4507
+ });
4508
+ this.server.listen(this.socketPath, () => {
4509
+ fs5__namespace.chmodSync(this.socketPath, 438);
4510
+ this.started = true;
4511
+ this.platform.logger.debug("UnixSocketServer started listening for adapter calls");
4512
+ resolve6();
4513
+ });
4514
+ });
4515
+ }
4516
+ /**
4517
+ * Handle new client connection.
4518
+ */
4519
+ handleClient(socket) {
4520
+ this.clients.add(socket);
4521
+ let buffer = "";
4522
+ socket.on("data", (data) => {
4523
+ buffer += data.toString("utf8");
4524
+ let newlineIndex;
4525
+ while ((newlineIndex = buffer.indexOf("\n")) !== -1) {
4526
+ const line = buffer.slice(0, newlineIndex);
4527
+ buffer = buffer.slice(newlineIndex + 1);
4528
+ if (line.trim().length === 0) {
4529
+ continue;
4530
+ }
4531
+ try {
4532
+ const call = JSON.parse(line);
4533
+ this.handleCall(socket, call);
4534
+ } catch (error) {
4535
+ this.platform.logger.warn("UnixSocketServer: failed to parse message", { error });
4536
+ }
4537
+ }
4538
+ });
4539
+ socket.on("close", () => {
4540
+ this.clients.delete(socket);
4541
+ });
4542
+ socket.on("error", (error) => {
4543
+ this.platform.logger.warn("UnixSocketServer: client socket error", { error });
4544
+ this.clients.delete(socket);
4545
+ });
4546
+ }
4547
+ /**
4548
+ * Handle adapter call from client.
4549
+ */
4550
+ async handleCall(socket, call) {
4551
+ const callAuthToken = call.context?.authToken;
4552
+ if (this.authToken && callAuthToken !== this.authToken) {
4553
+ const response = {
4554
+ type: "adapter:response",
4555
+ requestId: call.requestId,
4556
+ error: toSerializableError(new Error("Unauthorized IPC call: invalid auth token"))
4557
+ };
4558
+ socket.write(JSON.stringify(response) + "\n", "utf8");
4559
+ return;
4560
+ }
4561
+ if (call.version !== IPC_PROTOCOL_VERSION) {
4562
+ this.platform.logger.warn("UnixSocketServer: protocol version mismatch", {
4563
+ received: call.version,
4564
+ expected: IPC_PROTOCOL_VERSION,
4565
+ adapter: call.adapter,
4566
+ method: call.method,
4567
+ note: "Child process may be using outdated protocol. Consider rebuilding."
4568
+ });
4569
+ }
4570
+ if (call.context) {
4571
+ this.platform.logger.debug("UnixSocketServer: adapter call", {
4572
+ version: call.version,
4573
+ traceId: call.context.traceId,
4574
+ pluginId: call.context.pluginId,
4575
+ sessionId: call.context.sessionId,
4576
+ tenantId: call.context.tenantId,
4577
+ adapter: call.adapter,
4578
+ method: call.method
4579
+ });
4580
+ }
4581
+ try {
4582
+ const adapter = resolveIPCAdapter(this.platform, call.adapter);
4583
+ if (adapter === null || typeof adapter !== "object" && typeof adapter !== "function") {
4584
+ throw new Error(`Adapter '${call.adapter}' is not callable`);
4585
+ }
4586
+ const method = Reflect.get(adapter, call.method);
4587
+ if (typeof method !== "function") {
4588
+ throw new Error(
4589
+ `Method '${call.method}' not found on adapter '${call.adapter}'. Available methods: ${Object.getOwnPropertyNames(Object.getPrototypeOf(adapter)).join(", ")}`
4590
+ );
4591
+ }
4592
+ const args = await Promise.all(
4593
+ call.args.map(async (arg) => {
4594
+ const deserialized = deserialize(arg);
4595
+ if (BulkTransferHelper.isBulkTransfer(deserialized)) {
4596
+ return BulkTransferHelper.deserialize(deserialized);
4597
+ }
4598
+ return deserialized;
4599
+ })
4600
+ );
4601
+ const result = await method.apply(adapter, args);
4602
+ let serializedResult;
4603
+ if (result !== void 0 && result !== null && typeof result === "object") {
4604
+ const resultJson = JSON.stringify(result);
4605
+ if (resultJson.length > 1e6) {
4606
+ const transfer = await BulkTransferHelper.serialize(result, {
4607
+ maxInlineSize: 1e6,
4608
+ tempDir: process.env.KB_TEMP_DIR ?? os__namespace.tmpdir()
4609
+ });
4610
+ serializedResult = serialize(transfer);
4611
+ } else {
4612
+ serializedResult = serialize(result);
4613
+ }
4614
+ } else {
4615
+ serializedResult = serialize(result);
4616
+ }
4617
+ const response = {
4618
+ type: "adapter:response",
4619
+ requestId: call.requestId,
4620
+ result: serializedResult
4621
+ };
4622
+ const message = JSON.stringify(response) + "\n";
4623
+ socket.write(message, "utf8");
4624
+ } catch (error) {
4625
+ const response = {
4626
+ type: "adapter:response",
4627
+ requestId: call.requestId,
4628
+ error: toSerializableError(error)
4629
+ };
4630
+ const message = JSON.stringify(response) + "\n";
4631
+ socket.write(message, "utf8");
4632
+ const cause = error instanceof Error ? error.message : String(error);
4633
+ this.platform.logger.error(
4634
+ `UnixSocketServer: ${call.adapter}.${call.method} failed \u2014 ${cause}`,
4635
+ error instanceof Error ? error : new Error(String(error)),
4636
+ { adapter: call.adapter, method: call.method }
4637
+ );
4638
+ }
4639
+ }
4640
+ /**
4641
+ * Stop server and close all connections.
4642
+ */
4643
+ async close() {
4644
+ if (!this.started) {
4645
+ return;
4646
+ }
4647
+ for (const client of this.clients) {
4648
+ client.destroy();
4649
+ }
4650
+ this.clients.clear();
4651
+ if (this.server) {
4652
+ await new Promise((resolve6) => {
4653
+ this.server.close(() => {
4654
+ resolve6();
4655
+ });
4656
+ });
4657
+ this.server = null;
4658
+ }
4659
+ if (fs5__namespace.existsSync(this.socketPath)) {
4660
+ fs5__namespace.unlinkSync(this.socketPath);
4661
+ }
4662
+ this.started = false;
4663
+ this.platform.logger.debug("UnixSocketServer stopped listening for adapter calls");
4664
+ }
4665
+ /**
4666
+ * Check if server is started.
4667
+ */
4668
+ isStarted() {
4669
+ return this.started;
4670
+ }
4671
+ };
4672
+ IPCServer = class {
4673
+ /**
4674
+ * Create an IPC server.
4675
+ *
4676
+ * @param platform - Platform container with real adapters
4677
+ */
4678
+ constructor(platform2) {
4679
+ this.platform = platform2;
4680
+ this.messageHandler = this.handleMessage.bind(this);
4681
+ }
4682
+ platform;
4683
+ messageHandler;
4684
+ started = false;
4685
+ /**
4686
+ * Start listening for IPC messages.
4687
+ *
4688
+ * Call this in the parent process (CLI bin) after initPlatform().
4689
+ * The server will handle all adapter calls from child processes.
4690
+ *
4691
+ * @throws Error if already started
4692
+ * @throws Error if not running in parent process with IPC
4693
+ */
4694
+ start() {
4695
+ if (this.started) {
4696
+ throw new Error("IPCServer already started");
4697
+ }
4698
+ if (typeof process.on !== "function") {
4699
+ throw new Error("IPCServer requires Node.js process object");
4700
+ }
4701
+ process.on("message", this.messageHandler);
4702
+ this.started = true;
4703
+ this.platform.logger.debug("IPCServer started listening for adapter calls");
4704
+ }
4705
+ /**
4706
+ * Stop listening for IPC messages.
4707
+ *
4708
+ * Removes the message listener. Pending calls will not receive responses.
4709
+ */
4710
+ stop() {
4711
+ if (!this.started) {
4712
+ return;
4713
+ }
4714
+ process.off("message", this.messageHandler);
4715
+ this.started = false;
4716
+ this.platform.logger.debug("IPCServer stopped listening for adapter calls");
4717
+ }
4718
+ /**
4719
+ * Handle incoming IPC message.
4720
+ *
4721
+ * Validates message format, executes adapter call, and sends response.
4098
4722
  */
4099
4723
  async handleMessage(msg, sendHandle) {
4100
4724
  if (!isAdapterCall(msg)) {
@@ -4121,7 +4745,7 @@ var init_dist5 = __esm({
4121
4745
  });
4122
4746
  }
4123
4747
  try {
4124
- const adapter = this.getAdapter(msg.adapter);
4748
+ const adapter = resolveIPCAdapter(this.platform, msg.adapter);
4125
4749
  const method = adapter[msg.method];
4126
4750
  if (typeof method !== "function") {
4127
4751
  throw new Error(
@@ -4154,44 +4778,6 @@ var init_dist5 = __esm({
4154
4778
  );
4155
4779
  }
4156
4780
  }
4157
- /**
4158
- * Get adapter instance from platform container.
4159
- *
4160
- * @param name - Adapter name (e.g., 'vectorStore', 'cache')
4161
- * @returns Adapter instance
4162
- * @throws Error if adapter not found
4163
- */
4164
- getAdapter(name) {
4165
- switch (name) {
4166
- case "vectorStore":
4167
- return this.platform.vectorStore;
4168
- case "cache":
4169
- return this.platform.cache;
4170
- case "llm":
4171
- return this.platform.llm;
4172
- case "embeddings":
4173
- return this.platform.embeddings;
4174
- case "storage":
4175
- return this.platform.storage;
4176
- case "logger":
4177
- return this.platform.logger;
4178
- case "analytics":
4179
- return this.platform.analytics;
4180
- case "eventBus":
4181
- return this.platform.eventBus;
4182
- case "invoke":
4183
- return this.platform.invoke;
4184
- case "processExecutor":
4185
- if (!this.platform.processExecutor) {
4186
- throw new Error("Governed process executor is not configured on execution host");
4187
- }
4188
- return this.platform.processExecutor;
4189
- default:
4190
- throw new Error(
4191
- `Unknown adapter: '${name}'. Valid adapters: vectorStore, cache, llm, embeddings, storage, logger, analytics, eventBus, invoke, processExecutor`
4192
- );
4193
- }
4194
- }
4195
4781
  /**
4196
4782
  * Check if server is started.
4197
4783
  */
@@ -4279,7 +4865,7 @@ var init_dist5 = __esm({
4279
4865
  return;
4280
4866
  }
4281
4867
  try {
4282
- const adapter = this.getAdapter(msg.adapter);
4868
+ const adapter = resolveIPCAdapter(this.platform, msg.adapter);
4283
4869
  const method = adapter[msg.method];
4284
4870
  if (typeof method !== "function") {
4285
4871
  throw new Error(
@@ -4330,25 +4916,6 @@ var init_dist5 = __esm({
4330
4916
  this.child.send(response);
4331
4917
  }
4332
4918
  }
4333
- /**
4334
- * Get adapter from platform by name.
4335
- * Dynamic dispatch — no hardcoded switch; new adapters in IPlatformAdapters
4336
- * are automatically available without touching this file.
4337
- * The dotted names ('database.document', 'database.kv') are mapped explicitly.
4338
- */
4339
- getAdapter(name) {
4340
- if (name === "database.document") {
4341
- return this.platform.documentDatabase;
4342
- }
4343
- if (name === "database.kv") {
4344
- return this.platform.kvStore;
4345
- }
4346
- const adapter = this.platform[name];
4347
- if (adapter === void 0) {
4348
- throw new Error(`Unknown adapter: '${name}'`);
4349
- }
4350
- return adapter;
4351
- }
4352
4919
  isStarted() {
4353
4920
  return this.started;
4354
4921
  }
@@ -4623,19 +5190,23 @@ Caused by: ${cause.stack}`;
4623
5190
  throw new TransportError("Socket not available");
4624
5191
  }
4625
5192
  const timeout = selectTimeout(call, this.config.timeout);
5193
+ const outboundCall = this.config.authToken ? {
5194
+ ...call,
5195
+ context: { ...call.context, authToken: this.config.authToken }
5196
+ } : call;
4626
5197
  return new Promise((resolve6, reject) => {
4627
5198
  const timer = setTimeout(() => {
4628
5199
  this.pending.delete(call.requestId);
4629
5200
  reject(new TimeoutError(`Adapter call timed out after ${timeout}ms`, timeout));
4630
5201
  }, timeout);
4631
- this.pending.set(call.requestId, { resolve: resolve6, reject, timer });
4632
- const message = JSON.stringify(call) + "\n";
5202
+ this.pending.set(outboundCall.requestId, { resolve: resolve6, reject, timer });
5203
+ const message = JSON.stringify(outboundCall) + "\n";
4633
5204
  const written = this.socket.write(message, "utf8", (error) => {
4634
5205
  if (error) {
4635
- const pending = this.pending.get(call.requestId);
5206
+ const pending = this.pending.get(outboundCall.requestId);
4636
5207
  if (pending) {
4637
5208
  clearTimeout(pending.timer);
4638
- this.pending.delete(call.requestId);
5209
+ this.pending.delete(outboundCall.requestId);
4639
5210
  reject(new TransportError(`Failed to write to socket: ${error.message}`, error));
4640
5211
  }
4641
5212
  }
@@ -4703,202 +5274,9 @@ Caused by: ${cause.stack}`;
4703
5274
  };
4704
5275
  }
4705
5276
  };
4706
- RemoteAdapter = class {
5277
+ LLMProxy = class extends RemoteAdapter {
4707
5278
  /**
4708
- * Create a remote adapter proxy.
4709
- *
4710
- * @param adapterName - Name of the adapter (e.g., 'vectorStore', 'cache')
4711
- * @param transport - Transport layer for IPC communication
4712
- * @param context - Optional execution context for tracing/debugging
4713
- */
4714
- constructor(adapterName, transport, context) {
4715
- this.adapterName = adapterName;
4716
- this.transport = transport;
4717
- this.context = context;
4718
- }
4719
- adapterName;
4720
- transport;
4721
- context;
4722
- /**
4723
- * Set execution context for this adapter.
4724
- * Context is included in all subsequent adapter calls for tracing/debugging.
4725
- *
4726
- * @param context - Execution context (traceId, pluginId, sessionId, etc.)
4727
- *
4728
- * @example
4729
- * ```typescript
4730
- * proxy.setContext({
4731
- * traceId: 'trace-abc',
4732
- * pluginId: '@kb-labs/mind',
4733
- * sessionId: 'session-xyz',
4734
- * });
4735
- * ```
4736
- */
4737
- setContext(context) {
4738
- this.context = context;
4739
- }
4740
- /**
4741
- * Get current execution context.
4742
- */
4743
- getContext() {
4744
- return this.context;
4745
- }
4746
- /**
4747
- * Call a method on the remote adapter (in parent process).
4748
- *
4749
- * This method:
4750
- * 1. Generates a unique request ID
4751
- * 2. Serializes the method arguments
4752
- * 3. Sends the call via transport
4753
- * 4. Waits for response
4754
- * 5. Deserializes and returns the result (or throws error)
4755
- *
4756
- * @param method - Method name to call on the adapter
4757
- * @param args - Method arguments (will be serialized)
4758
- * @param timeout - Optional timeout in milliseconds (overrides transport default)
4759
- * @returns Promise resolving to deserialized result
4760
- * @throws Error if remote method throws or communication fails
4761
- *
4762
- * @example
4763
- * ```typescript
4764
- * // In VectorStoreProxy.search():
4765
- * return this.callRemote('search', [query, limit, filter]);
4766
- *
4767
- * // With custom timeout for bulk operations:
4768
- * return this.callRemote('upsert', [vectors], 120000); // 2 min timeout
4769
- * ```
4770
- */
4771
- async callRemote(method, args, timeout) {
4772
- const requestId = crypto.randomUUID();
4773
- const call = {
4774
- version: IPC_PROTOCOL_VERSION,
4775
- // Protocol version for backward compatibility
4776
- type: "adapter:call",
4777
- requestId,
4778
- adapter: this.adapterName,
4779
- method,
4780
- args: args.map((arg) => serialize(arg)),
4781
- timeout,
4782
- // Optional timeout for this specific call
4783
- context: this.context
4784
- // Include execution context for tracing/debugging
4785
- };
4786
- const response = await this.transport.send(call);
4787
- if (response.error) {
4788
- throw deserialize(response.error);
4789
- }
4790
- if (response.result === void 0) {
4791
- return void 0;
4792
- }
4793
- const result = deserialize(response.result);
4794
- if (BulkTransferHelper.isBulkTransfer(result)) {
4795
- return BulkTransferHelper.deserialize(result);
4796
- }
4797
- return result;
4798
- }
4799
- /**
4800
- * Get the adapter name this proxy represents.
4801
- */
4802
- getAdapterName() {
4803
- return this.adapterName;
4804
- }
4805
- /**
4806
- * Get the transport used by this proxy.
4807
- * Useful for advanced use cases (e.g., checking if transport is closed).
4808
- */
4809
- getTransport() {
4810
- return this.transport;
4811
- }
4812
- };
4813
- CacheProxy = class extends RemoteAdapter {
4814
- /**
4815
- * Create a cache proxy.
4816
- *
4817
- * @param transport - IPC transport to communicate with parent
4818
- */
4819
- constructor(transport) {
4820
- super("cache", transport);
4821
- }
4822
- /**
4823
- * Get a value from cache.
4824
- *
4825
- * @param key - Cache key
4826
- * @returns Cached value or null if not found/expired
4827
- */
4828
- async get(key) {
4829
- return await this.callRemote("get", [key]);
4830
- }
4831
- /**
4832
- * Set a value in cache.
4833
- *
4834
- * @param key - Cache key
4835
- * @param value - Value to cache
4836
- * @param ttl - Time to live in milliseconds (optional)
4837
- */
4838
- async set(key, value, ttl) {
4839
- await this.callRemote("set", [key, value, ttl]);
4840
- }
4841
- /**
4842
- * Delete a value from cache.
4843
- *
4844
- * @param key - Cache key
4845
- */
4846
- async delete(key) {
4847
- await this.callRemote("delete", [key]);
4848
- }
4849
- /**
4850
- * Clear cache entries matching a pattern.
4851
- *
4852
- * @param pattern - Glob pattern (e.g., 'user:*')
4853
- */
4854
- async clear(pattern) {
4855
- await this.callRemote("clear", [pattern]);
4856
- }
4857
- /**
4858
- * Add member to sorted set with score.
4859
- *
4860
- * @param key - Sorted set key
4861
- * @param score - Numeric score (typically timestamp)
4862
- * @param member - Member to add
4863
- */
4864
- async zadd(key, score, member) {
4865
- await this.callRemote("zadd", [key, score, member]);
4866
- }
4867
- /**
4868
- * Get members from sorted set by score range.
4869
- *
4870
- * @param key - Sorted set key
4871
- * @param min - Minimum score (inclusive)
4872
- * @param max - Maximum score (inclusive)
4873
- * @returns Array of members in score order
4874
- */
4875
- async zrangebyscore(key, min, max) {
4876
- return await this.callRemote("zrangebyscore", [key, min, max]);
4877
- }
4878
- /**
4879
- * Remove member from sorted set.
4880
- *
4881
- * @param key - Sorted set key
4882
- * @param member - Member to remove
4883
- */
4884
- async zrem(key, member) {
4885
- await this.callRemote("zrem", [key, member]);
4886
- }
4887
- /**
4888
- * Set key-value pair only if key does not exist (atomic operation).
4889
- *
4890
- * @param key - Cache key
4891
- * @param value - Value to set
4892
- * @param ttl - Time to live in milliseconds (optional)
4893
- * @returns true if value was set, false if key already exists
4894
- */
4895
- async setIfNotExists(key, value, ttl) {
4896
- return await this.callRemote("setIfNotExists", [key, value, ttl]);
4897
- }
4898
- };
4899
- LLMProxy = class extends RemoteAdapter {
4900
- /**
4901
- * Create an LLM proxy.
5279
+ * Create an LLM proxy.
4902
5280
  *
4903
5281
  * @param transport - IPC transport to communicate with parent
4904
5282
  */
@@ -5021,123 +5399,6 @@ Caused by: ${cause.stack}`;
5021
5399
  return this._dimensions;
5022
5400
  }
5023
5401
  };
5024
- VectorStoreProxy = class _VectorStoreProxy extends RemoteAdapter {
5025
- // Timeout for bulk operations that may trigger IPC backpressure
5026
- static BULK_OPERATION_TIMEOUT = 12e4;
5027
- // 2 minutes
5028
- // BulkTransfer configuration
5029
- bulkTransferOptions = {
5030
- maxInlineSize: 1e6,
5031
- // 1MB threshold
5032
- tempDir: process.env.KB_TEMP_DIR ?? os.tmpdir()
5033
- };
5034
- /**
5035
- * Create a vector store proxy.
5036
- *
5037
- * @param transport - IPC transport to communicate with parent
5038
- */
5039
- constructor(transport) {
5040
- super("vectorStore", transport);
5041
- }
5042
- /**
5043
- * Search for similar vectors.
5044
- *
5045
- * @param query - Query embedding vector
5046
- * @param limit - Maximum number of results
5047
- * @param filter - Optional metadata filter
5048
- * @returns Promise resolving to search results
5049
- */
5050
- async search(query, limit, filter, namespace) {
5051
- return await this.callRemote("search", [query, limit, filter, namespace]);
5052
- }
5053
- /**
5054
- * Insert or update vectors.
5055
- * Uses BulkTransfer for large payloads to avoid IPC backpressure.
5056
- *
5057
- * @param vectors - Vector records to upsert
5058
- */
5059
- async upsert(vectors, namespace) {
5060
- const transfer = await BulkTransferHelper.serialize(vectors, this.bulkTransferOptions);
5061
- await this.callRemote("upsert", [transfer, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5062
- }
5063
- /**
5064
- * Delete vectors by IDs.
5065
- * Uses extended timeout for bulk deletions.
5066
- *
5067
- * @param ids - Vector IDs to delete
5068
- */
5069
- async delete(ids, namespace) {
5070
- await this.callRemote("delete", [ids, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5071
- }
5072
- /**
5073
- * Upsert vectors with chunk metadata (used by Mind RAG).
5074
- * Uses extended timeout for bulk operations.
5075
- *
5076
- * @param scope - Scope ID
5077
- * @param vectors - Vector records to upsert
5078
- */
5079
- async upsertChunks(scope, vectors) {
5080
- await this.callRemote("upsertChunks", [scope, vectors], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5081
- }
5082
- /**
5083
- * Count total vectors in collection.
5084
- *
5085
- * @returns Promise resolving to vector count
5086
- */
5087
- async count(namespace) {
5088
- return await this.callRemote("count", [namespace]);
5089
- }
5090
- /**
5091
- * Get vectors by IDs.
5092
- * IDs argument is usually small, passed directly through IPC.
5093
- * Uses BulkTransfer only for large result sets.
5094
- *
5095
- * @param ids - Vector IDs to retrieve
5096
- * @returns Promise resolving to vector records
5097
- */
5098
- async get(ids, namespace) {
5099
- const resultTransfer = await this.callRemote("get", [ids, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5100
- if (BulkTransferHelper.isBulkTransfer(resultTransfer)) {
5101
- return BulkTransferHelper.deserialize(resultTransfer);
5102
- }
5103
- return resultTransfer;
5104
- }
5105
- /**
5106
- * Query vectors by metadata filter.
5107
- * Filter argument is small, passed directly through IPC.
5108
- * Uses BulkTransfer only for potentially large result sets.
5109
- *
5110
- * @param filter - Metadata filter to apply
5111
- * @returns Promise resolving to matching vector records
5112
- */
5113
- async query(filter, namespace) {
5114
- const resultTransfer = await this.callRemote("query", [filter, namespace], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5115
- if (BulkTransferHelper.isBulkTransfer(resultTransfer)) {
5116
- return BulkTransferHelper.deserialize(resultTransfer);
5117
- }
5118
- return resultTransfer;
5119
- }
5120
- /**
5121
- * Clear all vectors from collection.
5122
- * Uses extended timeout for bulk deletion.
5123
- */
5124
- async clear() {
5125
- await this.callRemote("clear", [], _VectorStoreProxy.BULK_OPERATION_TIMEOUT);
5126
- }
5127
- /**
5128
- * Initialize the vector store.
5129
- * Called during platform initialization.
5130
- */
5131
- async initialize() {
5132
- await this.callRemote("initialize", []);
5133
- }
5134
- /**
5135
- * Close connections and cleanup resources.
5136
- */
5137
- async close() {
5138
- await this.callRemote("close", []);
5139
- }
5140
- };
5141
5402
  StorageProxy = class extends RemoteAdapter {
5142
5403
  /**
5143
5404
  * Create a storage proxy.
@@ -5235,180 +5496,6 @@ Caused by: ${cause.stack}`;
5235
5496
  return await this.callRemote("listWithMetadata", [prefix]);
5236
5497
  }
5237
5498
  };
5238
- DocumentDatabaseProxy = class extends RemoteAdapter {
5239
- constructor(transport) {
5240
- super("database.document", transport);
5241
- }
5242
- async find(collection, filter, options) {
5243
- return await this.callRemote("find", [collection, filter, stripSignal(options)]);
5244
- }
5245
- // eslint-disable-next-line require-yield
5246
- async *findStream(_collection, _filter, _options) {
5247
- throw new Error(
5248
- "findStream() is not supported over IPC. Use bounded find({ limit }) and paginate explicitly."
5249
- );
5250
- }
5251
- async findById(collection, id, _options) {
5252
- return await this.callRemote("findById", [collection, id]);
5253
- }
5254
- async count(collection, filter, _options) {
5255
- return await this.callRemote("count", [collection, filter]);
5256
- }
5257
- async insertOne(collection, doc, _options) {
5258
- return await this.callRemote("insertOne", [collection, doc]);
5259
- }
5260
- async insertMany(collection, docs, _options) {
5261
- return await this.callRemote("insertMany", [collection, docs]);
5262
- }
5263
- async updateOne(collection, filter, update, options) {
5264
- return await this.callRemote("updateOne", [
5265
- collection,
5266
- filter,
5267
- update,
5268
- { upsert: options?.upsert }
5269
- ]);
5270
- }
5271
- async updateMany(collection, filter, update, _options) {
5272
- return await this.callRemote("updateMany", [collection, filter, update]);
5273
- }
5274
- async updateById(collection, id, update, _options) {
5275
- return await this.callRemote("updateById", [collection, id, update]);
5276
- }
5277
- async deleteMany(collection, filter, _options) {
5278
- return await this.callRemote("deleteMany", [collection, filter]);
5279
- }
5280
- async deleteById(collection, id, _options) {
5281
- return await this.callRemote("deleteById", [collection, id]);
5282
- }
5283
- async bulkWrite(collection, ops, _options) {
5284
- return await this.callRemote("bulkWrite", [collection, ops]);
5285
- }
5286
- async transaction(_fn) {
5287
- throw new Error(
5288
- "transaction() is not supported over IPC. Collect your writes into a single bulkWrite() instead."
5289
- );
5290
- }
5291
- async ensureCollection(name, options) {
5292
- await this.callRemote("ensureCollection", [name, options]);
5293
- }
5294
- async ping() {
5295
- return await this.callRemote("ping", []);
5296
- }
5297
- async close(options) {
5298
- await this.callRemote("close", [options]);
5299
- }
5300
- };
5301
- stripSignal = (options) => {
5302
- if (!options) {
5303
- return void 0;
5304
- }
5305
- const { signal: _signal, ...rest } = options;
5306
- return rest;
5307
- };
5308
- KVStoreProxy = class extends RemoteAdapter {
5309
- constructor(transport) {
5310
- super("database.kv", transport);
5311
- }
5312
- async get(key, _options) {
5313
- return await this.callRemote("get", [key]);
5314
- }
5315
- async getMany(keys, _options) {
5316
- return await this.callRemote("getMany", [keys]);
5317
- }
5318
- async set(key, value, options) {
5319
- return await this.callRemote("set", [key, value, stripSignal2(options)]);
5320
- }
5321
- async setMany(entries, _options) {
5322
- await this.callRemote("setMany", [entries]);
5323
- }
5324
- async setIfNotExists(key, value, options) {
5325
- return await this.callRemote("setIfNotExists", [key, value, stripSignal2(options)]);
5326
- }
5327
- async delete(key, _options) {
5328
- return await this.callRemote("delete", [key]);
5329
- }
5330
- async exists(key, _options) {
5331
- return await this.callRemote("exists", [key]);
5332
- }
5333
- async cas(key, expected, next, options) {
5334
- return await this.callRemote("cas", [key, expected, next, stripSignal2(options)]);
5335
- }
5336
- async incr(key, delta, options) {
5337
- return await this.callRemote("incr", [key, delta, stripSignal2(options)]);
5338
- }
5339
- async ttl(key) {
5340
- return await this.callRemote("ttl", [key]);
5341
- }
5342
- async expire(key, ttlMs) {
5343
- return await this.callRemote("expire", [key, ttlMs]);
5344
- }
5345
- async persist(key) {
5346
- return await this.callRemote("persist", [key]);
5347
- }
5348
- // eslint-disable-next-line require-yield
5349
- async *scan(_prefix, _options) {
5350
- throw new Error("scan() is not supported over IPC. Use bounded getMany() with an explicit key list.");
5351
- }
5352
- async ping() {
5353
- return await this.callRemote("ping", []);
5354
- }
5355
- async close(options) {
5356
- await this.callRemote("close", [options]);
5357
- }
5358
- };
5359
- stripSignal2 = (options) => {
5360
- if (!options) {
5361
- return void 0;
5362
- }
5363
- const { signal: _signal, ...rest } = options;
5364
- return rest;
5365
- };
5366
- ConfigProxy = class extends RemoteAdapter {
5367
- /**
5368
- * Create a config proxy.
5369
- *
5370
- * @param transport - IPC transport to communicate with parent
5371
- */
5372
- constructor(transport) {
5373
- super("config", transport);
5374
- }
5375
- /**
5376
- * Get product-specific configuration.
5377
- *
5378
- * @param productId - Product identifier (e.g., 'mind', 'workflow', 'plugins')
5379
- * @param profileId - Profile identifier (defaults to 'default' or KB_PROFILE env var)
5380
- * @returns Promise resolving to product-specific config or undefined
5381
- *
5382
- * @example
5383
- * ```typescript
5384
- * const mindConfig = await config.getConfig('mind');
5385
- * if (mindConfig?.scopes) {
5386
- * // Use scopes
5387
- * }
5388
- * ```
5389
- */
5390
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5391
- async getConfig(productId, profileId) {
5392
- return this.callRemote("getConfig", [productId, profileId]);
5393
- }
5394
- /**
5395
- * Get raw kb.config.json data.
5396
- *
5397
- * @returns Promise resolving to raw config object or undefined
5398
- *
5399
- * @example
5400
- * ```typescript
5401
- * const rawConfig = await config.getRawConfig();
5402
- * if (rawConfig) {
5403
- * const allProfiles = rawConfig.profiles;
5404
- * }
5405
- * ```
5406
- */
5407
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
5408
- async getRawConfig() {
5409
- return this.callRemote("getRawConfig", []);
5410
- }
5411
- };
5412
5499
  EventBusProxy = class {
5413
5500
  constructor(transport) {
5414
5501
  this.transport = transport;
@@ -68285,1380 +68372,342 @@ var init_container = __esm3({
68285
68372
  return this.assembled;
68286
68373
  }
68287
68374
  /**
68288
- * Initialize resource broker.
68289
- * Called internally by initPlatform().
68290
- */
68291
- initResourceBroker(broker) {
68292
- this._resourceBroker = broker;
68293
- }
68294
- /**
68295
- * Initialize Unix socket server.
68296
- * Called internally by initPlatform() in parent process.
68297
- */
68298
- initSocketServer(server) {
68299
- this._socketServer = server;
68300
- }
68301
- /**
68302
- * Get socket path for IPC communication.
68303
- * Returns undefined if not running in parent process.
68304
- */
68305
- getSocketPath() {
68306
- return this._socketServer?.getSocketPath();
68307
- }
68308
- /**
68309
- * Initialize execution backend.
68310
- * Called internally by initPlatform() AFTER adapters, BEFORE core features.
68311
- *
68312
- * @param backend - ExecutionBackend instance (from @kb-labs/plugin-execution)
68313
- */
68314
- initExecutionBackend(backend) {
68315
- if (this._executionBackend) {
68316
- this.logger.warn("ExecutionBackend already initialized, replacing");
68317
- }
68318
- this._executionBackend = backend;
68319
- this.logger.debug("ExecutionBackend initialized", {
68320
- mode: backend.constructor.name
68321
- });
68322
- }
68323
- /**
68324
- * Get execution backend.
68325
- * Returns the initialized backend or throws if not initialized.
68326
- *
68327
- * @throws Error if ExecutionBackend not initialized via initPlatform()
68328
- * @returns ExecutionBackend instance
68329
- */
68330
- get executionBackend() {
68331
- if (!this._executionBackend) {
68332
- throw new Error(
68333
- "ExecutionBackend not initialized. Call initPlatform() with execution config to initialize ExecutionBackend."
68334
- );
68335
- }
68336
- return this._executionBackend;
68337
- }
68338
- /**
68339
- * Check if execution backend is initialized.
68340
- */
68341
- get hasExecutionBackend() {
68342
- return !!this._executionBackend;
68343
- }
68344
- /**
68345
- * Initialize orchestration services.
68346
- * Called internally by initPlatform() after ExecutionBackend init.
68347
- */
68348
- initOrchestrationServices(environmentManager, runExecutor, runOrchestrator) {
68349
- this._environmentManager = environmentManager;
68350
- this._runExecutor = runExecutor;
68351
- this._runOrchestrator = runOrchestrator;
68352
- }
68353
- /**
68354
- * Initialize infrastructure capability services.
68355
- * Called internally by initPlatform().
68356
- */
68357
- initCapabilityServices(workspaceManager, snapshotManager) {
68358
- this._workspaceManager = workspaceManager;
68359
- this._snapshotManager = snapshotManager;
68360
- }
68361
- /**
68362
- * Environment manager service.
68363
- * Returns undefined when not initialized (e.g., proxy/minimal platforms).
68364
- */
68365
- get environmentManager() {
68366
- return this._environmentManager;
68367
- }
68368
- /**
68369
- * Workspace manager service.
68370
- * Returns undefined when not initialized (e.g., proxy/minimal platforms).
68371
- */
68372
- get workspaceManager() {
68373
- return this._workspaceManager;
68374
- }
68375
- /**
68376
- * Snapshot manager service.
68377
- * Returns undefined when not initialized (e.g., proxy/minimal platforms).
68378
- */
68379
- get snapshotManager() {
68380
- return this._snapshotManager;
68381
- }
68382
- /**
68383
- * Run executor service.
68384
- */
68385
- get runExecutor() {
68386
- if (!this._runExecutor) {
68387
- throw new Error("RunExecutor not initialized. Call initPlatform() first.");
68388
- }
68389
- return this._runExecutor;
68390
- }
68391
- /**
68392
- * Run orchestrator service.
68393
- */
68394
- get runOrchestrator() {
68395
- if (!this._runOrchestrator) {
68396
- throw new Error(
68397
- "RunOrchestrator not initialized. Call initPlatform() first."
68398
- );
68399
- }
68400
- return this._runOrchestrator;
68401
- }
68402
- /**
68403
- * Check if platform is initialized.
68404
- */
68405
- get isInitialized() {
68406
- return this.initialized;
68407
- }
68408
- /**
68409
- * Reset platform to initial state.
68410
- * Clears all adapters and core features.
68411
- * Used primarily for testing.
68412
- */
68413
- reset() {
68414
- this.adapters.clear();
68415
- this.adapters.set("logger", new ConsoleLogger());
68416
- this.lifecycleHooks.clear();
68417
- this._workflows = void 0;
68418
- this._jobs = void 0;
68419
- this._cron = void 0;
68420
- this._resources = void 0;
68421
- this._resourceBroker = void 0;
68422
- this._socketServer = void 0;
68423
- this._executionBackend = void 0;
68424
- this._environmentManager = void 0;
68425
- this._workspaceManager = void 0;
68426
- this._snapshotManager = void 0;
68427
- this._runExecutor = void 0;
68428
- this._runOrchestrator = void 0;
68429
- this.initialized = false;
68430
- this.assembled = false;
68431
- }
68432
- /**
68433
- * Shutdown platform gracefully.
68434
- * Closes all resources, stops workers, cleanup.
68435
- */
68436
- async shutdown() {
68437
- await this.emitLifecyclePhase("beforeShutdown", {
68438
- reason: "platform.shutdown",
68439
- metadata: {
68440
- adapterCount: this.adapters.size,
68441
- hasExecutionBackend: !!this._executionBackend
68442
- }
68443
- });
68444
- if (this._executionBackend) {
68445
- try {
68446
- await this._executionBackend.shutdown();
68447
- } catch (error) {
68448
- this.logger.warn("ExecutionBackend shutdown failed", {
68449
- error: error instanceof Error ? error.message : String(error)
68450
- });
68451
- }
68452
- }
68453
- if (this._environmentManager) {
68454
- try {
68455
- await this._environmentManager.shutdown();
68456
- } catch (error) {
68457
- this.logger.warn("EnvironmentManager shutdown failed", {
68458
- error: error instanceof Error ? error.message : String(error)
68459
- });
68460
- }
68461
- }
68462
- if (this._workspaceManager) {
68463
- try {
68464
- await this._workspaceManager.shutdown();
68465
- } catch (error) {
68466
- this.logger.warn("WorkspaceManager shutdown failed", {
68467
- error: error instanceof Error ? error.message : String(error)
68468
- });
68469
- }
68470
- }
68471
- if (this._snapshotManager) {
68472
- try {
68473
- await this._snapshotManager.shutdown();
68474
- } catch (error) {
68475
- this.logger.warn("SnapshotManager shutdown failed", {
68476
- error: error instanceof Error ? error.message : String(error)
68477
- });
68478
- }
68479
- }
68480
- const adaptersInReverseLoadOrder = Array.from(this.adapters.entries()).reverse();
68481
- for (const [adapterId, adapter] of adaptersInReverseLoadOrder) {
68482
- if (!adapter || adapter === this._executionBackend) {
68483
- continue;
68484
- }
68485
- const candidate = adapter;
68486
- try {
68487
- if (typeof candidate.close === "function") {
68488
- await candidate.close.call(adapter);
68489
- } else if (typeof candidate.dispose === "function") {
68490
- await candidate.dispose.call(adapter);
68491
- } else if (typeof candidate.shutdown === "function") {
68492
- await candidate.shutdown.call(adapter);
68493
- }
68494
- } catch (error) {
68495
- this.logger.warn("Adapter shutdown failed", {
68496
- adapterId,
68497
- error: error instanceof Error ? error.message : String(error)
68498
- });
68499
- }
68500
- }
68501
- await this.emitLifecyclePhase("shutdown", {
68502
- reason: "platform.shutdown",
68503
- metadata: {
68504
- adapterCount: this.adapters.size
68505
- }
68506
- });
68507
- }
68508
- };
68509
- PLATFORM_SINGLETON_KEY = /* @__PURE__ */ Symbol.for("kb.platform");
68510
- platform = (() => {
68511
- const existing = getPlatformFromProcess();
68512
- if (existing && typeof existing.setAdapter === "function" && typeof existing.getAdapter === "function") {
68513
- return existing;
68514
- }
68515
- const newPlatform = new PlatformContainer();
68516
- setPlatformInProcess(newPlatform);
68517
- return newPlatform;
68518
- })();
68519
- }
68520
- });
68521
- var discover_adapters_exports = {};
68522
- __export3(discover_adapters_exports, {
68523
- discoverAdapters: () => discoverAdapters,
68524
- resolveAdapter: () => resolveAdapter
68525
- });
68526
- async function loadAdapterModule(distPath) {
68527
- const fileUrl = url.pathToFileURL(distPath).href;
68528
- return import(fileUrl);
68529
- }
68530
- async function loadAdaptersFromLock(root, discovered, overwrite) {
68531
- const diag = new DiagnosticCollector();
68532
- const lock = await readMarketplaceLock(root, diag);
68533
- if (!lock) {
68534
- return;
68535
- }
68536
- for (const [pkgId, entry] of Object.entries(lock.installed)) {
68537
- if (entry.primaryKind !== "adapter") {
68538
- continue;
68539
- }
68540
- if (entry.enabled === false) {
68541
- continue;
68542
- }
68543
- const pkgRoot = path3__default__namespace.default.resolve(root, entry.resolvedPath);
68544
- let mainPath = "dist/index.js";
68545
- let npmPkgName;
68546
- try {
68547
- const pkgContent = await fs5.promises.readFile(path3__default__namespace.default.join(pkgRoot, "package.json"), "utf-8");
68548
- const pkg = JSON.parse(pkgContent);
68549
- mainPath = pkg.main || mainPath;
68550
- npmPkgName = pkg.name;
68551
- } catch {
68552
- }
68553
- const distPath = path3__default__namespace.default.join(pkgRoot, mainPath);
68554
- try {
68555
- await fs5.promises.access(distPath);
68556
- const module = await loadAdapterModule(distPath);
68557
- if (typeof module.createAdapter !== "function") {
68558
- continue;
68559
- }
68560
- const adapterEntry = {
68561
- packageName: npmPkgName ?? pkgId,
68562
- pkgRoot,
68563
- createAdapter: module.createAdapter,
68564
- module
68565
- };
68566
- if (overwrite || !discovered.has(pkgId)) {
68567
- discovered.set(pkgId, adapterEntry);
68568
- }
68569
- if (npmPkgName && npmPkgName !== pkgId) {
68570
- if (overwrite || !discovered.has(npmPkgName)) {
68571
- discovered.set(npmPkgName, adapterEntry);
68572
- }
68573
- }
68574
- } catch {
68575
- }
68576
- }
68577
- }
68578
- async function discoverAdapters(platformRoot, projectRoot) {
68579
- const discovered = /* @__PURE__ */ new Map();
68580
- if (projectRoot && projectRoot !== platformRoot) {
68581
- await loadAdaptersFromLock(
68582
- projectRoot,
68583
- discovered,
68584
- /* overwrite= */
68585
- true
68586
- );
68587
- }
68588
- await loadAdaptersFromLock(
68589
- platformRoot,
68590
- discovered,
68591
- /* overwrite= */
68592
- false
68593
- );
68594
- return discovered;
68595
- }
68596
- async function resolveAdapter(adapterPath, cwd, platformRoot) {
68597
- const discovered = await discoverAdapters(
68598
- platformRoot ?? cwd,
68599
- platformRoot && platformRoot !== cwd ? cwd : void 0
68600
- );
68601
- const basePkgName = adapterPath.split("/").slice(0, 2).join("/");
68602
- const subpath = adapterPath.includes("/") ? adapterPath.split("/").slice(2).join("/") : null;
68603
- const adapter = discovered.get(basePkgName);
68604
- if (adapter && subpath) {
68605
- const subpathFile = path3__default__namespace.default.join(adapter.pkgRoot, "dist", `${subpath}.js`);
68606
- try {
68607
- await fs5.promises.access(subpathFile);
68608
- const module = await loadAdapterModule(subpathFile);
68609
- if (typeof module.createAdapter === "function") {
68610
- return module.createAdapter;
68611
- }
68612
- if (typeof module.default === "function") {
68613
- return module.default;
68614
- }
68615
- } catch {
68616
- }
68617
- } else if (adapter) {
68618
- return adapter.createAdapter;
68619
- }
68620
- return null;
68621
- }
68622
- var init_discover_adapters = __esm3({
68623
- "src/discover-adapters.ts"() {
68624
- }
68625
- });
68626
- var TransportError2;
68627
- var TimeoutError4;
68628
- var init_transport = __esm3({
68629
- "src/transport/transport.ts"() {
68630
- TransportError2 = class extends Error {
68631
- cause;
68632
- constructor(message, cause) {
68633
- super(message);
68634
- this.name = "TransportError";
68635
- this.cause = cause;
68636
- if (cause) {
68637
- this.stack = `${this.stack}
68638
- Caused by: ${cause.stack}`;
68639
- }
68640
- }
68641
- };
68642
- TimeoutError4 = class extends TransportError2 {
68643
- timeoutMs;
68644
- constructor(message, timeoutMs) {
68645
- super(message);
68646
- this.name = "TimeoutError";
68647
- this.timeoutMs = timeoutMs;
68648
- }
68649
- };
68650
- }
68651
- });
68652
- function getOperationTimeout2(adapter, method) {
68653
- const exactKey = `${adapter}.${method}`;
68654
- if (exactKey in OPERATION_TIMEOUTS2) {
68655
- return OPERATION_TIMEOUTS2[exactKey];
68656
- }
68657
- const wildcardKey = `${adapter}.*`;
68658
- if (wildcardKey in OPERATION_TIMEOUTS2) {
68659
- return OPERATION_TIMEOUTS2[wildcardKey];
68660
- }
68661
- return OPERATION_TIMEOUTS2["*"];
68662
- }
68663
- function selectTimeout2(call, configTimeout) {
68664
- if (call.timeout !== void 0) {
68665
- return call.timeout;
68666
- }
68667
- if (configTimeout !== void 0) {
68668
- return configTimeout;
68669
- }
68670
- return getOperationTimeout2(call.adapter, call.method);
68671
- }
68672
- var OPERATION_TIMEOUTS2;
68673
- var init_timeout_config = __esm3({
68674
- "src/transport/timeout-config.ts"() {
68675
- OPERATION_TIMEOUTS2 = {
68676
- // === VectorStore operations ===
68677
- // Bulk upsert is slow (Qdrant indexing overhead)
68678
- "vectorStore.upsert": 12e4,
68679
- // 2 minutes
68680
- // Search operations - medium latency
68681
- "vectorStore.search": 3e4,
68682
- // 30 seconds
68683
- "vectorStore.hybridSearch": 45e3,
68684
- // 45 seconds (BM25 + vector)
68685
- // Bulk retrieval - potentially large result sets
68686
- "vectorStore.get": 12e4,
68687
- // 2 minutes (retrieving many vectors)
68688
- "vectorStore.query": 12e4,
68689
- // 2 minutes (metadata filtering + retrieval)
68690
- // Collection management - fast
68691
- "vectorStore.createCollection": 15e3,
68692
- "vectorStore.deleteCollection": 15e3,
68693
- "vectorStore.collectionExists": 5e3,
68694
- // === Embeddings operations ===
68695
- // Single embed - OpenAI API latency
68696
- "embeddings.embed": 3e4,
68697
- // 30 seconds
68698
- // Batch embeddings - OpenAI processes in parallel, but may rate limit
68699
- "embeddings.embedBatch": 12e4,
68700
- // 2 minutes
68701
- // Dimension check - fast property access
68702
- "embeddings.getDimensions": 5e3,
68703
- // === LLM operations ===
68704
- // Text generation - depends on output length
68705
- "llm.generate": 9e4,
68706
- // 1.5 minutes
68707
- "llm.generateStream": 12e4,
68708
- // 2 minutes (streaming may take longer)
68709
- // === Cache operations ===
68710
- // Cache is fast (Redis or in-memory)
68711
- "cache.get": 5e3,
68712
- "cache.set": 5e3,
68713
- "cache.delete": 5e3,
68714
- "cache.clear": 1e4,
68715
- "cache.has": 5e3,
68716
- // === Storage operations ===
68717
- // File I/O - medium latency
68718
- "storage.read": 15e3,
68719
- "storage.write": 3e4,
68720
- "storage.delete": 1e4,
68721
- "storage.exists": 5e3,
68722
- "storage.list": 2e4,
68723
- // === Wildcard defaults ===
68724
- // Default timeout for any vectorStore operation not listed above
68725
- "vectorStore.*": 6e4,
68726
- // Default timeout for any embeddings operation
68727
- "embeddings.*": 6e4,
68728
- // Default timeout for any LLM operation
68729
- "llm.*": 9e4,
68730
- // Default timeout for any cache operation
68731
- "cache.*": 1e4,
68732
- // Default timeout for any storage operation
68733
- "storage.*": 3e4,
68734
- // === Global fallback ===
68735
- // Used when no specific rule matches
68736
- "*": 3e4
68737
- // 30 seconds default
68738
- };
68739
- }
68740
- });
68741
- var unix_socket_transport_exports = {};
68742
- __export3(unix_socket_transport_exports, {
68743
- UnixSocketTransport: () => UnixSocketTransport2,
68744
- createUnixSocketTransport: () => createUnixSocketTransport2
68745
- });
68746
- function createUnixSocketTransport2(config) {
68747
- return new UnixSocketTransport2(config);
68748
- }
68749
- var UnixSocketTransport2;
68750
- var init_unix_socket_transport = __esm3({
68751
- "src/transport/unix-socket-transport.ts"() {
68752
- init_transport();
68753
- init_timeout_config();
68754
- UnixSocketTransport2 = class {
68755
- constructor(config = {}) {
68756
- this.config = config;
68757
- }
68758
- config;
68759
- socket = null;
68760
- pending = /* @__PURE__ */ new Map();
68761
- closed = false;
68762
- connecting = false;
68763
- buffer = "";
68764
- reconnectAttempts = 0;
68765
- /**
68766
- * Connect to Unix socket server.
68767
- * Called lazily on first send() or explicitly.
68768
- */
68769
- async connect() {
68770
- if (this.socket && !this.socket.destroyed) {
68771
- return;
68772
- }
68773
- if (this.connecting) {
68774
- await new Promise((resolve32) => {
68775
- setTimeout(resolve32, 100);
68776
- });
68777
- return this.connect();
68778
- }
68779
- this.connecting = true;
68780
- return new Promise((resolve32, reject) => {
68781
- const socketPath = this.config.socketPath ?? "/tmp/kb-ipc.sock";
68782
- this.socket = net__namespace.connect(socketPath);
68783
- this.socket.on("connect", () => {
68784
- this.connecting = false;
68785
- this.reconnectAttempts = 0;
68786
- resolve32();
68787
- });
68788
- this.socket.on("error", (error) => {
68789
- this.connecting = false;
68790
- const maxAttempts = this.config.maxReconnectAttempts ?? 3;
68791
- if (this.config.autoReconnect !== false && this.reconnectAttempts < maxAttempts) {
68792
- this.reconnectAttempts++;
68793
- setTimeout(() => this.connect(), 1e3 * this.reconnectAttempts);
68794
- return;
68795
- }
68796
- reject(new TransportError2(`Unix socket connection failed: ${error.message}`, error));
68797
- });
68798
- this.socket.on("data", (data) => {
68799
- this.handleData(data);
68800
- });
68801
- this.socket.on("close", () => {
68802
- if (!this.closed && this.config.autoReconnect !== false) {
68803
- setTimeout(() => this.connect(), 1e3);
68804
- }
68805
- });
68806
- });
68807
- }
68808
- async send(call) {
68809
- if (this.closed) {
68810
- throw new TransportError2("Transport is closed");
68811
- }
68812
- await this.connect();
68813
- if (!this.socket || this.socket.destroyed) {
68814
- throw new TransportError2("Socket not available");
68815
- }
68816
- const timeout = selectTimeout2(call, this.config.timeout);
68817
- return new Promise((resolve32, reject) => {
68818
- const timer = setTimeout(() => {
68819
- this.pending.delete(call.requestId);
68820
- reject(new TimeoutError4(`Adapter call timed out after ${timeout}ms`, timeout));
68821
- }, timeout);
68822
- this.pending.set(call.requestId, { resolve: resolve32, reject, timer });
68823
- const message = JSON.stringify(call) + "\n";
68824
- const written = this.socket.write(message, "utf8", (error) => {
68825
- if (error) {
68826
- const pending = this.pending.get(call.requestId);
68827
- if (pending) {
68828
- clearTimeout(pending.timer);
68829
- this.pending.delete(call.requestId);
68830
- reject(new TransportError2(`Failed to write to socket: ${error.message}`, error));
68831
- }
68832
- }
68833
- });
68834
- if (!written) {
68835
- this.socket.once("drain", () => {
68836
- });
68837
- }
68838
- });
68839
- }
68840
- /**
68841
- * Handle incoming data from Unix socket.
68842
- * Messages are newline-delimited JSON.
68843
- */
68844
- handleData(data) {
68845
- this.buffer += data.toString("utf8");
68846
- let newlineIndex;
68847
- while ((newlineIndex = this.buffer.indexOf("\n")) !== -1) {
68848
- const line = this.buffer.slice(0, newlineIndex);
68849
- this.buffer = this.buffer.slice(newlineIndex + 1);
68850
- if (line.trim().length === 0) {
68851
- continue;
68852
- }
68853
- try {
68854
- const msg = JSON.parse(line);
68855
- this.handleMessage(msg);
68856
- } catch {
68857
- }
68858
- }
68859
- }
68860
- handleMessage(msg) {
68861
- if (!isAdapterResponse(msg)) {
68862
- return;
68863
- }
68864
- const pending = this.pending.get(msg.requestId);
68865
- if (!pending) {
68866
- return;
68867
- }
68868
- clearTimeout(pending.timer);
68869
- this.pending.delete(msg.requestId);
68870
- pending.resolve(msg);
68871
- }
68872
- async close() {
68873
- if (this.closed) {
68874
- return;
68875
- }
68876
- this.closed = true;
68877
- if (this.socket) {
68878
- this.socket.destroy();
68879
- this.socket = null;
68880
- }
68881
- for (const [requestId, pending] of this.pending) {
68882
- clearTimeout(pending.timer);
68883
- pending.reject(new TransportError2("Transport closed"));
68884
- }
68885
- this.pending.clear();
68886
- }
68887
- isClosed() {
68888
- return this.closed;
68889
- }
68890
- };
68891
- }
68892
- });
68893
- var RemoteAdapter2;
68894
- var init_remote_adapter = __esm3({
68895
- "src/proxy/remote-adapter.ts"() {
68896
- RemoteAdapter2 = class {
68897
- /**
68898
- * Create a remote adapter proxy.
68899
- *
68900
- * @param adapterName - Name of the adapter (e.g., 'vectorStore', 'cache')
68901
- * @param transport - Transport layer for IPC communication
68902
- * @param context - Optional execution context for tracing/debugging
68903
- */
68904
- constructor(adapterName, transport, context) {
68905
- this.adapterName = adapterName;
68906
- this.transport = transport;
68907
- this.context = context;
68908
- }
68909
- adapterName;
68910
- transport;
68911
- context;
68912
- /**
68913
- * Set execution context for this adapter.
68914
- * Context is included in all subsequent adapter calls for tracing/debugging.
68915
- *
68916
- * @param context - Execution context (traceId, pluginId, sessionId, etc.)
68917
- *
68918
- * @example
68919
- * ```typescript
68920
- * proxy.setContext({
68921
- * traceId: 'trace-abc',
68922
- * pluginId: '@kb-labs/mind',
68923
- * sessionId: 'session-xyz',
68924
- * });
68925
- * ```
68926
- */
68927
- setContext(context) {
68928
- this.context = context;
68929
- }
68930
- /**
68931
- * Get current execution context.
68932
- */
68933
- getContext() {
68934
- return this.context;
68935
- }
68936
- /**
68937
- * Call a method on the remote adapter (in parent process).
68938
- *
68939
- * This method:
68940
- * 1. Generates a unique request ID
68941
- * 2. Serializes the method arguments
68942
- * 3. Sends the call via transport
68943
- * 4. Waits for response
68944
- * 5. Deserializes and returns the result (or throws error)
68945
- *
68946
- * @param method - Method name to call on the adapter
68947
- * @param args - Method arguments (will be serialized)
68948
- * @param timeout - Optional timeout in milliseconds (overrides transport default)
68949
- * @returns Promise resolving to deserialized result
68950
- * @throws Error if remote method throws or communication fails
68951
- *
68952
- * @example
68953
- * ```typescript
68954
- * // In VectorStoreProxy.search():
68955
- * return this.callRemote('search', [query, limit, filter]);
68956
- *
68957
- * // With custom timeout for bulk operations:
68958
- * return this.callRemote('upsert', [vectors], 120000); // 2 min timeout
68959
- * ```
68960
- */
68961
- async callRemote(method, args, timeout) {
68962
- const requestId = crypto.randomUUID();
68963
- const call = {
68964
- version: IPC_PROTOCOL_VERSION,
68965
- // Protocol version for backward compatibility
68966
- type: "adapter:call",
68967
- requestId,
68968
- adapter: this.adapterName,
68969
- method,
68970
- args: args.map((arg) => serialize(arg)),
68971
- timeout,
68972
- // Optional timeout for this specific call
68973
- context: this.context
68974
- // Include execution context for tracing/debugging
68975
- };
68976
- const response = await this.transport.send(call);
68977
- if (response.error) {
68978
- throw deserialize(response.error);
68979
- }
68980
- return response.result !== void 0 ? deserialize(response.result) : void 0;
68981
- }
68982
- /**
68983
- * Get the adapter name this proxy represents.
68984
- */
68985
- getAdapterName() {
68986
- return this.adapterName;
68987
- }
68988
- /**
68989
- * Get the transport used by this proxy.
68990
- * Useful for advanced use cases (e.g., checking if transport is closed).
68991
- */
68992
- getTransport() {
68993
- return this.transport;
68994
- }
68995
- };
68996
- }
68997
- });
68998
- var BulkTransferHelper2;
68999
- var init_bulk_transfer = __esm3({
69000
- "src/transport/bulk-transfer.ts"() {
69001
- BulkTransferHelper2 = class _BulkTransferHelper2 {
69002
- /** Map of temp file IDs to file paths (for cleanup) */
69003
- static tempFiles = /* @__PURE__ */ new Map();
69004
- /** Default options */
69005
- static defaultOptions = {
69006
- maxInlineSize: 1e6,
69007
- // 1MB
69008
- tempDir: os.tmpdir()
69009
- };
69010
- /**
69011
- * Serialize data: inline for small, temp file for large
69012
- *
69013
- * @example
69014
- * ```typescript
69015
- * const transfer = await BulkTransferHelper.serialize(vectors, {
69016
- * maxInlineSize: 1_000_000,
69017
- * tempDir: '/tmp'
69018
- * });
69019
- *
69020
- * if (transfer.type === 'inline') {
69021
- * console.log('Using inline IPC');
69022
- * } else {
69023
- * console.log('Using temp file:', transfer.payload); // Absolute path like '/tmp/bulk-123.json'
69024
- * }
69025
- * ```
69026
- */
69027
- static async serialize(data, options = {}) {
69028
- const opts = { ...this.defaultOptions, ...options };
69029
- const json = JSON.stringify(data);
69030
- if (json.length < opts.maxInlineSize) {
69031
- return { type: "inline", payload: json };
69032
- }
69033
- const tempId = `bulk-${Date.now()}-${Math.random().toString(36).slice(2)}`;
69034
- const tempPath = path3__default.join(opts.tempDir, `${tempId}.json`);
69035
- await fs2.writeFile(tempPath, json, "utf8");
69036
- this.tempFiles.set(tempPath, tempPath);
69037
- return { type: "file", payload: tempPath };
69038
- }
69039
- /**
69040
- * Deserialize from inline JSON or temp file
69041
- *
69042
- * @example
69043
- * ```typescript
69044
- * const transfer = { type: 'file', payload: '/tmp/bulk-123.json' };
69045
- * const data = await BulkTransferHelper.deserialize<VectorRecord[]>(transfer);
69046
- * ```
69047
- */
69048
- static async deserialize(transfer) {
69049
- if (transfer.type === "inline") {
69050
- return JSON.parse(transfer.payload);
69051
- }
69052
- const tempPath = transfer.payload;
69053
- try {
69054
- const json = await fs2.readFile(tempPath, "utf8");
69055
- return JSON.parse(json);
69056
- } finally {
69057
- await fs2.unlink(tempPath).catch(() => {
69058
- });
69059
- this.tempFiles.delete(tempPath);
69060
- }
69061
- }
69062
- /**
69063
- * Check if object is a BulkTransfer
69064
- */
69065
- static isBulkTransfer(obj) {
69066
- return typeof obj === "object" && obj !== null && "type" in obj && "payload" in obj && (obj.type === "inline" || obj.type === "file");
69067
- }
69068
- /**
69069
- * Cleanup all temp files (call on process exit)
69070
- */
69071
- static async cleanup() {
69072
- const cleanupPromises = Array.from(this.tempFiles.values()).map(
69073
- (path6) => fs2.unlink(path6).catch(() => {
69074
- })
69075
- );
69076
- await Promise.all(cleanupPromises);
69077
- this.tempFiles.clear();
69078
- }
69079
- /**
69080
- * Get statistics about temp files
69081
- */
69082
- static getStats() {
69083
- return {
69084
- tempFilesCount: this.tempFiles.size,
69085
- tempFilePaths: Array.from(this.tempFiles.values())
69086
- };
69087
- }
69088
- static registerSignalHandlers() {
69089
- process.on("SIGINT", async () => {
69090
- await _BulkTransferHelper2.cleanup();
69091
- process.exit(0);
69092
- });
69093
- process.on("SIGTERM", async () => {
69094
- await _BulkTransferHelper2.cleanup();
69095
- process.exit(0);
69096
- });
69097
- process.on("uncaughtException", async (error) => {
69098
- console.error("[BulkTransferHelper] Uncaught exception, cleaning up temp files:", error);
69099
- await _BulkTransferHelper2.cleanup();
69100
- process.exit(1);
69101
- });
69102
- }
69103
- };
69104
- process.on("exit", () => {
69105
- for (const path6 of BulkTransferHelper2.getStats().tempFilePaths) {
69106
- try {
69107
- fs5.unlinkSync(path6);
69108
- } catch {
69109
- }
69110
- }
69111
- });
69112
- }
69113
- });
69114
- var vector_store_proxy_exports = {};
69115
- __export3(vector_store_proxy_exports, {
69116
- VectorStoreProxy: () => VectorStoreProxy2,
69117
- createVectorStoreProxy: () => createVectorStoreProxy
69118
- });
69119
- function createVectorStoreProxy(transport) {
69120
- return new VectorStoreProxy2(transport);
69121
- }
69122
- var VectorStoreProxy2;
69123
- var init_vector_store_proxy = __esm3({
69124
- "src/proxy/vector-store-proxy.ts"() {
69125
- init_remote_adapter();
69126
- init_bulk_transfer();
69127
- VectorStoreProxy2 = class _VectorStoreProxy2 extends RemoteAdapter2 {
69128
- // Timeout for bulk operations that may trigger IPC backpressure
69129
- static BULK_OPERATION_TIMEOUT = 12e4;
69130
- // 2 minutes
69131
- // BulkTransfer configuration
69132
- bulkTransferOptions = {
69133
- maxInlineSize: 1e6,
69134
- // 1MB threshold
69135
- tempDir: process.env.KB_TEMP_DIR ?? os.tmpdir()
69136
- };
69137
- /**
69138
- * Create a vector store proxy.
69139
- *
69140
- * @param transport - IPC transport to communicate with parent
69141
- */
69142
- constructor(transport) {
69143
- super("vectorStore", transport);
69144
- }
69145
- /**
69146
- * Search for similar vectors.
69147
- *
69148
- * @param query - Query embedding vector
69149
- * @param limit - Maximum number of results
69150
- * @param filter - Optional metadata filter
69151
- * @returns Promise resolving to search results
69152
- */
69153
- async search(query, limit, filter, namespace) {
69154
- return await this.callRemote("search", [query, limit, filter, namespace]);
69155
- }
69156
- /**
69157
- * Insert or update vectors.
69158
- * Uses BulkTransfer for large payloads to avoid IPC backpressure.
69159
- *
69160
- * @param vectors - Vector records to upsert
69161
- */
69162
- async upsert(vectors, namespace) {
69163
- const transfer = await BulkTransferHelper2.serialize(vectors, this.bulkTransferOptions);
69164
- await this.callRemote("upsert", [transfer, namespace], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69165
- }
69166
- /**
69167
- * Delete vectors by IDs.
69168
- * Uses extended timeout for bulk deletions.
69169
- *
69170
- * @param ids - Vector IDs to delete
69171
- */
69172
- async delete(ids, namespace) {
69173
- await this.callRemote("delete", [ids, namespace], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69174
- }
69175
- /**
69176
- * Upsert vectors with chunk metadata (used by Mind RAG).
69177
- * Uses extended timeout for bulk operations.
69178
- *
69179
- * @param scope - Scope ID
69180
- * @param vectors - Vector records to upsert
69181
- */
69182
- async upsertChunks(scope, vectors) {
69183
- await this.callRemote("upsertChunks", [scope, vectors], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69184
- }
69185
- /**
69186
- * Count total vectors in collection.
69187
- *
69188
- * @returns Promise resolving to vector count
69189
- */
69190
- async count(namespace) {
69191
- return await this.callRemote("count", [namespace]);
69192
- }
69193
- /**
69194
- * Get vectors by IDs.
69195
- * IDs argument is usually small, passed directly through IPC.
69196
- * Uses BulkTransfer only for large result sets.
69197
- *
69198
- * @param ids - Vector IDs to retrieve
69199
- * @returns Promise resolving to vector records
69200
- */
69201
- async get(ids, namespace) {
69202
- const resultTransfer = await this.callRemote("get", [ids, namespace], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69203
- if (BulkTransferHelper2.isBulkTransfer(resultTransfer)) {
69204
- return BulkTransferHelper2.deserialize(resultTransfer);
69205
- }
69206
- return resultTransfer;
69207
- }
69208
- /**
69209
- * Query vectors by metadata filter.
69210
- * Filter argument is small, passed directly through IPC.
69211
- * Uses BulkTransfer only for potentially large result sets.
69212
- *
69213
- * @param filter - Metadata filter to apply
69214
- * @returns Promise resolving to matching vector records
69215
- */
69216
- async query(filter, namespace) {
69217
- const resultTransfer = await this.callRemote("query", [filter, namespace], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69218
- if (BulkTransferHelper2.isBulkTransfer(resultTransfer)) {
69219
- return BulkTransferHelper2.deserialize(resultTransfer);
69220
- }
69221
- return resultTransfer;
69222
- }
69223
- /**
69224
- * Clear all vectors from collection.
69225
- * Uses extended timeout for bulk deletion.
69226
- */
69227
- async clear() {
69228
- await this.callRemote("clear", [], _VectorStoreProxy2.BULK_OPERATION_TIMEOUT);
69229
- }
69230
- /**
69231
- * Initialize the vector store.
69232
- * Called during platform initialization.
69233
- */
69234
- async initialize() {
69235
- await this.callRemote("initialize", []);
69236
- }
69237
- /**
69238
- * Close connections and cleanup resources.
69239
- */
69240
- async close() {
69241
- await this.callRemote("close", []);
69242
- }
69243
- };
69244
- }
69245
- });
69246
- var cache_proxy_exports = {};
69247
- __export3(cache_proxy_exports, {
69248
- CacheProxy: () => CacheProxy2,
69249
- createCacheProxy: () => createCacheProxy
69250
- });
69251
- function createCacheProxy(transport) {
69252
- return new CacheProxy2(transport);
69253
- }
69254
- var CacheProxy2;
69255
- var init_cache_proxy = __esm3({
69256
- "src/proxy/cache-proxy.ts"() {
69257
- init_remote_adapter();
69258
- CacheProxy2 = class extends RemoteAdapter2 {
69259
- /**
69260
- * Create a cache proxy.
69261
- *
69262
- * @param transport - IPC transport to communicate with parent
69263
- */
69264
- constructor(transport) {
69265
- super("cache", transport);
69266
- }
69267
- /**
69268
- * Get a value from cache.
69269
- *
69270
- * @param key - Cache key
69271
- * @returns Cached value or null if not found/expired
69272
- */
69273
- async get(key) {
69274
- return await this.callRemote("get", [key]);
69275
- }
69276
- /**
69277
- * Set a value in cache.
69278
- *
69279
- * @param key - Cache key
69280
- * @param value - Value to cache
69281
- * @param ttl - Time to live in milliseconds (optional)
69282
- */
69283
- async set(key, value, ttl) {
69284
- await this.callRemote("set", [key, value, ttl]);
69285
- }
69286
- /**
69287
- * Delete a value from cache.
69288
- *
69289
- * @param key - Cache key
69290
- */
69291
- async delete(key) {
69292
- await this.callRemote("delete", [key]);
69293
- }
69294
- /**
69295
- * Clear cache entries matching a pattern.
69296
- *
69297
- * @param pattern - Glob pattern (e.g., 'user:*')
69298
- */
69299
- async clear(pattern) {
69300
- await this.callRemote("clear", [pattern]);
69301
- }
69302
- /**
69303
- * Add member to sorted set with score.
69304
- *
69305
- * @param key - Sorted set key
69306
- * @param score - Numeric score (typically timestamp)
69307
- * @param member - Member to add
69308
- */
69309
- async zadd(key, score, member) {
69310
- await this.callRemote("zadd", [key, score, member]);
69311
- }
69312
- /**
69313
- * Get members from sorted set by score range.
69314
- *
69315
- * @param key - Sorted set key
69316
- * @param min - Minimum score (inclusive)
69317
- * @param max - Maximum score (inclusive)
69318
- * @returns Array of members in score order
69319
- */
69320
- async zrangebyscore(key, min, max) {
69321
- return await this.callRemote("zrangebyscore", [key, min, max]);
69322
- }
69323
- /**
69324
- * Remove member from sorted set.
69325
- *
69326
- * @param key - Sorted set key
69327
- * @param member - Member to remove
69328
- */
69329
- async zrem(key, member) {
69330
- await this.callRemote("zrem", [key, member]);
69331
- }
69332
- /**
69333
- * Set key-value pair only if key does not exist (atomic operation).
69334
- *
69335
- * @param key - Cache key
69336
- * @param value - Value to set
69337
- * @param ttl - Time to live in milliseconds (optional)
69338
- * @returns true if value was set, false if key already exists
69339
- */
69340
- async setIfNotExists(key, value, ttl) {
69341
- return await this.callRemote("setIfNotExists", [key, value, ttl]);
69342
- }
69343
- };
69344
- }
69345
- });
69346
- var config_proxy_exports = {};
69347
- __export3(config_proxy_exports, {
69348
- ConfigProxy: () => ConfigProxy2
69349
- });
69350
- var ConfigProxy2;
69351
- var init_config_proxy = __esm3({
69352
- "src/proxy/config-proxy.ts"() {
69353
- init_remote_adapter();
69354
- ConfigProxy2 = class extends RemoteAdapter2 {
69355
- /**
69356
- * Create a config proxy.
69357
- *
69358
- * @param transport - IPC transport to communicate with parent
69359
- */
69360
- constructor(transport) {
69361
- super("config", transport);
69362
- }
69363
- /**
69364
- * Get product-specific configuration.
69365
- *
69366
- * @param productId - Product identifier (e.g., 'mind', 'workflow', 'plugins')
69367
- * @param profileId - Profile identifier (defaults to 'default' or KB_PROFILE env var)
69368
- * @returns Promise resolving to product-specific config or undefined
69369
- *
69370
- * @example
69371
- * ```typescript
69372
- * const mindConfig = await config.getConfig('mind');
69373
- * if (mindConfig?.scopes) {
69374
- * // Use scopes
69375
- * }
69376
- * ```
69377
- */
69378
- async getConfig(productId, profileId) {
69379
- return this.callRemote("getConfig", [productId, profileId]);
69380
- }
69381
- /**
69382
- * Get raw kb.config.json data.
69383
- *
69384
- * @returns Promise resolving to raw config object or undefined
69385
- *
69386
- * @example
69387
- * ```typescript
69388
- * const rawConfig = await config.getRawConfig();
69389
- * if (rawConfig) {
69390
- * const allProfiles = rawConfig.profiles;
69391
- * }
69392
- * ```
69393
- */
69394
- async getRawConfig() {
69395
- return this.callRemote("getRawConfig", []);
69396
- }
69397
- };
69398
- }
69399
- });
69400
- var llm_proxy_exports = {};
69401
- __export3(llm_proxy_exports, {
69402
- LLMProxy: () => LLMProxy2,
69403
- createLLMProxy: () => createLLMProxy
69404
- });
69405
- function createLLMProxy(transport) {
69406
- return new LLMProxy2(transport);
69407
- }
69408
- var LLMProxy2;
69409
- var init_llm_proxy = __esm3({
69410
- "src/proxy/llm-proxy.ts"() {
69411
- init_remote_adapter();
69412
- LLMProxy2 = class extends RemoteAdapter2 {
69413
- /**
69414
- * Create an LLM proxy.
69415
- *
69416
- * @param transport - IPC transport to communicate with parent
69417
- */
69418
- constructor(transport) {
69419
- super("llm", transport);
69420
- }
69421
- /**
69422
- * Generate a completion for the given prompt.
69423
- *
69424
- * @param prompt - Text prompt
69425
- * @param options - Optional generation options
69426
- * @returns LLM response with content and token usage
69427
- */
69428
- async complete(prompt, options) {
69429
- return await this.callRemote("complete", [prompt, options]);
69430
- }
69431
- getProtocolCapabilities() {
69432
- return {
69433
- cache: { supported: false },
69434
- stream: { supported: false }
69435
- };
69436
- }
69437
- /**
69438
- * Stream a completion for the given prompt.
69439
- *
69440
- * **Fallback over IPC**: Uses complete() and emits a single chunk.
69441
- *
69442
- * Streaming requires bidirectional communication which is not
69443
- * currently implemented in the IPC protocol. This fallback preserves
69444
- * API compatibility for callers expecting AsyncIterable<string>.
69445
- *
69446
- * @param prompt - Text prompt
69447
- * @param options - Optional generation options
69448
- * @returns Async iterable with a single chunk from complete()
69449
- */
69450
- async *stream(prompt, options) {
69451
- console.warn("[LLMProxy] stream() fallback via complete() over IPC.");
69452
- const response = await this.complete(prompt, options);
69453
- if (response.content) {
69454
- yield response.content;
69455
- }
69456
- }
69457
- /**
69458
- * Chat with native tool calling support.
69459
- *
69460
- * Forwards tool calling request to parent process via IPC.
69461
- *
69462
- * @param messages - Conversation history
69463
- * @param options - Options including tools and tool choice
69464
- * @returns LLM response with optional tool calls
68375
+ * Initialize resource broker.
68376
+ * Called internally by initPlatform().
69465
68377
  */
69466
- async chatWithTools(messages, options) {
69467
- return await this.callRemote("chatWithTools", [messages, options]);
68378
+ initResourceBroker(broker) {
68379
+ this._resourceBroker = broker;
69468
68380
  }
69469
- };
69470
- }
69471
- });
69472
- var embeddings_proxy_exports = {};
69473
- __export3(embeddings_proxy_exports, {
69474
- EmbeddingsProxy: () => EmbeddingsProxy2,
69475
- createEmbeddingsProxy: () => createEmbeddingsProxy
69476
- });
69477
- function createEmbeddingsProxy(transport, dimensions) {
69478
- return new EmbeddingsProxy2(transport, dimensions);
69479
- }
69480
- var EmbeddingsProxy2;
69481
- var init_embeddings_proxy = __esm3({
69482
- "src/proxy/embeddings-proxy.ts"() {
69483
- init_remote_adapter();
69484
- EmbeddingsProxy2 = class extends RemoteAdapter2 {
69485
- _dimensions;
69486
68381
  /**
69487
- * Create an embeddings proxy.
69488
- *
69489
- * @param transport - IPC transport to communicate with parent
69490
- * @param dimensions - Optional dimensions override (avoids IPC call)
68382
+ * Initialize Unix socket server.
68383
+ * Called internally by initPlatform() in parent process.
69491
68384
  */
69492
- constructor(transport, dimensions) {
69493
- super("embeddings", transport);
69494
- this._dimensions = dimensions;
68385
+ initSocketServer(server) {
68386
+ this._socketServer = server;
69495
68387
  }
69496
68388
  /**
69497
- * Generate embedding vector for a single text.
69498
- *
69499
- * @param text - Input text
69500
- * @returns Embedding vector
68389
+ * Get socket path for IPC communication.
68390
+ * Returns undefined if not running in parent process.
69501
68391
  */
69502
- async embed(text) {
69503
- return await this.callRemote("embed", [text]);
68392
+ getSocketPath() {
68393
+ return this._socketServer?.getSocketPath();
69504
68394
  }
69505
68395
  /**
69506
- * Generate embedding vectors for multiple texts.
68396
+ * Initialize execution backend.
68397
+ * Called internally by initPlatform() AFTER adapters, BEFORE core features.
69507
68398
  *
69508
- * @param texts - Array of input texts
69509
- * @returns Array of embedding vectors (same order as input)
68399
+ * @param backend - ExecutionBackend instance (from @kb-labs/plugin-execution)
69510
68400
  */
69511
- async embedBatch(texts) {
69512
- return await this.callRemote("embedBatch", [texts]);
68401
+ initExecutionBackend(backend) {
68402
+ if (this._executionBackend) {
68403
+ this.logger.warn("ExecutionBackend already initialized, replacing");
68404
+ }
68405
+ this._executionBackend = backend;
68406
+ this.logger.debug("ExecutionBackend initialized", {
68407
+ mode: backend.constructor.name
68408
+ });
69513
68409
  }
69514
68410
  /**
69515
- * Dimension of the embedding vectors.
68411
+ * Get execution backend.
68412
+ * Returns the initialized backend or throws if not initialized.
69516
68413
  *
69517
- * This value is fetched once from the parent on first access
69518
- * and cached locally for performance.
68414
+ * @throws Error if ExecutionBackend not initialized via initPlatform()
68415
+ * @returns ExecutionBackend instance
69519
68416
  */
69520
- get dimensions() {
69521
- if (this._dimensions === void 0) {
68417
+ get executionBackend() {
68418
+ if (!this._executionBackend) {
69522
68419
  throw new Error(
69523
- "EmbeddingsProxy dimensions not initialized. Call getDimensions() first or pass dimensions to constructor."
68420
+ "ExecutionBackend not initialized. Call initPlatform() with execution config to initialize ExecutionBackend."
69524
68421
  );
69525
68422
  }
69526
- return this._dimensions;
68423
+ return this._executionBackend;
69527
68424
  }
69528
68425
  /**
69529
- * Initialize dimensions by fetching from parent.
69530
- *
69531
- * This is called automatically by initPlatform() in child process.
69532
- * If you create EmbeddingsProxy manually, call this method before
69533
- * accessing the `dimensions` property.
69534
- *
69535
- * @returns Dimensions value
69536
- *
69537
- * @example
69538
- * ```typescript
69539
- * const proxy = new EmbeddingsProxy(transport);
69540
- * await proxy.getDimensions(); // Fetch once
69541
- * console.log(proxy.dimensions); // Now safe to access
69542
- * ```
68426
+ * Check if execution backend is initialized.
69543
68427
  */
69544
- async getDimensions() {
69545
- if (this._dimensions === void 0) {
69546
- this._dimensions = await this.callRemote("getDimensions", []);
69547
- }
69548
- return this._dimensions;
68428
+ get hasExecutionBackend() {
68429
+ return !!this._executionBackend;
69549
68430
  }
69550
- };
69551
- }
69552
- });
69553
- var storage_proxy_exports = {};
69554
- __export3(storage_proxy_exports, {
69555
- StorageProxy: () => StorageProxy2,
69556
- createStorageProxy: () => createStorageProxy
69557
- });
69558
- function createStorageProxy(transport) {
69559
- return new StorageProxy2(transport);
69560
- }
69561
- var StorageProxy2;
69562
- var init_storage_proxy = __esm3({
69563
- "src/proxy/storage-proxy.ts"() {
69564
- init_remote_adapter();
69565
- StorageProxy2 = class extends RemoteAdapter2 {
69566
68431
  /**
69567
- * Create a storage proxy.
69568
- *
69569
- * @param transport - IPC transport to communicate with parent
68432
+ * Initialize orchestration services.
68433
+ * Called internally by initPlatform() after ExecutionBackend init.
69570
68434
  */
69571
- constructor(transport) {
69572
- super("storage", transport);
68435
+ initOrchestrationServices(environmentManager, runExecutor, runOrchestrator) {
68436
+ this._environmentManager = environmentManager;
68437
+ this._runExecutor = runExecutor;
68438
+ this._runOrchestrator = runOrchestrator;
69573
68439
  }
69574
68440
  /**
69575
- * Read file contents.
69576
- *
69577
- * @param path - File path
69578
- * @returns File contents or null if not found
68441
+ * Initialize infrastructure capability services.
68442
+ * Called internally by initPlatform().
69579
68443
  */
69580
- async read(path6) {
69581
- return await this.callRemote("read", [path6]);
68444
+ initCapabilityServices(workspaceManager, snapshotManager) {
68445
+ this._workspaceManager = workspaceManager;
68446
+ this._snapshotManager = snapshotManager;
69582
68447
  }
69583
68448
  /**
69584
- * Write file contents.
69585
- *
69586
- * @param path - File path
69587
- * @param data - File contents
68449
+ * Environment manager service.
68450
+ * Returns undefined when not initialized (e.g., proxy/minimal platforms).
69588
68451
  */
69589
- async write(path6, data) {
69590
- await this.callRemote("write", [path6, data]);
68452
+ get environmentManager() {
68453
+ return this._environmentManager;
69591
68454
  }
69592
68455
  /**
69593
- * Delete a file.
69594
- *
69595
- * @param path - File path
68456
+ * Workspace manager service.
68457
+ * Returns undefined when not initialized (e.g., proxy/minimal platforms).
69596
68458
  */
69597
- async delete(path6) {
69598
- await this.callRemote("delete", [path6]);
68459
+ get workspaceManager() {
68460
+ return this._workspaceManager;
69599
68461
  }
69600
68462
  /**
69601
- * List files matching a prefix.
69602
- *
69603
- * @param prefix - Path prefix (e.g., 'docs/')
69604
- * @returns Array of file paths
68463
+ * Snapshot manager service.
68464
+ * Returns undefined when not initialized (e.g., proxy/minimal platforms).
69605
68465
  */
69606
- async list(prefix) {
69607
- return await this.callRemote("list", [prefix]);
68466
+ get snapshotManager() {
68467
+ return this._snapshotManager;
69608
68468
  }
69609
68469
  /**
69610
- * Check if a file exists.
69611
- *
69612
- * @param path - File path
69613
- * @returns True if file exists, false otherwise
68470
+ * Run executor service.
69614
68471
  */
69615
- async exists(path6) {
69616
- return await this.callRemote("exists", [path6]);
68472
+ get runExecutor() {
68473
+ if (!this._runExecutor) {
68474
+ throw new Error("RunExecutor not initialized. Call initPlatform() first.");
68475
+ }
68476
+ return this._runExecutor;
69617
68477
  }
69618
- // ═══════════════════════════════════════════════════════════════════════
69619
- // EXTENDED METHODS (optional - implements IStorage extended interface)
69620
- // ═══════════════════════════════════════════════════════════════════════
69621
68478
  /**
69622
- * Get file metadata.
69623
- * Optional method - implements IStorage.stat().
69624
- *
69625
- * @param path - File path
69626
- * @returns File metadata or null if not found
68479
+ * Run orchestrator service.
69627
68480
  */
69628
- async stat(path6) {
69629
- return await this.callRemote("stat", [path6]);
68481
+ get runOrchestrator() {
68482
+ if (!this._runOrchestrator) {
68483
+ throw new Error(
68484
+ "RunOrchestrator not initialized. Call initPlatform() first."
68485
+ );
68486
+ }
68487
+ return this._runOrchestrator;
69630
68488
  }
69631
68489
  /**
69632
- * Copy file within storage.
69633
- * Optional method - implements IStorage.copy().
69634
- *
69635
- * @param sourcePath - Source file path
69636
- * @param destPath - Destination file path
68490
+ * Check if platform is initialized.
69637
68491
  */
69638
- async copy(sourcePath, destPath) {
69639
- await this.callRemote("copy", [sourcePath, destPath]);
68492
+ get isInitialized() {
68493
+ return this.initialized;
69640
68494
  }
69641
68495
  /**
69642
- * Move file within storage.
69643
- * Optional method - implements IStorage.move().
69644
- *
69645
- * @param sourcePath - Source file path
69646
- * @param destPath - Destination file path
68496
+ * Reset platform to initial state.
68497
+ * Clears all adapters and core features.
68498
+ * Used primarily for testing.
69647
68499
  */
69648
- async move(sourcePath, destPath) {
69649
- await this.callRemote("move", [sourcePath, destPath]);
68500
+ reset() {
68501
+ this.adapters.clear();
68502
+ this.adapters.set("logger", new ConsoleLogger());
68503
+ this.lifecycleHooks.clear();
68504
+ this._workflows = void 0;
68505
+ this._jobs = void 0;
68506
+ this._cron = void 0;
68507
+ this._resources = void 0;
68508
+ this._resourceBroker = void 0;
68509
+ this._socketServer = void 0;
68510
+ this._executionBackend = void 0;
68511
+ this._environmentManager = void 0;
68512
+ this._workspaceManager = void 0;
68513
+ this._snapshotManager = void 0;
68514
+ this._runExecutor = void 0;
68515
+ this._runOrchestrator = void 0;
68516
+ this.initialized = false;
68517
+ this.assembled = false;
69650
68518
  }
69651
68519
  /**
69652
- * List files with metadata.
69653
- * Optional method - implements IStorage.listWithMetadata().
69654
- *
69655
- * @param prefix - Path prefix (e.g., 'docs/')
69656
- * @returns Array of file metadata
68520
+ * Shutdown platform gracefully.
68521
+ * Closes all resources, stops workers, cleanup.
69657
68522
  */
69658
- async listWithMetadata(prefix) {
69659
- return await this.callRemote("listWithMetadata", [prefix]);
68523
+ async shutdown() {
68524
+ await this.emitLifecyclePhase("beforeShutdown", {
68525
+ reason: "platform.shutdown",
68526
+ metadata: {
68527
+ adapterCount: this.adapters.size,
68528
+ hasExecutionBackend: !!this._executionBackend
68529
+ }
68530
+ });
68531
+ if (this._executionBackend) {
68532
+ try {
68533
+ await this._executionBackend.shutdown();
68534
+ } catch (error) {
68535
+ this.logger.warn("ExecutionBackend shutdown failed", {
68536
+ error: error instanceof Error ? error.message : String(error)
68537
+ });
68538
+ }
68539
+ }
68540
+ if (this._environmentManager) {
68541
+ try {
68542
+ await this._environmentManager.shutdown();
68543
+ } catch (error) {
68544
+ this.logger.warn("EnvironmentManager shutdown failed", {
68545
+ error: error instanceof Error ? error.message : String(error)
68546
+ });
68547
+ }
68548
+ }
68549
+ if (this._workspaceManager) {
68550
+ try {
68551
+ await this._workspaceManager.shutdown();
68552
+ } catch (error) {
68553
+ this.logger.warn("WorkspaceManager shutdown failed", {
68554
+ error: error instanceof Error ? error.message : String(error)
68555
+ });
68556
+ }
68557
+ }
68558
+ if (this._snapshotManager) {
68559
+ try {
68560
+ await this._snapshotManager.shutdown();
68561
+ } catch (error) {
68562
+ this.logger.warn("SnapshotManager shutdown failed", {
68563
+ error: error instanceof Error ? error.message : String(error)
68564
+ });
68565
+ }
68566
+ }
68567
+ const adaptersInReverseLoadOrder = Array.from(this.adapters.entries()).reverse();
68568
+ for (const [adapterId, adapter] of adaptersInReverseLoadOrder) {
68569
+ if (!adapter || adapter === this._executionBackend) {
68570
+ continue;
68571
+ }
68572
+ const candidate = adapter;
68573
+ try {
68574
+ if (typeof candidate.close === "function") {
68575
+ await candidate.close.call(adapter);
68576
+ } else if (typeof candidate.dispose === "function") {
68577
+ await candidate.dispose.call(adapter);
68578
+ } else if (typeof candidate.shutdown === "function") {
68579
+ await candidate.shutdown.call(adapter);
68580
+ }
68581
+ } catch (error) {
68582
+ this.logger.warn("Adapter shutdown failed", {
68583
+ adapterId,
68584
+ error: error instanceof Error ? error.message : String(error)
68585
+ });
68586
+ }
68587
+ }
68588
+ await this.emitLifecyclePhase("shutdown", {
68589
+ reason: "platform.shutdown",
68590
+ metadata: {
68591
+ adapterCount: this.adapters.size
68592
+ }
68593
+ });
69660
68594
  }
69661
68595
  };
68596
+ PLATFORM_SINGLETON_KEY = /* @__PURE__ */ Symbol.for("kb.platform");
68597
+ platform = (() => {
68598
+ const existing = getPlatformFromProcess();
68599
+ if (existing && typeof existing.setAdapter === "function" && typeof existing.getAdapter === "function") {
68600
+ return existing;
68601
+ }
68602
+ const newPlatform = new PlatformContainer();
68603
+ setPlatformInProcess(newPlatform);
68604
+ return newPlatform;
68605
+ })();
68606
+ }
68607
+ });
68608
+ var discover_adapters_exports = {};
68609
+ __export3(discover_adapters_exports, {
68610
+ discoverAdapters: () => discoverAdapters,
68611
+ resolveAdapter: () => resolveAdapter
68612
+ });
68613
+ async function loadAdapterModule(distPath) {
68614
+ const fileUrl = url.pathToFileURL(distPath).href;
68615
+ return import(fileUrl);
68616
+ }
68617
+ async function loadAdaptersFromLock(root, discovered, overwrite) {
68618
+ const diag = new DiagnosticCollector();
68619
+ const lock = await readMarketplaceLock(root, diag);
68620
+ if (!lock) {
68621
+ return;
68622
+ }
68623
+ for (const [pkgId, entry] of Object.entries(lock.installed)) {
68624
+ if (entry.primaryKind !== "adapter") {
68625
+ continue;
68626
+ }
68627
+ if (entry.enabled === false) {
68628
+ continue;
68629
+ }
68630
+ const pkgRoot = path3__default__namespace.default.resolve(root, entry.resolvedPath);
68631
+ let mainPath = "dist/index.js";
68632
+ let npmPkgName;
68633
+ try {
68634
+ const pkgContent = await fs5.promises.readFile(path3__default__namespace.default.join(pkgRoot, "package.json"), "utf-8");
68635
+ const pkg = JSON.parse(pkgContent);
68636
+ mainPath = pkg.main || mainPath;
68637
+ npmPkgName = pkg.name;
68638
+ } catch {
68639
+ }
68640
+ const distPath = path3__default__namespace.default.join(pkgRoot, mainPath);
68641
+ try {
68642
+ await fs5.promises.access(distPath);
68643
+ const module = await loadAdapterModule(distPath);
68644
+ if (typeof module.createAdapter !== "function") {
68645
+ continue;
68646
+ }
68647
+ const adapterEntry = {
68648
+ packageName: npmPkgName ?? pkgId,
68649
+ pkgRoot,
68650
+ createAdapter: module.createAdapter,
68651
+ module
68652
+ };
68653
+ if (overwrite || !discovered.has(pkgId)) {
68654
+ discovered.set(pkgId, adapterEntry);
68655
+ }
68656
+ if (npmPkgName && npmPkgName !== pkgId) {
68657
+ if (overwrite || !discovered.has(npmPkgName)) {
68658
+ discovered.set(npmPkgName, adapterEntry);
68659
+ }
68660
+ }
68661
+ } catch {
68662
+ }
68663
+ }
68664
+ }
68665
+ async function discoverAdapters(platformRoot, projectRoot) {
68666
+ const discovered = /* @__PURE__ */ new Map();
68667
+ if (projectRoot && projectRoot !== platformRoot) {
68668
+ await loadAdaptersFromLock(
68669
+ projectRoot,
68670
+ discovered,
68671
+ /* overwrite= */
68672
+ true
68673
+ );
68674
+ }
68675
+ await loadAdaptersFromLock(
68676
+ platformRoot,
68677
+ discovered,
68678
+ /* overwrite= */
68679
+ false
68680
+ );
68681
+ return discovered;
68682
+ }
68683
+ async function resolveAdapter(adapterPath, cwd, platformRoot) {
68684
+ const discovered = await discoverAdapters(
68685
+ platformRoot ?? cwd,
68686
+ platformRoot && platformRoot !== cwd ? cwd : void 0
68687
+ );
68688
+ const basePkgName = adapterPath.split("/").slice(0, 2).join("/");
68689
+ const subpath = adapterPath.includes("/") ? adapterPath.split("/").slice(2).join("/") : null;
68690
+ const adapter = discovered.get(basePkgName);
68691
+ if (adapter && subpath) {
68692
+ const subpathFile = path3__default__namespace.default.join(adapter.pkgRoot, "dist", `${subpath}.js`);
68693
+ try {
68694
+ await fs5.promises.access(subpathFile);
68695
+ const module = await loadAdapterModule(subpathFile);
68696
+ if (typeof module.createAdapter === "function") {
68697
+ return module.createAdapter;
68698
+ }
68699
+ if (typeof module.default === "function") {
68700
+ return module.default;
68701
+ }
68702
+ } catch {
68703
+ }
68704
+ } else if (adapter) {
68705
+ return adapter.createAdapter;
68706
+ }
68707
+ return null;
68708
+ }
68709
+ var init_discover_adapters = __esm3({
68710
+ "src/discover-adapters.ts"() {
69662
68711
  }
69663
68712
  });
69664
68713
  var config_adapter_exports = {};
@@ -69734,6 +68783,122 @@ var init_config_adapter = __esm3({
69734
68783
  };
69735
68784
  }
69736
68785
  });
68786
+ var BulkTransferHelper2;
68787
+ var init_bulk_transfer = __esm3({
68788
+ "src/transport/bulk-transfer.ts"() {
68789
+ BulkTransferHelper2 = class _BulkTransferHelper2 {
68790
+ /** Map of temp file IDs to file paths (for cleanup) */
68791
+ static tempFiles = /* @__PURE__ */ new Map();
68792
+ /** Default options */
68793
+ static defaultOptions = {
68794
+ maxInlineSize: 1e6,
68795
+ // 1MB
68796
+ tempDir: os.tmpdir()
68797
+ };
68798
+ /**
68799
+ * Serialize data: inline for small, temp file for large
68800
+ *
68801
+ * @example
68802
+ * ```typescript
68803
+ * const transfer = await BulkTransferHelper.serialize(vectors, {
68804
+ * maxInlineSize: 1_000_000,
68805
+ * tempDir: '/tmp'
68806
+ * });
68807
+ *
68808
+ * if (transfer.type === 'inline') {
68809
+ * console.log('Using inline IPC');
68810
+ * } else {
68811
+ * console.log('Using temp file:', transfer.payload); // Absolute path like '/tmp/bulk-123.json'
68812
+ * }
68813
+ * ```
68814
+ */
68815
+ static async serialize(data, options = {}) {
68816
+ const opts = { ...this.defaultOptions, ...options };
68817
+ const json = JSON.stringify(data);
68818
+ if (json.length < opts.maxInlineSize) {
68819
+ return { type: "inline", payload: json };
68820
+ }
68821
+ const tempId = `bulk-${Date.now()}-${Math.random().toString(36).slice(2)}`;
68822
+ const tempPath = path3__default.join(opts.tempDir, `${tempId}.json`);
68823
+ await fs2.writeFile(tempPath, json, "utf8");
68824
+ this.tempFiles.set(tempPath, tempPath);
68825
+ return { type: "file", payload: tempPath };
68826
+ }
68827
+ /**
68828
+ * Deserialize from inline JSON or temp file
68829
+ *
68830
+ * @example
68831
+ * ```typescript
68832
+ * const transfer = { type: 'file', payload: '/tmp/bulk-123.json' };
68833
+ * const data = await BulkTransferHelper.deserialize<VectorRecord[]>(transfer);
68834
+ * ```
68835
+ */
68836
+ static async deserialize(transfer) {
68837
+ if (transfer.type === "inline") {
68838
+ return JSON.parse(transfer.payload);
68839
+ }
68840
+ const tempPath = transfer.payload;
68841
+ try {
68842
+ const json = await fs2.readFile(tempPath, "utf8");
68843
+ return JSON.parse(json);
68844
+ } finally {
68845
+ await fs2.unlink(tempPath).catch(() => {
68846
+ });
68847
+ this.tempFiles.delete(tempPath);
68848
+ }
68849
+ }
68850
+ /**
68851
+ * Check if object is a BulkTransfer
68852
+ */
68853
+ static isBulkTransfer(obj) {
68854
+ return typeof obj === "object" && obj !== null && "type" in obj && "payload" in obj && (obj.type === "inline" || obj.type === "file");
68855
+ }
68856
+ /**
68857
+ * Cleanup all temp files (call on process exit)
68858
+ */
68859
+ static async cleanup() {
68860
+ const cleanupPromises = Array.from(this.tempFiles.values()).map(
68861
+ (path6) => fs2.unlink(path6).catch(() => {
68862
+ })
68863
+ );
68864
+ await Promise.all(cleanupPromises);
68865
+ this.tempFiles.clear();
68866
+ }
68867
+ /**
68868
+ * Get statistics about temp files
68869
+ */
68870
+ static getStats() {
68871
+ return {
68872
+ tempFilesCount: this.tempFiles.size,
68873
+ tempFilePaths: Array.from(this.tempFiles.values())
68874
+ };
68875
+ }
68876
+ static registerSignalHandlers() {
68877
+ process.on("SIGINT", async () => {
68878
+ await _BulkTransferHelper2.cleanup();
68879
+ process.exit(0);
68880
+ });
68881
+ process.on("SIGTERM", async () => {
68882
+ await _BulkTransferHelper2.cleanup();
68883
+ process.exit(0);
68884
+ });
68885
+ process.on("uncaughtException", async (error) => {
68886
+ console.error("[BulkTransferHelper] Uncaught exception, cleaning up temp files:", error);
68887
+ await _BulkTransferHelper2.cleanup();
68888
+ process.exit(1);
68889
+ });
68890
+ }
68891
+ };
68892
+ process.on("exit", () => {
68893
+ for (const path6 of BulkTransferHelper2.getStats().tempFilePaths) {
68894
+ try {
68895
+ fs5.unlinkSync(path6);
68896
+ } catch {
68897
+ }
68898
+ }
68899
+ });
68900
+ }
68901
+ });
69737
68902
  var unix_socket_server_exports = {};
69738
68903
  __export3(unix_socket_server_exports, {
69739
68904
  UnixSocketServer: () => UnixSocketServer2,
@@ -72407,35 +71572,37 @@ async function initPlatform(config = {}, cwd = process.cwd(), uiProvider, platfo
72407
71572
  try {
72408
71573
  if (isChildProcess) {
72409
71574
  platform.logger.debug("initPlatform child process detected - creating proxy adapters");
72410
- const { UnixSocketTransport: UnixSocketTransport3 } = await Promise.resolve().then(() => (init_unix_socket_transport(), unix_socket_transport_exports));
72411
- const { VectorStoreProxy: VectorStoreProxy22 } = await Promise.resolve().then(() => (init_vector_store_proxy(), vector_store_proxy_exports));
72412
- const { CacheProxy: CacheProxy22 } = await Promise.resolve().then(() => (init_cache_proxy(), cache_proxy_exports));
72413
- const { ConfigProxy: ConfigProxy22 } = await Promise.resolve().then(() => (init_config_proxy(), config_proxy_exports));
72414
- const { LLMProxy: LLMProxy22 } = await Promise.resolve().then(() => (init_llm_proxy(), llm_proxy_exports));
72415
- const { EmbeddingsProxy: EmbeddingsProxy22 } = await Promise.resolve().then(() => (init_embeddings_proxy(), embeddings_proxy_exports));
72416
- const { StorageProxy: StorageProxy22 } = await Promise.resolve().then(() => (init_storage_proxy(), storage_proxy_exports));
71575
+ const {
71576
+ UnixSocketTransport: UnixSocketTransport3,
71577
+ VectorStoreProxy: VectorStoreProxy2,
71578
+ CacheProxy: CacheProxy2,
71579
+ ConfigProxy: ConfigProxy2,
71580
+ LLMProxy: LLMProxy2,
71581
+ EmbeddingsProxy: EmbeddingsProxy2,
71582
+ StorageProxy: StorageProxy2
71583
+ } = await Promise.resolve().then(() => (init_dist5(), dist_exports));
72417
71584
  const transport = new UnixSocketTransport3();
72418
71585
  platform.logger.debug("initPlatform using Unix Socket transport");
72419
71586
  if (adapters.vectorStore) {
72420
- platform.setAdapter("vectorStore", new VectorStoreProxy22(transport));
71587
+ platform.setAdapter("vectorStore", new VectorStoreProxy2(transport));
72421
71588
  platform.logger.debug("initPlatform created VectorStoreProxy");
72422
71589
  }
72423
71590
  if (adapters.cache) {
72424
- platform.setAdapter("cache", new CacheProxy22(transport));
71591
+ platform.setAdapter("cache", new CacheProxy2(transport));
72425
71592
  platform.logger.debug("initPlatform created CacheProxy");
72426
71593
  }
72427
- platform.setAdapter("config", new ConfigProxy22(transport));
71594
+ platform.setAdapter("config", new ConfigProxy2(transport));
72428
71595
  platform.logger.debug("initPlatform created ConfigProxy");
72429
- platform.setAdapter("llm", new LLMProxy22(transport));
71596
+ platform.setAdapter("llm", new LLMProxy2(transport));
72430
71597
  platform.logger.debug("initPlatform created LLMProxy");
72431
71598
  if (adapters.embeddings) {
72432
- const embeddingsProxy = new EmbeddingsProxy22(transport);
71599
+ const embeddingsProxy = new EmbeddingsProxy2(transport);
72433
71600
  await embeddingsProxy.getDimensions();
72434
71601
  platform.setAdapter("embeddings", embeddingsProxy);
72435
71602
  platform.logger.debug("initPlatform created EmbeddingsProxy");
72436
71603
  }
72437
71604
  if (adapters.storage) {
72438
- platform.setAdapter("storage", new StorageProxy22(transport));
71605
+ platform.setAdapter("storage", new StorageProxy2(transport));
72439
71606
  platform.logger.debug("initPlatform created StorageProxy");
72440
71607
  }
72441
71608
  fillAdapterFallbacksAndRecord(
@@ -73546,21 +72713,7 @@ async function launchPlatform(options) {
73546
72713
  }
73547
72714
  init_container();
73548
72715
  init_discover_adapters();
73549
- init_remote_adapter();
73550
- init_vector_store_proxy();
73551
- init_cache_proxy();
73552
- init_llm_proxy();
73553
- init_embeddings_proxy();
73554
- init_storage_proxy();
73555
- init_remote_adapter();
73556
- init_remote_adapter();
73557
- init_unix_socket_transport();
73558
- init_cache_proxy();
73559
- init_llm_proxy();
73560
- init_embeddings_proxy();
73561
- init_vector_store_proxy();
73562
- init_storage_proxy();
73563
- init_remote_adapter();
72716
+ init_bulk_transfer();
73564
72717
  init_container();
73565
72718
  init_adapter_status();
73566
72719