owndesign 0.1.7 → 0.1.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1 -1
- package/dist/server/index.js +647 -1475
- package/dist/server/prompts/agents/component-audit.md +24 -0
- package/dist/server/prompts/agents/design-page.md +87 -55
- package/dist/server/prompts/index.ts +9 -16
- package/dist/server/templates/html/page-shell.html +65 -0
- package/dist/server/templates/index.ts +39 -0
- package/dist/web/assets/{angular-html-CoTKBCTn.js → angular-html-DCGj6j9k.js} +1 -1
- package/dist/web/assets/{angular-ts-B6lkmQt5.js → angular-ts-_jS5FvKQ.js} +1 -1
- package/dist/web/assets/{apl-DdUDDcTX.js → apl-COUiMcRO.js} +1 -1
- package/dist/web/assets/{arc-CpC_-kIU.js → arc-DO65316F.js} +1 -1
- package/dist/web/assets/architecture-7EHR7CIX-D10X4FnP.js +1 -0
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-BFC9sw4f.js → architectureDiagram-3BPJPVTR-4QTI95py.js} +1 -1
- package/dist/web/assets/{astro-D8dj_1e3.js → astro-DBm7xN0H.js} +1 -1
- package/dist/web/assets/{blade-BOBPcO2h.js → blade-BrcGRjeD.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-Dm-IZ0OK.js → blockDiagram-GPEHLZMM-DyW2gTLi.js} +1 -1
- package/dist/web/assets/{c-BuJlpWo1.js → c-DAqlvgYb.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-D_naMOBh.js → c4Diagram-AAUBKEIU-D7VLn3UY.js} +1 -1
- package/dist/web/assets/channel-D4A7yvhc.js +1 -0
- package/dist/web/assets/{chunk-2J33WTMH-Br9TjHyg.js → chunk-2J33WTMH-ZI7iZmam.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-BKXeBOxn.js → chunk-4BX2VUAB-BXZ1tYtp.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-D3MxtENu.js → chunk-55IACEB6-BruFuyzh.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-9i7OtYmm.js → chunk-727SXJPM-WfltwAyi.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-C1rNd_R7.js → chunk-AQP2D5EJ-m-6Oqccg.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-fJyYpXV-.js → chunk-FMBD7UC4-CTpop8z0.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-DNlEVqx2.js → chunk-ND2GUHAM-DXbYu7j4.js} +1 -1
- package/dist/web/assets/chunk-QZHKN3VN-JoHxC1mG.js +1 -0
- package/dist/web/assets/classDiagram-4FO5ZUOK-D2XS2ai4.js +1 -0
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-D2XS2ai4.js +1 -0
- package/dist/web/assets/{cobol-ClEhNYgi.js → cobol-CV8XIe3g.js} +1 -1
- package/dist/web/assets/{coffee-DKH3A-3k.js → coffee-CjS-bqem.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A-CKEXfMFa.js → cose-bilkent-S5V4N54A-qeF_aTDs.js} +1 -1
- package/dist/web/assets/{cpp-Dg0_NLWR.js → cpp-BWTrby03.js} +1 -1
- package/dist/web/assets/{crystal-B-pl8MQM.js → crystal-B4jSurfu.js} +1 -1
- package/dist/web/assets/{css-Q2XFe7KV.js → css-CXDKo6HN.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-CGLXhpG-.js → dagre-BM42HDAG-mtpIrAd-.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-Yz0i_67x.js → diagram-2AECGRRQ-C2daXqRz.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-BnSJ2Z2M.js → diagram-5GNKFQAL-Yn3Kkd1e.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-B15W-hhD.js → diagram-KO2AKTUF-BSZBlF1_.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-BLsYWrS9.js → diagram-LMA3HP47-C-o1wwy4.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-73omsPnV.js → diagram-OG6HWLK6-BadUuiav.js} +1 -1
- package/dist/web/assets/{edge-Dhh-Fs5C.js → edge-IP3F2dQ8.js} +1 -1
- package/dist/web/assets/{elixir-COHWreUF.js → elixir-DNv4dzV2.js} +1 -1
- package/dist/web/assets/{elm-CYxhy8U2.js → elm-DGlxwCzv.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-a5r4A3JM.js → erDiagram-TEJ5UH35-uLYwqFWM.js} +1 -1
- package/dist/web/assets/{erb-Dl2ohr-E.js → erb-Cx4MSh15.js} +1 -1
- package/dist/web/assets/eventmodeling-FCH6USID-CHKTnhfi.js +1 -0
- package/dist/web/assets/{flowDiagram-I6XJVG4X-Dmc3vUIl.js → flowDiagram-I6XJVG4X-C-JzpWfx.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-CRZVm0L0.js → ganttDiagram-6RSMTGT7-Be3WGPbk.js} +1 -1
- package/dist/web/assets/{git-rebase-DpESal6m.js → git-rebase-C_0JGP0g.js} +1 -1
- package/dist/web/assets/gitGraph-WXDBUCRP-aSGYLvSW.js +1 -0
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-DhRyyOcn.js → gitGraphDiagram-PVQCEYII-DqJ0yj3L.js} +1 -1
- package/dist/web/assets/{glimmer-js-X_N0IQZ1.js → glimmer-js-B7LRT5BS.js} +1 -1
- package/dist/web/assets/{glimmer-ts-CoiHLEBh.js → glimmer-ts-CojGZlfZ.js} +1 -1
- package/dist/web/assets/{glsl-jTdcbPse.js → glsl-CbmtoTb8.js} +1 -1
- package/dist/web/assets/{graphql-CSN8TYN_.js → graphql-qYEIhTt7.js} +1 -1
- package/dist/web/assets/{hack-Dv67vUdK.js → hack-DxHXCCdq.js} +1 -1
- package/dist/web/assets/{haml-BFAyoHic.js → haml-CiwrkJ8T.js} +1 -1
- package/dist/web/assets/{handlebars-DsO_0Mb7.js → handlebars-Cn5UPYUQ.js} +1 -1
- package/dist/web/assets/{highlighted-body-OFNGDK62-Bsqvzkqq.js → highlighted-body-OFNGDK62-ehiuxKzz.js} +1 -1
- package/dist/web/assets/{html-hcrGAGxi.js → html-Cst8cPsk.js} +1 -1
- package/dist/web/assets/{html-derivative-nsyf9xDk.js → html-derivative-lnPAgvry.js} +1 -1
- package/dist/web/assets/{http-CQ7kMaQ9.js → http-C5VDSUzW.js} +1 -1
- package/dist/web/assets/{hurl-w8EbNg5E.js → hurl-BFlMJrL0.js} +1 -1
- package/dist/web/assets/{index-DAN9Q3vY.js → index-Ai406YO8.js} +186 -186
- package/dist/web/assets/index-Cy3xCQ0m.css +2 -0
- package/dist/web/assets/info-J43DQDTF-C945CGZU.js +1 -0
- package/dist/web/assets/{infoDiagram-5YYISTIA-C2F76qt2.js → infoDiagram-5YYISTIA-CIanyf0S.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-CZ272mnP.js → ishikawaDiagram-YF4QCWOH--1RL7uDF.js} +1 -1
- package/dist/web/assets/{java-BL-j72lp.js → java-BGahCCe1.js} +1 -1
- package/dist/web/assets/{javascript-D-RCZsZB.js → javascript-D5uMI8kB.js} +1 -1
- package/dist/web/assets/{jinja-3re3UTai.js → jinja-B4krr1-l.js} +1 -1
- package/dist/web/assets/{jison-aPrUrs4_.js → jison-BMMSlNZQ.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-Kbp9PKPx.js → journeyDiagram-JHISSGLW-lkcDMGR5.js} +1 -1
- package/dist/web/assets/{json-DVgA95cK.js → json-DXJMlo78.js} +1 -1
- package/dist/web/assets/{jsx-CTgF7iub.js → jsx-C_bl3hBI.js} +1 -1
- package/dist/web/assets/{julia-Deji7okx.js → julia-Sc_vYT5t.js} +1 -1
- package/dist/web/assets/{just-CaYOtqeh.js → just-CILkVz1n.js} +1 -1
- package/dist/web/assets/{kanban-definition-UN3LZRKU-zVFckm48.js → kanban-definition-UN3LZRKU-Bi_hSUym.js} +1 -1
- package/dist/web/assets/{latex-DjTDu_8e.js → latex-DUmFelG8.js} +1 -1
- package/dist/web/assets/{linear-HBblcI1g.js → linear-Dpnh4Vbv.js} +1 -1
- package/dist/web/assets/{liquid-BcpQGDFc.js → liquid-BnB6JKD1.js} +1 -1
- package/dist/web/assets/{lua-CuYpYTBI.js → lua-DhxAQE0G.js} +1 -1
- package/dist/web/assets/{marko-DgfLsR3g.js → marko-CyzzY1hm.js} +1 -1
- package/dist/web/assets/{mdc-CJyxXGTG.js → mdc-BptK7sXI.js} +1 -1
- package/dist/web/assets/mermaid-GHXKKRXX-DOJ_Dro4.js +1 -0
- package/dist/web/assets/{mermaid-parser.core-I66T9jsL.js → mermaid-parser.core-DShH95hL.js} +2 -2
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-DaGOAyRB.js → mindmap-definition-RKZ34NQL-LqYVQ-zW.js} +1 -1
- package/dist/web/assets/{nginx-BoUl7sBZ.js → nginx-CR9TIk16.js} +1 -1
- package/dist/web/assets/{nim-CrEFP-aj.js → nim-DzWiwbcf.js} +1 -1
- package/dist/web/assets/packet-YPE3B663-DuGIOCMW.js +1 -0
- package/dist/web/assets/{perl-CZELP4Ds.js → perl-CgrDNBt5.js} +1 -1
- package/dist/web/assets/{php-CWKE0mzg.js → php-DtuJQDgr.js} +1 -1
- package/dist/web/assets/pie-LRSECV5Y-BYeTdyfo.js +1 -0
- package/dist/web/assets/{pieDiagram-4H26LBE5-CZEnKsEr.js → pieDiagram-4H26LBE5-B7_i9XPe.js} +1 -1
- package/dist/web/assets/{pug-ZalflcaW.js → pug--9BJCC2D.js} +1 -1
- package/dist/web/assets/{qml-D8g9QUr3.js → qml-C3iH27Ik.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-DsVGBWIs.js → quadrantDiagram-W4KKPZXB-C2tSamWU.js} +1 -1
- package/dist/web/assets/{r-t-w7nxIu.js → r-CqKTpWRo.js} +1 -1
- package/dist/web/assets/radar-GUYGQ44K-Cqw7n4df.js +1 -0
- package/dist/web/assets/{razor-KKTzZ9mx.js → razor-BNavdAx6.js} +1 -1
- package/dist/web/assets/{regexp-a1jUuWbn.js → regexp-zwVenqvj.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-BTfqkfe2.js → requirementDiagram-4Y6WPE33-iIbtgBoU.js} +1 -1
- package/dist/web/assets/{rst-aqfBGGXb.js → rst-BHNeA4na.js} +1 -1
- package/dist/web/assets/{ruby-BEZTW4wN.js → ruby-CkHs-w2j.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-DypLejq4.js → sankeyDiagram-5OEKKPKP-B05ECsV0.js} +1 -1
- package/dist/web/assets/{sas-C6p8OBCV.js → sas-COQs-ItK.js} +1 -1
- package/dist/web/assets/{scss-C8GTc8vc.js → scss-DVsO7q0E.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DNDK0sjs.js → sequenceDiagram-3UESZ5HK-CHtmtTcK.js} +1 -1
- package/dist/web/assets/{shellscript-CDcqP7X6.js → shellscript-DoNwQ9Oz.js} +1 -1
- package/dist/web/assets/{shellsession-CWzpCh1C.js → shellsession-DvIRWuae.js} +1 -1
- package/dist/web/assets/{soy-CepCYBkA.js → soy--AEUdRNF.js} +1 -1
- package/dist/web/assets/{sql-CAysnE0k.js → sql-BVv9DbTm.js} +1 -1
- package/dist/web/assets/{stata-BGr_WZqN.js → stata-Bzv07ePm.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-CnSW064B.js → stateDiagram-AJRCARHV-COllcCkO.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-D9SuEs4r.js +1 -0
- package/dist/web/assets/{surrealql-C7gNmBEt.js → surrealql-ChG0u1_y.js} +1 -1
- package/dist/web/assets/{svelte-D-4kj-uB.js → svelte-CTk-krYk.js} +1 -1
- package/dist/web/assets/{templ-BP_fNCUb.js → templ-CIOvt0Gn.js} +1 -1
- package/dist/web/assets/{tex-vDHHhfH8.js → tex-BLbgub0O.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-RE08Mx9v.js → timeline-definition-PNZ67QCA-Dj0aLVCY.js} +1 -1
- package/dist/web/assets/treeView-BLDUP644-Bsp-7xCN.js +1 -0
- package/dist/web/assets/treemap-LRROVOQU-BsTzhV2b.js +1 -0
- package/dist/web/assets/{ts-tags-BhUtB8KF.js → ts-tags-Cjp84wCR.js} +1 -1
- package/dist/web/assets/{tsx-CYOMJ3wf.js → tsx-BYXwwi4R.js} +1 -1
- package/dist/web/assets/{twig-DMJPvFzt.js → twig-CJXgadPB.js} +1 -1
- package/dist/web/assets/{typescript-JJOZ5Q74.js → typescript-SkJO5gXX.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-CTiIiyn-.js → vennDiagram-CIIHVFJN-DotTRq6i.js} +1 -1
- package/dist/web/assets/{vue-D6hN_u9i.js → vue-DnNvWsLF.js} +1 -1
- package/dist/web/assets/{vue-html-B8MKJvvw.js → vue-html-BtDfjhCy.js} +1 -1
- package/dist/web/assets/{vue-vine-BZtSJFfi.js → vue-vine-87qc9dJ9.js} +1 -1
- package/dist/web/assets/wardley-L42UT6IY-BtXwfgcx.js +1 -0
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-CpT1RVZp.js → wardleyDiagram-YWT4CUSO-C4mIx6nt.js} +1 -1
- package/dist/web/assets/{xml-Detdg-FS.js → xml-BwxGZI3_.js} +1 -1
- package/dist/web/assets/{xsl-CWUN_pbH.js → xsl-V11HisfD.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-C8BtIz3X.js → xychartDiagram-2RQKCTM6-CR2seeGg.js} +1 -1
- package/dist/web/assets/{yaml-8W-QgFv_.js → yaml-DoTdQeS-.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +5 -6
- package/dist/server/prompts/agents/turn-prompt-rewriter.md +0 -15
- package/dist/web/assets/architecture-7EHR7CIX-BuetZCIk.js +0 -1
- package/dist/web/assets/channel-CD2ivr_e.js +0 -1
- package/dist/web/assets/chunk-QZHKN3VN-Bf-N5Jmd.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-F8ONWgXY.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-F8ONWgXY.js +0 -1
- package/dist/web/assets/eventmodeling-FCH6USID-C5QIAlur.js +0 -1
- package/dist/web/assets/gitGraph-WXDBUCRP-Broa5-99.js +0 -1
- package/dist/web/assets/index-BFZtO7ji.css +0 -2
- package/dist/web/assets/info-J43DQDTF-5yru-lYW.js +0 -1
- package/dist/web/assets/mermaid-GHXKKRXX-tc_NirJc.js +0 -1
- package/dist/web/assets/packet-YPE3B663-eYBiCMjG.js +0 -1
- package/dist/web/assets/pie-LRSECV5Y-CEs_o2N-.js +0 -1
- package/dist/web/assets/radar-GUYGQ44K-D6SysS4p.js +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-BtuE7Ay0.js +0 -1
- package/dist/web/assets/treeView-BLDUP644-DEYw0jRo.js +0 -1
- package/dist/web/assets/treemap-LRROVOQU-BaQ1oGDR.js +0 -1
- package/dist/web/assets/wardley-L42UT6IY-F8LWMBYs.js +0 -1
package/dist/server/index.js
CHANGED
|
@@ -8037,10 +8037,10 @@ var init_chunkify = __esm({
|
|
|
8037
8037
|
// ../../node_modules/.pnpm/trash@10.1.1/node_modules/trash/lib/chunked-exec.js
|
|
8038
8038
|
import { promisify as promisify2 } from "node:util";
|
|
8039
8039
|
import { execFile } from "node:child_process";
|
|
8040
|
-
import { fileURLToPath as
|
|
8040
|
+
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
8041
8041
|
async function chunkedExec(binary3, paths, maxPaths) {
|
|
8042
8042
|
for (const chunk of chunkify(paths, maxPaths)) {
|
|
8043
|
-
await pExecFile(
|
|
8043
|
+
await pExecFile(fileURLToPath4(binary3), chunk);
|
|
8044
8044
|
}
|
|
8045
8045
|
}
|
|
8046
8046
|
var pExecFile;
|
|
@@ -11133,7 +11133,7 @@ var require_utils6 = __commonJS({
|
|
|
11133
11133
|
openSync,
|
|
11134
11134
|
readSync,
|
|
11135
11135
|
closeSync,
|
|
11136
|
-
readFileSync:
|
|
11136
|
+
readFileSync: readFileSync3,
|
|
11137
11137
|
existsSync: existsSync2
|
|
11138
11138
|
} = __require("fs");
|
|
11139
11139
|
var tmpBufMinLen = 4096 * 2;
|
|
@@ -11168,7 +11168,7 @@ var require_utils6 = __commonJS({
|
|
|
11168
11168
|
}
|
|
11169
11169
|
return ls;
|
|
11170
11170
|
};
|
|
11171
|
-
var readBuffer =
|
|
11171
|
+
var readBuffer = readFileSync3;
|
|
11172
11172
|
var exists = existsSync2;
|
|
11173
11173
|
var readdir2 = readdirSync;
|
|
11174
11174
|
var devIdGetMinor = (devId) => devId >> 20 << 8 | devId & 255;
|
|
@@ -56264,10 +56264,7 @@ import { randomUUID } from "node:crypto";
|
|
|
56264
56264
|
// ../core/src/settings/model-utils.ts
|
|
56265
56265
|
var DEEPSEEK_CONTEXT_SIZE_K = 1e3;
|
|
56266
56266
|
var DEFAULT_OPENAI_COMPATIBLE_CONTEXT_SIZE_K = 200;
|
|
56267
|
-
var DEEPSEEK_MODELS = [
|
|
56268
|
-
"deepseek-v4-flash",
|
|
56269
|
-
"deepseek-v4-pro"
|
|
56270
|
-
];
|
|
56267
|
+
var DEEPSEEK_MODELS = ["deepseek-v4-flash", "deepseek-v4-pro"];
|
|
56271
56268
|
var DEFAULT_DEEPSEEK_MODEL = DEEPSEEK_MODELS[0];
|
|
56272
56269
|
|
|
56273
56270
|
// ../core/src/settings/settings-service.ts
|
|
@@ -56355,12 +56352,8 @@ var SettingsService = class _SettingsService {
|
|
|
56355
56352
|
}
|
|
56356
56353
|
async writeSettings(settings) {
|
|
56357
56354
|
await mkdir(path.dirname(this.settingsPath), { recursive: true });
|
|
56358
|
-
await writeFile(
|
|
56359
|
-
|
|
56360
|
-
`${JSON.stringify(settings, null, 2)}
|
|
56361
|
-
`,
|
|
56362
|
-
"utf8"
|
|
56363
|
-
);
|
|
56355
|
+
await writeFile(this.settingsPath, `${JSON.stringify(settings, null, 2)}
|
|
56356
|
+
`, "utf8");
|
|
56364
56357
|
try {
|
|
56365
56358
|
const fileStats = await stat(this.settingsPath);
|
|
56366
56359
|
_SettingsService.cache.set(this.settingsPath, {
|
|
@@ -56399,9 +56392,7 @@ function parseStoredSettings(value) {
|
|
|
56399
56392
|
return {
|
|
56400
56393
|
defaultModelId: typeof value.defaultModelId === "string" ? value.defaultModelId : null,
|
|
56401
56394
|
interfaceLanguage: parseInterfaceLanguage(value.interfaceLanguage),
|
|
56402
|
-
modelConfigurations: Array.isArray(value.modelConfigurations) ? value.modelConfigurations.map((configuration) => parseStoredModelConfiguration(configuration)).filter(
|
|
56403
|
-
(configuration) => Boolean(configuration)
|
|
56404
|
-
) : [],
|
|
56395
|
+
modelConfigurations: Array.isArray(value.modelConfigurations) ? value.modelConfigurations.map((configuration) => parseStoredModelConfiguration(configuration)).filter((configuration) => Boolean(configuration)) : [],
|
|
56405
56396
|
resources: parseStoredResourceSettings(value.resources)
|
|
56406
56397
|
};
|
|
56407
56398
|
}
|
|
@@ -56486,10 +56477,7 @@ function normalizeSettings(settings) {
|
|
|
56486
56477
|
baseUrl: configuration.baseUrl.trim(),
|
|
56487
56478
|
model: normalizeModelId(configuration.model.trim(), configuration.provider),
|
|
56488
56479
|
apiKey: configuration.apiKey.trim(),
|
|
56489
|
-
contextSizeK: normalizeContextSizeK(
|
|
56490
|
-
configuration.contextSizeK,
|
|
56491
|
-
configuration.provider
|
|
56492
|
-
),
|
|
56480
|
+
contextSizeK: normalizeContextSizeK(configuration.contextSizeK, configuration.provider),
|
|
56493
56481
|
...providerOptions ? { providerOptions } : {}
|
|
56494
56482
|
};
|
|
56495
56483
|
});
|
|
@@ -56687,61 +56675,8 @@ function elapsedWallTime(startedAt) {
|
|
|
56687
56675
|
return Math.max(0, Math.round((performance.now() - startedAt) * 100) / 100);
|
|
56688
56676
|
}
|
|
56689
56677
|
|
|
56690
|
-
// ../core/src/agent/page-edit-mode.ts
|
|
56691
|
-
import path3 from "node:path";
|
|
56692
|
-
|
|
56693
56678
|
// ../core/src/agent/tools/cdn-guard.ts
|
|
56694
56679
|
import path2 from "node:path";
|
|
56695
|
-
async function writeProjectWorkspaceFileWithCdnGuard(workspaceStore, projectId, relativePath, content, approvedCdnUrls = []) {
|
|
56696
|
-
const guardedContent = await guardIndexHtmlCdnChanges(
|
|
56697
|
-
workspaceStore,
|
|
56698
|
-
projectId,
|
|
56699
|
-
relativePath,
|
|
56700
|
-
content,
|
|
56701
|
-
approvedCdnUrls
|
|
56702
|
-
);
|
|
56703
|
-
return workspaceStore.writeProjectWorkspaceFile(
|
|
56704
|
-
projectId,
|
|
56705
|
-
relativePath,
|
|
56706
|
-
guardedContent
|
|
56707
|
-
);
|
|
56708
|
-
}
|
|
56709
|
-
async function editProjectWorkspaceFileWithCdnGuard(workspaceStore, projectId, relativePath, oldString, newString, replaceAll = false, approvedCdnUrls = []) {
|
|
56710
|
-
const content = await workspaceStore.readProjectWorkspaceFile(
|
|
56711
|
-
projectId,
|
|
56712
|
-
relativePath
|
|
56713
|
-
);
|
|
56714
|
-
const updatedContent = replaceInContent(
|
|
56715
|
-
content,
|
|
56716
|
-
oldString,
|
|
56717
|
-
newString,
|
|
56718
|
-
replaceAll,
|
|
56719
|
-
relativePath
|
|
56720
|
-
);
|
|
56721
|
-
const writeResult = await writeProjectWorkspaceFileWithCdnGuard(
|
|
56722
|
-
workspaceStore,
|
|
56723
|
-
projectId,
|
|
56724
|
-
relativePath,
|
|
56725
|
-
updatedContent,
|
|
56726
|
-
approvedCdnUrls
|
|
56727
|
-
);
|
|
56728
|
-
return {
|
|
56729
|
-
diff: writeResult.diff,
|
|
56730
|
-
path: normalizeToolPath(relativePath),
|
|
56731
|
-
replacements: replaceAll ? countOccurrences(content, normalizeEditNeedle(content, oldString)) : 1
|
|
56732
|
-
};
|
|
56733
|
-
}
|
|
56734
|
-
async function applyProjectWorkspacePatchWithCdnGuard(workspaceStore, projectId, changes, approvedCdnUrls = []) {
|
|
56735
|
-
return workspaceStore.applyProjectWorkspacePatch(projectId, changes, {
|
|
56736
|
-
transformContent: async (relativePath, content) => guardIndexHtmlCdnChanges(
|
|
56737
|
-
workspaceStore,
|
|
56738
|
-
projectId,
|
|
56739
|
-
relativePath,
|
|
56740
|
-
content,
|
|
56741
|
-
approvedCdnUrls
|
|
56742
|
-
)
|
|
56743
|
-
});
|
|
56744
|
-
}
|
|
56745
56680
|
async function readProjectWorkspaceFileIfExists(workspaceStore, projectId, relativePath) {
|
|
56746
56681
|
try {
|
|
56747
56682
|
return await workspaceStore.readProjectWorkspaceFile(projectId, relativePath);
|
|
@@ -56752,364 +56687,15 @@ async function readProjectWorkspaceFileIfExists(workspaceStore, projectId, relat
|
|
|
56752
56687
|
throw error51;
|
|
56753
56688
|
}
|
|
56754
56689
|
}
|
|
56755
|
-
function buildCdnTag(input) {
|
|
56756
|
-
const attributes = [
|
|
56757
|
-
'data-owndesign-approved-cdn="true"',
|
|
56758
|
-
input.integrity ? `integrity="${escapeHtmlAttribute(input.integrity)}"` : "",
|
|
56759
|
-
input.crossorigin ? `crossorigin="${escapeHtmlAttribute(input.crossorigin)}"` : ""
|
|
56760
|
-
].filter(Boolean);
|
|
56761
|
-
const suffix = attributes.length ? ` ${attributes.join(" ")}` : "";
|
|
56762
|
-
const url2 = escapeHtmlAttribute(input.url);
|
|
56763
|
-
if (input.resourceType === "stylesheet") {
|
|
56764
|
-
return `<link rel="stylesheet" href="${url2}"${suffix}>`;
|
|
56765
|
-
}
|
|
56766
|
-
if (input.resourceType === "style-import") {
|
|
56767
|
-
return `<style${suffix}>
|
|
56768
|
-
@import url('${url2}');
|
|
56769
|
-
</style>`;
|
|
56770
|
-
}
|
|
56771
|
-
return `<script src="${url2}"${suffix}></script>`;
|
|
56772
|
-
}
|
|
56773
|
-
async function guardIndexHtmlCdnChanges(workspaceStore, projectId, relativePath, content, approvedCdnUrls) {
|
|
56774
|
-
if (!isHtmlPath(relativePath)) {
|
|
56775
|
-
return content;
|
|
56776
|
-
}
|
|
56777
|
-
const normalizedContent = normalizeConfiguredResourceCdnRefs(
|
|
56778
|
-
content,
|
|
56779
|
-
approvedCdnUrls
|
|
56780
|
-
);
|
|
56781
|
-
const approvedUrls = new Set(
|
|
56782
|
-
approvedCdnUrls.map(normalizeHttpsUrl).filter(Boolean)
|
|
56783
|
-
);
|
|
56784
|
-
const unapprovedRefs = extractExternalCdnRefs(normalizedContent).filter(
|
|
56785
|
-
({ url: url2 }) => !approvedUrls.has(url2)
|
|
56786
|
-
);
|
|
56787
|
-
if (unapprovedRefs.length > 0) {
|
|
56788
|
-
throw new Error(
|
|
56789
|
-
`HTML files can only use CDN resources configured in settings: ${unapprovedRefs.map(({ url: url2 }) => url2).join(", ")}`
|
|
56790
|
-
);
|
|
56791
|
-
}
|
|
56792
|
-
return normalizedContent;
|
|
56793
|
-
}
|
|
56794
|
-
function replaceInContent(content, oldString, newString, replaceAll, relativePath) {
|
|
56795
|
-
if (!oldString) {
|
|
56796
|
-
throw new Error("oldString must not be empty.");
|
|
56797
|
-
}
|
|
56798
|
-
if (oldString === newString) {
|
|
56799
|
-
throw new Error("No changes to apply: oldString and newString are identical.");
|
|
56800
|
-
}
|
|
56801
|
-
const needle = normalizeEditNeedle(content, oldString);
|
|
56802
|
-
const replacement = convertToLineEnding(newString, detectLineEnding(content));
|
|
56803
|
-
const firstIndex = content.indexOf(needle);
|
|
56804
|
-
if (firstIndex === -1) {
|
|
56805
|
-
throw new Error(`oldString was not found in Project Workspace file: ${relativePath}`);
|
|
56806
|
-
}
|
|
56807
|
-
if (replaceAll) {
|
|
56808
|
-
return content.split(needle).join(replacement);
|
|
56809
|
-
}
|
|
56810
|
-
if (content.indexOf(needle, firstIndex + needle.length) !== -1) {
|
|
56811
|
-
throw new Error(
|
|
56812
|
-
`oldString appears more than once in Project Workspace file: ${relativePath}`
|
|
56813
|
-
);
|
|
56814
|
-
}
|
|
56815
|
-
return content.slice(0, firstIndex) + replacement + content.slice(firstIndex + needle.length);
|
|
56816
|
-
}
|
|
56817
|
-
function normalizeEditNeedle(content, oldString) {
|
|
56818
|
-
return convertToLineEnding(oldString, detectLineEnding(content));
|
|
56819
|
-
}
|
|
56820
|
-
function detectLineEnding(text2) {
|
|
56821
|
-
return text2.includes("\r\n") ? "\r\n" : "\n";
|
|
56822
|
-
}
|
|
56823
|
-
function convertToLineEnding(text2, ending) {
|
|
56824
|
-
const normalized = text2.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
|
|
56825
|
-
return ending === "\n" ? normalized : normalized.replaceAll("\n", "\r\n");
|
|
56826
|
-
}
|
|
56827
|
-
function countOccurrences(content, needle) {
|
|
56828
|
-
if (!needle) {
|
|
56829
|
-
return 0;
|
|
56830
|
-
}
|
|
56831
|
-
return content.split(needle).length - 1;
|
|
56832
|
-
}
|
|
56833
|
-
function extractExternalCdnRefs(html) {
|
|
56834
|
-
return extractCdnTags(html).map(({ resourceType, url: url2 }) => ({
|
|
56835
|
-
resourceType,
|
|
56836
|
-
url: url2
|
|
56837
|
-
}));
|
|
56838
|
-
}
|
|
56839
|
-
function extractCdnTags(html) {
|
|
56840
|
-
const refs = [];
|
|
56841
|
-
for (const match2 of html.matchAll(/<script\b[^>]*>[\s\S]*?<\/script>/gi)) {
|
|
56842
|
-
const tag = match2[0];
|
|
56843
|
-
const src = getHtmlAttribute(tag, "src");
|
|
56844
|
-
if (src && isHttpsUrl(src)) {
|
|
56845
|
-
refs.push({
|
|
56846
|
-
rawUrl: src,
|
|
56847
|
-
resourceType: "script",
|
|
56848
|
-
tag,
|
|
56849
|
-
url: normalizeUrl(src)
|
|
56850
|
-
});
|
|
56851
|
-
}
|
|
56852
|
-
}
|
|
56853
|
-
for (const match2 of html.matchAll(/<link\b[^>]*>/gi)) {
|
|
56854
|
-
const tag = match2[0];
|
|
56855
|
-
const href = getHtmlAttribute(tag, "href");
|
|
56856
|
-
const rel = getHtmlAttribute(tag, "rel");
|
|
56857
|
-
if (href && isHttpsUrl(href) && rel?.toLowerCase().split(/\s+/).includes("stylesheet")) {
|
|
56858
|
-
refs.push({
|
|
56859
|
-
rawUrl: href,
|
|
56860
|
-
resourceType: "stylesheet",
|
|
56861
|
-
tag,
|
|
56862
|
-
url: normalizeUrl(href)
|
|
56863
|
-
});
|
|
56864
|
-
}
|
|
56865
|
-
}
|
|
56866
|
-
for (const match2 of html.matchAll(/<style\b[^>]*>[\s\S]*?<\/style>/gi)) {
|
|
56867
|
-
const tag = match2[0];
|
|
56868
|
-
for (const importMatch of tag.matchAll(
|
|
56869
|
-
/@import\s+(?:url\(\s*)?(?:"([^"]+)"|'([^']+)'|([^"')\s;]+))\s*\)?/gi
|
|
56870
|
-
)) {
|
|
56871
|
-
const url2 = importMatch[1] ?? importMatch[2] ?? importMatch[3];
|
|
56872
|
-
if (url2 && isHttpsUrl(url2)) {
|
|
56873
|
-
refs.push({
|
|
56874
|
-
rawUrl: url2,
|
|
56875
|
-
resourceType: "style-import",
|
|
56876
|
-
tag,
|
|
56877
|
-
url: normalizeUrl(url2)
|
|
56878
|
-
});
|
|
56879
|
-
}
|
|
56880
|
-
}
|
|
56881
|
-
}
|
|
56882
|
-
return refs;
|
|
56883
|
-
}
|
|
56884
|
-
function normalizeConfiguredResourceCdnRefs(html, approvedCdnUrls) {
|
|
56885
|
-
const approvedUrls = approvedCdnUrls.map(normalizeHttpsUrl).filter((url2) => Boolean(url2));
|
|
56886
|
-
const configuredFontCdn = approvedUrls.find(isGoogleFontsCss2Url);
|
|
56887
|
-
let updatedHtml = html;
|
|
56888
|
-
for (const ref of extractCdnTags(html)) {
|
|
56889
|
-
const replacementUrl = getConfiguredReplacementUrl(ref.url, {
|
|
56890
|
-
configuredFontCdn
|
|
56891
|
-
});
|
|
56892
|
-
if (!replacementUrl || ref.url === replacementUrl) {
|
|
56893
|
-
continue;
|
|
56894
|
-
}
|
|
56895
|
-
if (ref.resourceType === "stylesheet" && configuredFontCdn && ref.url !== configuredFontCdn && isGoogleFontsCss2Url(ref.url)) {
|
|
56896
|
-
updatedHtml = updatedHtml.replace(
|
|
56897
|
-
ref.tag,
|
|
56898
|
-
buildCdnTag({ resourceType: "style-import", url: configuredFontCdn })
|
|
56899
|
-
);
|
|
56900
|
-
continue;
|
|
56901
|
-
}
|
|
56902
|
-
updatedHtml = updatedHtml.split(ref.rawUrl).join(replacementUrl);
|
|
56903
|
-
}
|
|
56904
|
-
return updatedHtml;
|
|
56905
|
-
}
|
|
56906
|
-
function getConfiguredReplacementUrl(url2, replacements) {
|
|
56907
|
-
if (replacements.configuredFontCdn && isGoogleFontsCss2Url(url2)) {
|
|
56908
|
-
return replacements.configuredFontCdn;
|
|
56909
|
-
}
|
|
56910
|
-
return void 0;
|
|
56911
|
-
}
|
|
56912
|
-
function isGoogleFontsCss2Url(value) {
|
|
56913
|
-
try {
|
|
56914
|
-
const url2 = new URL(value);
|
|
56915
|
-
return url2.hostname === "fonts.googleapis.com" && url2.pathname === "/css2";
|
|
56916
|
-
} catch {
|
|
56917
|
-
return false;
|
|
56918
|
-
}
|
|
56919
|
-
}
|
|
56920
|
-
function getHtmlAttribute(tag, name21) {
|
|
56921
|
-
const pattern = new RegExp(
|
|
56922
|
-
`\\s${name21}\\s*=\\s*(?:"([^"]*)"|'([^']*)'|([^\\s>]+))`,
|
|
56923
|
-
"i"
|
|
56924
|
-
);
|
|
56925
|
-
const match2 = tag.match(pattern);
|
|
56926
|
-
return match2?.[1] ?? match2?.[2] ?? match2?.[3];
|
|
56927
|
-
}
|
|
56928
|
-
function isHttpsUrl(value) {
|
|
56929
|
-
try {
|
|
56930
|
-
return new URL(value).protocol === "https:";
|
|
56931
|
-
} catch {
|
|
56932
|
-
return false;
|
|
56933
|
-
}
|
|
56934
|
-
}
|
|
56935
|
-
function normalizeUrl(value) {
|
|
56936
|
-
return new URL(value).href;
|
|
56937
|
-
}
|
|
56938
56690
|
function isHtmlPath(relativePath) {
|
|
56939
56691
|
return normalizeToolPath(relativePath).toLowerCase().endsWith(".html");
|
|
56940
56692
|
}
|
|
56941
56693
|
function normalizeToolPath(relativePath) {
|
|
56942
56694
|
return path2.posix.normalize(relativePath.replaceAll("\\", "/"));
|
|
56943
56695
|
}
|
|
56944
|
-
function normalizeHttpsUrl(value) {
|
|
56945
|
-
try {
|
|
56946
|
-
const url2 = new URL(value);
|
|
56947
|
-
return url2.protocol === "https:" ? url2.href : void 0;
|
|
56948
|
-
} catch {
|
|
56949
|
-
return void 0;
|
|
56950
|
-
}
|
|
56951
|
-
}
|
|
56952
56696
|
function isMissingPathError2(error51) {
|
|
56953
56697
|
return error51 instanceof Error && "code" in error51 && error51.code === "ENOENT";
|
|
56954
56698
|
}
|
|
56955
|
-
function escapeHtmlAttribute(value) {
|
|
56956
|
-
return value.replaceAll("&", "&").replaceAll('"', """).replaceAll("<", "<").replaceAll(">", ">");
|
|
56957
|
-
}
|
|
56958
|
-
|
|
56959
|
-
// ../core/src/agent/page-edit-mode.ts
|
|
56960
|
-
var PAGE_EDIT_MODES = [
|
|
56961
|
-
"auto",
|
|
56962
|
-
"new_page",
|
|
56963
|
-
"direct_edit",
|
|
56964
|
-
"duplicate_edit"
|
|
56965
|
-
];
|
|
56966
|
-
function parsePageEditMode(value) {
|
|
56967
|
-
if (value === void 0 || value === null || value === "") {
|
|
56968
|
-
return "auto";
|
|
56969
|
-
}
|
|
56970
|
-
return PAGE_EDIT_MODES.includes(value) ? value : void 0;
|
|
56971
|
-
}
|
|
56972
|
-
async function buildPageEditModePolicy({
|
|
56973
|
-
currentPreviewPath,
|
|
56974
|
-
mode = "auto",
|
|
56975
|
-
projectId,
|
|
56976
|
-
workspaceStore
|
|
56977
|
-
}) {
|
|
56978
|
-
if (mode === "auto") {
|
|
56979
|
-
return { mode };
|
|
56980
|
-
}
|
|
56981
|
-
if (mode === "new_page") {
|
|
56982
|
-
return {
|
|
56983
|
-
currentPreviewPath: currentPreviewPath ? normalizeRequiredHtmlPath(currentPreviewPath, mode) : void 0,
|
|
56984
|
-
mode
|
|
56985
|
-
};
|
|
56986
|
-
}
|
|
56987
|
-
const sourcePath = normalizeRequiredHtmlPath(currentPreviewPath, mode);
|
|
56988
|
-
await readRequiredHtmlFile(workspaceStore, projectId, sourcePath, mode);
|
|
56989
|
-
if (mode === "direct_edit") {
|
|
56990
|
-
return {
|
|
56991
|
-
mode,
|
|
56992
|
-
targetPath: sourcePath
|
|
56993
|
-
};
|
|
56994
|
-
}
|
|
56995
|
-
const targetPath = await resolveUniqueCopyPath(
|
|
56996
|
-
workspaceStore,
|
|
56997
|
-
projectId,
|
|
56998
|
-
sourcePath
|
|
56999
|
-
);
|
|
57000
|
-
return {
|
|
57001
|
-
mode,
|
|
57002
|
-
sourcePath,
|
|
57003
|
-
targetPath
|
|
57004
|
-
};
|
|
57005
|
-
}
|
|
57006
|
-
function assertCreateHtmlAllowed(policy, relativePath) {
|
|
57007
|
-
assertHtmlPathOperationAllowed(policy, "create", relativePath);
|
|
57008
|
-
}
|
|
57009
|
-
function markCreatedHtmlPath(policy, relativePath) {
|
|
57010
|
-
if (policy?.mode === "new_page") {
|
|
57011
|
-
policy.createdHtmlPath = normalizeToolPath(relativePath);
|
|
57012
|
-
}
|
|
57013
|
-
}
|
|
57014
|
-
function assertCopyFileAllowed(policy, sourcePath, targetPath) {
|
|
57015
|
-
if (!policy || policy.mode !== "duplicate_edit") {
|
|
57016
|
-
return;
|
|
57017
|
-
}
|
|
57018
|
-
const normalizedSourcePath = normalizeToolPath(sourcePath);
|
|
57019
|
-
const normalizedTargetPath = normalizeToolPath(targetPath);
|
|
57020
|
-
if (normalizedSourcePath !== policy.sourcePath || normalizedTargetPath !== policy.targetPath) {
|
|
57021
|
-
throw new Error(
|
|
57022
|
-
`Page edit mode "duplicate_edit" can only copy ${policy.sourcePath} to ${policy.targetPath}; attempted ${normalizedSourcePath} to ${normalizedTargetPath}.`
|
|
57023
|
-
);
|
|
57024
|
-
}
|
|
57025
|
-
}
|
|
57026
|
-
function resolveHtmlOperationPathForPageEditModePolicy(policy, operation, relativePath) {
|
|
57027
|
-
if (!policy || policy.mode === "auto") {
|
|
57028
|
-
return relativePath;
|
|
57029
|
-
}
|
|
57030
|
-
const targetPath = normalizeToolPath(relativePath);
|
|
57031
|
-
if (!isHtmlPath(targetPath)) {
|
|
57032
|
-
return relativePath;
|
|
57033
|
-
}
|
|
57034
|
-
assertHtmlPathOperationAllowed(policy, operation, targetPath);
|
|
57035
|
-
return targetPath;
|
|
57036
|
-
}
|
|
57037
|
-
function assertHtmlPathOperationAllowed(policy, operation, relativePath) {
|
|
57038
|
-
if (!policy || policy.mode !== "duplicate_edit") {
|
|
57039
|
-
return;
|
|
57040
|
-
}
|
|
57041
|
-
const targetPath = normalizeToolPath(relativePath);
|
|
57042
|
-
if (!isHtmlPath(targetPath)) {
|
|
57043
|
-
return;
|
|
57044
|
-
}
|
|
57045
|
-
if (operation === "read") {
|
|
57046
|
-
return;
|
|
57047
|
-
}
|
|
57048
|
-
if (operation === "copy" && targetPath === policy.targetPath) {
|
|
57049
|
-
return;
|
|
57050
|
-
}
|
|
57051
|
-
if (targetPath !== policy.targetPath) {
|
|
57052
|
-
throw new Error(
|
|
57053
|
-
`Page edit mode "duplicate_edit" can only ${formatHtmlOperation(operation)} ${policy.targetPath}; attempted ${targetPath}.`
|
|
57054
|
-
);
|
|
57055
|
-
}
|
|
57056
|
-
}
|
|
57057
|
-
function formatHtmlOperation(operation) {
|
|
57058
|
-
switch (operation) {
|
|
57059
|
-
case "copy":
|
|
57060
|
-
return "copy";
|
|
57061
|
-
case "create":
|
|
57062
|
-
return "create";
|
|
57063
|
-
case "delete":
|
|
57064
|
-
return "delete";
|
|
57065
|
-
case "mutate":
|
|
57066
|
-
return "edit";
|
|
57067
|
-
case "preview":
|
|
57068
|
-
return "preview";
|
|
57069
|
-
case "read":
|
|
57070
|
-
return "read";
|
|
57071
|
-
}
|
|
57072
|
-
}
|
|
57073
|
-
function normalizeRequiredHtmlPath(relativePath, mode) {
|
|
57074
|
-
if (!relativePath) {
|
|
57075
|
-
throw new Error(`Page edit mode "${mode}" requires a current preview page.`);
|
|
57076
|
-
}
|
|
57077
|
-
const normalizedPath = normalizeToolPath(relativePath);
|
|
57078
|
-
if (!isHtmlPath(normalizedPath)) {
|
|
57079
|
-
throw new Error(
|
|
57080
|
-
`Page edit mode "${mode}" requires an HTML preview page: ${normalizedPath}`
|
|
57081
|
-
);
|
|
57082
|
-
}
|
|
57083
|
-
return normalizedPath;
|
|
57084
|
-
}
|
|
57085
|
-
async function readRequiredHtmlFile(workspaceStore, projectId, relativePath, mode) {
|
|
57086
|
-
try {
|
|
57087
|
-
return await workspaceStore.readProjectWorkspaceFile(projectId, relativePath);
|
|
57088
|
-
} catch {
|
|
57089
|
-
throw new Error(
|
|
57090
|
-
`Page edit mode "${mode}" requires an existing current preview page: ${relativePath}`
|
|
57091
|
-
);
|
|
57092
|
-
}
|
|
57093
|
-
}
|
|
57094
|
-
async function resolveUniqueCopyPath(workspaceStore, projectId, sourcePath) {
|
|
57095
|
-
const parsed = path3.posix.parse(sourcePath);
|
|
57096
|
-
const directory = parsed.dir ? `${parsed.dir}/` : "";
|
|
57097
|
-
const baseName = normalizeCopyBaseName(parsed.name);
|
|
57098
|
-
const extension = parsed.ext || ".html";
|
|
57099
|
-
for (let index = 1; index < 1e3; index += 1) {
|
|
57100
|
-
const suffix = index === 1 ? "copy" : `copy-${index}`;
|
|
57101
|
-
const candidatePath = `${directory}${baseName}.${suffix}${extension}`;
|
|
57102
|
-
try {
|
|
57103
|
-
await workspaceStore.readProjectWorkspaceFile(projectId, candidatePath);
|
|
57104
|
-
} catch {
|
|
57105
|
-
return candidatePath;
|
|
57106
|
-
}
|
|
57107
|
-
}
|
|
57108
|
-
throw new Error(`Could not create a unique copy path for ${sourcePath}.`);
|
|
57109
|
-
}
|
|
57110
|
-
function normalizeCopyBaseName(baseName) {
|
|
57111
|
-
return baseName.replace(/\.copy(?:-\d+)?$/, "");
|
|
57112
|
-
}
|
|
57113
56699
|
|
|
57114
56700
|
// ../core/src/agent/tools/copy-file.ts
|
|
57115
56701
|
function createCopyFileToolDefinition() {
|
|
@@ -57117,67 +56703,84 @@ function createCopyFileToolDefinition() {
|
|
|
57117
56703
|
description: "Copy one UTF-8 text file inside the current Project Workspace to a new path. Never overwrites existing files.",
|
|
57118
56704
|
inputSchema: external_exports.object({
|
|
57119
56705
|
sourcePath: external_exports.string().describe("Relative source file path inside the Project Workspace."),
|
|
57120
|
-
targetPath: external_exports.string().describe(
|
|
56706
|
+
targetPath: external_exports.string().describe(
|
|
56707
|
+
"Relative destination file path inside the Project Workspace. Must not already exist."
|
|
56708
|
+
)
|
|
57121
56709
|
}).strict(),
|
|
57122
56710
|
name: "copyFile",
|
|
57123
56711
|
parallelSafe: false,
|
|
57124
|
-
execute: async ({ sourcePath, targetPath }, {
|
|
56712
|
+
execute: async ({ sourcePath, targetPath }, { projectId, workspaceStore }) => {
|
|
57125
56713
|
const normalizedSourcePath = normalizeToolPath(sourcePath);
|
|
57126
56714
|
const normalizedTargetPath = normalizeToolPath(targetPath);
|
|
57127
|
-
assertCopyFileAllowed(
|
|
57128
|
-
pageEditModePolicy,
|
|
57129
|
-
normalizedSourcePath,
|
|
57130
|
-
normalizedTargetPath
|
|
57131
|
-
);
|
|
57132
56715
|
const existingTarget = await readProjectWorkspaceFileIfExists(
|
|
57133
56716
|
workspaceStore,
|
|
57134
56717
|
projectId,
|
|
57135
56718
|
normalizedTargetPath
|
|
57136
56719
|
);
|
|
57137
56720
|
if (existingTarget !== void 0) {
|
|
57138
|
-
throw new Error(
|
|
57139
|
-
`Project Workspace file already exists: ${normalizedTargetPath}`
|
|
57140
|
-
);
|
|
56721
|
+
throw new Error(`Project Workspace file already exists: ${normalizedTargetPath}`);
|
|
57141
56722
|
}
|
|
57142
56723
|
const sourceContent = await workspaceStore.readProjectWorkspaceFile(
|
|
57143
56724
|
projectId,
|
|
57144
56725
|
normalizedSourcePath
|
|
57145
56726
|
);
|
|
57146
|
-
return
|
|
57147
|
-
workspaceStore,
|
|
57148
|
-
projectId,
|
|
57149
|
-
normalizedTargetPath,
|
|
57150
|
-
sourceContent,
|
|
57151
|
-
approvedCdnUrls
|
|
57152
|
-
);
|
|
56727
|
+
return workspaceStore.writeProjectWorkspaceFile(projectId, normalizedTargetPath, sourceContent);
|
|
57153
56728
|
}
|
|
57154
56729
|
};
|
|
57155
56730
|
}
|
|
57156
56731
|
|
|
56732
|
+
// ../core/src/templates/index.ts
|
|
56733
|
+
import { readFileSync } from "node:fs";
|
|
56734
|
+
import path3 from "node:path";
|
|
56735
|
+
import { fileURLToPath } from "node:url";
|
|
56736
|
+
var TEMPLATE_FILES = {
|
|
56737
|
+
"html/page-shell": "html/page-shell.html"
|
|
56738
|
+
};
|
|
56739
|
+
function loadTemplate(name21) {
|
|
56740
|
+
const templateFile = TEMPLATE_FILES[name21];
|
|
56741
|
+
if (!templateFile) {
|
|
56742
|
+
throw new Error(`Unsupported template: ${String(name21)}`);
|
|
56743
|
+
}
|
|
56744
|
+
const currentDir = path3.dirname(fileURLToPath(import.meta.url));
|
|
56745
|
+
const candidatePaths = [
|
|
56746
|
+
path3.join(currentDir, "templates", templateFile),
|
|
56747
|
+
path3.join(currentDir, templateFile)
|
|
56748
|
+
];
|
|
56749
|
+
for (const candidatePath of candidatePaths) {
|
|
56750
|
+
try {
|
|
56751
|
+
return readFileSync(candidatePath, "utf8").trim();
|
|
56752
|
+
} catch (error51) {
|
|
56753
|
+
if (!isNotFoundError(error51)) {
|
|
56754
|
+
throw error51;
|
|
56755
|
+
}
|
|
56756
|
+
}
|
|
56757
|
+
}
|
|
56758
|
+
throw new Error(`Template "${name21}" was not found. Searched: ${candidatePaths.join(", ")}`);
|
|
56759
|
+
}
|
|
56760
|
+
function isNotFoundError(error51) {
|
|
56761
|
+
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
|
|
56762
|
+
}
|
|
56763
|
+
|
|
57157
56764
|
// ../core/src/agent/tools/create-html.ts
|
|
57158
56765
|
var DEFAULT_TITLE = "OwnDesign Preview";
|
|
56766
|
+
var SINGLE_HTML_PATH = "index.html";
|
|
57159
56767
|
function createCreateHtmlToolDefinition() {
|
|
57160
56768
|
return {
|
|
57161
|
-
description: "Create
|
|
56769
|
+
description: "Create the single previewable index.html file from the configured template before designing a missing Single HTML project. Never overwrites existing files.",
|
|
57162
56770
|
inputSchema: external_exports.object({
|
|
57163
|
-
|
|
57164
|
-
iconLibraryName: external_exports.string().describe("Optional configured icon library name. Omit to use the default icon library. Pass an empty string to disable icon resources.").optional(),
|
|
57165
|
-
path: external_exports.string().describe("Relative HTML file path inside the Project Workspace, such as index.html or pages/detail.html."),
|
|
56771
|
+
path: external_exports.string().describe("Relative HTML file path inside the Project Workspace. Must be index.html."),
|
|
57166
56772
|
title: external_exports.string().describe("Optional document title. Defaults to OwnDesign Preview.").optional()
|
|
57167
56773
|
}).strict(),
|
|
57168
56774
|
name: "createHtml",
|
|
57169
56775
|
parallelSafe: false,
|
|
57170
|
-
execute: async (input, {
|
|
57171
|
-
pageEditModePolicy,
|
|
57172
|
-
projectId,
|
|
57173
|
-
resources,
|
|
57174
|
-
workspaceStore
|
|
57175
|
-
}) => {
|
|
56776
|
+
execute: async (input, { projectId, workspaceStore }) => {
|
|
57176
56777
|
const targetPath = normalizeToolPath(input.path);
|
|
57177
|
-
assertCreateHtmlAllowed(pageEditModePolicy, targetPath);
|
|
57178
56778
|
if (!isHtmlPath(targetPath)) {
|
|
57179
56779
|
throw new Error(`HTML initialization target must end with .html: ${targetPath}`);
|
|
57180
56780
|
}
|
|
56781
|
+
if (targetPath !== SINGLE_HTML_PATH) {
|
|
56782
|
+
throw new Error(`Single HTML projects can only create ${SINGLE_HTML_PATH}: ${targetPath}`);
|
|
56783
|
+
}
|
|
57181
56784
|
const existingHtml = await readProjectWorkspaceFileIfExists(
|
|
57182
56785
|
workspaceStore,
|
|
57183
56786
|
projectId,
|
|
@@ -57186,94 +56789,28 @@ function createCreateHtmlToolDefinition() {
|
|
|
57186
56789
|
if (existingHtml !== void 0) {
|
|
57187
56790
|
throw new Error(`Project Workspace HTML file already exists: ${targetPath}`);
|
|
57188
56791
|
}
|
|
57189
|
-
const
|
|
57190
|
-
|
|
57191
|
-
|
|
57192
|
-
|
|
57193
|
-
|
|
57194
|
-
const iconLibrary = selectLibrary(
|
|
57195
|
-
resources.iconLibraries,
|
|
57196
|
-
input.iconLibraryName,
|
|
57197
|
-
"icon"
|
|
56792
|
+
const title = input.title?.trim() || DEFAULT_TITLE;
|
|
56793
|
+
await workspaceStore.writeProjectWorkspaceFile(
|
|
56794
|
+
projectId,
|
|
56795
|
+
targetPath,
|
|
56796
|
+
buildSingleHtmlTemplate({ title })
|
|
57198
56797
|
);
|
|
57199
|
-
const html = buildHtmlTemplate({
|
|
57200
|
-
fontLibrary,
|
|
57201
|
-
iconLibrary,
|
|
57202
|
-
title: input.title?.trim() || DEFAULT_TITLE
|
|
57203
|
-
});
|
|
57204
|
-
await workspaceStore.writeProjectWorkspaceFile(projectId, targetPath, html);
|
|
57205
|
-
markCreatedHtmlPath(pageEditModePolicy, targetPath);
|
|
57206
56798
|
return {
|
|
57207
|
-
fontLibrary: formatSelectedLibrary(fontLibrary),
|
|
57208
|
-
iconLibrary: formatSelectedLibrary(iconLibrary),
|
|
57209
56799
|
path: targetPath,
|
|
57210
|
-
title
|
|
56800
|
+
title
|
|
57211
56801
|
};
|
|
57212
56802
|
}
|
|
57213
56803
|
};
|
|
57214
56804
|
}
|
|
57215
|
-
function
|
|
57216
|
-
|
|
57217
|
-
|
|
57218
|
-
|
|
57219
|
-
|
|
57220
|
-
const library = libraries.find((item) => item.name === name21);
|
|
57221
|
-
if (!library) {
|
|
57222
|
-
throw new Error(`Configured ${kind} library was not found: ${name21}`);
|
|
57223
|
-
}
|
|
57224
|
-
return library;
|
|
57225
|
-
}
|
|
57226
|
-
return libraries.find((library) => library.isDefault) ?? libraries[0];
|
|
57227
|
-
}
|
|
57228
|
-
function buildHtmlTemplate({
|
|
57229
|
-
fontLibrary,
|
|
57230
|
-
iconLibrary,
|
|
57231
|
-
title
|
|
57232
|
-
}) {
|
|
57233
|
-
const headTags = [
|
|
57234
|
-
fontLibrary?.cdn ? buildCdnTag({ resourceType: "style-import", url: fontLibrary.cdn }) : "",
|
|
57235
|
-
iconLibrary?.cdn && inferIconLibraryResourceType(iconLibrary.cdn) === "stylesheet" ? buildCdnTag({ resourceType: "stylesheet", url: iconLibrary.cdn }) : ""
|
|
57236
|
-
].filter(Boolean);
|
|
57237
|
-
const bodyScripts = [
|
|
57238
|
-
iconLibrary?.cdn && inferIconLibraryResourceType(iconLibrary.cdn) === "script" ? buildCdnTag({ resourceType: "script", url: iconLibrary.cdn }) : "",
|
|
57239
|
-
isLucideLibrary(iconLibrary) ? " <script>window.lucide?.createIcons?.();</script>" : ""
|
|
57240
|
-
].filter(Boolean);
|
|
57241
|
-
return [
|
|
57242
|
-
"<!doctype html>",
|
|
57243
|
-
'<html lang="zh-CN">',
|
|
57244
|
-
"<head>",
|
|
57245
|
-
' <meta charset="utf-8">',
|
|
57246
|
-
' <meta name="viewport" content="width=device-width, initial-scale=1">',
|
|
57247
|
-
` <title>${escapeHtmlText(title)}</title>`,
|
|
57248
|
-
...headTags.map((tag) => indentMultiline(tag, " ")),
|
|
57249
|
-
"</head>",
|
|
57250
|
-
"<body>",
|
|
57251
|
-
' <main id="app"></main>',
|
|
57252
|
-
...bodyScripts.map((tag) => indentMultiline(tag, " ")),
|
|
57253
|
-
"</body>",
|
|
57254
|
-
"</html>",
|
|
57255
|
-
""
|
|
57256
|
-
].join("\n");
|
|
57257
|
-
}
|
|
57258
|
-
function inferIconLibraryResourceType(cdn) {
|
|
57259
|
-
const normalized = cdn.toLowerCase();
|
|
57260
|
-
return normalized.includes(".css") || normalized.includes("/css/") || normalized.includes("font-awesome") ? "stylesheet" : "script";
|
|
57261
|
-
}
|
|
57262
|
-
function isLucideLibrary(library) {
|
|
57263
|
-
if (!library?.cdn) {
|
|
57264
|
-
return false;
|
|
57265
|
-
}
|
|
57266
|
-
const value = `${library.name} ${library.cdn}`.toLowerCase();
|
|
57267
|
-
return value.includes("lucide");
|
|
57268
|
-
}
|
|
57269
|
-
function formatSelectedLibrary(library) {
|
|
57270
|
-
return library ? {
|
|
57271
|
-
cdn: library.cdn,
|
|
57272
|
-
name: library.name
|
|
57273
|
-
} : void 0;
|
|
56805
|
+
function buildSingleHtmlTemplate({ title }) {
|
|
56806
|
+
return renderTemplate(loadTemplate("html/page-shell"), {
|
|
56807
|
+
lang: "zh-CN",
|
|
56808
|
+
title: escapeHtmlText(title)
|
|
56809
|
+
});
|
|
57274
56810
|
}
|
|
57275
|
-
function
|
|
57276
|
-
return
|
|
56811
|
+
function renderTemplate(template, values) {
|
|
56812
|
+
return `${template.replace(/\{\{([a-zA-Z0-9]+)\}\}/g, (_match, key) => values[key] ?? "")}
|
|
56813
|
+
`;
|
|
57277
56814
|
}
|
|
57278
56815
|
function escapeHtmlText(value) {
|
|
57279
56816
|
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">");
|
|
@@ -57288,14 +56825,7 @@ function createDeleteToolDefinition() {
|
|
|
57288
56825
|
}).strict(),
|
|
57289
56826
|
name: "delete",
|
|
57290
56827
|
parallelSafe: false,
|
|
57291
|
-
execute: async ({ path: path16 }, {
|
|
57292
|
-
pageEditModePolicy,
|
|
57293
|
-
projectId,
|
|
57294
|
-
workspaceStore
|
|
57295
|
-
}) => {
|
|
57296
|
-
assertHtmlPathOperationAllowed(pageEditModePolicy, "delete", path16);
|
|
57297
|
-
return workspaceStore.deleteProjectWorkspacePath(projectId, path16);
|
|
57298
|
-
}
|
|
56828
|
+
execute: async ({ path: path16 }, { projectId, workspaceStore }) => workspaceStore.deleteProjectWorkspacePath(projectId, path16)
|
|
57299
56829
|
};
|
|
57300
56830
|
}
|
|
57301
56831
|
|
|
@@ -57311,27 +56841,7 @@ function createEditToolDefinition() {
|
|
|
57311
56841
|
}).strict(),
|
|
57312
56842
|
name: "edit",
|
|
57313
56843
|
parallelSafe: false,
|
|
57314
|
-
execute: async ({ newString, oldString, path: path16, replaceAll }, {
|
|
57315
|
-
approvedCdnUrls,
|
|
57316
|
-
pageEditModePolicy,
|
|
57317
|
-
projectId,
|
|
57318
|
-
workspaceStore
|
|
57319
|
-
}) => {
|
|
57320
|
-
const editPath = resolveHtmlOperationPathForPageEditModePolicy(
|
|
57321
|
-
pageEditModePolicy,
|
|
57322
|
-
"mutate",
|
|
57323
|
-
path16
|
|
57324
|
-
);
|
|
57325
|
-
return editProjectWorkspaceFileWithCdnGuard(
|
|
57326
|
-
workspaceStore,
|
|
57327
|
-
projectId,
|
|
57328
|
-
editPath,
|
|
57329
|
-
oldString,
|
|
57330
|
-
newString,
|
|
57331
|
-
replaceAll,
|
|
57332
|
-
approvedCdnUrls
|
|
57333
|
-
);
|
|
57334
|
-
}
|
|
56844
|
+
execute: async ({ newString, oldString, path: path16, replaceAll }, { projectId, workspaceStore }) => workspaceStore.editProjectWorkspaceFile(projectId, path16, oldString, newString, replaceAll)
|
|
57335
56845
|
};
|
|
57336
56846
|
}
|
|
57337
56847
|
|
|
@@ -57345,15 +56855,8 @@ function createGlobToolDefinition() {
|
|
|
57345
56855
|
}).strict(),
|
|
57346
56856
|
name: "glob",
|
|
57347
56857
|
parallelSafe: true,
|
|
57348
|
-
execute: async ({ path: path16, pattern }, {
|
|
57349
|
-
projectId,
|
|
57350
|
-
workspaceStore
|
|
57351
|
-
}) => {
|
|
57352
|
-
return workspaceStore.globProjectWorkspace(
|
|
57353
|
-
projectId,
|
|
57354
|
-
pattern,
|
|
57355
|
-
path16
|
|
57356
|
-
);
|
|
56858
|
+
execute: async ({ path: path16, pattern }, { projectId, workspaceStore }) => {
|
|
56859
|
+
return workspaceStore.globProjectWorkspace(projectId, pattern, path16);
|
|
57357
56860
|
}
|
|
57358
56861
|
};
|
|
57359
56862
|
}
|
|
@@ -57364,15 +56867,14 @@ function createGrepToolDefinition() {
|
|
|
57364
56867
|
description: "Search UTF-8 text files in the current Project Workspace using a JavaScript regular expression.",
|
|
57365
56868
|
inputSchema: external_exports.object({
|
|
57366
56869
|
include: external_exports.string().describe('Optional file glob to include, such as "*.html" or "**/*.{css,js}".').optional(),
|
|
57367
|
-
path: external_exports.string().describe(
|
|
56870
|
+
path: external_exports.string().describe(
|
|
56871
|
+
"Optional relative file or directory path inside the Project Workspace to search."
|
|
56872
|
+
).optional(),
|
|
57368
56873
|
pattern: external_exports.string().describe("JavaScript regular expression pattern to search for.")
|
|
57369
56874
|
}).strict(),
|
|
57370
56875
|
name: "grep",
|
|
57371
56876
|
parallelSafe: true,
|
|
57372
|
-
execute: async ({ include, path: path16, pattern }, {
|
|
57373
|
-
projectId,
|
|
57374
|
-
workspaceStore
|
|
57375
|
-
}) => {
|
|
56877
|
+
execute: async ({ include, path: path16, pattern }, { projectId, workspaceStore }) => {
|
|
57376
56878
|
return workspaceStore.grepProjectWorkspace(projectId, pattern, {
|
|
57377
56879
|
include,
|
|
57378
56880
|
path: path16
|
|
@@ -57386,48 +56888,35 @@ function createPatchToolDefinition() {
|
|
|
57386
56888
|
return {
|
|
57387
56889
|
description: "Apply coordinated UTF-8 file changes inside the current Project Workspace. Supports add/write, edit, and delete changes.",
|
|
57388
56890
|
inputSchema: external_exports.object({
|
|
57389
|
-
changes: external_exports.array(
|
|
57390
|
-
external_exports.
|
|
57391
|
-
|
|
57392
|
-
|
|
57393
|
-
|
|
57394
|
-
|
|
57395
|
-
|
|
57396
|
-
|
|
57397
|
-
|
|
57398
|
-
|
|
57399
|
-
|
|
57400
|
-
|
|
57401
|
-
|
|
57402
|
-
|
|
57403
|
-
|
|
57404
|
-
|
|
57405
|
-
|
|
57406
|
-
|
|
57407
|
-
|
|
57408
|
-
|
|
57409
|
-
|
|
57410
|
-
|
|
57411
|
-
|
|
56891
|
+
changes: external_exports.array(
|
|
56892
|
+
external_exports.discriminatedUnion("operation", [
|
|
56893
|
+
external_exports.object({
|
|
56894
|
+
content: external_exports.string().describe("Complete file content for add operations."),
|
|
56895
|
+
operation: external_exports.literal("add"),
|
|
56896
|
+
path: external_exports.string().describe("Relative file or directory path inside the Project Workspace.")
|
|
56897
|
+
}).strict(),
|
|
56898
|
+
external_exports.object({
|
|
56899
|
+
content: external_exports.string().describe("Complete file content for write operations."),
|
|
56900
|
+
operation: external_exports.literal("write"),
|
|
56901
|
+
path: external_exports.string().describe("Relative file or directory path inside the Project Workspace.")
|
|
56902
|
+
}).strict(),
|
|
56903
|
+
external_exports.object({
|
|
56904
|
+
newString: external_exports.string().describe("Replacement text for edit operations."),
|
|
56905
|
+
oldString: external_exports.string().describe("Text to replace for edit operations."),
|
|
56906
|
+
operation: external_exports.literal("edit"),
|
|
56907
|
+
path: external_exports.string().describe("Relative file or directory path inside the Project Workspace."),
|
|
56908
|
+
replaceAll: external_exports.boolean().describe("For edit operations, replace every occurrence of oldString.").optional()
|
|
56909
|
+
}).strict(),
|
|
56910
|
+
external_exports.object({
|
|
56911
|
+
operation: external_exports.literal("delete"),
|
|
56912
|
+
path: external_exports.string().describe("Relative file or directory path inside the Project Workspace.")
|
|
56913
|
+
}).strict()
|
|
56914
|
+
])
|
|
56915
|
+
).min(1)
|
|
57412
56916
|
}).strict(),
|
|
57413
56917
|
name: "patch",
|
|
57414
56918
|
parallelSafe: false,
|
|
57415
|
-
execute: async ({ changes }, {
|
|
57416
|
-
const resolvedChanges = changes.map((change) => ({
|
|
57417
|
-
...change,
|
|
57418
|
-
path: resolveHtmlOperationPathForPageEditModePolicy(
|
|
57419
|
-
pageEditModePolicy,
|
|
57420
|
-
change.operation === "delete" ? "delete" : "mutate",
|
|
57421
|
-
change.path
|
|
57422
|
-
)
|
|
57423
|
-
}));
|
|
57424
|
-
return applyProjectWorkspacePatchWithCdnGuard(
|
|
57425
|
-
workspaceStore,
|
|
57426
|
-
projectId,
|
|
57427
|
-
resolvedChanges,
|
|
57428
|
-
approvedCdnUrls
|
|
57429
|
-
);
|
|
57430
|
-
}
|
|
56919
|
+
execute: async ({ changes }, { projectId, workspaceStore }) => workspaceStore.applyProjectWorkspacePatch(projectId, changes)
|
|
57431
56920
|
};
|
|
57432
56921
|
}
|
|
57433
56922
|
|
|
@@ -57435,11 +56924,7 @@ function createPatchToolDefinition() {
|
|
|
57435
56924
|
var KEEPALIVE_INTERVAL_MS = 15e3;
|
|
57436
56925
|
var FrontendCommandBus = class {
|
|
57437
56926
|
connections = /* @__PURE__ */ new Map();
|
|
57438
|
-
registerConnection({
|
|
57439
|
-
frontendTabId,
|
|
57440
|
-
projectId,
|
|
57441
|
-
signal
|
|
57442
|
-
}) {
|
|
56927
|
+
registerConnection({ frontendTabId, projectId, signal }) {
|
|
57443
56928
|
const key = buildConnectionKey(projectId, frontendTabId);
|
|
57444
56929
|
const encoder = new TextEncoder();
|
|
57445
56930
|
let connection;
|
|
@@ -57476,9 +56961,7 @@ var FrontendCommandBus = class {
|
|
|
57476
56961
|
payload,
|
|
57477
56962
|
projectId
|
|
57478
56963
|
}) {
|
|
57479
|
-
const connection = this.connections.get(
|
|
57480
|
-
buildConnectionKey(projectId, frontendTabId)
|
|
57481
|
-
);
|
|
56964
|
+
const connection = this.connections.get(buildConnectionKey(projectId, frontendTabId));
|
|
57482
56965
|
if (!connection) {
|
|
57483
56966
|
return {
|
|
57484
56967
|
delivered: false,
|
|
@@ -57490,12 +56973,7 @@ var FrontendCommandBus = class {
|
|
|
57490
56973
|
id: createCommandId(),
|
|
57491
56974
|
payload
|
|
57492
56975
|
};
|
|
57493
|
-
enqueueSseEvent(
|
|
57494
|
-
connection.controller,
|
|
57495
|
-
connection.encoder,
|
|
57496
|
-
"frontend-command",
|
|
57497
|
-
command
|
|
57498
|
-
);
|
|
56976
|
+
enqueueSseEvent(connection.controller, connection.encoder, "frontend-command", command);
|
|
57499
56977
|
return {
|
|
57500
56978
|
command,
|
|
57501
56979
|
delivered: true
|
|
@@ -57535,12 +57013,10 @@ function sendFrontendCommand(input) {
|
|
|
57535
57013
|
return getFrontendCommandBus().sendCommand(input);
|
|
57536
57014
|
}
|
|
57537
57015
|
function enqueueSseEvent(controller, encoder, event, data) {
|
|
57538
|
-
controller.enqueue(
|
|
57539
|
-
encoder.encode(`event: ${event}
|
|
57016
|
+
controller.enqueue(encoder.encode(`event: ${event}
|
|
57540
57017
|
data: ${JSON.stringify(data)}
|
|
57541
57018
|
|
|
57542
|
-
`)
|
|
57543
|
-
);
|
|
57019
|
+
`));
|
|
57544
57020
|
}
|
|
57545
57021
|
function enqueueSseComment(controller, encoder, comment) {
|
|
57546
57022
|
controller.enqueue(encoder.encode(`: ${comment}
|
|
@@ -57585,76 +57061,24 @@ function createPreviewRefreshToolDefinition() {
|
|
|
57585
57061
|
};
|
|
57586
57062
|
}
|
|
57587
57063
|
|
|
57588
|
-
// ../core/src/agent/tools/preview-switch-html.ts
|
|
57589
|
-
function createPreviewSwitchHtmlToolDefinition() {
|
|
57590
|
-
return {
|
|
57591
|
-
description: "Switch the Preview Pane to an existing HTML file after successful previewable HTML changes.",
|
|
57592
|
-
inputSchema: external_exports.object({
|
|
57593
|
-
path: external_exports.string().describe("Relative HTML file path inside the Project Workspace to show in the Preview Pane.")
|
|
57594
|
-
}).strict(),
|
|
57595
|
-
name: "previewSwitchHtml",
|
|
57596
|
-
parallelSafe: false,
|
|
57597
|
-
execute: async ({ path: path16 }, context2) => {
|
|
57598
|
-
if (!context2.frontendTabId) {
|
|
57599
|
-
throw new Error("Frontend tab id is required to switch the preview.");
|
|
57600
|
-
}
|
|
57601
|
-
const targetPath = normalizeToolPath(path16);
|
|
57602
|
-
if (!targetPath || targetPath === ".") {
|
|
57603
|
-
throw new Error("Preview switch target path must not be empty.");
|
|
57604
|
-
}
|
|
57605
|
-
if (!isHtmlPath(targetPath)) {
|
|
57606
|
-
throw new Error(`Preview switch target must end with .html: ${targetPath}`);
|
|
57607
|
-
}
|
|
57608
|
-
const previewPath = resolveHtmlOperationPathForPageEditModePolicy(
|
|
57609
|
-
context2.pageEditModePolicy,
|
|
57610
|
-
"preview",
|
|
57611
|
-
targetPath
|
|
57612
|
-
);
|
|
57613
|
-
const htmlFiles = await context2.workspaceStore.listProjectHtmlFiles(
|
|
57614
|
-
context2.projectId
|
|
57615
|
-
);
|
|
57616
|
-
if (!htmlFiles.includes(previewPath)) {
|
|
57617
|
-
throw new Error(`Project Workspace HTML file was not found: ${previewPath}`);
|
|
57618
|
-
}
|
|
57619
|
-
const payload = { path: previewPath };
|
|
57620
|
-
const result = sendFrontendCommand({
|
|
57621
|
-
capability: "preview.switchHtml",
|
|
57622
|
-
frontendTabId: context2.frontendTabId,
|
|
57623
|
-
payload,
|
|
57624
|
-
projectId: context2.projectId
|
|
57625
|
-
});
|
|
57626
|
-
return {
|
|
57627
|
-
capability: "preview.switchHtml",
|
|
57628
|
-
delivered: result?.delivered ?? false,
|
|
57629
|
-
payload
|
|
57630
|
-
};
|
|
57631
|
-
}
|
|
57632
|
-
};
|
|
57633
|
-
}
|
|
57634
|
-
|
|
57635
57064
|
// ../core/src/agent/tools/read.ts
|
|
57636
57065
|
function createReadToolDefinition() {
|
|
57637
57066
|
return {
|
|
57638
57067
|
description: "Read one UTF-8 file or directory from the current Project Workspace. Files are returned with 1-indexed line numbers.",
|
|
57639
57068
|
inputSchema: external_exports.object({
|
|
57640
57069
|
limit: external_exports.number().describe("Maximum number of lines or directory entries to read. Defaults to 2000.").optional(),
|
|
57641
|
-
offset: external_exports.number().describe(
|
|
57070
|
+
offset: external_exports.number().describe(
|
|
57071
|
+
"1-indexed line or directory-entry offset to start reading from. Defaults to 1."
|
|
57072
|
+
).optional(),
|
|
57642
57073
|
path: external_exports.string().describe("Relative file or directory path inside the Project Workspace.")
|
|
57643
57074
|
}).strict(),
|
|
57644
57075
|
name: "read",
|
|
57645
57076
|
parallelSafe: true,
|
|
57646
|
-
execute: async ({ limit, offset, path: path16 }, {
|
|
57647
|
-
projectId,
|
|
57648
|
-
|
|
57649
|
-
|
|
57650
|
-
|
|
57651
|
-
projectId,
|
|
57652
|
-
path16,
|
|
57653
|
-
{
|
|
57654
|
-
limit,
|
|
57655
|
-
offset
|
|
57656
|
-
}
|
|
57657
|
-
);
|
|
57077
|
+
execute: async ({ limit, offset, path: path16 }, { projectId, workspaceStore }) => {
|
|
57078
|
+
return workspaceStore.readProjectWorkspaceEntry(projectId, path16, {
|
|
57079
|
+
limit,
|
|
57080
|
+
offset
|
|
57081
|
+
});
|
|
57658
57082
|
}
|
|
57659
57083
|
};
|
|
57660
57084
|
}
|
|
@@ -57669,25 +57093,7 @@ function createWriteToolDefinition() {
|
|
|
57669
57093
|
}).strict(),
|
|
57670
57094
|
name: "write",
|
|
57671
57095
|
parallelSafe: false,
|
|
57672
|
-
execute: async ({ content, path: path16 }, {
|
|
57673
|
-
approvedCdnUrls,
|
|
57674
|
-
pageEditModePolicy,
|
|
57675
|
-
projectId,
|
|
57676
|
-
workspaceStore
|
|
57677
|
-
}) => {
|
|
57678
|
-
const writePath = resolveHtmlOperationPathForPageEditModePolicy(
|
|
57679
|
-
pageEditModePolicy,
|
|
57680
|
-
"mutate",
|
|
57681
|
-
path16
|
|
57682
|
-
);
|
|
57683
|
-
return writeProjectWorkspaceFileWithCdnGuard(
|
|
57684
|
-
workspaceStore,
|
|
57685
|
-
projectId,
|
|
57686
|
-
writePath,
|
|
57687
|
-
content,
|
|
57688
|
-
approvedCdnUrls
|
|
57689
|
-
);
|
|
57690
|
-
}
|
|
57096
|
+
execute: async ({ content, path: path16 }, { projectId, workspaceStore }) => workspaceStore.writeProjectWorkspaceFile(projectId, path16, content)
|
|
57691
57097
|
};
|
|
57692
57098
|
}
|
|
57693
57099
|
|
|
@@ -57702,50 +57108,41 @@ function createProjectWorkspaceToolDefinitions() {
|
|
|
57702
57108
|
createGrepToolDefinition(),
|
|
57703
57109
|
createPatchToolDefinition(),
|
|
57704
57110
|
createPreviewRefreshToolDefinition(),
|
|
57705
|
-
createPreviewSwitchHtmlToolDefinition(),
|
|
57706
57111
|
createReadToolDefinition(),
|
|
57707
57112
|
createWriteToolDefinition()
|
|
57708
57113
|
];
|
|
57709
57114
|
}
|
|
57710
|
-
function createProjectWorkspaceTools(context2) {
|
|
57711
|
-
return createWorkspaceToolRegistry(
|
|
57712
|
-
createProjectWorkspaceToolDefinitions(),
|
|
57713
|
-
context2
|
|
57714
|
-
);
|
|
57715
|
-
}
|
|
57716
57115
|
|
|
57717
57116
|
// ../core/src/prompts/index.ts
|
|
57718
|
-
import { readFileSync } from "node:fs";
|
|
57117
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
57719
57118
|
import path4 from "node:path";
|
|
57720
|
-
import { fileURLToPath } from "node:url";
|
|
57119
|
+
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
57721
57120
|
var PROMPT_FILES = {
|
|
57722
|
-
"agents/
|
|
57723
|
-
"agents/
|
|
57121
|
+
"agents/component-audit": "agents/component-audit.md",
|
|
57122
|
+
"agents/design-page": "agents/design-page.md"
|
|
57724
57123
|
};
|
|
57725
57124
|
function loadPrompt(name21) {
|
|
57726
57125
|
const promptFile = PROMPT_FILES[name21];
|
|
57727
57126
|
if (!promptFile) {
|
|
57728
57127
|
throw new Error(`Unsupported prompt: ${String(name21)}`);
|
|
57729
57128
|
}
|
|
57730
|
-
const currentDir = path4.dirname(
|
|
57129
|
+
const currentDir = path4.dirname(fileURLToPath2(import.meta.url));
|
|
57731
57130
|
const candidatePaths = [
|
|
57732
57131
|
path4.join(currentDir, "prompts", promptFile),
|
|
57733
57132
|
path4.join(currentDir, promptFile)
|
|
57734
57133
|
];
|
|
57735
57134
|
for (const candidatePath of candidatePaths) {
|
|
57736
57135
|
try {
|
|
57737
|
-
return
|
|
57136
|
+
return readFileSync2(candidatePath, "utf8").trim();
|
|
57738
57137
|
} catch (error51) {
|
|
57739
|
-
if (!
|
|
57138
|
+
if (!isNotFoundError2(error51)) {
|
|
57740
57139
|
throw error51;
|
|
57741
57140
|
}
|
|
57742
57141
|
}
|
|
57743
57142
|
}
|
|
57744
|
-
throw new Error(
|
|
57745
|
-
`Prompt "${name21}" was not found. Searched: ${candidatePaths.join(", ")}`
|
|
57746
|
-
);
|
|
57143
|
+
throw new Error(`Prompt "${name21}" was not found. Searched: ${candidatePaths.join(", ")}`);
|
|
57747
57144
|
}
|
|
57748
|
-
function
|
|
57145
|
+
function isNotFoundError2(error51) {
|
|
57749
57146
|
return typeof error51 === "object" && error51 !== null && "code" in error51 && error51.code === "ENOENT";
|
|
57750
57147
|
}
|
|
57751
57148
|
|
|
@@ -57758,40 +57155,20 @@ var FRONTEND_CAPABILITIES = {
|
|
|
57758
57155
|
properties: {},
|
|
57759
57156
|
additionalProperties: false
|
|
57760
57157
|
}
|
|
57761
|
-
},
|
|
57762
|
-
"preview.switchHtml": {
|
|
57763
|
-
description: "Switch the Preview Pane to an existing HTML file.",
|
|
57764
|
-
payloadSchema: {
|
|
57765
|
-
type: "object",
|
|
57766
|
-
properties: {
|
|
57767
|
-
path: {
|
|
57768
|
-
type: "string",
|
|
57769
|
-
description: "Relative HTML file path inside the Project Workspace to show in the Preview Pane."
|
|
57770
|
-
}
|
|
57771
|
-
},
|
|
57772
|
-
required: ["path"],
|
|
57773
|
-
additionalProperties: false
|
|
57774
|
-
}
|
|
57775
57158
|
}
|
|
57776
57159
|
};
|
|
57777
|
-
var FRONTEND_CAPABILITY_IDS = Object.keys(
|
|
57778
|
-
FRONTEND_CAPABILITIES
|
|
57779
|
-
);
|
|
57160
|
+
var FRONTEND_CAPABILITY_IDS = Object.keys(FRONTEND_CAPABILITIES);
|
|
57780
57161
|
function buildFrontendCapabilityPrompt() {
|
|
57781
57162
|
return [
|
|
57782
57163
|
"## Frontend Capabilities",
|
|
57783
57164
|
"Use preview tools only to notify the browser UI after Project Workspace file changes are complete. They do not create, edit, or validate files.",
|
|
57784
|
-
"After successful previewable HTML changes, call exactly one
|
|
57165
|
+
"After successful previewable HTML changes, call exactly one `previewRefresh` before the final user-facing summary.",
|
|
57785
57166
|
"Do not call a preview tool when no previewable HTML file changed or the file operation failed.",
|
|
57786
|
-
"Use
|
|
57787
|
-
"- Use `previewSwitchHtml` only when the Preview Pane should move to a different existing relative `.html` file inside the Project Workspace.",
|
|
57788
|
-
"- Use `previewRefresh` when the Preview Pane is already showing the correct page and only needs to reload changed HTML.",
|
|
57167
|
+
"Use `previewRefresh` when `index.html` changed and should reload.",
|
|
57789
57168
|
"Do not use workspace file tools to simulate preview switching or refreshing.",
|
|
57790
57169
|
"Available capabilities:",
|
|
57791
57170
|
...FRONTEND_CAPABILITY_IDS.map((capability) => {
|
|
57792
|
-
const schema = JSON.stringify(
|
|
57793
|
-
FRONTEND_CAPABILITIES[capability].payloadSchema
|
|
57794
|
-
);
|
|
57171
|
+
const schema = JSON.stringify(FRONTEND_CAPABILITIES[capability].payloadSchema);
|
|
57795
57172
|
return `- ${capability}: ${FRONTEND_CAPABILITIES[capability].description} Payload schema: ${schema}`;
|
|
57796
57173
|
})
|
|
57797
57174
|
].join("\n");
|
|
@@ -57805,11 +57182,12 @@ var AiSdkDesignPageAgent = class {
|
|
|
57805
57182
|
}
|
|
57806
57183
|
workspaceStore;
|
|
57807
57184
|
async generateProjectOutput(input) {
|
|
57808
|
-
|
|
57809
|
-
|
|
57185
|
+
const projectType = normalizeProjectType(input.projectType, input.outputType);
|
|
57186
|
+
if (projectType !== "single_html") {
|
|
57187
|
+
throw new Error(`Unsupported Project Type: ${projectType}`);
|
|
57810
57188
|
}
|
|
57811
57189
|
const context2 = await createDesignPageAgentContext({
|
|
57812
|
-
|
|
57190
|
+
projectType,
|
|
57813
57191
|
projectId: input.projectId,
|
|
57814
57192
|
workspaceStore: this.workspaceStore
|
|
57815
57193
|
});
|
|
@@ -57827,36 +57205,27 @@ async function createDesignPageAgentContext({
|
|
|
57827
57205
|
frontendTabId,
|
|
57828
57206
|
modelConfigurationId,
|
|
57829
57207
|
outputType,
|
|
57830
|
-
|
|
57208
|
+
projectType,
|
|
57831
57209
|
projectId,
|
|
57832
57210
|
providerOptionsSelection,
|
|
57211
|
+
settingsPath,
|
|
57833
57212
|
workspaceStore
|
|
57834
57213
|
}) {
|
|
57835
|
-
|
|
57836
|
-
|
|
57214
|
+
projectType = normalizeProjectType(projectType, outputType);
|
|
57215
|
+
if (projectType !== "single_html") {
|
|
57216
|
+
throw new Error(`Unsupported Project Type: ${projectType}`);
|
|
57837
57217
|
}
|
|
57838
|
-
const settingsService = createSettingsService();
|
|
57218
|
+
const settingsService = createSettingsService({ settingsPath });
|
|
57839
57219
|
const [settings, modelConfiguration] = await Promise.all([
|
|
57840
57220
|
settingsService.getSettings(),
|
|
57841
57221
|
settingsService.resolveModelConfiguration(modelConfigurationId)
|
|
57842
57222
|
]);
|
|
57843
|
-
const pageEditModePolicy = await buildPageEditModePolicy({
|
|
57844
|
-
currentPreviewPath,
|
|
57845
|
-
mode: pageEditMode,
|
|
57846
|
-
projectId,
|
|
57847
|
-
workspaceStore
|
|
57848
|
-
});
|
|
57849
57223
|
return {
|
|
57850
57224
|
currentPreviewPath,
|
|
57851
57225
|
frontendTabId,
|
|
57852
57226
|
model: buildLanguageModel(modelConfiguration),
|
|
57853
|
-
|
|
57854
|
-
|
|
57855
|
-
pageEditModePolicy,
|
|
57856
|
-
providerOptions: buildProviderOptions(
|
|
57857
|
-
modelConfiguration,
|
|
57858
|
-
providerOptionsSelection
|
|
57859
|
-
),
|
|
57227
|
+
projectType,
|
|
57228
|
+
providerOptions: buildProviderOptions(modelConfiguration, providerOptionsSelection),
|
|
57860
57229
|
projectId,
|
|
57861
57230
|
resources: settings.resources,
|
|
57862
57231
|
workspaceStore
|
|
@@ -57868,30 +57237,25 @@ function createDesignPageAgent(context2) {
|
|
|
57868
57237
|
allowSystemInMessages: true,
|
|
57869
57238
|
model,
|
|
57870
57239
|
instructions: agentInstructions ?? buildDesignPageInstructions(context2),
|
|
57240
|
+
maxRetries: 5,
|
|
57871
57241
|
providerOptions,
|
|
57872
57242
|
stopWhen: stepCountIs(50),
|
|
57873
57243
|
tools: createDesignPageWorkspaceTools(context2)
|
|
57874
57244
|
});
|
|
57875
57245
|
}
|
|
57876
|
-
function createDesignPageWorkspaceTools({
|
|
57877
|
-
projectId,
|
|
57878
|
-
|
|
57879
|
-
workspaceStore,
|
|
57880
|
-
frontendTabId,
|
|
57881
|
-
pageEditModePolicy
|
|
57882
|
-
}) {
|
|
57883
|
-
return createProjectWorkspaceTools({
|
|
57246
|
+
function createDesignPageWorkspaceTools(context2) {
|
|
57247
|
+
const { frontendTabId, projectId, resources, workspaceStore } = context2;
|
|
57248
|
+
return createWorkspaceToolRegistry(createProjectWorkspaceToolDefinitions(), {
|
|
57884
57249
|
approvedCdnUrls: buildApprovedCdnUrls(resources),
|
|
57885
57250
|
frontendTabId,
|
|
57886
|
-
|
|
57251
|
+
model: context2.model,
|
|
57887
57252
|
projectId,
|
|
57253
|
+
providerOptions: context2.providerOptions,
|
|
57888
57254
|
resources,
|
|
57889
57255
|
workspaceStore
|
|
57890
57256
|
});
|
|
57891
57257
|
}
|
|
57892
|
-
function buildDesignPageInstructions({
|
|
57893
|
-
resources
|
|
57894
|
-
}) {
|
|
57258
|
+
function buildDesignPageInstructions({ resources }) {
|
|
57895
57259
|
return buildDesignPageConversationInstructions(resources);
|
|
57896
57260
|
}
|
|
57897
57261
|
function buildLanguageModel(configuration) {
|
|
@@ -57943,6 +57307,15 @@ function buildProviderOptions(configuration, selection) {
|
|
|
57943
57307
|
}
|
|
57944
57308
|
};
|
|
57945
57309
|
}
|
|
57310
|
+
function normalizeProjectType(projectType, outputType) {
|
|
57311
|
+
if (projectType) {
|
|
57312
|
+
return projectType;
|
|
57313
|
+
}
|
|
57314
|
+
if (outputType === "html") {
|
|
57315
|
+
return "single_html";
|
|
57316
|
+
}
|
|
57317
|
+
return "single_html";
|
|
57318
|
+
}
|
|
57946
57319
|
function buildDesignPageConversationInstructions(resources) {
|
|
57947
57320
|
const sections = [
|
|
57948
57321
|
{
|
|
@@ -57983,58 +57356,46 @@ function loadDesignPageAgentCorePrompt() {
|
|
|
57983
57356
|
}
|
|
57984
57357
|
function buildPageTargetProtocolPrompt() {
|
|
57985
57358
|
return [
|
|
57986
|
-
"##
|
|
57359
|
+
"## Single HTML Target Protocol",
|
|
57987
57360
|
"",
|
|
57988
|
-
"
|
|
57361
|
+
"The project has one previewable file: `index.html`.",
|
|
57989
57362
|
"",
|
|
57990
|
-
"
|
|
57991
|
-
"-
|
|
57992
|
-
"-
|
|
57993
|
-
"-
|
|
57994
|
-
|
|
57995
|
-
"-
|
|
57996
|
-
|
|
57997
|
-
"- If
|
|
57998
|
-
"- If multiple HTML files exist, no current preview page is available, and the target remains ambiguous after inspection, ask one concise follow-up question.",
|
|
57999
|
-
"- Do not ask a follow-up question just because the request is brief; act when the target can be resolved from the current user message, an explicit filename, or the `index.html` default.",
|
|
58000
|
-
"",
|
|
58001
|
-
"- Do not overwrite `index.html` for a new page unless the user intent points to the home or main page."
|
|
57363
|
+
"Rules:",
|
|
57364
|
+
"- Always target `index.html` for previewable output.",
|
|
57365
|
+
"- Do not create `login.html`, `detail.html`, versioned HTML files, or any other HTML page.",
|
|
57366
|
+
"- If the user asks for multiple pages, screens, or routes, implement them as internal views inside `index.html`.",
|
|
57367
|
+
"- Use ordinary HTML, CSS, and browser JavaScript in the file.",
|
|
57368
|
+
"- Do not create custom elements, component module folders, or page/component reuse metadata files.",
|
|
57369
|
+
'- If `index.html` is missing, call `createHtml({ path: "index.html" })` before editing.',
|
|
57370
|
+
"- If `index.html` exists, read it before editing and continue from the current design."
|
|
58002
57371
|
].join("\n");
|
|
58003
57372
|
}
|
|
58004
57373
|
function buildToolWorkflowPrompt() {
|
|
58005
57374
|
return [
|
|
58006
57375
|
"## Tool Workflow",
|
|
58007
|
-
"Use the narrowest reliable tool for each task
|
|
57376
|
+
"Use the narrowest reliable tool for each task.",
|
|
58008
57377
|
"",
|
|
58009
|
-
"Inspect before
|
|
57378
|
+
"Inspect before editing:",
|
|
58010
57379
|
"- Use `glob` to discover files.",
|
|
58011
57380
|
"- Use `grep` to locate relevant code or markup.",
|
|
58012
|
-
"- Use `read` before editing
|
|
58013
|
-
"- Always inspect before coordinated edits across existing files.",
|
|
57381
|
+
"- Use `read` before editing an existing file.",
|
|
58014
57382
|
"",
|
|
58015
|
-
"Choose
|
|
57383
|
+
"Choose tools by intent:",
|
|
57384
|
+
"- Use `createHtml` only to create a missing `index.html` file.",
|
|
58016
57385
|
"- Use `edit` for small, focused replacements in one existing file.",
|
|
58017
|
-
"- Use `patch` for coordinated changes
|
|
58018
|
-
"- Use `write` only for
|
|
58019
|
-
"- Do not use `write`
|
|
58020
|
-
"- Use `
|
|
58021
|
-
"- Use `
|
|
57386
|
+
"- Use `patch` for coordinated changes or repeated replacements.",
|
|
57387
|
+
"- Use `write` only for deliberate full-file replacement of `index.html`.",
|
|
57388
|
+
"- Do not use `write` to create the initial `index.html`; use `createHtml` first.",
|
|
57389
|
+
"- Use `copyFile` only when the current user message explicitly asks you to duplicate an existing file.",
|
|
57390
|
+
"- Use `delete` only after confirming the file is not referenced.",
|
|
58022
57391
|
"",
|
|
58023
|
-
"
|
|
58024
|
-
|
|
58025
|
-
"-
|
|
58026
|
-
"- For `createHtml`, pass the resolved target path. Pass `fontLibraryName` or `iconLibraryName` only when the user explicitly names a font or icon library; otherwise omit them so the tool reads configured defaults.",
|
|
58027
|
-
"- After `createHtml`, immediately use `read` on that file before editing it.",
|
|
58028
|
-
"- If the target HTML file exists, use `read` before editing it; do not call `createHtml`.",
|
|
58029
|
-
"- Use `edit` or `patch` for HTML changes after reading the file.",
|
|
57392
|
+
"Single HTML create vs update flow:",
|
|
57393
|
+
'- When `index.html` is missing, call `createHtml({ path: "index.html" })`, then read it and replace the default placeholder markup, CSS, and script with a complete designed prototype.',
|
|
57394
|
+
"- When `index.html` exists, read it before editing and do not call `createHtml`.",
|
|
58030
57395
|
"",
|
|
58031
57396
|
"Recover from tool failures:",
|
|
58032
|
-
"- If
|
|
58033
|
-
"- If a
|
|
58034
|
-
"",
|
|
58035
|
-
"Resource constraints:",
|
|
58036
|
-
"- Only use CDNs already listed in resource settings; do not add others.",
|
|
58037
|
-
"- `write`, `edit`, and `patch` will reject HTML with unlisted CDN tags - if rejected, fall back to configured libraries, system fonts, inline SVG, or local CSS."
|
|
57397
|
+
"- If an edit fails, read the file again and retry with a smaller edit or patch.",
|
|
57398
|
+
"- If a generated prototype becomes too large or brittle, simplify the file while preserving visible quality."
|
|
58038
57399
|
].join("\n");
|
|
58039
57400
|
}
|
|
58040
57401
|
function buildResourcePolicyPrompt(resources) {
|
|
@@ -58047,17 +57408,22 @@ function buildResourcePolicyPrompt(resources) {
|
|
|
58047
57408
|
"Use these global resource settings when designing HTML preview pages.",
|
|
58048
57409
|
defaultFontLibrary ? `Default font library: ${defaultFontLibrary.name}.` : "Default font library: none configured.",
|
|
58049
57410
|
defaultIconLibrary ? `Default icon library: ${defaultIconLibrary.name}.` : "Default icon library: none configured.",
|
|
58050
|
-
"
|
|
58051
|
-
"
|
|
58052
|
-
"
|
|
58053
|
-
"
|
|
58054
|
-
"
|
|
57411
|
+
"The default HTML template already configures Inter and Noto Sans SC on the `html` element.",
|
|
57412
|
+
"Unless the user explicitly asks for a different typeface, do not change `font-family`; adjust typography with size, weight, line-height, spacing, and hierarchy.",
|
|
57413
|
+
"Lucide icons are already configured by the default HTML template.",
|
|
57414
|
+
'Use Lucide icons with `<i data-lucide="menu"></i>` syntax, replacing `menu` with the appropriate Lucide icon name.',
|
|
57415
|
+
"Do not use other icon systems, inline SVG icons, emoji icons, or decorative emoji as UI icons.",
|
|
57416
|
+
"When styling Lucide icons, do not target `i`, `i[data-lucide]`, or tag selectors because Lucide replaces the placeholder with inline `svg` elements.",
|
|
57417
|
+
"Give icons a semantic class or wrap them in a classed element, then style the class and child `svg`, such as `.nav-icon svg { width: 18px; height: 18px; stroke-width: 2; }`.",
|
|
57418
|
+
"If JavaScript dynamically inserts markup that contains Lucide placeholders, call `lucide.createIcons()` after updating the DOM.",
|
|
57419
|
+
"Prefer configured resources and local CSS before adding any external resource.",
|
|
57420
|
+
"Add an extra external resource only when the user explicitly requests it or when it is necessary for the prototype quality.",
|
|
57421
|
+
"When a configured library has no CDN, follow the library choice in CSS naming only.",
|
|
58055
57422
|
"Configured font libraries:",
|
|
58056
57423
|
fontLines.length ? fontLines.join("\n") : "- none",
|
|
58057
57424
|
"Configured icon libraries:",
|
|
58058
57425
|
iconLines.length ? iconLines.join("\n") : "- none",
|
|
58059
|
-
"Use regular inline CSS as the primary styling method."
|
|
58060
|
-
"Do not add new CDN resources. If a needed resource is not configured, use system fonts, inline SVG, local CSS, or explain the limitation."
|
|
57426
|
+
"Use regular inline CSS as the primary styling method."
|
|
58061
57427
|
].join("\n");
|
|
58062
57428
|
}
|
|
58063
57429
|
function buildApprovedCdnUrls(resources) {
|
|
@@ -58075,75 +57441,6 @@ function formatResourceLibraryList(libraries) {
|
|
|
58075
57441
|
);
|
|
58076
57442
|
}
|
|
58077
57443
|
|
|
58078
|
-
// ../core/src/agent/turn-prompt-rewriter.ts
|
|
58079
|
-
async function rewriteTurnPrompt({
|
|
58080
|
-
model,
|
|
58081
|
-
originalUserPrompt,
|
|
58082
|
-
pageEditMode,
|
|
58083
|
-
pageEditModePolicy,
|
|
58084
|
-
previewPath,
|
|
58085
|
-
providerOptions
|
|
58086
|
-
}) {
|
|
58087
|
-
const result = await generateText({
|
|
58088
|
-
model,
|
|
58089
|
-
providerOptions,
|
|
58090
|
-
system: buildTurnPromptRewriterSystemPrompt(),
|
|
58091
|
-
prompt: buildTurnPromptRewriterPrompt({
|
|
58092
|
-
originalUserPrompt,
|
|
58093
|
-
pageEditMode,
|
|
58094
|
-
pageEditModePolicy,
|
|
58095
|
-
previewPath
|
|
58096
|
-
})
|
|
58097
|
-
});
|
|
58098
|
-
const rewrittenPrompt = cleanRewrittenPrompt(result.text);
|
|
58099
|
-
if (!rewrittenPrompt) {
|
|
58100
|
-
throw new Error("TurnPromptRewriter returned an empty prompt.");
|
|
58101
|
-
}
|
|
58102
|
-
return { rewrittenPrompt };
|
|
58103
|
-
}
|
|
58104
|
-
function buildTurnPromptRewriterSystemPrompt() {
|
|
58105
|
-
return loadPrompt("agents/turn-prompt-rewriter");
|
|
58106
|
-
}
|
|
58107
|
-
function buildTurnPromptRewriterPrompt({
|
|
58108
|
-
originalUserPrompt,
|
|
58109
|
-
pageEditMode,
|
|
58110
|
-
pageEditModePolicy,
|
|
58111
|
-
previewPath
|
|
58112
|
-
}) {
|
|
58113
|
-
return [
|
|
58114
|
-
`currentPreviewFile: ${previewPath ?? "none"}`,
|
|
58115
|
-
`pageEditMode: ${pageEditMode}`,
|
|
58116
|
-
formatPolicyLine(pageEditModePolicy),
|
|
58117
|
-
"",
|
|
58118
|
-
"Rewrite rules:",
|
|
58119
|
-
"- Keep the user's requested change unchanged in meaning.",
|
|
58120
|
-
"- Make the target page/action explicit when the edit mode provides one.",
|
|
58121
|
-
"- For duplicate_edit, tell the agent to use copyFile to copy the source page to the target page, then modify only the target HTML page.",
|
|
58122
|
-
"- For duplicate_edit, allow inspection of other files but forbid modifying any HTML page except the target page.",
|
|
58123
|
-
"- For new_page, tell the agent to create a new page, but do not forbid related edits such as navigation links.",
|
|
58124
|
-
"- For direct_edit, tell the agent to edit the current preview page directly.",
|
|
58125
|
-
"",
|
|
58126
|
-
"Original user request:",
|
|
58127
|
-
originalUserPrompt
|
|
58128
|
-
].join("\n");
|
|
58129
|
-
}
|
|
58130
|
-
function formatPolicyLine(policy) {
|
|
58131
|
-
if (policy.mode === "duplicate_edit") {
|
|
58132
|
-
return `duplicateSourcePath: ${policy.sourcePath}
|
|
58133
|
-
duplicateTargetPath: ${policy.targetPath}`;
|
|
58134
|
-
}
|
|
58135
|
-
if (policy.mode === "direct_edit") {
|
|
58136
|
-
return `targetPath: ${policy.targetPath}`;
|
|
58137
|
-
}
|
|
58138
|
-
if (policy.mode === "new_page") {
|
|
58139
|
-
return `currentPreviewFile: ${policy.currentPreviewPath ?? "none"}`;
|
|
58140
|
-
}
|
|
58141
|
-
return "targetPath: none";
|
|
58142
|
-
}
|
|
58143
|
-
function cleanRewrittenPrompt(text2) {
|
|
58144
|
-
return text2.trim().replace(/^```(?:text)?\s*/i, "").replace(/\s*```$/i, "").trim();
|
|
58145
|
-
}
|
|
58146
|
-
|
|
58147
57444
|
// ../core/src/preview/preview-server-manager.ts
|
|
58148
57445
|
import { access, readFile as readFile2 } from "node:fs/promises";
|
|
58149
57446
|
import path5 from "node:path";
|
|
@@ -58167,9 +57464,13 @@ var PreviewServerManager = class {
|
|
|
58167
57464
|
}
|
|
58168
57465
|
async ensure(projectId, clientId, previewPath) {
|
|
58169
57466
|
const entry = await this.getOrStartEntry(projectId, clientId);
|
|
58170
|
-
const files = await
|
|
57467
|
+
const [files, pageManifest] = await Promise.all([
|
|
57468
|
+
this.workspaceStore.listProjectHtmlFiles(projectId),
|
|
57469
|
+
this.workspaceStore.readProjectHtmlPageManifest(projectId)
|
|
57470
|
+
]);
|
|
58171
57471
|
const activePath = resolveActivePreviewPath(
|
|
58172
57472
|
files,
|
|
57473
|
+
pageManifest,
|
|
58173
57474
|
previewPath ?? entry.activePath
|
|
58174
57475
|
);
|
|
58175
57476
|
entry.activePath = activePath;
|
|
@@ -58178,6 +57479,7 @@ var PreviewServerManager = class {
|
|
|
58178
57479
|
return {
|
|
58179
57480
|
...activePath ? { activePath } : {},
|
|
58180
57481
|
files,
|
|
57482
|
+
pageManifest,
|
|
58181
57483
|
url: buildPreviewUrl(entry.baseUrl, activePath)
|
|
58182
57484
|
};
|
|
58183
57485
|
}
|
|
@@ -58211,9 +57513,7 @@ var PreviewServerManager = class {
|
|
|
58211
57513
|
return this.entries.size;
|
|
58212
57514
|
}
|
|
58213
57515
|
getLeaseCount(projectId) {
|
|
58214
|
-
return Array.from(this.entries.values()).filter(
|
|
58215
|
-
(entry) => entry.projectId === projectId
|
|
58216
|
-
).length;
|
|
57516
|
+
return Array.from(this.entries.values()).filter((entry) => entry.projectId === projectId).length;
|
|
58217
57517
|
}
|
|
58218
57518
|
async cleanupExpiredLeases() {
|
|
58219
57519
|
const now2 = this.now();
|
|
@@ -58253,24 +57553,21 @@ var PreviewServerManager = class {
|
|
|
58253
57553
|
key,
|
|
58254
57554
|
projectId
|
|
58255
57555
|
};
|
|
58256
|
-
app2.get(
|
|
58257
|
-
|
|
58258
|
-
async () => htmlResponse(await readIndexHtmlOrEmptyPreview(workspaceDirectory, entry))
|
|
58259
|
-
);
|
|
58260
|
-
app2.get(
|
|
58261
|
-
"/index.html",
|
|
58262
|
-
async () => htmlResponse(await readIndexHtmlOrEmptyPreview(workspaceDirectory, entry))
|
|
58263
|
-
);
|
|
57556
|
+
app2.get("/", async () => readIndexHtmlOrNotFound(workspaceDirectory, entry));
|
|
57557
|
+
app2.get("/index.html", async () => readIndexHtmlOrNotFound(workspaceDirectory, entry));
|
|
58264
57558
|
app2.use("*", async (context2, next) => {
|
|
58265
57559
|
context2.header("Cache-Control", PREVIEW_CACHE_CONTROL);
|
|
58266
57560
|
await next();
|
|
58267
57561
|
});
|
|
58268
|
-
app2.use(
|
|
58269
|
-
|
|
58270
|
-
|
|
58271
|
-
|
|
58272
|
-
|
|
58273
|
-
|
|
57562
|
+
app2.use(
|
|
57563
|
+
"*",
|
|
57564
|
+
serveStatic({
|
|
57565
|
+
onFound: (filePath) => {
|
|
57566
|
+
recordServedStaticPath(entry, workspaceDirectory, filePath);
|
|
57567
|
+
},
|
|
57568
|
+
root: workspaceDirectory
|
|
57569
|
+
})
|
|
57570
|
+
);
|
|
58274
57571
|
const server2 = await listenOnRandomPort(app2);
|
|
58275
57572
|
entry.server = server2.server;
|
|
58276
57573
|
entry.baseUrl = server2.baseUrl;
|
|
@@ -58349,123 +57646,32 @@ function getPreviewServerManager(workspaceStore) {
|
|
|
58349
57646
|
});
|
|
58350
57647
|
return globalThis.__owndesignPreviewServerManager;
|
|
58351
57648
|
}
|
|
58352
|
-
async function
|
|
57649
|
+
async function readIndexHtmlOrNotFound(workspaceDirectory, entry) {
|
|
58353
57650
|
const indexPath = path5.join(workspaceDirectory, "index.html");
|
|
58354
57651
|
try {
|
|
58355
57652
|
await access(indexPath);
|
|
58356
57653
|
entry.activePath = "index.html";
|
|
58357
|
-
return readFile2(indexPath, "utf8");
|
|
57654
|
+
return htmlResponse(await readFile2(indexPath, "utf8"));
|
|
58358
57655
|
} catch {
|
|
58359
|
-
return
|
|
58360
|
-
|
|
58361
|
-
|
|
58362
|
-
|
|
58363
|
-
|
|
58364
|
-
|
|
58365
|
-
|
|
58366
|
-
|
|
58367
|
-
|
|
58368
|
-
<title>OwnDesign Preview</title>
|
|
58369
|
-
<style>
|
|
58370
|
-
:root {
|
|
58371
|
-
color-scheme: dark;
|
|
58372
|
-
--bg-base: #0a0a0b;
|
|
58373
|
-
--bg-surface: #141416;
|
|
58374
|
-
--bg-elevated: #1c1c1f;
|
|
58375
|
-
--border-color: #2a2a2e;
|
|
58376
|
-
--border-light: #38383d;
|
|
58377
|
-
--text-primary: #f0f0f2;
|
|
58378
|
-
--text-secondary: #a0a0ab;
|
|
58379
|
-
--text-tertiary: #6b6b76;
|
|
58380
|
-
--shadow-lg: 0 18px 48px rgba(0, 0, 0, 0.45);
|
|
58381
|
-
}
|
|
58382
|
-
* {
|
|
58383
|
-
box-sizing: border-box;
|
|
58384
|
-
}
|
|
58385
|
-
html {
|
|
58386
|
-
height: 100%;
|
|
58387
|
-
background: var(--bg-base);
|
|
58388
|
-
}
|
|
58389
|
-
body {
|
|
58390
|
-
margin: 0;
|
|
58391
|
-
min-height: 100vh;
|
|
58392
|
-
display: flex;
|
|
58393
|
-
align-items: center;
|
|
58394
|
-
justify-content: center;
|
|
58395
|
-
padding: 24px;
|
|
58396
|
-
background:
|
|
58397
|
-
radial-gradient(circle at top, rgba(255,255,255,0.04), transparent 34%),
|
|
58398
|
-
var(--bg-base);
|
|
58399
|
-
color: var(--text-primary);
|
|
58400
|
-
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Noto Sans SC", sans-serif;
|
|
58401
|
-
}
|
|
58402
|
-
main {
|
|
58403
|
-
width: min(100%, 28rem);
|
|
58404
|
-
padding: 2rem;
|
|
58405
|
-
border: 1px solid var(--border-color);
|
|
58406
|
-
border-radius: 24px;
|
|
58407
|
-
background: var(--bg-surface);
|
|
58408
|
-
text-align: center;
|
|
58409
|
-
box-shadow: var(--shadow-lg);
|
|
58410
|
-
}
|
|
58411
|
-
.icon {
|
|
58412
|
-
width: 56px;
|
|
58413
|
-
height: 56px;
|
|
58414
|
-
margin: 0 auto;
|
|
58415
|
-
display: flex;
|
|
58416
|
-
align-items: center;
|
|
58417
|
-
justify-content: center;
|
|
58418
|
-
border-radius: 18px;
|
|
58419
|
-
border: 1px solid var(--border-light);
|
|
58420
|
-
background: var(--bg-elevated);
|
|
58421
|
-
color: var(--text-secondary);
|
|
58422
|
-
box-shadow: inset 0 1px 0 rgba(255,255,255,0.03);
|
|
58423
|
-
}
|
|
58424
|
-
.badge {
|
|
58425
|
-
margin-top: 20px;
|
|
58426
|
-
color: var(--text-tertiary);
|
|
58427
|
-
font-size: 11px;
|
|
58428
|
-
font-weight: 600;
|
|
58429
|
-
letter-spacing: 0.24em;
|
|
58430
|
-
text-transform: uppercase;
|
|
58431
|
-
}
|
|
58432
|
-
h1 {
|
|
58433
|
-
margin: 8px 0 0;
|
|
58434
|
-
color: var(--text-primary);
|
|
58435
|
-
font-size: 1.125rem;
|
|
58436
|
-
font-weight: 600;
|
|
58437
|
-
letter-spacing: -0.02em;
|
|
58438
|
-
}
|
|
58439
|
-
p {
|
|
58440
|
-
margin: 10px auto 0;
|
|
58441
|
-
max-width: 22rem;
|
|
58442
|
-
color: var(--text-secondary);
|
|
58443
|
-
font-size: 14px;
|
|
58444
|
-
line-height: 1.7;
|
|
58445
|
-
}
|
|
58446
|
-
</style>
|
|
58447
|
-
</head>
|
|
58448
|
-
<body>
|
|
58449
|
-
<main>
|
|
58450
|
-
<div class="icon" aria-hidden="true">
|
|
58451
|
-
<svg viewBox="0 0 24 24" width="24" height="24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">
|
|
58452
|
-
<path d="M4 7.5A2.5 2.5 0 0 1 6.5 5H10l2 2h5.5A2.5 2.5 0 0 1 20 9.5v7A2.5 2.5 0 0 1 17.5 19h-11A2.5 2.5 0 0 1 4 16.5z" />
|
|
58453
|
-
</svg>
|
|
58454
|
-
</div>
|
|
58455
|
-
<div class="badge">Preview</div>
|
|
58456
|
-
<h1>\u7B49\u5F85\u751F\u6210 HTML</h1>
|
|
58457
|
-
<p>\u5728\u5DE6\u4FA7\u8F93\u5165\u201C\u8BBE\u8BA1\u4E00\u4E2A XXX \u7684\u754C\u9762\u201D\uFF0C\u751F\u6210\u7ED3\u679C\u4F1A\u663E\u793A\u5728\u8FD9\u91CC\u3002</p>
|
|
58458
|
-
</main>
|
|
58459
|
-
</body>
|
|
58460
|
-
</html>`;
|
|
58461
|
-
}
|
|
58462
|
-
function resolveActivePreviewPath(files, previewPath) {
|
|
57656
|
+
return new Response(null, {
|
|
57657
|
+
headers: {
|
|
57658
|
+
"Cache-Control": PREVIEW_CACHE_CONTROL
|
|
57659
|
+
},
|
|
57660
|
+
status: 404
|
|
57661
|
+
});
|
|
57662
|
+
}
|
|
57663
|
+
}
|
|
57664
|
+
function resolveActivePreviewPath(files, pageManifest, previewPath) {
|
|
58463
57665
|
if (previewPath && files.includes(previewPath)) {
|
|
58464
57666
|
return previewPath;
|
|
58465
57667
|
}
|
|
58466
57668
|
if (files.includes("index.html")) {
|
|
58467
57669
|
return "index.html";
|
|
58468
57670
|
}
|
|
57671
|
+
const manifestPath = pageManifest.pages.find((page) => files.includes(page.htmlPath))?.htmlPath;
|
|
57672
|
+
if (manifestPath) {
|
|
57673
|
+
return manifestPath;
|
|
57674
|
+
}
|
|
58469
57675
|
return files[0];
|
|
58470
57676
|
}
|
|
58471
57677
|
function buildPreviewUrl(baseUrl, previewPath) {
|
|
@@ -58493,11 +57699,7 @@ function recordServedStaticPath(entry, workspaceDirectory, servedPath) {
|
|
|
58493
57699
|
}
|
|
58494
57700
|
|
|
58495
57701
|
// ../core/src/navigation.ts
|
|
58496
|
-
function buildWorkspaceHref({
|
|
58497
|
-
conversationId,
|
|
58498
|
-
previewPath,
|
|
58499
|
-
projectId
|
|
58500
|
-
}) {
|
|
57702
|
+
function buildWorkspaceHref({ conversationId, previewPath, projectId }) {
|
|
58501
57703
|
if (!projectId) {
|
|
58502
57704
|
return "/";
|
|
58503
57705
|
}
|
|
@@ -58548,11 +57750,7 @@ var ConversationService = class {
|
|
|
58548
57750
|
titleManuallySet: true,
|
|
58549
57751
|
updatedAt: this.now()
|
|
58550
57752
|
};
|
|
58551
|
-
return this.workspaceStore.updateConversation(
|
|
58552
|
-
projectId,
|
|
58553
|
-
conversationId,
|
|
58554
|
-
updatedConversation
|
|
58555
|
-
);
|
|
57753
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58556
57754
|
}
|
|
58557
57755
|
async switchConversation(projectId, conversationId) {
|
|
58558
57756
|
return this.workspaceStore.getConversation(projectId, conversationId);
|
|
@@ -58571,7 +57769,7 @@ var ConversationService = class {
|
|
|
58571
57769
|
};
|
|
58572
57770
|
const agentResult = await this.generateProjectOutputSafely({
|
|
58573
57771
|
content,
|
|
58574
|
-
|
|
57772
|
+
projectType: project.projectType ?? "single_html",
|
|
58575
57773
|
projectId
|
|
58576
57774
|
});
|
|
58577
57775
|
const mockReply = {
|
|
@@ -58579,11 +57777,7 @@ var ConversationService = class {
|
|
|
58579
57777
|
content: agentResult.content,
|
|
58580
57778
|
createdAt: timestamp
|
|
58581
57779
|
};
|
|
58582
|
-
const messages = [
|
|
58583
|
-
...existingConversation.messages,
|
|
58584
|
-
userMessage,
|
|
58585
|
-
mockReply
|
|
58586
|
-
];
|
|
57780
|
+
const messages = [...existingConversation.messages, userMessage, mockReply];
|
|
58587
57781
|
const updatedConversation = {
|
|
58588
57782
|
...existingConversation,
|
|
58589
57783
|
title: !existingConversation.titleManuallySet && existingConversation.title === DEFAULT_CONVERSATION_TITLE && existingConversation.messages.length === 0 ? summarizeConversationTitle(content) : existingConversation.title,
|
|
@@ -58596,11 +57790,7 @@ var ConversationService = class {
|
|
|
58596
57790
|
updatedAt: timestamp
|
|
58597
57791
|
};
|
|
58598
57792
|
await this.workspaceStore.updateProject(projectId, updatedProject);
|
|
58599
|
-
return this.workspaceStore.updateConversation(
|
|
58600
|
-
projectId,
|
|
58601
|
-
conversationId,
|
|
58602
|
-
updatedConversation
|
|
58603
|
-
);
|
|
57793
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58604
57794
|
}
|
|
58605
57795
|
async saveUIMessageStream(projectId, conversationId, messages) {
|
|
58606
57796
|
const existingConversation = await this.workspaceStore.getConversation(
|
|
@@ -58622,22 +57812,13 @@ var ConversationService = class {
|
|
|
58622
57812
|
updatedAt: timestamp
|
|
58623
57813
|
};
|
|
58624
57814
|
await this.workspaceStore.updateProject(projectId, updatedProject);
|
|
58625
|
-
return this.workspaceStore.updateConversation(
|
|
58626
|
-
projectId,
|
|
58627
|
-
conversationId,
|
|
58628
|
-
updatedConversation
|
|
58629
|
-
);
|
|
57815
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58630
57816
|
}
|
|
58631
57817
|
async deleteConversation(projectId, conversationId, defaultTitle) {
|
|
58632
57818
|
await this.workspaceStore.deleteConversation(projectId, conversationId);
|
|
58633
|
-
let remainingConversations = await this.workspaceStore.listConversations(
|
|
58634
|
-
projectId
|
|
58635
|
-
);
|
|
57819
|
+
let remainingConversations = await this.workspaceStore.listConversations(projectId);
|
|
58636
57820
|
if (remainingConversations.length === 0) {
|
|
58637
|
-
const replacementConversation = await this.createConversation(
|
|
58638
|
-
projectId,
|
|
58639
|
-
defaultTitle
|
|
58640
|
-
);
|
|
57821
|
+
const replacementConversation = await this.createConversation(projectId, defaultTitle);
|
|
58641
57822
|
remainingConversations = [replacementConversation];
|
|
58642
57823
|
}
|
|
58643
57824
|
return remainingConversations;
|
|
@@ -58676,11 +57857,16 @@ var ProjectService = class {
|
|
|
58676
57857
|
this.previewServerManager = options.previewServerManager;
|
|
58677
57858
|
}
|
|
58678
57859
|
async createProject(input) {
|
|
57860
|
+
const projectType = input.projectType ?? "single_html";
|
|
57861
|
+
if (projectType === "react") {
|
|
57862
|
+
throw new Error("React project type is reserved but not supported yet.");
|
|
57863
|
+
}
|
|
58679
57864
|
const timestamp = this.now();
|
|
58680
57865
|
const project = {
|
|
58681
57866
|
id: this.createId(),
|
|
58682
57867
|
name: input.name,
|
|
58683
57868
|
description: input.description,
|
|
57869
|
+
projectType,
|
|
58684
57870
|
outputType: "html",
|
|
58685
57871
|
createdAt: timestamp,
|
|
58686
57872
|
updatedAt: timestamp
|
|
@@ -58694,6 +57880,11 @@ var ProjectService = class {
|
|
|
58694
57880
|
messages: []
|
|
58695
57881
|
};
|
|
58696
57882
|
await this.workspaceStore.createProject(project);
|
|
57883
|
+
await this.workspaceStore.writeProjectWorkspaceFile(
|
|
57884
|
+
project.id,
|
|
57885
|
+
"index.html",
|
|
57886
|
+
buildSingleHtmlTemplate({ title: input.name })
|
|
57887
|
+
);
|
|
58697
57888
|
await this.workspaceStore.createConversation(conversation);
|
|
58698
57889
|
return { conversation, project };
|
|
58699
57890
|
}
|
|
@@ -58720,15 +57911,7 @@ var ProjectService = class {
|
|
|
58720
57911
|
};
|
|
58721
57912
|
|
|
58722
57913
|
// ../core/src/workspace-store/store.ts
|
|
58723
|
-
import {
|
|
58724
|
-
lstat,
|
|
58725
|
-
mkdir as mkdir2,
|
|
58726
|
-
readdir,
|
|
58727
|
-
readFile as readFile4,
|
|
58728
|
-
rm,
|
|
58729
|
-
stat as stat3,
|
|
58730
|
-
writeFile as writeFile2
|
|
58731
|
-
} from "node:fs/promises";
|
|
57914
|
+
import { copyFile, lstat, mkdir as mkdir2, readdir, readFile as readFile4, rm, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
|
|
58732
57915
|
import os5 from "node:os";
|
|
58733
57916
|
import path13 from "node:path";
|
|
58734
57917
|
import process12 from "node:process";
|
|
@@ -58744,7 +57927,7 @@ function normalizePositiveInteger(value, fallback, name21) {
|
|
|
58744
57927
|
}
|
|
58745
57928
|
return value;
|
|
58746
57929
|
}
|
|
58747
|
-
function
|
|
57930
|
+
function countOccurrences(content, needle) {
|
|
58748
57931
|
if (!needle) {
|
|
58749
57932
|
return 0;
|
|
58750
57933
|
}
|
|
@@ -58757,27 +57940,25 @@ function applyTextEdit(content, oldText, newText, replaceAll = false, relativePa
|
|
|
58757
57940
|
if (oldText === newText) {
|
|
58758
57941
|
throw new Error("No changes to apply: oldText and newText are identical.");
|
|
58759
57942
|
}
|
|
58760
|
-
const normalizedOldText =
|
|
58761
|
-
const normalizedNewText =
|
|
57943
|
+
const normalizedOldText = convertToLineEnding(oldText, detectLineEnding(content));
|
|
57944
|
+
const normalizedNewText = convertToLineEnding(newText, detectLineEnding(content));
|
|
58762
57945
|
const firstIndex = content.indexOf(normalizedOldText);
|
|
58763
57946
|
if (firstIndex === -1) {
|
|
58764
57947
|
throw new Error(`oldText was not found in Project Workspace file: ${relativePath}`);
|
|
58765
57948
|
}
|
|
58766
|
-
const replacements =
|
|
57949
|
+
const replacements = countOccurrences(content, normalizedOldText);
|
|
58767
57950
|
if (!replaceAll && replacements > 1) {
|
|
58768
|
-
throw new Error(
|
|
58769
|
-
`oldText appears more than once in Project Workspace file: ${relativePath}`
|
|
58770
|
-
);
|
|
57951
|
+
throw new Error(`oldText appears more than once in Project Workspace file: ${relativePath}`);
|
|
58771
57952
|
}
|
|
58772
57953
|
return {
|
|
58773
57954
|
content: replaceAll ? content.split(normalizedOldText).join(normalizedNewText) : content.slice(0, firstIndex) + normalizedNewText + content.slice(firstIndex + normalizedOldText.length),
|
|
58774
57955
|
replacements: replaceAll ? replacements : 1
|
|
58775
57956
|
};
|
|
58776
57957
|
}
|
|
58777
|
-
function
|
|
57958
|
+
function detectLineEnding(text2) {
|
|
58778
57959
|
return text2.includes("\r\n") ? "\r\n" : "\n";
|
|
58779
57960
|
}
|
|
58780
|
-
function
|
|
57961
|
+
function convertToLineEnding(text2, ending) {
|
|
58781
57962
|
const normalized = text2.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
|
|
58782
57963
|
return ending === "\n" ? normalized : normalized.replaceAll("\n", "\r\n");
|
|
58783
57964
|
}
|
|
@@ -58832,6 +58013,39 @@ function buildUnifiedDiff(oldContent, newContent, relativePath) {
|
|
|
58832
58013
|
return lines.join("\n");
|
|
58833
58014
|
}
|
|
58834
58015
|
|
|
58016
|
+
// ../core/src/html-page-manifest.ts
|
|
58017
|
+
var HTML_PAGE_MANIFEST_PATH = ".owndesign-pages.json";
|
|
58018
|
+
var EMPTY_HTML_PAGE_MANIFEST = {
|
|
58019
|
+
pages: []
|
|
58020
|
+
};
|
|
58021
|
+
function parseHtmlPageManifest(content) {
|
|
58022
|
+
if (!content) {
|
|
58023
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58024
|
+
}
|
|
58025
|
+
let value;
|
|
58026
|
+
try {
|
|
58027
|
+
value = JSON.parse(content);
|
|
58028
|
+
} catch {
|
|
58029
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58030
|
+
}
|
|
58031
|
+
if (!isRecord2(value) || !Array.isArray(value.pages)) {
|
|
58032
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58033
|
+
}
|
|
58034
|
+
const pages = value.pages.filter(isRecord2).map((page) => ({
|
|
58035
|
+
componentSource: typeof page.componentSource === "string" ? page.componentSource.trim() : "",
|
|
58036
|
+
componentTag: typeof page.componentTag === "string" ? page.componentTag.trim() : "",
|
|
58037
|
+
displayName: typeof page.displayName === "string" ? page.displayName.trim() : "",
|
|
58038
|
+
htmlPath: typeof page.htmlPath === "string" ? page.htmlPath.trim() : "",
|
|
58039
|
+
slug: typeof page.slug === "string" ? page.slug.trim() : ""
|
|
58040
|
+
})).filter(
|
|
58041
|
+
(page) => page.slug && page.displayName && page.htmlPath && page.componentTag && page.componentSource
|
|
58042
|
+
);
|
|
58043
|
+
return { pages };
|
|
58044
|
+
}
|
|
58045
|
+
function isRecord2(value) {
|
|
58046
|
+
return typeof value === "object" && value !== null;
|
|
58047
|
+
}
|
|
58048
|
+
|
|
58835
58049
|
// ../core/src/workspace-store/files.ts
|
|
58836
58050
|
import { open, readFile as readFile3, stat as stat2 } from "node:fs/promises";
|
|
58837
58051
|
|
|
@@ -59153,10 +58367,10 @@ var isSymlinkSync = isTypeSync.bind(void 0, "lstatSync", "isSymbolicLink");
|
|
|
59153
58367
|
// ../../node_modules/.pnpm/unicorn-magic@0.3.0/node_modules/unicorn-magic/node.js
|
|
59154
58368
|
import { promisify } from "node:util";
|
|
59155
58369
|
import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
|
|
59156
|
-
import { fileURLToPath as
|
|
58370
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
59157
58371
|
var execFileOriginal = promisify(execFileCallback);
|
|
59158
58372
|
function toPath(urlOrPath) {
|
|
59159
|
-
return urlOrPath instanceof URL ?
|
|
58373
|
+
return urlOrPath instanceof URL ? fileURLToPath3(urlOrPath) : urlOrPath;
|
|
59160
58374
|
}
|
|
59161
58375
|
var TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
|
|
59162
58376
|
|
|
@@ -59543,14 +58757,7 @@ if ($item.PSIsContainer) {
|
|
|
59543
58757
|
`;
|
|
59544
58758
|
await execFileAsync(
|
|
59545
58759
|
"powershell.exe",
|
|
59546
|
-
[
|
|
59547
|
-
"-NoProfile",
|
|
59548
|
-
"-NonInteractive",
|
|
59549
|
-
"-ExecutionPolicy",
|
|
59550
|
-
"Bypass",
|
|
59551
|
-
"-Command",
|
|
59552
|
-
recycleScript
|
|
59553
|
-
],
|
|
58760
|
+
["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", recycleScript],
|
|
59554
58761
|
{
|
|
59555
58762
|
env: {
|
|
59556
58763
|
...process11.env,
|
|
@@ -59604,7 +58811,7 @@ var WorkspaceStore = class {
|
|
|
59604
58811
|
path13.join(projectsRoot, entry.name, "project.json"),
|
|
59605
58812
|
"utf8"
|
|
59606
58813
|
);
|
|
59607
|
-
return JSON.parse(projectJson);
|
|
58814
|
+
return normalizeProjectRecord(JSON.parse(projectJson));
|
|
59608
58815
|
})
|
|
59609
58816
|
);
|
|
59610
58817
|
return projects.sort(
|
|
@@ -59622,7 +58829,7 @@ var WorkspaceStore = class {
|
|
|
59622
58829
|
path13.join(this.getProjectDirectory(projectId), "project.json"),
|
|
59623
58830
|
"utf8"
|
|
59624
58831
|
);
|
|
59625
|
-
return JSON.parse(projectJson);
|
|
58832
|
+
return normalizeProjectRecord(JSON.parse(projectJson));
|
|
59626
58833
|
}
|
|
59627
58834
|
async updateProject(projectId, project) {
|
|
59628
58835
|
await writeFile2(
|
|
@@ -59685,6 +58892,70 @@ var WorkspaceStore = class {
|
|
|
59685
58892
|
);
|
|
59686
58893
|
return conversation;
|
|
59687
58894
|
}
|
|
58895
|
+
async createCheckpoint(input) {
|
|
58896
|
+
assertSafeCheckpointId(input.id);
|
|
58897
|
+
const record2 = {
|
|
58898
|
+
...input,
|
|
58899
|
+
files: ["index.html"]
|
|
58900
|
+
};
|
|
58901
|
+
const checkpointDirectory = this.getCheckpointDirectory(input.projectId, input.id);
|
|
58902
|
+
const filesDirectory = path13.join(checkpointDirectory, "files");
|
|
58903
|
+
const sourceFilePath = await this.resolveProjectWorkspacePath(input.projectId, "index.html", {
|
|
58904
|
+
checkTargetSymlink: true
|
|
58905
|
+
});
|
|
58906
|
+
await mkdir2(filesDirectory, { recursive: true });
|
|
58907
|
+
await copyFile(sourceFilePath, path13.join(filesDirectory, "index.html"));
|
|
58908
|
+
await writeFile2(
|
|
58909
|
+
path13.join(checkpointDirectory, "meta.json"),
|
|
58910
|
+
`${JSON.stringify(record2, null, 2)}
|
|
58911
|
+
`,
|
|
58912
|
+
"utf8"
|
|
58913
|
+
);
|
|
58914
|
+
return record2;
|
|
58915
|
+
}
|
|
58916
|
+
async listCheckpoints(projectId) {
|
|
58917
|
+
const checkpointsDirectory = this.getCheckpointsDirectory(projectId);
|
|
58918
|
+
try {
|
|
58919
|
+
const entries = await readdir(checkpointsDirectory, { withFileTypes: true });
|
|
58920
|
+
const checkpoints = await Promise.all(
|
|
58921
|
+
entries.filter((entry) => entry.isDirectory()).map(async (entry) => this.readCheckpoint(projectId, entry.name))
|
|
58922
|
+
);
|
|
58923
|
+
return checkpoints.sort(
|
|
58924
|
+
(left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime()
|
|
58925
|
+
);
|
|
58926
|
+
} catch (error51) {
|
|
58927
|
+
if (isMissingPathError3(error51)) {
|
|
58928
|
+
return [];
|
|
58929
|
+
}
|
|
58930
|
+
throw error51;
|
|
58931
|
+
}
|
|
58932
|
+
}
|
|
58933
|
+
async readCheckpoint(projectId, checkpointId) {
|
|
58934
|
+
assertSafeCheckpointId(checkpointId);
|
|
58935
|
+
const checkpointJson = await readFile4(
|
|
58936
|
+
path13.join(this.getCheckpointDirectory(projectId, checkpointId), "meta.json"),
|
|
58937
|
+
"utf8"
|
|
58938
|
+
);
|
|
58939
|
+
const checkpoint = JSON.parse(checkpointJson);
|
|
58940
|
+
if (checkpoint.projectId !== projectId || checkpoint.id !== checkpointId) {
|
|
58941
|
+
throw new Error("Checkpoint metadata does not match the requested project.");
|
|
58942
|
+
}
|
|
58943
|
+
return checkpoint;
|
|
58944
|
+
}
|
|
58945
|
+
async restoreCheckpointFiles(projectId, checkpointId) {
|
|
58946
|
+
const checkpoint = await this.readCheckpoint(projectId, checkpointId);
|
|
58947
|
+
const checkpointDirectory = this.getCheckpointDirectory(projectId, checkpointId);
|
|
58948
|
+
for (const file2 of checkpoint.files) {
|
|
58949
|
+
const sourcePath = path13.join(checkpointDirectory, "files", file2);
|
|
58950
|
+
const targetPath = await this.resolveProjectWorkspacePath(projectId, file2, {
|
|
58951
|
+
checkTargetSymlink: true,
|
|
58952
|
+
targetMayBeMissing: true
|
|
58953
|
+
});
|
|
58954
|
+
await mkdir2(path13.dirname(targetPath), { recursive: true });
|
|
58955
|
+
await copyFile(sourcePath, targetPath);
|
|
58956
|
+
}
|
|
58957
|
+
return checkpoint;
|
|
58958
|
+
}
|
|
59688
58959
|
async writeProjectOutput(projectId, outputType, content) {
|
|
59689
58960
|
const outputPath = this.getProjectOutputFilePath(projectId, outputType);
|
|
59690
58961
|
await mkdir2(path13.dirname(outputPath), { recursive: true });
|
|
@@ -59721,18 +58992,24 @@ var WorkspaceStore = class {
|
|
|
59721
58992
|
return left.localeCompare(right);
|
|
59722
58993
|
});
|
|
59723
58994
|
}
|
|
58995
|
+
async readProjectHtmlPageManifest(projectId) {
|
|
58996
|
+
try {
|
|
58997
|
+
return parseHtmlPageManifest(
|
|
58998
|
+
await this.readProjectWorkspaceFile(projectId, HTML_PAGE_MANIFEST_PATH)
|
|
58999
|
+
);
|
|
59000
|
+
} catch (error51) {
|
|
59001
|
+
if (isMissingPathError3(error51)) {
|
|
59002
|
+
return parseHtmlPageManifest(void 0);
|
|
59003
|
+
}
|
|
59004
|
+
throw error51;
|
|
59005
|
+
}
|
|
59006
|
+
}
|
|
59724
59007
|
async readProjectWorkspaceEntry(projectId, relativePath, options = {}) {
|
|
59725
59008
|
const offset = normalizePositiveInteger(options.offset, 1, "offset");
|
|
59726
|
-
const limit = normalizePositiveInteger(
|
|
59727
|
-
|
|
59728
|
-
|
|
59729
|
-
|
|
59730
|
-
);
|
|
59731
|
-
const targetPath = relativePath === "." ? this.getProjectWorkspaceDirectory(projectId) : await this.resolveProjectWorkspacePath(
|
|
59732
|
-
projectId,
|
|
59733
|
-
relativePath,
|
|
59734
|
-
{ checkTargetSymlink: true }
|
|
59735
|
-
);
|
|
59009
|
+
const limit = normalizePositiveInteger(options.limit, DEFAULT_READ_LIMIT, "limit");
|
|
59010
|
+
const targetPath = relativePath === "." ? this.getProjectWorkspaceDirectory(projectId) : await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59011
|
+
checkTargetSymlink: true
|
|
59012
|
+
});
|
|
59736
59013
|
const targetStats = await lstat(targetPath);
|
|
59737
59014
|
const normalizedPath = normalizeWorkspaceRelativePath(relativePath);
|
|
59738
59015
|
if (targetStats.isSymbolicLink()) {
|
|
@@ -59752,15 +59029,11 @@ var WorkspaceStore = class {
|
|
|
59752
59029
|
return void 0;
|
|
59753
59030
|
}
|
|
59754
59031
|
return {
|
|
59755
|
-
path: normalizeWorkspaceRelativePath(
|
|
59756
|
-
path13.relative(rootPath, absolutePath)
|
|
59757
|
-
),
|
|
59032
|
+
path: normalizeWorkspaceRelativePath(path13.relative(rootPath, absolutePath)),
|
|
59758
59033
|
type: entryStats.isDirectory() ? "directory" : "file"
|
|
59759
59034
|
};
|
|
59760
59035
|
})
|
|
59761
|
-
)).filter(
|
|
59762
|
-
(entry) => Boolean(entry)
|
|
59763
|
-
).sort((left, right) => left.path.localeCompare(right.path));
|
|
59036
|
+
)).filter((entry) => Boolean(entry)).sort((left, right) => left.path.localeCompare(right.path));
|
|
59764
59037
|
const start2 = offset - 1;
|
|
59765
59038
|
const sliced = visibleEntries.slice(start2, start2 + limit);
|
|
59766
59039
|
return {
|
|
@@ -59833,20 +59106,16 @@ var WorkspaceStore = class {
|
|
|
59833
59106
|
const startPath = relativePath && relativePath !== "." ? relativePath : "";
|
|
59834
59107
|
const matcher = globToRegExp(pattern);
|
|
59835
59108
|
const matches = [];
|
|
59836
|
-
await this.walkProjectWorkspace(
|
|
59837
|
-
|
|
59838
|
-
|
|
59839
|
-
|
|
59840
|
-
|
|
59841
|
-
|
|
59842
|
-
|
|
59843
|
-
|
|
59844
|
-
type: entry.type,
|
|
59845
|
-
updatedAt: entry.updatedAt
|
|
59846
|
-
});
|
|
59847
|
-
}
|
|
59109
|
+
await this.walkProjectWorkspace(projectId, startPath, async (entry) => {
|
|
59110
|
+
const pathFromStart = startPath ? normalizeWorkspaceRelativePath(path13.relative(startPath, entry.path)) : entry.path;
|
|
59111
|
+
if (matcher.test(pathFromStart) || matcher.test(path13.basename(entry.path))) {
|
|
59112
|
+
matches.push({
|
|
59113
|
+
path: entry.path,
|
|
59114
|
+
type: entry.type,
|
|
59115
|
+
updatedAt: entry.updatedAt
|
|
59116
|
+
});
|
|
59848
59117
|
}
|
|
59849
|
-
);
|
|
59118
|
+
});
|
|
59850
59119
|
const sortedMatches = matches.sort(
|
|
59851
59120
|
(left, right) => new Date(right.updatedAt).getTime() - new Date(left.updatedAt).getTime()
|
|
59852
59121
|
);
|
|
@@ -59944,11 +59213,7 @@ var WorkspaceStore = class {
|
|
|
59944
59213
|
if (!changes.length) {
|
|
59945
59214
|
throw new Error("Project Workspace patch must include at least one change.");
|
|
59946
59215
|
}
|
|
59947
|
-
const prepared = await this.prepareProjectWorkspacePatch(
|
|
59948
|
-
projectId,
|
|
59949
|
-
changes,
|
|
59950
|
-
options
|
|
59951
|
-
);
|
|
59216
|
+
const prepared = await this.prepareProjectWorkspacePatch(projectId, changes, options);
|
|
59952
59217
|
for (const change of prepared) {
|
|
59953
59218
|
if (change.operation === "delete") {
|
|
59954
59219
|
await rm(change.absolutePath, { force: false, recursive: true });
|
|
@@ -59978,26 +59243,14 @@ var WorkspaceStore = class {
|
|
|
59978
59243
|
}) : this.getProjectWorkspaceDirectory(projectId);
|
|
59979
59244
|
const startStats = await stat3(startPath);
|
|
59980
59245
|
if (startStats.isFile()) {
|
|
59981
|
-
await this.searchWorkspaceFile(
|
|
59982
|
-
projectId,
|
|
59983
|
-
startPath,
|
|
59984
|
-
query,
|
|
59985
|
-
matches,
|
|
59986
|
-
skippedFiles
|
|
59987
|
-
);
|
|
59246
|
+
await this.searchWorkspaceFile(projectId, startPath, query, matches, skippedFiles);
|
|
59988
59247
|
} else if (startStats.isDirectory()) {
|
|
59989
59248
|
await this.walkProjectWorkspace(
|
|
59990
59249
|
projectId,
|
|
59991
59250
|
relativePath === "." ? "" : relativePath,
|
|
59992
59251
|
async (entry, absolutePath) => {
|
|
59993
59252
|
if (entry.type === "file") {
|
|
59994
|
-
await this.searchWorkspaceFile(
|
|
59995
|
-
projectId,
|
|
59996
|
-
absolutePath,
|
|
59997
|
-
query,
|
|
59998
|
-
matches,
|
|
59999
|
-
skippedFiles
|
|
60000
|
-
);
|
|
59253
|
+
await this.searchWorkspaceFile(projectId, absolutePath, query, matches, skippedFiles);
|
|
60001
59254
|
}
|
|
60002
59255
|
}
|
|
60003
59256
|
);
|
|
@@ -60011,11 +59264,9 @@ var WorkspaceStore = class {
|
|
|
60011
59264
|
};
|
|
60012
59265
|
}
|
|
60013
59266
|
async readProjectWorkspaceFile(projectId, relativePath) {
|
|
60014
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60015
|
-
|
|
60016
|
-
|
|
60017
|
-
{ checkTargetSymlink: true }
|
|
60018
|
-
);
|
|
59267
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59268
|
+
checkTargetSymlink: true
|
|
59269
|
+
});
|
|
60019
59270
|
const fileStats = await stat3(filePath);
|
|
60020
59271
|
if (!fileStats.isFile()) {
|
|
60021
59272
|
throw new Error(`Project Workspace path is not a file: ${relativePath}`);
|
|
@@ -60023,11 +59274,9 @@ var WorkspaceStore = class {
|
|
|
60023
59274
|
return readFile4(filePath, "utf8");
|
|
60024
59275
|
}
|
|
60025
59276
|
async readProjectWorkspaceFileBuffer(projectId, relativePath) {
|
|
60026
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60027
|
-
|
|
60028
|
-
|
|
60029
|
-
{ checkTargetSymlink: true }
|
|
60030
|
-
);
|
|
59277
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59278
|
+
checkTargetSymlink: true
|
|
59279
|
+
});
|
|
60031
59280
|
const fileStats = await stat3(filePath);
|
|
60032
59281
|
if (!fileStats.isFile()) {
|
|
60033
59282
|
throw new Error(`Project Workspace path is not a file: ${relativePath}`);
|
|
@@ -60035,11 +59284,10 @@ var WorkspaceStore = class {
|
|
|
60035
59284
|
return readFile4(filePath);
|
|
60036
59285
|
}
|
|
60037
59286
|
async writeProjectWorkspaceFile(projectId, relativePath, content) {
|
|
60038
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60039
|
-
|
|
60040
|
-
|
|
60041
|
-
|
|
60042
|
-
);
|
|
59287
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59288
|
+
checkTargetSymlink: true,
|
|
59289
|
+
targetMayBeMissing: true
|
|
59290
|
+
});
|
|
60043
59291
|
const previousContent = await readTextFileIfExists(filePath);
|
|
60044
59292
|
await mkdir2(path13.dirname(filePath), { recursive: true });
|
|
60045
59293
|
await writeFile2(filePath, content, "utf8");
|
|
@@ -60074,21 +59322,15 @@ var WorkspaceStore = class {
|
|
|
60074
59322
|
);
|
|
60075
59323
|
await this.writeProjectWorkspaceFile(projectId, relativePath, updatedContent);
|
|
60076
59324
|
return {
|
|
60077
|
-
diff: buildUnifiedDiff(
|
|
60078
|
-
content,
|
|
60079
|
-
updatedContent,
|
|
60080
|
-
normalizeWorkspaceRelativePath(relativePath)
|
|
60081
|
-
),
|
|
59325
|
+
diff: buildUnifiedDiff(content, updatedContent, normalizeWorkspaceRelativePath(relativePath)),
|
|
60082
59326
|
path: normalizeWorkspaceRelativePath(relativePath),
|
|
60083
59327
|
replacements: replaceAll ? replacements : 1
|
|
60084
59328
|
};
|
|
60085
59329
|
}
|
|
60086
59330
|
async deleteProjectWorkspacePath(projectId, relativePath) {
|
|
60087
|
-
const targetPath = await this.resolveProjectWorkspacePath(
|
|
60088
|
-
|
|
60089
|
-
|
|
60090
|
-
{ checkTargetSymlink: true }
|
|
60091
|
-
);
|
|
59331
|
+
const targetPath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59332
|
+
checkTargetSymlink: true
|
|
59333
|
+
});
|
|
60092
59334
|
await rm(targetPath, { force: false, recursive: true });
|
|
60093
59335
|
return {
|
|
60094
59336
|
deleted: true,
|
|
@@ -60096,9 +59338,7 @@ var WorkspaceStore = class {
|
|
|
60096
59338
|
};
|
|
60097
59339
|
}
|
|
60098
59340
|
async deleteConversation(projectId, conversationId) {
|
|
60099
|
-
await this.moveToTrash(
|
|
60100
|
-
this.getConversationFilePath(projectId, conversationId)
|
|
60101
|
-
);
|
|
59341
|
+
await this.moveToTrash(this.getConversationFilePath(projectId, conversationId));
|
|
60102
59342
|
}
|
|
60103
59343
|
async deleteProject(projectId) {
|
|
60104
59344
|
await this.moveToTrash(this.getProjectDirectory(projectId));
|
|
@@ -60112,17 +59352,17 @@ var WorkspaceStore = class {
|
|
|
60112
59352
|
getConversationsDirectory(projectId) {
|
|
60113
59353
|
return path13.join(this.getProjectDirectory(projectId), "conversations");
|
|
60114
59354
|
}
|
|
59355
|
+
getCheckpointsDirectory(projectId) {
|
|
59356
|
+
return path13.join(this.getProjectDirectory(projectId), "checkpoints");
|
|
59357
|
+
}
|
|
59358
|
+
getCheckpointDirectory(projectId, checkpointId) {
|
|
59359
|
+
return path13.join(this.getCheckpointsDirectory(projectId), checkpointId);
|
|
59360
|
+
}
|
|
60115
59361
|
getProjectOutputFilePath(projectId, outputType) {
|
|
60116
|
-
return path13.join(
|
|
60117
|
-
this.getProjectWorkspaceDirectory(projectId),
|
|
60118
|
-
`index.${outputType}`
|
|
60119
|
-
);
|
|
59362
|
+
return path13.join(this.getProjectWorkspaceDirectory(projectId), `index.${outputType}`);
|
|
60120
59363
|
}
|
|
60121
59364
|
getConversationFilePath(projectId, conversationId) {
|
|
60122
|
-
return path13.join(
|
|
60123
|
-
this.getConversationsDirectory(projectId),
|
|
60124
|
-
`${conversationId}.json`
|
|
60125
|
-
);
|
|
59365
|
+
return path13.join(this.getConversationsDirectory(projectId), `${conversationId}.json`);
|
|
60126
59366
|
}
|
|
60127
59367
|
async walkProjectWorkspace(projectId, relativePath, visit2) {
|
|
60128
59368
|
const rootPath = this.getProjectWorkspaceDirectory(projectId);
|
|
@@ -60224,25 +59464,20 @@ var WorkspaceStore = class {
|
|
|
60224
59464
|
if (state.has(relativePath)) {
|
|
60225
59465
|
return state.get(relativePath);
|
|
60226
59466
|
}
|
|
60227
|
-
const absolutePath = await this.resolveProjectWorkspacePath(
|
|
60228
|
-
|
|
60229
|
-
|
|
60230
|
-
|
|
60231
|
-
);
|
|
59467
|
+
const absolutePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59468
|
+
checkTargetSymlink: true,
|
|
59469
|
+
targetMayBeMissing: true
|
|
59470
|
+
});
|
|
60232
59471
|
const content = await readTextFileIfExists(absolutePath);
|
|
60233
59472
|
state.set(relativePath, content);
|
|
60234
59473
|
return content;
|
|
60235
59474
|
};
|
|
60236
59475
|
for (const change of changes) {
|
|
60237
59476
|
const relativePath = normalizeWorkspaceRelativePath(change.path);
|
|
60238
|
-
const absolutePath = await this.resolveProjectWorkspacePath(
|
|
60239
|
-
|
|
60240
|
-
|
|
60241
|
-
|
|
60242
|
-
checkTargetSymlink: true,
|
|
60243
|
-
targetMayBeMissing: change.operation !== "delete"
|
|
60244
|
-
}
|
|
60245
|
-
);
|
|
59477
|
+
const absolutePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59478
|
+
checkTargetSymlink: true,
|
|
59479
|
+
targetMayBeMissing: change.operation !== "delete"
|
|
59480
|
+
});
|
|
60246
59481
|
if (change.operation === "delete") {
|
|
60247
59482
|
const targetStats = await lstat(absolutePath);
|
|
60248
59483
|
const previousContent2 = targetStats.isFile() ? await readCurrentContent(relativePath) : void 0;
|
|
@@ -60313,11 +59548,7 @@ var WorkspaceStore = class {
|
|
|
60313
59548
|
if (!relativeFromWorkspace || relativeFromWorkspace.startsWith("..") || path13.isAbsolute(relativeFromWorkspace)) {
|
|
60314
59549
|
throw new Error(`Project Workspace path escapes workspace: ${relativePath}`);
|
|
60315
59550
|
}
|
|
60316
|
-
await this.assertNoWorkspaceSymlinkPath(
|
|
60317
|
-
workspaceDirectory,
|
|
60318
|
-
relativeFromWorkspace,
|
|
60319
|
-
options
|
|
60320
|
-
);
|
|
59551
|
+
await this.assertNoWorkspaceSymlinkPath(workspaceDirectory, relativeFromWorkspace, options);
|
|
60321
59552
|
return targetPath;
|
|
60322
59553
|
}
|
|
60323
59554
|
async assertNoWorkspaceSymlinkPath(workspaceDirectory, relativeFromWorkspace, options) {
|
|
@@ -60341,6 +59572,17 @@ var WorkspaceStore = class {
|
|
|
60341
59572
|
}
|
|
60342
59573
|
}
|
|
60343
59574
|
};
|
|
59575
|
+
function normalizeProjectRecord(project) {
|
|
59576
|
+
return {
|
|
59577
|
+
...project,
|
|
59578
|
+
projectType: project.projectType ?? "single_html"
|
|
59579
|
+
};
|
|
59580
|
+
}
|
|
59581
|
+
function assertSafeCheckpointId(checkpointId) {
|
|
59582
|
+
if (!/^[A-Za-z0-9_-]+$/.test(checkpointId)) {
|
|
59583
|
+
throw new Error(`Invalid checkpoint id: ${checkpointId}`);
|
|
59584
|
+
}
|
|
59585
|
+
}
|
|
60344
59586
|
|
|
60345
59587
|
// src/services.ts
|
|
60346
59588
|
function createWorkspaceStore(options = {}) {
|
|
@@ -60371,9 +59613,7 @@ function createOwnDesignServices(options = {}) {
|
|
|
60371
59613
|
function sanitizePublicConversation(conversation) {
|
|
60372
59614
|
return {
|
|
60373
59615
|
...conversation,
|
|
60374
|
-
messages: Array.isArray(conversation.messages) ? conversation.messages.map(
|
|
60375
|
-
(message) => sanitizePublicUIMessage(message)
|
|
60376
|
-
) : conversation.messages
|
|
59616
|
+
messages: Array.isArray(conversation.messages) ? conversation.messages.map((message) => sanitizePublicUIMessage(message)) : conversation.messages
|
|
60377
59617
|
};
|
|
60378
59618
|
}
|
|
60379
59619
|
function sanitizePublicUIMessage(message) {
|
|
@@ -60592,10 +59832,14 @@ var ChatRunManager = class {
|
|
|
60592
59832
|
} else {
|
|
60593
59833
|
run.status = "failed";
|
|
60594
59834
|
this.flushPendingLiveChunks(run);
|
|
60595
|
-
this.publish(
|
|
60596
|
-
|
|
60597
|
-
|
|
60598
|
-
|
|
59835
|
+
this.publish(
|
|
59836
|
+
run,
|
|
59837
|
+
{
|
|
59838
|
+
errorText: error51 instanceof Error ? error51.message : "\u751F\u6210\u5931\u8D25\uFF1AUnknown error",
|
|
59839
|
+
type: "error"
|
|
59840
|
+
},
|
|
59841
|
+
{ immediate: true }
|
|
59842
|
+
);
|
|
60599
59843
|
}
|
|
60600
59844
|
} finally {
|
|
60601
59845
|
run.completedAt = run.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -60615,10 +59859,7 @@ var ChatRunManager = class {
|
|
|
60615
59859
|
message: getLastAssistantMessage(run.initialMessages),
|
|
60616
59860
|
stream: stream2
|
|
60617
59861
|
})) {
|
|
60618
|
-
run.latestMessages = mergeResponseMessage(
|
|
60619
|
-
run.initialMessages,
|
|
60620
|
-
responseMessage
|
|
60621
|
-
);
|
|
59862
|
+
run.latestMessages = mergeResponseMessage(run.initialMessages, responseMessage);
|
|
60622
59863
|
if (isRunAtResumableBoundary(run)) {
|
|
60623
59864
|
run.safeMessages = run.latestMessages;
|
|
60624
59865
|
run.safeSnapshotChunkIndex = run.safeResumeChunkIndex;
|
|
@@ -60812,25 +60053,19 @@ function createOwnDesignApp(options = {}) {
|
|
|
60812
60053
|
activeConversationId: activeConversation?.id,
|
|
60813
60054
|
activeProject,
|
|
60814
60055
|
activeRun: activeProject ? chatRunManager.getActiveRun(activeProject.id) : void 0,
|
|
60815
|
-
conversations: conversationState.conversations.map(
|
|
60816
|
-
sanitizePublicConversation
|
|
60817
|
-
),
|
|
60056
|
+
conversations: conversationState.conversations.map(sanitizePublicConversation),
|
|
60818
60057
|
projects: projectState.projects,
|
|
60819
60058
|
settings
|
|
60820
60059
|
});
|
|
60821
60060
|
});
|
|
60822
60061
|
app2.get("/api/settings", async (context2) => {
|
|
60823
|
-
return context2.json(
|
|
60824
|
-
await createOwnDesignServices(options).settingsService.getPublicSettings()
|
|
60825
|
-
);
|
|
60062
|
+
return context2.json(await createOwnDesignServices(options).settingsService.getPublicSettings());
|
|
60826
60063
|
});
|
|
60827
60064
|
app2.put("/api/settings", async (context2) => {
|
|
60828
60065
|
try {
|
|
60829
60066
|
const body = await context2.req.json();
|
|
60830
60067
|
return context2.json(
|
|
60831
|
-
await createOwnDesignServices(options).settingsService.updatePublicSettings(
|
|
60832
|
-
body
|
|
60833
|
-
)
|
|
60068
|
+
await createOwnDesignServices(options).settingsService.updatePublicSettings(body)
|
|
60834
60069
|
);
|
|
60835
60070
|
} catch (error51) {
|
|
60836
60071
|
return context2.text(
|
|
@@ -60872,17 +60107,20 @@ function createOwnDesignApp(options = {}) {
|
|
|
60872
60107
|
app2.post("/api/projects", async (context2) => {
|
|
60873
60108
|
const body = await context2.req.json();
|
|
60874
60109
|
const trimmedName = asNonEmptyString(body.name);
|
|
60875
|
-
|
|
60110
|
+
const projectType = parseProjectType(body.projectType);
|
|
60111
|
+
if (!trimmedName || !projectType) {
|
|
60876
60112
|
return context2.json({}, 400);
|
|
60877
60113
|
}
|
|
60114
|
+
if (projectType === "react") {
|
|
60115
|
+
return context2.text("React project type is reserved but not supported yet.", 400);
|
|
60116
|
+
}
|
|
60878
60117
|
const services = createOwnDesignServices(options);
|
|
60879
60118
|
const settings = await services.settingsService.getSettings();
|
|
60880
60119
|
const result = await services.projectService.createProject({
|
|
60881
|
-
defaultConversationTitle: getDefaultConversationTitle(
|
|
60882
|
-
settings.interfaceLanguage
|
|
60883
|
-
),
|
|
60120
|
+
defaultConversationTitle: getDefaultConversationTitle(settings.interfaceLanguage),
|
|
60884
60121
|
name: trimmedName,
|
|
60885
|
-
description: asNonEmptyString(body.description)
|
|
60122
|
+
description: asNonEmptyString(body.description),
|
|
60123
|
+
projectType
|
|
60886
60124
|
});
|
|
60887
60125
|
return context2.json({
|
|
60888
60126
|
href: buildWorkspaceHref({
|
|
@@ -60909,9 +60147,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
60909
60147
|
await createProjectService(options).deleteProject(projectId);
|
|
60910
60148
|
const projectState = await createProjectService(options).getProjectState();
|
|
60911
60149
|
const fallbackProject = projectState.projects[0];
|
|
60912
|
-
const fallbackConversation = fallbackProject ? (await createConversationService(options).getConversationState(
|
|
60913
|
-
fallbackProject.id
|
|
60914
|
-
)).conversations[0] : void 0;
|
|
60150
|
+
const fallbackConversation = fallbackProject ? (await createConversationService(options).getConversationState(fallbackProject.id)).conversations[0] : void 0;
|
|
60915
60151
|
return context2.json({
|
|
60916
60152
|
href: buildWorkspaceHref({
|
|
60917
60153
|
conversationId: fallbackConversation?.id,
|
|
@@ -60934,76 +60170,58 @@ function createOwnDesignApp(options = {}) {
|
|
|
60934
60170
|
})
|
|
60935
60171
|
});
|
|
60936
60172
|
});
|
|
60937
|
-
app2.post(
|
|
60938
|
-
"
|
|
60939
|
-
|
|
60940
|
-
|
|
60941
|
-
|
|
60942
|
-
|
|
60943
|
-
projectId,
|
|
60944
|
-
conversationId
|
|
60945
|
-
);
|
|
60946
|
-
return context2.json({
|
|
60947
|
-
href: buildWorkspaceHref({
|
|
60948
|
-
conversationId,
|
|
60949
|
-
projectId
|
|
60950
|
-
})
|
|
60951
|
-
});
|
|
60952
|
-
}
|
|
60953
|
-
);
|
|
60954
|
-
app2.patch(
|
|
60955
|
-
"/api/projects/:projectId/conversations/:conversationId",
|
|
60956
|
-
async (context2) => {
|
|
60957
|
-
const projectId = context2.req.param("projectId");
|
|
60958
|
-
const conversationId = context2.req.param("conversationId");
|
|
60959
|
-
const body = await context2.req.json();
|
|
60960
|
-
const trimmedTitle = asNonEmptyString(body.title);
|
|
60961
|
-
if (!trimmedTitle) {
|
|
60962
|
-
return context2.json({}, 400);
|
|
60963
|
-
}
|
|
60964
|
-
await createConversationService(options).renameConversation(
|
|
60965
|
-
projectId,
|
|
60966
|
-
conversationId,
|
|
60967
|
-
{ title: trimmedTitle }
|
|
60968
|
-
);
|
|
60969
|
-
return context2.json({});
|
|
60970
|
-
}
|
|
60971
|
-
);
|
|
60972
|
-
app2.delete(
|
|
60973
|
-
"/api/projects/:projectId/conversations/:conversationId",
|
|
60974
|
-
async (context2) => {
|
|
60975
|
-
const projectId = context2.req.param("projectId");
|
|
60976
|
-
const conversationId = context2.req.param("conversationId");
|
|
60977
|
-
const currentConversationId = context2.req.query("currentConversationId");
|
|
60978
|
-
const services = createOwnDesignServices(options);
|
|
60979
|
-
const settings = await services.settingsService.getSettings();
|
|
60980
|
-
const remainingConversations = await services.conversationService.deleteConversation(
|
|
60981
|
-
projectId,
|
|
60173
|
+
app2.post("/api/projects/:projectId/conversations/:conversationId/select", async (context2) => {
|
|
60174
|
+
const projectId = context2.req.param("projectId");
|
|
60175
|
+
const conversationId = context2.req.param("conversationId");
|
|
60176
|
+
await createConversationService(options).switchConversation(projectId, conversationId);
|
|
60177
|
+
return context2.json({
|
|
60178
|
+
href: buildWorkspaceHref({
|
|
60982
60179
|
conversationId,
|
|
60983
|
-
|
|
60984
|
-
)
|
|
60985
|
-
|
|
60986
|
-
|
|
60987
|
-
|
|
60988
|
-
|
|
60989
|
-
|
|
60990
|
-
|
|
60991
|
-
|
|
60180
|
+
projectId
|
|
60181
|
+
})
|
|
60182
|
+
});
|
|
60183
|
+
});
|
|
60184
|
+
app2.patch("/api/projects/:projectId/conversations/:conversationId", async (context2) => {
|
|
60185
|
+
const projectId = context2.req.param("projectId");
|
|
60186
|
+
const conversationId = context2.req.param("conversationId");
|
|
60187
|
+
const body = await context2.req.json();
|
|
60188
|
+
const trimmedTitle = asNonEmptyString(body.title);
|
|
60189
|
+
if (!trimmedTitle) {
|
|
60190
|
+
return context2.json({}, 400);
|
|
60992
60191
|
}
|
|
60993
|
-
|
|
60192
|
+
await createConversationService(options).renameConversation(projectId, conversationId, {
|
|
60193
|
+
title: trimmedTitle
|
|
60194
|
+
});
|
|
60195
|
+
return context2.json({});
|
|
60196
|
+
});
|
|
60197
|
+
app2.delete("/api/projects/:projectId/conversations/:conversationId", async (context2) => {
|
|
60198
|
+
const projectId = context2.req.param("projectId");
|
|
60199
|
+
const conversationId = context2.req.param("conversationId");
|
|
60200
|
+
const currentConversationId = context2.req.query("currentConversationId");
|
|
60201
|
+
const services = createOwnDesignServices(options);
|
|
60202
|
+
const settings = await services.settingsService.getSettings();
|
|
60203
|
+
const remainingConversations = await services.conversationService.deleteConversation(
|
|
60204
|
+
projectId,
|
|
60205
|
+
conversationId,
|
|
60206
|
+
getDefaultConversationTitle(settings.interfaceLanguage)
|
|
60207
|
+
);
|
|
60208
|
+
const nextConversationId = currentConversationId === conversationId ? remainingConversations[0]?.id : currentConversationId;
|
|
60209
|
+
return context2.json({
|
|
60210
|
+
href: buildWorkspaceHref({
|
|
60211
|
+
conversationId: nextConversationId,
|
|
60212
|
+
projectId
|
|
60213
|
+
})
|
|
60214
|
+
});
|
|
60215
|
+
});
|
|
60994
60216
|
app2.post("/api/chat", async (context2) => {
|
|
60995
60217
|
const body = await context2.req.json();
|
|
60996
60218
|
const projectId = asNonEmptyString(body.projectId);
|
|
60997
60219
|
const conversationId = asNonEmptyString(body.conversationId);
|
|
60998
60220
|
const requestedPreviewPath = asNonEmptyString(body.previewPath);
|
|
60999
|
-
const pageEditMode = parsePageEditMode(body.pageEditMode);
|
|
61000
60221
|
const currentUserMessage = createCurrentUserMessage(body.message);
|
|
61001
60222
|
if (!projectId || !conversationId || !currentUserMessage) {
|
|
61002
60223
|
return context2.text("Invalid chat request.", 400);
|
|
61003
60224
|
}
|
|
61004
|
-
if (!pageEditMode) {
|
|
61005
|
-
return context2.text("Invalid page edit mode.", 400);
|
|
61006
|
-
}
|
|
61007
60225
|
const workspaceStore = createWorkspaceStore(options);
|
|
61008
60226
|
const project = await workspaceStore.getProject(projectId);
|
|
61009
60227
|
const previewPath = await resolveExistingPreviewPath(
|
|
@@ -61014,29 +60232,29 @@ function createOwnDesignApp(options = {}) {
|
|
|
61014
60232
|
if (chatRunManager.getActiveRun(projectId)) {
|
|
61015
60233
|
return context2.text("\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4EFB\u52A1\u6B63\u5728\u6267\u884C\u3002", 409);
|
|
61016
60234
|
}
|
|
61017
|
-
|
|
60235
|
+
await workspaceStore.createCheckpoint({
|
|
60236
|
+
id: createCheckpointId(),
|
|
60237
|
+
conversationId,
|
|
60238
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61018
60239
|
projectId,
|
|
61019
|
-
|
|
61020
|
-
|
|
60240
|
+
userMessageId: currentUserMessage.id,
|
|
60241
|
+
userPrompt: getUIMessageText(currentUserMessage)
|
|
60242
|
+
});
|
|
60243
|
+
let conversation = await workspaceStore.getConversation(projectId, conversationId);
|
|
61021
60244
|
const storedMessages = normalizeConversationMessages(
|
|
61022
60245
|
conversation.messages
|
|
61023
60246
|
);
|
|
61024
|
-
let messages = [
|
|
61025
|
-
...storedMessages,
|
|
61026
|
-
currentUserMessage
|
|
61027
|
-
];
|
|
60247
|
+
let messages = [...storedMessages, currentUserMessage];
|
|
61028
60248
|
let agentContext;
|
|
61029
60249
|
try {
|
|
61030
60250
|
agentContext = await createDesignPageAgentContext({
|
|
61031
60251
|
currentPreviewPath: previewPath,
|
|
61032
60252
|
frontendTabId: asNonEmptyString(body.frontendTabId),
|
|
61033
60253
|
modelConfigurationId: asNonEmptyString(body.modelConfigurationId),
|
|
61034
|
-
|
|
61035
|
-
pageEditMode,
|
|
60254
|
+
projectType: project.projectType ?? "single_html",
|
|
61036
60255
|
projectId,
|
|
61037
|
-
providerOptionsSelection: parseProviderOptionsSelection(
|
|
61038
|
-
|
|
61039
|
-
),
|
|
60256
|
+
providerOptionsSelection: parseProviderOptionsSelection(body.providerOptionsSelection),
|
|
60257
|
+
settingsPath: options.settingsPath,
|
|
61040
60258
|
workspaceStore
|
|
61041
60259
|
});
|
|
61042
60260
|
} catch (error51) {
|
|
@@ -61046,33 +60264,13 @@ function createOwnDesignApp(options = {}) {
|
|
|
61046
60264
|
);
|
|
61047
60265
|
}
|
|
61048
60266
|
if (!conversation.agentInstructions) {
|
|
61049
|
-
conversation = await workspaceStore.updateConversation(
|
|
61050
|
-
|
|
61051
|
-
|
|
61052
|
-
|
|
61053
|
-
...conversation,
|
|
61054
|
-
agentInstructions: buildDesignPageConversationInstructions(
|
|
61055
|
-
agentContext.resources
|
|
61056
|
-
),
|
|
61057
|
-
agentPromptVersion: DESIGN_PAGE_AGENT_PROMPT_VERSION
|
|
61058
|
-
}
|
|
61059
|
-
);
|
|
61060
|
-
}
|
|
61061
|
-
agentContext.agentInstructions = conversation.agentInstructions;
|
|
61062
|
-
try {
|
|
61063
|
-
messages = await rewriteLastUserMessageForDesignAgent({
|
|
61064
|
-
messages,
|
|
61065
|
-
pageEditMode,
|
|
61066
|
-
pageEditModePolicy: agentContext.pageEditModePolicy ?? { mode: "auto" },
|
|
61067
|
-
previewPath,
|
|
61068
|
-
agentContext
|
|
60267
|
+
conversation = await workspaceStore.updateConversation(projectId, conversationId, {
|
|
60268
|
+
...conversation,
|
|
60269
|
+
agentInstructions: buildDesignPageConversationInstructions(agentContext.resources),
|
|
60270
|
+
agentPromptVersion: DESIGN_PAGE_AGENT_PROMPT_VERSION
|
|
61069
60271
|
});
|
|
61070
|
-
} catch (error51) {
|
|
61071
|
-
return context2.text(
|
|
61072
|
-
error51 instanceof Error ? error51.message : "Failed to rewrite user prompt.",
|
|
61073
|
-
500
|
|
61074
|
-
);
|
|
61075
60272
|
}
|
|
60273
|
+
agentContext.agentInstructions = conversation.agentInstructions;
|
|
61076
60274
|
const agent = createDesignPageAgent(agentContext);
|
|
61077
60275
|
let latestStepUsage;
|
|
61078
60276
|
const run = chatRunManager.startRun({
|
|
@@ -61124,6 +60322,49 @@ function createOwnDesignApp(options = {}) {
|
|
|
61124
60322
|
}
|
|
61125
60323
|
return createChatRunStreamResponse(run.stream);
|
|
61126
60324
|
});
|
|
60325
|
+
app2.get("/api/projects/:projectId/checkpoints", async (context2) => {
|
|
60326
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60327
|
+
const projectId = context2.req.param("projectId");
|
|
60328
|
+
await workspaceStore.getProject(projectId);
|
|
60329
|
+
return context2.json(await workspaceStore.listCheckpoints(projectId));
|
|
60330
|
+
});
|
|
60331
|
+
app2.post("/api/projects/:projectId/checkpoints/:checkpointId/restore", async (context2) => {
|
|
60332
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60333
|
+
const projectId = context2.req.param("projectId");
|
|
60334
|
+
const checkpointId = context2.req.param("checkpointId");
|
|
60335
|
+
const body = await readJson(context2.req.raw);
|
|
60336
|
+
const mode = parseCheckpointRestoreMode(body?.mode);
|
|
60337
|
+
if (!mode) {
|
|
60338
|
+
return context2.text("Invalid checkpoint restore request.", 400);
|
|
60339
|
+
}
|
|
60340
|
+
if (chatRunManager.getActiveRun(projectId)) {
|
|
60341
|
+
return context2.text("\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4EFB\u52A1\u6B63\u5728\u6267\u884C\u3002", 409);
|
|
60342
|
+
}
|
|
60343
|
+
try {
|
|
60344
|
+
const checkpoint = mode === "conversation" ? await workspaceStore.readCheckpoint(projectId, checkpointId) : await workspaceStore.restoreCheckpointFiles(projectId, checkpointId);
|
|
60345
|
+
if (mode === "conversation" || mode === "both") {
|
|
60346
|
+
await restoreCheckpointConversation({
|
|
60347
|
+
options,
|
|
60348
|
+
workspaceStore,
|
|
60349
|
+
checkpoint
|
|
60350
|
+
});
|
|
60351
|
+
}
|
|
60352
|
+
return context2.json({
|
|
60353
|
+
href: buildWorkspaceHref({
|
|
60354
|
+
conversationId: checkpoint.conversationId,
|
|
60355
|
+
projectId
|
|
60356
|
+
})
|
|
60357
|
+
});
|
|
60358
|
+
} catch (error51) {
|
|
60359
|
+
if (isMissingPathError4(error51)) {
|
|
60360
|
+
return context2.text("Checkpoint not found.", 404);
|
|
60361
|
+
}
|
|
60362
|
+
return context2.text(
|
|
60363
|
+
error51 instanceof Error ? error51.message : "Checkpoint restore failed.",
|
|
60364
|
+
400
|
|
60365
|
+
);
|
|
60366
|
+
}
|
|
60367
|
+
});
|
|
61127
60368
|
app2.get("/api/projects/:projectId/runs/active", async (context2) => {
|
|
61128
60369
|
const activeRun = chatRunManager.getActiveRun(context2.req.param("projectId"));
|
|
61129
60370
|
if (!activeRun) {
|
|
@@ -61132,9 +60373,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
61132
60373
|
return context2.json(activeRun);
|
|
61133
60374
|
});
|
|
61134
60375
|
app2.delete("/api/projects/:projectId/runs/active", async (context2) => {
|
|
61135
|
-
const activeRun = chatRunManager.cancelActiveRun(
|
|
61136
|
-
context2.req.param("projectId")
|
|
61137
|
-
);
|
|
60376
|
+
const activeRun = chatRunManager.cancelActiveRun(context2.req.param("projectId"));
|
|
61138
60377
|
if (!activeRun) {
|
|
61139
60378
|
return new Response(null, { status: 204 });
|
|
61140
60379
|
}
|
|
@@ -61143,10 +60382,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
61143
60382
|
app2.get(
|
|
61144
60383
|
"/api/projects/:projectId/conversations/:conversationId/runs/active/stream",
|
|
61145
60384
|
async (context2) => {
|
|
61146
|
-
const afterChunkIndex = Number.parseInt(
|
|
61147
|
-
context2.req.query("after") ?? "0",
|
|
61148
|
-
10
|
|
61149
|
-
);
|
|
60385
|
+
const afterChunkIndex = Number.parseInt(context2.req.query("after") ?? "0", 10);
|
|
61150
60386
|
const stream2 = chatRunManager.subscribeActiveRun(
|
|
61151
60387
|
context2.req.param("projectId"),
|
|
61152
60388
|
context2.req.param("conversationId"),
|
|
@@ -61197,57 +60433,51 @@ function createOwnDesignApp(options = {}) {
|
|
|
61197
60433
|
await manager.release(context2.req.param("projectId"), clientId);
|
|
61198
60434
|
return new Response(null, { status: 204 });
|
|
61199
60435
|
});
|
|
61200
|
-
app2.post(
|
|
61201
|
-
|
|
61202
|
-
|
|
61203
|
-
|
|
61204
|
-
|
|
61205
|
-
if (!clientId) {
|
|
61206
|
-
return context2.text("Invalid preview heartbeat request.", 400);
|
|
61207
|
-
}
|
|
61208
|
-
const workspaceStore = createWorkspaceStore(options);
|
|
61209
|
-
const manager = getPreviewServerManager(workspaceStore);
|
|
61210
|
-
const session = await manager.heartbeat(
|
|
61211
|
-
context2.req.param("projectId"),
|
|
61212
|
-
clientId,
|
|
61213
|
-
asNonEmptyString(body?.previewPath)
|
|
61214
|
-
);
|
|
61215
|
-
return context2.json(session);
|
|
60436
|
+
app2.post("/api/projects/:projectId/preview-session/heartbeat", async (context2) => {
|
|
60437
|
+
const body = await readJson(context2.req.raw);
|
|
60438
|
+
const clientId = asNonEmptyString(body?.clientId);
|
|
60439
|
+
if (!clientId) {
|
|
60440
|
+
return context2.text("Invalid preview heartbeat request.", 400);
|
|
61216
60441
|
}
|
|
61217
|
-
|
|
61218
|
-
|
|
61219
|
-
|
|
61220
|
-
|
|
61221
|
-
|
|
61222
|
-
|
|
61223
|
-
|
|
61224
|
-
|
|
61225
|
-
|
|
61226
|
-
|
|
61227
|
-
|
|
61228
|
-
|
|
61229
|
-
|
|
61230
|
-
return
|
|
61231
|
-
|
|
61232
|
-
|
|
61233
|
-
|
|
61234
|
-
|
|
61235
|
-
|
|
61236
|
-
|
|
61237
|
-
|
|
61238
|
-
|
|
61239
|
-
|
|
61240
|
-
|
|
61241
|
-
|
|
61242
|
-
|
|
61243
|
-
|
|
60442
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60443
|
+
const manager = getPreviewServerManager(workspaceStore);
|
|
60444
|
+
const session = await manager.heartbeat(
|
|
60445
|
+
context2.req.param("projectId"),
|
|
60446
|
+
clientId,
|
|
60447
|
+
asNonEmptyString(body?.previewPath)
|
|
60448
|
+
);
|
|
60449
|
+
return context2.json(session);
|
|
60450
|
+
});
|
|
60451
|
+
app2.get("/api/projects/:projectId/frontend-capabilities/stream", async (context2) => {
|
|
60452
|
+
const projectId = context2.req.param("projectId");
|
|
60453
|
+
const tabId = context2.req.query("tabId")?.trim();
|
|
60454
|
+
if (!tabId) {
|
|
60455
|
+
return context2.text("Invalid frontend capability stream request.", 400);
|
|
60456
|
+
}
|
|
60457
|
+
await createWorkspaceStore(options).getProject(projectId);
|
|
60458
|
+
context2.header("Cache-Control", "no-cache, no-transform");
|
|
60459
|
+
context2.header("Connection", "keep-alive");
|
|
60460
|
+
context2.header("Content-Type", "text/event-stream; charset=utf-8");
|
|
60461
|
+
return stream(context2, async (streamApi) => {
|
|
60462
|
+
const commandStream = registerFrontendConnection({
|
|
60463
|
+
frontendTabId: tabId,
|
|
60464
|
+
projectId,
|
|
60465
|
+
signal: context2.req.raw.signal
|
|
60466
|
+
});
|
|
60467
|
+
const reader = commandStream.getReader();
|
|
60468
|
+
try {
|
|
60469
|
+
while (true) {
|
|
60470
|
+
const { done, value } = await reader.read();
|
|
60471
|
+
if (done) {
|
|
60472
|
+
break;
|
|
61244
60473
|
}
|
|
61245
|
-
|
|
61246
|
-
reader.releaseLock();
|
|
60474
|
+
await streamApi.write(value);
|
|
61247
60475
|
}
|
|
61248
|
-
}
|
|
61249
|
-
|
|
61250
|
-
|
|
60476
|
+
} finally {
|
|
60477
|
+
reader.releaseLock();
|
|
60478
|
+
}
|
|
60479
|
+
});
|
|
60480
|
+
});
|
|
61251
60481
|
app2.get("/api/projects/:projectId/download", async (context2) => {
|
|
61252
60482
|
const workspaceStore = createWorkspaceStore(options);
|
|
61253
60483
|
const projectId = context2.req.param("projectId");
|
|
@@ -61327,15 +60557,10 @@ async function downloadCurrentHtml(workspaceStore, projectId, previewPath) {
|
|
|
61327
60557
|
return new Response("Invalid download request.", { status: 400 });
|
|
61328
60558
|
}
|
|
61329
60559
|
try {
|
|
61330
|
-
const content = await workspaceStore.readProjectWorkspaceFileBuffer(
|
|
61331
|
-
projectId,
|
|
61332
|
-
previewPath
|
|
61333
|
-
);
|
|
60560
|
+
const content = await workspaceStore.readProjectWorkspaceFileBuffer(projectId, previewPath);
|
|
61334
60561
|
return new Response(content, {
|
|
61335
60562
|
headers: {
|
|
61336
|
-
"Content-Disposition": createAttachmentDisposition(
|
|
61337
|
-
path14.basename(previewPath)
|
|
61338
|
-
),
|
|
60563
|
+
"Content-Disposition": createAttachmentDisposition(path14.basename(previewPath)),
|
|
61339
60564
|
"Content-Type": "text/html; charset=utf-8"
|
|
61340
60565
|
},
|
|
61341
60566
|
status: 200
|
|
@@ -61348,15 +60573,10 @@ async function downloadWorkspaceZip(workspaceStore, projectId) {
|
|
|
61348
60573
|
let tempDirectory;
|
|
61349
60574
|
try {
|
|
61350
60575
|
const project = await workspaceStore.getProject(projectId);
|
|
61351
|
-
tempDirectory = await mkdtemp(
|
|
61352
|
-
path14.join(os6.tmpdir(), "owndesign-project-download-")
|
|
61353
|
-
);
|
|
60576
|
+
tempDirectory = await mkdtemp(path14.join(os6.tmpdir(), "owndesign-project-download-"));
|
|
61354
60577
|
const zipPath = path14.join(tempDirectory, "workspace.zip");
|
|
61355
60578
|
await writeWorkspaceZip(workspaceStore, projectId, zipPath);
|
|
61356
|
-
const [zipStats, zipBuffer] = await Promise.all([
|
|
61357
|
-
stat4(zipPath),
|
|
61358
|
-
readFile5(zipPath)
|
|
61359
|
-
]);
|
|
60579
|
+
const [zipStats, zipBuffer] = await Promise.all([stat4(zipPath), readFile5(zipPath)]);
|
|
61360
60580
|
await rm2(tempDirectory, { force: true, recursive: true });
|
|
61361
60581
|
tempDirectory = void 0;
|
|
61362
60582
|
return new Response(zipBuffer, {
|
|
@@ -61391,10 +60611,7 @@ async function writeWorkspaceZip(workspaceStore, projectId, zipPath) {
|
|
|
61391
60611
|
if (entry.type !== "file") {
|
|
61392
60612
|
continue;
|
|
61393
60613
|
}
|
|
61394
|
-
const content = await workspaceStore.readProjectWorkspaceFileBuffer(
|
|
61395
|
-
projectId,
|
|
61396
|
-
entry.path
|
|
61397
|
-
);
|
|
60614
|
+
const content = await workspaceStore.readProjectWorkspaceFileBuffer(projectId, entry.path);
|
|
61398
60615
|
zipFile.addBuffer(content, entry.path);
|
|
61399
60616
|
}
|
|
61400
60617
|
zipFile.end();
|
|
@@ -61448,16 +60665,13 @@ async function readJson(request) {
|
|
|
61448
60665
|
}
|
|
61449
60666
|
}
|
|
61450
60667
|
function createCurrentUserMessage(value) {
|
|
61451
|
-
if (!
|
|
60668
|
+
if (!isRecord3(value)) {
|
|
61452
60669
|
return void 0;
|
|
61453
60670
|
}
|
|
61454
60671
|
const id = asNonEmptyString(value.id);
|
|
61455
60672
|
const text2 = typeof value.text === "string" ? value.text : "";
|
|
61456
60673
|
const files = Array.isArray(value.files) ? value.files.filter(isFileUIPart2) : [];
|
|
61457
|
-
const parts = [
|
|
61458
|
-
...text2 ? [{ text: text2, type: "text" }] : [],
|
|
61459
|
-
...files
|
|
61460
|
-
];
|
|
60674
|
+
const parts = [...text2 ? [{ text: text2, type: "text" }] : [], ...files];
|
|
61461
60675
|
if (!id || parts.length === 0) {
|
|
61462
60676
|
return void 0;
|
|
61463
60677
|
}
|
|
@@ -61468,93 +60682,9 @@ function createCurrentUserMessage(value) {
|
|
|
61468
60682
|
};
|
|
61469
60683
|
}
|
|
61470
60684
|
function isFileUIPart2(value) {
|
|
61471
|
-
return
|
|
61472
|
-
}
|
|
61473
|
-
async function rewriteLastUserMessageForDesignAgent({
|
|
61474
|
-
agentContext,
|
|
61475
|
-
messages,
|
|
61476
|
-
pageEditMode,
|
|
61477
|
-
pageEditModePolicy,
|
|
61478
|
-
previewPath
|
|
61479
|
-
}) {
|
|
61480
|
-
const lastUserMessageIndex = findLastUserMessageIndex(messages);
|
|
61481
|
-
if (lastUserMessageIndex < 0) {
|
|
61482
|
-
return messages;
|
|
61483
|
-
}
|
|
61484
|
-
const lastUserMessage = messages[lastUserMessageIndex];
|
|
61485
|
-
if (!lastUserMessage || hasPromptRewriteMetadata(lastUserMessage)) {
|
|
61486
|
-
return messages;
|
|
61487
|
-
}
|
|
61488
|
-
const originalUserPrompt = getUIMessageText(lastUserMessage);
|
|
61489
|
-
const { rewrittenPrompt } = await rewriteTurnPrompt({
|
|
61490
|
-
model: agentContext.model,
|
|
61491
|
-
originalUserPrompt,
|
|
61492
|
-
pageEditMode,
|
|
61493
|
-
pageEditModePolicy,
|
|
61494
|
-
previewPath,
|
|
61495
|
-
providerOptions: agentContext.providerOptions
|
|
61496
|
-
});
|
|
61497
|
-
const metadata = createTurnPromptRewriteMetadata({
|
|
61498
|
-
originalUserPrompt,
|
|
61499
|
-
pageEditMode,
|
|
61500
|
-
pageEditModePolicy,
|
|
61501
|
-
previewPath
|
|
61502
|
-
});
|
|
61503
|
-
const rewrittenMessage = {
|
|
61504
|
-
...lastUserMessage,
|
|
61505
|
-
metadata: {
|
|
61506
|
-
...isRecord2(lastUserMessage.metadata) ? lastUserMessage.metadata : {},
|
|
61507
|
-
...metadata
|
|
61508
|
-
},
|
|
61509
|
-
parts: [
|
|
61510
|
-
{
|
|
61511
|
-
text: rewrittenPrompt,
|
|
61512
|
-
type: "text"
|
|
61513
|
-
},
|
|
61514
|
-
...lastUserMessage.parts.filter((part) => part.type !== "text")
|
|
61515
|
-
]
|
|
61516
|
-
};
|
|
61517
|
-
return [
|
|
61518
|
-
...messages.slice(0, lastUserMessageIndex),
|
|
61519
|
-
rewrittenMessage,
|
|
61520
|
-
...messages.slice(lastUserMessageIndex + 1)
|
|
61521
|
-
];
|
|
61522
|
-
}
|
|
61523
|
-
function findLastUserMessageIndex(messages) {
|
|
61524
|
-
for (let index = messages.length - 1; index >= 0; index -= 1) {
|
|
61525
|
-
const message = messages[index];
|
|
61526
|
-
if (message?.role === "user") {
|
|
61527
|
-
return index;
|
|
61528
|
-
}
|
|
61529
|
-
}
|
|
61530
|
-
return -1;
|
|
61531
|
-
}
|
|
61532
|
-
function createTurnPromptRewriteMetadata({
|
|
61533
|
-
originalUserPrompt,
|
|
61534
|
-
pageEditMode,
|
|
61535
|
-
pageEditModePolicy,
|
|
61536
|
-
previewPath
|
|
61537
|
-
}) {
|
|
61538
|
-
return {
|
|
61539
|
-
originalUserPrompt,
|
|
61540
|
-
promptRewrite: {
|
|
61541
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61542
|
-
kind: "turn-prompt-rewriter",
|
|
61543
|
-
pageEditMode,
|
|
61544
|
-
previewFileExists: Boolean(previewPath),
|
|
61545
|
-
...previewPath ? { previewPath } : {},
|
|
61546
|
-
...pageEditModePolicy.mode === "duplicate_edit" ? {
|
|
61547
|
-
duplicateSourcePath: pageEditModePolicy.sourcePath,
|
|
61548
|
-
duplicateTargetPath: pageEditModePolicy.targetPath
|
|
61549
|
-
} : {}
|
|
61550
|
-
}
|
|
61551
|
-
};
|
|
61552
|
-
}
|
|
61553
|
-
function hasPromptRewriteMetadata(message) {
|
|
61554
|
-
const metadata = message.metadata;
|
|
61555
|
-
return isRecord2(metadata) && isRecord2(metadata.promptRewrite) && metadata.promptRewrite.kind === "turn-prompt-rewriter";
|
|
60685
|
+
return isRecord3(value) && value.type === "file";
|
|
61556
60686
|
}
|
|
61557
|
-
function
|
|
60687
|
+
function isRecord3(value) {
|
|
61558
60688
|
return typeof value === "object" && value !== null;
|
|
61559
60689
|
}
|
|
61560
60690
|
async function resolveExistingPreviewPath(workspaceStore, projectId, previewPath) {
|
|
@@ -61567,8 +60697,20 @@ async function resolveExistingPreviewPath(workspaceStore, projectId, previewPath
|
|
|
61567
60697
|
function asNonEmptyString(value) {
|
|
61568
60698
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
61569
60699
|
}
|
|
60700
|
+
function parseProjectType(value) {
|
|
60701
|
+
if (value === void 0 || value === null || value === "") {
|
|
60702
|
+
return "single_html";
|
|
60703
|
+
}
|
|
60704
|
+
if (value === "single_html" || value === "react") {
|
|
60705
|
+
return value;
|
|
60706
|
+
}
|
|
60707
|
+
return void 0;
|
|
60708
|
+
}
|
|
60709
|
+
function parseCheckpointRestoreMode(value) {
|
|
60710
|
+
return value === "files" || value === "conversation" || value === "both" ? value : void 0;
|
|
60711
|
+
}
|
|
61570
60712
|
function parseProviderOptionsSelection(value) {
|
|
61571
|
-
if (!
|
|
60713
|
+
if (!isRecord3(value)) {
|
|
61572
60714
|
return void 0;
|
|
61573
60715
|
}
|
|
61574
60716
|
const deepseek2 = parseDeepSeekThinkingMode(value.deepseek);
|
|
@@ -61581,6 +60723,36 @@ function parseProviderOptionsSelection(value) {
|
|
|
61581
60723
|
...deepseek2 ? { deepseek: deepseek2 } : {}
|
|
61582
60724
|
};
|
|
61583
60725
|
}
|
|
60726
|
+
function createCheckpointId() {
|
|
60727
|
+
const id = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
60728
|
+
return `cp_${id.replace(/[^A-Za-z0-9_-]/g, "_")}`;
|
|
60729
|
+
}
|
|
60730
|
+
async function restoreCheckpointConversation({
|
|
60731
|
+
checkpoint,
|
|
60732
|
+
options,
|
|
60733
|
+
workspaceStore
|
|
60734
|
+
}) {
|
|
60735
|
+
const conversation = await workspaceStore.getConversation(
|
|
60736
|
+
checkpoint.projectId,
|
|
60737
|
+
checkpoint.conversationId
|
|
60738
|
+
);
|
|
60739
|
+
const messages = normalizeConversationMessages(conversation.messages);
|
|
60740
|
+
const targetIndex = messages.findIndex((message) => message.id === checkpoint.userMessageId);
|
|
60741
|
+
if (targetIndex < 0) {
|
|
60742
|
+
throw new Error("Checkpoint user message was not found in the conversation.");
|
|
60743
|
+
}
|
|
60744
|
+
const nextMessages = messages.slice(0, targetIndex);
|
|
60745
|
+
const settings = await createOwnDesignServices(options).settingsService.getSettings();
|
|
60746
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
60747
|
+
const lastMessage = nextMessages.at(-1);
|
|
60748
|
+
await workspaceStore.updateConversation(checkpoint.projectId, checkpoint.conversationId, {
|
|
60749
|
+
...conversation,
|
|
60750
|
+
lastMessageAt: lastMessage ? timestamp : void 0,
|
|
60751
|
+
messages: nextMessages,
|
|
60752
|
+
title: !conversation.titleManuallySet && nextMessages.length === 0 ? getDefaultConversationTitle(settings.interfaceLanguage) : conversation.title,
|
|
60753
|
+
updatedAt: timestamp
|
|
60754
|
+
});
|
|
60755
|
+
}
|
|
61584
60756
|
|
|
61585
60757
|
// src/index.ts
|
|
61586
60758
|
var DEFAULT_HOST = "127.0.0.1";
|