@openspecui/web 1.1.1 → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/assets/{BufferResource-BynRzySn.js → BufferResource-DdnZHNU-.js} +1 -1
  2. package/dist/assets/{CanvasRenderer-CbECvW_h.js → CanvasRenderer-W0-8maEY.js} +1 -1
  3. package/{dist-ssg/client/assets/Filter-BjiflTCt.js → dist/assets/Filter-BCHzFO9X.js} +1 -1
  4. package/{dist-ssg/client/assets/RenderTargetSystem-CD3Xxio1.js → dist/assets/RenderTargetSystem-QYja7U1C.js} +1 -1
  5. package/dist/assets/{WebGLRenderer-DsWqcm9A.js → WebGLRenderer-CN6ngwpu.js} +1 -1
  6. package/{dist-ssg/client/assets/WebGPURenderer-BnVEe7ZL.js → dist/assets/WebGPURenderer-CSfhxPBR.js} +1 -1
  7. package/{dist-ssg/client/assets/browserAll-Cb6nfsf4.js → dist/assets/browserAll-CChvoSPa.js} +1 -1
  8. package/{dist-ssg/client/assets/index-DmhYrwH_.js → dist/assets/index-8kjDfgtP.js} +1 -1
  9. package/dist/assets/index-BBa-UOW9.css +1 -0
  10. package/{dist-ssg/client/assets/index-o68ShgAu.js → dist/assets/index-BPuO-i8p.js} +1 -1
  11. package/dist/assets/{index-3oN9R9iN.js → index-BTVg5Nau.js} +1 -1
  12. package/dist/assets/{index-CSmGqpdI.js → index-BcA9ozYL.js} +171 -171
  13. package/{dist-ssg/client/assets/index-B5u6uSVz.js → dist/assets/index-CWB6CIXv.js} +1 -1
  14. package/dist/assets/{index-CsSu022q.js → index-Ca41ecb5.js} +1 -1
  15. package/dist/assets/{index-C5CFYfMw.js → index-CoF0ewHZ.js} +1 -1
  16. package/dist/assets/{index-BkA1vsv2.js → index-D2pLblyv.js} +1 -1
  17. package/dist/assets/{index-F5V_nJpw.js → index-DS0kz2NM.js} +1 -1
  18. package/dist/assets/{index-D2zSLUgf.js → index-DSkiV8t7.js} +1 -1
  19. package/{dist-ssg/client/assets/index-CVWM2euh.js → dist/assets/index-DWh8uDpX.js} +1 -1
  20. package/dist/assets/{index-CbMWJK9x.js → index-DXb6uuwe.js} +1 -1
  21. package/dist/assets/{index-BiSFkDHl.js → index-Do3bWt1y.js} +1 -1
  22. package/{dist-ssg/client/assets/index-DRNAjv5N.js → dist/assets/index-a4zt_8am.js} +1 -1
  23. package/dist/assets/{index-mA1BhKJg.js → index-fWg8Cn9O.js} +1 -1
  24. package/{dist-ssg/client/assets/index-DaJuvT8s.js → dist/assets/index-hysFimNk.js} +1 -1
  25. package/{dist-ssg/client/assets/webworkerAll-DfP6Gnah.js → dist/assets/webworkerAll-T10QBdIL.js} +1 -1
  26. package/dist/index.html +2 -2
  27. package/dist-ssg/client/.vite/ssr-manifest.json +197 -191
  28. package/dist-ssg/client/assets/{BufferResource-BynRzySn.js → BufferResource-DdnZHNU-.js} +1 -1
  29. package/dist-ssg/client/assets/{CanvasRenderer-CbECvW_h.js → CanvasRenderer-W0-8maEY.js} +1 -1
  30. package/{dist/assets/Filter-BjiflTCt.js → dist-ssg/client/assets/Filter-BCHzFO9X.js} +1 -1
  31. package/{dist/assets/RenderTargetSystem-CD3Xxio1.js → dist-ssg/client/assets/RenderTargetSystem-QYja7U1C.js} +1 -1
  32. package/dist-ssg/client/assets/{WebGLRenderer-DsWqcm9A.js → WebGLRenderer-CN6ngwpu.js} +1 -1
  33. package/{dist/assets/WebGPURenderer-BnVEe7ZL.js → dist-ssg/client/assets/WebGPURenderer-CSfhxPBR.js} +1 -1
  34. package/{dist/assets/browserAll-Cb6nfsf4.js → dist-ssg/client/assets/browserAll-CChvoSPa.js} +1 -1
  35. package/{dist/assets/index-DmhYrwH_.js → dist-ssg/client/assets/index-8kjDfgtP.js} +1 -1
  36. package/dist-ssg/client/assets/index-BBa-UOW9.css +1 -0
  37. package/{dist/assets/index-o68ShgAu.js → dist-ssg/client/assets/index-BPuO-i8p.js} +1 -1
  38. package/dist-ssg/client/assets/{index-3oN9R9iN.js → index-BTVg5Nau.js} +1 -1
  39. package/dist-ssg/client/assets/{index-CSmGqpdI.js → index-BcA9ozYL.js} +171 -171
  40. package/{dist/assets/index-B5u6uSVz.js → dist-ssg/client/assets/index-CWB6CIXv.js} +1 -1
  41. package/dist-ssg/client/assets/{index-CsSu022q.js → index-Ca41ecb5.js} +1 -1
  42. package/dist-ssg/client/assets/{index-C5CFYfMw.js → index-CoF0ewHZ.js} +1 -1
  43. package/dist-ssg/client/assets/{index-BkA1vsv2.js → index-D2pLblyv.js} +1 -1
  44. package/dist-ssg/client/assets/{index-F5V_nJpw.js → index-DS0kz2NM.js} +1 -1
  45. package/dist-ssg/client/assets/{index-D2zSLUgf.js → index-DSkiV8t7.js} +1 -1
  46. package/{dist/assets/index-CVWM2euh.js → dist-ssg/client/assets/index-DWh8uDpX.js} +1 -1
  47. package/dist-ssg/client/assets/{index-CbMWJK9x.js → index-DXb6uuwe.js} +1 -1
  48. package/dist-ssg/client/assets/{index-BiSFkDHl.js → index-Do3bWt1y.js} +1 -1
  49. package/{dist/assets/index-DRNAjv5N.js → dist-ssg/client/assets/index-a4zt_8am.js} +1 -1
  50. package/dist-ssg/client/assets/{index-mA1BhKJg.js → index-fWg8Cn9O.js} +1 -1
  51. package/{dist/assets/index-DaJuvT8s.js → dist-ssg/client/assets/index-hysFimNk.js} +1 -1
  52. package/{dist/assets/webworkerAll-DfP6Gnah.js → dist-ssg/client/assets/webworkerAll-T10QBdIL.js} +1 -1
  53. package/dist-ssg/client/index.html +2 -2
  54. package/dist-ssg/server/entry-server.js +218 -118
  55. package/package.json +2 -2
  56. package/dist/assets/index-BfjQi4qu.css +0 -1
  57. package/dist-ssg/client/assets/index-BfjQi4qu.css +0 -1
