openspecui 1.6.0 → 2.0.1
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/cli.mjs +8 -9
- package/dist/index.mjs +1 -1
- package/dist/{src-Brh3druE.mjs → src-CFsMWl3_.mjs} +238 -60
- package/package.json +3 -3
- package/web/assets/{BufferResource-LpIscPOh.js → BufferResource-Cipj3hQ5.js} +1 -1
- package/web/assets/{CanvasRenderer-hdBAgk8Z.js → CanvasRenderer-C151fKcy.js} +1 -1
- package/web/assets/{Filter-DJVBXWdE.js → Filter-BpxymkGv.js} +1 -1
- package/web/assets/{RenderTargetSystem-CEuUrT8d.js → RenderTargetSystem-C0zk81Mh.js} +1 -1
- package/web/assets/{WebGLRenderer-DUSFltAk.js → WebGLRenderer-De3GrxdN.js} +1 -1
- package/web/assets/{WebGPURenderer-DafJULoy.js → WebGPURenderer-BkpejvST.js} +1 -1
- package/web/assets/{browserAll-DYvdsmhE.js → browserAll-B8KqF-Xa.js} +1 -1
- package/web/assets/{ghostty-web-BitlvuYh.js → ghostty-web-BO5ww0eG.js} +1 -1
- package/web/assets/{index-CYTyn82I.js → index-2DXouwnE.js} +1 -1
- package/web/assets/index-B-vvVL83.js +1541 -0
- package/web/assets/{index-hXwe0Xwc.js → index-Bp2dpDFJ.js} +1 -1
- package/web/assets/{index-CjHce-bH.js → index-Bxm-n0do.js} +1 -1
- package/web/assets/{index-Dge9ymDE.js → index-CDX9fioY.js} +1 -1
- package/web/assets/{index-CGTRVPmS.js → index-CFAzjIVm.js} +1 -1
- package/web/assets/{index-BhxOfd1V.js → index-Cj_nv8ue.js} +1 -1
- package/web/assets/{index-BwqUcS4o.js → index-Cv-LON1K.js} +1 -1
- package/web/assets/{index-DtJ1xKq6.js → index-CwA_uPvf.js} +1 -1
- package/web/assets/{index-DEgCfC-b.js → index-CxDip8xJ.js} +1 -1
- package/web/assets/{index-gPPYc26D.js → index-DL08rl2O.js} +1 -1
- package/web/assets/{index-5zLYkWge.js → index-DtTSWBHJ.js} +1 -1
- package/web/assets/{index-B8AH-4mO.js → index-DzK6gT7C.js} +1 -1
- package/web/assets/{index-DbrGteUX.js → index-Nl7iD8Yi.js} +1 -1
- package/web/assets/{index-CuiBRRWA.js → index-a8osabOh.js} +1 -1
- package/web/assets/index-aWxXp1oO.css +1 -0
- package/web/assets/{index-BXlwoClD.js → index-iROJdLzk.js} +1 -1
- package/web/assets/{webworkerAll-CFbGR7bA.js → webworkerAll-DPcI1cDK.js} +1 -1
- package/web/index.html +2 -2
- package/web/assets/index-CKfGQiMr.js +0 -1547
- package/web/assets/index-USotIqwU.css +0 -1
package/dist/cli.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { a as SchemaInfoSchema, c as toOpsxDisplayPath, d as DEFAULT_CONFIG, f as OpenSpecAdapter, i as SchemaDetailSchema, l as CliExecutor, m as __toESM, o as SchemaResolutionSchema, p as __commonJS, r as require_dist, s as TemplatesSchema, t as startServer, u as ConfigManager } from "./src-
|
|
2
|
+
import { a as SchemaInfoSchema, c as toOpsxDisplayPath, d as DEFAULT_CONFIG, f as OpenSpecAdapter, i as SchemaDetailSchema, l as CliExecutor, m as __toESM, o as SchemaResolutionSchema, p as __commonJS, r as require_dist, s as TemplatesSchema, t as startServer, u as ConfigManager } from "./src-CFsMWl3_.mjs";
|
|
3
3
|
import { createRequire } from "node:module";
|
|
4
4
|
import { basename, dirname, extname, join, normalize, relative, resolve } from "path";
|
|
5
5
|
import { readFile } from "node:fs/promises";
|
|
@@ -4507,7 +4507,7 @@ var yargs_default = Yargs;
|
|
|
4507
4507
|
//#endregion
|
|
4508
4508
|
//#region package.json
|
|
4509
4509
|
var import_dist = require_dist();
|
|
4510
|
-
var version = "
|
|
4510
|
+
var version = "2.0.1";
|
|
4511
4511
|
|
|
4512
4512
|
//#endregion
|
|
4513
4513
|
//#region src/export.ts
|
|
@@ -4766,12 +4766,11 @@ async function generateSnapshot(projectDir) {
|
|
|
4766
4766
|
const changesMeta = await adapter.listChangesWithMeta();
|
|
4767
4767
|
const changes = await Promise.all(changesMeta.map(async (meta) => {
|
|
4768
4768
|
const change = await adapter.readChange(meta.id);
|
|
4769
|
-
if (!change) return null;
|
|
4770
4769
|
const files = await adapter.readChangeFiles(meta.id);
|
|
4771
4770
|
const proposalFile = files.find((f) => f.path === "proposal.md");
|
|
4772
4771
|
const tasksFile = files.find((f) => f.path === "tasks.md");
|
|
4773
4772
|
const designFile = files.find((f) => f.path === "design.md");
|
|
4774
|
-
const deltas = (change
|
|
4773
|
+
const deltas = (change?.deltaSpecs || []).map((ds) => ({
|
|
4775
4774
|
capability: ds.specId,
|
|
4776
4775
|
content: ds.content || ""
|
|
4777
4776
|
}));
|
|
@@ -4781,11 +4780,11 @@ async function generateSnapshot(projectDir) {
|
|
|
4781
4780
|
proposal: proposalFile?.content || "",
|
|
4782
4781
|
tasks: tasksFile?.content,
|
|
4783
4782
|
design: designFile?.content,
|
|
4784
|
-
why: change
|
|
4785
|
-
whatChanges: change
|
|
4786
|
-
parsedTasks: change
|
|
4783
|
+
why: change?.why || "",
|
|
4784
|
+
whatChanges: change?.whatChanges || "",
|
|
4785
|
+
parsedTasks: change?.tasks || [],
|
|
4787
4786
|
deltas,
|
|
4788
|
-
progress: meta.progress,
|
|
4787
|
+
progress: change?.progress ?? meta.progress,
|
|
4789
4788
|
createdAt: meta.createdAt,
|
|
4790
4789
|
updatedAt: meta.updatedAt
|
|
4791
4790
|
};
|
|
@@ -4917,7 +4916,7 @@ async function generateSnapshot(projectDir) {
|
|
|
4917
4916
|
git,
|
|
4918
4917
|
config: uiConfig,
|
|
4919
4918
|
specs,
|
|
4920
|
-
changes
|
|
4919
|
+
changes,
|
|
4921
4920
|
archives,
|
|
4922
4921
|
projectMd,
|
|
4923
4922
|
agentsMd,
|
package/dist/index.mjs
CHANGED
|
@@ -1817,47 +1817,50 @@ var OpenSpecAdapter = class {
|
|
|
1817
1817
|
}
|
|
1818
1818
|
/**
|
|
1819
1819
|
* List changes with metadata (id, name, progress, and time info)
|
|
1820
|
-
*
|
|
1820
|
+
* Returns every change directory, including schema-specific layouts that
|
|
1821
|
+
* don't use proposal.md/tasks.md.
|
|
1821
1822
|
* Sorted by updatedAt descending (most recent first)
|
|
1822
1823
|
*/
|
|
1823
1824
|
async listChangesWithMeta() {
|
|
1824
1825
|
const ids = await this.listChanges();
|
|
1825
1826
|
return (await Promise.all(ids.map(async (id) => {
|
|
1826
1827
|
const change = await this.readChange(id);
|
|
1827
|
-
|
|
1828
|
-
const
|
|
1829
|
-
const timeInfo = await this.getFileTimeInfo(proposalPath);
|
|
1828
|
+
const changeDir = join(this.changesDir, id);
|
|
1829
|
+
const timeInfo = await this.getFileTimeInfo(changeDir);
|
|
1830
1830
|
return {
|
|
1831
1831
|
id,
|
|
1832
|
-
name: change
|
|
1833
|
-
progress: change
|
|
1832
|
+
name: change?.name ?? id,
|
|
1833
|
+
progress: change?.progress ?? {
|
|
1834
|
+
total: 0,
|
|
1835
|
+
completed: 0
|
|
1836
|
+
},
|
|
1834
1837
|
createdAt: timeInfo?.createdAt ?? 0,
|
|
1835
1838
|
updatedAt: timeInfo?.updatedAt ?? 0
|
|
1836
1839
|
};
|
|
1837
|
-
}))).
|
|
1840
|
+
}))).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
1838
1841
|
}
|
|
1839
1842
|
async listArchivedChanges() {
|
|
1840
1843
|
return reactiveReadDir(this.archiveDir, { directoriesOnly: true });
|
|
1841
1844
|
}
|
|
1842
1845
|
/**
|
|
1843
1846
|
* List archived changes with metadata and time info
|
|
1844
|
-
*
|
|
1847
|
+
* Returns every archive directory, including schema-specific layouts that
|
|
1848
|
+
* don't use proposal.md/tasks.md.
|
|
1845
1849
|
* Sorted by updatedAt descending (most recent first)
|
|
1846
1850
|
*/
|
|
1847
1851
|
async listArchivedChangesWithMeta() {
|
|
1848
1852
|
const ids = await this.listArchivedChanges();
|
|
1849
1853
|
return (await Promise.all(ids.map(async (id) => {
|
|
1850
1854
|
const change = await this.readArchivedChange(id);
|
|
1851
|
-
|
|
1852
|
-
const
|
|
1853
|
-
const timeInfo = await this.getFileTimeInfo(proposalPath);
|
|
1855
|
+
const archiveDir = join(this.archiveDir, id);
|
|
1856
|
+
const timeInfo = await this.getFileTimeInfo(archiveDir);
|
|
1854
1857
|
return {
|
|
1855
1858
|
id,
|
|
1856
|
-
name: change
|
|
1859
|
+
name: change?.name ?? id,
|
|
1857
1860
|
createdAt: timeInfo?.createdAt ?? 0,
|
|
1858
1861
|
updatedAt: timeInfo?.updatedAt ?? 0
|
|
1859
1862
|
};
|
|
1860
|
-
}))).
|
|
1863
|
+
}))).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
1861
1864
|
}
|
|
1862
1865
|
/**
|
|
1863
1866
|
* Read project.md content (reactive)
|
|
@@ -1923,7 +1926,7 @@ var OpenSpecAdapter = class {
|
|
|
1923
1926
|
});
|
|
1924
1927
|
}
|
|
1925
1928
|
async collectChangeFiles(root, dir) {
|
|
1926
|
-
const names = await reactiveReadDir(dir, { includeHidden:
|
|
1929
|
+
const names = await reactiveReadDir(dir, { includeHidden: true });
|
|
1927
1930
|
const files = [];
|
|
1928
1931
|
for (const name of names) {
|
|
1929
1932
|
const fullPath = join(dir, name);
|
|
@@ -5939,8 +5942,18 @@ const CURSOR_STYLE_VALUES = [
|
|
|
5939
5942
|
"underline",
|
|
5940
5943
|
"bar"
|
|
5941
5944
|
];
|
|
5945
|
+
const CODE_EDITOR_THEME_VALUES = [
|
|
5946
|
+
"github",
|
|
5947
|
+
"material",
|
|
5948
|
+
"vscode",
|
|
5949
|
+
"tokyo",
|
|
5950
|
+
"gruvbox",
|
|
5951
|
+
"monokai",
|
|
5952
|
+
"nord"
|
|
5953
|
+
];
|
|
5942
5954
|
const TERMINAL_RENDERER_ENGINE_VALUES = ["xterm", "ghostty"];
|
|
5943
5955
|
const TerminalRendererEngineSchema = enumType(TERMINAL_RENDERER_ENGINE_VALUES);
|
|
5956
|
+
const CodeEditorThemeSchema = enumType(CODE_EDITOR_THEME_VALUES);
|
|
5944
5957
|
const BASE_PACKAGE_MANAGER_RUNNERS = [
|
|
5945
5958
|
{
|
|
5946
5959
|
id: "npx",
|
|
@@ -6282,6 +6295,7 @@ const TerminalConfigSchema = objectType({
|
|
|
6282
6295
|
rendererEngine: stringType().default("xterm")
|
|
6283
6296
|
});
|
|
6284
6297
|
const DashboardConfigSchema = objectType({ trendPointLimit: numberType().int().min(20).max(500).default(100) });
|
|
6298
|
+
const CodeEditorConfigSchema = objectType({ theme: CodeEditorThemeSchema.default("github") });
|
|
6285
6299
|
/**
|
|
6286
6300
|
* OpenSpecUI 配置 Schema
|
|
6287
6301
|
*
|
|
@@ -6293,6 +6307,7 @@ const OpenSpecUIConfigSchema = objectType({
|
|
|
6293
6307
|
args: arrayType(stringType()).optional()
|
|
6294
6308
|
}).default({}),
|
|
6295
6309
|
theme: enumType(THEME_VALUES).default("system"),
|
|
6310
|
+
codeEditor: CodeEditorConfigSchema.default(CodeEditorConfigSchema.parse({})),
|
|
6296
6311
|
terminal: TerminalConfigSchema.default(TerminalConfigSchema.parse({})),
|
|
6297
6312
|
dashboard: DashboardConfigSchema.default(DashboardConfigSchema.parse({}))
|
|
6298
6313
|
});
|
|
@@ -6300,6 +6315,7 @@ const OpenSpecUIConfigSchema = objectType({
|
|
|
6300
6315
|
const DEFAULT_CONFIG = {
|
|
6301
6316
|
cli: {},
|
|
6302
6317
|
theme: "system",
|
|
6318
|
+
codeEditor: CodeEditorConfigSchema.parse({}),
|
|
6303
6319
|
terminal: TerminalConfigSchema.parse({}),
|
|
6304
6320
|
dashboard: DashboardConfigSchema.parse({})
|
|
6305
6321
|
};
|
|
@@ -6364,6 +6380,10 @@ var ConfigManager = class {
|
|
|
6364
6380
|
...current,
|
|
6365
6381
|
cli: nextCli,
|
|
6366
6382
|
theme: config.theme ?? current.theme,
|
|
6383
|
+
codeEditor: {
|
|
6384
|
+
...current.codeEditor,
|
|
6385
|
+
...config.codeEditor
|
|
6386
|
+
},
|
|
6367
6387
|
terminal: {
|
|
6368
6388
|
...current.terminal,
|
|
6369
6389
|
...config.terminal
|
|
@@ -6577,13 +6597,15 @@ var CliExecutor = class {
|
|
|
6577
6597
|
/**
|
|
6578
6598
|
* 执行 openspec init(非交互式)
|
|
6579
6599
|
*/
|
|
6580
|
-
async init(
|
|
6581
|
-
const
|
|
6582
|
-
|
|
6583
|
-
"
|
|
6584
|
-
"--tools",
|
|
6585
|
-
|
|
6586
|
-
|
|
6600
|
+
async init(options) {
|
|
6601
|
+
const args = ["init"];
|
|
6602
|
+
if (options?.tools !== void 0) {
|
|
6603
|
+
const toolsArg = Array.isArray(options.tools) ? options.tools.join(",") : options.tools;
|
|
6604
|
+
args.push("--tools", toolsArg);
|
|
6605
|
+
}
|
|
6606
|
+
if (options?.profile) args.push("--profile", options.profile);
|
|
6607
|
+
if (options?.force) args.push("--force");
|
|
6608
|
+
return this.execute(args);
|
|
6587
6609
|
}
|
|
6588
6610
|
/**
|
|
6589
6611
|
* 执行 openspec archive <changeId>(非交互式)
|
|
@@ -6750,13 +6772,15 @@ var CliExecutor = class {
|
|
|
6750
6772
|
/**
|
|
6751
6773
|
* 流式执行 openspec init
|
|
6752
6774
|
*/
|
|
6753
|
-
initStream(
|
|
6754
|
-
const
|
|
6755
|
-
|
|
6756
|
-
"
|
|
6757
|
-
"--tools",
|
|
6758
|
-
|
|
6759
|
-
|
|
6775
|
+
initStream(options, onEvent) {
|
|
6776
|
+
const args = ["init"];
|
|
6777
|
+
if (options.tools !== void 0) {
|
|
6778
|
+
const toolsArg = Array.isArray(options.tools) ? options.tools.join(",") : options.tools;
|
|
6779
|
+
args.push("--tools", toolsArg);
|
|
6780
|
+
}
|
|
6781
|
+
if (options.profile) args.push("--profile", options.profile);
|
|
6782
|
+
if (options.force) args.push("--force");
|
|
6783
|
+
return this.executeStream(args, onEvent);
|
|
6760
6784
|
}
|
|
6761
6785
|
/**
|
|
6762
6786
|
* 流式执行 openspec archive
|
|
@@ -6841,7 +6865,9 @@ const SKILL_NAMES = [
|
|
|
6841
6865
|
"openspec-sync-specs",
|
|
6842
6866
|
"openspec-archive-change",
|
|
6843
6867
|
"openspec-bulk-archive-change",
|
|
6844
|
-
"openspec-verify-change"
|
|
6868
|
+
"openspec-verify-change",
|
|
6869
|
+
"openspec-onboard",
|
|
6870
|
+
"openspec-propose"
|
|
6845
6871
|
];
|
|
6846
6872
|
/**
|
|
6847
6873
|
* 所有支持的 AI 工具配置
|
|
@@ -6960,6 +6986,13 @@ const AI_TOOLS = [
|
|
|
6960
6986
|
successLabel: "Kilo Code",
|
|
6961
6987
|
skillsDir: ".kilocode"
|
|
6962
6988
|
},
|
|
6989
|
+
{
|
|
6990
|
+
name: "Kiro",
|
|
6991
|
+
value: "kiro",
|
|
6992
|
+
available: true,
|
|
6993
|
+
successLabel: "Kiro",
|
|
6994
|
+
skillsDir: ".kiro"
|
|
6995
|
+
},
|
|
6963
6996
|
{
|
|
6964
6997
|
name: "OpenCode",
|
|
6965
6998
|
value: "opencode",
|
|
@@ -6967,6 +7000,13 @@ const AI_TOOLS = [
|
|
|
6967
7000
|
successLabel: "OpenCode",
|
|
6968
7001
|
skillsDir: ".opencode"
|
|
6969
7002
|
},
|
|
7003
|
+
{
|
|
7004
|
+
name: "Pi",
|
|
7005
|
+
value: "pi",
|
|
7006
|
+
available: true,
|
|
7007
|
+
successLabel: "Pi",
|
|
7008
|
+
skillsDir: ".pi"
|
|
7009
|
+
},
|
|
6970
7010
|
{
|
|
6971
7011
|
name: "Qoder",
|
|
6972
7012
|
value: "qoder",
|
|
@@ -23950,6 +23990,12 @@ const t = initTRPC.context().create();
|
|
|
23950
23990
|
const router = t.router;
|
|
23951
23991
|
const publicProcedure = t.procedure;
|
|
23952
23992
|
const execFileAsync = promisify$1(execFile);
|
|
23993
|
+
const OPSX_CORE_PROFILE_WORKFLOWS = [
|
|
23994
|
+
"propose",
|
|
23995
|
+
"explore",
|
|
23996
|
+
"apply",
|
|
23997
|
+
"archive"
|
|
23998
|
+
];
|
|
23953
23999
|
const dashboardGitTaskStatusEmitter = new EventEmitter$1();
|
|
23954
24000
|
dashboardGitTaskStatusEmitter.setMaxListeners(200);
|
|
23955
24001
|
const dashboardGitTaskStatus = {
|
|
@@ -24023,6 +24069,94 @@ function requireChangeId(changeId) {
|
|
|
24023
24069
|
if (!changeId) throw new Error("change is required");
|
|
24024
24070
|
return changeId;
|
|
24025
24071
|
}
|
|
24072
|
+
function parseOpsxProfileListJson(stdout) {
|
|
24073
|
+
try {
|
|
24074
|
+
const parsed = JSON.parse(stdout);
|
|
24075
|
+
const profile = parsed.profile === "custom" ? "custom" : "core";
|
|
24076
|
+
return {
|
|
24077
|
+
profile,
|
|
24078
|
+
delivery: parsed.delivery === "skills" || parsed.delivery === "commands" ? parsed.delivery : "both",
|
|
24079
|
+
workflows: Array.isArray(parsed.workflows) ? parsed.workflows.filter((item) => typeof item === "string" && item.length > 0) : profile === "core" ? [...OPSX_CORE_PROFILE_WORKFLOWS] : []
|
|
24080
|
+
};
|
|
24081
|
+
} catch {
|
|
24082
|
+
return null;
|
|
24083
|
+
}
|
|
24084
|
+
}
|
|
24085
|
+
function parseOpsxConfigDrift(output) {
|
|
24086
|
+
const lines = output.split(/\r?\n/).map((line) => line.trim()).filter((line) => line.length > 0);
|
|
24087
|
+
const warningLine = lines.find((line) => /global config.+not applied.+project/i.test(line)) ?? lines.find((line) => /out of sync/i.test(line)) ?? lines.find((line) => /run\s+`?openspec\s+update`?/i.test(line)) ?? null;
|
|
24088
|
+
return {
|
|
24089
|
+
drift: warningLine !== null,
|
|
24090
|
+
warningText: warningLine
|
|
24091
|
+
};
|
|
24092
|
+
}
|
|
24093
|
+
async function fetchOpsxProfileState(ctx) {
|
|
24094
|
+
const configListJson = await ctx.cliExecutor.execute([
|
|
24095
|
+
"config",
|
|
24096
|
+
"list",
|
|
24097
|
+
"--json"
|
|
24098
|
+
]);
|
|
24099
|
+
if (!configListJson.success) return {
|
|
24100
|
+
available: false,
|
|
24101
|
+
profile: null,
|
|
24102
|
+
delivery: null,
|
|
24103
|
+
workflows: [],
|
|
24104
|
+
driftStatus: "unknown",
|
|
24105
|
+
warningText: null,
|
|
24106
|
+
error: configListJson.stderr || "Failed to load profile config."
|
|
24107
|
+
};
|
|
24108
|
+
const parsed = parseOpsxProfileListJson(configListJson.stdout);
|
|
24109
|
+
if (!parsed) return {
|
|
24110
|
+
available: false,
|
|
24111
|
+
profile: null,
|
|
24112
|
+
delivery: null,
|
|
24113
|
+
workflows: [],
|
|
24114
|
+
driftStatus: "unknown",
|
|
24115
|
+
warningText: null,
|
|
24116
|
+
error: "Invalid JSON from `openspec config list --json`."
|
|
24117
|
+
};
|
|
24118
|
+
const configListText = await ctx.cliExecutor.execute(["config", "list"]);
|
|
24119
|
+
if (!configListText.success) return {
|
|
24120
|
+
available: true,
|
|
24121
|
+
profile: parsed.profile,
|
|
24122
|
+
delivery: parsed.delivery,
|
|
24123
|
+
workflows: parsed.workflows,
|
|
24124
|
+
driftStatus: "unknown",
|
|
24125
|
+
warningText: null
|
|
24126
|
+
};
|
|
24127
|
+
const drift = parseOpsxConfigDrift(`${configListText.stdout}\n${configListText.stderr}`);
|
|
24128
|
+
return {
|
|
24129
|
+
available: true,
|
|
24130
|
+
profile: parsed.profile,
|
|
24131
|
+
delivery: parsed.delivery,
|
|
24132
|
+
workflows: parsed.workflows,
|
|
24133
|
+
driftStatus: drift.drift ? "drift" : "in-sync",
|
|
24134
|
+
warningText: drift.warningText
|
|
24135
|
+
};
|
|
24136
|
+
}
|
|
24137
|
+
async function resolveGlobalConfigPath(ctx) {
|
|
24138
|
+
const result = await ctx.cliExecutor.execute(["config", "path"]);
|
|
24139
|
+
if (!result.success) throw new Error(result.stderr || "Failed to resolve OpenSpec global config path.");
|
|
24140
|
+
const path$1 = result.stdout.trim();
|
|
24141
|
+
if (!path$1) throw new Error("OpenSpec global config path is empty.");
|
|
24142
|
+
return path$1;
|
|
24143
|
+
}
|
|
24144
|
+
async function fetchGlobalConfigJson(ctx) {
|
|
24145
|
+
const result = await ctx.cliExecutor.execute([
|
|
24146
|
+
"config",
|
|
24147
|
+
"list",
|
|
24148
|
+
"--json"
|
|
24149
|
+
]);
|
|
24150
|
+
if (!result.success) throw new Error(result.stderr || "Failed to load OpenSpec global config.");
|
|
24151
|
+
try {
|
|
24152
|
+
const parsed = JSON.parse(result.stdout);
|
|
24153
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("OpenSpec global config must be a JSON object.");
|
|
24154
|
+
return parsed;
|
|
24155
|
+
} catch (error) {
|
|
24156
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
24157
|
+
throw new Error(`Invalid JSON from \`openspec config list --json\`: ${message}`);
|
|
24158
|
+
}
|
|
24159
|
+
}
|
|
24026
24160
|
function ensureEditableSource(source, label) {
|
|
24027
24161
|
if (source === "package") throw new Error(`${label} is read-only (package source)`);
|
|
24028
24162
|
}
|
|
@@ -24145,6 +24279,35 @@ async function fetchDashboardOverview(ctx, reason = "dashboard-refresh") {
|
|
|
24145
24279
|
ctx.adapter.listChangesWithMeta(),
|
|
24146
24280
|
ctx.adapter.listArchivedChangesWithMeta()
|
|
24147
24281
|
]);
|
|
24282
|
+
await ctx.kernel.waitForWarmup();
|
|
24283
|
+
await ctx.kernel.ensureStatusList();
|
|
24284
|
+
const statusList = ctx.kernel.getStatusList();
|
|
24285
|
+
const changeMetaMap = new Map(changeMetas.map((change) => [change.id, change]));
|
|
24286
|
+
const activeChangeIds = new Set([...changeMetas.map((change) => change.id), ...statusList.map((status) => status.changeName)]);
|
|
24287
|
+
const statusByChange = new Map(statusList.map((status) => [status.changeName, status]));
|
|
24288
|
+
const activeChanges = (await Promise.all([...activeChangeIds].map(async (changeId) => {
|
|
24289
|
+
const status = statusByChange.get(changeId);
|
|
24290
|
+
const changeMeta = changeMetaMap.get(changeId);
|
|
24291
|
+
const statInfo = await reactiveStat(join$1(ctx.projectDir, "openspec", "changes", changeId));
|
|
24292
|
+
let progress = changeMeta?.progress ?? {
|
|
24293
|
+
total: 0,
|
|
24294
|
+
completed: 0
|
|
24295
|
+
};
|
|
24296
|
+
if (status) try {
|
|
24297
|
+
await ctx.kernel.ensureApplyInstructions(changeId, status.schemaName);
|
|
24298
|
+
const apply = ctx.kernel.getApplyInstructions(changeId, status.schemaName);
|
|
24299
|
+
progress = {
|
|
24300
|
+
total: apply.progress.total,
|
|
24301
|
+
completed: apply.progress.complete
|
|
24302
|
+
};
|
|
24303
|
+
} catch {}
|
|
24304
|
+
return {
|
|
24305
|
+
id: changeId,
|
|
24306
|
+
name: changeMeta?.name ?? changeId,
|
|
24307
|
+
progress,
|
|
24308
|
+
updatedAt: changeMeta?.updatedAt ?? statInfo?.mtime ?? 0
|
|
24309
|
+
};
|
|
24310
|
+
}))).sort((a, b) => b.updatedAt - a.updatedAt);
|
|
24148
24311
|
const archivedChanges = (await Promise.all(archiveMetas.map(async (meta) => {
|
|
24149
24312
|
const change = await ctx.adapter.readArchivedChange(meta.id);
|
|
24150
24313
|
if (!change) return null;
|
|
@@ -24165,12 +24328,6 @@ async function fetchDashboardOverview(ctx, reason = "dashboard-refresh") {
|
|
|
24165
24328
|
updatedAt: meta.updatedAt
|
|
24166
24329
|
};
|
|
24167
24330
|
}))).filter((item) => item !== null).sort((a, b) => b.requirements - a.requirements || b.updatedAt - a.updatedAt);
|
|
24168
|
-
const activeChanges = changeMetas.map((change) => ({
|
|
24169
|
-
id: change.id,
|
|
24170
|
-
name: change.name,
|
|
24171
|
-
progress: change.progress,
|
|
24172
|
-
updatedAt: change.updatedAt
|
|
24173
|
-
}));
|
|
24174
24331
|
const requirements = specifications.reduce((sum, spec) => sum + spec.requirements, 0);
|
|
24175
24332
|
const tasksTotal = activeChanges.reduce((sum, change) => sum + change.progress.total, 0);
|
|
24176
24333
|
const tasksCompleted = activeChanges.reduce((sum, change) => sum + change.progress.completed, 0);
|
|
@@ -24501,6 +24658,7 @@ const configRouter = router({
|
|
|
24501
24658
|
"dark",
|
|
24502
24659
|
"system"
|
|
24503
24660
|
]).optional(),
|
|
24661
|
+
codeEditor: objectType({ theme: CodeEditorThemeSchema.optional() }).optional(),
|
|
24504
24662
|
terminal: TerminalConfigSchema.omit({ rendererEngine: true }).partial().extend({ rendererEngine: TerminalRendererEngineSchema.optional() }).optional(),
|
|
24505
24663
|
dashboard: DashboardConfigSchema.partial().optional()
|
|
24506
24664
|
})).mutation(async ({ ctx, input }) => {
|
|
@@ -24508,8 +24666,9 @@ const configRouter = router({
|
|
|
24508
24666
|
const hasCliArgs = input.cli !== void 0 && Object.prototype.hasOwnProperty.call(input.cli, "args");
|
|
24509
24667
|
if (hasCliCommand && !hasCliArgs) {
|
|
24510
24668
|
await ctx.configManager.setCliCommand(input.cli?.command ?? "");
|
|
24511
|
-
if (input.theme !== void 0 || input.terminal !== void 0 || input.dashboard !== void 0) await ctx.configManager.writeConfig({
|
|
24669
|
+
if (input.theme !== void 0 || input.codeEditor !== void 0 || input.terminal !== void 0 || input.dashboard !== void 0) await ctx.configManager.writeConfig({
|
|
24512
24670
|
theme: input.theme,
|
|
24671
|
+
codeEditor: input.codeEditor,
|
|
24513
24672
|
terminal: input.terminal,
|
|
24514
24673
|
dashboard: input.dashboard
|
|
24515
24674
|
});
|
|
@@ -24570,18 +24729,41 @@ const cliRouter = router({
|
|
|
24570
24729
|
successLabel: tool.successLabel
|
|
24571
24730
|
}));
|
|
24572
24731
|
}),
|
|
24732
|
+
getProfileState: publicProcedure.query(async ({ ctx }) => {
|
|
24733
|
+
return fetchOpsxProfileState(ctx);
|
|
24734
|
+
}),
|
|
24735
|
+
getGlobalConfigPath: publicProcedure.query(async ({ ctx }) => {
|
|
24736
|
+
return { path: await resolveGlobalConfigPath(ctx) };
|
|
24737
|
+
}),
|
|
24738
|
+
getGlobalConfig: publicProcedure.query(async ({ ctx }) => {
|
|
24739
|
+
return fetchGlobalConfigJson(ctx);
|
|
24740
|
+
}),
|
|
24741
|
+
setGlobalConfig: publicProcedure.input(objectType({ config: recordType(stringType(), unknownType()) })).mutation(async ({ ctx, input }) => {
|
|
24742
|
+
const configPath = await resolveGlobalConfigPath(ctx);
|
|
24743
|
+
await mkdir$1(dirname$1(configPath), { recursive: true });
|
|
24744
|
+
await writeFile$1(configPath, `${JSON.stringify(input.config, null, 2)}\n`, "utf8");
|
|
24745
|
+
return { success: true };
|
|
24746
|
+
}),
|
|
24573
24747
|
getConfiguredTools: publicProcedure.query(async ({ ctx }) => {
|
|
24574
24748
|
return getConfiguredTools(ctx.projectDir);
|
|
24575
24749
|
}),
|
|
24576
24750
|
subscribeConfiguredTools: publicProcedure.subscription(({ ctx }) => {
|
|
24577
24751
|
return createReactiveSubscription(() => getConfiguredTools(ctx.projectDir));
|
|
24578
24752
|
}),
|
|
24579
|
-
init: publicProcedure.input(objectType({
|
|
24580
|
-
|
|
24581
|
-
|
|
24582
|
-
|
|
24583
|
-
|
|
24584
|
-
|
|
24753
|
+
init: publicProcedure.input(objectType({
|
|
24754
|
+
tools: unionType([
|
|
24755
|
+
arrayType(stringType()),
|
|
24756
|
+
literalType("all"),
|
|
24757
|
+
literalType("none")
|
|
24758
|
+
]).optional(),
|
|
24759
|
+
profile: enumType(["core", "custom"]).optional(),
|
|
24760
|
+
force: booleanType().optional()
|
|
24761
|
+
}).optional()).mutation(async ({ ctx, input }) => {
|
|
24762
|
+
return ctx.cliExecutor.init({
|
|
24763
|
+
tools: input?.tools,
|
|
24764
|
+
profile: input?.profile,
|
|
24765
|
+
force: input?.force
|
|
24766
|
+
});
|
|
24585
24767
|
}),
|
|
24586
24768
|
archive: publicProcedure.input(objectType({
|
|
24587
24769
|
changeId: stringType(),
|
|
@@ -24608,12 +24790,20 @@ const cliRouter = router({
|
|
|
24608
24790
|
execute: publicProcedure.input(objectType({ args: arrayType(stringType()) })).mutation(async ({ ctx, input }) => {
|
|
24609
24791
|
return ctx.cliExecutor.execute(input.args);
|
|
24610
24792
|
}),
|
|
24611
|
-
initStream: publicProcedure.input(objectType({
|
|
24612
|
-
|
|
24613
|
-
|
|
24614
|
-
|
|
24615
|
-
|
|
24616
|
-
|
|
24793
|
+
initStream: publicProcedure.input(objectType({
|
|
24794
|
+
tools: unionType([
|
|
24795
|
+
arrayType(stringType()),
|
|
24796
|
+
literalType("all"),
|
|
24797
|
+
literalType("none")
|
|
24798
|
+
]).optional(),
|
|
24799
|
+
profile: enumType(["core", "custom"]).optional(),
|
|
24800
|
+
force: booleanType().optional()
|
|
24801
|
+
}).optional()).subscription(({ ctx, input }) => {
|
|
24802
|
+
return createCliStreamObservable((onEvent) => ctx.cliExecutor.initStream({
|
|
24803
|
+
tools: input?.tools,
|
|
24804
|
+
profile: input?.profile,
|
|
24805
|
+
force: input?.force
|
|
24806
|
+
}, onEvent));
|
|
24617
24807
|
}),
|
|
24618
24808
|
archiveStream: publicProcedure.input(objectType({
|
|
24619
24809
|
changeId: stringType(),
|
|
@@ -24847,18 +25037,6 @@ const opsxRouter = router({
|
|
|
24847
25037
|
return ctx.kernel.getChangeIds();
|
|
24848
25038
|
});
|
|
24849
25039
|
}),
|
|
24850
|
-
changeMetadata: publicProcedure.input(objectType({ changeId: stringType() })).query(async ({ ctx, input }) => {
|
|
24851
|
-
await ctx.kernel.waitForWarmup();
|
|
24852
|
-
await ctx.kernel.ensureChangeMetadata(input.changeId);
|
|
24853
|
-
return ctx.kernel.getChangeMetadata(input.changeId);
|
|
24854
|
-
}),
|
|
24855
|
-
subscribeChangeMetadata: publicProcedure.input(objectType({ changeId: stringType() })).subscription(({ ctx, input }) => {
|
|
24856
|
-
return createReactiveSubscription(async () => {
|
|
24857
|
-
await ctx.kernel.waitForWarmup();
|
|
24858
|
-
await ctx.kernel.ensureChangeMetadata(input.changeId);
|
|
24859
|
-
return ctx.kernel.getChangeMetadata(input.changeId);
|
|
24860
|
-
});
|
|
24861
|
-
}),
|
|
24862
25040
|
readArtifactOutput: publicProcedure.input(objectType({
|
|
24863
25041
|
changeId: stringType(),
|
|
24864
25042
|
outputPath: stringType()
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "openspecui",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"description": "OpenSpec UI - Visual interface for spec-driven development",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.mjs",
|
|
@@ -33,8 +33,8 @@
|
|
|
33
33
|
"typescript": "^5.7.2",
|
|
34
34
|
"vitest": "^2.1.8",
|
|
35
35
|
"yargs": "^18.0.0",
|
|
36
|
-
"@openspecui/
|
|
37
|
-
"@openspecui/
|
|
36
|
+
"@openspecui/web": "2.0.1",
|
|
37
|
+
"@openspecui/server": "2.0.0"
|
|
38
38
|
},
|
|
39
39
|
"scripts": {
|
|
40
40
|
"build": "pnpm run build:web && pnpm run build:copy-web && tsdown",
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{y as U,z as g,A as c,B as S,D as _,F as m,H as I,J as p}from"./index-
|
|
1
|
+
import{y as U,z as g,A as c,B as S,D as _,F as m,H as I,J as p}from"./index-B-vvVL83.js";const x={name:"local-uniform-bit",vertex:{header:`
|
|
2
2
|
|
|
3
3
|
struct LocalUniforms {
|
|
4
4
|
uTransformMatrix:mat3x3<f32>,
|