@openspecui/core 2.1.7 → 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
@@ -1861,6 +1861,7 @@ type DashboardGitEntry = DashboardGitCommitEntry | DashboardGitUncommittedEntry;
1861
1861
  interface DashboardGitWorktree {
1862
1862
  path: string;
1863
1863
  relativePath: string;
1864
+ pathAvailable: boolean;
1864
1865
  branchName: string;
1865
1866
  detached: boolean;
1866
1867
  isCurrent: boolean;
@@ -2412,6 +2413,64 @@ interface ExportSnapshot {
2412
2413
  };
2413
2414
  }
2414
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
2415
2474
  //#region src/opsx-kernel.d.ts
2416
2475
  type TemplateContentMap = Record<string, {
2417
2476
  content: string | null;
@@ -3008,4 +3067,4 @@ type PtyServerMessage = z.infer<typeof PtyServerMessageSchema>;
3008
3067
  type PtySessionInfo = z.infer<typeof PtySessionInfoSchema>;
3009
3068
  type PtyPlatform = z.infer<typeof PtyPlatformSchema>;
3010
3069
  //#endregion
3011
- 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.7",
3
+ "version": "2.2.0",
4
4
  "description": "Core OpenSpec adapter and parser",
5
5
  "type": "module",
6
6
  "main": "./dist/index.mjs",