@@ -36129,7 +36129,7 @@ const DEFAULT_MAIN_TABS = [
36129
36129
  "/settings"
36130
36130
  ];
36131
36131
  const DEFAULT_BOTTOM_TABS = isStaticMode() ? [] : ["/terminal"];
36132
- const POP_ROUTES = ["/search"];
36132
+ const POP_ROUTES = ["/search", "/opsx-new"];
36133
36133
  const KV_KEY$1 = "nav-layout";
36134
36134
  const LS_KEY = "nav-layout";
36135
36135
  const PERSIST_DEBOUNCE = 300;
@@ -47681,21 +47681,13 @@ async function getOpsxProjectConfig() {
47681
47681
  const snapshot = await loadSnapshot();
47682
47682
  return snapshot?.opsx?.configYaml ?? null;
47683
47683
  }
47684
- async function getOpsxSchemas() {
47684
+ async function getOpsxConfigBundle() {
47685
47685
  const snapshot = await loadSnapshot();
47686
- return snapshot?.opsx?.schemas ?? [];
47687
- }
47688
- async function getOpsxSchemaDetail(name2) {
47689
- if (!name2) return null;
47690
- const snapshot = await loadSnapshot();
47691
- const details = snapshot?.opsx?.schemaDetails;
47692
- return details?.[name2] ?? null;
47693
- }
47694
- async function getOpsxSchemaResolution(name2) {
47695
- if (!name2) return null;
47696
- const snapshot = await loadSnapshot();
47697
- const resolutions = snapshot?.opsx?.schemaResolutions;
47698
- return resolutions?.[name2] ?? null;
47686
+ return {
47687
+ schemas: snapshot?.opsx?.schemas ?? [],
47688
+ schemaDetails: snapshot?.opsx?.schemaDetails ?? {},
47689
+ schemaResolutions: snapshot?.opsx?.schemaResolutions ?? {}
47690
+ };
47699
47691
  }
47700
47692
  async function getOpsxTemplates(schema2) {
47701
47693
  const snapshot = await loadSnapshot();
@@ -106569,15 +106561,20 @@ function useOpsxStatusSubscription(input) {
106569
106561
  input.change ? `opsx.subscribeStatus:${input.change}:${input.schema}:${input.refreshKey}` : void 0
106570
106562
  );
106571
106563
  }
106572
- function useOpsxSchemasSubscription() {
106564
+ function useOpsxConfigBundleSubscription() {
106573
106565
  const subscribe2 = reactExports.useCallback(
106574
- (callbacks) => trpcClient.opsx.subscribeSchemas.subscribe(void 0, {
106566
+ (callbacks) => trpcClient.opsx.subscribeConfigBundle.subscribe(void 0, {
106575
106567
  onData: callbacks.onData,
106576
106568
  onError: callbacks.onError
106577
106569
  }),
106578
106570
  []
106579
106571
  );
106580
- return useSubscription(subscribe2, getOpsxSchemas, [], "opsx.subscribeSchemas");
106572
+ return useSubscription(
106573
+ subscribe2,
106574
+ getOpsxConfigBundle,
106575
+ [],
106576
+ "opsx.subscribeConfigBundle"
106577
+ );
106581
106578
  }
106582
106579
  function useOpsxStatusListSubscription() {
106583
106580
  const subscribe2 = reactExports.useCallback(
@@ -106587,67 +106584,19 @@ function useOpsxStatusListSubscription() {
106587
106584
  }),
106588
106585
  []
106589
106586
  );
106590
- return useSubscription(subscribe2, getOpsxStatusList, [], "opsx.subscribeStatusList");
106591
- }
106592
- function useOpsxSchemaDetailSubscription(name2) {
106593
- const subscribe2 = reactExports.useCallback(
106594
- (callbacks) => {
106595
- if (!name2) {
106596
- callbacks.onData(null);
106597
- return { unsubscribe: () => {
106598
- } };
106599
- }
106600
- return trpcClient.opsx.subscribeSchemaDetail.subscribe(
106601
- { name: name2 },
106602
- {
106603
- onData: callbacks.onData,
106604
- onError: callbacks.onError
106605
- }
106606
- );
106607
- },
106608
- [name2]
106609
- );
106610
106587
  return useSubscription(
106611
106588
  subscribe2,
106612
- () => getOpsxSchemaDetail(name2),
106613
- [name2],
106614
- name2 ? `opsx.subscribeSchemaDetail:${name2}` : void 0
106615
- );
106616
- }
106617
- function useOpsxSchemaResolutionSubscription(name2) {
106618
- const subscribe2 = reactExports.useCallback(
106619
- (callbacks) => {
106620
- if (!name2) {
106621
- callbacks.onData(null);
106622
- return { unsubscribe: () => {
106623
- } };
106624
- }
106625
- return trpcClient.opsx.subscribeSchemaResolution.subscribe(
106626
- { name: name2 },
106627
- {
106628
- onData: callbacks.onData,
106629
- onError: callbacks.onError
106630
- }
106631
- );
106632
- },
106633
- [name2]
106634
- );
106635
- return useSubscription(
106636
- subscribe2,
106637
- () => getOpsxSchemaResolution(name2),
106638
- [name2],
106639
- name2 ? `opsx.subscribeSchemaResolution:${name2}` : void 0
106589
+ getOpsxStatusList,
106590
+ [],
106591
+ "opsx.subscribeStatusList"
106640
106592
  );
106641
106593
  }
106642
106594
  function useOpsxTemplatesSubscription(schema2) {
106643
106595
  const subscribe2 = reactExports.useCallback(
106644
- (callbacks) => trpcClient.opsx.subscribeTemplates.subscribe(
106645
- schema2 ? { schema: schema2 } : void 0,
106646
- {
106647
- onData: callbacks.onData,
106648
- onError: callbacks.onError
106649
- }
106650
- ),
106596
+ (callbacks) => trpcClient.opsx.subscribeTemplates.subscribe(schema2 ? { schema: schema2 } : void 0, {
106597
+ onData: callbacks.onData,
106598
+ onError: callbacks.onError
106599
+ }),
106651
106600
  [schema2]
106652
106601
  );
106653
106602
  return useSubscription(
@@ -106684,13 +106633,10 @@ function useOpsxSchemaFilesSubscription(name2) {
106684
106633
  }
106685
106634
  function useOpsxTemplateContentsSubscription(schema2) {
106686
106635
  const subscribe2 = reactExports.useCallback(
106687
- (callbacks) => trpcClient.opsx.subscribeTemplateContents.subscribe(
106688
- schema2 ? { schema: schema2 } : void 0,
106689
- {
106690
- onData: callbacks.onData,
106691
- onError: callbacks.onError
106692
- }
106693
- ),
106636
+ (callbacks) => trpcClient.opsx.subscribeTemplateContents.subscribe(schema2 ? { schema: schema2 } : void 0, {
106637
+ onData: callbacks.onData,
106638
+ onError: callbacks.onError
106639
+ }),
106694
106640
  [schema2]
106695
106641
  );
106696
106642
  return useSubscription(
@@ -106708,7 +106654,12 @@ function useOpsxProjectConfigSubscription() {
106708
106654
  }),
106709
106655
  []
106710
106656
  );
106711
- return useSubscription(subscribe2, getOpsxProjectConfig, [], "opsx.subscribeProjectConfig");
106657
+ return useSubscription(
106658
+ subscribe2,
106659
+ getOpsxProjectConfig,
106660
+ [],
106661
+ "opsx.subscribeProjectConfig"
106662
+ );
106712
106663
  }
106713
106664
  function useOpsxChangeListSubscription() {
106714
106665
  const subscribe2 = reactExports.useCallback(
@@ -106718,7 +106669,12 @@ function useOpsxChangeListSubscription() {
106718
106669
  }),
106719
106670
  []
106720
106671
  );
106721
- return useSubscription(subscribe2, getOpsxChangeList, [], "opsx.subscribeChanges");
106672
+ return useSubscription(
106673
+ subscribe2,
106674
+ getOpsxChangeList,
106675
+ [],
106676
+ "opsx.subscribeChanges"
106677
+ );
106722
106678
  }
106723
106679
  function useOpsxChangeMetadataSubscription(changeId) {
106724
106680
  const subscribe2 = reactExports.useCallback(
@@ -106842,9 +106798,19 @@ function ChangeList() {
106842
106798
  );
106843
106799
  }),
106844
106800
  statuses?.length === 0 && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-muted-foreground p-4 text-center", children: [
106845
- "No active changes. Use ",
106846
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "/opsx:new" }),
106847
- " to create one."
106801
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "No active changes." }),
106802
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
106803
+ "button",
106804
+ {
106805
+ type: "button",
106806
+ onClick: () => navController.activatePop("/opsx-new"),
106807
+ className: "text-primary mt-2 inline-flex items-center gap-1 hover:underline",
106808
+ children: [
106809
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-3.5 w-3.5" }),
106810
+ "/opsx:new"
106811
+ ]
106812
+ }
106813
+ )
106848
106814
  ] })
