@nextclaw/kernel 0.7.0 → 0.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10,7 +10,7 @@ import { catchError, filter, from, lastValueFrom, tap } from "rxjs";
10
10
  import { appendFileSync, chmodSync, constants, createReadStream, existsSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, writeFileSync } from "node:fs";
11
11
  import path, { basename, delimiter, dirname, extname, isAbsolute, join, normalize, relative, resolve, sep } from "node:path";
12
12
  import { access, appendFile, mkdir, mkdtemp, open, readFile, readdir, realpath, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
13
- import { AppHomeService, AppInstallationService, AppInstanceStorageService, AppManifestService, AppRegistryService, isAppComponentManifestBundle } from "@nextclaw/app-runtime";
13
+ import { AppHomeService, AppInstallationService, AppInstanceInventoryService, AppInstanceStorageService, AppManifestService, AppRegistryService, FileLockService, isAppComponentManifestBundle } from "@nextclaw/app-runtime";
14
14
  import { execFileSync, spawn } from "node:child_process";
15
15
  import { fileURLToPath } from "node:url";
16
16
  import { BUILTIN_PROVIDER_PLUGINS } from "@nextclaw/runtime";
@@ -2876,13 +2876,16 @@ var AppPackageManager = class {
2876
2876
  installRuntimeHooks = (hooks) => {
2877
2877
  this.runtimeHooks = hooks;
2878
2878
  };
2879
- listPackages = async () => {
2880
- await this.ensureBuiltInPackages();
2879
+ start = async () => await this.ensureBuiltInPackages();
2880
+ listPackages = async (options = {}) => {
2881
2881
  const records = await this.registryService.listApps();
2882
- return { entries: await Promise.all(records.map(async (record) => await this.toPackageView(await this.installationService.info(record.appId)))) };
2882
+ return { entries: await Promise.all(records.map(async (record) => await this.toPackageView(await this.installationService.info(record.appId, { measureStorageUsage: options.includeStorageUsage !== false })))) };
2883
2883
  };
2884
+ listInstalledDataOwners = async () => (await this.registryService.listApps()).map((record) => ({
2885
+ id: record.appId,
2886
+ name: record.name
2887
+ }));
2884
2888
  getPackage = async (appId) => {
2885
- await this.ensureBuiltInPackages();
2886
2889
  try {
2887
2890
  return await this.toPackageView(await this.installationService.info(appId));
2888
2891
  } catch (error) {
@@ -2891,7 +2894,6 @@ var AppPackageManager = class {
2891
2894
  }
2892
2895
  };
2893
2896
  listActiveComponentSources = async () => {
2894
- await this.ensureBuiltInPackages();
2895
2897
  const records = await this.registryService.listApps();
2896
2898
  return (await Promise.all(records.filter((record) => record.enabled).map(async (record) => {
2897
2899
  await this.installationService.assertVersionIntegrity(record.appId, record.activeVersion);
@@ -3188,6 +3190,165 @@ var AppPackageManager = class {
3188
3190
  isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
3189
3191
  };
3190
3192
  //#endregion
3193
+ //#region src/types/app-data.types.ts
3194
+ var AppDataError = class extends Error {
3195
+ constructor(code, message) {
3196
+ super(message);
3197
+ this.code = code;
3198
+ this.name = "AppDataError";
3199
+ }
3200
+ };
3201
+ function isAppDataError(error) {
3202
+ return error instanceof AppDataError;
3203
+ }
3204
+ //#endregion
3205
+ //#region src/managers/app-data.manager.ts
3206
+ const DATA_ID_PREFIX = "ad1.";
3207
+ const SAFE_ID_PATTERN = /^[a-z0-9]+(?:[.-][a-z0-9]+)*$/;
3208
+ const WORKSPACE_SCOPE_PATTERN = /^[a-f0-9]{16}$/;
3209
+ var AppDataManager = class {
3210
+ appHomeService;
3211
+ fileLockService = new FileLockService();
3212
+ inventoryService = new AppInstanceInventoryService();
3213
+ reconciliationDiagnostics = [];
3214
+ constructor(params) {
3215
+ this.params = params;
3216
+ this.appHomeService = new AppHomeService(params.appHomeDirectory);
3217
+ }
3218
+ start = async () => {
3219
+ const workspacePath = path.resolve(this.params.getWorkspacePath());
3220
+ const [packageDiagnostics, workspaceDiagnostics] = await Promise.all([this.inventoryService.reconcileDeletions(this.appHomeService.getInstancesDirectory()), this.inventoryService.reconcileDeletions(this.getWorkspaceInstancesRoot(workspacePath))]);
3221
+ this.reconciliationDiagnostics = [...packageDiagnostics.map((entry) => ({
3222
+ ...entry,
3223
+ source: "package"
3224
+ })), ...workspaceDiagnostics.map((entry) => ({
3225
+ ...entry,
3226
+ source: "workspace-service"
3227
+ }))];
3228
+ };
3229
+ list = async () => {
3230
+ const workspacePath = path.resolve(this.params.getWorkspacePath());
3231
+ const workspaceInstancesRoot = this.getWorkspaceInstancesRoot(workspacePath);
3232
+ const [packageInventory, workspaceInventory, packageList, workspaceOwners] = await Promise.all([
3233
+ this.inventoryService.list(this.appHomeService.getInstancesDirectory()),
3234
+ this.inventoryService.list(workspaceInstancesRoot),
3235
+ this.params.listInstalledPackageOwners(),
3236
+ this.params.listWorkspaceDataOwners()
3237
+ ]);
3238
+ const packageOwners = new Map(packageList.map((entry) => [entry.id, entry]));
3239
+ const workspaceOwnerMap = new Map(workspaceOwners.map((entry) => [entry.id, entry]));
3240
+ const workspaceScope = this.workspaceScope(workspacePath);
3241
+ const entries = [...packageInventory.entries.map((entry) => this.toEntry({
3242
+ entry,
3243
+ source: "package",
3244
+ displayName: packageOwners.get(entry.appId)?.name ?? entry.appId,
3245
+ active: packageOwners.has(entry.appId)
3246
+ })), ...workspaceInventory.entries.map((entry) => this.toEntry({
3247
+ entry,
3248
+ source: "workspace-service",
3249
+ displayName: workspaceOwnerMap.get(entry.appId)?.title ?? entry.appId,
3250
+ active: workspaceOwnerMap.has(entry.appId),
3251
+ scope: workspaceScope
3252
+ }))].sort((left, right) => left.displayName.localeCompare(right.displayName) || left.id.localeCompare(right.id));
3253
+ const currentDiagnostics = [...packageInventory.diagnostics.map((diagnostic) => ({
3254
+ ...diagnostic,
3255
+ source: "package"
3256
+ })), ...workspaceInventory.diagnostics.map((diagnostic) => ({
3257
+ ...diagnostic,
3258
+ source: "workspace-service"
3259
+ }))];
3260
+ const currentDiagnosticKeys = new Set(currentDiagnostics.map((entry) => `${entry.source}:${entry.instanceDirectory}`));
3261
+ const diagnostics = /* @__PURE__ */ new Map();
3262
+ for (const entry of [...currentDiagnostics, ...this.reconciliationDiagnostics.filter((diagnostic) => currentDiagnosticKeys.has(`${diagnostic.source}:${diagnostic.instanceDirectory}`))]) diagnostics.set(`${entry.source}:${entry.instanceDirectory}`, entry);
3263
+ return {
3264
+ entries,
3265
+ diagnostics: Array.from(diagnostics.values())
3266
+ };
3267
+ };
3268
+ deleteRetained = async (dataId, confirmAppId) => {
3269
+ const payload = this.parseDataId(dataId);
3270
+ if (confirmAppId !== payload.appId) throw new AppDataError("APP_DATA_CONFIRMATION_MISMATCH", `确认的 App id 与目标不一致:${confirmAppId || "(empty)"}`);
3271
+ if (payload.source === "package") await this.deletePackageData(payload);
3272
+ else await this.deleteWorkspaceData(payload);
3273
+ return {
3274
+ deleted: true,
3275
+ id: dataId,
3276
+ appId: payload.appId,
3277
+ instanceId: payload.instanceId
3278
+ };
3279
+ };
3280
+ deletePackageData = async (payload) => {
3281
+ await this.fileLockService.withLock(this.appHomeService.getAppOperationLockPath(payload.appId), async () => {
3282
+ await this.inventoryService.purge({
3283
+ instancesRoot: this.appHomeService.getInstancesDirectory(),
3284
+ appId: payload.appId,
3285
+ instanceId: payload.instanceId,
3286
+ assertCanPurge: async () => {
3287
+ if (await this.isPackageActive(payload.appId)) throw new AppDataError("APP_DATA_ACTIVE", `应用 ${payload.appId} 仍已安装,请通过卸载入口处理其数据。`);
3288
+ }
3289
+ });
3290
+ }).catch((error) => this.rethrowMissing(error, payload));
3291
+ };
3292
+ deleteWorkspaceData = async (payload) => {
3293
+ const workspacePath = path.resolve(this.params.getWorkspacePath());
3294
+ if (payload.scope !== this.workspaceScope(workspacePath)) throw new AppDataError("APP_DATA_INVALID_ID", "App data id 不属于当前 workspace。");
3295
+ const lockPath = path.join(workspacePath, ".nextclaw", "locks", "service-apps", `${payload.appId}.lock`);
3296
+ await this.fileLockService.withLock(lockPath, async () => {
3297
+ await this.inventoryService.purge({
3298
+ instancesRoot: this.getWorkspaceInstancesRoot(workspacePath),
3299
+ appId: payload.appId,
3300
+ instanceId: payload.instanceId,
3301
+ assertCanPurge: async () => {
3302
+ if (await this.isWorkspaceServiceActive(payload.appId)) throw new AppDataError("APP_DATA_ACTIVE", `Service App ${payload.appId} 仍在 workspace 中,请通过 Service Apps 删除入口处理其数据。`);
3303
+ }
3304
+ });
3305
+ }).catch((error) => this.rethrowMissing(error, payload));
3306
+ };
3307
+ toEntry = (params) => {
3308
+ const { active, displayName, entry, scope, source } = params;
3309
+ return {
3310
+ id: this.createDataId({
3311
+ version: 1,
3312
+ source,
3313
+ appId: entry.appId,
3314
+ instanceId: entry.instanceId,
3315
+ scope
3316
+ }),
3317
+ appId: entry.appId,
3318
+ instanceId: entry.instanceId,
3319
+ publisherId: entry.publisherId,
3320
+ displayName,
3321
+ source,
3322
+ lifecycle: active ? "active" : "retained",
3323
+ storage: entry.storage,
3324
+ usage: entry.usage,
3325
+ createdAt: entry.createdAt,
3326
+ migratedAt: entry.migratedAt,
3327
+ actions: { deleteRetainedData: !active }
3328
+ };
3329
+ };
3330
+ createDataId = (payload) => `${DATA_ID_PREFIX}${Buffer.from(JSON.stringify(payload), "utf8").toString("base64url")}`;
3331
+ parseDataId = (dataId) => {
3332
+ try {
3333
+ if (!dataId.startsWith(DATA_ID_PREFIX)) throw new Error("prefix");
3334
+ const raw = JSON.parse(Buffer.from(dataId.slice(4), "base64url").toString("utf8"));
3335
+ if (raw.version !== 1 || raw.source !== "package" && raw.source !== "workspace-service" || typeof raw.appId !== "string" || !SAFE_ID_PATTERN.test(raw.appId) || typeof raw.instanceId !== "string" || !SAFE_ID_PATTERN.test(raw.instanceId) || raw.source === "package" && raw.scope !== void 0 || raw.source === "workspace-service" && (typeof raw.scope !== "string" || !WORKSPACE_SCOPE_PATTERN.test(raw.scope))) throw new Error("shape");
3336
+ return raw;
3337
+ } catch {
3338
+ throw new AppDataError("APP_DATA_INVALID_ID", "App data id 无效。");
3339
+ }
3340
+ };
3341
+ isPackageActive = async (appId) => (await this.params.listInstalledPackageOwners()).some((entry) => entry.id === appId);
3342
+ isWorkspaceServiceActive = async (appId) => (await this.params.listWorkspaceDataOwners()).some((entry) => entry.id === appId);
3343
+ getWorkspaceInstancesRoot = (workspacePath) => path.join(workspacePath, ".nextclaw", "app-instances");
3344
+ workspaceScope = (workspacePath) => createHash("sha256").update(workspacePath).digest("hex").slice(0, 16);
3345
+ rethrowMissing = (error, payload) => {
3346
+ if (error instanceof Error && (error.message.includes("metadata 不存在") || this.isMissingFileError(error))) throw new AppDataError("APP_DATA_NOT_FOUND", `未找到 App 数据:${payload.appId}/${payload.instanceId}`);
3347
+ throw error;
3348
+ };
3349
+ isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
3350
+ };
3351
+ //#endregion
3191
3352
  //#region src/managers/channel.manager.ts
3192
3353
  var ChannelManager = class {
3193
3354
  channels = {};
@@ -9879,7 +10040,7 @@ var McpServiceAppRuntimeService = class {
9879
10040
  };
9880
10041
  //#endregion
9881
10042
  //#region src/utils/service-app-manifest.utils.ts
9882
- const SERVICE_APP_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
10043
+ const SERVICE_APP_ID_PATTERN$1 = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
9883
10044
  const SERVICE_ACTION_RISKS = new Set([
9884
10045
  "read",
9885
10046
  "write",
@@ -9902,7 +10063,7 @@ function parseServiceAppManifest(raw) {
9902
10063
  }
9903
10064
  if (!isRecord$9(parsed)) throw new Error("service-app.json must contain an object.");
9904
10065
  const id = readRequiredString$6(parsed, "id");
9905
- if (!SERVICE_APP_ID_PATTERN.test(id)) throw new Error("service app id must be kebab-case.");
10066
+ if (!SERVICE_APP_ID_PATTERN$1.test(id)) throw new Error("service app id must be kebab-case.");
9906
10067
  const protocol = readOptionalString$7(parsed, "protocol") ?? "mcp";
9907
10068
  if (protocol !== "mcp") throw new Error("service app protocol must be mcp.");
9908
10069
  return {
@@ -9969,7 +10130,8 @@ var ServiceAppRecordService = class {
9969
10130
  const dirPath = join(serviceAppsPath, dirName);
9970
10131
  try {
9971
10132
  const manifest = await readServiceAppManifest(dirPath);
9972
- return this.fromManifest(dirPath, manifest, void 0, await this.materializeWorkspaceStorage(manifest.id));
10133
+ if (manifest.id !== dirName) throw new Error(`service app manifest id must match directory name: ${dirName}`);
10134
+ return this.fromManifest(dirPath, manifest, void 0, await this.inspectWorkspaceStorage(manifest.id));
9973
10135
  } catch (error) {
9974
10136
  if (this.isMissingFileError(error)) return null;
9975
10137
  return this.failedWorkspaceRecord(dirName, dirPath, error);
@@ -9984,14 +10146,36 @@ var ServiceAppRecordService = class {
9984
10146
  return this.failedPackageRecord(source, error);
9985
10147
  }
9986
10148
  };
10149
+ listWorkspaceDataOwners = async (serviceAppsPath, dirNames) => {
10150
+ return (await Promise.all(dirNames.map(async (dirName) => {
10151
+ try {
10152
+ const manifest = await readServiceAppManifest(join(serviceAppsPath, dirName));
10153
+ return manifest.id === dirName ? {
10154
+ id: manifest.id,
10155
+ title: manifest.title
10156
+ } : null;
10157
+ } catch {
10158
+ return null;
10159
+ }
10160
+ }))).filter((entry) => Boolean(entry));
10161
+ };
9987
10162
  materializeWorkspaceStorage = async (serviceId) => {
9988
- const instanceDirectory = join(this.params.getWorkspacePath(), ".nextclaw", "app-instances", serviceId, "default");
10163
+ const instanceDirectory = this.getWorkspaceInstanceDirectory(serviceId);
9989
10164
  return (await this.instanceStorageService.materialize({
9990
10165
  appId: serviceId,
9991
10166
  instanceId: "default",
9992
10167
  instanceDirectory
9993
10168
  })).storage;
9994
10169
  };
10170
+ inspectWorkspaceStorage = async (serviceId) => {
10171
+ const instanceDirectory = this.getWorkspaceInstanceDirectory(serviceId);
10172
+ if (!await this.pathExists(instanceDirectory)) return;
10173
+ return (await this.instanceStorageService.inspect({
10174
+ appId: serviceId,
10175
+ instanceId: "default",
10176
+ instanceDirectory
10177
+ })).storage;
10178
+ };
9995
10179
  fromManifest = (dirPath, manifest, packageSource, storage) => {
9996
10180
  const runtimeStatus = this.params.runtimeService.getStatus(manifest.id);
9997
10181
  return {
@@ -10051,9 +10235,146 @@ var ServiceAppRecordService = class {
10051
10235
  isolation: source.isolation
10052
10236
  });
10053
10237
  toTitle = (value) => basename(value).replace(/[-_]+/g, " ").trim() || value;
10238
+ getWorkspaceInstanceDirectory = (serviceId) => join(this.params.getWorkspacePath(), ".nextclaw", "app-instances", serviceId, "default");
10239
+ pathExists = async (targetPath) => {
10240
+ try {
10241
+ await access(targetPath);
10242
+ return true;
10243
+ } catch (error) {
10244
+ if (this.isMissingFileError(error)) return false;
10245
+ throw error;
10246
+ }
10247
+ };
10054
10248
  isMissingFileError = (error) => typeof error === "object" && error !== null && error.code === "ENOENT";
10055
10249
  };
10056
10250
  //#endregion
10251
+ //#region src/services/service-app-removal.service.ts
10252
+ const TRANSACTION_ID = "[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}";
10253
+ const CURRENT_DELETION_PATTERN = new RegExp(`^\\.deleting-(?<appId>[a-z0-9]+(?:-[a-z0-9]+)*)-(?<transactionId>${TRANSACTION_ID})$`);
10254
+ const LEGACY_DELETION_PATTERN = new RegExp(`^(?<appId>[a-z0-9]+(?:-[a-z0-9]+)*)\\.deleting-(?<transactionId>${TRANSACTION_ID})$`);
10255
+ function isServiceAppDeletionTombstone(directoryName) {
10256
+ return Boolean(parseServiceAppDeletionTombstone(directoryName));
10257
+ }
10258
+ var ServiceAppRemovalCleanupError = class extends Error {
10259
+ constructor(cause) {
10260
+ super(`临时目录清理失败:${cause instanceof Error ? cause.message : String(cause)}`);
10261
+ this.cause = cause;
10262
+ this.name = "ServiceAppRemovalCleanupError";
10263
+ }
10264
+ };
10265
+ var ServiceAppRemovalService = class {
10266
+ fileLockService = new FileLockService();
10267
+ listCanonicalDirectoryNames = async (serviceAppsPath) => (await this.listDirectories(serviceAppsPath)).filter((directoryName) => !directoryName.startsWith(".") && !isServiceAppDeletionTombstone(directoryName));
10268
+ remove = async (params) => await this.fileLockService.withLock(params.lockPath, async () => {
10269
+ const record = await params.loadRecord();
10270
+ await this.removeLocked({
10271
+ ...params,
10272
+ record
10273
+ });
10274
+ return record;
10275
+ });
10276
+ reconcile = async (params) => {
10277
+ const { grantStore, lockPathForAppId, serviceAppsPath } = params;
10278
+ const diagnostics = [];
10279
+ for (const directoryName of await this.listDirectories(serviceAppsPath)) {
10280
+ const appId = parseServiceAppDeletionTombstone(directoryName);
10281
+ if (!appId) continue;
10282
+ const stagedPath = join(serviceAppsPath, directoryName);
10283
+ const canonicalPath = join(serviceAppsPath, appId);
10284
+ try {
10285
+ await this.fileLockService.withLock(lockPathForAppId(appId), async () => {
10286
+ const manifest = await readServiceAppManifest(stagedPath);
10287
+ if (manifest.id !== appId) throw new Error(`Service App 删除墓碑 identity 不匹配:${manifest.id}`);
10288
+ if (!await this.pathExists(canonicalPath)) await grantStore.revokeActionsByPrefix(`${appId}.`);
10289
+ await rm(stagedPath, { recursive: true });
10290
+ });
10291
+ } catch (error) {
10292
+ diagnostics.push({
10293
+ appId,
10294
+ stagedPath,
10295
+ message: error instanceof Error ? error.message : String(error)
10296
+ });
10297
+ }
10298
+ }
10299
+ return diagnostics.sort((left, right) => left.stagedPath.localeCompare(right.stagedPath));
10300
+ };
10301
+ removeLocked = async (params) => {
10302
+ const { grantStore, purgeData, record, stopRuntime } = params;
10303
+ const grants = (await grantStore.list()).filter((grant) => grant.actionId.startsWith(`${record.id}.`));
10304
+ const stagedPaths = [];
10305
+ try {
10306
+ await stopRuntime(record);
10307
+ await this.stageSourcePath(record.dirPath, stagedPaths);
10308
+ if (purgeData && record.storage) await this.stageInstancePath(record.storage.instanceDirectory, stagedPaths);
10309
+ await grantStore.revokeActionsByPrefix(`${record.id}.`);
10310
+ } catch (error) {
10311
+ const recoveryErrors = [...await this.restoreStagedPaths(stagedPaths), ...await this.restoreGrants(grantStore, grants)];
10312
+ if (recoveryErrors.length > 0) throw new AggregateError([error, ...recoveryErrors], `Service App ${record.id} 删除失败,且恢复未完整完成。`);
10313
+ throw error;
10314
+ }
10315
+ try {
10316
+ await Promise.all(stagedPaths.map(async ({ stagedPath }) => await rm(stagedPath, { recursive: true })));
10317
+ } catch (error) {
10318
+ throw new ServiceAppRemovalCleanupError(error);
10319
+ }
10320
+ };
10321
+ stageSourcePath = async (originalPath, stagedPaths) => {
10322
+ const stagedPath = join(dirname(originalPath), `.deleting-${basename(originalPath)}-${randomUUID()}`);
10323
+ await rename(originalPath, stagedPath);
10324
+ stagedPaths.push({
10325
+ originalPath,
10326
+ stagedPath
10327
+ });
10328
+ };
10329
+ stageInstancePath = async (originalPath, stagedPaths) => {
10330
+ const stagedPath = `${originalPath}.deleting-${randomUUID()}`;
10331
+ await rename(originalPath, stagedPath);
10332
+ stagedPaths.push({
10333
+ originalPath,
10334
+ stagedPath
10335
+ });
10336
+ };
10337
+ listDirectories = async (directory) => {
10338
+ try {
10339
+ return (await readdir(directory, { withFileTypes: true })).filter((entry) => entry.isDirectory()).map((entry) => entry.name);
10340
+ } catch (error) {
10341
+ if (this.isMissingFileError(error)) return [];
10342
+ throw error;
10343
+ }
10344
+ };
10345
+ pathExists = async (targetPath) => {
10346
+ try {
10347
+ await access(targetPath);
10348
+ return true;
10349
+ } catch (error) {
10350
+ if (this.isMissingFileError(error)) return false;
10351
+ throw error;
10352
+ }
10353
+ };
10354
+ isMissingFileError = (error) => typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
10355
+ restoreStagedPaths = async (stagedPaths) => {
10356
+ const errors = [];
10357
+ for (const entry of [...stagedPaths].reverse()) try {
10358
+ await rename(entry.stagedPath, entry.originalPath);
10359
+ } catch (error) {
10360
+ errors.push(error);
10361
+ }
10362
+ return errors;
10363
+ };
10364
+ restoreGrants = async (grantStore, grants) => {
10365
+ const errors = [];
10366
+ for (const grant of grants) try {
10367
+ await grantStore.grant(grant);
10368
+ } catch (error) {
10369
+ errors.push(error);
10370
+ }
10371
+ return errors;
10372
+ };
10373
+ };
10374
+ function parseServiceAppDeletionTombstone(directoryName) {
10375
+ return CURRENT_DELETION_PATTERN.exec(directoryName)?.groups?.appId ?? LEGACY_DELETION_PATTERN.exec(directoryName)?.groups?.appId;
10376
+ }
10377
+ //#endregion
10057
10378
  //#region src/stores/service-action-grant.store.ts
10058
10379
  const EMPTY_GRANTS = {
10059
10380
  version: 1,
@@ -10192,6 +10513,7 @@ function mergeServiceAppRuntimeActions({ record, manifest, runtimeActions }) {
10192
10513
  //#endregion
10193
10514
  //#region src/managers/service-app.manager.ts
10194
10515
  const SERVICE_ACTION_GRANTS_FILE_NAME = ".service-action-grants.json";
10516
+ const SERVICE_APP_ID_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
10195
10517
  var ServiceAppError = class extends Error {
10196
10518
  constructor(code, message) {
10197
10519
  super(message);
@@ -10199,12 +10521,12 @@ var ServiceAppError = class extends Error {
10199
10521
  this.name = "ServiceAppError";
10200
10522
  }
10201
10523
  };
10202
- function isServiceAppError(error) {
10203
- return error instanceof ServiceAppError;
10204
- }
10524
+ const isServiceAppError = (error) => error instanceof ServiceAppError;
10205
10525
  var ServiceAppManager = class {
10526
+ removalService = new ServiceAppRemovalService();
10206
10527
  runtimeService;
10207
10528
  recordService;
10529
+ reconciliationDiagnostics = [];
10208
10530
  constructor(params) {
10209
10531
  this.params = params;
10210
10532
  this.runtimeService = params.runtimeService ?? new McpServiceAppRuntimeService({ getConfig: () => params.configManager.config });
@@ -10213,6 +10535,13 @@ var ServiceAppManager = class {
10213
10535
  runtimeService: this.runtimeService
10214
10536
  });
10215
10537
  }
10538
+ start = async () => {
10539
+ this.reconciliationDiagnostics = await this.removalService.reconcile({
10540
+ grantStore: this.createGrantStore(),
10541
+ lockPathForAppId: (appId) => this.getServiceAppLockPath(this.getWorkspacePath(), appId),
10542
+ serviceAppsPath: this.getServiceAppsPath(this.getWorkspacePath())
10543
+ });
10544
+ };
10216
10545
  listServiceApps = async () => {
10217
10546
  const workspacePath = this.getWorkspacePath();
10218
10547
  const serviceAppsPath = this.getServiceAppsPath(workspacePath);
@@ -10223,6 +10552,7 @@ var ServiceAppManager = class {
10223
10552
  return {
10224
10553
  workspacePath,
10225
10554
  serviceAppsPath,
10555
+ diagnostics: this.reconciliationDiagnostics,
10226
10556
  entries: [...workspaceEntries, ...packageEntries].filter((entry) => Boolean(entry)).sort((left, right) => left.title.localeCompare(right.title))
10227
10557
  };
10228
10558
  };
@@ -10235,7 +10565,7 @@ var ServiceAppManager = class {
10235
10565
  return await Promise.all(actions.map(async (action) => await this.withGrantState(action, params)));
10236
10566
  };
10237
10567
  discoverServiceAppActions = async (appId) => {
10238
- const { manifest, record } = await this.requireServiceApp(appId);
10568
+ const { manifest, record } = await this.requireServiceApp(appId, true);
10239
10569
  return mergeServiceAppRuntimeActions({
10240
10570
  record,
10241
10571
  manifest,
@@ -10248,7 +10578,7 @@ var ServiceAppManager = class {
10248
10578
  invokeServiceAction = async (actionId, request) => {
10249
10579
  this.assertCaller(request.caller);
10250
10580
  this.assertDeclaredAction(actionId, request.declaredActions);
10251
- const { manifest, record } = await this.requireServiceAppForAction(actionId);
10581
+ const { manifest, record } = await this.requireServiceAppForAction(actionId, true);
10252
10582
  const actionName = getServiceActionName(actionId, record.id);
10253
10583
  if (!Object.hasOwn(manifest.actions, actionName)) throw new ServiceAppError("SERVICE_APP_ACTION_NOT_FOUND", "service action not found");
10254
10584
  const declaredRisk = manifest.actions[actionName]?.risk ?? "dangerous";
@@ -10300,20 +10630,34 @@ var ServiceAppManager = class {
10300
10630
  await this.runtimeService.restart(record.id);
10301
10631
  return await this.getServiceApp(appId);
10302
10632
  };
10303
- deleteServiceApp = async (appId) => {
10304
- const { record } = await this.requireServiceApp(appId);
10305
- if (record.sourceKind === "package") throw new ServiceAppError("SERVICE_APP_MANAGED_SOURCE", `package service must be managed through Apps: ${record.packageId}`);
10306
- await this.runtimeService.restart(record.id);
10307
- await rm(record.dirPath, { recursive: true });
10308
- await this.createGrantStore().revokeActionsByPrefix(`${record.id}.`);
10633
+ listWorkspaceDataOwners = async () => await this.recordService.listWorkspaceDataOwners(this.getServiceAppsPath(this.getWorkspacePath()), await this.listServiceAppDirNames(this.getServiceAppsPath(this.getWorkspacePath())));
10634
+ deleteServiceApp = async (appId, purgeData = false) => {
10635
+ if (!SERVICE_APP_ID_PATTERN.test(appId)) throw new ServiceAppError("SERVICE_APP_INVALID_MANIFEST", "service app id must use kebab-case");
10636
+ const workspacePath = this.getWorkspacePath();
10637
+ let record;
10638
+ try {
10639
+ record = await this.removalService.remove({
10640
+ grantStore: this.createGrantStore(),
10641
+ lockPath: this.getServiceAppLockPath(workspacePath, appId),
10642
+ purgeData,
10643
+ loadRecord: async () => {
10644
+ const { record } = await this.requireServiceApp(appId);
10645
+ if (record.sourceKind === "package") throw new ServiceAppError("SERVICE_APP_MANAGED_SOURCE", `package service must be managed through Apps: ${record.packageId}`);
10646
+ return record;
10647
+ },
10648
+ stopRuntime: async (loaded) => await this.runtimeService.restart(loaded.id)
10649
+ });
10650
+ } catch (error) {
10651
+ if (error instanceof ServiceAppRemovalCleanupError) throw new ServiceAppError("SERVICE_APP_RUNTIME_FAILED", `Service App ${appId} 已从 workspace 移除,但${error.message}`);
10652
+ throw error;
10653
+ }
10309
10654
  return {
10310
10655
  deleted: true,
10311
- id: record.id
10656
+ id: record.id,
10657
+ dataRemoved: purgeData
10312
10658
  };
10313
10659
  };
10314
- dispose = async () => {
10315
- await this.runtimeService.dispose();
10316
- };
10660
+ dispose = async () => await this.runtimeService.dispose();
10317
10661
  assertCanActivatePackageComponents = async (components) => {
10318
10662
  const serviceComponents = components.filter((component) => component.kind === "service");
10319
10663
  if (serviceComponents.length === 0) return;
@@ -10382,12 +10726,12 @@ var ServiceAppManager = class {
10382
10726
  if (!action) throw new ServiceAppError("SERVICE_APP_ACTION_NOT_FOUND", "service action not found");
10383
10727
  return action;
10384
10728
  };
10385
- requireServiceAppForAction = async (actionId) => {
10729
+ requireServiceAppForAction = async (actionId, materializeStorage = false) => {
10386
10730
  const appId = actionId.split(".")[0]?.trim();
10387
10731
  if (!appId) throw new ServiceAppError("SERVICE_APP_INVALID_ACTION", "service action id is invalid");
10388
- return await this.requireServiceApp(appId);
10732
+ return await this.requireServiceApp(appId, materializeStorage);
10389
10733
  };
10390
- requireServiceApp = async (appId) => {
10734
+ requireServiceApp = async (appId, materializeStorage = false) => {
10391
10735
  let dirPath = join(this.getServiceAppsPath(this.getWorkspacePath()), appId);
10392
10736
  let packageSource;
10393
10737
  try {
@@ -10402,9 +10746,10 @@ var ServiceAppManager = class {
10402
10746
  if (!(await stat(dirPath)).isDirectory()) throw new ServiceAppError("SERVICE_APP_NOT_FOUND", "service app not found");
10403
10747
  const manifest = await readServiceAppManifest(dirPath);
10404
10748
  if (manifest.id !== appId) throw new ServiceAppError("SERVICE_APP_INVALID_MANIFEST", "service app manifest id must match directory name");
10749
+ const storage = packageSource?.storage ?? (materializeStorage ? await this.recordService.materializeWorkspaceStorage(manifest.id) : await this.recordService.inspectWorkspaceStorage(manifest.id));
10405
10750
  return {
10406
10751
  manifest,
10407
- record: this.recordService.fromManifest(dirPath, manifest, packageSource, packageSource?.storage ?? await this.recordService.materializeWorkspaceStorage(manifest.id))
10752
+ record: this.recordService.fromManifest(dirPath, manifest, packageSource, storage)
10408
10753
  };
10409
10754
  } catch (error) {
10410
10755
  if (isServiceAppError(error)) throw error;
@@ -10422,7 +10767,7 @@ var ServiceAppManager = class {
10422
10767
  const manifest = await readServiceAppManifest(dirPath);
10423
10768
  return {
10424
10769
  manifest,
10425
- record: this.recordService.fromManifest(dirPath, manifest, void 0, await this.recordService.materializeWorkspaceStorage(manifest.id))
10770
+ record: this.recordService.fromManifest(dirPath, manifest, void 0, await this.recordService.inspectWorkspaceStorage(manifest.id))
10426
10771
  };
10427
10772
  } catch {
10428
10773
  return null;
@@ -10450,13 +10795,13 @@ var ServiceAppManager = class {
10450
10795
  normalizeActionIds = (actionIds) => Array.from(new Set(actionIds.map((actionId) => actionId.trim()).filter((actionId) => actionId.length > 0)));
10451
10796
  getWorkspacePath = () => getWorkspacePathFromConfig(this.params.configManager.config);
10452
10797
  getServiceAppsPath = (workspacePath) => join(workspacePath, DEFAULT_SERVICE_APPS_DIR);
10798
+ getServiceAppLockPath = (workspacePath, appId) => join(workspacePath, ".nextclaw", "locks", "service-apps", `${appId}.lock`);
10453
10799
  createGrantStore = () => new ServiceActionGrantStore(join(this.getServiceAppsPath(this.getWorkspacePath()), SERVICE_ACTION_GRANTS_FILE_NAME));
10454
10800
  listPackageComponentSources = async () => await this.params.listPackageComponentSources?.() ?? [];
10455
10801
  listServiceAppDirNames = async (serviceAppsPath) => {
10456
10802
  try {
10457
- return (await readdir(serviceAppsPath, { withFileTypes: true })).filter((entry) => entry.isDirectory() && !entry.name.startsWith(".")).map((entry) => entry.name);
10803
+ return await this.removalService.listCanonicalDirectoryNames(serviceAppsPath);
10458
10804
  } catch (error) {
10459
- if (this.isMissingFileError(error)) return [];
10460
10805
  throw new ServiceAppError("SERVICE_APP_READ_FAILED", error instanceof Error ? error.message : String(error));
10461
10806
  }
10462
10807
  };
@@ -15515,35 +15860,48 @@ var ToolProviderContribution = class {
15515
15860
  };
15516
15861
  };
15517
15862
  //#endregion
15518
- //#region src/app/nextclaw-kernel.ts
15863
+ //#region src/app/kernel-storage-paths.ts
15519
15864
  function resolveKernelAppHomeDirectory(options) {
15520
15865
  const homeDir = options.homeDir?.trim();
15521
15866
  return resolve(homeDir ? expandHome(homeDir) : getDataDir(), "apps");
15522
15867
  }
15523
15868
  function resolveKernelSessionsDir(options) {
15524
15869
  const homeDir = options.homeDir?.trim();
15525
- if (homeDir) return ensureDir(resolve(expandHome(homeDir), "sessions"));
15526
- return getSessionsPath();
15870
+ return homeDir ? ensureDir(resolve(expandHome(homeDir), "sessions")) : getSessionsPath();
15527
15871
  }
15528
15872
  function resolveKernelAutomationStorePath(options) {
15529
- const homeDir = options.homeDir?.trim();
15530
- if (homeDir) return resolve(expandHome(homeDir), "cron", "jobs.json");
15531
- return resolve(getDataDir(), "cron", "jobs.json");
15873
+ return resolveKernelDataPath(options, "cron", "jobs.json");
15532
15874
  }
15533
15875
  function resolveKernelPreferenceStorePath(options) {
15534
- const homeDir = options.homeDir?.trim();
15535
- if (homeDir) return resolve(expandHome(homeDir), "preferences", "preferences.json");
15536
- return resolve(getDataDir(), "preferences", "preferences.json");
15876
+ return resolveKernelDataPath(options, "preferences", "preferences.json");
15537
15877
  }
15538
15878
  function resolveKernelProjectStorePath(options) {
15539
- const homeDir = options.homeDir?.trim();
15540
- if (homeDir) return resolve(expandHome(homeDir), "projects", "projects.json");
15541
- return resolve(getDataDir(), "projects", "projects.json");
15879
+ return resolveKernelDataPath(options, "projects", "projects.json");
15542
15880
  }
15543
15881
  function resolveKernelInboxDeliveryStorePath(options) {
15882
+ return resolveKernelDataPath(options, "inbox", "deliveries.json");
15883
+ }
15884
+ function resolveKernelDataPath(options, ...segments) {
15544
15885
  const homeDir = options.homeDir?.trim();
15545
- if (homeDir) return resolve(expandHome(homeDir), "inbox", "deliveries.json");
15546
- return resolve(getDataDir(), "inbox", "deliveries.json");
15886
+ return resolve(homeDir ? expandHome(homeDir) : getDataDir(), ...segments);
15887
+ }
15888
+ //#endregion
15889
+ //#region src/app/nextclaw-kernel.ts
15890
+ function createKernelServiceAppManagers(params) {
15891
+ const { appHomeDirectory, appPackageManager, configManager } = params;
15892
+ const serviceAppManager = new ServiceAppManager({
15893
+ configManager,
15894
+ listPackageComponentSources: appPackageManager.listActiveComponentSources
15895
+ });
15896
+ return {
15897
+ serviceAppManager,
15898
+ appDataManager: new AppDataManager({
15899
+ appHomeDirectory,
15900
+ getWorkspacePath: () => getWorkspacePathFromConfig(configManager.config),
15901
+ listInstalledPackageOwners: appPackageManager.listInstalledDataOwners,
15902
+ listWorkspaceDataOwners: serviceAppManager.listWorkspaceDataOwners
15903
+ })
15904
+ };
15547
15905
  }
15548
15906
  var NextclawKernelControlManager = class {
15549
15907
  runtimeControl = null;
@@ -15569,6 +15927,7 @@ var NextclawKernel = class {
15569
15927
  skills;
15570
15928
  automation;
15571
15929
  appPackageManager;
15930
+ appDataManager;
15572
15931
  channels;
15573
15932
  sessionRequests;
15574
15933
  sessionSearch;
@@ -15646,10 +16005,11 @@ var NextclawKernel = class {
15646
16005
  listPackageComponentSources: this.appPackageManager.listActiveComponentSources
15647
16006
  });
15648
16007
  this.preferenceManager = new PreferenceManager({ storePath: resolveKernelPreferenceStorePath(options) });
15649
- this.serviceAppManager = new ServiceAppManager({
15650
- configManager: this.configManager,
15651
- listPackageComponentSources: this.appPackageManager.listActiveComponentSources
15652
- });
16008
+ ({appDataManager: this.appDataManager, serviceAppManager: this.serviceAppManager} = createKernelServiceAppManagers({
16009
+ appHomeDirectory: resolveKernelAppHomeDirectory(options),
16010
+ appPackageManager: this.appPackageManager,
16011
+ configManager: this.configManager
16012
+ }));
15653
16013
  this.installAppPackageRuntimeHooks();
15654
16014
  this.extensions = new ExtensionManager({
15655
16015
  configManager: this.configManager,
@@ -15713,6 +16073,9 @@ var NextclawKernel = class {
15713
16073
  };
15714
16074
  getGatewayController = () => this.gatewayController;
15715
16075
  start = async () => {
16076
+ await this.appPackageManager.start();
16077
+ await this.appDataManager.start();
16078
+ await this.serviceAppManager.start();
15716
16079
  this.sessionSearch.start();
15717
16080
  this.mcpManager.start();
15718
16081
  this.providerModelCatalog.start();
@@ -16306,6 +16669,6 @@ function resolveLegacyEventType(message) {
16306
16669
  return `message.${role || "other"}`;
16307
16670
  }
16308
16671
  //#endregion
16309
- export { AUTOMATIC_UPDATE_CHECK_INTERVAL_MS, AccessManager, AgentManager, AgentRunClient, AppPackageError, AppPackageManager, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_CONTINUATION_TEXT, CONTEXT_COMPACTION_PROJECTION_KIND, CONTEXT_COMPACTION_PROJECTION_METADATA_KEY, CONTEXT_COMPACTION_SYSTEM_PREAMBLE, CONTEXT_COMPACTION_TIMELINE_KIND, ChannelManager, CommandRegistry, ConfigManager, ContextCompactionJournalRecoveryService, ContextCompactionPreflightService, DEFAULT_AGENT_RUNTIME_ENTRY_ID, DEFAULT_SERVICE_ACTION_RISK, ExtensionManager, GatewayInboundProcessor, InboxDeliveryError, InboxDeliveryManager, LlmProviderManager, LlmUsageManager, LlmUsageStore, MAX_INBOX_DELIVERY_CONTENT_LENGTH, McpManager, McpServiceAppRuntimeService, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, NEXTCLAW_TIMELINE_KIND_METADATA_KEY, NcpAgentSessionJournalStore, NextclawKernel, PANEL_APP_AGENT_CAPABILITIES, PROJECT_TEMPLATE_IDS, PROVIDER_MODEL_CATALOG_REFRESH_INTERVAL_MS, PanelAppAssetTokenService, PanelAppError, PanelAppManager, PreferenceError, PreferenceManager, ProjectError, ProjectManager, ProviderManagerNcpLLMApi, ProviderModelCatalogManager, SERVICE_APP_MANIFEST_FILE_NAME, ServiceAppError, ServiceAppManager, SessionContextCompactionError, SessionContextCompactionManager, SessionManager, SessionMessageCursorError, SessionRequestManager, SessionSettingsError, SkillManager, SystemObjectReferenceError, SystemObjectReferenceManager, UpdateManifestReader, buildAgentRunSendPayload, buildContextCompactionModelProjection, buildContextCompactionTimelineNcpMessage, buildLlmUsageSummary, buildLocalizedTextMap, buildNextclawNcpRunContext, buildServiceActionId, createAgentRuntimeSessionRequestDispatcher, createAssetTools, createContextCompactionMessageId, createContextWindowSignature, createCronJobSystemObjectProvider, createInboxDeliverySystemObjectProvider, createLlmUsageRecord, describeAgentRuntimeSessionTypes, dispatchAgentRuntimeSessionRequest, dispatchChannelReplyRoute, dispatchPromptOverNcp, getAutomaticUpdateCheckDelay, getServiceActionName, getServiceAppManifestPath, getUiContentParamsBootstrapScript, getUnsignedUpdateManifest, hasLlmUsageTelemetry, injectUiContentParamsBootstrap, isAppPackageError, isContextCompactionProjectionMessage, isContextCompactionTimelineMessage, isContextWindowSnapshot, isInboxDeliveryError, isPanelAppAgentCapability, isPanelAppError, isPreferenceError, isProjectError, isReplyCapableChannel, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError, isSystemObjectReferenceError, listExtensionChannelIds, listServiceAppManifestActions, mergeServiceAppRuntimeActions, normalizeAgentRuntimeSessionTypeIcon, normalizeLlmUsageModel, normalizeOptionalString, parseServiceAppManifest, parseSkillFrontmatter, readContextCompactionCheckpoint, readContextWindowEventSessionId, readLatestContextCompactionCheckpoint, readLearningLoopRuntimeConfig, readMetadataModel, readMetadataThinking, readServiceAppManifest, resolveAgentRuntimeEntries, resolveAutomaticUpdateCheckIntervalMs, resolveChannelReplyRoute, resolveEffectiveModel, resolveLegacyEventType, resolveSessionChannelContext, runGatewayInboundLoop, sanitizeLlmUsage, serializeUnsignedUpdateManifest, shouldRefreshContextWindowDuringStream, shouldRefreshContextWindowImmediately, stripSkillFrontmatter, syncSessionThinkingPreference, toNcpMessages, waitForAgentRuntimeSessionReply };
16672
+ export { AUTOMATIC_UPDATE_CHECK_INTERVAL_MS, AccessManager, AgentManager, AgentRunClient, AppDataError, AppDataManager, AppPackageError, AppPackageManager, AutomationManager, BuiltinNarpRuntimeProviderService, CONTEXT_COMPACTION_CONTINUATION_TEXT, CONTEXT_COMPACTION_PROJECTION_KIND, CONTEXT_COMPACTION_PROJECTION_METADATA_KEY, CONTEXT_COMPACTION_SYSTEM_PREAMBLE, CONTEXT_COMPACTION_TIMELINE_KIND, ChannelManager, CommandRegistry, ConfigManager, ContextCompactionJournalRecoveryService, ContextCompactionPreflightService, DEFAULT_AGENT_RUNTIME_ENTRY_ID, DEFAULT_SERVICE_ACTION_RISK, ExtensionManager, GatewayInboundProcessor, InboxDeliveryError, InboxDeliveryManager, LlmProviderManager, LlmUsageManager, LlmUsageStore, MAX_INBOX_DELIVERY_CONTENT_LENGTH, McpManager, McpServiceAppRuntimeService, NARP_HTTP_RUNTIME_KIND, NARP_STDIO_RUNTIME_KIND, NEXTCLAW_TIMELINE_KIND_METADATA_KEY, NcpAgentSessionJournalStore, NextclawKernel, PANEL_APP_AGENT_CAPABILITIES, PROJECT_TEMPLATE_IDS, PROVIDER_MODEL_CATALOG_REFRESH_INTERVAL_MS, PanelAppAssetTokenService, PanelAppError, PanelAppManager, PreferenceError, PreferenceManager, ProjectError, ProjectManager, ProviderManagerNcpLLMApi, ProviderModelCatalogManager, SERVICE_APP_MANIFEST_FILE_NAME, ServiceAppError, ServiceAppManager, SessionContextCompactionError, SessionContextCompactionManager, SessionManager, SessionMessageCursorError, SessionRequestManager, SessionSettingsError, SkillManager, SystemObjectReferenceError, SystemObjectReferenceManager, UpdateManifestReader, buildAgentRunSendPayload, buildContextCompactionModelProjection, buildContextCompactionTimelineNcpMessage, buildLlmUsageSummary, buildLocalizedTextMap, buildNextclawNcpRunContext, buildServiceActionId, createAgentRuntimeSessionRequestDispatcher, createAssetTools, createContextCompactionMessageId, createContextWindowSignature, createCronJobSystemObjectProvider, createInboxDeliverySystemObjectProvider, createLlmUsageRecord, describeAgentRuntimeSessionTypes, dispatchAgentRuntimeSessionRequest, dispatchChannelReplyRoute, dispatchPromptOverNcp, getAutomaticUpdateCheckDelay, getServiceActionName, getServiceAppManifestPath, getUiContentParamsBootstrapScript, getUnsignedUpdateManifest, hasLlmUsageTelemetry, injectUiContentParamsBootstrap, isAppDataError, isAppPackageError, isContextCompactionProjectionMessage, isContextCompactionTimelineMessage, isContextWindowSnapshot, isInboxDeliveryError, isPanelAppAgentCapability, isPanelAppError, isPreferenceError, isProjectError, isReplyCapableChannel, isServiceAppError, isSessionContextCompactionError, isSessionMessageCursorError, isSessionSettingsError, isSystemObjectReferenceError, listExtensionChannelIds, listServiceAppManifestActions, mergeServiceAppRuntimeActions, normalizeAgentRuntimeSessionTypeIcon, normalizeLlmUsageModel, normalizeOptionalString, parseServiceAppManifest, parseSkillFrontmatter, readContextCompactionCheckpoint, readContextWindowEventSessionId, readLatestContextCompactionCheckpoint, readLearningLoopRuntimeConfig, readMetadataModel, readMetadataThinking, readServiceAppManifest, resolveAgentRuntimeEntries, resolveAutomaticUpdateCheckIntervalMs, resolveChannelReplyRoute, resolveEffectiveModel, resolveLegacyEventType, resolveSessionChannelContext, runGatewayInboundLoop, sanitizeLlmUsage, serializeUnsignedUpdateManifest, shouldRefreshContextWindowDuringStream, shouldRefreshContextWindowImmediately, stripSkillFrontmatter, syncSessionThinkingPreference, toNcpMessages, waitForAgentRuntimeSessionReply };
16310
16673
 
16311
16674
  //# sourceMappingURL=index.js.map