@openspecui/server 7.0.0 → 7.0.2
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/{api-B4zHqR-f.mjs → api-C_H23KUr.mjs} +1 -1
- package/dist/index.mjs +167 -70
- package/package.json +4 -4
|
@@ -2,9 +2,9 @@ import m, { createRequire } from "node:module";
|
|
|
2
2
|
import a from "node:path";
|
|
3
3
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
4
4
|
import se, { writeSync } from "node:fs";
|
|
5
|
+
import Ht from "node:crypto";
|
|
5
6
|
import o from "node:os";
|
|
6
7
|
import p from "node:net";
|
|
7
|
-
import Ht from "node:crypto";
|
|
8
8
|
import { inspect } from "node:util";
|
|
9
9
|
import { MessageChannel } from "node:worker_threads";
|
|
10
10
|
import { createRequire as createRequire$1 } from "module";
|
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
import { a as resolveCt2ModelDownloadPlanFromRepositoryFiles } from "./src-Dh_UAz5C.mjs";
|
|
2
2
|
import { t as resolveGgufModelDownloadPlanFromRepositoryFiles } from "./src-CZfiVL_-.mjs";
|
|
3
|
-
import { AI_TOOLS, ActiveRootMutationSchema, ActiveRootRevisionSchema, AgentDeliveryPolicyUpdateSchema, BatchTranslateInputSchema, CliExecutor, CliProjectionCommandError, CliProjectionNoticeSchema, CodeEditorThemeSchema, ConfigManager, CustomSoundHashSchema, DASHBOARD_METRIC_KEYS, DashboardConfigSchema, DashboardGitSnapshotSchema, DashboardSummaryInvalidationSchema, DashboardSummaryProjectionStateSchema, DashboardTrendsProjectionSchema, DocumentTranslationConfigUpdateSchema, EnvironmentDefaultStoreUpdateSchema, EnvironmentGlobalConfigValueSchema, EnvironmentGlobalFileProjectionDataSchema, EnvironmentGlobalFileProjectionStateSchema, EnvironmentGlobalProjectionDataSchema, EnvironmentGlobalProjectionStateSchema, GitConfigSchema, GlobalSettingsManager, LocalModelAssetStateSchema, LocalModelLifecycleFileStateSchema, LocalModelLifecycleGroupStateSchema, LocalModelProfileManifestSchema, MarkdownParser, NotificationPublishInputSchema, NotificationSettingsSchema, OPENSPECUI_DOCUMENT_HOOK_VERSION, OPENSPECUI_WORKFLOW_HOOK_VERSION, OPSX_ARTIFACT_INPUT_ACTIONS, OPSX_CHANGE_INPUT_ACTIONS, OPSX_COMMAND_CAPABLE_WORKFLOWS, OPSX_CORE_PROFILE_WORKFLOWS, OPSX_TEXT_INPUT_ACTIONS, OpenSpecAdapter, OpenSpecDataHomeObserver, OpenSpecUIGlobalSettingsUpdateSchema, OpenSpecWatcher, OpsxConfigSchema, OpsxKernel, OwnedSpecIdentitySchema, PINNED_AGENT_GENERATOR_VERSION, PlanningCliProjectionDataSchema, PlanningCliProjectionSelectorSchema, PlanningCliProjectionStateSchema, ProjectBindingUpdateSchema, ProjectWatcher, PtyClientMessageSchema, RUNTIME_INVALIDATION_FACETS, ReactiveContext, ReactiveObservationEnvironment, ReactiveState, RuntimeInvalidationIndex, RuntimeRootInvalidationRegistry, ServiceTranslationEngineIdSchema, SpecIdentitySchema, StoreDoctorResultSchema, StoreListResultSchema, StoreMutationLifecycleEventSchema, StoreMutationStartResponseSchema, TRANSLATION_ENGINE_MANIFESTS, TerminalConfigSchema, TerminalControlParser, TerminalRendererEngineSchema, TranslationCacheReadInputSchema, TranslationCacheWriteInputSchema, TranslationEngineIdSchema, TranslationEngineLifecycleStatusSchema, acquireWatcher, applyAgentDeliveryPolicy, buildBackendHealthPayload, buildLocalDownloadPlanFromRepositoryFiles, buildRuntimePackageInstallCommand, checkLocalDirectionalModelLanguagePair, classifyStoreCliResult, clearCache, compareAndWriteAtomicPhysicalReactiveFile, computeEnvUri, constantTimeEqual, createCleanCliEnv, createPhysicalReactiveDirectory, createToolInitStateProjection, createTranslationEngineLifecycleStatus, detectRuntimePackageManager, getAllTools, getAvailableTools, getConfiguredTools, getDefaultCliCommandString, getDetectedProjectTools, getExternalCodexCommandObservationRoot, getManagedLocalTranslationEngineManifest, getOpsxEntityRootRelativePath, getRootContextCliSelector, getToolInitStates, getTranslationEngineLifecycleMessage, getWatcherRuntimeStatus, inferFileMime, inferFilePreviewKind, inspectActiveRootOfficialConfig, inspectEnvironmentDefaultStore, inspectProjectBinding, isDirectionalManagedLocalTranslationEngineId, isManagedLocalTranslationEngineId, isTerminalMutationStatus, isTranslationEngineDependencyReady, isTranslationEngineRuntimeReady, loadOpenSpecAgentCommandContents, normalizeAgentDeliveryPolicy, normalizeBatchTranslationError, parseCliCommandResult, parseOpsxEntityMetadata, parseOpsxSchemaDetail, patchActiveRootOfficialFields, reactiveReadFile, reactiveStat, removePhysicalReactivePath, requireCanonicalOpenSpecEntityId, requireCanonicalOpenSpecSpecId, requireOpenSpecEntityRelativePath, resolveOpenSpecDataScope, resolveRootContext, resolveRuntimePackageInstallStrategy, resolveTerminalShellDefaults, runPhysicalReactivePathMutation, selectLocalDownloadGroup, shouldShowTranslationEngineInstallGate, sniffGlobalCli, subscribeWatcherRuntimeStatus, terminalNotificationEventToPublishInput, toCliProjectionCommandEvidence, toCliProjectionFailure, toCliProjectionNotice, toStoreFeatureResult, toggleMarkdownTask, updateProjectBindingContent, updateReactiveFileCache, validateActiveRootRawYaml, writePhysicalReactiveFile } from "@openspecui/core";
|
|
3
|
+
import { AI_TOOLS, ActiveRootMutationSchema, ActiveRootRevisionSchema, AgentDeliveryPolicyUpdateSchema, BatchTranslateInputSchema, CliExecutor, CliProjectionCommandError, CliProjectionNoticeSchema, CodeEditorThemeSchema, ConfigManager, CustomSoundHashSchema, DASHBOARD_METRIC_KEYS, DashboardConfigSchema, DashboardGitSnapshotSchema, DashboardSummaryInvalidationSchema, DashboardSummaryProjectionStateSchema, DashboardTrendsProjectionSchema, DocumentTranslationConfigUpdateSchema, EnvironmentDefaultStoreUpdateSchema, EnvironmentGlobalConfigValueSchema, EnvironmentGlobalFileProjectionDataSchema, EnvironmentGlobalFileProjectionStateSchema, EnvironmentGlobalProjectionDataSchema, EnvironmentGlobalProjectionStateSchema, GitConfigSchema, GlobalSettingsManager, LocalModelAssetStateSchema, LocalModelLifecycleFileStateSchema, LocalModelLifecycleGroupStateSchema, LocalModelProfileManifestSchema, MarkdownParser, NotificationPublishInputSchema, NotificationSettingsSchema, OPENSPECUI_DOCUMENT_HOOK_VERSION, OPENSPECUI_WORKFLOW_HOOK_VERSION, OPSX_ARTIFACT_INPUT_ACTIONS, OPSX_CHANGE_INPUT_ACTIONS, OPSX_COMMAND_CAPABLE_WORKFLOWS, OPSX_CORE_PROFILE_WORKFLOWS, OPSX_TEXT_INPUT_ACTIONS, OpenSpecAdapter, OpenSpecDataHomeObserver, OpenSpecUIGlobalSettingsUpdateSchema, OpenSpecWatcher, OpsxConfigSchema, OpsxKernel, OwnedSpecIdentitySchema, PINNED_AGENT_GENERATOR_VERSION, PlanningCliProjectionDataSchema, PlanningCliProjectionSelectorSchema, PlanningCliProjectionStateSchema, ProjectBindingUpdateSchema, ProjectWatcher, PtyClientMessageSchema, RUNTIME_INVALIDATION_FACETS, ReactiveContext, ReactiveObservationEnvironment, ReactiveState, RuntimeInvalidationIndex, RuntimeRootInvalidationRegistry, ServiceTranslationEngineIdSchema, SpecIdentitySchema, StoreDoctorResultSchema, StoreListResultSchema, StoreMutationLifecycleEventSchema, StoreMutationStartResponseSchema, TRANSLATION_ENGINE_MANIFESTS, TerminalConfigSchema, TerminalControlParser, TerminalRendererEngineSchema, TranslationCacheReadInputSchema, TranslationCacheWriteInputSchema, TranslationEngineIdSchema, TranslationEngineLifecycleStatusSchema, acquireWatcher, applyAgentDeliveryPolicy, buildBackendHealthPayload, buildLocalDownloadPlanFromRepositoryFiles, buildRuntimePackageInstallCommand, checkLocalDirectionalModelLanguagePair, classifyStoreCliResult, clearCache, compareAndWriteAtomicPhysicalReactiveFile, computeEnvUri, constantTimeEqual, createCleanCliEnv, createPhysicalReactiveDirectory, createToolInitStateProjection, createTranslationEngineLifecycleStatus, detectRuntimePackageManager, getAllTools, getAvailableTools, getConfiguredTools, getDefaultCliCommandString, getDetectedProjectTools, getExternalCodexCommandObservationRoot, getManagedLocalTranslationEngineManifest, getOpsxEntityRootRelativePath, getRootContextCliSelector, getToolInitStates, getTranslationEngineLifecycleMessage, getWatcherRuntimeStatus, inferFileMime, inferFilePreviewKind, inspectActiveRootOfficialConfig, inspectEnvironmentDefaultStore, inspectProjectBinding, isDirectionalManagedLocalTranslationEngineId, isManagedLocalTranslationEngineId, isTerminalMutationStatus, isTranslationEngineDependencyReady, isTranslationEngineRuntimeReady, loadOpenSpecAgentCommandContents, normalizeAgentDeliveryPolicy, normalizeBatchTranslationError, parseCliCommandResult, parseOpsxEntityMetadata, parseOpsxSchemaDetail, patchActiveRootOfficialFields, reactiveReadFile, reactiveStat, removePhysicalReactivePath, replaceFileAtomically, requireCanonicalOpenSpecEntityId, requireCanonicalOpenSpecSpecId, requireOpenSpecEntityRelativePath, resolveCommandInvocation, resolveOpenSpecDataScope, resolveRootContext, resolveRuntimePackageInstallStrategy, resolveTerminalShellDefaults, runPhysicalReactivePathMutation, selectLocalDownloadGroup, shouldShowTranslationEngineInstallGate, sniffGlobalCli, spawnSafe, subscribeWatcherRuntimeStatus, terminalNotificationEventToPublishInput, terminateChildProcessTree, toCliProjectionCommandEvidence, toCliProjectionFailure, toCliProjectionNotice, toStoreFeatureResult, toggleMarkdownTask, updateProjectBindingContent, updateReactiveFileCache, validateActiveRootRawYaml, writePhysicalReactiveFile } from "@openspecui/core";
|
|
4
4
|
import { basename, dirname, extname, isAbsolute, join, matchesGlob, relative, resolve, sep } from "node:path";
|
|
5
|
-
import { access, copyFile, lstat, mkdir, open, readFile, readlink, realpath, rename, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
5
|
+
import { access, copyFile, link, lstat, mkdir, open, readFile, readlink, realpath, rename, rm, stat, symlink, unlink, writeFile } from "node:fs/promises";
|
|
6
6
|
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
7
7
|
import { downloadFile, fileDownloadInfo, listFiles, modelInfo } from "@huggingface/hub";
|
|
8
8
|
import { observable } from "@trpc/server/observable";
|
|
9
9
|
import { existsSync, readFileSync, realpathSync, statSync, write, writeFileSync } from "node:fs";
|
|
10
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
10
11
|
import { freemem, homedir, hostname, platform, totalmem } from "node:os";
|
|
11
12
|
import { z } from "zod";
|
|
12
13
|
import { Agent, EnvHttpProxyAgent, setGlobalDispatcher } from "undici";
|
|
@@ -20,7 +21,6 @@ import { cors } from "hono/cors";
|
|
|
20
21
|
import { WebSocketServer } from "ws";
|
|
21
22
|
import { Buffer as Buffer$1 } from "node:buffer";
|
|
22
23
|
import { CustomSoundHashSchema as CustomSoundHashSchema$1, CustomSoundIdSchema, CustomSoundMetadataFileSchema, customHashFromSoundId, soundIdFromCustomHash } from "@openspecui/core/sounds";
|
|
23
|
-
import { createHash, randomUUID } from "node:crypto";
|
|
24
24
|
import { execFile, spawn } from "node:child_process";
|
|
25
25
|
import { promisify } from "node:util";
|
|
26
26
|
import { NotificationGroupKeySchema, NotificationPublishInputSchema as NotificationPublishInputSchema$1, getNotificationGroupKey } from "@openspecui/core/notifications";
|
|
@@ -502,7 +502,7 @@ var ProjectHookRuntime = class {
|
|
|
502
502
|
}
|
|
503
503
|
async loadFresh() {
|
|
504
504
|
if (!await pathExists$1(this.hooksPath)) return {};
|
|
505
|
-
const { tsImport } = await import("./api-
|
|
505
|
+
const { tsImport } = await import("./api-C_H23KUr.mjs");
|
|
506
506
|
return normalizeHooksModule(await tsImport(`${pathToFileURL(this.hooksPath).href}?t=${Date.now()}`, { parentURL: pathToFileURL(this.hooksPath).href }));
|
|
507
507
|
}
|
|
508
508
|
};
|
|
@@ -524,6 +524,14 @@ function buildHuggingFaceApiBaseUrl(endpoint) {
|
|
|
524
524
|
|
|
525
525
|
//#endregion
|
|
526
526
|
//#region src/local-model-asset-store.ts
|
|
527
|
+
/**
|
|
528
|
+
* Orthogonal intents (updated 2026-08-05 Asia/Shanghai):
|
|
529
|
+
* 1. Persist normalized local-model lifecycle state through complete JSON replacements.
|
|
530
|
+
* 2. Survive transient Windows target locks without exposing partial metadata.
|
|
531
|
+
* 3. Retire reactive caches only after the replacement commits.
|
|
532
|
+
*
|
|
533
|
+
* Original request (2026-08-05): Continue the Windows adaptation and fix equivalent failures together.
|
|
534
|
+
*/
|
|
527
535
|
const LocalModelAssetIndexSchema = LocalModelAssetStateSchema.array();
|
|
528
536
|
var LocalModelAssetStore = class {
|
|
529
537
|
constructor(options) {
|
|
@@ -549,9 +557,13 @@ var LocalModelAssetStore = class {
|
|
|
549
557
|
const normalized = LocalModelAssetIndexSchema.parse([...states].sort((left, right) => left.modelId.localeCompare(right.modelId)));
|
|
550
558
|
const serialized = JSON.stringify(normalized, null, 2);
|
|
551
559
|
await mkdir(dirname(this.options.indexPath), { recursive: true });
|
|
552
|
-
const tempPath = `${this.options.indexPath}.${process.pid}.${
|
|
553
|
-
|
|
554
|
-
|
|
560
|
+
const tempPath = `${this.options.indexPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
561
|
+
try {
|
|
562
|
+
await writeFile(tempPath, `${serialized}\n`, "utf8");
|
|
563
|
+
await replaceFileAtomically(tempPath, this.options.indexPath);
|
|
564
|
+
} finally {
|
|
565
|
+
await rm(tempPath, { force: true }).catch(() => void 0);
|
|
566
|
+
}
|
|
555
567
|
clearCache();
|
|
556
568
|
}
|
|
557
569
|
async upsert(state) {
|
|
@@ -759,6 +771,14 @@ function getTransformersFileCacheModelPath(cacheDir, modelId) {
|
|
|
759
771
|
|
|
760
772
|
//#endregion
|
|
761
773
|
//#region src/local-model-profile-manifest-store.ts
|
|
774
|
+
/**
|
|
775
|
+
* Orthogonal intents (updated 2026-08-05 Asia/Shanghai):
|
|
776
|
+
* 1. Persist normalized local-model profile manifests through complete JSON replacements.
|
|
777
|
+
* 2. Survive transient Windows target locks without exposing partial metadata.
|
|
778
|
+
* 3. Retire reactive caches only after the replacement commits.
|
|
779
|
+
*
|
|
780
|
+
* Original request (2026-08-05): Continue the Windows adaptation and fix equivalent failures together.
|
|
781
|
+
*/
|
|
762
782
|
const LocalModelProfileManifestIndexSchema = z.object({
|
|
763
783
|
version: z.literal(1).default(1),
|
|
764
784
|
manifests: z.array(LocalModelProfileManifestSchema).default([])
|
|
@@ -786,9 +806,13 @@ var LocalModelProfileManifestStore = class {
|
|
|
786
806
|
});
|
|
787
807
|
const serialized = JSON.stringify(normalized, null, 2);
|
|
788
808
|
await mkdir(dirname(this.options.manifestPath), { recursive: true });
|
|
789
|
-
const tempPath = `${this.options.manifestPath}.${process.pid}.${
|
|
790
|
-
|
|
791
|
-
|
|
809
|
+
const tempPath = `${this.options.manifestPath}.${process.pid}.${randomUUID()}.tmp`;
|
|
810
|
+
try {
|
|
811
|
+
await writeFile(tempPath, `${serialized}\n`, "utf8");
|
|
812
|
+
await replaceFileAtomically(tempPath, this.options.manifestPath);
|
|
813
|
+
} finally {
|
|
814
|
+
await rm(tempPath, { force: true }).catch(() => void 0);
|
|
815
|
+
}
|
|
792
816
|
clearCache();
|
|
793
817
|
}
|
|
794
818
|
async upsert(manifest) {
|
|
@@ -1390,6 +1414,16 @@ function isRecord$2(value) {
|
|
|
1390
1414
|
|
|
1391
1415
|
//#endregion
|
|
1392
1416
|
//#region src/local-model-asset-service.ts
|
|
1417
|
+
/**
|
|
1418
|
+
* Orthogonal intents (updated 2026-08-09 Asia/Shanghai):
|
|
1419
|
+
* 1. Resolve local translation model catalogs and versioned profile manifests.
|
|
1420
|
+
* 2. Own resumable download, pause, cancellation, retry, progress, and bounded Windows finalization.
|
|
1421
|
+
* 3. Materialize downloaded profiles and platform-appropriate Hugging Face cache pointers.
|
|
1422
|
+
* 4. Preserve selected-group authority while background work settles.
|
|
1423
|
+
* 5. Publish typed lifecycle snapshots and bounded diagnostics.
|
|
1424
|
+
*
|
|
1425
|
+
* Original request (2026-08-04): "Adapt macOS-first development and runtime paths to Windows."
|
|
1426
|
+
*/
|
|
1393
1427
|
const DEFAULT_NETWORK_RETRY_LIMIT$2 = Number.POSITIVE_INFINITY;
|
|
1394
1428
|
const DEFAULT_NETWORK_RETRY_DELAY_MS$2 = 500;
|
|
1395
1429
|
const DEFAULT_NETWORK_RETRY_DELAY_MAX_MS$2 = 5e3;
|
|
@@ -2742,10 +2776,10 @@ async function streamDownloadToIncompleteFile(input) {
|
|
|
2742
2776
|
}
|
|
2743
2777
|
return true;
|
|
2744
2778
|
}
|
|
2779
|
+
/** Commit one complete model file without deleting the previous target before replacement succeeds. */
|
|
2745
2780
|
async function finalizeDownloadedFile$1(input) {
|
|
2746
2781
|
await mkdir(dirname(input.targetPath), { recursive: true });
|
|
2747
|
-
await
|
|
2748
|
-
await rename(input.incompletePath, input.targetPath);
|
|
2782
|
+
await replaceFileAtomically(input.incompletePath, input.targetPath);
|
|
2749
2783
|
}
|
|
2750
2784
|
async function mirrorDownloadedFileToHubCache(input) {
|
|
2751
2785
|
await mkdir(dirname(input.cachePaths.blobPath), { recursive: true });
|
|
@@ -2753,7 +2787,8 @@ async function mirrorDownloadedFileToHubCache(input) {
|
|
|
2753
2787
|
await rm(input.cachePaths.blobPath, { force: true });
|
|
2754
2788
|
await copyFile(input.targetPath, input.cachePaths.blobPath);
|
|
2755
2789
|
await unlink(input.cachePaths.pointerPath).catch(() => void 0);
|
|
2756
|
-
await
|
|
2790
|
+
if (process.platform === "win32") await link(input.cachePaths.blobPath, input.cachePaths.pointerPath);
|
|
2791
|
+
else await symlink(input.cachePaths.blobPath, input.cachePaths.pointerPath);
|
|
2757
2792
|
}
|
|
2758
2793
|
function getHubCacheFilePaths(input) {
|
|
2759
2794
|
const repoPath = getHubCacheRepoPath(input.cacheDir, input.modelId);
|
|
@@ -6504,7 +6539,10 @@ var EnvironmentGlobalProjectionService = class {
|
|
|
6504
6539
|
* 2. Distinguish a valid non-repository path from an identity-command failure.
|
|
6505
6540
|
* 3. Canonicalize repository paths for binding identity and stale-intent checks.
|
|
6506
6541
|
* 4. Propagate cooperative cancellation into Git subprocess ownership.
|
|
6542
|
+
* 5. Hide the Git subprocess console window (`windowsHide`) so Git executed by a console-less
|
|
6543
|
+
* Windows daemon never flashes a cmd window.
|
|
6507
6544
|
*
|
|
6545
|
+
* Original request (2026-08-14): "在Windows平台上,执行命令总是会弹出cmd窗口,这个可否统一隐藏,你先调查一下原因"
|
|
6508
6546
|
* Original request (2026-07-19): "代码已经提交,开始review。如果有问题,那么可更新change。"
|
|
6509
6547
|
* Derived requirement (2026-07-19): Checkpoint 6.11 preserves objective Planning Git failures.
|
|
6510
6548
|
* Original request (2026-07-31): "Code Git Snapshot,它非常慢,有时候甚至要十几秒"
|
|
@@ -6521,7 +6559,8 @@ async function defaultRunGit(cwd, args, signal) {
|
|
|
6521
6559
|
cwd,
|
|
6522
6560
|
encoding: "utf8",
|
|
6523
6561
|
maxBuffer: 8 * 1024 * 1024,
|
|
6524
|
-
signal
|
|
6562
|
+
signal,
|
|
6563
|
+
windowsHide: true
|
|
6525
6564
|
});
|
|
6526
6565
|
return {
|
|
6527
6566
|
ok: true,
|
|
@@ -9076,7 +9115,10 @@ async function buildDashboardGitSnapshot(options) {
|
|
|
9076
9115
|
* 2. Preserve backend-issued Code binding provenance and observable Git task lifecycle.
|
|
9077
9116
|
* 3. Trigger explicit Git snapshot invalidation through a reactive stamp without broad Dashboard reloads.
|
|
9078
9117
|
* 4. Propagate Projection Work cancellation into the Git subprocess tree.
|
|
9118
|
+
* 5. Hide Git identity-probe subprocess console windows (`windowsHide`) under the console-less
|
|
9119
|
+
* Windows daemon.
|
|
9079
9120
|
*
|
|
9121
|
+
* Original request (2026-08-14): "在Windows平台上,执行命令总是会弹出cmd窗口,这个可否统一隐藏,你先调查一下原因"
|
|
9080
9122
|
* Original request (2026-07-23): "现在页面数据的加载数据非常慢(比如dashboard页面、changes页面都要等待非常久,页面刷新后,似乎后台没有缓存一样,也要加载很久。"
|
|
9081
9123
|
* Derived requirement (2026-07-25): P4.3 settles a cached refresh stamp before Dashboard Git refresh returns.
|
|
9082
9124
|
* Original request (2026-07-31): "Code Git Snapshot,它非常慢,有时候甚至要十几秒"
|
|
@@ -9127,7 +9169,8 @@ async function resolveGitMetadataDir(projectDir) {
|
|
|
9127
9169
|
const { stdout } = await execFileAsync$1("git", ["rev-parse", "--git-dir"], {
|
|
9128
9170
|
cwd: projectDir,
|
|
9129
9171
|
maxBuffer: 1024 * 1024,
|
|
9130
|
-
encoding: "utf8"
|
|
9172
|
+
encoding: "utf8",
|
|
9173
|
+
windowsHide: true
|
|
9131
9174
|
});
|
|
9132
9175
|
const gitDirRaw = stdout.trim();
|
|
9133
9176
|
if (!gitDirRaw) return null;
|
|
@@ -9667,12 +9710,13 @@ function resolveEntityEntryPath(input) {
|
|
|
9667
9710
|
//#endregion
|
|
9668
9711
|
//#region src/file-preview-service.ts
|
|
9669
9712
|
/**
|
|
9670
|
-
* Orthogonal intents (updated 2026-
|
|
9713
|
+
* Orthogonal intents (updated 2026-08-04 Asia/Shanghai):
|
|
9671
9714
|
* 1. Prepare source-bound preview sessions for supported entity files.
|
|
9672
|
-
* 2. Serve preview documents and bundled assets with confined path resolution.
|
|
9715
|
+
* 2. Serve preview documents and bundled assets with platform-neutral confined path resolution.
|
|
9673
9716
|
* 3. Retire every preview session when its owning Planning root is replaced.
|
|
9674
9717
|
*
|
|
9675
9718
|
* Original request (2026-07-16): "A -> B 后必须清退 A 的 preview。"
|
|
9719
|
+
* Original request (2026-08-04): "Make pnpm openspecui start and equivalent package scripts work on Windows."
|
|
9676
9720
|
*/
|
|
9677
9721
|
const PREVIEW_ENTRY_FILE_BY_KIND = {
|
|
9678
9722
|
image: "image-preview.html",
|
|
@@ -9696,6 +9740,10 @@ function toHash(input) {
|
|
|
9696
9740
|
function stripLeadingSlash(path) {
|
|
9697
9741
|
return path.replace(/^\/+/, "");
|
|
9698
9742
|
}
|
|
9743
|
+
function isPathInsideRoot(rootPath, candidatePath) {
|
|
9744
|
+
const relativePath$1 = relative(rootPath, candidatePath);
|
|
9745
|
+
return relativePath$1 === "" || relativePath$1 !== ".." && !relativePath$1.startsWith(`..${sep}`) && !isAbsolute(relativePath$1);
|
|
9746
|
+
}
|
|
9699
9747
|
function inferPreviewAssetContentType(path) {
|
|
9700
9748
|
switch (extname(path).toLowerCase()) {
|
|
9701
9749
|
case ".html": return "text/html";
|
|
@@ -9773,7 +9821,7 @@ var FilePreviewService = class {
|
|
|
9773
9821
|
const normalized = stripLeadingSlash(requestPath);
|
|
9774
9822
|
if (session.previewKind === "html") {
|
|
9775
9823
|
const absolutePath$1 = resolve(session.directoryPath, normalized);
|
|
9776
|
-
if (!
|
|
9824
|
+
if (!isPathInsideRoot(session.directoryPath, absolutePath$1)) return null;
|
|
9777
9825
|
if (!existsSync(absolutePath$1) || !statSync(absolutePath$1).isFile()) return null;
|
|
9778
9826
|
return {
|
|
9779
9827
|
content: readFileSync(absolutePath$1),
|
|
@@ -9783,7 +9831,7 @@ var FilePreviewService = class {
|
|
|
9783
9831
|
if (normalized.startsWith("resource/")) {
|
|
9784
9832
|
const resourcePath = normalized.slice(9);
|
|
9785
9833
|
const absolutePath$1 = resolve(session.directoryPath, resourcePath);
|
|
9786
|
-
if (!
|
|
9834
|
+
if (!isPathInsideRoot(session.directoryPath, absolutePath$1)) return null;
|
|
9787
9835
|
if (!existsSync(absolutePath$1) || !statSync(absolutePath$1).isFile()) return null;
|
|
9788
9836
|
return {
|
|
9789
9837
|
content: readFileSync(absolutePath$1),
|
|
@@ -9793,7 +9841,7 @@ var FilePreviewService = class {
|
|
|
9793
9841
|
const assetName = normalized || session.entryFileName;
|
|
9794
9842
|
if (!assetName) return null;
|
|
9795
9843
|
const absolutePath = resolve(this.previewAssetsDir, assetName);
|
|
9796
|
-
if (!
|
|
9844
|
+
if (!isPathInsideRoot(this.previewAssetsDir, absolutePath)) return null;
|
|
9797
9845
|
if (!existsSync(absolutePath) || !statSync(absolutePath).isFile()) return null;
|
|
9798
9846
|
if (isRewritablePreviewAsset(assetName)) {
|
|
9799
9847
|
const rewritten = rewritePreviewAssetPaths(readFileSync(absolutePath, "utf8"), hash);
|
|
@@ -11828,11 +11876,12 @@ var PtyInputWriter = class {
|
|
|
11828
11876
|
//#endregion
|
|
11829
11877
|
//#region src/pty-manager.ts
|
|
11830
11878
|
/**
|
|
11831
|
-
* Orthogonal intents (updated 2026-
|
|
11879
|
+
* Orthogonal intents (updated 2026-08-09 Asia/Shanghai):
|
|
11832
11880
|
* 1. Own PTY session process, ordered input, buffer, title, and lifecycle state.
|
|
11833
11881
|
* 2. Spawn each session at an explicitly resolved launch-project or planning-root cwd and retain its immutable Root generation.
|
|
11834
11882
|
* 3. Preserve the inherited backend environment, including XDG_DATA_HOME, across cwd targets.
|
|
11835
11883
|
* 4. List and close server-owned sessions for reconnect and teardown.
|
|
11884
|
+
* 5. Resolve Windows Agent launchers to native argv while retaining the requested display command.
|
|
11836
11885
|
*
|
|
11837
11886
|
* Original request (2026-07-16): "3.8 Terminal exposes explicit launch-project cwd and planning-root cwd while preserving inherited XDG_DATA_HOME"
|
|
11838
11887
|
* Owner-reported defect (2026-07-21): Pre-created Agent terminals are absent from Compose Send.
|
|
@@ -11919,7 +11968,11 @@ var PtySession = class extends EventEmitter$1 {
|
|
|
11919
11968
|
this.rootGeneration = opts.rootGeneration;
|
|
11920
11969
|
this.maxBufferLines = opts.scrollback ?? DEFAULT_SCROLLBACK;
|
|
11921
11970
|
this.maxBufferBytes = opts.maxBufferBytes ?? DEFAULT_MAX_BUFFER_BYTES;
|
|
11922
|
-
|
|
11971
|
+
const invocation = resolveCommandInvocation(this.command, this.args, {
|
|
11972
|
+
cwd: opts.cwd,
|
|
11973
|
+
env: process.env
|
|
11974
|
+
});
|
|
11975
|
+
this.process = pty.spawn(invocation.command, invocation.args, {
|
|
11923
11976
|
name: "xterm-256color",
|
|
11924
11977
|
cols: opts.cols ?? 80,
|
|
11925
11978
|
rows: opts.rows ?? 24,
|
|
@@ -17774,10 +17827,12 @@ var TranslationCacheService = class {
|
|
|
17774
17827
|
//#endregion
|
|
17775
17828
|
//#region src/runtime-package-host.ts
|
|
17776
17829
|
/**
|
|
17777
|
-
*
|
|
17830
|
+
* Original request (2026-08-04): "The project was developed on macOS and now needs Windows adaptation."
|
|
17831
|
+
* Orthogonal intents (updated 2026-08-08 Asia/Shanghai):
|
|
17778
17832
|
* 1. Resolve the physical host manifest that owns on-demand runtime installation.
|
|
17779
17833
|
* 2. Read declared runtime ranges without treating optional peers as install-time dependencies.
|
|
17780
17834
|
* 3. Normalize legacy on-demand optional dependency records after package-manager installation.
|
|
17835
|
+
* 4. Execute the npm dependency probe through Core's shell-independent Windows-safe spawn owner.
|
|
17781
17836
|
*
|
|
17782
17837
|
* Original request (2026-07-31): "这个依赖好像会导致安装的时候仍然会被强制装上去,可能要改成 peerDependencies 会更好"
|
|
17783
17838
|
*/
|
|
@@ -17814,7 +17869,7 @@ function readRuntimeHostPackageDependencyRequest(input) {
|
|
|
17814
17869
|
return `${input.packageName}@${range}`;
|
|
17815
17870
|
}
|
|
17816
17871
|
async function readRuntimeHostPackageDependencyTree(input) {
|
|
17817
|
-
const
|
|
17872
|
+
const started = spawnSafe("npm", [
|
|
17818
17873
|
"list",
|
|
17819
17874
|
"--json",
|
|
17820
17875
|
"--omit=dev",
|
|
@@ -17822,9 +17877,10 @@ async function readRuntimeHostPackageDependencyTree(input) {
|
|
|
17822
17877
|
...input.packageNames
|
|
17823
17878
|
], {
|
|
17824
17879
|
cwd: input.runtimeHost.packageDir,
|
|
17825
|
-
shell: false,
|
|
17826
17880
|
env: createCleanCliEnv()
|
|
17827
17881
|
});
|
|
17882
|
+
if (!started.ok) throw new Error(`Unable to start npm list: ${started.error.message}`);
|
|
17883
|
+
const { child } = started;
|
|
17828
17884
|
const stdoutChunks = [];
|
|
17829
17885
|
const stderrChunks = [];
|
|
17830
17886
|
const exitCode = await new Promise((resolve$1, reject) => {
|
|
@@ -18066,6 +18122,17 @@ function buildRuntimeConfig(engineId, profile) {
|
|
|
18066
18122
|
|
|
18067
18123
|
//#endregion
|
|
18068
18124
|
//#region src/translation-engine-service.ts
|
|
18125
|
+
/**
|
|
18126
|
+
* Orthogonal intents (updated 2026-08-09 Asia/Shanghai):
|
|
18127
|
+
* 1. Project translation-engine inventory, selection, lifecycle, and immutable settings snapshots.
|
|
18128
|
+
* 2. Install and cancel managed local runtime dependencies through observable, bounded process settlement.
|
|
18129
|
+
* 3. Own local model search, download plans, persisted asset readiness, and profile validation.
|
|
18130
|
+
* 4. Execute browser, OpenAI, and managed-local batch translation with cache-aware events.
|
|
18131
|
+
* 5. Preserve CT2/llama runtime policy, directional language constraints, and resource limits.
|
|
18132
|
+
*
|
|
18133
|
+
* Original request (2026-05-22): "Server provides engine registry, installation sessions, installation logs, selection, and translation."
|
|
18134
|
+
* Original request (2026-08-04): "Make pnpm openspecui start and equivalent package scripts work on Windows."
|
|
18135
|
+
*/
|
|
18069
18136
|
const __dirname$2 = dirname(fileURLToPath(import.meta.url));
|
|
18070
18137
|
var TranslationEngineService = class {
|
|
18071
18138
|
projectDir;
|
|
@@ -18796,55 +18863,82 @@ async function installManagedLocalRuntime(engineId, input) {
|
|
|
18796
18863
|
input.onLifecycle?.(finalLifecycle);
|
|
18797
18864
|
return finalLifecycle;
|
|
18798
18865
|
}
|
|
18866
|
+
/** Run one package-manager installation with bounded cross-platform tree cancellation. */
|
|
18799
18867
|
async function runRuntimeInstallCommand(input) {
|
|
18800
|
-
|
|
18801
|
-
|
|
18802
|
-
|
|
18803
|
-
|
|
18804
|
-
|
|
18805
|
-
|
|
18806
|
-
|
|
18807
|
-
}
|
|
18808
|
-
|
|
18809
|
-
|
|
18810
|
-
|
|
18811
|
-
|
|
18812
|
-
|
|
18813
|
-
} catch {}
|
|
18814
|
-
};
|
|
18815
|
-
input.signal?.addEventListener("abort", abort, { once: true });
|
|
18816
|
-
try {
|
|
18817
|
-
await new Promise((resolve$1, reject) => {
|
|
18818
|
-
child.stdout?.on("data", (data) => {
|
|
18819
|
-
input.onLog?.({
|
|
18820
|
-
stream: "stdout",
|
|
18821
|
-
text: data.toString()
|
|
18822
|
-
});
|
|
18823
|
-
});
|
|
18824
|
-
child.stderr?.on("data", (data) => {
|
|
18825
|
-
input.onLog?.({
|
|
18826
|
-
stream: "stderr",
|
|
18827
|
-
text: data.toString()
|
|
18828
|
-
});
|
|
18829
|
-
});
|
|
18830
|
-
child.on("error", (error) => {
|
|
18831
|
-
reject(error);
|
|
18868
|
+
if (input.signal?.aborted) return "Translation runtime installation cancelled.";
|
|
18869
|
+
const started = spawnSafe(input.command.cmd, input.command.args, {
|
|
18870
|
+
cwd: input.cwd,
|
|
18871
|
+
shell: false,
|
|
18872
|
+
env: createCleanCliEnv()
|
|
18873
|
+
});
|
|
18874
|
+
if (!started.ok) return started.error.message;
|
|
18875
|
+
const { child } = started;
|
|
18876
|
+
const completion = new Promise((resolve$1) => {
|
|
18877
|
+
child.stdout?.on("data", (data) => {
|
|
18878
|
+
input.onLog?.({
|
|
18879
|
+
stream: "stdout",
|
|
18880
|
+
text: data.toString()
|
|
18832
18881
|
});
|
|
18833
|
-
|
|
18834
|
-
|
|
18835
|
-
|
|
18836
|
-
|
|
18837
|
-
|
|
18838
|
-
reject(/* @__PURE__ */ new Error(`${input.command.displayCommand} exited with code ${exitCode ?? "unknown"}.`));
|
|
18882
|
+
});
|
|
18883
|
+
child.stderr?.on("data", (data) => {
|
|
18884
|
+
input.onLog?.({
|
|
18885
|
+
stream: "stderr",
|
|
18886
|
+
text: data.toString()
|
|
18839
18887
|
});
|
|
18840
18888
|
});
|
|
18841
|
-
|
|
18842
|
-
|
|
18843
|
-
|
|
18889
|
+
child.once("error", (error) => resolve$1(error.message));
|
|
18890
|
+
child.once("close", (exitCode) => {
|
|
18891
|
+
resolve$1(exitCode === 0 ? null : `${input.command.displayCommand} exited with code ${exitCode ?? "unknown"}.`);
|
|
18892
|
+
});
|
|
18893
|
+
});
|
|
18894
|
+
let requestAbort = null;
|
|
18895
|
+
const abortRequested = new Promise((resolve$1) => {
|
|
18896
|
+
requestAbort = resolve$1;
|
|
18897
|
+
});
|
|
18898
|
+
const abort = () => requestAbort?.();
|
|
18899
|
+
input.signal?.addEventListener("abort", abort, { once: true });
|
|
18900
|
+
try {
|
|
18901
|
+
const outcome = await Promise.race([completion.then((result) => ({
|
|
18902
|
+
kind: "complete",
|
|
18903
|
+
result
|
|
18904
|
+
})), abortRequested.then(() => ({ kind: "abort" }))]);
|
|
18905
|
+
if (outcome.kind === "complete") return outcome.result;
|
|
18906
|
+
return settleRuntimeInstallCancellation(child, completion, input.terminationTimeoutMs ?? 5e3);
|
|
18844
18907
|
} finally {
|
|
18845
18908
|
input.signal?.removeEventListener("abort", abort);
|
|
18846
18909
|
}
|
|
18847
18910
|
}
|
|
18911
|
+
async function settleRuntimeInstallCancellation(child, completion, timeoutMs) {
|
|
18912
|
+
const failures = [];
|
|
18913
|
+
const terminate = async (signal) => {
|
|
18914
|
+
let timer = null;
|
|
18915
|
+
try {
|
|
18916
|
+
await Promise.race([terminateChildProcessTree(child, signal), new Promise((_resolve, reject) => {
|
|
18917
|
+
timer = setTimeout(() => reject(/* @__PURE__ */ new Error(`Timed out requesting ${signal} for runtime installation.`)), timeoutMs);
|
|
18918
|
+
})]);
|
|
18919
|
+
} catch (error) {
|
|
18920
|
+
failures.push(error);
|
|
18921
|
+
} finally {
|
|
18922
|
+
if (timer) clearTimeout(timer);
|
|
18923
|
+
}
|
|
18924
|
+
};
|
|
18925
|
+
const waitForCompletion = async () => {
|
|
18926
|
+
let timer = null;
|
|
18927
|
+
try {
|
|
18928
|
+
return await Promise.race([completion.then(() => true), new Promise((resolve$1) => {
|
|
18929
|
+
timer = setTimeout(() => resolve$1(false), timeoutMs);
|
|
18930
|
+
})]);
|
|
18931
|
+
} finally {
|
|
18932
|
+
if (timer) clearTimeout(timer);
|
|
18933
|
+
}
|
|
18934
|
+
};
|
|
18935
|
+
await terminate("SIGTERM");
|
|
18936
|
+
if (await waitForCompletion()) return "Translation runtime installation cancelled.";
|
|
18937
|
+
await terminate("SIGKILL");
|
|
18938
|
+
if (await waitForCompletion()) return "Translation runtime installation cancelled.";
|
|
18939
|
+
const failureText = failures.map((error) => error instanceof Error ? error.message : String(error)).join(" ");
|
|
18940
|
+
return `Translation runtime installation cancellation did not settle.${failureText ? ` ${failureText}` : ""}`;
|
|
18941
|
+
}
|
|
18848
18942
|
function getManagedLocalRuntimeSpec(engineId) {
|
|
18849
18943
|
if (engineId === "local") return {
|
|
18850
18944
|
packageNames: ["@huggingface/transformers", "onnxruntime-node"],
|
|
@@ -18957,7 +19051,9 @@ function readCurrentRuntimeMemory() {
|
|
|
18957
19051
|
* 2. Execute translation engines in isolated worker-thread or process hosts.
|
|
18958
19052
|
* 3. Enforce cancellation and process memory limits while preserving batch evidence.
|
|
18959
19053
|
* 4. Route worker-thread payloads by an explicit translation protocol kind.
|
|
19054
|
+
* 5. Hide the process-host bootstrap console window (`windowsHide`) under a console-less Windows daemon.
|
|
18960
19055
|
*
|
|
19056
|
+
* Original request (2026-08-14): "在Windows平台上,执行命令总是会弹出cmd窗口,这个可否统一隐藏,你先调查一下原因"
|
|
18961
19057
|
* Original request (2026-07-24): "Production worker kinds must not claim each other's payloads."
|
|
18962
19058
|
*/
|
|
18963
19059
|
const execFileAsync = promisify(execFile);
|
|
@@ -19253,7 +19349,8 @@ function createManagedLocalTranslationProcess(input) {
|
|
|
19253
19349
|
"inherit",
|
|
19254
19350
|
"inherit",
|
|
19255
19351
|
"ipc"
|
|
19256
|
-
]
|
|
19352
|
+
],
|
|
19353
|
+
windowsHide: true
|
|
19257
19354
|
});
|
|
19258
19355
|
}
|
|
19259
19356
|
function resolveProcessEntryUrl() {
|
|
@@ -19410,11 +19507,11 @@ if (!isMainThread) {
|
|
|
19410
19507
|
//#endregion
|
|
19411
19508
|
//#region src/server.ts
|
|
19412
19509
|
/**
|
|
19413
|
-
* Orthogonal intents (updated 2026-08-
|
|
19510
|
+
* Orthogonal intents (updated 2026-08-04 Asia/Shanghai):
|
|
19414
19511
|
* 1. Bootstrap HTTP/tRPC, WebSocket, PTY, and launch-project runtime services.
|
|
19415
19512
|
* 2. Delegate planning-root, Store, Environment Global, Agent, and Root Context projection ownership.
|
|
19416
19513
|
* 3. Host notifications, sound, preview-resource, translation, and telemetry boundaries.
|
|
19417
|
-
* 4. Admit dynamic loopback App origins and
|
|
19514
|
+
* 4. Admit dynamic loopback App origins and await deterministic native-handle teardown.
|
|
19418
19515
|
* 5. Bridge settled machine-global config changes into Root Context replacement.
|
|
19419
19516
|
*
|
|
19420
19517
|
* Original request (2026-07-15): "你先负责后端(内核)的开发。"
|
|
@@ -19936,7 +20033,7 @@ async function createWebSocketServer(server, httpServer, config) {
|
|
|
19936
20033
|
() => ptyManager.closeAll(),
|
|
19937
20034
|
() => closeWebSocketServer(ptyWss),
|
|
19938
20035
|
() => closeWebSocketServer(wss),
|
|
19939
|
-
() => server.watcher?.
|
|
20036
|
+
() => server.watcher?.close()
|
|
19940
20037
|
]);
|
|
19941
20038
|
await settleCleanupPhase(failures, [() => server.storeObservationFallback.dispose()]);
|
|
19942
20039
|
await settleCleanupPhase(failures, [() => server.storeMutationService.dispose()]);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@openspecui/server",
|
|
3
|
-
"version": "7.0.
|
|
3
|
+
"version": "7.0.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/index.mjs",
|
|
6
6
|
"exports": {
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
"typecheck:nested-spec-tests": "tsc -p tsconfig.nested-spec-tests.json --noEmit",
|
|
26
26
|
"typecheck:project-initialization-tests": "tsc -p tsconfig.project-initialization-tests.json --noEmit",
|
|
27
27
|
"typecheck:default-store-tests": "tsc -p tsconfig.default-store-tests.json --noEmit",
|
|
28
|
-
"dev": "
|
|
28
|
+
"dev": "tsx watch --conditions=development --include '../core/dist/**' --include '../search/dist/**' src/standalone.ts",
|
|
29
29
|
"test": "vitest run",
|
|
30
30
|
"test:watch": "vitest"
|
|
31
31
|
},
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"@hono/node-server": "^1.14.1",
|
|
34
34
|
"@huggingface/hub": "^2.12.0",
|
|
35
35
|
"@lydell/node-pty": "^1.1.0",
|
|
36
|
-
"@openspecui/core": "7.0.
|
|
37
|
-
"@openspecui/search": "7.0.
|
|
36
|
+
"@openspecui/core": "7.0.2",
|
|
37
|
+
"@openspecui/search": "7.0.2",
|
|
38
38
|
"@opentelemetry/api": "^1.9.1",
|
|
39
39
|
"@opentelemetry/exporter-trace-otlp-http": "^0.221.0",
|
|
40
40
|
"@opentelemetry/sdk-node": "^0.221.0",
|