106849
106815
  ] })
106850
106816
  ] });
@@ -106861,7 +106827,7 @@ function ArtifactHeader({ artifact }) {
106861
106827
  const status = statusConfig[artifact.status];
106862
106828
  const StatusIcon = status.icon;
106863
106829
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
106864
- /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-border flex flex-wrap items-center justify-between gap-3 rounded-md border bg-card px-4 py-3", children: [
106830
+ /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-border bg-card flex flex-wrap items-center justify-between gap-3 rounded-md border px-4 py-3", children: [
106865
106831
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "flex items-center gap-2", children: [
106866
106832
  /* @__PURE__ */ jsxRuntimeExports.jsx(FileText, { className: "text-muted-foreground h-4 w-4" }),
106867
106833
  /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "font-medium", children: artifact.id }),
@@ -106882,7 +106848,10 @@ function ArtifactHeader({ artifact }) {
106882
106848
  ] });
106883
106849
  }
106884
106850
  function SingleFileContent({ changeId, artifact }) {
106885
- const { data: content2, isLoading } = useOpsxArtifactOutputSubscription(changeId, artifact.outputPath);
106851
+ const { data: content2, isLoading } = useOpsxArtifactOutputSubscription(
106852
+ changeId,
106853
+ artifact.outputPath
106854
+ );
106886
106855
  if (isLoading) {
106887
106856
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "text-muted-foreground flex h-full items-center justify-center text-sm", children: "Loading output..." });
106888
106857
  }
