@openspecui/core 2.3.5 → 2.3.7

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.d.mts CHANGED
@@ -306,11 +306,11 @@ declare const DeltaSpecSchema: z.ZodObject<{
306
306
  /** Raw markdown content of the delta spec */
307
307
  content: z.ZodString;
308
308
  }, "strip", z.ZodTypeAny, {
309
- content: string;
310
309
  specId: string;
311
- }, {
312
310
  content: string;
311
+ }, {
313
312
  specId: string;
313
+ content: string;
314
314
  }>;
315
315
  type DeltaSpec = z.infer<typeof DeltaSpecSchema>;
316
316
  /**
@@ -488,11 +488,11 @@ declare const ChangeSchema: z.ZodObject<{
488
488
  /** Raw markdown content of the delta spec */
489
489
  content: z.ZodString;
490
490
  }, "strip", z.ZodTypeAny, {
491
- content: string;
492
491
  specId: string;
493
- }, {
494
492
  content: string;
493
+ }, {
495
494
  specId: string;
495
+ content: string;
496
496
  }>, "many">>;
497
497
  /** Optional metadata */
498
498
  metadata: z.ZodOptional<z.ZodObject<{
@@ -549,8 +549,8 @@ declare const ChangeSchema: z.ZodObject<{
549
549
  } | undefined;
550
550
  design?: string | undefined;
551
551
  deltaSpecs?: {
552
- content: string;
553
552
  specId: string;
553
+ content: string;
554
554
  }[] | undefined;
555
555
  }, {
556
556
  id: string;
@@ -596,8 +596,8 @@ declare const ChangeSchema: z.ZodObject<{
596
596
  } | undefined;
597
597
  design?: string | undefined;
598
598
  deltaSpecs?: {
599
- content: string;
600
599
  specId: string;
600
+ content: string;
601
601
  }[] | undefined;
602
602
  }>;
603
603
  type Change = z.infer<typeof ChangeSchema>;
@@ -803,8 +803,8 @@ declare class OpenSpecAdapter {
803
803
  } | undefined;
804
804
  design?: string | undefined;
805
805
  deltaSpecs?: {
806
- content: string;
807
806
  specId: string;
807
+ content: string;
808
808
  }[] | undefined;
809
809
  }[];
810
810
  archivedCount: number;
