@openspecui/core 2.1.5 → 2.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.mts CHANGED
@@ -1846,12 +1846,14 @@ interface DashboardGitCommitEntry {
1846
1846
  type: 'commit';
1847
1847
  hash: string;
1848
1848
  title: string;
1849
+ committedAt: number;
1849
1850
  relatedChanges: string[];
1850
1851
  diff: DashboardGitDiffStats;
1851
1852
  }
1852
1853
  interface DashboardGitUncommittedEntry {
1853
1854
  type: 'uncommitted';
1854
1855
  title: string;
1856
+ updatedAt: number | null;
1855
1857
  relatedChanges: string[];
1856
1858
  diff: DashboardGitDiffStats;
1857
1859
  }
@@ -1859,6 +1861,7 @@ type DashboardGitEntry = DashboardGitCommitEntry | DashboardGitUncommittedEntry;
1859
1861
  interface DashboardGitWorktree {
1860
1862
  path: string;
1861
1863
  relativePath: string;
1864
+ pathAvailable: boolean;
1862
1865
  branchName: string;
1863
1866
  detached: boolean;
1864
1867
  isCurrent: boolean;
@@ -2410,6 +2413,64 @@ interface ExportSnapshot {
2410
2413
  };
2411
2414
  }
2412
2415
  //#endregion
2416
+ //#region src/git-panel-types.d.ts
2417
+ type GitEntryCursor = string;
2418
+ type GitEntrySelector = {
2419
+ type: 'uncommitted';
2420
+ } | {
2421
+ type: 'commit';
2422
+ hash: string;
2423
+ };
2424
+ type GitFileChangeType = 'added' | 'modified' | 'deleted' | 'renamed' | 'copied' | 'typechanged' | 'unmerged' | 'unknown';
2425
+ type GitPatchState = 'available' | 'binary' | 'too-large' | 'unavailable';
2426
+ type GitEntryFileSource = 'tracked' | 'untracked';
2427
+ type GitEntryFileDiff = ({
2428
+ state: 'ready';
2429
+ } & DashboardGitDiffStats) | {
2430
+ state: 'loading' | 'unavailable';
2431
+ files: number;
2432
+ };
2433
+ type GitWorktreeSummary = Omit<DashboardGitWorktree, 'entries'>;
2434
+ interface GitEntriesPage {
2435
+ items: DashboardGitEntry[];
2436
+ nextCursor: GitEntryCursor | null;
2437
+ }
2438
+ interface GitEntryFileSummary {
2439
+ fileId: string;
2440
+ source: GitEntryFileSource;
2441
+ path: string;
2442
+ displayPath: string;
2443
+ previousPath: string | null;
2444
+ changeType: GitFileChangeType;
2445
+ diff: GitEntryFileDiff;
2446
+ }
2447
+ interface GitEntryFilePatch extends GitEntryFileSummary {
2448
+ patch: string | null;
2449
+ state: GitPatchState;
2450
+ }
2451
+ interface GitEntryShell {
2452
+ entry: DashboardGitEntry | null;
2453
+ files: GitEntryFileSummary[];
2454
+ }
2455
+ interface GitEntryPatch {
2456
+ entry: DashboardGitEntry | null;
2457
+ file: GitEntryFilePatch | null;
2458
+ }
2459
+ type GitPatchFile = GitEntryFilePatch;
2460
+ interface GitEntryDetail {
2461
+ entry: DashboardGitEntry | null;
2462
+ files: GitEntryFilePatch[];
2463
+ }
2464
+ interface GitWorktreeOverview {
2465
+ defaultBranch: string;
2466
+ currentWorktree: GitWorktreeSummary | null;
2467
+ otherWorktrees: GitWorktreeSummary[];
2468
+ }
2469
+ interface GitWorktreeHandoff {
2470
+ projectDir: string;
2471
+ serverUrl: string;
2472
+ }
2473
+ //#endregion
2413
2474
  //#region src/opsx-kernel.d.ts