@@ -106891,19 +106860,22 @@ function SingleFileContent({ changeId, artifact }) {
106891
106860
  }
106892
106861
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-muted-foreground flex h-full items-center justify-center rounded-md border border-dashed p-6 text-sm", children: [
106893
106862
  "Not yet generated. Use ",
106894
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Continue" }),
106863
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "mx-2", children: "Continue" }),
106895
106864
  " to generate this artifact."
106896
106865
  ] });
106897
106866
  }
106898
106867
  function GlobContent({ changeId, artifact }) {
106899
- const { data: files, isLoading } = useOpsxGlobArtifactFilesSubscription(changeId, artifact.outputPath);
106868
+ const { data: files, isLoading } = useOpsxGlobArtifactFilesSubscription(
106869
+ changeId,
106870
+ artifact.outputPath
106871
+ );
106900
106872
  if (isLoading) {
106901
106873
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "flex h-[400px] items-center justify-center", children: /* @__PURE__ */ jsxRuntimeExports.jsx(LoaderCircle, { className: "text-muted-foreground h-6 w-6 animate-spin" }) });
106902
106874
  }
106903
106875
  if (!files?.length) {
106904
106876
  return /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "text-muted-foreground flex h-full items-center justify-center rounded-md border border-dashed p-6 text-sm", children: [
106905
106877
  "Not yet generated. Use ",
106906
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "Continue" }),
106878
+ /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { className: "mx-2", children: "Continue" }),
106907
106879
  " to generate this artifact."
106908
106880
  ] });
106909
106881
  }
