@openspecui/core 2.2.0 → 2.3.3

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
@@ -19,13 +19,13 @@ declare const ChangeFileSchema: z.ZodObject<{
19
19
  /** Optional byte size for files */
20
20
  size: z.ZodOptional<z.ZodNumber>;
21
21
  }, "strip", z.ZodTypeAny, {
22
- path: string;
23
22
  type: "file" | "directory";
23
+ path: string;
24
24
  content?: string | undefined;
25
25
  size?: number | undefined;
26
26
  }, {
27
- path: string;
28
27
  type: "file" | "directory";
28
+ path: string;
29
29
  content?: string | undefined;
30
30
  size?: number | undefined;
31
31
  }>;
@@ -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;
@@ -1406,6 +1406,15 @@ declare const DashboardConfigSchema: z.ZodObject<{
1406
1406
  trendPointLimit?: number | undefined;
1407
1407
  }>;
1408
1408
  type DashboardConfig = z.infer<typeof DashboardConfigSchema>;
1409
+ declare const DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET = 1000;
1410
+ declare const GitConfigSchema: z.ZodObject<{
1411
+ diffEagerLineBudget: z.ZodDefault<z.ZodNumber>;
1412
+ }, "strip", z.ZodTypeAny, {
1413
+ diffEagerLineBudget: number;
1414
+ }, {
1415
+ diffEagerLineBudget?: number | undefined;
1416
+ }>;
1417
+ type GitConfig = z.infer<typeof GitConfigSchema>;
1409
1418
  /**
1410
1419
  * OpenSpecUI 配置 Schema
1411
1420
  *
@@ -1468,6 +1477,14 @@ declare const OpenSpecUIConfigSchema: z.ZodObject<{
1468
1477
  }, {
1469
1478
  trendPointLimit?: number | undefined;
1470
1479
  }>>;
1480
+ /** Git detail 配置 */
1481
+ git: z.ZodDefault<z.ZodObject<{
1482
+ diffEagerLineBudget: z.ZodDefault<z.ZodNumber>;
1483
+ }, "strip", z.ZodTypeAny, {
1484
+ diffEagerLineBudget: number;
1485
+ }, {
1486
+ diffEagerLineBudget?: number | undefined;
1487
+ }>>;
1471
1488
  }, "strip", z.ZodTypeAny, {
1472
1489
  theme: "light" | "dark" | "system";
1473
1490
  cli: {
@@ -1489,6 +1506,9 @@ declare const OpenSpecUIConfigSchema: z.ZodObject<{
1489
1506
  dashboard: {
1490
1507
  trendPointLimit: number;
1491
1508
  };
1509
+ git: {
1510
+ diffEagerLineBudget: number;
1511
+ };
1492
1512
  }, {
1493
1513
  theme?: "light" | "dark" | "system" | undefined;
1494
1514
  cli?: {
@@ -1510,6 +1530,9 @@ declare const OpenSpecUIConfigSchema: z.ZodObject<{
1510
1530
  dashboard?: {
1511
1531
  trendPointLimit?: number | undefined;
1512
1532
  } | undefined;
1533
+ git?: {
1534
+ diffEagerLineBudget?: number | undefined;
1535
+ } | undefined;
1513
1536
  }>;
1514
1537
  type OpenSpecUIConfig = z.infer<typeof OpenSpecUIConfigSchema>;
1515
1538
  type OpenSpecUIConfigUpdate = {
@@ -1522,6 +1545,7 @@ type OpenSpecUIConfigUpdate = {
1522
1545
  appBaseUrl?: OpenSpecUIConfig['appBaseUrl'];
1523
1546
  terminal?: Partial<TerminalConfig>;
1524
1547
  dashboard?: Partial<DashboardConfig>;
1548
+ git?: Partial<GitConfig>;
1525
1549
  };
1526
1550
  /** 默认配置(静态,用于测试和类型) */
1527
1551
  declare const DEFAULT_CONFIG: OpenSpecUIConfig;
@@ -2452,8 +2476,13 @@ interface GitEntryShell {
2452
2476
  entry: DashboardGitEntry | null;
2453
2477
  files: GitEntryFileSummary[];
2454
2478
  }
2479
+ interface GitEntryFiles {
2480
+ files: GitEntryFileSummary[];
2481
+ eagerFiles: GitEntryFilePatch[];
2482
+ eagerPatchLineBudget: number;
2483
+ eagerPatchLineCount: number;
2484
+ }
2455
2485
  interface GitEntryPatch {
2456
- entry: DashboardGitEntry | null;
2457
2486
  file: GitEntryFilePatch | null;
2458
2487
  }
2459
2488
  type GitPatchFile = GitEntryFilePatch;
@@ -2584,22 +2613,22 @@ declare const PtySessionInfoSchema: z.ZodObject<{
2584
2613
  closeTip: z.ZodOptional<z.ZodString>;
2585
2614
  closeCallbackUrl: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
2586
2615
  }, "strip", z.ZodTypeAny, {
2587
- id: string;
2588
2616
  command: string;
2589
2617
  args: string[];
2590
2618
  platform: "windows" | "macos" | "common";
2591
2619
  exitCode: number | null;
2592
2620
  title: string;
2621
+ id: string;
2593
2622
  isExited: boolean;
2594
2623
  closeTip?: string | undefined;
2595
2624
  closeCallbackUrl?: string | Record<string, string> | undefined;
2596
2625
  }, {
2597
- id: string;
2598
2626
  command: string;
2599
2627
  args: string[];
2600
2628
  platform: "windows" | "macos" | "common";
2601
2629
  exitCode: number | null;
2602
2630
  title: string;
2631
+ id: string;
2603
2632
  isExited: boolean;
2604
2633
  closeTip?: string | undefined;
2605
2634
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -2860,22 +2889,22 @@ declare const PtyListResponseSchema: z.ZodObject<{
2860
2889
  closeTip: z.ZodOptional<z.ZodString>;
2861
2890
  closeCallbackUrl: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
2862
2891
  }, "strip", z.ZodTypeAny, {
2863
- id: string;
2864
2892
  command: string;
2865
2893
  args: string[];
2866
2894
  platform: "windows" | "macos" | "common";
2867
2895
  exitCode: number | null;
2868
2896
  title: string;
2897
+ id: string;
2869
2898
  isExited: boolean;
2870
2899
  closeTip?: string | undefined;
2871
2900
  closeCallbackUrl?: string | Record<string, string> | undefined;
2872
2901
  }, {
2873
- id: string;
2874
2902
  command: string;
2875
2903
  args: string[];
2876
2904
  platform: "windows" | "macos" | "common";
2877
2905
  exitCode: number | null;
2878
2906
  title: string;
2907
+ id: string;
2879
2908
  isExited: boolean;
2880
2909
  closeTip?: string | undefined;
2881
2910
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -2883,12 +2912,12 @@ declare const PtyListResponseSchema: z.ZodObject<{
2883
2912
  }, "strip", z.ZodTypeAny, {
2884
2913
  type: "list";
2885
2914
  sessions: {
2886
- id: string;
2887
2915
  command: string;
2888
2916
  args: string[];
2889
2917
  platform: "windows" | "macos" | "common";
2890
2918
  exitCode: number | null;
2891
2919
  title: string;
2920
+ id: string;
2892
2921
  isExited: boolean;
2893
2922
  closeTip?: string | undefined;
2894
2923
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -2896,12 +2925,12 @@ declare const PtyListResponseSchema: z.ZodObject<{
2896
2925
  }, {
2897
2926
  type: "list";
2898
2927
  sessions: {
2899
- id: string;
2900
2928
  command: string;
2901
2929
  args: string[];
2902
2930
  platform: "windows" | "macos" | "common";
2903
2931
  exitCode: number | null;
2904
2932
  title: string;
2933
+ id: string;
2905
2934
  isExited: boolean;
2906
2935
  closeTip?: string | undefined;
2907
2936
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -3000,22 +3029,22 @@ declare const PtyServerMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
3000
3029
  closeTip: z.ZodOptional<z.ZodString>;
3001
3030
  closeCallbackUrl: z.ZodOptional<z.ZodUnion<[z.ZodString, z.ZodRecord<z.ZodString, z.ZodString>]>>;
3002
3031
  }, "strip", z.ZodTypeAny, {
3003
- id: string;
3004
3032
  command: string;
3005
3033
  args: string[];
3006
3034
  platform: "windows" | "macos" | "common";
3007
3035
  exitCode: number | null;
3008
3036
  title: string;
3037
+ id: string;
3009
3038
  isExited: boolean;
3010
3039
  closeTip?: string | undefined;
3011
3040
  closeCallbackUrl?: string | Record<string, string> | undefined;
3012
3041
  }, {
3013
- id: string;
3014
3042
  command: string;
3015
3043
  args: string[];
3016
3044
  platform: "windows" | "macos" | "common";
3017
3045
  exitCode: number | null;
3018
3046
  title: string;
3047
+ id: string;
3019
3048
  isExited: boolean;
3020
3049
  closeTip?: string | undefined;
3021
3050
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -3023,12 +3052,12 @@ declare const PtyServerMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
3023
3052
  }, "strip", z.ZodTypeAny, {
3024
3053
  type: "list";
3025
3054
  sessions: {
3026
- id: string;
3027
3055
  command: string;
3028
3056
  args: string[];
3029
3057
  platform: "windows" | "macos" | "common";
3030
3058
  exitCode: number | null;
3031
3059
  title: string;
3060
+ id: string;
3032
3061
  isExited: boolean;
3033
3062
  closeTip?: string | undefined;
3034
3063
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -3036,12 +3065,12 @@ declare const PtyServerMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
3036
3065
  }, {
3037
3066
  type: "list";
3038
3067
  sessions: {
3039
- id: string;
3040
3068
  command: string;
3041
3069
  args: string[];
3042
3070
  platform: "windows" | "macos" | "common";
3043
3071
  exitCode: number | null;
3044
3072
  title: string;
3073
+ id: string;
3045
3074
  isExited: boolean;
3046
3075
  closeTip?: string | undefined;
3047
3076
  closeCallbackUrl?: string | Record<string, string> | undefined;
@@ -3067,4 +3096,4 @@ type PtyServerMessage = z.infer<typeof PtyServerMessageSchema>;
3067
3096
  type PtySessionInfo = z.infer<typeof PtySessionInfoSchema>;
3068
3097
  type PtyPlatform = z.infer<typeof PtyPlatformSchema>;
3069
3098
  //#endregion
3070
- 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, 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 GitEntriesPage, type GitEntryCursor, type GitEntryDetail, type GitEntryFileDiff, type GitEntryFilePatch, type GitEntryFileSource, type GitEntryFileSummary, 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 };
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 };
package/dist/index.mjs CHANGED
@@ -1919,6 +1919,101 @@ function createFileChangeObservable(watcher) {
1919
1919
  } };
1920
1920
  }
1921
1921
 
1922
+ //#endregion
1923
+ //#region src/spawn-safe.ts
1924
+ function getSpawnErrorCode(err) {
1925
+ if (typeof err !== "object" || err === null || !("code" in err)) return;
1926
+ const code = err.code;
1927
+ return typeof code === "string" ? code : void 0;
1928
+ }
1929
+ function formatSpawnError(err) {
1930
+ const message = err instanceof Error ? err.message : String(err);
1931
+ const code = getSpawnErrorCode(err);
1932
+ return {
1933
+ code,
1934
+ message: `${message}${code ? ` (${code})` : ""}`
1935
+ };
1936
+ }
1937
+ function spawnSafe(command, args, options) {
1938
+ try {
1939
+ return {
1940
+ ok: true,
1941
+ child: spawn(command, [...args], options)
1942
+ };
1943
+ } catch (err) {
1944
+ return {
1945
+ ok: false,
1946
+ error: formatSpawnError(err)
1947
+ };
1948
+ }
1949
+ }
1950
+ function killChild(child) {
1951
+ try {
1952
+ child.kill();
1953
+ } catch {}
1954
+ }
1955
+ function runBufferedCommand(options) {
1956
+ return new Promise((resolve$1) => {
1957
+ const started = spawnSafe(options.command, options.args, {
1958
+ cwd: options.cwd,
1959
+ shell: false,
1960
+ env: options.env
1961
+ });
1962
+ if (!started.ok) {
1963
+ resolve$1({
1964
+ stdout: "",
1965
+ stderr: "",
1966
+ exitCode: null,
1967
+ timedOut: false,
1968
+ spawnError: started.error
1969
+ });
1970
+ return;
1971
+ }
1972
+ const { child } = started;
1973
+ let stdout = "";
1974
+ let stderr = "";
1975
+ let timedOut = false;
1976
+ let settled = false;
1977
+ let clearTimer = () => {};
1978
+ if (options.timeoutMs !== void 0) {
1979
+ const timer = setTimeout(() => {
1980
+ timedOut = true;
1981
+ killChild(child);
1982
+ }, options.timeoutMs);
1983
+ clearTimer = () => clearTimeout(timer);
1984
+ }
1985
+ const finish = (result) => {
1986
+ if (settled) return;
1987
+ settled = true;
1988
+ clearTimer();
1989
+ resolve$1(result);
1990
+ };
1991
+ child.stdout?.on("data", (data) => {
1992
+ stdout += data.toString();
1993
+ });
1994
+ child.stderr?.on("data", (data) => {
1995
+ stderr += data.toString();
1996
+ });
1997
+ child.on("error", (err) => {
1998
+ finish({
1999
+ stdout,
2000
+ stderr,
2001
+ exitCode: null,
2002
+ timedOut,
2003
+ spawnError: formatSpawnError(err)
2004
+ });
2005
+ });
2006
+ child.on("close", (exitCode) => {
2007
+ finish({
2008
+ stdout,
2009
+ stderr,
2010
+ exitCode,
2011
+ timedOut
2012
+ });
2013
+ });
2014
+ });
2015
+ }
2016
+
1922
2017
  //#endregion
1923
2018
  //#region src/config.ts
1924
2019
  const execAsync = promisify(exec);
@@ -2172,69 +2267,44 @@ function createCleanCliEnv(baseEnv = process.env) {
2172
2267
  }
2173
2268
  async function probeCliRunner(candidate, cwd, env) {
2174
2269
  const [cmd, ...cmdArgs] = candidate.commandParts;
2175
- return new Promise((resolve$1) => {
2176
- let stdout = "";
2177
- let stderr = "";
2178
- let timedOut = false;
2179
- const timer = setTimeout(() => {
2180
- timedOut = true;
2181
- child.kill();
2182
- }, CLI_PROBE_TIMEOUT_MS);
2183
- const child = spawn(cmd, [...cmdArgs, "--version"], {
2184
- cwd,
2185
- shell: false,
2186
- env
2187
- });
2188
- child.stdout?.on("data", (data) => {
2189
- stdout += data.toString();
2190
- });
2191
- child.stderr?.on("data", (data) => {
2192
- stderr += data.toString();
2193
- });
2194
- child.on("error", (err) => {
2195
- clearTimeout(timer);
2196
- const code = err.code;
2197
- const suffix = code ? ` (${code})` : "";
2198
- resolve$1({
2199
- source: candidate.source,
2200
- command: commandToString(candidate.commandParts),
2201
- success: false,
2202
- error: `${err.message}${suffix}`,
2203
- exitCode: null
2204
- });
2205
- });
2206
- child.on("close", (exitCode) => {
2207
- clearTimeout(timer);
2208
- if (timedOut) {
2209
- resolve$1({
2210
- source: candidate.source,
2211
- command: commandToString(candidate.commandParts),
2212
- success: false,
2213
- error: "CLI probe timed out",
2214
- exitCode
2215
- });
2216
- return;
2217
- }
2218
- if (exitCode === 0) {
2219
- const version = stdout.trim().split("\n")[0] || void 0;
2220
- resolve$1({
2221
- source: candidate.source,
2222
- command: commandToString(candidate.commandParts),
2223
- success: true,
2224
- version,
2225
- exitCode
2226
- });
2227
- return;
2228
- }
2229
- resolve$1({
2230
- source: candidate.source,
2231
- command: commandToString(candidate.commandParts),
2232
- success: false,
2233
- error: stderr.trim() || `Exit code ${exitCode ?? "null"}`,
2234
- exitCode
2235
- });
2236
- });
2270
+ const result = await runBufferedCommand({
2271
+ command: cmd,
2272
+ args: [...cmdArgs, "--version"],
2273
+ cwd,
2274
+ env,
2275
+ timeoutMs: CLI_PROBE_TIMEOUT_MS
2237
2276
  });
2277
+ if (result.timedOut) return {
2278
+ source: candidate.source,
2279
+ command: commandToString(candidate.commandParts),
2280
+ success: false,
2281
+ error: "CLI probe timed out",
2282
+ exitCode: result.exitCode
2283
+ };
2284
+ if (result.spawnError) return {
2285
+ source: candidate.source,
2286
+ command: commandToString(candidate.commandParts),
2287
+ success: false,
2288
+ error: result.spawnError.message,
2289
+ exitCode: null
2290
+ };
2291
+ if (result.exitCode === 0) {
2292
+ const version = result.stdout.trim().split("\n")[0] || void 0;
2293
+ return {
2294
+ source: candidate.source,
2295
+ command: commandToString(candidate.commandParts),
2296
+ success: true,
2297
+ version,
2298
+ exitCode: result.exitCode
2299
+ };
2300
+ }
2301
+ return {
2302
+ source: candidate.source,
2303
+ command: commandToString(candidate.commandParts),
2304
+ success: false,
2305
+ error: result.stderr.trim() || `Exit code ${result.exitCode ?? "null"}`,
2306
+ exitCode: result.exitCode
2307
+ };
2238
2308
  }
2239
2309
  async function resolveCliRunner(candidates, cwd, env) {
2240
2310
  const expandedCandidates = await expandCliRunnerCandidates(candidates, cwd, env);
@@ -2344,6 +2414,8 @@ const TerminalConfigSchema = z.object({
2344
2414
  rendererEngine: z.string().default("xterm")
2345
2415
  });
2346
2416
  const DashboardConfigSchema = z.object({ trendPointLimit: z.number().int().min(20).max(500).default(100) });
2417
+ const DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET = 1e3;
2418
+ const GitConfigSchema = z.object({ diffEagerLineBudget: z.number().int().min(0).max(2e5).default(DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET) });
2347
2419
  const CodeEditorConfigSchema = z.object({ theme: CodeEditorThemeSchema.default("github") });
2348
2420
  /**
2349
2421
  * OpenSpecUI 配置 Schema
@@ -2359,7 +2431,8 @@ const OpenSpecUIConfigSchema = z.object({
2359
2431
  codeEditor: CodeEditorConfigSchema.default(CodeEditorConfigSchema.parse({})),
2360
2432
  appBaseUrl: z.string().default(""),
2361
2433
  terminal: TerminalConfigSchema.default(TerminalConfigSchema.parse({})),
2362
- dashboard: DashboardConfigSchema.default(DashboardConfigSchema.parse({}))
2434
+ dashboard: DashboardConfigSchema.default(DashboardConfigSchema.parse({})),
2435
+ git: GitConfigSchema.default(GitConfigSchema.parse({}))
2363
2436
  });
2364
2437
  /** 默认配置(静态,用于测试和类型) */
2365
2438
  const DEFAULT_CONFIG = {
@@ -2368,7 +2441,8 @@ const DEFAULT_CONFIG = {
2368
2441
  codeEditor: CodeEditorConfigSchema.parse({}),
2369
2442
  appBaseUrl: "",
2370
2443
  terminal: TerminalConfigSchema.parse({}),
2371
- dashboard: DashboardConfigSchema.parse({})
2444
+ dashboard: DashboardConfigSchema.parse({}),
2445
+ git: GitConfigSchema.parse({})
2372
2446
  };
2373
2447
  function areStringArraysEqual(left, right) {
2374
2448
  if (left === right) return true;
@@ -2419,6 +2493,9 @@ function toPersistedConfig(config, options = {}) {
2419
2493
  const dashboard = {};
2420
2494
  if (config.dashboard.trendPointLimit !== DEFAULT_CONFIG.dashboard.trendPointLimit) dashboard.trendPointLimit = config.dashboard.trendPointLimit;
2421
2495
  if (hasOwnEntries(dashboard)) persisted.dashboard = dashboard;
2496
+ const git = {};
2497
+ if (config.git.diffEagerLineBudget !== DEFAULT_CONFIG.git.diffEagerLineBudget) git.diffEagerLineBudget = config.git.diffEagerLineBudget;
2498
+ if (hasOwnEntries(git)) persisted.git = git;
2422
2499
  return persisted;
2423
2500
  }
2424
2501
  function isPersistedConfigEmpty(config) {
@@ -2505,6 +2582,10 @@ var ConfigManager = class {
2505
2582
  dashboard: {
2506
2583
  ...current.dashboard,
2507
2584
  ...config.dashboard
2585
+ },
2586
+ git: {
2587
+ ...current.git,
2588
+ ...config.git
2508
2589
  }
2509
2590
  });
2510
2591
  if (isPersistedConfigEmpty(persisted) && !fileExists) return;
@@ -2645,42 +2726,27 @@ var CliExecutor = class {
2645
2726
  async buildCommandArray(args) {
2646
2727
  return [...await this.configManager.getCliCommand(), ...args];
2647
2728
  }
2648
- runCommandOnce(fullCommand) {
2729
+ async runCommandOnce(fullCommand) {
2649
2730
  const [cmd, ...cmdArgs] = fullCommand;
2650
- return new Promise((resolve$1) => {
2651
- const child = spawn(cmd, cmdArgs, {
2652
- cwd: this.projectDir,
2653
- shell: false,
2654
- env: createCleanCliEnv()
2655
- });
2656
- let stdout = "";
2657
- let stderr = "";
2658
- child.stdout?.on("data", (data) => {
2659
- stdout += data.toString();
2660
- });
2661
- child.stderr?.on("data", (data) => {
2662
- stderr += data.toString();
2663
- });
2664
- child.on("close", (exitCode) => {
2665
- resolve$1({
2666
- success: exitCode === 0,
2667
- stdout,
2668
- stderr,
2669
- exitCode
2670
- });
2671
- });
2672
- child.on("error", (err) => {
2673
- const errorCode = err.code;
2674
- const errorMessage = err.message + (errorCode ? ` (${errorCode})` : "");
2675
- resolve$1({
2676
- success: false,
2677
- stdout,
2678
- stderr: stderr ? `${stderr}\n${errorMessage}` : errorMessage,
2679
- exitCode: null,
2680
- errorCode
2681
- });
2682
- });
2731
+ const result = await runBufferedCommand({
2732
+ command: cmd,
2733
+ args: cmdArgs,
2734
+ cwd: this.projectDir,
2735
+ env: createCleanCliEnv()
2683
2736
  });
2737
+ if (result.spawnError) return {
2738
+ success: false,
2739
+ stdout: result.stdout,
2740
+ stderr: result.stderr ? `${result.stderr}\n${result.spawnError.message}` : result.spawnError.message,
2741
+ exitCode: null,
2742
+ errorCode: result.spawnError.code
2743
+ };
2744
+ return {
2745
+ success: result.exitCode === 0,
2746
+ stdout: result.stdout,
2747
+ stderr: result.stderr,
2748
+ exitCode: result.exitCode
2749
+ };
2684
2750
  }
2685
2751
  async executeInternal(args, allowRetry) {
2686
2752
  let fullCommand;
@@ -2834,11 +2900,29 @@ var CliExecutor = class {
2834
2900
  data: fullCommand.join(" ")
2835
2901
  });
2836
2902
  const [cmd, ...cmdArgs] = fullCommand;
2837
- const child = spawn(cmd, cmdArgs, {
2903
+ const started = spawnSafe(cmd, cmdArgs, {
2838
2904
  cwd: this.projectDir,
2839
2905
  shell: false,
2840
2906
  env: createCleanCliEnv()
2841
2907
  });
2908
+ if (!started.ok) {
2909
+ const { code, message } = started.error;
2910
+ if (allowRetry && code === "ENOENT" && !cancelled) {
2911
+ this.configManager.invalidateResolvedCliRunner();
2912
+ start(false);
2913
+ return;
2914
+ }
2915
+ onEvent({
2916
+ type: "stderr",
2917
+ data: message
2918
+ });
2919
+ onEvent({
2920
+ type: "exit",
2921
+ exitCode: null
2922
+ });
2923
+ return;
2924
+ }
2925
+ const child = started.child;
2842
2926
  activeChild = child;
2843
2927
  child.stdout?.on("data", (data) => {
2844
2928
  onEvent({
@@ -2863,8 +2947,7 @@ var CliExecutor = class {
2863
2947
  child.on("error", (err) => {
2864
2948
  if (activeChild !== child) return;
2865
2949
  activeChild = null;
2866
- const code = err.code;
2867
- const message = err.message + (code ? ` (${code})` : "");
2950
+ const { code, message } = formatSpawnError(err);
2868
2951
  if (allowRetry && code === "ENOENT" && !cancelled) {
2869
2952
  this.configManager.invalidateResolvedCliRunner();
2870
2953
  start(false);
@@ -2949,11 +3032,23 @@ var CliExecutor = class {
2949
3032
  type: "command",
2950
3033
  data: command.join(" ")
2951
3034
  });
2952
- const child = spawn(cmd, cmdArgs, {
3035
+ const started = spawnSafe(cmd, cmdArgs, {
2953
3036
  cwd: this.projectDir,
2954
3037
  shell: false,
2955
3038
  env: createCleanCliEnv()
2956
3039
  });
3040
+ if (!started.ok) {
3041
+ onEvent({
3042
+ type: "stderr",
3043
+ data: started.error.message
3044
+ });
3045
+ onEvent({
3046
+ type: "exit",
3047
+ exitCode: null
3048
+ });
3049
+ return () => {};
3050
+ }
3051
+ const child = started.child;
2957
3052
  child.stdout?.on("data", (data) => {
2958
3053
  onEvent({
2959
3054
  type: "stdout",
@@ -2973,10 +3068,10 @@ var CliExecutor = class {
2973
3068
  });
2974
3069
  });
2975
3070
  child.on("error", (err) => {
2976
- const code = err.code;
3071
+ const { message } = formatSpawnError(err);
2977
3072
  onEvent({
2978
3073
  type: "stderr",
2979
- data: err.message + (code ? ` (${code})` : "")
3074
+ data: message
2980
3075
  });
2981
3076
  onEvent({
2982
3077
  type: "exit",
@@ -4341,4 +4436,4 @@ const PtyServerMessageSchema = z.discriminatedUnion("type", [
4341
4436
  ]);
4342
4437
 
4343
4438
  //#endregion
4344
- export { AI_TOOLS, ApplyInstructionsSchema, ApplyTaskSchema, ArtifactInstructionsSchema, ArtifactStatusSchema, CODE_EDITOR_THEME_VALUES, ChangeFileSchema, ChangeSchema, ChangeStatusSchema, CliExecutor, CodeEditorThemeSchema, ConfigManager, DASHBOARD_METRIC_KEYS, DEFAULT_CONFIG, DashboardConfigSchema, DeltaOperationType, DeltaSchema, DeltaSpecSchema, DependencyInfoSchema, 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 };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openspecui/core",
3
- "version": "2.2.0",
3
+ "version": "2.3.3",
4
4
  "description": "Core OpenSpec adapter and parser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",
@@ -39,10 +39,10 @@
39
39
  "zod": "^3.24.1"
40
40
  },
41
41
  "devDependencies": {
42
- "@vitest/coverage-v8": "^2.1.9",
42
+ "@vitest/coverage-v8": "^4.1.0",
43
43
  "tsdown": "^0.16.6",
44
44
  "typescript": "^5.7.2",
45
- "vitest": "^2.1.8"
45
+ "vitest": "^4.1.0"
46
46
  },
47
47
  "peerDependencies": {
48
48
  "typescript": "^5.0.0"