2414
2475
  type TemplateContentMap = Record<string, {
2415
2476
  content: string | null;
@@ -2555,19 +2616,19 @@ declare const PtyCreateMessageSchema: z.ZodObject<{
2555
2616
  }, "strip", z.ZodTypeAny, {
2556
2617
  type: "create";
2557
2618
  requestId: string;
2558
- command?: string | undefined;
2559
- args?: string[] | undefined;
2560
2619
  cols?: number | undefined;
2561
2620
  rows?: number | undefined;
2621
+ command?: string | undefined;
2622
+ args?: string[] | undefined;
2562
2623
  closeTip?: string | undefined;
2563
2624
  closeCallbackUrl?: string | Record<string, string> | undefined;
2564
2625
  }, {
2565
2626
  type: "create";
2566
2627
  requestId: string;
2567
- command?: string | undefined;
2568
- args?: string[] | undefined;
2569
2628
  cols?: number | undefined;
2570
2629
  rows?: number | undefined;
2630
+ command?: string | undefined;
2631
+ args?: string[] | undefined;
2571
2632
  closeTip?: string | undefined;
2572
2633
  closeCallbackUrl?: string | Record<string, string> | undefined;
2573
2634
  }>;
@@ -2645,19 +2706,19 @@ declare const PtyClientMessageSchema: z.ZodDiscriminatedUnion<"type", [z.ZodObje
2645
2706
  }, "strip", z.ZodTypeAny, {
2646
2707
  type: "create";
2647
2708
  requestId: string;
2648
- command?: string | undefined;
2649
- args?: string[] | undefined;
2650
2709
  cols?: number | undefined;
2651
2710
  rows?: number | undefined;
2711
+ command?: string | undefined;
2712
+ args?: string[] | undefined;
2652
2713
  closeTip?: string | undefined;
2653
2714
  closeCallbackUrl?: string | Record<string, string> | undefined;
2654
2715
  }, {
2655
2716
  type: "create";
2656
2717
  requestId: string;
2657
- command?: string | undefined;
2658
- args?: string[] | undefined;
2659
2718
  cols?: number | undefined;
2660
2719
  rows?: number | undefined;
2720
+ command?: string | undefined;
2721
+ args?: string[] | undefined;
2661
2722
  closeTip?: string | undefined;
2662
2723
  closeCallbackUrl?: string | Record<string, string> | undefined;
2663
2724
  }>, z.ZodObject<{
@@ -3006,4 +3067,4 @@ type PtyServerMessage = z.infer<typeof PtyServerMessageSchema>;
3006
3067
  type PtySessionInfo = z.infer<typeof PtySessionInfoSchema>;
3007
3068
  type PtyPlatform = z.infer<typeof PtyPlatformSchema>;
3008
3069
  //#endregion
3009
- 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 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 };
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 };
package/dist/index.mjs CHANGED
@@ -9,7 +9,7 @@ import { existsSync, lstatSync, realpathSync } from "node:fs";
9
9
  import { z } from "zod";
10
10
  import { EventEmitter } from "events";
11
11
  import { watch } from "fs";
12
- import { exec, spawn } from "child_process";
12
+ import { exec, execFile, spawn } from "child_process";
13
13
  import { promisify } from "util";
14
14
  import { homedir } from "node:os";
15
15
  import { parse } from "yaml";