@@ -109935,6 +109907,59 @@ ZodTuple.create = (schemas, params) => {
109935
109907
  ...processCreateParams(params)
109936
109908
  });
109937
109909
  };
109910
+ class ZodRecord extends ZodType {
109911
+ get keySchema() {
109912
+ return this._def.keyType;
109913
+ }
109914
+ get valueSchema() {
109915
+ return this._def.valueType;
109916
+ }
109917
+ _parse(input) {
109918
+ const { status, ctx } = this._processInputParams(input);
109919
+ if (ctx.parsedType !== ZodParsedType.object) {
109920
+ addIssueToContext(ctx, {
109921
+ code: ZodIssueCode.invalid_type,
109922
+ expected: ZodParsedType.object,
109923
+ received: ctx.parsedType
109924
+ });
109925
+ return INVALID;
109926
+ }
109927
+ const pairs2 = [];
109928
+ const keyType = this._def.keyType;
109929
+ const valueType = this._def.valueType;
109930
+ for (const key2 in ctx.data) {
109931
+ pairs2.push({
109932
+ key: keyType._parse(new ParseInputLazyPath(ctx, key2, ctx.path, key2)),
109933
+ value: valueType._parse(new ParseInputLazyPath(ctx, ctx.data[key2], ctx.path, key2)),
109934
+ alwaysSet: key2 in ctx.data
109935
+ });
109936
+ }
109937
+ if (ctx.common.async) {
109938
+ return ParseStatus.mergeObjectAsync(status, pairs2);
109939
+ } else {
109940
+ return ParseStatus.mergeObjectSync(status, pairs2);
109941
+ }
109942
+ }
109943
+ get element() {
109944
+ return this._def.valueType;
109945
+ }
109946
+ static create(first, second, third) {
109947
+ if (second instanceof ZodType) {
109948
+ return new ZodRecord({
109949
+ keyType: first,
109950
+ valueType: second,
109951
+ typeName: ZodFirstPartyTypeKind.ZodRecord,
109952
+ ...processCreateParams(third)
109953
+ });
109954
+ }
109955
+ return new ZodRecord({
109956
+ keyType: ZodString.create(),
109957
+ valueType: first,
109958
+ typeName: ZodFirstPartyTypeKind.ZodRecord,
109959
+ ...processCreateParams(second)
109960
+ });
109961
+ }
109962
+ }
109938
109963
  class ZodMap extends ZodType {
109939
109964
  get keySchema() {
109940
109965
  return this._def.keyType;
@@ -110679,10 +110704,11 @@ const booleanType = ZodBoolean.create;
110679
110704
  ZodNever.create;
110680
110705
  const arrayType = ZodArray.create;
110681
110706
  const objectType = ZodObject.create;
110682
- ZodUnion.create;
110707
+ const unionType = ZodUnion.create;
110683
110708
  const discriminatedUnionType = ZodDiscriminatedUnion.create;
110684
110709
  ZodIntersection.create;
110685
110710
  ZodTuple.create;
110711
+ const recordType = ZodRecord.create;
110686
110712
  const literalType = ZodLiteral.create;
110687
110713
  const enumType = ZodEnum.create;
110688
110714
  ZodPromise.create;
@@ -110690,6 +110716,7 @@ ZodOptional.create;
110690
110716
  ZodNullable.create;
110691
110717
  const PositiveInt = numberType().int().positive();
110692
110718
  const PtyPlatformSchema = enumType(["windows", "macos", "common"]);
110719
+ const CloseCallbackUrlSchema = unionType([stringType(), recordType(stringType())]);
110693
110720
  const PtySessionInfoSchema = objectType({
110694
110721
  id: stringType().min(1),
110695
110722
  title: stringType(),
@@ -110697,7 +110724,9 @@ const PtySessionInfoSchema = objectType({
110697
110724
  args: arrayType(stringType()),
110698
110725
  platform: PtyPlatformSchema,
110699
110726
  isExited: booleanType(),
110700
- exitCode: numberType().int().nullable()
110727
+ exitCode: numberType().int().nullable(),
110728
+ closeTip: stringType().optional(),
110729
+ closeCallbackUrl: CloseCallbackUrlSchema.optional()
110701
110730
  });
110702
110731
  const PtyCreateMessageSchema = objectType({
110703
110732
  type: literalType("create"),
@@ -110705,7 +110734,9 @@ const PtyCreateMessageSchema = objectType({
110705
110734
  cols: PositiveInt.optional(),
110706
110735
  rows: PositiveInt.optional(),
110707
110736
  command: stringType().min(1).optional(),
110708
- args: arrayType(stringType()).optional()
110737
+ args: arrayType(stringType()).optional(),
110738
+ closeTip: stringType().optional(),
110739
+ closeCallbackUrl: CloseCallbackUrlSchema.optional()
110709
110740
  });
110710
110741
  const PtyInputMessageSchema = objectType({
110711
110742
  type: literalType("input"),
@@ -148182,6 +148213,8 @@ class TerminalController {
148182
148213
  command: opts?.command,
148183
148214
  args: opts?.args,
148184
148215
  isDedicated: opts?.isDedicated ?? false,
148216
+ closeTip: opts?.closeTip,
148217
+ closeCallbackUrl: opts?.closeCallbackUrl,
148185
148218
  restored: false,
148186
148219
  serverSessionId: null,
148187
148220
  platform: DEFAULT_PTY_PLATFORM
@@ -148204,13 +148237,17 @@ class TerminalController {
148204
148237
  cols: instance.terminal.cols || 80,
148205
148238
  rows: instance.terminal.rows || 24,
148206
148239
  command: opts?.command,
148207
- args: opts?.args
148240
+ args: opts?.args,
148241
+ closeTip: opts?.closeTip,
148242
+ closeCallbackUrl: opts?.closeCallbackUrl
148208
148243
  });
148209
148244
  } else {
148210
148245
  this.pendingCreates.push({
148211
148246
  requestId: id2,
148212
148247
  command: opts?.command,
148213
148248
  args: opts?.args,
148249
+ closeTip: opts?.closeTip,
148250
+ closeCallbackUrl: opts?.closeCallbackUrl,
148214
148251
  cols: instance.terminal.cols || 80,
148215
148252
  rows: instance.terminal.rows || 24
148216
148253
  });
@@ -148279,6 +148316,8 @@ class TerminalController {
148279
148316
  exitCode: null,
148280
148317
  command: opts.command,
148281
148318
  args: opts.args,
148319
+ closeTip: opts.closeTip,
148320
+ closeCallbackUrl: opts.closeCallbackUrl,
148282
148321
  mountedContainer: null,
148283
148322
  resizeObserver: null,
148284
148323
  hasOpened: false,
@@ -148288,9 +148327,10 @@ class TerminalController {
148288
148327
  platform: opts.platform
148289
148328
  };
148290
148329
  }
148291
- closeSession(id2) {
148330
+ closeSession(id2, opts) {
148292
148331
  const instance = this.instances.get(id2);
148293
148332
  if (!instance) return;
148333
+ const shouldTriggerCloseCallback = opts?.triggerCloseCallback !== false;
148294
148334
  if (instance.mountedContainer) {
148295
148335
  this.unmount(id2);
148296
148336
  }
@@ -148309,12 +148349,15 @@ class TerminalController {
148309
148349
  }
148310
148350
  }
148311
148351
  instance.terminal.dispose();
148352
+ if (shouldTriggerCloseCallback) {
148353
+ this.runCloseCallback(instance);
148354
+ }
148312
148355
  this.instances.delete(id2);
148313
148356
  this.notify();
148314
148357
  }
148315
148358
  closeAll() {
148316
148359
  for (const id2 of [...this.instances.keys()]) {
148317
- this.closeSession(id2);
148360
+ this.closeSession(id2, { triggerCloseCallback: false });
148318
148361
  }
148319
148362
  }
148320
148363
  // --- DOM mount/unmount ---
@@ -148512,10 +148555,11 @@ class TerminalController {
148512
148555
  if (!instance) return;
148513
148556
  instance.isExited = true;
148514
148557
  instance.exitCode = msg.exitCode;
148515
- if (instance.isDedicated) {
148558
+ if (instance.closeTip || instance.isDedicated) {
148559
+ const tip = instance.closeTip ?? "Press any key to close (equivalent to close action).";
148516
148560
  instance.terminal.write(
148517
148561
  `\r
148518
- \x1B[90m[Process exited with code ${msg.exitCode}. Press any key to close (equivalent to close action).]\x1B[0m`
148562
+ \x1B[90m[Process exited with code ${msg.exitCode}. ${tip}]\x1B[0m`
148519
148563
  );
148520
148564
  }
148521
148565
  this.notify();
@@ -148591,6 +148635,8 @@ class TerminalController {
148591
148635
  outputActive: inst.lastOutputTime > 0 && Date.now() - inst.lastOutputTime < OUTPUT_IDLE_THRESHOLD,
148592
148636
  command: inst.command,
148593
148637
  args: inst.args,
148638
+ closeTip: inst.closeTip,
148639
+ closeCallbackUrl: inst.closeCallbackUrl,
148594
148640
  platform: inst.platform
148595
148641
  });
148596
148642
  }
@@ -148632,7 +148678,9 @@ class TerminalController {
148632
148678
  cols: pending.cols,
148633
148679
  rows: pending.rows,
148634
148680
  command: pending.command,
148635
- args: pending.args
148681
+ args: pending.args,
148682
+ closeTip: pending.closeTip,
148683
+ closeCallbackUrl: pending.closeCallbackUrl
148636
148684
  });
148637
148685
  }
148638
148686
  this.pendingCreates = [];
@@ -148715,6 +148763,8 @@ class TerminalController {
148715
148763
  command: serverSession.command,
148716
148764
  args: serverSession.args,
148717
148765
  isDedicated: false,
148766
+ closeTip: serverSession.closeTip,
148767
+ closeCallbackUrl: serverSession.closeCallbackUrl,
148718
148768
  restored: true,
148719
148769
  serverSessionId: serverSession.id,
148720
148770
  platform: serverSession.platform ?? DEFAULT_PTY_PLATFORM
@@ -148737,6 +148787,8 @@ class TerminalController {
148737
148787
  } else if (!instance.serverSessionId) {
148738
148788
  instance.serverSessionId = serverSession.id;
148739
148789
  }
148790
+ instance.closeTip = serverSession.closeTip;
148791
+ instance.closeCallbackUrl = serverSession.closeCallbackUrl;
148740
148792
  instance.platform = serverSession.platform ?? DEFAULT_PTY_PLATFORM;
148741
148793
  instance.inputPanelAddon.setPlatform(instance.platform);
148742
148794
  this.serverToLocalSessionId.set(serverSession.id, instance.id);
@@ -148760,12 +148812,45 @@ class TerminalController {
148760
148812
  get discoveredSessions() {
148761
148813
  return this.hasDiscoveredSessions;
148762
148814
  }
148815
+ runCloseCallback(instance) {
148816
+ if (!instance.isExited) return;
148817
+ const callbackUrl = resolveCloseCallbackUrl(instance.closeCallbackUrl, instance.exitCode);
148818
+ if (!callbackUrl) return;
148819
+ navigateCloseCallback(callbackUrl);
148820
+ }
148763
148821
  wsSend(msg) {
148764
148822
  if (this.ws?.readyState === WebSocket.OPEN) {
148765
148823
  this.ws.send(JSON.stringify(msg));
148766
148824
  }
148767
148825
  }
148768
148826
  }
148827
+ function resolveCloseCallbackUrl(raw2, exitCode) {
148828
+ if (!raw2) return null;
148829
+ if (typeof raw2 === "string") {
148830
+ const trimmed = raw2.trim();
148831
+ return trimmed.length > 0 ? trimmed : null;
148832
+ }
148833
+ const exact = raw2[exitCode == null ? "null" : String(exitCode)];
148834
+ if (typeof exact === "string" && exact.trim().length > 0) return exact.trim();
148835
+ const fallback = raw2["*"];
148836
+ if (typeof fallback === "string" && fallback.trim().length > 0) return fallback.trim();
148837
+ return null;
148838
+ }
148839
+ function navigateCloseCallback(rawUrl) {
148840
+ let parsed;
148841
+ try {
148842
+ parsed = new URL(rawUrl, window.location.origin);
148843
+ } catch {
148844
+ return;
148845
+ }
148846
+ if (parsed.origin === window.location.origin) {
148847
+ const href = `${parsed.pathname}${parsed.search}${parsed.hash}`;
148848
+ const targetArea = navController.getAreaForPath(parsed.pathname);
148849
+ navController.push(targetArea, href, null);
148850
+ return;
148851
+ }
148852
+ window.open(parsed.toString(), "_blank", "noopener,noreferrer");
148853
+ }
148769
148854
  const terminalController = new TerminalController();
148770
148855
  const TerminalContext = reactExports.createContext(null);
148771
148856
  function useTerminalContext() {
@@ -148966,13 +149051,14 @@ function Config() {
148966
149051
  const [newSchemaSource, setNewSchemaSource] = reactExports.useState("spec-driven");
148967
149052
  const { data: configYaml, isLoading: configLoading } = useOpsxProjectConfigSubscription();
148968
149053
  const {
148969
- data: schemas,
149054
+ data: configBundle,
148970
149055
  isLoading: schemasLoading,
148971
149056
  error: schemasError
148972
- } = useOpsxSchemasSubscription();
149057
+ } = useOpsxConfigBundleSubscription();
149058
+ const schemas = configBundle?.schemas;
148973
149059
  const [selectedSchema, setSelectedSchema] = reactExports.useState(void 0);
148974
- const { data: schemaDetail } = useOpsxSchemaDetailSubscription(selectedSchema);
148975
- const { data: schemaResolution } = useOpsxSchemaResolutionSubscription(selectedSchema);
149060
+ const schemaDetail = selectedSchema ? configBundle?.schemaDetails[selectedSchema] ?? null : null;
149061
+ const schemaResolution = selectedSchema ? configBundle?.schemaResolutions[selectedSchema] ?? null : null;
148976
149062
  const { data: schemaFiles, error: schemaFilesError } = useOpsxSchemaFilesSubscription(selectedSchema);
148977
149063
  const { data: templates } = useOpsxTemplatesSubscription(selectedSchema);
148978
149064
  const { data: templateContents } = useOpsxTemplateContentsSubscription(selectedSchema);
@@ -150241,7 +150327,6 @@ function Config() {
150241
150327
  }
150242
150328
  function Dashboard() {
150243
150329
  const { data: statuses, isLoading, error } = useOpsxStatusListSubscription();
150244
- const { createDedicatedSession } = useTerminalContext();
150245
150330
  const summary = reactExports.useMemo(() => {
150246
150331
  const totalChanges = statuses?.length ?? 0;
150247
150332
  const totalArtifacts = statuses?.reduce((count2, status) => count2 + status.artifacts.length, 0) ?? 0;
@@ -150252,15 +150337,8 @@ function Dashboard() {
150252
150337
  return { totalChanges, totalArtifacts, doneArtifacts };
150253
150338
  }, [statuses]);
150254
150339
  const runNewChange = reactExports.useCallback(() => {
150255
- const name2 = window.prompt("Change name (kebab-case):");
150256
- if (!name2) return;
150257
- const schema2 = window.prompt("Schema (optional):");
150258
- const args = ["new", "change", name2.trim()];
150259
- if (schema2) {
150260
- args.push("--schema", schema2.trim());
150261
- }
150262
- createDedicatedSession("openspec", args);
150263
- }, [createDedicatedSession]);
150340
+ navController.activatePop("/opsx-new");
150341
+ }, []);
150264
150342
  if (isLoading && !statuses) {
150265
150343
  return /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "route-loading animate-pulse", children: "Loading dashboard..." });
150266
150344
  }
@@ -150293,13 +150371,35 @@ function Dashboard() {
150293
150371
  ] }),
150294
150372
  /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "grid grid-cols-1 gap-4 md:grid-cols-3", children: [
150295
150373
  /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Active Changes", value: summary.totalChanges }),
150296
- /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Artifacts Complete", value: `${summary.doneArtifacts}/${summary.totalArtifacts}` }),
150297
- /* @__PURE__ */ jsxRuntimeExports.jsx(StatCard, { label: "Completion", value: summary.totalArtifacts > 0 ? `${Math.round(summary.doneArtifacts / summary.totalArtifacts * 100)}%` : "0%" })
150374
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
150375
+ StatCard,
150376
+ {
150377
+ label: "Artifacts Complete",
150378
+ value: `${summary.doneArtifacts}/${summary.totalArtifacts}`
150379
+ }
150380
+ ),
150381
+ /* @__PURE__ */ jsxRuntimeExports.jsx(
150382
+ StatCard,
150383
+ {
150384
+ label: "Completion",
150385
+ value: summary.totalArtifacts > 0 ? `${Math.round(summary.doneArtifacts / summary.totalArtifacts * 100)}%` : "0%"
150386
+ }
150387
+ )
150298
150388
  ] }),
150299
150389
  !hasChanges && /* @__PURE__ */ jsxRuntimeExports.jsxs("div", { className: "border-border text-muted-foreground rounded-md border border-dashed p-6 text-center text-sm", children: [
150300
- "No active changes yet. Use ",
150301
- /* @__PURE__ */ jsxRuntimeExports.jsx("strong", { children: "/opsx:new" }),
150302
- " to create your first change."
150390
+ /* @__PURE__ */ jsxRuntimeExports.jsx("div", { children: "No active changes yet." }),
150391
+ /* @__PURE__ */ jsxRuntimeExports.jsxs(
150392
+ "button",
150393
+ {
150394
+ type: "button",
150395
+ onClick: runNewChange,
150396
+ className: "text-primary mt-2 inline-flex items-center gap-1 hover:underline",
150397
+ children: [
150398
+ /* @__PURE__ */ jsxRuntimeExports.jsx(Sparkles, { className: "h-3.5 w-3.5" }),
150399
+ "/opsx:new"
150400
+ ]
150401
+ }
150402
+ )
150303
150403
  ] }),
150304
150404
  hasChanges && /* @__PURE__ */ jsxRuntimeExports.jsx("div", { className: "border-border divide-border divide-y rounded-lg border", children: statuses?.map((status) => {
150305
150405
  const done = status.artifacts.filter((a2) => a2.status === "done").length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openspecui/web",
3
- "version": "1.1.1",
3
+ "version": "1.2.0",
4
4
  "type": "module",
5
5
  "bin": {
6
6
  "openspecui-ssg": "./dist-ssg/ssg-cli.mjs"
@@ -61,8 +61,8 @@
61
61
  "vitest": "^4.0.18",
62
62
  "yaml": "^2.8.0",
63
63
  "yargs": "^18.0.0",
64
+ "@openspecui/server": "1.2.0",
64
65
  "xterm-input-panel": "1.0.0",
65
- "@openspecui/server": "1.1.0",
66
66
  "@openspecui/search": "1.1.0"
67
67
  },
68
68
  "scripts": {