@@ -1036,13 +1036,23 @@ interface WatchEvent {
1036
1036
  type PathCallback = (events: WatchEvent[]) => void;
1037
1037
  /** watcher 重建原因 */
1038
1038
  type ProjectWatcherReinitializeReason = 'drop-events' | 'watcher-error' | 'missing-project-dir' | 'project-dir-replaced' | 'manual';
1039
+ type ProjectResidencyEvictionReason = Extract<ProjectWatcherReinitializeReason, 'missing-project-dir' | 'project-dir-replaced'>;
1040
+ type ProjectResidencyStatus = {
1041
+ state: 'active';
1042
+ } | {
1043
+ state: 'evicted';
1044
+ reason: ProjectResidencyEvictionReason;
1045
+ detectedAt: number;
1046
+ };
1039
1047
  /** watcher 运行时状态(用于调试和运维观测) */
1040
1048
  interface ProjectWatcherRuntimeStatus {
1041
1049
  generation: number;
1042
1050
  reinitializeCount: number;
1043
1051
  lastReinitializeReason: ProjectWatcherReinitializeReason | null;
1044
1052
  reinitializeReasonCounts: Readonly<Record<ProjectWatcherReinitializeReason, number>>;
1053
+ projectResidency: ProjectResidencyStatus;
1045
1054
  }
1055
+ type ProjectWatcherRuntimeStatusListener = (status: ProjectWatcherRuntimeStatus) => void;
1046
1056
  /**
1047
1057
  * 项目监听器
1048
1058
  *
@@ -1074,6 +1084,8 @@ declare class ProjectWatcher {
1074
1084
  private reinitializeCount;
1075
1085
  private lastReinitializeReason;
1076
1086
  private reinitializeReasonCounts;
1087
+ private projectResidency;
1088
+ private runtimeStatusListeners;
1077
1089
  constructor(projectDir: string, options?: {
1078
1090
  debounceMs?: number;
1079
1091
  ignore?: string[];
@@ -1159,10 +1171,16 @@ declare class ProjectWatcher {
1159
1171
  * 获取 watcher 运行时状态
1160
1172
  */
1161
1173
  get runtimeStatus(): ProjectWatcherRuntimeStatus;
1174
+ subscribeRuntimeStatus(listener: ProjectWatcherRuntimeStatusListener, options?: {
1175
+ emitCurrent?: boolean;
1176
+ }): () => void;
1162
1177
  /**
1163
1178
  * 记录重建统计
1164
1179
  */
1165
1180
  private markReinitialized;
1181
+ private markProjectResidencyActive;
1182
+ private markProjectResidencyEvicted;
1183
+ private emitRuntimeStatus;
1166
1184
  /**
1167
1185
  * 重新初始化 watcher
1168
1186
  */
@@ -1241,6 +1259,9 @@ declare function getWatchedProjectDir(): string | null;
1241
1259
  * 获取 watcher 运行时状态
1242
1260
  */
1243
1261
  declare function getWatcherRuntimeStatus(): WatcherRuntimeStatus | null;
1262
+ declare function subscribeWatcherRuntimeStatus(listener: (status: WatcherRuntimeStatus | null) => void, options?: {
1263
+ emitCurrent?: boolean;
1264
+ }): () => void;
1244
1265
  //#endregion
1245
1266
  //#region src/watcher.d.ts
1246
1267
  /**
@@ -2500,6 +2521,34 @@ interface GitWorktreeHandoff {
2500
2521
  serverUrl: string;
2501
2522
  }
2502
2523
  //#endregion
2524
+ //#region src/runtime-types.d.ts
2525
+ type ProjectRecoveryStatus = {
2526
+ state: 'idle';
2527
+ } | {
2528
+ state: 'evicted';
2529
+ reason: ProjectResidencyEvictionReason;
2530
+ detectedAt: number;
2531
+ } | {
2532
+ state: 'resolving';
2533
+ reason: ProjectResidencyEvictionReason;
2534
+ detectedAt: number;
2535
+ } | {
2536
+ state: 'ready';
2537
+ reason: ProjectResidencyEvictionReason;
2538
+ detectedAt: number;
2539
+ handoff: GitWorktreeHandoff;
2540
+ } | {
2541
+ state: 'unavailable';
2542
+ reason: ProjectResidencyEvictionReason;
2543
+ detectedAt: number;
2544
+ message: string;
2545
+ } | {
2546
+ state: 'failed';
2547
+ reason: ProjectResidencyEvictionReason;
2548
+ detectedAt: number;
2549
+ message: string;
2550
+ };
2551
+ //#endregion
2503
2552
  //#region src/opsx-kernel.d.ts
2504
2553
  type TemplateContentMap = Record<string, {
2505
2554
  content: string | null;
@@ -3096,4 +3145,4 @@ type PtyServerMessage = z.infer<typeof PtyServerMessageSchema>;
3096
3145
  type PtySessionInfo = z.infer<typeof PtySessionInfoSchema>;
3097
3146
  type PtyPlatform = z.infer<typeof PtyPlatformSchema>;
3098
3147
  //#endregion
3099
- export { type AIToolOption, AI_TOOLS, type ApplyInstructions, ApplyInstructionsSchema, type ApplyTask, ApplyTaskSchema, type ArchiveMeta, type ArtifactInstructions, ArtifactInstructionsSchema, type ArtifactStatus, ArtifactStatusSchema, CODE_EDITOR_THEME_VALUES, type Change, type ChangeFile, ChangeFileSchema, type ChangeMeta, ChangeSchema, type ChangeStatus, ChangeStatusSchema, CliExecutor, type CliResult, type CliRunnerAttempt, type CliSniffResult, type CliStreamEvent, type CodeEditorTheme, CodeEditorThemeSchema, ConfigManager, DASHBOARD_METRIC_KEYS, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, type DashboardCardAvailability, type DashboardConfig, DashboardConfigSchema, type DashboardGitCommitEntry, type DashboardGitDiffStats, type DashboardGitEntry, type DashboardGitSnapshot, type DashboardGitUncommittedEntry, type DashboardGitWorktree, type DashboardMetricKey, type DashboardOverview, type DashboardSummary, type DashboardTrendKind, type DashboardTrendMeta, type DashboardTrendPoint, type DashboardTriColorTrendPoint, type Delta, type DeltaOperation, DeltaOperationType, DeltaSchema, type DeltaSpec, DeltaSpecSchema, type DependencyInfo, DependencyInfoSchema, type ExportSnapshot, type FileChangeEvent, type FileChangeType, type GitConfig, GitConfigSchema, type GitEntriesPage, type GitEntryCursor, type GitEntryDetail, type GitEntryFileDiff, type GitEntryFilePatch, type GitEntryFileSource, type GitEntryFileSummary, type GitEntryFiles, type GitEntryPatch, type GitEntrySelector, type GitEntryShell, type GitFileChangeType, type GitPatchFile, type GitPatchState, type GitWorktreeHandoff, type GitWorktreeOverview, type GitWorktreeSummary, type HostedAppChannelKind, type HostedAppChannelManifest, type HostedAppCompatibilityEntry, type HostedAppVersionManifest, type HostedBackendHealthResponse, MarkdownParser, OFFICIAL_APP_BASE_URL, OpenSpecAdapter, type OpenSpecUIConfig, OpenSpecUIConfigSchema, type OpenSpecUIConfigUpdate, OpenSpecWatcher, OpsxKernel, type PathCallback, ProjectWatcher, type ProjectWatcherReinitializeReason, type ProjectWatcherRuntimeStatus, PtyAttachMessageSchema, PtyBufferResponseSchema, type PtyClientMessage, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, type PtyPlatform, PtyPlatformSchema, PtyResizeMessageSchema, type PtyServerMessage, PtyServerMessageSchema, type PtySessionInfo, PtyTitleResponseSchema, ReactiveContext, ReactiveState, type ReactiveStateOptions, type Requirement, RequirementSchema, type ResolvedCliRunner, type SchemaArtifact, SchemaArtifactSchema, type SchemaDetail, SchemaDetailSchema, type SchemaInfo, SchemaInfoSchema, type SchemaResolution, SchemaResolutionSchema, type Spec, type SpecMeta, SpecSchema, TOOL_WORKFLOW_TO_SKILL_DIR, type Task, TaskSchema, type TemplateContentMap, type TemplatesMap, TemplatesSchema, type TerminalConfig, TerminalConfigSchema, type TerminalRendererEngine, TerminalRendererEngineSchema, type ToolConfig, type ToolInitDelivery, type ToolInitState, type ToolInitStatus, type ToolWorkflowId, VIRTUAL_PROJECT_DIRNAME, type ValidationIssue, type ValidationResult, Validator, type WatchEvent, type WatchEventType, type WatcherRuntimeStatus, acquireWatcher, buildCliRunnerCandidates, buildHostedLaunchUrl, buildHostedVersionManifestUrl, clearCache, closeAllProjectWatchers, closeAllWatchers, contextStorage, createCleanCliEnv, createFileChangeObservable, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDetectedProjectTools, getProjectWatcher, getToolById, getToolInitStates, getWatchedProjectDir, getWatcherRuntimeStatus, initWatcherPool, isGlobPattern, isHostedAppVersionManifest, isHostedBackendHealthResponse, isTerminalRendererEngine, isToolConfigured, isWatcherPoolInitialized, normalizeHostedAppBaseUrl, parseCliCommand, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, resolveHostedAppBaseUrl, resolveHostedChannelForVersion, sniffGlobalCli, toOpsxDisplayPath };
3148
+ export { type AIToolOption, AI_TOOLS, type ApplyInstructions, ApplyInstructionsSchema, type ApplyTask, ApplyTaskSchema, type ArchiveMeta, type ArtifactInstructions, ArtifactInstructionsSchema, type ArtifactStatus, ArtifactStatusSchema, CODE_EDITOR_THEME_VALUES, type Change, type ChangeFile, ChangeFileSchema, type ChangeMeta, ChangeSchema, type ChangeStatus, ChangeStatusSchema, CliExecutor, type CliResult, type CliRunnerAttempt, type CliSniffResult, type CliStreamEvent, type CodeEditorTheme, CodeEditorThemeSchema, ConfigManager, DASHBOARD_METRIC_KEYS, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, type DashboardCardAvailability, type DashboardConfig, DashboardConfigSchema, type DashboardGitCommitEntry, type DashboardGitDiffStats, type DashboardGitEntry, type DashboardGitSnapshot, type DashboardGitUncommittedEntry, type DashboardGitWorktree, type DashboardMetricKey, type DashboardOverview, type DashboardSummary, type DashboardTrendKind, type DashboardTrendMeta, type DashboardTrendPoint, type DashboardTriColorTrendPoint, type Delta, type DeltaOperation, DeltaOperationType, DeltaSchema, type DeltaSpec, DeltaSpecSchema, type DependencyInfo, DependencyInfoSchema, type ExportSnapshot, type FileChangeEvent, type FileChangeType, type GitConfig, GitConfigSchema, type GitEntriesPage, type GitEntryCursor, type GitEntryDetail, type GitEntryFileDiff, type GitEntryFilePatch, type GitEntryFileSource, type GitEntryFileSummary, type GitEntryFiles, type GitEntryPatch, type GitEntrySelector, type GitEntryShell, type GitFileChangeType, type GitPatchFile, type GitPatchState, type GitWorktreeHandoff, type GitWorktreeOverview, type GitWorktreeSummary, type HostedAppChannelKind, type HostedAppChannelManifest, type HostedAppCompatibilityEntry, type HostedAppVersionManifest, type HostedBackendHealthResponse, MarkdownParser, OFFICIAL_APP_BASE_URL, OpenSpecAdapter, type OpenSpecUIConfig, OpenSpecUIConfigSchema, type OpenSpecUIConfigUpdate, OpenSpecWatcher, OpsxKernel, type PathCallback, type ProjectRecoveryStatus, type ProjectResidencyEvictionReason, type ProjectResidencyStatus, ProjectWatcher, type ProjectWatcherReinitializeReason, type ProjectWatcherRuntimeStatus, type ProjectWatcherRuntimeStatusListener, PtyAttachMessageSchema, PtyBufferResponseSchema, type PtyClientMessage, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, type PtyPlatform, PtyPlatformSchema, PtyResizeMessageSchema, type PtyServerMessage, PtyServerMessageSchema, type PtySessionInfo, PtyTitleResponseSchema, ReactiveContext, ReactiveState, type ReactiveStateOptions, type Requirement, RequirementSchema, type ResolvedCliRunner, type SchemaArtifact, SchemaArtifactSchema, type SchemaDetail, SchemaDetailSchema, type SchemaInfo, SchemaInfoSchema, type SchemaResolution, SchemaResolutionSchema, type Spec, type SpecMeta, SpecSchema, TOOL_WORKFLOW_TO_SKILL_DIR, type Task, TaskSchema, type TemplateContentMap, type TemplatesMap, TemplatesSchema, type TerminalConfig, TerminalConfigSchema, type TerminalRendererEngine, TerminalRendererEngineSchema, type ToolConfig, type ToolInitDelivery, type ToolInitState, type ToolInitStatus, type ToolWorkflowId, VIRTUAL_PROJECT_DIRNAME, type ValidationIssue, type ValidationResult, Validator, type WatchEvent, type WatchEventType, type WatcherRuntimeStatus, acquireWatcher, buildCliRunnerCandidates, buildHostedLaunchUrl, buildHostedVersionManifestUrl, clearCache, closeAllProjectWatchers, closeAllWatchers, contextStorage, createCleanCliEnv, createFileChangeObservable, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDetectedProjectTools, getProjectWatcher, getToolById, getToolInitStates, getWatchedProjectDir, getWatcherRuntimeStatus, initWatcherPool, isGlobPattern, isHostedAppVersionManifest, isHostedBackendHealthResponse, isTerminalRendererEngine, isToolConfigured, isWatcherPoolInitialized, normalizeHostedAppBaseUrl, parseCliCommand, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, resolveHostedAppBaseUrl, resolveHostedChannelForVersion, sniffGlobalCli, subscribeWatcherRuntimeStatus, toOpsxDisplayPath };
package/dist/index.mjs CHANGED
@@ -542,6 +542,8 @@ var ProjectWatcher = class {
542
542
  "project-dir-replaced": 0,
543
543
  manual: 0
544
544
  };
545
+ projectResidency = { state: "active" };
546
+ runtimeStatusListeners = /* @__PURE__ */ new Set();
545
547
  constructor(projectDir, options = {}) {
546
548
  this.projectDir = getRealPath$1(projectDir);
547
549
  this.debounceMs = options.debounceMs ?? DEBOUNCE_MS$1;
@@ -571,7 +573,9 @@ var ProjectWatcher = class {
571
573
  this.initialized = true;
572
574
  this.generation += 1;
573
575
  this.projectDirFingerprint = this.getProjectDirFingerprint();
576
+ this.projectResidency = { state: "active" };
574
577
  this.startPathLivenessMonitor();
578
+ this.emitRuntimeStatus();
575
579
  }
576
580
  /**
577
581
  * 处理 watcher 错误
@@ -644,18 +648,23 @@ var ProjectWatcher = class {
644
648
  if (!this.initialized || this.reinitializePending) return;
645
649
  const current = this.getProjectDirFingerprint();
646
650
  if (current === null) {
651
+ this.markProjectResidencyEvicted("missing-project-dir");
647
652
  console.warn("[ProjectWatcher] Project directory missing, scheduling reinitialize...");
648
653
  this.scheduleReinitialize("missing-project-dir");
649
654
  return;
650
655
  }
651
656
  if (this.projectDirFingerprint === null) {
652
657
  this.projectDirFingerprint = current;
658
+ this.markProjectResidencyActive();
653
659
  return;
654
660
  }
655
661
  if (current !== this.projectDirFingerprint) {
662
+ this.markProjectResidencyEvicted("project-dir-replaced");
656
663
  console.warn("[ProjectWatcher] Project directory replaced, scheduling reinitialize...");
657
664
  this.scheduleReinitialize("project-dir-replaced");
665
+ return;
658
666
  }
667
+ this.markProjectResidencyActive();
659
668
  }
660
669
  /**
661
670
  * 处理原始事件
@@ -755,7 +764,15 @@ var ProjectWatcher = class {
755
764
  generation: this.generation,
756
765
  reinitializeCount: this.reinitializeCount,
757
766
  lastReinitializeReason: this.lastReinitializeReason,
758
- reinitializeReasonCounts: { ...this.reinitializeReasonCounts }
767
+ reinitializeReasonCounts: { ...this.reinitializeReasonCounts },
768
+ projectResidency: { ...this.projectResidency }
769
+ };
770
+ }
771
+ subscribeRuntimeStatus(listener, options = {}) {
772
+ this.runtimeStatusListeners.add(listener);
773
+ if (options.emitCurrent !== false) listener(this.runtimeStatus);
774
+ return () => {
775
+ this.runtimeStatusListeners.delete(listener);
759
776
  };
760
777
  }
761
778
  /**
@@ -765,6 +782,29 @@ var ProjectWatcher = class {
765
782
  this.reinitializeCount += 1;
766
783
  this.lastReinitializeReason = reason;
767
784
  this.reinitializeReasonCounts[reason] += 1;
785
+ this.emitRuntimeStatus();
786
+ }
787
+ markProjectResidencyActive() {
788
+ if (this.projectResidency.state === "active") return;
789
+ this.projectResidency = { state: "active" };
790
+ this.emitRuntimeStatus();
791
+ }
792
+ markProjectResidencyEvicted(reason) {
793
+ if (this.projectResidency.state === "evicted" && this.projectResidency.reason === reason) return;
794
+ this.projectResidency = {
795
+ state: "evicted",
796
+ reason,
797
+ detectedAt: Date.now()
798
+ };
799
+ this.emitRuntimeStatus();
800
+ }
801
+ emitRuntimeStatus() {
802
+ const status = this.runtimeStatus;
803
+ for (const listener of this.runtimeStatusListeners) try {
804
+ listener(status);
805
+ } catch (error) {
806
+ console.error("[ProjectWatcher] Runtime status listener failed:", error);
807
+ }
768
808
  }
769
809
  /**
770
810
  * 重新初始化 watcher
@@ -780,6 +820,7 @@ var ProjectWatcher = class {
780
820
  this.initialized = false;
781
821
  this.initPromise = null;
782
822
  this.projectDirFingerprint = null;
823
+ this.emitRuntimeStatus();
783
824
  if (!existsSync(this.projectDir)) {
784
825
  console.warn("[ProjectWatcher] Project directory does not exist, waiting for it to be created...");
785
826
  this.waitForProjectDir("missing-project-dir");
@@ -842,6 +883,8 @@ var ProjectWatcher = class {
842
883
  this.initialized = false;
843
884
  this.initPromise = null;
844
885
  this.projectDirFingerprint = null;
886
+ this.projectResidency = { state: "active" };
887
+ this.emitRuntimeStatus();
845
888
  }
846
889
  };
847
890
  /**
@@ -894,6 +937,25 @@ const DEBOUNCE_MS = 100;
894
937
  const subscriptionCache = /* @__PURE__ */ new Map();
895
938
  /** 防抖定时器 */
896
939
  const debounceTimers = /* @__PURE__ */ new Map();
940
+ const watcherRuntimeStatusListeners = /* @__PURE__ */ new Set();
941
+ let releaseProjectWatcherRuntimeSubscription = null;
942
+ function emitWatcherRuntimeStatus() {
943
+ const status = getWatcherRuntimeStatus();
944
+ for (const listener of watcherRuntimeStatusListeners) listener(status);
945
+ }
946
+ function bindProjectWatcherRuntimeStatus() {
947
+ releaseProjectWatcherRuntimeSubscription?.();
948
+ releaseProjectWatcherRuntimeSubscription = null;
949
+ if (!globalProjectWatcher) {
950
+ emitWatcherRuntimeStatus();
951
+ return;
952
+ }
953
+ const forward = () => {
954
+ emitWatcherRuntimeStatus();
955
+ };
956
+ releaseProjectWatcherRuntimeSubscription = globalProjectWatcher.subscribeRuntimeStatus(forward, { emitCurrent: false });
957
+ emitWatcherRuntimeStatus();
958
+ }
897
959
  /**
898
960
  * 初始化 watcher pool
899
961
  *
@@ -905,9 +967,14 @@ const debounceTimers = /* @__PURE__ */ new Map();
905
967
  async function initWatcherPool(projectDir) {
906
968
  const normalizedDir = getRealPath(projectDir);
907
969
  if (globalProjectWatcher && globalProjectDir === normalizedDir) return;
908
- if (globalProjectWatcher) await globalProjectWatcher.close();
970
+ if (globalProjectWatcher) {
971
+ releaseProjectWatcherRuntimeSubscription?.();
972
+ releaseProjectWatcherRuntimeSubscription = null;
973
+ await globalProjectWatcher.close();
974
+ }
909
975
  globalProjectDir = normalizedDir;
910
976
  globalProjectWatcher = getProjectWatcher(normalizedDir);
977
+ bindProjectWatcherRuntimeStatus();
911
978
  await globalProjectWatcher.init();
912
979
  }
913
980
  /**
@@ -989,10 +1056,13 @@ async function closeAllWatchers() {
989
1056
  subscriptionCache.clear();
990
1057
  debounceTimers.clear();
991
1058
  if (globalProjectWatcher) {
1059
+ releaseProjectWatcherRuntimeSubscription?.();
1060
+ releaseProjectWatcherRuntimeSubscription = null;
992
1061
  await globalProjectWatcher.close();
993
1062
  globalProjectWatcher = null;
994
1063
  globalProjectDir = null;
995
1064
  }
1065
+ emitWatcherRuntimeStatus();
996
1066
  }
997
1067
  /**
998
1068
  * 检查 watcher pool 是否已初始化
@@ -1019,7 +1089,15 @@ function getWatcherRuntimeStatus() {
1019
1089
  generation: runtime.generation,
1020
1090
  reinitializeCount: runtime.reinitializeCount,
1021
1091
  lastReinitializeReason: runtime.lastReinitializeReason,
1022
- reinitializeReasonCounts: runtime.reinitializeReasonCounts
1092
+ reinitializeReasonCounts: runtime.reinitializeReasonCounts,
1093
+ projectResidency: runtime.projectResidency
1094
+ };
1095
+ }
1096
+ function subscribeWatcherRuntimeStatus(listener, options = {}) {
1097
+ watcherRuntimeStatusListeners.add(listener);
1098
+ if (options.emitCurrent !== false) listener(getWatcherRuntimeStatus());
1099
+ return () => {
1100
+ watcherRuntimeStatusListeners.delete(listener);
1023
1101
  };
1024
1102
  }
1025
1103
 
@@ -4436,4 +4514,4 @@ const PtyServerMessageSchema = z.discriminatedUnion("type", [
4436
4514
  ]);
4437
4515
 
4438
4516
  //#endregion
4439
- export { AI_TOOLS, ApplyInstructionsSchema, ApplyTaskSchema, ArtifactInstructionsSchema, ArtifactStatusSchema, CODE_EDITOR_THEME_VALUES, ChangeFileSchema, ChangeSchema, ChangeStatusSchema, CliExecutor, CodeEditorThemeSchema, ConfigManager, DASHBOARD_METRIC_KEYS, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, DashboardConfigSchema, DeltaOperationType, DeltaSchema, DeltaSpecSchema, DependencyInfoSchema, GitConfigSchema, MarkdownParser, OFFICIAL_APP_BASE_URL, OpenSpecAdapter, OpenSpecUIConfigSchema, OpenSpecWatcher, OpsxKernel, ProjectWatcher, PtyAttachMessageSchema, PtyBufferResponseSchema, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, PtyPlatformSchema, PtyResizeMessageSchema, PtyServerMessageSchema, PtyTitleResponseSchema, ReactiveContext, ReactiveState, RequirementSchema, SchemaArtifactSchema, SchemaDetailSchema, SchemaInfoSchema, SchemaResolutionSchema, SpecSchema, TOOL_WORKFLOW_TO_SKILL_DIR, TaskSchema, TemplatesSchema, TerminalConfigSchema, TerminalRendererEngineSchema, VIRTUAL_PROJECT_DIRNAME, Validator, acquireWatcher, buildCliRunnerCandidates, buildHostedLaunchUrl, buildHostedVersionManifestUrl, clearCache, closeAllProjectWatchers, closeAllWatchers, contextStorage, createCleanCliEnv, createFileChangeObservable, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDetectedProjectTools, getProjectWatcher, getToolById, getToolInitStates, getWatchedProjectDir, getWatcherRuntimeStatus, initWatcherPool, isGlobPattern, isHostedAppVersionManifest, isHostedBackendHealthResponse, isTerminalRendererEngine, isToolConfigured, isWatcherPoolInitialized, normalizeHostedAppBaseUrl, parseCliCommand, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, resolveHostedAppBaseUrl, resolveHostedChannelForVersion, sniffGlobalCli, toOpsxDisplayPath };
4517
+ export { AI_TOOLS, ApplyInstructionsSchema, ApplyTaskSchema, ArtifactInstructionsSchema, ArtifactStatusSchema, CODE_EDITOR_THEME_VALUES, ChangeFileSchema, ChangeSchema, ChangeStatusSchema, CliExecutor, CodeEditorThemeSchema, ConfigManager, DASHBOARD_METRIC_KEYS, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, DashboardConfigSchema, DeltaOperationType, DeltaSchema, DeltaSpecSchema, DependencyInfoSchema, GitConfigSchema, MarkdownParser, OFFICIAL_APP_BASE_URL, OpenSpecAdapter, OpenSpecUIConfigSchema, OpenSpecWatcher, OpsxKernel, ProjectWatcher, PtyAttachMessageSchema, PtyBufferResponseSchema, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, PtyPlatformSchema, PtyResizeMessageSchema, PtyServerMessageSchema, PtyTitleResponseSchema, ReactiveContext, ReactiveState, RequirementSchema, SchemaArtifactSchema, SchemaDetailSchema, SchemaInfoSchema, SchemaResolutionSchema, SpecSchema, TOOL_WORKFLOW_TO_SKILL_DIR, TaskSchema, TemplatesSchema, TerminalConfigSchema, TerminalRendererEngineSchema, VIRTUAL_PROJECT_DIRNAME, Validator, acquireWatcher, buildCliRunnerCandidates, buildHostedLaunchUrl, buildHostedVersionManifestUrl, clearCache, closeAllProjectWatchers, closeAllWatchers, contextStorage, createCleanCliEnv, createFileChangeObservable, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDetectedProjectTools, getProjectWatcher, getToolById, getToolInitStates, getWatchedProjectDir, getWatcherRuntimeStatus, initWatcherPool, isGlobPattern, isHostedAppVersionManifest, isHostedBackendHealthResponse, isTerminalRendererEngine, isToolConfigured, isWatcherPoolInitialized, normalizeHostedAppBaseUrl, parseCliCommand, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, resolveHostedAppBaseUrl, resolveHostedChannelForVersion, sniffGlobalCli, subscribeWatcherRuntimeStatus, toOpsxDisplayPath };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openspecui/core",
3
- "version": "2.3.5",
3
+ "version": "2.3.7",
4
4
  "description": "Core OpenSpec adapter and parser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",