@@ -1922,6 +1922,7 @@ function createFileChangeObservable(watcher) {
1922
1922
  //#endregion
1923
1923
  //#region src/config.ts
1924
1924
  const execAsync = promisify(exec);
1925
+ const execFileAsync = promisify(execFile);
1925
1926
  const CLI_PROBE_TIMEOUT_MS = 2e4;
1926
1927
  const THEME_VALUES = [
1927
1928
  "light",
@@ -2084,6 +2085,53 @@ function commandToString(commandParts) {
2084
2085
  };
2085
2086
  return commandParts.map(formatToken).join(" ").trim();
2086
2087
  }
2088
+ function isBareExecutableCommand(command) {
2089
+ if (!command) return false;
2090
+ if (command === "." || command === "..") return false;
2091
+ return !/[\\/]/.test(command);
2092
+ }
2093
+ function quotePosixShellArg(value) {
2094
+ return `'${value.replace(/'/g, `'\\''`)}'`;
2095
+ }
2096
+ async function resolveShellExecutablePath(command, cwd, env) {
2097
+ if (!isBareExecutableCommand(command)) return null;
2098
+ try {
2099
+ if (process.platform === "win32") {
2100
+ const { stdout: stdout$1 } = await execFileAsync("where", [command], {
2101
+ cwd,
2102
+ env,
2103
+ encoding: "utf8",
2104
+ timeout: 5e3
2105
+ });
2106
+ return stdout$1.split(/\r?\n/).map((line) => line.trim()).find((line) => line.length > 0) || null;
2107
+ }
2108
+ const { stdout } = await execFileAsync(env.SHELL || process.env.SHELL || "/bin/sh", ["-lc", `command -v -- ${quotePosixShellArg(command)}`], {
2109
+ cwd,
2110
+ env,
2111
+ encoding: "utf8",
2112
+ timeout: 5e3
2113
+ });
2114
+ return stdout.split("\n").map((line) => line.trim()).find((line) => line.startsWith("/")) || null;
2115
+ } catch {
2116
+ return null;
2117
+ }
2118
+ }
2119
+ async function expandCliRunnerCandidates(candidates, cwd, env) {
2120
+ const expanded = [];
2121
+ for (const candidate of candidates) {
2122
+ const [command, ...rest] = candidate.commandParts;
2123
+ if ((candidate.id === "openspec" || candidate.id === "configured" && command.trim().toLowerCase() === "openspec") && command) {
2124
+ const shellResolved = await resolveShellExecutablePath(command, cwd, env);
2125
+ if (shellResolved && shellResolved !== command) expanded.push({
2126
+ ...candidate,
2127
+ source: `${candidate.source} (shell)`,
2128
+ commandParts: [shellResolved, ...rest]
2129
+ });
2130
+ }
2131
+ expanded.push(candidate);
2132
+ }
2133
+ return expanded;
2134
+ }
2087
2135
  function getRunnerPriorityFromUserAgent(userAgent) {
2088
2136
  if (!userAgent) return null;
2089
2137
  if (userAgent.startsWith("bun")) return "bunx";
@@ -2189,8 +2237,9 @@ async function probeCliRunner(candidate, cwd, env) {
2189
2237
  });
2190
2238
  }
2191
2239
  async function resolveCliRunner(candidates, cwd, env) {
2240
+ const expandedCandidates = await expandCliRunnerCandidates(candidates, cwd, env);
2192
2241
  const attempts = [];
2193
- for (const candidate of candidates) {
2242
+ for (const candidate of expandedCandidates) {
2194
2243
  const attempt = await probeCliRunner(candidate, cwd, env);
2195
2244
  attempts.push(attempt);
2196
2245
  if (attempt.success) return {
@@ -2243,7 +2292,13 @@ async function fetchLatestVersion() {
2243
2292
  * 每次调用都会重新检测,不使用缓存。
2244
2293
  */
2245
2294
  async function sniffGlobalCli() {
2246
- const [localResult, latestVersion] = await Promise.all([execAsync("openspec --version", { timeout: 1e4 }).catch((err) => ({ error: err })), fetchLatestVersion()]);
2295
+ const env = createCleanCliEnv();
2296
+ const resolvedCommand = await resolveShellExecutablePath("openspec", process.cwd(), env) ?? "openspec";
2297
+ const [localResult, latestVersion] = await Promise.all([execFileAsync(resolvedCommand, ["--version"], {
2298
+ env,
2299
+ timeout: 1e4,
2300
+ encoding: "utf8"
2301
+ }).catch((err) => ({ error: err })), fetchLatestVersion()]);
2247
2302
  if ("error" in localResult) {
2248
2303
  const error = localResult.error instanceof Error ? localResult.error.message : String(localResult.error);
2249
2304
  if (error.includes("not found") || error.includes("ENOENT") || error.includes("not recognized")) return {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openspecui/core",
3
- "version": "2.1.5",
3
+ "version": "2.2.0",
4
4
  "description": "Core OpenSpec adapter and parser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",