@openspecui/core 7.0.1 → 9.0.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/{active-root-config-DxRGkvOp.d.mts → active-root-config-C77Duro0.d.mts} +9 -9
- package/dist/active-root-config.d.mts +5 -5
- package/dist/active-root-config.mjs +1 -1
- package/dist/{cli-projection-BeBPIxhK.d.mts → cli-projection-BAU6-rFs.d.mts} +9 -9
- package/dist/cli-projection.d.mts +5 -5
- package/dist/cli-projection.mjs +1 -1
- package/dist/{dashboard-summary-transport-CXGjAcQZ.d.mts → dashboard-summary-transport-C3No2o4i.d.mts} +2985 -2578
- package/dist/{dashboard-summary-transport-ILCfZD_I.mjs → dashboard-summary-transport-Do8pzSES.mjs} +10 -1
- package/dist/dashboard-summary-transport.d.mts +26 -26
- package/dist/dashboard-summary-transport.mjs +2 -2
- package/dist/{document-translation-B3xaP0dJ.mjs → document-translation-Dmg3YJDA.mjs} +1 -1
- package/dist/document-translation.d.mts +1 -1
- package/dist/document-translation.mjs +2 -2
- package/dist/{hosted-app-B_T_tTvO.mjs → hosted-app-CHqdo5vd.mjs} +1 -1
- package/dist/hosted-app.d.mts +26 -26
- package/dist/hosted-app.mjs +6 -6
- package/dist/{hosted-contract-BxUx6ksP.mjs → hosted-contract-Qe5AmkiE.mjs} +4 -4
- package/dist/hosted-contract.d.mts +26 -26
- package/dist/hosted-contract.mjs +5 -5
- package/dist/{index-CkwSp1WZ.d.mts → index-BGT-MVqL.d.mts} +837 -91
- package/dist/index.d.mts +27 -27
- package/dist/index.mjs +902 -392
- package/dist/{local-download-profiles-DYeaRK_E.d.mts → local-download-profiles-BZj6Tw_s.d.mts} +1 -1
- package/dist/local-download-profiles.d.mts +2 -2
- package/dist/local-download-profiles.mjs +1 -1
- package/dist/markdown-facts.d.mts +1 -1
- package/dist/{markdown-reading--Sr6JAl5.d.mts → markdown-reading-CsLbxubT.d.mts} +1 -1
- package/dist/markdown-reading.d.mts +2 -2
- package/dist/{notifications-B43aFxw9.d.mts → notifications-B9cvPamG.d.mts} +4 -4
- package/dist/{notifications-Cy74GVN7.mjs → notifications-D6XlgL9b.mjs} +2 -2
- package/dist/notifications.d.mts +2 -2
- package/dist/notifications.mjs +3 -3
- package/dist/{openspec-annotations-BylPW5rz.d.mts → openspec-annotations-8ppmICAU.d.mts} +2 -2
- package/dist/openspec-annotations.d.mts +3 -3
- package/dist/openspec-compat-B246EQNW.mjs +121 -0
- package/dist/openspec-compat.d.mts +48 -13
- package/dist/openspec-compat.mjs +4 -79
- package/dist/{openspec-projection-NGJSLiSk.d.mts → openspec-projection-vJ03fcdF.d.mts} +3 -3
- package/dist/openspec-projection.d.mts +5 -5
- package/dist/opsx-display-path.d.mts +1 -1
- package/dist/opsx-display-path.mjs +1 -1
- package/dist/{opsx-entity-5ATD3peX.d.mts → opsx-entity-BFPRTIWN.d.mts} +2 -2
- package/dist/opsx-entity.d.mts +7 -7
- package/dist/{opsx-schema-detail-Cu7mIrGm.d.mts → opsx-schema-detail-D1129ezo.d.mts} +2 -2
- package/dist/opsx-schema-detail.d.mts +8 -8
- package/dist/{opsx-types-DJzyK1W7.d.mts → opsx-types-C_4QxcU6.d.mts} +162 -161
- package/dist/opsx-workflows.d.mts +1 -1
- package/dist/opsx-workflows.mjs +1 -1
- package/dist/{planning-cli-projection-BreqsrYA.mjs → planning-cli-projection-DV22v3Xl.mjs} +23 -12
- package/dist/planning-cli-projection.d.mts +26 -26
- package/dist/planning-cli-projection.mjs +4 -3
- package/dist/{schemas-kuds0tNv.d.mts → schemas-Dnw_rfST.d.mts} +130 -130
- package/dist/{sounds-vwRCMSzL.d.mts → sounds-BoLuHRve.d.mts} +9 -9
- package/dist/sounds.d.mts +1 -1
- package/dist/sounds.mjs +1 -1
- package/dist/{spec-catalog-DEk_oHAx.mjs → spec-catalog-Ce3uSLSc.mjs} +45 -328
- package/dist/spec-catalog.d.mts +26 -26
- package/dist/spec-catalog.mjs +3 -2
- package/dist/{store-content-projection-Bpdb7_d9.mjs → store-content-projection-DV31znWA.mjs} +1 -1
- package/dist/store-content-projection.d.mts +1 -1
- package/dist/store-content-projection.mjs +2 -2
- package/dist/{store-mutation-protocol-D9IK_wrr.d.mts → store-mutation-protocol-C4rRiO4b.d.mts} +48 -48
- package/dist/store-mutation-protocol.d.mts +1 -1
- package/dist/store-mutation-protocol.mjs +1 -1
- package/dist/{store-types-DxvwR0sj.d.mts → store-types-CMqxPwaj.d.mts} +1 -1
- package/dist/store-types.d.mts +5 -5
- package/dist/store-types.mjs +1 -1
- package/dist/task-progress.d.mts +6 -6
- package/dist/{terminal-audio-BcjP_os4.d.mts → terminal-audio-CNhCiZul.d.mts} +2 -2
- package/dist/{terminal-audio-DeubAfFC.mjs → terminal-audio-ELHVH24M.mjs} +1 -1
- package/dist/terminal-audio.d.mts +2 -2
- package/dist/terminal-audio.mjs +2 -2
- package/dist/{terminal-control-c6oS-lFb.mjs → terminal-control-D893EEN_.mjs} +21 -1
- package/dist/terminal-control.d.mts +2 -2
- package/dist/terminal-control.mjs +1 -1
- package/dist/{terminal-invocation-BW357tO1.d.mts → terminal-invocation-BnMhxtP1.d.mts} +46 -46
- package/dist/terminal-invocation.d.mts +1 -1
- package/dist/terminal-invocation.mjs +1 -1
- package/dist/terminal-theme.d.mts +1 -1
- package/dist/terminal-theme.mjs +1 -1
- package/dist/translation-language-pair.d.mts +1 -1
- package/dist/translation-language-pair.mjs +1 -1
- package/dist/{translator-YggUX3F7.d.mts → translator-B7GQxmun.d.mts} +86 -86
- package/dist/translator.d.mts +1 -1
- package/dist/translator.mjs +1 -1
- package/dist/workflow-CmQ4pFYC.mjs +344 -0
- package/package.json +3 -1
- /package/dist/{active-root-config-L5QaMb3A.mjs → active-root-config-K_wVeuI3.mjs} +0 -0
- /package/dist/{cli-projection-CKRwTvwf.mjs → cli-projection-Bc2WVwGj.mjs} +0 -0
- /package/dist/{document-translation-BNbM3fEj.d.mts → document-translation-CBqubtWC.d.mts} +0 -0
- /package/dist/{local-download-profiles-h9lUTXr-.mjs → local-download-profiles-BRsR1-kK.mjs} +0 -0
- /package/dist/{markdown-facts-DLclHfpE.d.mts → markdown-facts-CEACwik1.d.mts} +0 -0
- /package/dist/{opsx-display-path-BD34M8QV.d.mts → opsx-display-path-DvvAFlWG.d.mts} +0 -0
- /package/dist/{opsx-display-path-ocbNzMZj.mjs → opsx-display-path-cv0NJHzW.mjs} +0 -0
- /package/dist/{opsx-workflows-DX1r6e5j.d.mts → opsx-workflows-B72EGtj_.d.mts} +0 -0
- /package/dist/{opsx-workflows-byPfLlo8.mjs → opsx-workflows-BA-46T7_.mjs} +0 -0
- /package/dist/{sounds-6prQvKXl.mjs → sounds-cd9lIDxN.mjs} +0 -0
- /package/dist/{store-content-projection-R74MV_sD.d.mts → store-content-projection-BnNYyb0x.d.mts} +0 -0
- /package/dist/{store-mutation-protocol-CJGUWWI6.mjs → store-mutation-protocol-CBrPcppU.mjs} +0 -0
- /package/dist/{store-types-CvpEVNoE.mjs → store-types-C87SlrJ3.mjs} +0 -0
- /package/dist/{terminal-invocation-DIpoFYDo.mjs → terminal-invocation-C_FsxEUs.mjs} +0 -0
- /package/dist/{terminal-theme-Byzxmnjm.mjs → terminal-theme-C6BPfQ2G.mjs} +0 -0
- /package/dist/{terminal-theme-DX08Gci8.d.mts → terminal-theme-C7X8pUqT.d.mts} +0 -0
- /package/dist/{translation-language-pair-BR5uxGm-.d.mts → translation-language-pair-B6A39Cai.d.mts} +0 -0
- /package/dist/{translation-language-pair-DG9mOuFD.mjs → translation-language-pair-CWLlH7Ab.mjs} +0 -0
- /package/dist/{translator-CEGdRmKw.mjs → translator-BkNACZ9R.mjs} +0 -0
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { A as requireCanonicalOpenSpecEntityId, C as CliStoreDoctorSchema, E as CliStoreSchema, M as requireOpenSpecEntityRelativePath, O as CliSchemasSuccessSchema, S as CliStoreDoctorEntrySchema, T as CliStoreMutationSchema, _ as specRoutePath, a as SpecDocumentProjectionSchema, b as CliDoctorSchema, c as createStaticSpecCatalogOwnedProjection, d as getSpecCatalogEntry, f as isReferencedSpecIdentity, g as specIdentityKey, h as specIdentityFromRoute, i as SpecCommandEvidenceSchema, j as requireCanonicalOpenSpecSpecId, k as isCliSchemasFailure, l as createStaticSpecCatalogReferenceProjection, m as specDocumentDisplayPath, n as ReferencedSpecIdentitySchema, o as SpecIdentitySchema, p as mergeSpecCatalog, r as SpecCatalogSchema, s as buildSpecCatalog, t as OwnedSpecIdentitySchema, u as createStaticSpecCatalogReferenceSource, v as OpenSpecCliContractExecutor, w as CliStoreListSchema, x as CliStoreCleanupSchema, y as CliContextSchema } from "./spec-catalog-Ce3uSLSc.mjs";
|
|
2
2
|
import { _ as isTextLikeMime, a as DeltaSpecSchema, c as ScenarioStepSchema, d as TrackedTaskProgressSchema, f as FILE_PREVIEW_KINDS, g as isTextLikeFile, h as isPreviewableFile, i as DeltaSchema, l as SpecSchema, m as inferFilePreviewKind, n as ChangeSchema, o as RequirementSchema, p as inferFileMime, r as DeltaOperationType, s as ScenarioStepKeywordSchema, t as ChangeFileSchema, u as TaskSchema } from "./schemas-CMThmKx1.mjs";
|
|
3
3
|
import { a as normalizeOpsxEntityPath, c as parseOpsxEntityMetadata, i as isOpsxGlobPattern, n as getOpsxEntityMetadataPath, o as opsxGlobToRegex, r as getOpsxEntityRootRelativePath, s as opsxPathMatchesPattern, t as buildOpsxEntityDetail } from "./opsx-entity-BnO3k48r.mjs";
|
|
4
4
|
import { t as parseOpsxSchemaDetail } from "./opsx-schema-detail-zk8ePaKK.mjs";
|
|
@@ -8,33 +8,36 @@ import { a as getOpenSpecAnnotationsForFact, i as getOpenSpecAnnotation, n as an
|
|
|
8
8
|
import { a as getOpenSpecReadingSections, c as projectOpenSpecMarkdown, i as getOpenSpecProjectionAnnotation, n as OPEN_SPEC_SPEC_PROJECTION_ID, o as parseOpenSpecMarkdownToSpec, r as createOpenSpecReadingPlugin, s as projectAnnotatedOpenSpecToSpec, t as OPEN_SPEC_READING_SECTIONS_PROJECTION_ID } from "./openspec-projection-Cno7FlwE.mjs";
|
|
9
9
|
import { a as isMarkdownTaskSourcePath, c as toggleMarkdownTask, i as deriveTrackedTaskPhase, n as createDocumentChecklistSummary, o as parseMarkdownTasks, r as createTrackedTaskProgress, s as projectTaskProjectionsFromMarkdownFiles, t as createApplyInstructionProgress } from "./task-progress-Bvid_Ws8.mjs";
|
|
10
10
|
import { a as CliRootSchema, i as CliReferenceIndexEntrySchema, n as CliDiagnosticSchema, o as CliRootSourceSchema, r as CliDoctorReferenceEntrySchema, t as CliDiagnosticFailureSchema } from "./common-BRL_34xt.mjs";
|
|
11
|
-
import { a as
|
|
12
|
-
import {
|
|
13
|
-
import { a as
|
|
14
|
-
import { a as
|
|
15
|
-
import {
|
|
16
|
-
import { n as
|
|
17
|
-
import {
|
|
18
|
-
import { n as
|
|
19
|
-
import {
|
|
20
|
-
import { i as
|
|
21
|
-
import { n as
|
|
22
|
-
import {
|
|
23
|
-
import { a as
|
|
24
|
-
import {
|
|
25
|
-
import { a as
|
|
26
|
-
import "./
|
|
27
|
-
import {
|
|
28
|
-
import
|
|
29
|
-
import {
|
|
30
|
-
import {
|
|
31
|
-
import { a as
|
|
11
|
+
import { C as CliWorkflowStatusSuccessSchema, S as CliWorkflowStatusSchema, T as parseCliCommandResult, _ as CliSpecListSchema, a as CliArchiveInstructionsSuccessSchema, b as CliValidateReportSchema, c as CliArtifactInstructionsSuccessSchema, g as CliShowSpecSchema, h as CliShowSpecDocumentSchema, i as CliArchiveInstructionsSchema, n as CliApplyInstructionsSchema, o as CliArchiveSchema, r as CliApplyInstructionsSuccessSchema, s as CliArtifactInstructionsSchema, u as CliChangeListSchema, w as CliCommandTransportSchema, x as CliValidateSchema } from "./workflow-CmQ4pFYC.mjs";
|
|
12
|
+
import { a as CliProjectionInvalidationCauseSchema, d as toCliProjectionCommandEvidence, f as toCliProjectionFailure, i as CliProjectionFailureSchema, l as cliProjectionStates, n as CliProjectionCommandError, o as CliProjectionNoticeSchema, p as toCliProjectionNotice, r as CliProjectionCommandEvidenceSchema, s as CliProjectionStateNameSchema, t as CliJsonValueSchema, u as createCliProjectionStateSchema } from "./cli-projection-Bc2WVwGj.mjs";
|
|
13
|
+
import { $ as shouldShowTranslationEngineInstallGate, A as TranslationEngineIdSchema, B as TranslationLocalLlamaSettingsUpdateSchema, C as TranslationDownloadGroupPlanSchema, D as TranslationEngineDependencyStatusSchema, E as TranslationEngineDependencyStateSchema, F as TranslationEngineRuntimeStateSchema, G as createTranslationEngineLifecycleStatus, H as TranslationLocalSettingsUpdateSchema, I as TranslationEngineRuntimeStatusSchema, J as getTranslationEngineManifest, K as getManagedLocalTranslationEngineManifest, L as TranslationLocalCt2SettingsSchema, M as TranslationEngineInstallLogStreamSchema, N as TranslationEngineLifecycleEventSchema, O as TranslationEngineGlobalSettingsSchema, P as TranslationEngineLifecycleStatusSchema, Q as isTranslationEngineRuntimeReady, R as TranslationLocalCt2SettingsUpdateSchema, S as TranslationDownloadFilePlanSchema, T as TranslationEngineAssetStatusSchema, U as TranslationOpenAISettingsSchema, V as TranslationLocalSettingsSchema, W as TranslationOpenAISettingsUpdateSchema, X as isManagedLocalTranslationEngineId, Y as isDirectionalManagedLocalTranslationEngineId, Z as isTranslationEngineDependencyReady, _ as SERVICE_TRANSLATION_ENGINE_IDS, a as LocalModelAssetLogSchema, b as TRANSLATION_ENGINE_MANIFESTS, c as LocalModelDownloadStatusSchema, d as LocalModelProfileLoadStateSchema, et as isBatchTranslationAbort, f as LocalModelProfileManifestFileSchema, g as ManagedLocalCatalogSourceSchema, h as LocalModelProfileStatusSchema, i as DEFAULT_TRANSLATION_ENGINE_ID, j as TranslationEngineInstallLogEventSchema, k as TranslationEngineGlobalSettingsUpdateSchema, l as LocalModelLifecycleFileStateSchema, m as LocalModelProfileManifestSchema, n as BatchTranslateInputSchema, nt as runControlledTranslationTask, o as LocalModelAssetPlanSnapshotSchema, p as LocalModelProfileManifestGroupSchema, q as getTranslationEngineLifecycleMessage, s as LocalModelAssetStateSchema, t as BatchTranslateEventSchema, tt as normalizeBatchTranslationError, u as LocalModelLifecycleGroupStateSchema, v as ServiceTranslationEngineIdSchema, w as TranslationEngineAssetStateSchema, x as TRANSLATOR_CONTRACT_VERSION, y as TRANSLATION_ENGINE_IDS, z as TranslationLocalLlamaSettingsSchema } from "./translator-BkNACZ9R.mjs";
|
|
14
|
+
import { a as ActiveRootOfficialConfigSchema, c as MAX_ACTIVE_ROOT_CONTEXT_BYTES, i as ActiveRootMutationSchema, n as patchActiveRootOfficialFields, o as ActiveRootRevisionSchema, r as validateActiveRootRawYaml, s as ActiveRootStructuredUpdateSchema, t as inspectActiveRootOfficialConfig } from "./active-root-config-K_wVeuI3.mjs";
|
|
15
|
+
import { a as DocumentTranslationDisplayModeSchema, c as TRANSLATION_CACHE_POLICY_VERSION, d as TranslationCacheSettingsSchema, f as TranslationCacheSettingsUpdateSchema, g as TranslationEngineProjectSettingsUpdateSchema, h as TranslationEngineProjectSettingsSchema, i as DocumentTranslationConfigUpdateSchema, l as TranslationCacheEntrySchema, m as TranslationCacheWriteInputSchema, n as DOCUMENT_TRANSLATION_DISPLAY_MODES, o as MAX_TRANSLATION_CACHE_ENTRY_LIMIT, p as TranslationCacheStatsSchema, r as DocumentTranslationConfigSchema, s as MIN_TRANSLATION_CACHE_ENTRY_LIMIT, t as DEFAULT_TRANSLATION_CACHE_ENTRY_LIMIT, u as TranslationCacheReadInputSchema } from "./document-translation-Dmg3YJDA.mjs";
|
|
16
|
+
import { _ as customHashFromSoundId, a as CustomSoundHashSchema, b as soundIdFromCustomHash, c as CustomSoundMetadataSchema, f as LEGACY_SOUND_ID_MAP, g as SoundVolumeSchema, h as SoundIdSchema, i as CUSTOM_SOUND_ADD_VALUE, l as DEFAULT_BELL_SOUND_ID, m as SoundConfigIdSchema, n as BUILTIN_SOUND_OPTIONS, o as CustomSoundIdSchema, p as SILENT_SOUND_ID, r as BuiltinSoundIdSchema, s as CustomSoundMetadataFileSchema, t as BUILTIN_SOUND_IDS, u as DEFAULT_NOTIFICATION_SOUND_ID, v as getBuiltinSoundUrl, y as normalizeLegacySoundId } from "./sounds-cd9lIDxN.mjs";
|
|
17
|
+
import { n as terminalNotificationEventToPublishInput, t as TerminalControlParser } from "./terminal-control-D893EEN_.mjs";
|
|
18
|
+
import { a as NotificationPublishInputSchema, c as NotificationSoundSchema, h as groupNotifications, i as NotificationGroupKeySchema, l as NotificationSourceSchema, m as getNotificationGroupLabel, n as NOTIFICATION_SOUND_VALUES, o as NotificationRecordSchema, p as getNotificationGroupKey, r as NotificationActionSchema, s as NotificationSettingsSchema, t as NOTIFICATION_SOUND_OPTIONS, u as TerminalNotificationParser } from "./notifications-D6XlgL9b.mjs";
|
|
19
|
+
import { n as TERMINAL_BELL_SOUND_VALUES, r as TerminalBellSoundSchema, t as TERMINAL_BELL_SOUND_OPTIONS } from "./terminal-audio-ELHVH24M.mjs";
|
|
20
|
+
import { a as TERMINAL_THEME_VALUES, i as TERMINAL_THEME_MODE_VALUES, n as DEFAULT_TERMINAL_LIGHT_THEME, r as DEFAULT_TERMINAL_THEME_MODE, t as DEFAULT_TERMINAL_DARK_THEME } from "./terminal-theme-C6BPfQ2G.mjs";
|
|
21
|
+
import { i as selectLocalDownloadGroup, n as buildLocalDownloadPlanFromRepositoryFiles, r as buildLocalDownloadPlanFromRuntimeProfileFiles, t as LOCAL_MODEL_PROFILE_DEFINITIONS } from "./local-download-profiles-BRsR1-kK.mjs";
|
|
22
|
+
import { n as inferLocalDirectionalModelLanguagePair, t as checkLocalDirectionalModelLanguagePair } from "./translation-language-pair-CWLlH7Ab.mjs";
|
|
23
|
+
import { C as SchemaResolutionSchema, D as isGlobPattern, E as TemplatesSchema, S as SchemaInfoSchema, T as TemplateContentSchema, _ as OpsxCliEvidenceSchema, a as PlanningCliProjectionDataSchema, b as SchemaArtifactSchema, c as ApplyInstructionsContextFilesSchema, d as ApplyTaskSchema, f as ArchiveInstructionsSchema, g as DependencyInfoSchema, h as ChangeStatusSchema, i as EnvironmentGlobalProjectionStateSchema, l as ApplyInstructionsProjectionSchema, m as ArtifactStatusSchema, n as EnvironmentGlobalFileProjectionStateSchema, o as PlanningCliProjectionSelectorSchema, p as ArtifactInstructionsSchema, r as EnvironmentGlobalProjectionDataSchema, s as PlanningCliProjectionStateSchema, t as EnvironmentGlobalFileProjectionDataSchema, u as ApplyInstructionsSchema, v as OpsxConfigBundleSchema, w as TemplateContentMapSchema, x as SchemaDetailSchema, y as OpsxStatusEvidenceSchema } from "./planning-cli-projection-DV22v3Xl.mjs";
|
|
24
|
+
import { h as parseOpenSpecCliVersion, p as deriveOpenSpecCliCapabilities } from "./openspec-compat-B246EQNW.mjs";
|
|
25
|
+
import { a as OPSX_CORE_PROFILE_WORKFLOWS, c as OPSX_WORKFLOW_TO_SKILL_DIR, i as OPSX_COMMAND_CAPABLE_WORKFLOWS, l as isOpsxCoreWorkflowSelection, n as OPSX_ARTIFACT_INPUT_ACTIONS, o as OPSX_TEXT_INPUT_ACTIONS, r as OPSX_CHANGE_INPUT_ACTIONS, s as OPSX_WORKFLOW_LABELS, t as OPSX_ALL_WORKFLOWS } from "./opsx-workflows-BA-46T7_.mjs";
|
|
26
|
+
import { a as DASHBOARD_METRIC_KEYS, c as DashboardSummaryProjectionSchema, i as DashboardSummaryProjectionStateSchema, l as DashboardTrendsProjectionSchema, n as DashboardSummaryInvalidationCauseSchema, o as DashboardGitSnapshotSchema, r as DashboardSummaryInvalidationSchema, s as DashboardOverviewSchema, t as DashboardSummaryIdentitySchema } from "./dashboard-summary-transport-Do8pzSES.mjs";
|
|
27
|
+
import { a as StoreListResultSchema, n as StoreDoctorResultSchema, o as classifyStoreCliResult, s as toStoreFeatureResult } from "./store-types-C87SlrJ3.mjs";
|
|
28
|
+
import "./store-content-projection-DV31znWA.mjs";
|
|
29
|
+
import { i as StoreMutationStartResponseSchema, n as StoreMutationResultSchema, r as StoreMutationSchema, t as StoreMutationLifecycleEventSchema } from "./store-mutation-protocol-CBrPcppU.mjs";
|
|
30
|
+
import { C as OPENSPECUI_RUNTIME_CAPABILITIES, D as isTerminalMutationStatus, E as hasCapability, T as asEnvUri, t as HOSTED_SHELL_PROTOCOL_VERSION } from "./hosted-contract-Qe5AmkiE.mjs";
|
|
31
|
+
import { a as buildHostedLaunchUrl, c as isSupportedEmbeddedUiUrl, d as resolveHostedAppBaseUrl, i as buildEmbeddedUiLaunchUrl, l as normalizeEmbeddedUiUrl, n as OFFICIAL_APP_BASE_URL, o as isBackendHealthRuntimeMetadata, r as buildBackendHealthPayload, s as isHostedBackendHealthResponse, u as normalizeHostedAppBaseUrl } from "./hosted-app-CHqdo5vd.mjs";
|
|
32
|
+
import { n as toOpsxDisplayPath, t as VIRTUAL_PROJECT_DIRNAME } from "./opsx-display-path-cv0NJHzW.mjs";
|
|
33
|
+
import { a as TerminalInvocationSettingsSchema, c as TerminalSpawnCommandSchema, f as quoteTerminalShellArg, g as resolveTerminalShellDefaults, h as renderTerminalSpawnCommandLine, i as TerminalCommandFieldSchema, n as TERMINAL_COMMAND_FIELD_TYPE_VALUES, o as TerminalShellProfileSchema, p as renderTerminalCommandArgs, r as TERMINAL_SHELL_QUOTE_STYLE_VALUES, s as TerminalShellQuoteStyleSchema, t as BUILTIN_TERMINAL_SPAWN_COMMANDS, u as getTerminalCommandDefaultValues } from "./terminal-invocation-C_FsxEUs.mjs";
|
|
32
34
|
import { mkdir, writeFile } from "fs/promises";
|
|
33
35
|
import { dirname, join } from "path";
|
|
34
36
|
import { isMap, parseDocument } from "yaml";
|
|
35
37
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
36
38
|
import { access, lstat, mkdir as mkdir$1, open, readFile, readdir, realpath, rename, rm, stat, writeFile as writeFile$1 } from "node:fs/promises";
|
|
37
|
-
import { basename, dirname as dirname$1, isAbsolute, join as join$1, matchesGlob, posix, relative, resolve, sep, win32 } from "node:path";
|
|
39
|
+
import { basename, dirname as dirname$1, extname, isAbsolute, join as join$1, matchesGlob, posix, relative, resolve, sep, win32 } from "node:path";
|
|
40
|
+
import { setTimeout as setTimeout$1 } from "node:timers/promises";
|
|
38
41
|
import { existsSync, lstatSync, readFileSync, realpathSync } from "node:fs";
|
|
39
42
|
import { AsyncLocalStorage } from "node:async_hooks";
|
|
40
43
|
import { z } from "zod";
|
|
@@ -42,12 +45,14 @@ import { EventEmitter } from "events";
|
|
|
42
45
|
import { watch } from "fs";
|
|
43
46
|
import { exec, execFile } from "child_process";
|
|
44
47
|
import { promisify } from "util";
|
|
45
|
-
import
|
|
48
|
+
import { pathToFileURL } from "node:url";
|
|
49
|
+
import { execFile as execFile$1, spawn, spawnSync } from "node:child_process";
|
|
50
|
+
import process$1 from "node:process";
|
|
51
|
+
import { promisify as promisify$1 } from "node:util";
|
|
46
52
|
import { homedir, loadavg, platform } from "node:os";
|
|
47
53
|
import { context, trace } from "@opentelemetry/api";
|
|
48
54
|
import { performance as performance$1 } from "node:perf_hooks";
|
|
49
55
|
import { Worker } from "node:worker_threads";
|
|
50
|
-
import { pathToFileURL } from "node:url";
|
|
51
56
|
|
|
52
57
|
//#region src/parser.ts
|
|
53
58
|
const SCENARIO_STEP_PATTERN = new RegExp(`^\\s*[-*+]\\s+(?:\\*\\*)?(${[
|
|
@@ -540,7 +545,7 @@ var ProjectWatcher = class {
|
|
|
540
545
|
matchPath(event, sub) {
|
|
541
546
|
const eventPath = event.path;
|
|
542
547
|
if (sub.watchAncestorsWhileMissing && sub.awaitingPathCreation && isStrictAncestorPath(eventPath, sub.path)) return true;
|
|
543
|
-
if (sub.watchChildren) return eventPath
|
|
548
|
+
if (sub.watchChildren) return eventPath === sub.path || isStrictAncestorPath(sub.path, eventPath);
|
|
544
549
|
else {
|
|
545
550
|
const eventDir = dirname$1(eventPath);
|
|
546
551
|
return eventPath === sub.path || eventDir === sub.path;
|
|
@@ -756,13 +761,14 @@ async function closeAllProjectWatchers() {
|
|
|
756
761
|
//#endregion
|
|
757
762
|
//#region src/reactive-fs/watcher-pool.ts
|
|
758
763
|
/**
|
|
759
|
-
* Orthogonal intents (updated 2026-07
|
|
764
|
+
* Orthogonal intents (updated 2026-08-07 Asia/Shanghai):
|
|
760
765
|
* 1. Own a reference-counted dynamic set of physical watcher roots, including missing logical roots
|
|
761
766
|
* through their nearest existing ancestor.
|
|
762
767
|
* 2. Bind shared path subscriptions to the deepest active containing root.
|
|
763
768
|
* 3. Rebind pending subscriptions when roots appear, disappear, or recover.
|
|
764
769
|
* 4. Expose aggregate and per-root runtime status for server diagnostics.
|
|
765
|
-
* 5. Keep missing-path ancestor settlement explicit in subscription identity and
|
|
770
|
+
* 5. Keep missing-path ancestor settlement explicit in subscription identity and retire every
|
|
771
|
+
* physical subscription plus cached ProjectWatcher during full teardown.
|
|
766
772
|
*
|
|
767
773
|
* Original request (2026-07-15): "响应式内核要观察 data home、Store roots 和 connected project roots。"
|
|
768
774
|
* Remote CI fixed point (2026-07-28): data-home Schema creation may arrive as an ancestor event on Linux.
|
|
@@ -989,6 +995,7 @@ async function closeAllWatchers() {
|
|
|
989
995
|
]);
|
|
990
996
|
closingWatcherRoots.clear();
|
|
991
997
|
closingPhysicalWatchers.clear();
|
|
998
|
+
await closeAllProjectWatchers();
|
|
992
999
|
emitWatcherRuntimeStatus();
|
|
993
1000
|
}
|
|
994
1001
|
function isWatcherPoolInitialized() {
|
|
@@ -1617,19 +1624,37 @@ function getCacheSize() {
|
|
|
1617
1624
|
//#endregion
|
|
1618
1625
|
//#region src/physical-reactive-file-writer.ts
|
|
1619
1626
|
/**
|
|
1620
|
-
* Orthogonal intents (updated 2026-08-
|
|
1627
|
+
* Orthogonal intents (updated 2026-08-05 Asia/Shanghai):
|
|
1621
1628
|
* 1. Own lexical and existing-ancestor physical confinement for root-scoped mutations.
|
|
1622
|
-
* 2. Execute direct or atomic UTF-8 write,
|
|
1629
|
+
* 2. Execute direct or atomic UTF-8 write, including bounded Windows replacement retries.
|
|
1623
1630
|
* 3. Settle overlapping reactive projections before returning any terminal outcome.
|
|
1624
1631
|
* 4. Keep TOCTOU and hard-link alias limitations explicit at the mutation seam.
|
|
1625
1632
|
*
|
|
1626
1633
|
* Original request (2026-07-16): "建立唯一的 physical/reactive entity-write owner。"
|
|
1627
1634
|
* Original request (2026-07-16): "Schema/Template mutations must reject symlink escape and settle reactive projections before success."
|
|
1628
1635
|
* Derived requirement (2026-08-02): "Raw Active Root YAML uses same-directory atomic replacement before reactive settlement."
|
|
1636
|
+
* Original request (2026-08-05): Continue the Windows adaptation and fix equivalent failures together.
|
|
1629
1637
|
*/
|
|
1638
|
+
const WINDOWS_FILE_REPLACEMENT_RETRY_LIMIT = 80;
|
|
1639
|
+
const WINDOWS_FILE_REPLACEMENT_RETRY_DELAY_MS = 25;
|
|
1630
1640
|
function isMissingPath(error) {
|
|
1631
1641
|
return typeof error === "object" && error !== null && "code" in error && error.code === "ENOENT";
|
|
1632
1642
|
}
|
|
1643
|
+
function isRetryableWindowsFileReplacementError(error) {
|
|
1644
|
+
if (typeof error !== "object" || error === null || !("code" in error)) return false;
|
|
1645
|
+
const code = error.code;
|
|
1646
|
+
return code === "EACCES" || code === "EBUSY" || code === "EPERM";
|
|
1647
|
+
}
|
|
1648
|
+
/** Commit one prepared replacement through rename, retrying transient Windows file locks. */
|
|
1649
|
+
async function replaceFileAtomically(temporaryPath, targetPath) {
|
|
1650
|
+
for (let attempt = 0;; attempt += 1) try {
|
|
1651
|
+
await rename(temporaryPath, targetPath);
|
|
1652
|
+
return;
|
|
1653
|
+
} catch (error) {
|
|
1654
|
+
if (process.platform !== "win32" || !isRetryableWindowsFileReplacementError(error) || attempt >= WINDOWS_FILE_REPLACEMENT_RETRY_LIMIT) throw error;
|
|
1655
|
+
await setTimeout$1(WINDOWS_FILE_REPLACEMENT_RETRY_DELAY_MS);
|
|
1656
|
+
}
|
|
1657
|
+
}
|
|
1633
1658
|
function ensureContained(rootPath, candidatePath, boundary) {
|
|
1634
1659
|
const childPath = relative(rootPath, candidatePath);
|
|
1635
1660
|
if (childPath === ".." || childPath.startsWith(`..${sep}`) || isAbsolute(childPath)) throw new Error(`Mutation target escaped the ${boundary} root.`);
|
|
@@ -1734,7 +1759,7 @@ async function writeAtomicPhysicalReactiveFile(input) {
|
|
|
1734
1759
|
await temporaryFile.close();
|
|
1735
1760
|
temporaryFile = null;
|
|
1736
1761
|
await assertMutationTarget(target);
|
|
1737
|
-
await
|
|
1762
|
+
await replaceFileAtomically(temporaryPath, target.targetPath);
|
|
1738
1763
|
} finally {
|
|
1739
1764
|
await temporaryFile?.close().catch(() => void 0);
|
|
1740
1765
|
await rm(temporaryPath, { force: true }).catch(() => void 0);
|
|
@@ -1777,7 +1802,7 @@ async function compareAndWriteAtomicPhysicalReactiveFile(input) {
|
|
|
1777
1802
|
state: "conflict",
|
|
1778
1803
|
content: currentContent
|
|
1779
1804
|
};
|
|
1780
|
-
await
|
|
1805
|
+
await replaceFileAtomically(temporaryPath, target.targetPath);
|
|
1781
1806
|
committed = true;
|
|
1782
1807
|
return { state: "written" };
|
|
1783
1808
|
} finally {
|
|
@@ -1894,9 +1919,9 @@ var Validator = class {
|
|
|
1894
1919
|
//#endregion
|
|
1895
1920
|
//#region src/adapter.ts
|
|
1896
1921
|
/**
|
|
1897
|
-
* Orthogonal intents (updated 2026-08-
|
|
1922
|
+
* Orthogonal intents (updated 2026-08-04 Asia/Shanghai):
|
|
1898
1923
|
* 1. Read and mutate one CLI-selected planning root through reactive filesystem APIs.
|
|
1899
|
-
* 2. Project recursive Specs, Changes, Archives, and schema-neutral entity files.
|
|
1924
|
+
* 2. Project recursive Specs, Changes, Archives, and schema-neutral entity files with canonical protocol paths.
|
|
1900
1925
|
* 3. Keep tracked workflow tasks distinct from document checklist analytics.
|
|
1901
1926
|
* 4. Preserve filesystem provenance and mutation boundaries for server consumers.
|
|
1902
1927
|
* 5. Expose Launch Project local-initialization evidence independently from Planning-root readiness.
|
|
@@ -1904,6 +1929,7 @@ var Validator = class {
|
|
|
1904
1929
|
* Original request (2026-07-15): "Split formal tracked progress, document checklist statistics, and Apply instruction progress into non-interchangeable facts."
|
|
1905
1930
|
* Original request (2026-08-01): adapt OpenSpec 1.7 nested Spec ids such as `platform/auth`.
|
|
1906
1931
|
* Review correction (2026-08-02): a same-named ordinary file is not initialized project structure.
|
|
1932
|
+
* Original request (2026-08-04): "Make pnpm openspecui start and equivalent package scripts work on Windows."
|
|
1907
1933
|
*/
|
|
1908
1934
|
/**
|
|
1909
1935
|
* OpenSpec filesystem adapter
|
|
@@ -1996,7 +2022,8 @@ var OpenSpecAdapter = class {
|
|
|
1996
2022
|
trackedTaskProgress: taskProjection.trackedTaskProgress,
|
|
1997
2023
|
documentChecklistSummary: taskProjection.documentChecklistSummary,
|
|
1998
2024
|
createdAt: timeInfo?.createdAt ?? 0,
|
|
1999
|
-
updatedAt: timeInfo?.updatedAt ?? 0
|
|
2025
|
+
updatedAt: timeInfo?.updatedAt ?? 0,
|
|
2026
|
+
cliTaskSummary: null
|
|
2000
2027
|
};
|
|
2001
2028
|
}
|
|
2002
2029
|
/**
|
|
@@ -2117,7 +2144,7 @@ var OpenSpecAdapter = class {
|
|
|
2117
2144
|
const fullPath = join(dir, name);
|
|
2118
2145
|
const statInfo = await reactiveStat(fullPath);
|
|
2119
2146
|
if (!statInfo) continue;
|
|
2120
|
-
const relativePath = fullPath.slice(root.length + 1);
|
|
2147
|
+
const relativePath = normalizeOpsxEntityPath(fullPath.slice(root.length + 1));
|
|
2121
2148
|
if (statInfo.isDirectory) {
|
|
2122
2149
|
files.push({
|
|
2123
2150
|
path: relativePath,
|
|
@@ -2503,6 +2530,17 @@ function updateProjectBindingContent(content, update) {
|
|
|
2503
2530
|
//#endregion
|
|
2504
2531
|
//#region src/watcher.ts
|
|
2505
2532
|
/**
|
|
2533
|
+
* Orthogonal intents (updated 2026-08-09 Asia/Shanghai):
|
|
2534
|
+
* 1. Project legacy OpenSpec directory changes for compatibility consumers.
|
|
2535
|
+
* 2. Settle every native watcher handle before runtime teardown completes.
|
|
2536
|
+
* 3. Interpret native recursive-watch paths without assuming one directory separator.
|
|
2537
|
+
*
|
|
2538
|
+
* Original request (2026-08-04): "Make pnpm openspecui start and equivalent package scripts work on Windows."
|
|
2539
|
+
*/
|
|
2540
|
+
function watchedPathSegments(filename) {
|
|
2541
|
+
return filename.split(/[\\/]+/).filter(Boolean);
|
|
2542
|
+
}
|
|
2543
|
+
/**
|
|
2506
2544
|
* OpenSpec file watcher
|
|
2507
2545
|
* Watches the openspec/ directory for changes and emits events
|
|
2508
2546
|
*/
|
|
@@ -2533,33 +2571,36 @@ var OpenSpecWatcher = class extends EventEmitter {
|
|
|
2533
2571
|
start() {
|
|
2534
2572
|
this.stop();
|
|
2535
2573
|
this.watchDir(this.specsDir, (filename, eventType) => {
|
|
2536
|
-
const
|
|
2537
|
-
|
|
2574
|
+
const segments = watchedPathSegments(filename);
|
|
2575
|
+
const id = segments.length > 1 ? segments[0] : void 0;
|
|
2576
|
+
if (id) this.emitDebounced(`spec:${id}`, {
|
|
2538
2577
|
type: "spec",
|
|
2539
2578
|
action: eventType === "rename" ? "create" : "update",
|
|
2540
|
-
id
|
|
2541
|
-
path: join(this.specsDir,
|
|
2579
|
+
id,
|
|
2580
|
+
path: join(this.specsDir, ...segments),
|
|
2542
2581
|
timestamp: Date.now()
|
|
2543
2582
|
});
|
|
2544
2583
|
});
|
|
2545
2584
|
this.watchDir(this.changesDir, (filename, eventType) => {
|
|
2546
|
-
|
|
2547
|
-
|
|
2548
|
-
|
|
2585
|
+
const segments = watchedPathSegments(filename);
|
|
2586
|
+
if (segments[0] === "archive") return;
|
|
2587
|
+
const id = segments.length > 1 ? segments[0] : void 0;
|
|
2588
|
+
if (id) this.emitDebounced(`change:${id}`, {
|
|
2549
2589
|
type: "change",
|
|
2550
2590
|
action: eventType === "rename" ? "create" : "update",
|
|
2551
|
-
id
|
|
2552
|
-
path: join(this.changesDir,
|
|
2591
|
+
id,
|
|
2592
|
+
path: join(this.changesDir, ...segments),
|
|
2553
2593
|
timestamp: Date.now()
|
|
2554
2594
|
});
|
|
2555
2595
|
});
|
|
2556
2596
|
this.watchDir(this.archiveDir, (filename, eventType) => {
|
|
2557
|
-
const
|
|
2558
|
-
|
|
2597
|
+
const segments = watchedPathSegments(filename);
|
|
2598
|
+
const id = segments.length > 1 ? segments[0] : void 0;
|
|
2599
|
+
if (id) this.emitDebounced(`archive:${id}`, {
|
|
2559
2600
|
type: "archive",
|
|
2560
2601
|
action: eventType === "rename" ? "create" : "update",
|
|
2561
|
-
id
|
|
2562
|
-
path: join(this.archiveDir,
|
|
2602
|
+
id,
|
|
2603
|
+
path: join(this.archiveDir, ...segments),
|
|
2563
2604
|
timestamp: Date.now()
|
|
2564
2605
|
});
|
|
2565
2606
|
});
|
|
@@ -2577,11 +2618,22 @@ var OpenSpecWatcher = class extends EventEmitter {
|
|
|
2577
2618
|
* Stop watching for file changes
|
|
2578
2619
|
*/
|
|
2579
2620
|
stop() {
|
|
2580
|
-
for (const watcher of this.
|
|
2621
|
+
for (const watcher of this.takeWatchers()) watcher.close();
|
|
2622
|
+
}
|
|
2623
|
+
/** Close every watcher and wait until native filesystem handles are released. */
|
|
2624
|
+
async close() {
|
|
2625
|
+
await Promise.all(this.takeWatchers().map((watcher) => new Promise((resolve$1) => {
|
|
2626
|
+
watcher.once("close", resolve$1);
|
|
2627
|
+
watcher.close();
|
|
2628
|
+
})));
|
|
2629
|
+
}
|
|
2630
|
+
takeWatchers() {
|
|
2631
|
+
const watchers = this.watchers;
|
|
2581
2632
|
this.watchers = [];
|
|
2582
2633
|
for (const timer of this.debounceTimers.values()) clearTimeout(timer);
|
|
2583
2634
|
this.debounceTimers.clear();
|
|
2584
2635
|
this.emit("stopped");
|
|
2636
|
+
return watchers;
|
|
2585
2637
|
}
|
|
2586
2638
|
/**
|
|
2587
2639
|
* Watch a directory recursively
|
|
@@ -2682,6 +2734,218 @@ function sanitizePersistedSettings(value, rules) {
|
|
|
2682
2734
|
return sanitized;
|
|
2683
2735
|
}
|
|
2684
2736
|
|
|
2737
|
+
//#endregion
|
|
2738
|
+
//#region src/child-process-tree.ts
|
|
2739
|
+
const execFileAsync$1 = promisify$1(execFile$1);
|
|
2740
|
+
const WINDOWS_PROCESS_TABLE_MAX_BUFFER = 16 * 1024 * 1024;
|
|
2741
|
+
function hasChildExited(child) {
|
|
2742
|
+
return child.exitCode !== null || child.signalCode !== null;
|
|
2743
|
+
}
|
|
2744
|
+
function normalizeWindowsExecutablePath(path) {
|
|
2745
|
+
return win32.normalize(path).toLowerCase();
|
|
2746
|
+
}
|
|
2747
|
+
function isWindowsProcessRecord(value) {
|
|
2748
|
+
if (typeof value !== "object" || value === null) return false;
|
|
2749
|
+
const row = value;
|
|
2750
|
+
return typeof row.ProcessId === "number" && typeof row.ParentProcessId === "number" && (typeof row.ExecutablePath === "string" || row.ExecutablePath === null);
|
|
2751
|
+
}
|
|
2752
|
+
/** Read the current Windows process table used for exact ancestry and root ownership checks. */
|
|
2753
|
+
async function readWindowsProcessTable() {
|
|
2754
|
+
const { stdout } = await execFileAsync$1("powershell.exe", [
|
|
2755
|
+
"-NoLogo",
|
|
2756
|
+
"-NoProfile",
|
|
2757
|
+
"-NonInteractive",
|
|
2758
|
+
"-Command",
|
|
2759
|
+
"[Console]::OutputEncoding = [Text.UTF8Encoding]::new($false); Get-CimInstance Win32_Process | Select-Object ProcessId,ParentProcessId,ExecutablePath | ConvertTo-Json -Compress"
|
|
2760
|
+
], {
|
|
2761
|
+
encoding: "utf8",
|
|
2762
|
+
maxBuffer: WINDOWS_PROCESS_TABLE_MAX_BUFFER,
|
|
2763
|
+
windowsHide: true
|
|
2764
|
+
});
|
|
2765
|
+
const json = stdout.trim();
|
|
2766
|
+
if (json.length === 0) return [];
|
|
2767
|
+
const parsed = JSON.parse(json);
|
|
2768
|
+
return (Array.isArray(parsed) ? parsed : [parsed]).filter(isWindowsProcessRecord);
|
|
2769
|
+
}
|
|
2770
|
+
/** Terminate a Windows tree only when the root PID still owns the expected executable. */
|
|
2771
|
+
async function terminateWindowsProcessTreeByIdentity(rootPid, expectedExecutablePath) {
|
|
2772
|
+
const root = (await readWindowsProcessTable()).find((row) => row.ProcessId === rootPid);
|
|
2773
|
+
if (!root) return;
|
|
2774
|
+
const expectedExecutable = normalizeWindowsExecutablePath(expectedExecutablePath);
|
|
2775
|
+
const actualExecutable = root.ExecutablePath ? normalizeWindowsExecutablePath(root.ExecutablePath) : null;
|
|
2776
|
+
if (actualExecutable !== expectedExecutable) throw new Error(`Refusing to terminate PID ${rootPid}: expected ${expectedExecutable}, observed ${actualExecutable ?? "no executable path"}.`);
|
|
2777
|
+
try {
|
|
2778
|
+
await execFileAsync$1("taskkill.exe", [
|
|
2779
|
+
"/PID",
|
|
2780
|
+
String(rootPid),
|
|
2781
|
+
"/T",
|
|
2782
|
+
"/F"
|
|
2783
|
+
], { windowsHide: true });
|
|
2784
|
+
} catch (error) {
|
|
2785
|
+
if (!(await readWindowsProcessTable()).some((row) => row.ProcessId === rootPid)) return;
|
|
2786
|
+
throw error;
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
async function terminateWindowsProcessTree(child) {
|
|
2790
|
+
const rootPid = child.pid;
|
|
2791
|
+
if (rootPid === void 0 || hasChildExited(child)) return;
|
|
2792
|
+
await terminateWindowsProcessTreeByIdentity(rootPid, child.spawnfile);
|
|
2793
|
+
}
|
|
2794
|
+
/** Request termination of one spawned child and every Windows descendant it owns. */
|
|
2795
|
+
async function terminateChildProcessTree(child, signal = "SIGTERM") {
|
|
2796
|
+
if (child.pid === void 0) {
|
|
2797
|
+
child.kill(signal);
|
|
2798
|
+
return;
|
|
2799
|
+
}
|
|
2800
|
+
if (process$1.platform === "win32") {
|
|
2801
|
+
await terminateWindowsProcessTree(child);
|
|
2802
|
+
return;
|
|
2803
|
+
}
|
|
2804
|
+
if (hasChildExited(child)) return;
|
|
2805
|
+
child.kill(signal);
|
|
2806
|
+
}
|
|
2807
|
+
|
|
2808
|
+
//#endregion
|
|
2809
|
+
//#region src/command-invocation.ts
|
|
2810
|
+
/**
|
|
2811
|
+
* Orthogonal intents (created 2026-08-09 Asia/Shanghai):
|
|
2812
|
+
* 1. Resolve caller-environment Windows commands to native argv-preserving executable boundaries.
|
|
2813
|
+
* 2. Project standard npm-style shims and explicit Node shebang launchers onto their real Node executable.
|
|
2814
|
+
* 3. Prefer native executables, route shell-sensitive pnpm through Corepack, and reject opaque command shims.
|
|
2815
|
+
*
|
|
2816
|
+
* Original request (2026-08-04): "Make pnpm openspecui start and equivalent package scripts work on Windows."
|
|
2817
|
+
*/
|
|
2818
|
+
const WINDOWS_NATIVE_EXTENSIONS = new Set([".com", ".exe"]);
|
|
2819
|
+
function isBareCommand(command$1) {
|
|
2820
|
+
return !/[\\/]/.test(command$1);
|
|
2821
|
+
}
|
|
2822
|
+
function commandName(command$1) {
|
|
2823
|
+
return basename(command$1, extname(command$1)).toLowerCase();
|
|
2824
|
+
}
|
|
2825
|
+
function requiresShellIndependentInvocation(args) {
|
|
2826
|
+
return args.some((argument) => /[%^&|<>"]/.test(argument) || argument.endsWith("\\"));
|
|
2827
|
+
}
|
|
2828
|
+
function systemExecutable(name, env) {
|
|
2829
|
+
return resolve(env.SystemRoot ?? env.SYSTEMROOT ?? process$1.env.SystemRoot ?? "C:\\Windows", "System32", name);
|
|
2830
|
+
}
|
|
2831
|
+
function findWindowsCommandCandidates(command$1, options) {
|
|
2832
|
+
const env = options.env ?? process$1.env;
|
|
2833
|
+
const result = spawnSync(systemExecutable("where.exe", env), [command$1], {
|
|
2834
|
+
cwd: options.cwd,
|
|
2835
|
+
encoding: "utf8",
|
|
2836
|
+
env,
|
|
2837
|
+
windowsHide: true
|
|
2838
|
+
});
|
|
2839
|
+
if (result.error) throw result.error;
|
|
2840
|
+
if (result.status !== 0) throw new Error(result.stderr.trim() || `Unable to resolve ${command$1} from PATH.`);
|
|
2841
|
+
return result.stdout.split(/\r?\n/).map((candidate) => candidate.trim()).filter(Boolean);
|
|
2842
|
+
}
|
|
2843
|
+
function tryFindWindowsCommandCandidates(command$1, options) {
|
|
2844
|
+
try {
|
|
2845
|
+
return findWindowsCommandCandidates(command$1, options);
|
|
2846
|
+
} catch {
|
|
2847
|
+
return [];
|
|
2848
|
+
}
|
|
2849
|
+
}
|
|
2850
|
+
function explicitCommandCandidates(command$1, cwd) {
|
|
2851
|
+
const absolute = isAbsolute(command$1) ? command$1 : resolve(cwd, command$1);
|
|
2852
|
+
if (extname(absolute)) return [absolute];
|
|
2853
|
+
return [
|
|
2854
|
+
`${absolute}.exe`,
|
|
2855
|
+
`${absolute}.cmd`,
|
|
2856
|
+
absolute
|
|
2857
|
+
].filter(existsSync);
|
|
2858
|
+
}
|
|
2859
|
+
function commandCandidates(command$1, options) {
|
|
2860
|
+
if (isBareCommand(command$1)) return findWindowsCommandCandidates(command$1, options);
|
|
2861
|
+
return explicitCommandCandidates(command$1, options.cwd ?? process$1.cwd());
|
|
2862
|
+
}
|
|
2863
|
+
function findNativeExecutable(candidates) {
|
|
2864
|
+
return candidates.find((candidate) => WINDOWS_NATIVE_EXTENSIONS.has(extname(candidate).toLowerCase())) ?? null;
|
|
2865
|
+
}
|
|
2866
|
+
function findNodeExecutable(commandShim, options) {
|
|
2867
|
+
const siblingNode = resolve(dirname$1(commandShim), "node.exe");
|
|
2868
|
+
if (existsSync(siblingNode)) return siblingNode;
|
|
2869
|
+
const fromPath = findNativeExecutable(findWindowsCommandCandidates("node", options));
|
|
2870
|
+
if (fromPath) return fromPath;
|
|
2871
|
+
if (process$1.release.name === "node" && extname(process$1.execPath).toLowerCase() === ".exe") return process$1.execPath;
|
|
2872
|
+
throw new Error(`Unable to resolve the Node executable required by ${commandShim}.`);
|
|
2873
|
+
}
|
|
2874
|
+
function resolveNodeCommandShim(commandShim, args, options) {
|
|
2875
|
+
const source = readFileSync(commandShim, "utf8");
|
|
2876
|
+
if (!/(?:node(?:\.exe)?|node_exe|npm_node_execpath|_prog)/i.test(source)) return null;
|
|
2877
|
+
const entries = [];
|
|
2878
|
+
for (const match of source.matchAll(/%~dp0([^"\r\n]*?\.(?:c|m)?js)/gi)) {
|
|
2879
|
+
const relativeEntry = match[1]?.trim().replace(/^[\\/]+/, "");
|
|
2880
|
+
if (!relativeEntry) continue;
|
|
2881
|
+
const entry$1 = resolve(dirname$1(commandShim), relativeEntry);
|
|
2882
|
+
if (existsSync(entry$1)) entries.push(entry$1);
|
|
2883
|
+
}
|
|
2884
|
+
const entry = entries.at(-1);
|
|
2885
|
+
if (!entry) return null;
|
|
2886
|
+
return {
|
|
2887
|
+
command: findNodeExecutable(commandShim, options),
|
|
2888
|
+
args: [entry, ...args]
|
|
2889
|
+
};
|
|
2890
|
+
}
|
|
2891
|
+
function resolveCommandShim(candidates, args, options) {
|
|
2892
|
+
for (const candidate of candidates) {
|
|
2893
|
+
if (extname(candidate).toLowerCase() !== ".cmd") continue;
|
|
2894
|
+
const invocation = resolveNodeCommandShim(candidate, args, options);
|
|
2895
|
+
if (invocation) return invocation;
|
|
2896
|
+
}
|
|
2897
|
+
return null;
|
|
2898
|
+
}
|
|
2899
|
+
function resolveNodeShebangInvocation(candidates, args, options) {
|
|
2900
|
+
for (const candidate of candidates) {
|
|
2901
|
+
if (!existsSync(candidate) || extname(candidate).toLowerCase() === ".cmd") continue;
|
|
2902
|
+
const firstLine = readFileSync(candidate, "utf8").split(/\r?\n/, 1)[0]?.trim() ?? "";
|
|
2903
|
+
if (!/^#!.*(?:\/|\s)node(?:\.exe)?(?:\s|$)/i.test(firstLine)) continue;
|
|
2904
|
+
return {
|
|
2905
|
+
command: findNodeExecutable(candidate, options),
|
|
2906
|
+
args: [candidate, ...args]
|
|
2907
|
+
};
|
|
2908
|
+
}
|
|
2909
|
+
return null;
|
|
2910
|
+
}
|
|
2911
|
+
/** Resolve one Windows command without projecting argv through cmd.exe. */
|
|
2912
|
+
function resolveWindowsCommandInvocation(command$1, args, options = {}) {
|
|
2913
|
+
const candidates = commandCandidates(command$1, options);
|
|
2914
|
+
const name = commandName(command$1);
|
|
2915
|
+
const shellSensitive = requiresShellIndependentInvocation(args);
|
|
2916
|
+
if (name === "pnpm" && shellSensitive) {
|
|
2917
|
+
const corepack = findNativeExecutable(tryFindWindowsCommandCandidates("corepack", options));
|
|
2918
|
+
if (corepack) return {
|
|
2919
|
+
command: corepack,
|
|
2920
|
+
args: ["pnpm", ...args]
|
|
2921
|
+
};
|
|
2922
|
+
}
|
|
2923
|
+
if (name === "npm" && shellSensitive) {
|
|
2924
|
+
const shimInvocation$1 = resolveCommandShim(candidates, args, options);
|
|
2925
|
+
if (shimInvocation$1) return shimInvocation$1;
|
|
2926
|
+
}
|
|
2927
|
+
const executable = findNativeExecutable(candidates);
|
|
2928
|
+
if (executable) return {
|
|
2929
|
+
command: executable,
|
|
2930
|
+
args: [...args]
|
|
2931
|
+
};
|
|
2932
|
+
const shimInvocation = resolveCommandShim(candidates, args, options);
|
|
2933
|
+
if (shimInvocation) return shimInvocation;
|
|
2934
|
+
const shebangInvocation = resolveNodeShebangInvocation(candidates, args, options);
|
|
2935
|
+
if (shebangInvocation) return shebangInvocation;
|
|
2936
|
+
const commandShim = candidates.find((candidate) => extname(candidate).toLowerCase() === ".cmd");
|
|
2937
|
+
if (commandShim) throw new Error(`${commandShim} is an opaque Windows command shim; refusing to reinterpret argv through cmd.exe.`);
|
|
2938
|
+
throw new Error(`${command$1} did not resolve to a native Windows executable or Node command shim.`);
|
|
2939
|
+
}
|
|
2940
|
+
/** Resolve one command using the caller's cwd and environment while preserving POSIX behavior. */
|
|
2941
|
+
function resolveCommandInvocation(command$1, args, options = {}) {
|
|
2942
|
+
if (process$1.platform !== "win32") return {
|
|
2943
|
+
command: command$1,
|
|
2944
|
+
args: [...args]
|
|
2945
|
+
};
|
|
2946
|
+
return resolveWindowsCommandInvocation(command$1, args, options);
|
|
2947
|
+
}
|
|
2948
|
+
|
|
2685
2949
|
//#endregion
|
|
2686
2950
|
//#region src/spawn-safe.ts
|
|
2687
2951
|
function getSpawnErrorCode(err) {
|
|
@@ -2697,11 +2961,20 @@ function formatSpawnError(err) {
|
|
|
2697
2961
|
message: `${message}${code ? ` (${code})` : ""}`
|
|
2698
2962
|
};
|
|
2699
2963
|
}
|
|
2964
|
+
/** Spawn without a shell after resolving one caller-environment native argv boundary. */
|
|
2700
2965
|
function spawnSafe(command$1, args, options) {
|
|
2701
2966
|
try {
|
|
2967
|
+
const invocation = resolveCommandInvocation(command$1, args, {
|
|
2968
|
+
cwd: typeof options.cwd === "string" ? options.cwd : void 0,
|
|
2969
|
+
env: options.env
|
|
2970
|
+
});
|
|
2702
2971
|
return {
|
|
2703
2972
|
ok: true,
|
|
2704
|
-
child:
|
|
2973
|
+
child: spawn(invocation.command, invocation.args, {
|
|
2974
|
+
...options,
|
|
2975
|
+
shell: false,
|
|
2976
|
+
windowsHide: options.windowsHide ?? true
|
|
2977
|
+
})
|
|
2705
2978
|
};
|
|
2706
2979
|
} catch (err) {
|
|
2707
2980
|
return {
|
|
@@ -2710,12 +2983,7 @@ function spawnSafe(command$1, args, options) {
|
|
|
2710
2983
|
};
|
|
2711
2984
|
}
|
|
2712
2985
|
}
|
|
2713
|
-
|
|
2714
|
-
try {
|
|
2715
|
-
child.kill(signal);
|
|
2716
|
-
} catch {}
|
|
2717
|
-
}
|
|
2718
|
-
const EAGER_JSON_EXIT_GRACE_MS = 25;
|
|
2986
|
+
const EAGER_JSON_EXIT_GRACE_MS = 100;
|
|
2719
2987
|
const BUFFERED_FORCE_KILL_DELAY_MS = 1e3;
|
|
2720
2988
|
function runBufferedCommand(options) {
|
|
2721
2989
|
return new Promise((resolve$1) => {
|
|
@@ -2769,11 +3037,17 @@ function runBufferedCommand(options) {
|
|
|
2769
3037
|
let timedOut = false;
|
|
2770
3038
|
let settled = false;
|
|
2771
3039
|
let eagerJsonTimer = null;
|
|
3040
|
+
let eagerJsonImmediate = null;
|
|
2772
3041
|
let forceKillTimer = null;
|
|
2773
|
-
const
|
|
2774
|
-
if (
|
|
2775
|
-
|
|
2776
|
-
|
|
3042
|
+
const clearEagerJsonResolution = () => {
|
|
3043
|
+
if (eagerJsonTimer) {
|
|
3044
|
+
clearTimeout(eagerJsonTimer);
|
|
3045
|
+
eagerJsonTimer = null;
|
|
3046
|
+
}
|
|
3047
|
+
if (eagerJsonImmediate) {
|
|
3048
|
+
clearImmediate(eagerJsonImmediate);
|
|
3049
|
+
eagerJsonImmediate = null;
|
|
3050
|
+
}
|
|
2777
3051
|
};
|
|
2778
3052
|
const clearForceKillTimer = () => {
|
|
2779
3053
|
if (!forceKillTimer) return;
|
|
@@ -2785,11 +3059,11 @@ function runBufferedCommand(options) {
|
|
|
2785
3059
|
phases.terminationRequestedAt = performance.now();
|
|
2786
3060
|
observe("termination-requested", { reason });
|
|
2787
3061
|
}
|
|
2788
|
-
|
|
3062
|
+
terminateChildProcessTree(child).catch(() => void 0);
|
|
2789
3063
|
if (forceKillTimer) return;
|
|
2790
3064
|
forceKillTimer = setTimeout(() => {
|
|
2791
3065
|
forceKillTimer = null;
|
|
2792
|
-
if (!phases.exitAt && !phases.closeAt)
|
|
3066
|
+
if (!phases.exitAt && !phases.closeAt) terminateChildProcessTree(child, "SIGKILL").catch(() => void 0);
|
|
2793
3067
|
}, BUFFERED_FORCE_KILL_DELAY_MS);
|
|
2794
3068
|
};
|
|
2795
3069
|
let clearTimer = () => {};
|
|
@@ -2811,7 +3085,7 @@ function runBufferedCommand(options) {
|
|
|
2811
3085
|
if (settled) return;
|
|
2812
3086
|
settled = true;
|
|
2813
3087
|
clearTimer();
|
|
2814
|
-
|
|
3088
|
+
clearEagerJsonResolution();
|
|
2815
3089
|
if (reason !== "eager-json") clearForceKillTimer();
|
|
2816
3090
|
phases.resultResolvedAt = performance.now();
|
|
2817
3091
|
phases.resultReason = reason;
|
|
@@ -2835,14 +3109,18 @@ function runBufferedCommand(options) {
|
|
|
2835
3109
|
observe("json-complete-observed");
|
|
2836
3110
|
eagerJsonTimer = setTimeout(() => {
|
|
2837
3111
|
eagerJsonTimer = null;
|
|
2838
|
-
if (settled || phases.exitAt) return;
|
|
2839
|
-
|
|
2840
|
-
|
|
2841
|
-
|
|
2842
|
-
|
|
2843
|
-
|
|
2844
|
-
|
|
2845
|
-
|
|
3112
|
+
if (settled || phases.exitAt || child.exitCode !== null || stderr.length > 0) return;
|
|
3113
|
+
eagerJsonImmediate = setImmediate(() => {
|
|
3114
|
+
eagerJsonImmediate = null;
|
|
3115
|
+
if (settled || phases.exitAt || child.exitCode !== null || stderr.length > 0) return;
|
|
3116
|
+
phases.eagerResolved = true;
|
|
3117
|
+
requestTermination("eager-json");
|
|
3118
|
+
finish("eager-json", {
|
|
3119
|
+
stdout,
|
|
3120
|
+
stderr,
|
|
3121
|
+
exitCode: 0,
|
|
3122
|
+
timedOut
|
|
3123
|
+
});
|
|
2846
3124
|
});
|
|
2847
3125
|
}, EAGER_JSON_EXIT_GRACE_MS);
|
|
2848
3126
|
} catch {}
|
|
@@ -2855,7 +3133,7 @@ function runBufferedCommand(options) {
|
|
|
2855
3133
|
stderr += data.toString();
|
|
2856
3134
|
});
|
|
2857
3135
|
child.on("exit", (exitCode, signal) => {
|
|
2858
|
-
|
|
3136
|
+
clearEagerJsonResolution();
|
|
2859
3137
|
clearForceKillTimer();
|
|
2860
3138
|
if (!phases.exitAt) {
|
|
2861
3139
|
phases.exitAt = performance.now();
|
|
@@ -2902,7 +3180,10 @@ function runBufferedCommand(options) {
|
|
|
2902
3180
|
* 4. Preserve reactive config reads and serialized config writes.
|
|
2903
3181
|
* 5. Resolve Windows `where` candidates by PATHEXT so the executable shim is preferred over the
|
|
2904
3182
|
* extension-less script (issue #209 hotfix).
|
|
3183
|
+
* 6. Hide runner-probe subprocess console windows (`windowsHide`) so a console-less Windows daemon
|
|
3184
|
+
* never flashes a cmd window while resolving or sniffing the CLI runner.
|
|
2905
3185
|
*
|
|
3186
|
+
* Original request (2026-08-14): "在Windows平台上,执行命令总是会弹出cmd窗口,这个可否统一隐藏,你先调查一下原因"
|
|
2906
3187
|
* Original request (2026-07-14): "openspec 1.6.0 已经放出,我们需要开始进行适配。"
|
|
2907
3188
|
* Independent review correction (2026-07-20): Global CLI installation must retire cached and
|
|
2908
3189
|
* in-flight runner authority.
|
|
@@ -3113,7 +3394,8 @@ async function resolveShellExecutablePath(command$1, cwd, env) {
|
|
|
3113
3394
|
cwd,
|
|
3114
3395
|
env,
|
|
3115
3396
|
encoding: "utf8",
|
|
3116
|
-
timeout: 5e3
|
|
3397
|
+
timeout: 5e3,
|
|
3398
|
+
windowsHide: true
|
|
3117
3399
|
});
|
|
3118
3400
|
return pickWindowsExecutablePath(stdout$1.split(/\r?\n/), env.PATHEXT);
|
|
3119
3401
|
}
|
|
@@ -3284,7 +3566,8 @@ async function sniffGlobalCli() {
|
|
|
3284
3566
|
const [localResult, latestVersion] = await Promise.all([execFileAsync(resolvedCommand, ["--version"], {
|
|
3285
3567
|
env,
|
|
3286
3568
|
timeout: 1e4,
|
|
3287
|
-
encoding: "utf8"
|
|
3569
|
+
encoding: "utf8",
|
|
3570
|
+
windowsHide: true
|
|
3288
3571
|
}).catch((err) => ({ error: err })), fetchLatestVersion()]);
|
|
3289
3572
|
if ("error" in localResult) {
|
|
3290
3573
|
const error = localResult.error instanceof Error ? localResult.error.message : String(localResult.error);
|
|
@@ -4461,14 +4744,17 @@ const ownersByChild = /* @__PURE__ */ new WeakMap();
|
|
|
4461
4744
|
//#endregion
|
|
4462
4745
|
//#region src/openspec-cli-worker.ts
|
|
4463
4746
|
/**
|
|
4464
|
-
* Orthogonal intents (updated 2026-
|
|
4747
|
+
* Orthogonal intents (updated 2026-08-06 Asia/Shanghai):
|
|
4465
4748
|
* 1. Resolve an installed OpenSpec package's importable CLI module from its configured runner and
|
|
4466
4749
|
* distinguish objective module absence from Worker startup/execution failure.
|
|
4467
4750
|
* 2. Execute one buffered OpenSpec command inside an isolated Node Worker with project cwd semantics.
|
|
4468
4751
|
* 3. Project Worker stdout, stderr, cancellation, and settlement through the buffered spawn contract.
|
|
4752
|
+
* 4. Treat observed Worker stderr as exit-owned evidence and settle it through the real Worker exit
|
|
4753
|
+
* instead of eager JSON retirement.
|
|
4469
4754
|
*
|
|
4470
4755
|
* Original request (2026-07-31): "直接寻址到本地 openspec 背后的 js,直接用 worker_thread 来运行它。"
|
|
4471
4756
|
* Original request (2026-07-31): "通过 OPENSPEC_SPAWN_MODE=process|worker 来进行区分两种模式。"
|
|
4757
|
+
* Original request (2026-08-06): "continue"
|
|
4472
4758
|
*/
|
|
4473
4759
|
const OPENSPEC_SPAWN_MODE_ENV = "OPENSPEC_SPAWN_MODE";
|
|
4474
4760
|
/** Objective signal that no importable OpenSpec CLI JavaScript module exists behind the runner. */
|
|
@@ -4597,6 +4883,18 @@ function runOpenSpecCliWorker(options) {
|
|
|
4597
4883
|
let completedExitCode = null;
|
|
4598
4884
|
let workerError;
|
|
4599
4885
|
let aborted = false;
|
|
4886
|
+
let eagerJsonTimer = null;
|
|
4887
|
+
let eagerJsonImmediate = null;
|
|
4888
|
+
const clearEagerJsonResolution = () => {
|
|
4889
|
+
if (eagerJsonTimer) {
|
|
4890
|
+
clearTimeout(eagerJsonTimer);
|
|
4891
|
+
eagerJsonTimer = null;
|
|
4892
|
+
}
|
|
4893
|
+
if (eagerJsonImmediate) {
|
|
4894
|
+
clearImmediate(eagerJsonImmediate);
|
|
4895
|
+
eagerJsonImmediate = null;
|
|
4896
|
+
}
|
|
4897
|
+
};
|
|
4600
4898
|
const observe = (phase, evidence = {}) => options.onPhase?.({
|
|
4601
4899
|
phase,
|
|
4602
4900
|
at: performance$1.now(),
|
|
@@ -4605,6 +4903,7 @@ function runOpenSpecCliWorker(options) {
|
|
|
4605
4903
|
const finish = (reason, exitCode) => {
|
|
4606
4904
|
if (settled) return;
|
|
4607
4905
|
settled = true;
|
|
4906
|
+
clearEagerJsonResolution();
|
|
4608
4907
|
phases.resultResolvedAt = performance$1.now();
|
|
4609
4908
|
phases.resultReason = reason;
|
|
4610
4909
|
observe("result-resolved", { reason });
|
|
@@ -4680,12 +4979,21 @@ function runOpenSpecCliWorker(options) {
|
|
|
4680
4979
|
observe("first-stdout-observed");
|
|
4681
4980
|
}
|
|
4682
4981
|
stdout += data.toString();
|
|
4683
|
-
if (options.eagerResolveJson && !phases.
|
|
4982
|
+
if (options.eagerResolveJson && !phases.jsonCompleteAt && stdout.trimStart().startsWith("{")) try {
|
|
4684
4983
|
JSON.parse(stdout);
|
|
4685
|
-
phases.eagerResolved = true;
|
|
4686
4984
|
phases.jsonCompleteAt = performance$1.now();
|
|
4687
4985
|
observe("json-complete-observed");
|
|
4688
|
-
|
|
4986
|
+
eagerJsonTimer = setTimeout(() => {
|
|
4987
|
+
eagerJsonTimer = null;
|
|
4988
|
+
if (settled || phases.exitAt || workerError || completedExitCode !== null || stderr.length > 0) return;
|
|
4989
|
+
eagerJsonImmediate = setImmediate(() => {
|
|
4990
|
+
eagerJsonImmediate = null;
|
|
4991
|
+
if (settled || phases.exitAt || workerError || completedExitCode !== null || stderr.length > 0) return;
|
|
4992
|
+
phases.eagerResolved = true;
|
|
4993
|
+
requestTermination("eager-json");
|
|
4994
|
+
finish("eager-json", 0);
|
|
4995
|
+
});
|
|
4996
|
+
}, EAGER_JSON_EXIT_GRACE_MS);
|
|
4689
4997
|
} catch {}
|
|
4690
4998
|
});
|
|
4691
4999
|
worker.stderr.on("data", (data) => {
|
|
@@ -4704,6 +5012,7 @@ function runOpenSpecCliWorker(options) {
|
|
|
4704
5012
|
});
|
|
4705
5013
|
worker.once("exit", (workerExitCode) => {
|
|
4706
5014
|
options.signal?.removeEventListener("abort", onAbort);
|
|
5015
|
+
clearEagerJsonResolution();
|
|
4707
5016
|
phases.exitAt = performance$1.now();
|
|
4708
5017
|
const exitCode = aborted ? null : phases.eagerResolved ? 0 : completedExitCode ?? workerExitCode;
|
|
4709
5018
|
observe("exit-observed", { exitCode });
|
|
@@ -4724,27 +5033,19 @@ function runOpenSpecCliWorker(options) {
|
|
|
4724
5033
|
//#endregion
|
|
4725
5034
|
//#region src/cli-executor.ts
|
|
4726
5035
|
/**
|
|
4727
|
-
* Orthogonal intents (updated 2026-08-
|
|
4728
|
-
* 1. Execute buffered CLI work through process/Worker backends with runner recovery,
|
|
4729
|
-
*
|
|
4730
|
-
* 2. Own streaming CLI
|
|
4731
|
-
* 3. Retain lifecycle helpers
|
|
4732
|
-
*
|
|
4733
|
-
*
|
|
4734
|
-
*
|
|
5036
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
5037
|
+
* 1. Execute buffered CLI work through process/Worker backends with runner recovery, observer-explicit
|
|
5038
|
+
* OTel phase evidence, bounded probes, and owner-scoped disposal.
|
|
5039
|
+
* 2. Own streaming CLI process trees through cancellation request, escalation, and confirmed settlement.
|
|
5040
|
+
* 3. Retain lifecycle helpers, add the fixed-path tools-none project bootstrap stream, and keep the
|
|
5041
|
+
* Core-owned direct-child slot clear independently from stream settlement.
|
|
5042
|
+
* 4. Expose the physically separated OpenSpec 1.6-1.9 typed command facade with response-Span delivery
|
|
5043
|
+
* separate from late child-process settlement evidence.
|
|
5044
|
+
* 5. Report eager-resolved exit codes as unknown instead of fabricated zeros.
|
|
4735
5045
|
*
|
|
4736
5046
|
* Original request (2026-07-15): "你先负责后端(内核)的开发。"
|
|
4737
5047
|
* Original request (2026-07-17): "A stream cancellation request is not child-process settlement."
|
|
4738
|
-
*
|
|
4739
|
-
* Tracing (2026-07-31): each CLI subprocess call is wrapped in an OpenTelemetry span so the Server
|
|
4740
|
-
* `planningRoot.runOperation` breakdown can attribute latency to specific CLI invocations
|
|
4741
|
-
* (doctor / context / list ...). Uses `@opentelemetry/api` only — a no-op tracer is returned when
|
|
4742
|
-
* no SDK is registered, so standalone Core use incurs zero overhead.
|
|
4743
|
-
* Original request (2026-07-31): "这些命令的执行,时间绝对不是七八秒那么久...请看一下代码,看能不能让trace更精确"
|
|
4744
|
-
* Original request (2026-07-31): "终端大量报错,比如: Cannot execute the operation on ended Span"
|
|
4745
|
-
* Original request (2026-07-31): "在主线程,通过 OPENSPEC_SPAWN_MODE=process|worker 来进行区分两种模式。"
|
|
4746
|
-
* Original request (2026-08-02): initialize the Launch Project with `openspec init <path> --tools=none`.
|
|
4747
|
-
* Review correction (2026-08-02): streamed command evidence must preserve argv boundaries.
|
|
5048
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
4748
5049
|
*/
|
|
4749
5050
|
/** Failure raised when even forced termination cannot confirm child-process close. */
|
|
4750
5051
|
var CliStreamTerminationError = class extends Error {
|
|
@@ -5017,11 +5318,12 @@ var CliExecutor = class {
|
|
|
5017
5318
|
phases: result.phases,
|
|
5018
5319
|
spawnMode
|
|
5019
5320
|
};
|
|
5321
|
+
const eagerResolved = result.phases?.resultReason === "eager-json";
|
|
5020
5322
|
return {
|
|
5021
|
-
success: result.exitCode === 0,
|
|
5323
|
+
success: result.exitCode === 0 || eagerResolved && result.exitCode === null,
|
|
5022
5324
|
stdout: result.stdout,
|
|
5023
5325
|
stderr: result.stderr,
|
|
5024
|
-
exitCode: result.exitCode,
|
|
5326
|
+
exitCode: eagerResolved ? null : result.exitCode,
|
|
5025
5327
|
phases: result.phases,
|
|
5026
5328
|
spawnMode
|
|
5027
5329
|
};
|
|
@@ -5191,10 +5493,12 @@ var CliExecutor = class {
|
|
|
5191
5493
|
return this.execute(args);
|
|
5192
5494
|
}
|
|
5193
5495
|
/**
|
|
5194
|
-
* 执行 openspec schemas --json
|
|
5496
|
+
* 执行 openspec schemas --json(可选转发所选 Root 的 Store 选择器)
|
|
5195
5497
|
*/
|
|
5196
|
-
async schemas() {
|
|
5197
|
-
|
|
5498
|
+
async schemas(selector = {}) {
|
|
5499
|
+
const args = ["schemas", "--json"];
|
|
5500
|
+
if (selector.store !== void 0) args.push("--store", selector.store);
|
|
5501
|
+
return this.execute(args);
|
|
5198
5502
|
}
|
|
5199
5503
|
/**
|
|
5200
5504
|
* 执行 openspec schema which <name> --json
|
|
@@ -5321,14 +5625,10 @@ var CliExecutor = class {
|
|
|
5321
5625
|
const requestChildTermination = (child) => {
|
|
5322
5626
|
if (terminationStarted || settled) return;
|
|
5323
5627
|
terminationStarted = true;
|
|
5324
|
-
|
|
5325
|
-
child.kill("SIGTERM");
|
|
5326
|
-
} catch {}
|
|
5628
|
+
terminateChildProcessTree(child).catch(() => {});
|
|
5327
5629
|
terminationTimer = setTimeout(() => {
|
|
5328
5630
|
if (settled || !childOwner.owns(child)) return;
|
|
5329
|
-
|
|
5330
|
-
child.kill("SIGKILL");
|
|
5331
|
-
} catch {}
|
|
5631
|
+
terminateChildProcessTree(child, "SIGKILL").catch(() => {});
|
|
5332
5632
|
forceCloseTimer = setTimeout(() => {
|
|
5333
5633
|
if (!settled && childOwner.owns(child)) failTermination();
|
|
5334
5634
|
}, STREAM_FORCE_CLOSE_TIMEOUT_MS);
|
|
@@ -5904,6 +6204,59 @@ var RuntimeRootInvalidationRegistry = class {
|
|
|
5904
6204
|
|
|
5905
6205
|
//#endregion
|
|
5906
6206
|
//#region src/agent-delivery-registry.ts
|
|
6207
|
+
/**
|
|
6208
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
6209
|
+
* 1. Preserve the complete pinned OpenSpec 1.9 Agent delivery registry in one typed physical owner.
|
|
6210
|
+
* 2. Co-locate capability, command artifact, invocation, alias, setup, cleanup, and migration metadata.
|
|
6211
|
+
* 3. Model current/legacy project roots, user-global skill roots, detection paths, and IDE restart facts.
|
|
6212
|
+
* 4. Provide deterministic path-template helpers without reading runtime filesystem state.
|
|
6213
|
+
* 5. Select the official inventory per admitted CLI line (1.8 lacks Command Code and restart facts).
|
|
6214
|
+
*
|
|
6215
|
+
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
6216
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
6217
|
+
*/
|
|
6218
|
+
function agentCliSeriesOrder(series) {
|
|
6219
|
+
return series === "1.9" ? 19 : 18;
|
|
6220
|
+
}
|
|
6221
|
+
/**
|
|
6222
|
+
* Select the official Agent delivery inventory for one CLI version string.
|
|
6223
|
+
*
|
|
6224
|
+
* Only a stable, admitted version — current (1.9.x) or supported non-current (1.8.x) — selects
|
|
6225
|
+
* an inventory. Unsupported forms (prereleases, >=1.10, below-range) and unparseable output
|
|
6226
|
+
* select none: a page-level version bypass must not manufacture a 1.9 inventory for a CLI the
|
|
6227
|
+
* release line refuses to admit.
|
|
6228
|
+
*/
|
|
6229
|
+
function selectAgentDeliveryRegistry(cliVersion) {
|
|
6230
|
+
const series = parseOpenSpecCliSeries(cliVersion);
|
|
6231
|
+
if (series === null) return [];
|
|
6232
|
+
const running = agentCliSeriesOrder(series);
|
|
6233
|
+
return AGENT_DELIVERY_REGISTRY.filter((tool) => {
|
|
6234
|
+
if (tool.minCliSeries && agentCliSeriesOrder(tool.minCliSeries) > running) return false;
|
|
6235
|
+
return true;
|
|
6236
|
+
}).map((tool) => {
|
|
6237
|
+
if (tool.requiresIdeRestart !== void 0 && tool.requiresIdeRestartSince && agentCliSeriesOrder(tool.requiresIdeRestartSince) > running) {
|
|
6238
|
+
const { ...rest } = tool;
|
|
6239
|
+
delete rest.requiresIdeRestart;
|
|
6240
|
+
return rest;
|
|
6241
|
+
}
|
|
6242
|
+
return { ...tool };
|
|
6243
|
+
});
|
|
6244
|
+
}
|
|
6245
|
+
/**
|
|
6246
|
+
* Parse a CLI version string into an admitted Agent inventory line.
|
|
6247
|
+
*
|
|
6248
|
+
* Delegates to the single compat version parser so the same stdout that classifies a session
|
|
6249
|
+
* also selects its inventory — two parsers must never disagree at this boundary. Returns
|
|
6250
|
+
* '1.9' only for stable 1.9.x, '1.8' only for stable 1.8.x, and null for every non-admitted
|
|
6251
|
+
* form: prereleases, >=1.10, below-range, or unparseable output.
|
|
6252
|
+
*/
|
|
6253
|
+
function parseOpenSpecCliSeries(cliVersion) {
|
|
6254
|
+
const version = parseOpenSpecCliVersion(cliVersion ?? void 0);
|
|
6255
|
+
if (!version || version.prerelease !== null) return null;
|
|
6256
|
+
if (version.major === 1 && version.minor === 9) return "1.9";
|
|
6257
|
+
if (version.major === 1 && version.minor === 8) return "1.8";
|
|
6258
|
+
return null;
|
|
6259
|
+
}
|
|
5907
6260
|
const CODEX_MANAGED_PROMPTS = {
|
|
5908
6261
|
"opsx-propose.md": ["propose"],
|
|
5909
6262
|
"opsx-explore.md": ["explore"],
|
|
@@ -5958,7 +6311,7 @@ const projectCleanup = (...patterns) => ({
|
|
|
5958
6311
|
kind: "project-patterns",
|
|
5959
6312
|
patterns
|
|
5960
6313
|
});
|
|
5961
|
-
/** Complete OpenSpec 1.
|
|
6314
|
+
/** Complete OpenSpec 1.9 Agent delivery registry in official order. */
|
|
5962
6315
|
const AGENT_DELIVERY_REGISTRY = [
|
|
5963
6316
|
{
|
|
5964
6317
|
name: "Amazon Q Developer",
|
|
@@ -5966,6 +6319,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
5966
6319
|
available: true,
|
|
5967
6320
|
successLabel: "Amazon Q Developer",
|
|
5968
6321
|
skillsDir: ".amazonq",
|
|
6322
|
+
requiresIdeRestart: true,
|
|
6323
|
+
requiresIdeRestartSince: "1.9",
|
|
5969
6324
|
capability: "adapter-backed",
|
|
5970
6325
|
command: command(".amazonq/prompts/opsx-{workflow}.md", yamlMarkdown("description"), { invocationPrefix: "@" }),
|
|
5971
6326
|
cleanup: projectCleanup(".amazonq/prompts/openspec-*.md")
|
|
@@ -5976,6 +6331,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
5976
6331
|
available: true,
|
|
5977
6332
|
successLabel: "Antigravity",
|
|
5978
6333
|
skillsDir: ".agent",
|
|
6334
|
+
requiresIdeRestart: true,
|
|
6335
|
+
requiresIdeRestartSince: "1.9",
|
|
5979
6336
|
capability: "adapter-backed",
|
|
5980
6337
|
command: command(".agent/workflows/opsx-{workflow}.md", yamlMarkdown("description")),
|
|
5981
6338
|
cleanup: projectCleanup(".agent/workflows/openspec-*.md")
|
|
@@ -6015,10 +6372,22 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6015
6372
|
available: true,
|
|
6016
6373
|
successLabel: "Cline",
|
|
6017
6374
|
skillsDir: ".cline",
|
|
6375
|
+
requiresIdeRestart: true,
|
|
6376
|
+
requiresIdeRestartSince: "1.9",
|
|
6018
6377
|
capability: "adapter-backed",
|
|
6019
6378
|
command: command(".clinerules/workflows/opsx-{workflow}.md", headingMarkdown),
|
|
6020
6379
|
cleanup: projectCleanup(".clinerules/workflows/openspec-*.md")
|
|
6021
6380
|
},
|
|
6381
|
+
{
|
|
6382
|
+
name: "Command Code",
|
|
6383
|
+
value: "command-code",
|
|
6384
|
+
minCliSeries: "1.9",
|
|
6385
|
+
available: true,
|
|
6386
|
+
successLabel: "Command Code",
|
|
6387
|
+
skillsDir: ".commandcode",
|
|
6388
|
+
capability: "adapter-backed",
|
|
6389
|
+
command: command(".commandcode/commands/opsx-{workflow}.md", plainMarkdown)
|
|
6390
|
+
},
|
|
6022
6391
|
{
|
|
6023
6392
|
name: "CodeArts",
|
|
6024
6393
|
value: "codeartsagent",
|
|
@@ -6033,7 +6402,9 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6033
6402
|
value: "codex",
|
|
6034
6403
|
available: true,
|
|
6035
6404
|
successLabel: "Codex",
|
|
6036
|
-
skillsDir: ".
|
|
6405
|
+
skillsDir: ".agents",
|
|
6406
|
+
legacySkillsDirs: [".codex"],
|
|
6407
|
+
detectionPaths: [".agents/skills", ".codex/skills"],
|
|
6037
6408
|
capability: "skills-invocable",
|
|
6038
6409
|
command: null,
|
|
6039
6410
|
cleanup: {
|
|
@@ -6041,7 +6412,12 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6041
6412
|
projectPatterns: [".codex/prompts/openspec-*.md"],
|
|
6042
6413
|
managedFiles: CODEX_MANAGED_PROMPTS,
|
|
6043
6414
|
replacementLabel: "Codex skills"
|
|
6044
|
-
}
|
|
6415
|
+
},
|
|
6416
|
+
migrations: [{
|
|
6417
|
+
from: ".codex",
|
|
6418
|
+
to: ".agents",
|
|
6419
|
+
needsConsent: false
|
|
6420
|
+
}]
|
|
6045
6421
|
},
|
|
6046
6422
|
{
|
|
6047
6423
|
name: "Devin Desktop (formerly Windsurf)",
|
|
@@ -6050,6 +6426,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6050
6426
|
successLabel: "Devin Desktop",
|
|
6051
6427
|
skillsDir: ".devin",
|
|
6052
6428
|
detectionPaths: [".devin", ".windsurf"],
|
|
6429
|
+
requiresIdeRestart: true,
|
|
6430
|
+
requiresIdeRestartSince: "1.9",
|
|
6053
6431
|
capability: "adapter-backed",
|
|
6054
6432
|
command: command(".devin/workflows/opsx-{workflow}.md", yamlMarkdown("name", "description", "category", "tags")),
|
|
6055
6433
|
aliases: ["windsurf"],
|
|
@@ -6085,6 +6463,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6085
6463
|
available: true,
|
|
6086
6464
|
successLabel: "Continue (VS Code / JetBrains / Cli)",
|
|
6087
6465
|
skillsDir: ".continue",
|
|
6466
|
+
requiresIdeRestart: true,
|
|
6467
|
+
requiresIdeRestartSince: "1.9",
|
|
6088
6468
|
capability: "adapter-backed",
|
|
6089
6469
|
command: command(".continue/prompts/opsx-{workflow}.prompt", yamlMarkdown("name", "description", "invokable")),
|
|
6090
6470
|
cleanup: projectCleanup(".continue/prompts/openspec-*.prompt")
|
|
@@ -6095,6 +6475,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6095
6475
|
available: true,
|
|
6096
6476
|
successLabel: "CoStrict",
|
|
6097
6477
|
skillsDir: ".cospec",
|
|
6478
|
+
requiresIdeRestart: true,
|
|
6479
|
+
requiresIdeRestartSince: "1.9",
|
|
6098
6480
|
capability: "adapter-backed",
|
|
6099
6481
|
command: command(".cospec/openspec/commands/opsx-{workflow}.md", yamlMarkdown("description", "argument-hint")),
|
|
6100
6482
|
cleanup: projectCleanup(".cospec/openspec/commands")
|
|
@@ -6115,6 +6497,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6115
6497
|
available: true,
|
|
6116
6498
|
successLabel: "Cursor",
|
|
6117
6499
|
skillsDir: ".cursor",
|
|
6500
|
+
requiresIdeRestart: true,
|
|
6501
|
+
requiresIdeRestartSince: "1.9",
|
|
6118
6502
|
capability: "adapter-backed",
|
|
6119
6503
|
command: command(".cursor/commands/opsx-{workflow}.md", yamlMarkdown("name", "id", "category", "description")),
|
|
6120
6504
|
cleanup: projectCleanup(".cursor/commands/openspec-*.md")
|
|
@@ -6154,6 +6538,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6154
6538
|
".github/skills",
|
|
6155
6539
|
".github/.mcp.json"
|
|
6156
6540
|
],
|
|
6541
|
+
requiresIdeRestart: true,
|
|
6542
|
+
requiresIdeRestartSince: "1.9",
|
|
6157
6543
|
capability: "adapter-backed",
|
|
6158
6544
|
command: command(".github/prompts/opsx-{workflow}.prompt.md", yamlMarkdown("description")),
|
|
6159
6545
|
cleanup: projectCleanup(".github/prompts/openspec-*.prompt.md")
|
|
@@ -6189,6 +6575,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6189
6575
|
available: true,
|
|
6190
6576
|
successLabel: "Junie",
|
|
6191
6577
|
skillsDir: ".junie",
|
|
6578
|
+
requiresIdeRestart: true,
|
|
6579
|
+
requiresIdeRestartSince: "1.9",
|
|
6192
6580
|
capability: "adapter-backed",
|
|
6193
6581
|
command: command(".junie/commands/opsx-{workflow}.md", yamlMarkdown("description")),
|
|
6194
6582
|
cleanup: projectCleanup(".junie/commands/opsx-*.md", ".junie/commands/openspec-*.md")
|
|
@@ -6199,6 +6587,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6199
6587
|
available: true,
|
|
6200
6588
|
successLabel: "Kilo Code",
|
|
6201
6589
|
skillsDir: ".kilocode",
|
|
6590
|
+
requiresIdeRestart: true,
|
|
6591
|
+
requiresIdeRestartSince: "1.9",
|
|
6202
6592
|
capability: "adapter-backed",
|
|
6203
6593
|
command: command(".kilocode/workflows/opsx-{workflow}.md", plainMarkdown),
|
|
6204
6594
|
cleanup: projectCleanup(".kilocode/workflows/openspec-*.md")
|
|
@@ -6224,6 +6614,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6224
6614
|
available: true,
|
|
6225
6615
|
successLabel: "Kiro",
|
|
6226
6616
|
skillsDir: ".kiro",
|
|
6617
|
+
requiresIdeRestart: true,
|
|
6618
|
+
requiresIdeRestartSince: "1.9",
|
|
6227
6619
|
capability: "adapter-backed",
|
|
6228
6620
|
command: command(".kiro/prompts/opsx-{workflow}.prompt.md", yamlMarkdown("description")),
|
|
6229
6621
|
cleanup: projectCleanup(".kiro/prompts/openspec-*.prompt.md")
|
|
@@ -6234,10 +6626,22 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6234
6626
|
available: true,
|
|
6235
6627
|
successLabel: "Lingma",
|
|
6236
6628
|
skillsDir: ".lingma",
|
|
6629
|
+
requiresIdeRestart: true,
|
|
6630
|
+
requiresIdeRestartSince: "1.9",
|
|
6237
6631
|
capability: "adapter-backed",
|
|
6238
6632
|
command: command(".lingma/commands/opsx/{workflow}.md", yamlMarkdown("name", "description", "category", "tags")),
|
|
6239
6633
|
cleanup: projectCleanup(".lingma/commands/openspec")
|
|
6240
6634
|
},
|
|
6635
|
+
{
|
|
6636
|
+
name: "MiniMax Code",
|
|
6637
|
+
value: "minimax-code",
|
|
6638
|
+
available: true,
|
|
6639
|
+
successLabel: "MiniMax Code",
|
|
6640
|
+
skillsDir: null,
|
|
6641
|
+
globalSkillsDir: ".minimax",
|
|
6642
|
+
capability: "skills-invocable",
|
|
6643
|
+
command: null
|
|
6644
|
+
},
|
|
6241
6645
|
{
|
|
6242
6646
|
name: "Mistral Vibe",
|
|
6243
6647
|
value: "vibe",
|
|
@@ -6281,6 +6685,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6281
6685
|
available: true,
|
|
6282
6686
|
successLabel: "Qoder",
|
|
6283
6687
|
skillsDir: ".qoder",
|
|
6688
|
+
requiresIdeRestart: true,
|
|
6689
|
+
requiresIdeRestartSince: "1.9",
|
|
6284
6690
|
capability: "adapter-backed",
|
|
6285
6691
|
command: command(".qoder/commands/opsx/{workflow}.md", yamlMarkdown("name", "description", "category", "tags")),
|
|
6286
6692
|
cleanup: projectCleanup(".qoder/commands/openspec")
|
|
@@ -6295,12 +6701,24 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6295
6701
|
command: command(".qwen/commands/opsx-{workflow}.md", yamlMarkdown("description")),
|
|
6296
6702
|
cleanup: projectCleanup(".qwen/commands/opsx-*.toml", ".qwen/commands/openspec-*.toml")
|
|
6297
6703
|
},
|
|
6704
|
+
{
|
|
6705
|
+
name: "Rovo Dev CLI",
|
|
6706
|
+
value: "rovodev",
|
|
6707
|
+
available: true,
|
|
6708
|
+
successLabel: "Rovo Dev CLI",
|
|
6709
|
+
skillsDir: ".rovodev",
|
|
6710
|
+
detectionPaths: [".rovodev/skills", ".rovodev"],
|
|
6711
|
+
capability: "skills-invocable",
|
|
6712
|
+
command: null
|
|
6713
|
+
},
|
|
6298
6714
|
{
|
|
6299
6715
|
name: "Zoo Code",
|
|
6300
6716
|
value: "roocode",
|
|
6301
6717
|
available: true,
|
|
6302
6718
|
successLabel: "Zoo Code",
|
|
6303
6719
|
skillsDir: ".roo",
|
|
6720
|
+
requiresIdeRestart: true,
|
|
6721
|
+
requiresIdeRestartSince: "1.9",
|
|
6304
6722
|
capability: "adapter-backed",
|
|
6305
6723
|
command: command(".roo/commands/opsx-{workflow}.md", headingMarkdown),
|
|
6306
6724
|
cleanup: projectCleanup(".roo/commands/openspec-*.md")
|
|
@@ -6311,6 +6729,8 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6311
6729
|
available: true,
|
|
6312
6730
|
successLabel: "Trae",
|
|
6313
6731
|
skillsDir: ".trae",
|
|
6732
|
+
requiresIdeRestart: true,
|
|
6733
|
+
requiresIdeRestartSince: "1.9",
|
|
6314
6734
|
capability: "adapter-backed",
|
|
6315
6735
|
command: command(".trae/commands/opsx-{workflow}.md", yamlMarkdown("name", "description"))
|
|
6316
6736
|
},
|
|
@@ -6324,12 +6744,13 @@ const AGENT_DELIVERY_REGISTRY = [
|
|
|
6324
6744
|
command: command(".zcode/commands/opsx/{workflow}.md", yamlMarkdown("name", "description", "category", "tags"))
|
|
6325
6745
|
},
|
|
6326
6746
|
{
|
|
6327
|
-
name: "
|
|
6747
|
+
name: "Shared .agents skills",
|
|
6328
6748
|
value: "agents",
|
|
6329
|
-
available:
|
|
6330
|
-
successLabel: "
|
|
6331
|
-
skillsDir:
|
|
6332
|
-
|
|
6749
|
+
available: true,
|
|
6750
|
+
successLabel: "shared .agents skills",
|
|
6751
|
+
skillsDir: ".agents",
|
|
6752
|
+
detectionPaths: [".agents/skills"],
|
|
6753
|
+
capability: "skills-invocable",
|
|
6333
6754
|
command: null
|
|
6334
6755
|
}
|
|
6335
6756
|
];
|
|
@@ -6345,280 +6766,109 @@ function resolveAgentCommandPathTemplate(pathTemplate, workflow) {
|
|
|
6345
6766
|
}
|
|
6346
6767
|
|
|
6347
6768
|
//#endregion
|
|
6348
|
-
//#region src/tool-
|
|
6769
|
+
//#region src/tool-init-state.ts
|
|
6349
6770
|
/**
|
|
6350
|
-
* Orthogonal intents (updated 2026-08-
|
|
6351
|
-
* 1.
|
|
6352
|
-
* 2.
|
|
6771
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
6772
|
+
* 1. Project the unified OpenSpec 1.9 Agent registry into exact skill and command artifact state.
|
|
6773
|
+
* 2. Report partial, stale-version, cleanup-needed, migration-required, and unavailable states from physical evidence.
|
|
6774
|
+
* 3. Observe user-global skill roots (e.g. MiniMax Code) without ever cleaning or migrating them here.
|
|
6775
|
+
* 4. Preserve bounded reactive directory observation and fresh one-shot cache invalidation.
|
|
6776
|
+
* 5. Expose Codex managed-global-prompt observation without treating those prompts as current commands.
|
|
6353
6777
|
*
|
|
6354
6778
|
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
6779
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
6355
6780
|
*/
|
|
6356
|
-
/**
|
|
6357
|
-
const
|
|
6358
|
-
|
|
6359
|
-
|
|
6360
|
-
|
|
6361
|
-
|
|
6362
|
-
|
|
6363
|
-
|
|
6364
|
-
|
|
6365
|
-
|
|
6366
|
-
|
|
6367
|
-
|
|
6368
|
-
"
|
|
6369
|
-
|
|
6370
|
-
|
|
6371
|
-
|
|
6372
|
-
|
|
6373
|
-
|
|
6374
|
-
|
|
6375
|
-
|
|
6376
|
-
|
|
6377
|
-
|
|
6781
|
+
/** Pinned source version used when a runtime CLI version is not supplied by the Server owner. */
|
|
6782
|
+
const PINNED_AGENT_GENERATOR_VERSION = "1.9.0";
|
|
6783
|
+
/** Resolve the physical skills inventory scope for one registry entry. */
|
|
6784
|
+
function resolveToolSkillsScope(tool) {
|
|
6785
|
+
if (tool.globalSkillsDir) return {
|
|
6786
|
+
kind: "user-global",
|
|
6787
|
+
globalSkillsDir: tool.globalSkillsDir
|
|
6788
|
+
};
|
|
6789
|
+
if (tool.skillsDir) return {
|
|
6790
|
+
kind: "project",
|
|
6791
|
+
skillsDir: tool.skillsDir
|
|
6792
|
+
};
|
|
6793
|
+
return { kind: "none" };
|
|
6794
|
+
}
|
|
6795
|
+
/** Resolve the home directory the same way the official CLI resolves user-global roots. */
|
|
6796
|
+
function resolveAgentHome() {
|
|
6797
|
+
return process.env.USERPROFILE || process.env.HOME || homedir();
|
|
6798
|
+
}
|
|
6799
|
+
/** Resolve the absolute user-global skills inventory directory for a global root (e.g. `.minimax`). */
|
|
6800
|
+
function resolveGlobalSkillsInventoryDir(globalSkillsDir) {
|
|
6801
|
+
return resolve(resolveAgentHome(), globalSkillsDir, "skills");
|
|
6802
|
+
}
|
|
6803
|
+
/** External user-global skills inventory roots observed by the Agent delivery projection. */
|
|
6804
|
+
function getExternalAgentSkillsObservationRoots() {
|
|
6805
|
+
return AI_TOOLS.flatMap((tool) => {
|
|
6806
|
+
if (!tool.globalSkillsDir) return [];
|
|
6807
|
+
const root = resolveGlobalSkillsInventoryDir(tool.globalSkillsDir);
|
|
6808
|
+
return root === getExternalCodexCommandObservationRoot() ? [] : [root];
|
|
6809
|
+
});
|
|
6378
6810
|
}
|
|
6379
|
-
|
|
6380
|
-
function
|
|
6381
|
-
return
|
|
6811
|
+
const ALL_TOOL_WORKFLOWS = [...OPSX_ALL_WORKFLOWS];
|
|
6812
|
+
function toKnownWorkflows(workflows) {
|
|
6813
|
+
return workflows.filter((workflow) => workflow in OPSX_WORKFLOW_TO_SKILL_DIR);
|
|
6382
6814
|
}
|
|
6383
|
-
|
|
6384
|
-
|
|
6385
|
-
return (
|
|
6386
|
-
if (!tool.skillsDir) return null;
|
|
6387
|
-
if (tool.detectionPaths?.length) return (await Promise.all(tool.detectionPaths.map((detectionPath) => reactiveStat(join$1(projectDir, detectionPath))))).some((entry) => entry !== null) ? tool : null;
|
|
6388
|
-
return (await reactiveStat(join$1(projectDir, tool.skillsDir)))?.isDirectory === true ? tool : null;
|
|
6389
|
-
}))).filter((tool) => tool !== null);
|
|
6815
|
+
function resolveCodexHome() {
|
|
6816
|
+
const configuredHome = process.env.CODEX_HOME?.trim();
|
|
6817
|
+
return resolve(configuredHome ? configuredHome : join$1(homedir(), ".codex"));
|
|
6390
6818
|
}
|
|
6391
|
-
/** Return
|
|
6392
|
-
function
|
|
6393
|
-
return
|
|
6819
|
+
/** Return the external directory containing allowlisted managed legacy Codex prompts. */
|
|
6820
|
+
function getExternalCodexCommandObservationRoot() {
|
|
6821
|
+
return join$1(resolveCodexHome(), "prompts");
|
|
6394
6822
|
}
|
|
6395
|
-
|
|
6396
|
-
|
|
6397
|
-
const
|
|
6398
|
-
|
|
6823
|
+
function resolveCommandArtifact(projectDir, tool, workflow, rootOverride) {
|
|
6824
|
+
if (!tool.command) return null;
|
|
6825
|
+
const rebase = (pathTemplate) => {
|
|
6826
|
+
if (!rootOverride || !tool.skillsDir || !pathTemplate.startsWith(`${tool.skillsDir}/`)) return pathTemplate;
|
|
6827
|
+
return `${rootOverride}${pathTemplate.slice(tool.skillsDir.length)}`;
|
|
6828
|
+
};
|
|
6829
|
+
return {
|
|
6830
|
+
workflow,
|
|
6831
|
+
path: resolve(projectDir, resolveAgentCommandPathTemplate(rebase(tool.command.pathTemplate), workflow)),
|
|
6832
|
+
legacyPaths: tool.command.legacyPathTemplates?.map((pathTemplate) => resolve(projectDir, resolveAgentCommandPathTemplate(rebase(pathTemplate), workflow)))
|
|
6833
|
+
};
|
|
6399
6834
|
}
|
|
6400
|
-
|
|
6401
|
-
|
|
6402
|
-
|
|
6403
|
-
|
|
6835
|
+
function getSkillArtifactsFromInventory(inventoryRoot, workflows = ALL_TOOL_WORKFLOWS) {
|
|
6836
|
+
return workflows.map((workflow) => ({
|
|
6837
|
+
workflow,
|
|
6838
|
+
path: resolve(inventoryRoot, OPSX_WORKFLOW_TO_SKILL_DIR[workflow], "SKILL.md")
|
|
6839
|
+
}));
|
|
6404
6840
|
}
|
|
6405
|
-
|
|
6406
|
-
|
|
6407
|
-
if (!skillsDir) return 0;
|
|
6408
|
-
let count = 0;
|
|
6409
|
-
for (const skillName of SKILL_NAMES) if (await reactiveExists(join$1(skillsDir, skillName, "SKILL.md"))) count++;
|
|
6410
|
-
return count;
|
|
6841
|
+
function getSkillArtifacts(projectDir, skillsDir, workflows = ALL_TOOL_WORKFLOWS) {
|
|
6842
|
+
return getSkillArtifactsFromInventory(resolve(projectDir, skillsDir, "skills"), workflows);
|
|
6411
6843
|
}
|
|
6412
|
-
|
|
6413
|
-
return
|
|
6414
|
-
|
|
6415
|
-
return
|
|
6416
|
-
})
|
|
6844
|
+
function getCommandArtifacts(projectDir, tool, rootOverride) {
|
|
6845
|
+
return ALL_TOOL_WORKFLOWS.flatMap((workflow) => {
|
|
6846
|
+
const artifact = resolveCommandArtifact(projectDir, tool, workflow, rootOverride);
|
|
6847
|
+
return artifact ? [artifact] : [];
|
|
6848
|
+
});
|
|
6417
6849
|
}
|
|
6418
|
-
function
|
|
6419
|
-
const
|
|
6850
|
+
function invalidateToolInitCaches(projectDir) {
|
|
6851
|
+
const cacheRoots = new Set([
|
|
6852
|
+
resolve(projectDir),
|
|
6853
|
+
getExternalCodexCommandObservationRoot(),
|
|
6854
|
+
...getExternalAgentSkillsObservationRoots()
|
|
6855
|
+
]);
|
|
6420
6856
|
for (const tool of AI_TOOLS) {
|
|
6421
|
-
if (tool.skillsDir)
|
|
6422
|
-
for (const
|
|
6857
|
+
if (tool.skillsDir) cacheRoots.add(resolve(projectDir, tool.skillsDir));
|
|
6858
|
+
for (const legacyRoot of tool.legacySkillsDirs ?? []) cacheRoots.add(resolve(projectDir, legacyRoot));
|
|
6859
|
+
for (const migration of tool.migrations ?? []) cacheRoots.add(resolve(projectDir, migration.from));
|
|
6860
|
+
for (const commandArtifact of getCommandArtifacts(projectDir, tool)) {
|
|
6861
|
+
cacheRoots.add(dirname$1(commandArtifact.path));
|
|
6862
|
+
for (const legacyPath of commandArtifact.legacyPaths ?? []) cacheRoots.add(dirname$1(legacyPath));
|
|
6863
|
+
}
|
|
6423
6864
|
}
|
|
6424
|
-
|
|
6865
|
+
for (const root of cacheRoots) clearCache(root);
|
|
6425
6866
|
}
|
|
6426
|
-
|
|
6427
|
-
|
|
6428
|
-
const normalizedPath = resolve(projectDir);
|
|
6429
|
-
const key = `tools:${normalizedPath}`;
|
|
6430
|
-
let state = stateCache.get(key);
|
|
6431
|
-
if (!state) {
|
|
6432
|
-
state = new ReactiveState(await scanConfiguredTools(normalizedPath), { equals: (left, right) => left.length === right.length && left.every((value, index) => value === right[index]) });
|
|
6433
|
-
stateCache.set(key, state);
|
|
6434
|
-
const releases = [];
|
|
6435
|
-
const onUpdate = async () => state?.set(await scanConfiguredTools(normalizedPath));
|
|
6436
|
-
for (const dir of getProjectWatchDirs(normalizedPath)) releases.push(acquireWatcher(dir, onUpdate, { recursive: true }));
|
|
6437
|
-
releases.push(acquireWatcher(normalizedPath, onUpdate, { recursive: false }));
|
|
6438
|
-
releaseCache.set(key, () => releases.forEach((release) => release()));
|
|
6439
|
-
}
|
|
6440
|
-
return state.get();
|
|
6867
|
+
async function readArtifactDirectory(dir) {
|
|
6868
|
+
return new Set(await reactiveReadDir(dir, { includeHidden: true }));
|
|
6441
6869
|
}
|
|
6442
|
-
|
|
6443
|
-
|
|
6444
|
-
return (await getConfiguredTools(projectDir)).includes(resolveAgentToolId(toolId));
|
|
6445
|
-
}
|
|
6446
|
-
|
|
6447
|
-
//#endregion
|
|
6448
|
-
//#region src/agent-delivery-policy.ts
|
|
6449
|
-
/**
|
|
6450
|
-
* Orthogonal intents (created 2026-08-01 Asia/Shanghai):
|
|
6451
|
-
* 1. Define the structured Agent profile, delivery, and workflow mutation contract.
|
|
6452
|
-
* 2. Normalize Core versus Custom workflow semantics exactly once.
|
|
6453
|
-
* 3. Preserve unknown environment-global JSON fields while updating official Agent policy keys.
|
|
6454
|
-
*
|
|
6455
|
-
* Original request (2026-08-01): keep raw environment config authoring while moving official Agent controls to Config.
|
|
6456
|
-
*/
|
|
6457
|
-
const AgentDeliveryProfileSchema = z.enum(["core", "custom"]);
|
|
6458
|
-
const AgentDeliveryModeSchema = z.enum([
|
|
6459
|
-
"both",
|
|
6460
|
-
"skills",
|
|
6461
|
-
"commands"
|
|
6462
|
-
]);
|
|
6463
|
-
const AgentDeliveryWorkflowSchema = z.enum(OPSX_ALL_WORKFLOWS);
|
|
6464
|
-
const AgentDeliveryPolicyUpdateSchema = z.object({
|
|
6465
|
-
profile: AgentDeliveryProfileSchema,
|
|
6466
|
-
delivery: AgentDeliveryModeSchema,
|
|
6467
|
-
workflows: z.array(AgentDeliveryWorkflowSchema)
|
|
6468
|
-
}).superRefine((value, context$1) => {
|
|
6469
|
-
if (new Set(value.workflows).size !== value.workflows.length) context$1.addIssue({
|
|
6470
|
-
code: "custom",
|
|
6471
|
-
message: "Agent workflows must be unique."
|
|
6472
|
-
});
|
|
6473
|
-
});
|
|
6474
|
-
/** Normalize authored policy through official omitted-value defaults and Core workflow semantics. */
|
|
6475
|
-
function normalizeAgentDeliveryPolicy(input) {
|
|
6476
|
-
const profile = input.profile === "custom" ? "custom" : "core";
|
|
6477
|
-
return {
|
|
6478
|
-
profile,
|
|
6479
|
-
delivery: input.delivery === "skills" || input.delivery === "commands" ? input.delivery : "both",
|
|
6480
|
-
workflows: profile === "core" ? [...OPSX_CORE_PROFILE_WORKFLOWS] : OPSX_ALL_WORKFLOWS.filter((workflow) => input.workflows?.includes(workflow))
|
|
6481
|
-
};
|
|
6482
|
-
}
|
|
6483
|
-
/** Update only official Agent policy keys while retaining every team-authored extension field. */
|
|
6484
|
-
function applyAgentDeliveryPolicy(config, update) {
|
|
6485
|
-
const policy = normalizeAgentDeliveryPolicy(update);
|
|
6486
|
-
return {
|
|
6487
|
-
...config,
|
|
6488
|
-
profile: policy.profile,
|
|
6489
|
-
delivery: policy.delivery,
|
|
6490
|
-
workflows: policy.workflows
|
|
6491
|
-
};
|
|
6492
|
-
}
|
|
6493
|
-
|
|
6494
|
-
//#endregion
|
|
6495
|
-
//#region src/agent-command-content.ts
|
|
6496
|
-
/**
|
|
6497
|
-
* Orthogonal intents (created 2026-08-01 Asia/Shanghai):
|
|
6498
|
-
* 1. Resolve the running OpenSpec CLI's private command-generation boundary without bundling copied prompts.
|
|
6499
|
-
* 2. Produce exact per-Agent, per-workflow command contents for physical fingerprint comparison.
|
|
6500
|
-
* 3. Fail closed when the configured runner has no importable OpenSpec module or compatible generator contract.
|
|
6501
|
-
*
|
|
6502
|
-
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
6503
|
-
*/
|
|
6504
|
-
const KNOWN_WORKFLOWS = new Set(OPSX_ALL_WORKFLOWS);
|
|
6505
|
-
function isRecord(value) {
|
|
6506
|
-
return typeof value === "object" && value !== null;
|
|
6507
|
-
}
|
|
6508
|
-
function isRuntimeSkillGenerationModule(value) {
|
|
6509
|
-
return isRecord(value) && typeof value.getCommandContents === "function";
|
|
6510
|
-
}
|
|
6511
|
-
function isRuntimeCommandAdapterRegistry(value) {
|
|
6512
|
-
if (typeof value !== "object" && typeof value !== "function" || value === null) return false;
|
|
6513
|
-
return "get" in value && typeof value.get === "function";
|
|
6514
|
-
}
|
|
6515
|
-
function isRuntimeCommandGenerationModule(value) {
|
|
6516
|
-
return isRecord(value) && isRuntimeCommandAdapterRegistry(value.CommandAdapterRegistry) && typeof value.generateCommands === "function";
|
|
6517
|
-
}
|
|
6518
|
-
function isRuntimeCommandContent(value) {
|
|
6519
|
-
return isRecord(value) && typeof value.id === "string" && KNOWN_WORKFLOWS.has(value.id);
|
|
6520
|
-
}
|
|
6521
|
-
function isRuntimeGeneratedCommand(value) {
|
|
6522
|
-
return isRecord(value) && typeof value.fileContent === "string";
|
|
6523
|
-
}
|
|
6524
|
-
/**
|
|
6525
|
-
* Load exact command contents from the configured OpenSpec CLI.
|
|
6526
|
-
*
|
|
6527
|
-
* The private generator is intentionally treated as optional evidence. When the runner is not an
|
|
6528
|
-
* importable local OpenSpec module, callers receive `null` and commands-only installs cannot be
|
|
6529
|
-
* declared current from path existence alone.
|
|
6530
|
-
*/
|
|
6531
|
-
async function loadOpenSpecAgentCommandContents(cliCommand, workflows) {
|
|
6532
|
-
try {
|
|
6533
|
-
const cliModuleDir = dirname$1((await resolveOpenSpecWorkerInvocation(cliCommand)).modulePath);
|
|
6534
|
-
const [skillGenerationModule, commandGenerationModule] = await Promise.all([import(pathToFileURL(resolve(cliModuleDir, "../core/shared/skill-generation.js")).href), import(pathToFileURL(resolve(cliModuleDir, "../core/command-generation/index.js")).href)]);
|
|
6535
|
-
if (!isRuntimeSkillGenerationModule(skillGenerationModule) || !isRuntimeCommandGenerationModule(commandGenerationModule)) return null;
|
|
6536
|
-
const commandContents = skillGenerationModule.getCommandContents(workflows);
|
|
6537
|
-
if (!Array.isArray(commandContents) || !commandContents.every(isRuntimeCommandContent)) return null;
|
|
6538
|
-
const catalog = {};
|
|
6539
|
-
for (const tool of AGENT_DELIVERY_REGISTRY) {
|
|
6540
|
-
if (!tool.command) continue;
|
|
6541
|
-
const adapter = commandGenerationModule.CommandAdapterRegistry.get(tool.value);
|
|
6542
|
-
if (!adapter) return null;
|
|
6543
|
-
const generatedCommands = commandGenerationModule.generateCommands(commandContents, adapter);
|
|
6544
|
-
if (!Array.isArray(generatedCommands) || generatedCommands.length !== commandContents.length || !generatedCommands.every(isRuntimeGeneratedCommand)) return null;
|
|
6545
|
-
catalog[tool.value] = Object.fromEntries(commandContents.map((content, index) => [content.id, generatedCommands[index]?.fileContent]));
|
|
6546
|
-
}
|
|
6547
|
-
return catalog;
|
|
6548
|
-
} catch {
|
|
6549
|
-
return null;
|
|
6550
|
-
}
|
|
6551
|
-
}
|
|
6552
|
-
|
|
6553
|
-
//#endregion
|
|
6554
|
-
//#region src/tool-init-state.ts
|
|
6555
|
-
/**
|
|
6556
|
-
* Orthogonal intents (updated 2026-08-01 Asia/Shanghai):
|
|
6557
|
-
* 1. Project the unified OpenSpec 1.7 Agent registry into exact skill and command artifact state.
|
|
6558
|
-
* 2. Report partial, stale-version, cleanup-needed, migration-required, and unavailable states from physical evidence.
|
|
6559
|
-
* 3. Preserve bounded reactive directory observation and fresh one-shot cache invalidation.
|
|
6560
|
-
* 4. Expose Codex managed-global-prompt observation without treating those prompts as current commands.
|
|
6561
|
-
*
|
|
6562
|
-
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
6563
|
-
*/
|
|
6564
|
-
/** Pinned source version used when a runtime CLI version is not supplied by the Server owner. */
|
|
6565
|
-
const PINNED_AGENT_GENERATOR_VERSION = "1.7.0";
|
|
6566
|
-
const ALL_TOOL_WORKFLOWS = [...OPSX_ALL_WORKFLOWS];
|
|
6567
|
-
function toKnownWorkflows(workflows) {
|
|
6568
|
-
return workflows.filter((workflow) => workflow in OPSX_WORKFLOW_TO_SKILL_DIR);
|
|
6569
|
-
}
|
|
6570
|
-
function resolveCodexHome() {
|
|
6571
|
-
const configuredHome = process.env.CODEX_HOME?.trim();
|
|
6572
|
-
return resolve(configuredHome ? configuredHome : join$1(homedir(), ".codex"));
|
|
6573
|
-
}
|
|
6574
|
-
/** Return the external directory containing allowlisted managed legacy Codex prompts. */
|
|
6575
|
-
function getExternalCodexCommandObservationRoot() {
|
|
6576
|
-
return join$1(resolveCodexHome(), "prompts");
|
|
6577
|
-
}
|
|
6578
|
-
function resolveCommandArtifact(projectDir, tool, workflow, rootOverride) {
|
|
6579
|
-
if (!tool.command) return null;
|
|
6580
|
-
const rebase = (pathTemplate) => {
|
|
6581
|
-
if (!rootOverride || !tool.skillsDir || !pathTemplate.startsWith(`${tool.skillsDir}/`)) return pathTemplate;
|
|
6582
|
-
return `${rootOverride}${pathTemplate.slice(tool.skillsDir.length)}`;
|
|
6583
|
-
};
|
|
6584
|
-
return {
|
|
6585
|
-
workflow,
|
|
6586
|
-
path: resolve(projectDir, resolveAgentCommandPathTemplate(rebase(tool.command.pathTemplate), workflow)),
|
|
6587
|
-
legacyPaths: tool.command.legacyPathTemplates?.map((pathTemplate) => resolve(projectDir, resolveAgentCommandPathTemplate(rebase(pathTemplate), workflow)))
|
|
6588
|
-
};
|
|
6589
|
-
}
|
|
6590
|
-
function getSkillArtifacts(projectDir, skillsDir, workflows = ALL_TOOL_WORKFLOWS) {
|
|
6591
|
-
return workflows.map((workflow) => ({
|
|
6592
|
-
workflow,
|
|
6593
|
-
path: resolve(projectDir, skillsDir, "skills", OPSX_WORKFLOW_TO_SKILL_DIR[workflow], "SKILL.md")
|
|
6594
|
-
}));
|
|
6595
|
-
}
|
|
6596
|
-
function getCommandArtifacts(projectDir, tool, rootOverride) {
|
|
6597
|
-
return ALL_TOOL_WORKFLOWS.flatMap((workflow) => {
|
|
6598
|
-
const artifact = resolveCommandArtifact(projectDir, tool, workflow, rootOverride);
|
|
6599
|
-
return artifact ? [artifact] : [];
|
|
6600
|
-
});
|
|
6601
|
-
}
|
|
6602
|
-
function invalidateToolInitCaches(projectDir) {
|
|
6603
|
-
const cacheRoots = new Set([resolve(projectDir), getExternalCodexCommandObservationRoot()]);
|
|
6604
|
-
for (const tool of AI_TOOLS) {
|
|
6605
|
-
if (tool.skillsDir) cacheRoots.add(resolve(projectDir, tool.skillsDir));
|
|
6606
|
-
for (const migration of tool.migrations ?? []) cacheRoots.add(resolve(projectDir, migration.from));
|
|
6607
|
-
for (const commandArtifact of getCommandArtifacts(projectDir, tool)) {
|
|
6608
|
-
cacheRoots.add(dirname$1(commandArtifact.path));
|
|
6609
|
-
for (const legacyPath of commandArtifact.legacyPaths ?? []) cacheRoots.add(dirname$1(legacyPath));
|
|
6610
|
-
}
|
|
6611
|
-
}
|
|
6612
|
-
for (const root of cacheRoots) clearCache(root);
|
|
6613
|
-
}
|
|
6614
|
-
async function readArtifactDirectory(dir) {
|
|
6615
|
-
return new Set(await reactiveReadDir(dir, { includeHidden: true }));
|
|
6616
|
-
}
|
|
6617
|
-
async function getExistingSkillPaths(projectDir, skillsDir, entries, projectRootEntries) {
|
|
6618
|
-
const toolRoot = resolve(projectDir, skillsDir);
|
|
6619
|
-
if (!projectRootEntries.has(basename(toolRoot))) return /* @__PURE__ */ new Set();
|
|
6620
|
-
if (!(await readArtifactDirectory(toolRoot)).has("skills")) return /* @__PURE__ */ new Set();
|
|
6621
|
-
const rootEntries = await readArtifactDirectory(resolve(toolRoot, "skills"));
|
|
6870
|
+
async function getExistingInventorySkillPaths(inventoryRoot, entries) {
|
|
6871
|
+
const rootEntries = await readArtifactDirectory(inventoryRoot);
|
|
6622
6872
|
const presentEntries = entries.filter((entry) => rootEntries.has(basename(dirname$1(entry.path))));
|
|
6623
6873
|
const directoryEntries = await Promise.all(presentEntries.map(async (entry) => ({
|
|
6624
6874
|
entry,
|
|
@@ -6626,6 +6876,12 @@ async function getExistingSkillPaths(projectDir, skillsDir, entries, projectRoot
|
|
|
6626
6876
|
})));
|
|
6627
6877
|
return new Set(directoryEntries.filter(({ entry, files }) => files.has(basename(entry.path))).map(({ entry }) => entry.path));
|
|
6628
6878
|
}
|
|
6879
|
+
async function getExistingSkillPaths(projectDir, skillsDir, entries, projectRootEntries) {
|
|
6880
|
+
const toolRoot = resolve(projectDir, skillsDir);
|
|
6881
|
+
if (!projectRootEntries.has(basename(toolRoot))) return /* @__PURE__ */ new Set();
|
|
6882
|
+
if (!(await readArtifactDirectory(toolRoot)).has("skills")) return /* @__PURE__ */ new Set();
|
|
6883
|
+
return getExistingInventorySkillPaths(resolve(toolRoot, "skills"), entries);
|
|
6884
|
+
}
|
|
6629
6885
|
async function getExistingCommandPaths(entries) {
|
|
6630
6886
|
const pathsByDirectory = /* @__PURE__ */ new Map();
|
|
6631
6887
|
for (const entry of entries) for (const path of [entry.path, ...entry.legacyPaths ?? []]) {
|
|
@@ -6755,7 +7011,7 @@ async function collectCleanup(projectDir, tool, projectRootEntries) {
|
|
|
6755
7011
|
kind: projectCleanup$1.paths.length > 0 && globalCleanup ? "mixed" : globalCleanup ? "managed-global-prompts" : "project-artifacts",
|
|
6756
7012
|
paths,
|
|
6757
7013
|
workflows,
|
|
6758
|
-
replacementLabel: globalCleanup?.replacementLabel ?? "OpenSpec 1.
|
|
7014
|
+
replacementLabel: globalCleanup?.replacementLabel ?? "OpenSpec 1.9 Agent delivery"
|
|
6759
7015
|
};
|
|
6760
7016
|
}
|
|
6761
7017
|
async function collectMigrationEvidence(projectDir, tool, projectRootEntries) {
|
|
@@ -6790,14 +7046,17 @@ async function projectToolInitStates(projectDir, options) {
|
|
|
6790
7046
|
const desiredWorkflows = toKnownWorkflows(options.workflows);
|
|
6791
7047
|
const desiredWorkflowSet = new Set(desiredWorkflows);
|
|
6792
7048
|
const projectRootEntries = await readArtifactDirectory(projectDir);
|
|
6793
|
-
|
|
6794
|
-
|
|
7049
|
+
const officialRegistry = options.registry ?? AI_TOOLS;
|
|
7050
|
+
return Promise.all(officialRegistry.map(async (tool) => {
|
|
7051
|
+
const skillsScope = resolveToolSkillsScope(tool);
|
|
7052
|
+
if (!tool.available || skillsScope.kind === "none") return {
|
|
6795
7053
|
toolId: tool.value,
|
|
6796
7054
|
toolName: tool.name,
|
|
6797
7055
|
status: "unavailable",
|
|
6798
7056
|
readiness: "unavailable",
|
|
6799
7057
|
issues: [],
|
|
6800
7058
|
hasAnyArtifacts: false,
|
|
7059
|
+
commandSurfaceUnavailableReason: null,
|
|
6801
7060
|
expectedSkillCount: 0,
|
|
6802
7061
|
presentExpectedSkillCount: 0,
|
|
6803
7062
|
detectedSkillCount: 0,
|
|
@@ -6811,13 +7070,17 @@ async function projectToolInitStates(projectDir, options) {
|
|
|
6811
7070
|
legacyCommandWorkflows: [],
|
|
6812
7071
|
installedSkillWorkflows: [],
|
|
6813
7072
|
installedCommandWorkflows: [],
|
|
6814
|
-
generatedByVersion: null
|
|
7073
|
+
generatedByVersion: null,
|
|
7074
|
+
skillsScope,
|
|
7075
|
+
legacySkillRoots: [],
|
|
7076
|
+
requiresIdeRestart: tool.requiresIdeRestart === true
|
|
6815
7077
|
};
|
|
6816
7078
|
const shouldGenerateSkills = options.delivery !== "commands" || tool.capability === "skills-invocable";
|
|
6817
7079
|
const shouldGenerateCommands = options.delivery !== "skills" && tool.capability === "adapter-backed";
|
|
6818
|
-
const
|
|
6819
|
-
const
|
|
6820
|
-
const
|
|
7080
|
+
const inventoryRoot = skillsScope.kind === "user-global" ? resolveGlobalSkillsInventoryDir(skillsScope.globalSkillsDir) : resolve(projectDir, skillsScope.skillsDir, "skills");
|
|
7081
|
+
const skillArtifacts = getSkillArtifactsFromInventory(inventoryRoot);
|
|
7082
|
+
const commandArtifacts = skillsScope.kind === "user-global" ? [] : getCommandArtifacts(projectDir, tool);
|
|
7083
|
+
const existingSkillPaths = skillsScope.kind === "user-global" ? await getExistingInventorySkillPaths(inventoryRoot, skillArtifacts) : await getExistingSkillPaths(projectDir, skillsScope.skillsDir, skillArtifacts, projectRootEntries);
|
|
6821
7084
|
const existingCommandPaths = await getExistingCommandPaths(commandArtifacts);
|
|
6822
7085
|
const expectedSkillArtifacts = shouldGenerateSkills ? skillArtifacts.filter((entry) => desiredWorkflowSet.has(entry.workflow)) : [];
|
|
6823
7086
|
const expectedCommandArtifacts = shouldGenerateCommands ? commandArtifacts.filter((entry) => desiredWorkflowSet.has(entry.workflow)) : [];
|
|
@@ -6866,6 +7129,10 @@ async function projectToolInitStates(projectDir, options) {
|
|
|
6866
7129
|
installedSkillWorkflows,
|
|
6867
7130
|
installedCommandWorkflows,
|
|
6868
7131
|
generatedByVersion,
|
|
7132
|
+
skillsScope,
|
|
7133
|
+
legacySkillRoots: [...tool.legacySkillsDirs ?? []],
|
|
7134
|
+
requiresIdeRestart: tool.requiresIdeRestart === true,
|
|
7135
|
+
commandSurfaceUnavailableReason: options.unavailableCommandTools?.[tool.value] ?? null,
|
|
6869
7136
|
cleanup,
|
|
6870
7137
|
migration
|
|
6871
7138
|
};
|
|
@@ -6882,11 +7149,235 @@ function createToolInitStateProjection(projectDir, options) {
|
|
|
6882
7149
|
delivery: options.delivery,
|
|
6883
7150
|
workflows: [...options.workflows],
|
|
6884
7151
|
generatorVersion: options.generatorVersion,
|
|
6885
|
-
commandContents: options.commandContents
|
|
7152
|
+
commandContents: options.commandContents,
|
|
7153
|
+
unavailableCommandTools: options.unavailableCommandTools ?? null,
|
|
7154
|
+
registry: options.registry ? options.registry.map((tool) => ({ ...tool })) : void 0
|
|
6886
7155
|
};
|
|
6887
7156
|
return () => projectToolInitStates(projectDir, projectionOptions);
|
|
6888
7157
|
}
|
|
6889
7158
|
|
|
7159
|
+
//#endregion
|
|
7160
|
+
//#region src/tool-config.ts
|
|
7161
|
+
/**
|
|
7162
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
7163
|
+
* 1. Expose the unified OpenSpec 1.9 Agent delivery registry through the established Tool APIs.
|
|
7164
|
+
* 2. Detect configured project-local and user-global Agent roots reactively without duplicating registry metadata.
|
|
7165
|
+
*
|
|
7166
|
+
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
7167
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
7168
|
+
*/
|
|
7169
|
+
/** OpenSpec initialization generated skill directory names. */
|
|
7170
|
+
const SKILL_NAMES = [
|
|
7171
|
+
"openspec-explore",
|
|
7172
|
+
"openspec-new-change",
|
|
7173
|
+
"openspec-continue-change",
|
|
7174
|
+
"openspec-apply-change",
|
|
7175
|
+
"openspec-update-change",
|
|
7176
|
+
"openspec-ff-change",
|
|
7177
|
+
"openspec-sync-specs",
|
|
7178
|
+
"openspec-archive-change",
|
|
7179
|
+
"openspec-bulk-archive-change",
|
|
7180
|
+
"openspec-verify-change",
|
|
7181
|
+
"openspec-onboard",
|
|
7182
|
+
"openspec-propose"
|
|
7183
|
+
];
|
|
7184
|
+
/** Return registry entries available to OpenSpec init/update. */
|
|
7185
|
+
function getAvailableTools() {
|
|
7186
|
+
return AI_TOOLS.filter((tool) => tool.available);
|
|
7187
|
+
}
|
|
7188
|
+
/** Return available official Tool ids. */
|
|
7189
|
+
function getAvailableToolIds() {
|
|
7190
|
+
return getAvailableTools().map((tool) => tool.value);
|
|
7191
|
+
}
|
|
7192
|
+
/** Return the complete official registry, including unavailable pseudo-tools. */
|
|
7193
|
+
function getAllTools() {
|
|
7194
|
+
return AI_TOOLS;
|
|
7195
|
+
}
|
|
7196
|
+
/** Detect configured Agents using the official OpenSpec project and user-global detection rules. */
|
|
7197
|
+
async function getDetectedProjectTools(projectDir) {
|
|
7198
|
+
return (await Promise.all(AI_TOOLS.map(async (tool) => {
|
|
7199
|
+
if (tool.globalSkillsDir) {
|
|
7200
|
+
const inventoryRoot = resolveGlobalSkillsInventoryDir(tool.globalSkillsDir);
|
|
7201
|
+
return (await Promise.all(SKILL_NAMES.map((skillName) => reactiveExists(join$1(inventoryRoot, skillName, "SKILL.md"))))).some(Boolean) ? tool : null;
|
|
7202
|
+
}
|
|
7203
|
+
if (!tool.skillsDir) return null;
|
|
7204
|
+
if (tool.detectionPaths?.length) return (await Promise.all(tool.detectionPaths.map((detectionPath) => reactiveStat(join$1(projectDir, detectionPath))))).some((entry) => entry !== null) ? tool : null;
|
|
7205
|
+
return (await reactiveStat(join$1(projectDir, tool.skillsDir)))?.isDirectory === true ? tool : null;
|
|
7206
|
+
}))).filter((tool) => tool !== null);
|
|
7207
|
+
}
|
|
7208
|
+
/** Return every current official Tool id in registry order. */
|
|
7209
|
+
function getAllToolIds() {
|
|
7210
|
+
return AI_TOOLS.map((tool) => tool.value);
|
|
7211
|
+
}
|
|
7212
|
+
/** Resolve one current or retired Tool id to its official registry entry. */
|
|
7213
|
+
function getToolById(toolId) {
|
|
7214
|
+
const resolvedToolId = resolveAgentToolId(toolId);
|
|
7215
|
+
return AI_TOOLS.find((tool) => tool.value === resolvedToolId);
|
|
7216
|
+
}
|
|
7217
|
+
const stateCache = /* @__PURE__ */ new Map();
|
|
7218
|
+
const releaseCache = /* @__PURE__ */ new Map();
|
|
7219
|
+
function getSkillsDir(projectDir, tool) {
|
|
7220
|
+
if (tool.globalSkillsDir) return resolveGlobalSkillsInventoryDir(tool.globalSkillsDir);
|
|
7221
|
+
return tool.skillsDir ? join$1(projectDir, tool.skillsDir, "skills") : null;
|
|
7222
|
+
}
|
|
7223
|
+
async function getSkillCount(projectDir, tool) {
|
|
7224
|
+
const skillsDir = getSkillsDir(projectDir, tool);
|
|
7225
|
+
if (!skillsDir) return 0;
|
|
7226
|
+
let count = 0;
|
|
7227
|
+
for (const skillName of SKILL_NAMES) if (await reactiveExists(join$1(skillsDir, skillName, "SKILL.md"))) count++;
|
|
7228
|
+
return count;
|
|
7229
|
+
}
|
|
7230
|
+
async function scanConfiguredTools(projectDir) {
|
|
7231
|
+
return (await Promise.all(AI_TOOLS.map(async (tool) => {
|
|
7232
|
+
if (!tool.skillsDir && !tool.globalSkillsDir) return null;
|
|
7233
|
+
return await getSkillCount(projectDir, tool) > 0 ? tool.value : null;
|
|
7234
|
+
}))).filter((toolId) => toolId !== null);
|
|
7235
|
+
}
|
|
7236
|
+
function getProjectWatchDirs(projectDir) {
|
|
7237
|
+
const dirs = /* @__PURE__ */ new Set();
|
|
7238
|
+
for (const tool of AI_TOOLS) {
|
|
7239
|
+
if (tool.skillsDir) dirs.add(join$1(projectDir, tool.skillsDir));
|
|
7240
|
+
for (const migration of tool.migrations ?? []) dirs.add(join$1(projectDir, migration.from));
|
|
7241
|
+
}
|
|
7242
|
+
return [...dirs];
|
|
7243
|
+
}
|
|
7244
|
+
/** Detect configured Agents through a retained reactive projection. */
|
|
7245
|
+
async function getConfiguredTools(projectDir) {
|
|
7246
|
+
const normalizedPath = resolve(projectDir);
|
|
7247
|
+
const key = `tools:${normalizedPath}`;
|
|
7248
|
+
let state = stateCache.get(key);
|
|
7249
|
+
if (!state) {
|
|
7250
|
+
state = new ReactiveState(await scanConfiguredTools(normalizedPath), { equals: (left, right) => left.length === right.length && left.every((value, index) => value === right[index]) });
|
|
7251
|
+
stateCache.set(key, state);
|
|
7252
|
+
const releases = [];
|
|
7253
|
+
const onUpdate = async () => state?.set(await scanConfiguredTools(normalizedPath));
|
|
7254
|
+
for (const dir of getProjectWatchDirs(normalizedPath)) releases.push(acquireWatcher(dir, onUpdate, { recursive: true }));
|
|
7255
|
+
releases.push(acquireWatcher(normalizedPath, onUpdate, { recursive: false }));
|
|
7256
|
+
releaseCache.set(key, () => releases.forEach((release) => release()));
|
|
7257
|
+
}
|
|
7258
|
+
return state.get();
|
|
7259
|
+
}
|
|
7260
|
+
/** Check whether a current or retired Tool id resolves to configured skills. */
|
|
7261
|
+
async function isToolConfigured(projectDir, toolId) {
|
|
7262
|
+
return (await getConfiguredTools(projectDir)).includes(resolveAgentToolId(toolId));
|
|
7263
|
+
}
|
|
7264
|
+
|
|
7265
|
+
//#endregion
|
|
7266
|
+
//#region src/agent-delivery-policy.ts
|
|
7267
|
+
/**
|
|
7268
|
+
* Orthogonal intents (created 2026-08-01 Asia/Shanghai):
|
|
7269
|
+
* 1. Define the structured Agent profile, delivery, and workflow mutation contract.
|
|
7270
|
+
* 2. Normalize Core versus Custom workflow semantics exactly once.
|
|
7271
|
+
* 3. Preserve unknown environment-global JSON fields while updating official Agent policy keys.
|
|
7272
|
+
*
|
|
7273
|
+
* Original request (2026-08-01): keep raw environment config authoring while moving official Agent controls to Config.
|
|
7274
|
+
*/
|
|
7275
|
+
const AgentDeliveryProfileSchema = z.enum(["core", "custom"]);
|
|
7276
|
+
const AgentDeliveryModeSchema = z.enum([
|
|
7277
|
+
"both",
|
|
7278
|
+
"skills",
|
|
7279
|
+
"commands"
|
|
7280
|
+
]);
|
|
7281
|
+
const AgentDeliveryWorkflowSchema = z.enum(OPSX_ALL_WORKFLOWS);
|
|
7282
|
+
const AgentDeliveryPolicyUpdateSchema = z.object({
|
|
7283
|
+
profile: AgentDeliveryProfileSchema,
|
|
7284
|
+
delivery: AgentDeliveryModeSchema,
|
|
7285
|
+
workflows: z.array(AgentDeliveryWorkflowSchema)
|
|
7286
|
+
}).superRefine((value, context$1) => {
|
|
7287
|
+
if (new Set(value.workflows).size !== value.workflows.length) context$1.addIssue({
|
|
7288
|
+
code: "custom",
|
|
7289
|
+
message: "Agent workflows must be unique."
|
|
7290
|
+
});
|
|
7291
|
+
});
|
|
7292
|
+
/** Normalize authored policy through official omitted-value defaults and Core workflow semantics. */
|
|
7293
|
+
function normalizeAgentDeliveryPolicy(input) {
|
|
7294
|
+
const profile = input.profile === "custom" ? "custom" : "core";
|
|
7295
|
+
return {
|
|
7296
|
+
profile,
|
|
7297
|
+
delivery: input.delivery === "skills" || input.delivery === "commands" ? input.delivery : "both",
|
|
7298
|
+
workflows: profile === "core" ? [...OPSX_CORE_PROFILE_WORKFLOWS] : OPSX_ALL_WORKFLOWS.filter((workflow) => input.workflows?.includes(workflow))
|
|
7299
|
+
};
|
|
7300
|
+
}
|
|
7301
|
+
/** Update only official Agent policy keys while retaining every team-authored extension field. */
|
|
7302
|
+
function applyAgentDeliveryPolicy(config, update) {
|
|
7303
|
+
const policy = normalizeAgentDeliveryPolicy(update);
|
|
7304
|
+
return {
|
|
7305
|
+
...config,
|
|
7306
|
+
profile: policy.profile,
|
|
7307
|
+
delivery: policy.delivery,
|
|
7308
|
+
workflows: policy.workflows
|
|
7309
|
+
};
|
|
7310
|
+
}
|
|
7311
|
+
|
|
7312
|
+
//#endregion
|
|
7313
|
+
//#region src/agent-command-content.ts
|
|
7314
|
+
/**
|
|
7315
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
7316
|
+
* 1. Resolve the running OpenSpec CLI's private command-generation boundary without bundling copied prompts.
|
|
7317
|
+
* 2. Produce exact per-Agent, per-workflow command contents for physical fingerprint comparison.
|
|
7318
|
+
* 3. Fail closed when the configured runner has no importable OpenSpec module or compatible generator contract.
|
|
7319
|
+
* 4. Isolate per-tool adapter absence as version-scoped unavailability, keeping unrelated evidence.
|
|
7320
|
+
*
|
|
7321
|
+
* Original request (2026-08-01): adapt the complete OpenSpec 1.7 Agent delivery protocol for OpenSpecUI 7.
|
|
7322
|
+
|
|
7323
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
7324
|
+
*/
|
|
7325
|
+
const KNOWN_WORKFLOWS = new Set(OPSX_ALL_WORKFLOWS);
|
|
7326
|
+
function isRecord(value) {
|
|
7327
|
+
return typeof value === "object" && value !== null;
|
|
7328
|
+
}
|
|
7329
|
+
function isRuntimeSkillGenerationModule(value) {
|
|
7330
|
+
return isRecord(value) && typeof value.getCommandContents === "function";
|
|
7331
|
+
}
|
|
7332
|
+
function isRuntimeCommandAdapterRegistry(value) {
|
|
7333
|
+
if (typeof value !== "object" && typeof value !== "function" || value === null) return false;
|
|
7334
|
+
return "get" in value && typeof value.get === "function";
|
|
7335
|
+
}
|
|
7336
|
+
function isRuntimeCommandGenerationModule(value) {
|
|
7337
|
+
return isRecord(value) && isRuntimeCommandAdapterRegistry(value.CommandAdapterRegistry) && typeof value.generateCommands === "function";
|
|
7338
|
+
}
|
|
7339
|
+
function isRuntimeCommandContent(value) {
|
|
7340
|
+
return isRecord(value) && typeof value.id === "string" && KNOWN_WORKFLOWS.has(value.id);
|
|
7341
|
+
}
|
|
7342
|
+
function isRuntimeGeneratedCommand(value) {
|
|
7343
|
+
return isRecord(value) && typeof value.fileContent === "string";
|
|
7344
|
+
}
|
|
7345
|
+
/**
|
|
7346
|
+
* Load exact command contents from the configured OpenSpec CLI.
|
|
7347
|
+
*
|
|
7348
|
+
* The private generator is intentionally treated as optional evidence. When the runner is not an
|
|
7349
|
+
* importable local OpenSpec module, callers receive `null` and commands-only installs cannot be
|
|
7350
|
+
* declared current from path existence alone.
|
|
7351
|
+
*/
|
|
7352
|
+
async function loadOpenSpecAgentCommandContents(cliCommand, workflows) {
|
|
7353
|
+
try {
|
|
7354
|
+
const cliModuleDir = dirname$1((await resolveOpenSpecWorkerInvocation(cliCommand)).modulePath);
|
|
7355
|
+
const [skillGenerationModule, commandGenerationModule] = await Promise.all([import(pathToFileURL(resolve(cliModuleDir, "../core/shared/skill-generation.js")).href), import(pathToFileURL(resolve(cliModuleDir, "../core/command-generation/index.js")).href)]);
|
|
7356
|
+
if (!isRuntimeSkillGenerationModule(skillGenerationModule) || !isRuntimeCommandGenerationModule(commandGenerationModule)) return null;
|
|
7357
|
+
const commandContents = skillGenerationModule.getCommandContents(workflows);
|
|
7358
|
+
if (!Array.isArray(commandContents) || !commandContents.every(isRuntimeCommandContent)) return null;
|
|
7359
|
+
const catalog = {};
|
|
7360
|
+
const unavailableTools = {};
|
|
7361
|
+
for (const tool of AGENT_DELIVERY_REGISTRY) {
|
|
7362
|
+
if (!tool.command) continue;
|
|
7363
|
+
const adapter = commandGenerationModule.CommandAdapterRegistry.get(tool.value);
|
|
7364
|
+
if (!adapter) {
|
|
7365
|
+
unavailableTools[tool.value] = tool.minCliSeries !== void 0 ? `Command adapter first ships with OpenSpec CLI ${tool.minCliSeries}; this runner does not declare it.` : "This OpenSpec CLI runner does not register the command adapter.";
|
|
7366
|
+
continue;
|
|
7367
|
+
}
|
|
7368
|
+
const generatedCommands = commandGenerationModule.generateCommands(commandContents, adapter);
|
|
7369
|
+
if (!Array.isArray(generatedCommands) || generatedCommands.length !== commandContents.length || !generatedCommands.every(isRuntimeGeneratedCommand)) return null;
|
|
7370
|
+
catalog[tool.value] = Object.fromEntries(commandContents.map((content, index) => [content.id, generatedCommands[index]?.fileContent]));
|
|
7371
|
+
}
|
|
7372
|
+
return {
|
|
7373
|
+
catalog,
|
|
7374
|
+
unavailableTools
|
|
7375
|
+
};
|
|
7376
|
+
} catch {
|
|
7377
|
+
return null;
|
|
7378
|
+
}
|
|
7379
|
+
}
|
|
7380
|
+
|
|
6890
7381
|
//#endregion
|
|
6891
7382
|
//#region src/hooks.ts
|
|
6892
7383
|
const OPENSPECUI_DOCUMENT_HOOK_VERSION = 1;
|
|
@@ -7039,17 +7530,16 @@ async function mapCliProjectionSeries(inputs, project) {
|
|
|
7039
7530
|
//#endregion
|
|
7040
7531
|
//#region src/opsx-kernel.ts
|
|
7041
7532
|
/**
|
|
7042
|
-
* Orthogonal intents (updated 2026-08-
|
|
7533
|
+
* Orthogonal intents (updated 2026-08-15 Asia/Shanghai):
|
|
7043
7534
|
* 1. Maintain reactive CLI-backed projections and their direct typed Projection Work readers.
|
|
7044
7535
|
* 2. Share and release per-entity streams through one planning-root kernel lifecycle.
|
|
7045
7536
|
* 3. Keep OpenSpec configuration ownership outside the workflow cache while tracking both YAML filename variants.
|
|
7046
7537
|
* 4. Preserve typed Status and Artifact/Apply/Archive Instructions provenance with the resolved root selector.
|
|
7047
|
-
* 5.
|
|
7538
|
+
* 5. Resolve per-command CLI capabilities once per lifetime and gate version-only selectors behind admission.
|
|
7048
7539
|
*
|
|
7049
7540
|
* Original request (2026-07-15): "Planning-root adapters and services consume the CLI-resolved root."
|
|
7050
|
-
* Original request (2026-07-23): "OPSX Status 不应等待完整 Kernel warmup,且必须保留 CLI evidence。"
|
|
7051
|
-
* Original request (2026-07-26): "展开全面的接口升级和内核升级和测试升级。"
|
|
7052
7541
|
* Original request (2026-07-31): "系统性地进行修复,因为List页面也有类似的问题。所有可能其它页面都有类似的问题。"
|
|
7542
|
+
* Original request (2026-08-15): "v9的适配需要同时适配 1.8和1.9。"
|
|
7053
7543
|
*/
|
|
7054
7544
|
function toRelativePath(root, absolutePath) {
|
|
7055
7545
|
return relative(root, absolutePath).split(sep).join("/");
|
|
@@ -7202,6 +7692,7 @@ var OpsxKernel = class {
|
|
|
7202
7692
|
cliExecutor;
|
|
7203
7693
|
runtimeInvalidation;
|
|
7204
7694
|
rootSelector;
|
|
7695
|
+
cliCapabilitiesPromise = null;
|
|
7205
7696
|
controller = new AbortController();
|
|
7206
7697
|
warmupPromise = null;
|
|
7207
7698
|
_streamReady = /* @__PURE__ */ new Map();
|
|
@@ -7524,15 +8015,28 @@ var OpsxKernel = class {
|
|
|
7524
8015
|
clearStreamReadyByPrefix(prefix) {
|
|
7525
8016
|
for (const key of this._streamReady.keys()) if (key.startsWith(prefix)) this._streamReady.delete(key);
|
|
7526
8017
|
}
|
|
8018
|
+
/**
|
|
8019
|
+
* Resolve the admitted CLI's per-command capabilities once per Kernel lifetime.
|
|
8020
|
+
*
|
|
8021
|
+
* The detected version decides whether version-specific selectors and options are forwarded.
|
|
8022
|
+
* A failed availability probe yields no capabilities, so no version-only flag is ever sent
|
|
8023
|
+
* to an unverifiable CLI.
|
|
8024
|
+
*/
|
|
8025
|
+
resolveCliCapabilities() {
|
|
8026
|
+
this.cliCapabilitiesPromise ??= this.cliExecutor.checkAvailability().then((availability) => deriveOpenSpecCliCapabilities(availability.available ? parseOpenSpecCliVersion(availability.version) : null)).catch(() => deriveOpenSpecCliCapabilities(null));
|
|
8027
|
+
return this.cliCapabilitiesPromise;
|
|
8028
|
+
}
|
|
7527
8029
|
async fetchSchemas() {
|
|
7528
8030
|
return (await this.fetchSchemasProjection()).value;
|
|
7529
8031
|
}
|
|
7530
8032
|
async fetchSchemasProjection() {
|
|
7531
8033
|
this.runtimeInvalidation.track("schemas");
|
|
7532
8034
|
await touchOpsxProjectDeps(this.projectDir);
|
|
7533
|
-
const
|
|
8035
|
+
const schemasSelector = (await this.resolveCliCapabilities()).schemasRootSelector ? { ...this.rootSelector } : {};
|
|
8036
|
+
const result = await this.cliExecutor.contracts.schemas(schemasSelector);
|
|
8037
|
+
if (result.data && isCliSchemasFailure(result.data)) throw new CliProjectionCommandError(result.data.status.map((diagnostic) => diagnostic.message).join("\n") || "openspec schemas failed to select a Root.", result);
|
|
7534
8038
|
return {
|
|
7535
|
-
value: requireCommandData("openspec schemas", result,
|
|
8039
|
+
value: requireCommandData("openspec schemas", result, CliSchemasSuccessSchema),
|
|
7536
8040
|
evidence: toCliProjectionCommandEvidence(result)
|
|
7537
8041
|
};
|
|
7538
8042
|
}
|
|
@@ -7546,8 +8050,10 @@ var OpsxKernel = class {
|
|
|
7546
8050
|
async fetchChangeListProjection() {
|
|
7547
8051
|
await this.fetchChangeIds();
|
|
7548
8052
|
const result = await this.cliExecutor.contracts.listChanges(this.rootSelector);
|
|
8053
|
+
const data = requireCommandData("openspec list", result, CliChangeListSchema);
|
|
7549
8054
|
return {
|
|
7550
|
-
value:
|
|
8055
|
+
value: data.changes.map(({ name }) => name),
|
|
8056
|
+
entries: data.changes,
|
|
7551
8057
|
evidence: toCliProjectionCommandEvidence(result)
|
|
7552
8058
|
};
|
|
7553
8059
|
}
|
|
@@ -7563,7 +8069,7 @@ var OpsxKernel = class {
|
|
|
7563
8069
|
const status = ChangeStatusSchema.parse({
|
|
7564
8070
|
changeName: data.changeName,
|
|
7565
8071
|
schemaName: data.schemaName,
|
|
7566
|
-
|
|
8072
|
+
isPlanningComplete: data.isPlanningComplete,
|
|
7567
8073
|
applyRequires: data.applyRequires,
|
|
7568
8074
|
artifacts: data.artifacts,
|
|
7569
8075
|
provenance: {
|
|
@@ -7733,7 +8239,11 @@ var OpsxKernel = class {
|
|
|
7733
8239
|
readStatusProjection(changeId, schema) {
|
|
7734
8240
|
return this.fetchStatus(changeId, schema);
|
|
7735
8241
|
}
|
|
7736
|
-
/**
|
|
8242
|
+
/**
|
|
8243
|
+
* Execute CLI-owned Change enumeration with file dependencies owned by the caller's Work
|
|
8244
|
+
* generation. `entries` carries the CLI's own per-Change task counts and phase so list
|
|
8245
|
+
* surfaces can show CLI-reported progress without UI-side file arithmetic.
|
|
8246
|
+
*/
|
|
7737
8247
|
readChangeListProjection() {
|
|
7738
8248
|
return this.fetchChangeListProjection();
|
|
7739
8249
|
}
|
|
@@ -8085,4 +8595,4 @@ const PtyServerMessageSchema = z.discriminatedUnion("type", [
|
|
|
8085
8595
|
]);
|
|
8086
8596
|
|
|
8087
8597
|
//#endregion
|
|
8088
|
-
export { ACCESS_GATE_CREDENTIAL_BYTES, AI_TOOLS, ActiveRootMutationSchema, ActiveRootOfficialConfigSchema, ActiveRootRevisionSchema, ActiveRootStructuredUpdateSchema, AgentDeliveryModeSchema, AgentDeliveryPolicyUpdateSchema, AgentDeliveryProfileSchema, AgentDeliveryWorkflowSchema, ApplyInstructionsContextFilesSchema, ApplyInstructionsProjectionSchema, ApplyInstructionsSchema, ApplyTaskSchema, ArchiveInstructionsSchema, ArtifactInstructionsSchema, ArtifactStatusSchema, BUILTIN_SOUND_IDS, BUILTIN_SOUND_OPTIONS, BUILTIN_TERMINAL_SPAWN_COMMANDS, BatchTranslateEventSchema, BatchTranslateInputSchema, BuiltinSoundIdSchema, CODE_EDITOR_THEME_VALUES, CUSTOM_SOUND_ADD_VALUE, ChangeFileSchema, ChangeSchema, ChangeStatusSchema, CliApplyInstructionsSchema, CliArchiveInstructionsSchema, CliArchiveSchema, CliArtifactInstructionsSchema, CliChangeListSchema, CliContextSchema, CliDiagnosticFailureSchema, CliDiagnosticSchema, CliDoctorReferenceEntrySchema, CliDoctorSchema, CliExecutor, CliJsonValueSchema, CliProjectionCommandError, CliProjectionCommandEvidenceSchema, CliProjectionFailureSchema, CliProjectionInvalidationCauseSchema, CliProjectionNoticeSchema, CliProjectionStateNameSchema, CliReferenceIndexEntrySchema, CliRootSchema, CliRootSourceSchema, CliShowSpecDocumentSchema, CliShowSpecSchema, CliSpecListSchema, CliStoreCleanupSchema, CliStoreDoctorEntrySchema, CliStoreDoctorSchema, CliStoreListSchema, CliStoreMutationSchema, CliStoreSchema, CliStreamTerminationError, CliValidateSchema, CliWorkflowStatusSchema, CodeEditorThemeSchema, ConfigManager, CustomSoundHashSchema, CustomSoundIdSchema, CustomSoundMetadataFileSchema, CustomSoundMetadataSchema, DASHBOARD_METRIC_KEYS, DEFAULT_BELL_SOUND_ID, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, DEFAULT_GLOBAL_SETTINGS, DEFAULT_NOTIFICATION_SOUND_ID, DEFAULT_TERMINAL_DARK_THEME, DEFAULT_TERMINAL_LIGHT_THEME, DEFAULT_TERMINAL_THEME_MODE, DEFAULT_TRANSLATION_CACHE_ENTRY_LIMIT, DEFAULT_TRANSLATION_ENGINE_ID, DOCUMENT_TRANSLATION_DISPLAY_MODES, DashboardConfigSchema, DashboardGitSnapshotSchema, DashboardOverviewSchema, DashboardSummaryIdentitySchema, DashboardSummaryInvalidationCauseSchema, DashboardSummaryInvalidationSchema, DashboardSummaryProjectionSchema, DashboardSummaryProjectionStateSchema, DashboardTrendsProjectionSchema, DeltaOperationType, DeltaSchema, DeltaSpecSchema, DependencyInfoSchema, DocumentTranslationConfigSchema, DocumentTranslationConfigUpdateSchema, DocumentTranslationDisplayModeSchema, DocumentTranslationGlobalSettingsUpdateSchema, EnvironmentDefaultStoreUpdateSchema, EnvironmentGlobalConfigValueSchema, EnvironmentGlobalFileProjectionDataSchema, EnvironmentGlobalFileProjectionStateSchema, EnvironmentGlobalProjectionDataSchema, EnvironmentGlobalProjectionStateSchema, FILE_PREVIEW_KINDS, GitConfigSchema, GlobalSettingsManager, HOSTED_SHELL_PROTOCOL_VERSION, LEGACY_SOUND_ID_MAP, LOCAL_MODEL_PROFILE_DEFINITIONS, LocalModelAssetLogSchema, LocalModelAssetPlanSnapshotSchema, LocalModelAssetStateSchema, LocalModelDownloadStatusSchema, LocalModelLifecycleFileStateSchema, LocalModelLifecycleGroupStateSchema, LocalModelProfileLoadStateSchema, LocalModelProfileManifestFileSchema, LocalModelProfileManifestGroupSchema, LocalModelProfileManifestSchema, LocalModelProfileStatusSchema, MAX_ACTIVE_ROOT_CONTEXT_BYTES, MAX_TRANSLATION_CACHE_ENTRY_LIMIT, MIN_TRANSLATION_CACHE_ENTRY_LIMIT, ManagedLocalCatalogSourceSchema, MarkdownParser, MarkdownReadingPluginRegistry, NOTIFICATION_SOUND_OPTIONS, NOTIFICATION_SOUND_VALUES, NotificationActionSchema, NotificationGroupKeySchema, NotificationPublishInputSchema, NotificationRecordSchema, NotificationSettingsSchema, NotificationSoundSchema, NotificationSourceSchema, OFFICIAL_APP_BASE_URL, OPENSPECUI_DOCUMENT_HOOK_VERSION, OPENSPECUI_RUNTIME_CAPABILITIES, OPENSPECUI_WORKFLOW_HOOK_VERSION, OPENSPEC_SPAWN_MODE_ENV, OPEN_SPEC_DATA_DIRECTORY_NAME, OPEN_SPEC_DATA_HOME_OBSERVATION_TARGETS, OPEN_SPEC_READING_SECTIONS_PROJECTION_ID, OPEN_SPEC_SPEC_PROJECTION_ID, OPSX_AGENT_INVOCATION_MODE_VALUES, OPSX_ALL_WORKFLOWS, OPSX_ARTIFACT_INPUT_ACTIONS, OPSX_CHANGE_INPUT_ACTIONS, OPSX_COMMAND_CAPABLE_WORKFLOWS, OPSX_CORE_PROFILE_WORKFLOWS, OPSX_TEXT_INPUT_ACTIONS, OPSX_WORKFLOW_LABELS, OPSX_WORKFLOW_TO_SKILL_DIR, OPSX_WORKFLOW_TO_SKILL_DIR as TOOL_WORKFLOW_TO_SKILL_DIR, OpenSpecAdapter, OpenSpecCliContractExecutor, OpenSpecDataHomeObserver, OpenSpecUIConfigSchema, OpenSpecUIGlobalSettingsSchema, OpenSpecUIGlobalSettingsUpdateSchema, OpenSpecWatcher, OpsxAgentInvocationModeSchema, OpsxCliEvidenceSchema, OpsxConfigBundleSchema, OpsxConfigSchema, OpsxKernel, OpsxStatusEvidenceSchema, OwnedSpecIdentitySchema, PINNED_AGENT_GENERATOR_VERSION, PlanningCliProjectionDataSchema, PlanningCliProjectionSelectorSchema, PlanningCliProjectionStateSchema, PlanningConfigJsonValueSchema, PlanningConfigReferenceSchema, ProjectBindingUpdateSchema, ProjectWatcher, PtyAttachMessageSchema, PtyBellResponseSchema, PtyBufferResponseSchema, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, PtyPlatformSchema, PtyProcessTitleResponseSchema, PtyResizeMessageSchema, PtyServerMessageSchema, PtyTitleResponseSchema, RUNTIME_INVALIDATION_FACETS, ReactiveContext, ReactiveObservationEnvironment, ReactiveState, ReferencedSpecIdentitySchema, RequirementSchema, RuntimeInvalidationIndex, RuntimeRootInvalidationRegistry, SERVE_PRESENTATION_MODES, SERVICE_TRANSLATION_ENGINE_IDS, SILENT_SOUND_ID, ScenarioStepKeywordSchema, ScenarioStepSchema, SchemaArtifactSchema, SchemaDetailSchema, SchemaInfoSchema, SchemaResolutionSchema, ServePresentationModeSchema, ServiceTranslationEngineIdSchema, SoundConfigIdSchema, SoundIdSchema, SpecCatalogSchema, SpecCommandEvidenceSchema, SpecDocumentProjectionSchema, SpecIdentitySchema, SpecSchema, StoreDoctorResultSchema, StoreListResultSchema, StoreMutationLifecycleEventSchema, StoreMutationResultSchema, StoreMutationSchema, StoreMutationStartResponseSchema, TERMINAL_BELL_SOUND_OPTIONS, TERMINAL_BELL_SOUND_VALUES, TERMINAL_COMMAND_FIELD_TYPE_VALUES, TERMINAL_SHELL_QUOTE_STYLE_VALUES, TERMINAL_THEME_MODE_VALUES, TERMINAL_THEME_VALUES, TRANSLATION_CACHE_POLICY_VERSION, TRANSLATION_ENGINE_IDS, TRANSLATION_ENGINE_MANIFESTS, TRANSLATOR_CONTRACT_VERSION, TaskSchema, TemplateContentMapSchema, TemplateContentSchema, TemplatesSchema, TerminalBellSoundSchema, TerminalCommandFieldSchema, TerminalConfigSchema, TerminalControlParser, TerminalCwdTargetSchema, TerminalInvocationSettingsSchema, TerminalNotificationParser, TerminalRendererEngineSchema, TerminalShellProfileSchema, TerminalShellQuoteStyleSchema, TerminalSpawnCommandSchema, TerminalThemeModeSchema, TerminalThemeSchema, TrackedTaskProgressSchema, TranslationCacheEntrySchema, TranslationCacheReadInputSchema, TranslationCacheSettingsSchema, TranslationCacheSettingsUpdateSchema, TranslationCacheStatsSchema, TranslationCacheWriteInputSchema, TranslationDownloadFilePlanSchema, TranslationDownloadGroupPlanSchema, TranslationEngineAssetStateSchema, TranslationEngineAssetStatusSchema, TranslationEngineDependencyStateSchema, TranslationEngineDependencyStatusSchema, TranslationEngineGlobalSettingsSchema, TranslationEngineGlobalSettingsUpdateSchema, TranslationEngineIdSchema, TranslationEngineInstallLogEventSchema, TranslationEngineInstallLogStreamSchema, TranslationEngineLifecycleEventSchema, TranslationEngineLifecycleStatusSchema, TranslationEngineProjectSettingsSchema, TranslationEngineProjectSettingsUpdateSchema, TranslationEngineRuntimeStateSchema, TranslationEngineRuntimeStatusSchema, TranslationLocalCt2SettingsSchema, TranslationLocalCt2SettingsUpdateSchema, TranslationLocalLlamaSettingsSchema, TranslationLocalLlamaSettingsUpdateSchema, TranslationLocalSettingsSchema, TranslationLocalSettingsUpdateSchema, TranslationOpenAISettingsSchema, TranslationOpenAISettingsUpdateSchema, VIRTUAL_PROJECT_DIRNAME, Validator, accessGateFingerprint, acquireWatcher, acquireWatcherRoot, annotateOpenSpecFacts, annotateOpenSpecMarkdown, applyAgentDeliveryPolicy, asEnvUri, buildBackendHealthPayload, buildCliRunnerCandidates, buildEmbeddedUiLaunchUrl, buildHostedLaunchUrl, buildLocalDownloadPlanFromRepositoryFiles, buildLocalDownloadPlanFromRuntimeProfileFiles, buildMarkdownParentMap, buildOpsxEntityDetail, buildRuntimePackageInstallCommand, buildSpecCatalog, builtinOpenSpecReadingPlugin, checkLocalDirectionalModelLanguagePair, classifyStoreCliResult, clearCache, cliProjectionStates, closeAllProjectWatchers, closeAllWatchers, compareAndWriteAtomicPhysicalReactiveFile, computeEnvUri, constantTimeEqual, contextStorage, createApplyInstructionProgress, createCleanCliEnv, createCliProjectionStateSchema, createDocumentChecklistSummary, createFileChangeObservable, createMarkdownReadingDocument, createMarkdownReadingDocumentFromFacts, createOpenSpecReadingPlugin, createPhysicalReactiveDirectory, createStaticSpecCatalogOwnedProjection, createStaticSpecCatalogReferenceProjection, createStaticSpecCatalogReferenceSource, createToolInitStateProjection, createTrackedTaskProgress, createTranslationEngineLifecycleStatus, customHashFromSoundId, deriveTrackedTaskPhase, detectRuntimePackageManager, generateAccessGateCredential, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getBuiltinSoundUrl, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDefaultGlobalSettingsPath, getDetectedProjectTools, getExternalCodexCommandObservationRoot, getManagedLocalTranslationEngineManifest, getMarkdownAnnotation, getMarkdownAnnotationsForFact, getMarkdownFactSpan, getMarkdownHeadingEnd, getMarkdownHeadingFacts, getNotificationGroupKey, getNotificationGroupLabel, getOpenSpecAnnotation, getOpenSpecAnnotationsForFact, getOpenSpecProjectionAnnotation, getOpenSpecReadingSections, getOpsxEntityMetadataPath, getOpsxEntityRootRelativePath, getProjectWatcher, getRootContextCliSelector, getSpecCatalogEntry, getTerminalCommandDefaultValues, getToolById, getToolInitStates, getTranslationEngineLifecycleMessage, getTranslationEngineManifest, getWatcherRuntimeStatus, groupNotifications, hasCapability, inferFileMime, inferFilePreviewKind, inferLocalDirectionalModelLanguagePair, inspectActiveRootOfficialConfig, inspectEnvironmentDefaultStore, inspectProjectBinding, isBackendHealthRuntimeMetadata, isBatchTranslationAbort, isDirectionalManagedLocalTranslationEngineId, isGlobPattern, isHostedBackendHealthResponse, isManagedLocalTranslationEngineId, isMarkdownTaskSourcePath, isOpsxCoreWorkflowSelection, isOpsxGlobPattern, isPreviewableFile, isReferencedSpecIdentity, isSupportedEmbeddedUiUrl, isTerminalMutationStatus, isTerminalRendererEngine, isTextLikeFile, isTextLikeMime, isToolConfigured, isTranslationEngineDependencyReady, isTranslationEngineRuntimeReady, isWatcherPoolInitialized, loadOpenSpecAgentCommandContents, mergeSpecCatalog, normalizeAccessGatePassword, normalizeAgentDeliveryPolicy, normalizeBatchTranslationError, normalizeEmbeddedUiUrl, normalizeHostedAppBaseUrl, normalizeLegacySoundId, normalizeOpsxEntityPath, openSpecAnnotationRules, opsxGlobToRegex, opsxPathMatchesPattern, parseCliCommand, parseCliCommandResult, parseMarkdownFacts, parseMarkdownTasks, parseOpenSpecMarkdownToSpec, parseOpsxEntityMetadata, parseOpsxSchemaDetail, patchActiveRootOfficialFields, projectAnnotatedOpenSpecToSpec, projectOpenSpecMarkdown, projectTaskProjectionsFromMarkdownFiles, quoteTerminalShellArg, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, redactSnapshotForPublication, removePhysicalReactivePath, renderTerminalCommandArgs, renderTerminalSpawnCommandLine, requireCanonicalOpenSpecEntityId, requireCanonicalOpenSpecSpecId, requireOpenSpecEntityRelativePath, resolveHostedAppBaseUrl, resolveOpenSpecDataScope, resolveOpenSpecSpawnMode, resolveRootContext, resolveRuntimePackageInstallStrategy, resolveTerminalShellDefaults, runControlledTranslationTask, runPhysicalReactivePathMutation, selectLocalDownloadGroup, shouldShowTranslationEngineInstallGate, snapshotHasAbsolutePath, sniffGlobalCli, sortMarkdownReadingPlugins, soundIdFromCustomHash, specDocumentDisplayPath, specIdentityFromRoute, specIdentityKey, specRoutePath, subscribeWatcherRuntimeStatus, terminalNotificationEventToPublishInput, toCliProjectionCommandEvidence, toCliProjectionFailure, toCliProjectionNotice, toMarkdownFactKind, toOpsxDisplayPath, toPersistedGlobalSettings, toStoreFeatureResult, toggleMarkdownTask, trimMarkdownSlice, updateProjectBindingContent, updateReactiveFileCache, validateActiveRootRawYaml, writeAtomicPhysicalReactiveFile, writePhysicalReactiveFile };
|
|
8598
|
+
export { ACCESS_GATE_CREDENTIAL_BYTES, AI_TOOLS, ActiveRootMutationSchema, ActiveRootOfficialConfigSchema, ActiveRootRevisionSchema, ActiveRootStructuredUpdateSchema, AgentDeliveryModeSchema, AgentDeliveryPolicyUpdateSchema, AgentDeliveryProfileSchema, AgentDeliveryWorkflowSchema, ApplyInstructionsContextFilesSchema, ApplyInstructionsProjectionSchema, ApplyInstructionsSchema, ApplyTaskSchema, ArchiveInstructionsSchema, ArtifactInstructionsSchema, ArtifactStatusSchema, BUILTIN_SOUND_IDS, BUILTIN_SOUND_OPTIONS, BUILTIN_TERMINAL_SPAWN_COMMANDS, BatchTranslateEventSchema, BatchTranslateInputSchema, BuiltinSoundIdSchema, CODE_EDITOR_THEME_VALUES, CUSTOM_SOUND_ADD_VALUE, ChangeFileSchema, ChangeSchema, ChangeStatusSchema, CliApplyInstructionsSchema, CliArchiveInstructionsSchema, CliArchiveSchema, CliArtifactInstructionsSchema, CliChangeListSchema, CliCommandTransportSchema, CliContextSchema, CliDiagnosticFailureSchema, CliDiagnosticSchema, CliDoctorReferenceEntrySchema, CliDoctorSchema, CliExecutor, CliJsonValueSchema, CliProjectionCommandError, CliProjectionCommandEvidenceSchema, CliProjectionFailureSchema, CliProjectionInvalidationCauseSchema, CliProjectionNoticeSchema, CliProjectionStateNameSchema, CliReferenceIndexEntrySchema, CliRootSchema, CliRootSourceSchema, CliShowSpecDocumentSchema, CliShowSpecSchema, CliSpecListSchema, CliStoreCleanupSchema, CliStoreDoctorEntrySchema, CliStoreDoctorSchema, CliStoreListSchema, CliStoreMutationSchema, CliStoreSchema, CliStreamTerminationError, CliValidateReportSchema, CliValidateSchema, CliWorkflowStatusSchema, CodeEditorThemeSchema, ConfigManager, CustomSoundHashSchema, CustomSoundIdSchema, CustomSoundMetadataFileSchema, CustomSoundMetadataSchema, DASHBOARD_METRIC_KEYS, DEFAULT_BELL_SOUND_ID, DEFAULT_CONFIG, DEFAULT_GIT_DIFF_EAGER_LINE_BUDGET, DEFAULT_GLOBAL_SETTINGS, DEFAULT_NOTIFICATION_SOUND_ID, DEFAULT_TERMINAL_DARK_THEME, DEFAULT_TERMINAL_LIGHT_THEME, DEFAULT_TERMINAL_THEME_MODE, DEFAULT_TRANSLATION_CACHE_ENTRY_LIMIT, DEFAULT_TRANSLATION_ENGINE_ID, DOCUMENT_TRANSLATION_DISPLAY_MODES, DashboardConfigSchema, DashboardGitSnapshotSchema, DashboardOverviewSchema, DashboardSummaryIdentitySchema, DashboardSummaryInvalidationCauseSchema, DashboardSummaryInvalidationSchema, DashboardSummaryProjectionSchema, DashboardSummaryProjectionStateSchema, DashboardTrendsProjectionSchema, DeltaOperationType, DeltaSchema, DeltaSpecSchema, DependencyInfoSchema, DocumentTranslationConfigSchema, DocumentTranslationConfigUpdateSchema, DocumentTranslationDisplayModeSchema, DocumentTranslationGlobalSettingsUpdateSchema, EnvironmentDefaultStoreUpdateSchema, EnvironmentGlobalConfigValueSchema, EnvironmentGlobalFileProjectionDataSchema, EnvironmentGlobalFileProjectionStateSchema, EnvironmentGlobalProjectionDataSchema, EnvironmentGlobalProjectionStateSchema, FILE_PREVIEW_KINDS, GitConfigSchema, GlobalSettingsManager, HOSTED_SHELL_PROTOCOL_VERSION, LEGACY_SOUND_ID_MAP, LOCAL_MODEL_PROFILE_DEFINITIONS, LocalModelAssetLogSchema, LocalModelAssetPlanSnapshotSchema, LocalModelAssetStateSchema, LocalModelDownloadStatusSchema, LocalModelLifecycleFileStateSchema, LocalModelLifecycleGroupStateSchema, LocalModelProfileLoadStateSchema, LocalModelProfileManifestFileSchema, LocalModelProfileManifestGroupSchema, LocalModelProfileManifestSchema, LocalModelProfileStatusSchema, MAX_ACTIVE_ROOT_CONTEXT_BYTES, MAX_TRANSLATION_CACHE_ENTRY_LIMIT, MIN_TRANSLATION_CACHE_ENTRY_LIMIT, ManagedLocalCatalogSourceSchema, MarkdownParser, MarkdownReadingPluginRegistry, NOTIFICATION_SOUND_OPTIONS, NOTIFICATION_SOUND_VALUES, NotificationActionSchema, NotificationGroupKeySchema, NotificationPublishInputSchema, NotificationRecordSchema, NotificationSettingsSchema, NotificationSoundSchema, NotificationSourceSchema, OFFICIAL_APP_BASE_URL, OPENSPECUI_DOCUMENT_HOOK_VERSION, OPENSPECUI_RUNTIME_CAPABILITIES, OPENSPECUI_WORKFLOW_HOOK_VERSION, OPENSPEC_SPAWN_MODE_ENV, OPEN_SPEC_DATA_DIRECTORY_NAME, OPEN_SPEC_DATA_HOME_OBSERVATION_TARGETS, OPEN_SPEC_READING_SECTIONS_PROJECTION_ID, OPEN_SPEC_SPEC_PROJECTION_ID, OPSX_AGENT_INVOCATION_MODE_VALUES, OPSX_ALL_WORKFLOWS, OPSX_ARTIFACT_INPUT_ACTIONS, OPSX_CHANGE_INPUT_ACTIONS, OPSX_COMMAND_CAPABLE_WORKFLOWS, OPSX_CORE_PROFILE_WORKFLOWS, OPSX_TEXT_INPUT_ACTIONS, OPSX_WORKFLOW_LABELS, OPSX_WORKFLOW_TO_SKILL_DIR, OPSX_WORKFLOW_TO_SKILL_DIR as TOOL_WORKFLOW_TO_SKILL_DIR, OpenSpecAdapter, OpenSpecCliContractExecutor, OpenSpecDataHomeObserver, OpenSpecUIConfigSchema, OpenSpecUIGlobalSettingsSchema, OpenSpecUIGlobalSettingsUpdateSchema, OpenSpecWatcher, OpsxAgentInvocationModeSchema, OpsxCliEvidenceSchema, OpsxConfigBundleSchema, OpsxConfigSchema, OpsxKernel, OpsxStatusEvidenceSchema, OwnedSpecIdentitySchema, PINNED_AGENT_GENERATOR_VERSION, PlanningCliProjectionDataSchema, PlanningCliProjectionSelectorSchema, PlanningCliProjectionStateSchema, PlanningConfigJsonValueSchema, PlanningConfigReferenceSchema, ProjectBindingUpdateSchema, ProjectWatcher, PtyAttachMessageSchema, PtyBellResponseSchema, PtyBufferResponseSchema, PtyClientMessageSchema, PtyCloseMessageSchema, PtyCreateMessageSchema, PtyCreatedResponseSchema, PtyErrorCodeSchema, PtyErrorResponseSchema, PtyExitResponseSchema, PtyInputMessageSchema, PtyListMessageSchema, PtyListResponseSchema, PtyOutputResponseSchema, PtyPlatformSchema, PtyProcessTitleResponseSchema, PtyResizeMessageSchema, PtyServerMessageSchema, PtyTitleResponseSchema, RUNTIME_INVALIDATION_FACETS, ReactiveContext, ReactiveObservationEnvironment, ReactiveState, ReferencedSpecIdentitySchema, RequirementSchema, RuntimeInvalidationIndex, RuntimeRootInvalidationRegistry, SERVE_PRESENTATION_MODES, SERVICE_TRANSLATION_ENGINE_IDS, SILENT_SOUND_ID, ScenarioStepKeywordSchema, ScenarioStepSchema, SchemaArtifactSchema, SchemaDetailSchema, SchemaInfoSchema, SchemaResolutionSchema, ServePresentationModeSchema, ServiceTranslationEngineIdSchema, SoundConfigIdSchema, SoundIdSchema, SpecCatalogSchema, SpecCommandEvidenceSchema, SpecDocumentProjectionSchema, SpecIdentitySchema, SpecSchema, StoreDoctorResultSchema, StoreListResultSchema, StoreMutationLifecycleEventSchema, StoreMutationResultSchema, StoreMutationSchema, StoreMutationStartResponseSchema, TERMINAL_BELL_SOUND_OPTIONS, TERMINAL_BELL_SOUND_VALUES, TERMINAL_COMMAND_FIELD_TYPE_VALUES, TERMINAL_SHELL_QUOTE_STYLE_VALUES, TERMINAL_THEME_MODE_VALUES, TERMINAL_THEME_VALUES, TRANSLATION_CACHE_POLICY_VERSION, TRANSLATION_ENGINE_IDS, TRANSLATION_ENGINE_MANIFESTS, TRANSLATOR_CONTRACT_VERSION, TaskSchema, TemplateContentMapSchema, TemplateContentSchema, TemplatesSchema, TerminalBellSoundSchema, TerminalCommandFieldSchema, TerminalConfigSchema, TerminalControlParser, TerminalCwdTargetSchema, TerminalInvocationSettingsSchema, TerminalNotificationParser, TerminalRendererEngineSchema, TerminalShellProfileSchema, TerminalShellQuoteStyleSchema, TerminalSpawnCommandSchema, TerminalThemeModeSchema, TerminalThemeSchema, TrackedTaskProgressSchema, TranslationCacheEntrySchema, TranslationCacheReadInputSchema, TranslationCacheSettingsSchema, TranslationCacheSettingsUpdateSchema, TranslationCacheStatsSchema, TranslationCacheWriteInputSchema, TranslationDownloadFilePlanSchema, TranslationDownloadGroupPlanSchema, TranslationEngineAssetStateSchema, TranslationEngineAssetStatusSchema, TranslationEngineDependencyStateSchema, TranslationEngineDependencyStatusSchema, TranslationEngineGlobalSettingsSchema, TranslationEngineGlobalSettingsUpdateSchema, TranslationEngineIdSchema, TranslationEngineInstallLogEventSchema, TranslationEngineInstallLogStreamSchema, TranslationEngineLifecycleEventSchema, TranslationEngineLifecycleStatusSchema, TranslationEngineProjectSettingsSchema, TranslationEngineProjectSettingsUpdateSchema, TranslationEngineRuntimeStateSchema, TranslationEngineRuntimeStatusSchema, TranslationLocalCt2SettingsSchema, TranslationLocalCt2SettingsUpdateSchema, TranslationLocalLlamaSettingsSchema, TranslationLocalLlamaSettingsUpdateSchema, TranslationLocalSettingsSchema, TranslationLocalSettingsUpdateSchema, TranslationOpenAISettingsSchema, TranslationOpenAISettingsUpdateSchema, VIRTUAL_PROJECT_DIRNAME, Validator, accessGateFingerprint, acquireWatcher, acquireWatcherRoot, annotateOpenSpecFacts, annotateOpenSpecMarkdown, applyAgentDeliveryPolicy, asEnvUri, buildBackendHealthPayload, buildCliRunnerCandidates, buildEmbeddedUiLaunchUrl, buildHostedLaunchUrl, buildLocalDownloadPlanFromRepositoryFiles, buildLocalDownloadPlanFromRuntimeProfileFiles, buildMarkdownParentMap, buildOpsxEntityDetail, buildRuntimePackageInstallCommand, buildSpecCatalog, builtinOpenSpecReadingPlugin, checkLocalDirectionalModelLanguagePair, classifyStoreCliResult, clearCache, cliProjectionStates, closeAllProjectWatchers, closeAllWatchers, compareAndWriteAtomicPhysicalReactiveFile, computeEnvUri, constantTimeEqual, contextStorage, createApplyInstructionProgress, createCleanCliEnv, createCliProjectionStateSchema, createDocumentChecklistSummary, createFileChangeObservable, createMarkdownReadingDocument, createMarkdownReadingDocumentFromFacts, createOpenSpecReadingPlugin, createPhysicalReactiveDirectory, createStaticSpecCatalogOwnedProjection, createStaticSpecCatalogReferenceProjection, createStaticSpecCatalogReferenceSource, createToolInitStateProjection, createTrackedTaskProgress, createTranslationEngineLifecycleStatus, customHashFromSoundId, deriveTrackedTaskPhase, detectRuntimePackageManager, generateAccessGateCredential, getActiveWatcherCount, getAllToolIds, getAllTools, getAvailableToolIds, getAvailableTools, getBuiltinSoundUrl, getCacheSize, getConfiguredTools, getDefaultCliCommand, getDefaultCliCommandString, getDefaultGlobalSettingsPath, getDetectedProjectTools, getExternalAgentSkillsObservationRoots, getExternalCodexCommandObservationRoot, getManagedLocalTranslationEngineManifest, getMarkdownAnnotation, getMarkdownAnnotationsForFact, getMarkdownFactSpan, getMarkdownHeadingEnd, getMarkdownHeadingFacts, getNotificationGroupKey, getNotificationGroupLabel, getOpenSpecAnnotation, getOpenSpecAnnotationsForFact, getOpenSpecProjectionAnnotation, getOpenSpecReadingSections, getOpsxEntityMetadataPath, getOpsxEntityRootRelativePath, getProjectWatcher, getRootContextCliSelector, getSpecCatalogEntry, getTerminalCommandDefaultValues, getToolById, getToolInitStates, getTranslationEngineLifecycleMessage, getTranslationEngineManifest, getWatcherRuntimeStatus, groupNotifications, hasCapability, inferFileMime, inferFilePreviewKind, inferLocalDirectionalModelLanguagePair, inspectActiveRootOfficialConfig, inspectEnvironmentDefaultStore, inspectProjectBinding, isBackendHealthRuntimeMetadata, isBatchTranslationAbort, isDirectionalManagedLocalTranslationEngineId, isGlobPattern, isHostedBackendHealthResponse, isManagedLocalTranslationEngineId, isMarkdownTaskSourcePath, isOpsxCoreWorkflowSelection, isOpsxGlobPattern, isPreviewableFile, isReferencedSpecIdentity, isSupportedEmbeddedUiUrl, isTerminalMutationStatus, isTerminalRendererEngine, isTextLikeFile, isTextLikeMime, isToolConfigured, isTranslationEngineDependencyReady, isTranslationEngineRuntimeReady, isWatcherPoolInitialized, loadOpenSpecAgentCommandContents, mergeSpecCatalog, normalizeAccessGatePassword, normalizeAgentDeliveryPolicy, normalizeBatchTranslationError, normalizeEmbeddedUiUrl, normalizeHostedAppBaseUrl, normalizeLegacySoundId, normalizeOpsxEntityPath, openSpecAnnotationRules, opsxGlobToRegex, opsxPathMatchesPattern, parseCliCommand, parseCliCommandResult, parseMarkdownFacts, parseMarkdownTasks, parseOpenSpecMarkdownToSpec, parseOpsxEntityMetadata, parseOpsxSchemaDetail, patchActiveRootOfficialFields, projectAnnotatedOpenSpecToSpec, projectOpenSpecMarkdown, projectTaskProjectionsFromMarkdownFiles, quoteTerminalShellArg, reactiveExists, reactiveReadDir, reactiveReadFile, reactiveStat, redactSnapshotForPublication, removePhysicalReactivePath, renderTerminalCommandArgs, renderTerminalSpawnCommandLine, replaceFileAtomically, requireCanonicalOpenSpecEntityId, requireCanonicalOpenSpecSpecId, requireOpenSpecEntityRelativePath, resolveCommandInvocation, resolveGlobalSkillsInventoryDir, resolveHostedAppBaseUrl, resolveOpenSpecDataScope, resolveOpenSpecSpawnMode, resolveRootContext, resolveRuntimePackageInstallStrategy, resolveTerminalShellDefaults, resolveToolSkillsScope, resolveWindowsCommandInvocation, runControlledTranslationTask, runPhysicalReactivePathMutation, selectAgentDeliveryRegistry, selectLocalDownloadGroup, shouldShowTranslationEngineInstallGate, snapshotHasAbsolutePath, sniffGlobalCli, sortMarkdownReadingPlugins, soundIdFromCustomHash, spawnSafe, specDocumentDisplayPath, specIdentityFromRoute, specIdentityKey, specRoutePath, subscribeWatcherRuntimeStatus, terminalNotificationEventToPublishInput, terminateChildProcessTree, terminateWindowsProcessTreeByIdentity, toCliProjectionCommandEvidence, toCliProjectionFailure, toCliProjectionNotice, toMarkdownFactKind, toOpsxDisplayPath, toPersistedGlobalSettings, toStoreFeatureResult, toggleMarkdownTask, trimMarkdownSlice, updateProjectBindingContent, updateReactiveFileCache, validateActiveRootRawYaml, writeAtomicPhysicalReactiveFile, writePhysicalReactiveFile };
|