owndesign 0.1.4 → 0.1.8
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 -2
- package/dist/server/index.js +656 -1474
- package/dist/server/prompts/agents/component-audit.md +24 -0
- package/dist/server/prompts/agents/design-page.md +83 -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-jQS2hAnh.js → angular-html-DCGj6j9k.js} +1 -1
- package/dist/web/assets/{angular-ts-DXCIRK8J.js → angular-ts-_jS5FvKQ.js} +1 -1
- package/dist/web/assets/{apl-uLTVM0SV.js → apl-COUiMcRO.js} +1 -1
- package/dist/web/assets/{arc-C6K-4bbh.js → arc-DO65316F.js} +1 -1
- package/dist/web/assets/architecture-7EHR7CIX-D10X4FnP.js +1 -0
- package/dist/web/assets/{architectureDiagram-3BPJPVTR-Nra6nVfI.js → architectureDiagram-3BPJPVTR-4QTI95py.js} +1 -1
- package/dist/web/assets/{astro-QydxzDKL.js → astro-DBm7xN0H.js} +1 -1
- package/dist/web/assets/{blade-g81cs1jW.js → blade-BrcGRjeD.js} +1 -1
- package/dist/web/assets/{blockDiagram-GPEHLZMM-Ei76DVKM.js → blockDiagram-GPEHLZMM-DyW2gTLi.js} +1 -1
- package/dist/web/assets/{c-CV8Fejge.js → c-DAqlvgYb.js} +1 -1
- package/dist/web/assets/{c4Diagram-AAUBKEIU-oIOIFFc0.js → c4Diagram-AAUBKEIU-D7VLn3UY.js} +1 -1
- package/dist/web/assets/channel-D4A7yvhc.js +1 -0
- package/dist/web/assets/{chunk-2J33WTMH-BokYjerh.js → chunk-2J33WTMH-ZI7iZmam.js} +1 -1
- package/dist/web/assets/{chunk-4BX2VUAB-CW80cEPP.js → chunk-4BX2VUAB-BXZ1tYtp.js} +1 -1
- package/dist/web/assets/{chunk-55IACEB6-cqUqIGMR.js → chunk-55IACEB6-BruFuyzh.js} +1 -1
- package/dist/web/assets/{chunk-727SXJPM-en_nLLtx.js → chunk-727SXJPM-WfltwAyi.js} +1 -1
- package/dist/web/assets/{chunk-AQP2D5EJ-E7hL18Vm.js → chunk-AQP2D5EJ-m-6Oqccg.js} +1 -1
- package/dist/web/assets/{chunk-FMBD7UC4-D2Mn_3Ze.js → chunk-FMBD7UC4-CTpop8z0.js} +1 -1
- package/dist/web/assets/{chunk-ND2GUHAM-BxpfbjDb.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-CMtH7Q60.js → cobol-CV8XIe3g.js} +1 -1
- package/dist/web/assets/{coffee-Dd2oge0M.js → coffee-CjS-bqem.js} +1 -1
- package/dist/web/assets/{cose-bilkent-S5V4N54A-DlIl_zlL.js → cose-bilkent-S5V4N54A-qeF_aTDs.js} +1 -1
- package/dist/web/assets/{cpp-BxOkDHcj.js → cpp-BWTrby03.js} +1 -1
- package/dist/web/assets/{crystal-CP-EFrvi.js → crystal-B4jSurfu.js} +1 -1
- package/dist/web/assets/{css-56wYI_pE.js → css-CXDKo6HN.js} +1 -1
- package/dist/web/assets/{dagre-BM42HDAG-DPLYcjid.js → dagre-BM42HDAG-mtpIrAd-.js} +1 -1
- package/dist/web/assets/{diagram-2AECGRRQ-BCMoYOQK.js → diagram-2AECGRRQ-C2daXqRz.js} +1 -1
- package/dist/web/assets/{diagram-5GNKFQAL-CLKyT-zH.js → diagram-5GNKFQAL-Yn3Kkd1e.js} +1 -1
- package/dist/web/assets/{diagram-KO2AKTUF-aunZGxvu.js → diagram-KO2AKTUF-BSZBlF1_.js} +1 -1
- package/dist/web/assets/{diagram-LMA3HP47-BYp0cf90.js → diagram-LMA3HP47-C-o1wwy4.js} +1 -1
- package/dist/web/assets/{diagram-OG6HWLK6-M3iTfH5g.js → diagram-OG6HWLK6-BadUuiav.js} +1 -1
- package/dist/web/assets/{edge-DpKZbKMc.js → edge-IP3F2dQ8.js} +1 -1
- package/dist/web/assets/{elixir-CzSMdKdn.js → elixir-DNv4dzV2.js} +1 -1
- package/dist/web/assets/{elm-CPk9x22f.js → elm-DGlxwCzv.js} +1 -1
- package/dist/web/assets/{erDiagram-TEJ5UH35-BX0VkvGe.js → erDiagram-TEJ5UH35-uLYwqFWM.js} +1 -1
- package/dist/web/assets/{erb-TQAaZlNV.js → erb-Cx4MSh15.js} +1 -1
- package/dist/web/assets/eventmodeling-FCH6USID-CHKTnhfi.js +1 -0
- package/dist/web/assets/{flowDiagram-I6XJVG4X-Bvl7AO6M.js → flowDiagram-I6XJVG4X-C-JzpWfx.js} +1 -1
- package/dist/web/assets/{ganttDiagram-6RSMTGT7-Bcc6aiz3.js → ganttDiagram-6RSMTGT7-Be3WGPbk.js} +1 -1
- package/dist/web/assets/{git-rebase-C36akiNM.js → git-rebase-C_0JGP0g.js} +1 -1
- package/dist/web/assets/gitGraph-WXDBUCRP-aSGYLvSW.js +1 -0
- package/dist/web/assets/{gitGraphDiagram-PVQCEYII-DwIrICP0.js → gitGraphDiagram-PVQCEYII-DqJ0yj3L.js} +1 -1
- package/dist/web/assets/{glimmer-js-ZijKRLl6.js → glimmer-js-B7LRT5BS.js} +1 -1
- package/dist/web/assets/{glimmer-ts-DngRkkD1.js → glimmer-ts-CojGZlfZ.js} +1 -1
- package/dist/web/assets/{glsl-BaB0p3pF.js → glsl-CbmtoTb8.js} +1 -1
- package/dist/web/assets/{graphql-Betoeq1K.js → graphql-qYEIhTt7.js} +1 -1
- package/dist/web/assets/{hack-CE6PSHKG.js → hack-DxHXCCdq.js} +1 -1
- package/dist/web/assets/{haml-SuyMrzSD.js → haml-CiwrkJ8T.js} +1 -1
- package/dist/web/assets/{handlebars-JDrZp4fR.js → handlebars-Cn5UPYUQ.js} +1 -1
- package/dist/web/assets/{highlighted-body-OFNGDK62-CgC4ngzm.js → highlighted-body-OFNGDK62-ehiuxKzz.js} +1 -1
- package/dist/web/assets/{html-DC1Ltqmc.js → html-Cst8cPsk.js} +1 -1
- package/dist/web/assets/{html-derivative-iG8t5u5_.js → html-derivative-lnPAgvry.js} +1 -1
- package/dist/web/assets/{http-C40sH4NS.js → http-C5VDSUzW.js} +1 -1
- package/dist/web/assets/{hurl-CmUE8H3s.js → hurl-BFlMJrL0.js} +1 -1
- package/dist/web/assets/{index-Bz6PFGaR.js → index-Ai406YO8.js} +179 -179
- 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-D92ErDLp.js → infoDiagram-5YYISTIA-CIanyf0S.js} +1 -1
- package/dist/web/assets/{ishikawaDiagram-YF4QCWOH-COfhdNCZ.js → ishikawaDiagram-YF4QCWOH--1RL7uDF.js} +1 -1
- package/dist/web/assets/{java-Jk3c_AWT.js → java-BGahCCe1.js} +1 -1
- package/dist/web/assets/{javascript-D7j9lLtB.js → javascript-D5uMI8kB.js} +1 -1
- package/dist/web/assets/{jinja-KOP4LHnr.js → jinja-B4krr1-l.js} +1 -1
- package/dist/web/assets/{jison-CsByL99k.js → jison-BMMSlNZQ.js} +1 -1
- package/dist/web/assets/{journeyDiagram-JHISSGLW-BAaoSHcS.js → journeyDiagram-JHISSGLW-lkcDMGR5.js} +1 -1
- package/dist/web/assets/{json-bLUVjOwA.js → json-DXJMlo78.js} +1 -1
- package/dist/web/assets/{jsx-B-ZJ5sYl.js → jsx-C_bl3hBI.js} +1 -1
- package/dist/web/assets/{julia-DLZVVunR.js → julia-Sc_vYT5t.js} +1 -1
- package/dist/web/assets/{just-CTVFuTGe.js → just-CILkVz1n.js} +1 -1
- package/dist/web/assets/{kanban-definition-UN3LZRKU-txA385kR.js → kanban-definition-UN3LZRKU-Bi_hSUym.js} +1 -1
- package/dist/web/assets/{latex-BQMKb74T.js → latex-DUmFelG8.js} +1 -1
- package/dist/web/assets/{linear-D7ZS4umN.js → linear-Dpnh4Vbv.js} +1 -1
- package/dist/web/assets/{liquid-CG92kJNU.js → liquid-BnB6JKD1.js} +1 -1
- package/dist/web/assets/{lua-BVSZYGx9.js → lua-DhxAQE0G.js} +1 -1
- package/dist/web/assets/{marko-DEmKFKi0.js → marko-CyzzY1hm.js} +1 -1
- package/dist/web/assets/{mdc-Do8EO_lC.js → mdc-BptK7sXI.js} +1 -1
- package/dist/web/assets/mermaid-GHXKKRXX-DOJ_Dro4.js +1 -0
- package/dist/web/assets/{mermaid-parser.core-BaLOFMn_.js → mermaid-parser.core-DShH95hL.js} +2 -2
- package/dist/web/assets/{mindmap-definition-RKZ34NQL-D-yV4PLs.js → mindmap-definition-RKZ34NQL-LqYVQ-zW.js} +1 -1
- package/dist/web/assets/{nginx-BKSyUILj.js → nginx-CR9TIk16.js} +1 -1
- package/dist/web/assets/{nim-DnJRnIIP.js → nim-DzWiwbcf.js} +1 -1
- package/dist/web/assets/packet-YPE3B663-DuGIOCMW.js +1 -0
- package/dist/web/assets/{perl-3bt2qR9m.js → perl-CgrDNBt5.js} +1 -1
- package/dist/web/assets/{php-BzdDALOQ.js → php-DtuJQDgr.js} +1 -1
- package/dist/web/assets/pie-LRSECV5Y-BYeTdyfo.js +1 -0
- package/dist/web/assets/{pieDiagram-4H26LBE5-Bd114I4X.js → pieDiagram-4H26LBE5-B7_i9XPe.js} +1 -1
- package/dist/web/assets/{pug-DdwUkMw4.js → pug--9BJCC2D.js} +1 -1
- package/dist/web/assets/{qml-DP4is7YC.js → qml-C3iH27Ik.js} +1 -1
- package/dist/web/assets/{quadrantDiagram-W4KKPZXB-bREh_EBC.js → quadrantDiagram-W4KKPZXB-C2tSamWU.js} +1 -1
- package/dist/web/assets/{r-BF_jXTwW.js → r-CqKTpWRo.js} +1 -1
- package/dist/web/assets/radar-GUYGQ44K-Cqw7n4df.js +1 -0
- package/dist/web/assets/{razor-3soncf9G.js → razor-BNavdAx6.js} +1 -1
- package/dist/web/assets/{regexp-EYBuLXF9.js → regexp-zwVenqvj.js} +1 -1
- package/dist/web/assets/{requirementDiagram-4Y6WPE33-VtNiXWaP.js → requirementDiagram-4Y6WPE33-iIbtgBoU.js} +1 -1
- package/dist/web/assets/{rst-C71o5usK.js → rst-BHNeA4na.js} +1 -1
- package/dist/web/assets/{ruby-w0pHTyII.js → ruby-CkHs-w2j.js} +1 -1
- package/dist/web/assets/{sankeyDiagram-5OEKKPKP-CPbj-Xb-.js → sankeyDiagram-5OEKKPKP-B05ECsV0.js} +1 -1
- package/dist/web/assets/{sas-DXIh1KZ4.js → sas-COQs-ItK.js} +1 -1
- package/dist/web/assets/{scss-C4aItG-0.js → scss-DVsO7q0E.js} +1 -1
- package/dist/web/assets/{sequenceDiagram-3UESZ5HK-DwH_u_zz.js → sequenceDiagram-3UESZ5HK-CHtmtTcK.js} +1 -1
- package/dist/web/assets/{shellscript-BV5fN4m0.js → shellscript-DoNwQ9Oz.js} +1 -1
- package/dist/web/assets/{shellsession-COL1kA2z.js → shellsession-DvIRWuae.js} +1 -1
- package/dist/web/assets/{soy-Ccpzfdcl.js → soy--AEUdRNF.js} +1 -1
- package/dist/web/assets/{sql-DCE87e5l.js → sql-BVv9DbTm.js} +1 -1
- package/dist/web/assets/{stata-CEWTedB6.js → stata-Bzv07ePm.js} +1 -1
- package/dist/web/assets/{stateDiagram-AJRCARHV-B3VdYVO-.js → stateDiagram-AJRCARHV-COllcCkO.js} +1 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-D9SuEs4r.js +1 -0
- package/dist/web/assets/{surrealql-CUKNwDpQ.js → surrealql-ChG0u1_y.js} +1 -1
- package/dist/web/assets/{svelte-DONiSH1x.js → svelte-CTk-krYk.js} +1 -1
- package/dist/web/assets/{templ-B_johG2O.js → templ-CIOvt0Gn.js} +1 -1
- package/dist/web/assets/{tex-Dh316BCp.js → tex-BLbgub0O.js} +1 -1
- package/dist/web/assets/{timeline-definition-PNZ67QCA-Blixs7cX.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-CWDOkWop.js → ts-tags-Cjp84wCR.js} +1 -1
- package/dist/web/assets/{tsx-STHGXrTg.js → tsx-BYXwwi4R.js} +1 -1
- package/dist/web/assets/{twig-DeYz4MvR.js → twig-CJXgadPB.js} +1 -1
- package/dist/web/assets/{typescript-BkMW9mh2.js → typescript-SkJO5gXX.js} +1 -1
- package/dist/web/assets/{vennDiagram-CIIHVFJN-OUEEmD5m.js → vennDiagram-CIIHVFJN-DotTRq6i.js} +1 -1
- package/dist/web/assets/{vue-BhG5XYAd.js → vue-DnNvWsLF.js} +1 -1
- package/dist/web/assets/{vue-html-Cw0OXIMV.js → vue-html-BtDfjhCy.js} +1 -1
- package/dist/web/assets/{vue-vine-DxYQGujI.js → vue-vine-87qc9dJ9.js} +1 -1
- package/dist/web/assets/wardley-L42UT6IY-BtXwfgcx.js +1 -0
- package/dist/web/assets/{wardleyDiagram-YWT4CUSO-CbSRnjwb.js → wardleyDiagram-YWT4CUSO-C4mIx6nt.js} +1 -1
- package/dist/web/assets/{xml-Co1Haim6.js → xml-BwxGZI3_.js} +1 -1
- package/dist/web/assets/{xsl-Dyxp9ECK.js → xsl-V11HisfD.js} +1 -1
- package/dist/web/assets/{xychartDiagram-2RQKCTM6-PQFpoSrS.js → xychartDiagram-2RQKCTM6-CR2seeGg.js} +1 -1
- package/dist/web/assets/{yaml-DfBwtMv_.js → yaml-DoTdQeS-.js} +1 -1
- package/dist/web/index.html +2 -2
- package/package.json +6 -7
- package/dist/server/prompts/agents/turn-prompt-rewriter.md +0 -15
- package/dist/web/assets/architecture-7EHR7CIX-BUVdwEbF.js +0 -1
- package/dist/web/assets/channel-DC7LeJJp.js +0 -1
- package/dist/web/assets/chunk-QZHKN3VN-DTMt_eZs.js +0 -1
- package/dist/web/assets/classDiagram-4FO5ZUOK-jfKwbhh5.js +0 -1
- package/dist/web/assets/classDiagram-v2-Q7XG4LA2-jfKwbhh5.js +0 -1
- package/dist/web/assets/eventmodeling-FCH6USID-CelVcBa9.js +0 -1
- package/dist/web/assets/gitGraph-WXDBUCRP-D9mlI27B.js +0 -1
- package/dist/web/assets/index-BFZtO7ji.css +0 -2
- package/dist/web/assets/info-J43DQDTF-DmWxkfWc.js +0 -1
- package/dist/web/assets/mermaid-GHXKKRXX-L1cLS261.js +0 -1
- package/dist/web/assets/packet-YPE3B663-CrP5sMYi.js +0 -1
- package/dist/web/assets/pie-LRSECV5Y-Di4KiVyS.js +0 -1
- package/dist/web/assets/radar-GUYGQ44K-BWc_UrwT.js +0 -1
- package/dist/web/assets/stateDiagram-v2-BHNVJYJU-C7wmfqKn.js +0 -1
- package/dist/web/assets/treeView-BLDUP644-DRpNUAD5.js +0 -1
- package/dist/web/assets/treemap-LRROVOQU-CRkuQjMq.js +0 -1
- package/dist/web/assets/wardley-L42UT6IY-AM6lsfHi.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,56 @@ function loadDesignPageAgentCorePrompt() {
|
|
|
57983
57356
|
}
|
|
57984
57357
|
function buildPageTargetProtocolPrompt() {
|
|
57985
57358
|
return [
|
|
57986
|
-
"##
|
|
57987
|
-
"",
|
|
57988
|
-
"Resolve the target HTML page before creating or updating previewable output.",
|
|
57359
|
+
"## Single HTML Target Protocol",
|
|
57989
57360
|
"",
|
|
57990
|
-
"
|
|
57991
|
-
"- All previewable pages must be relative workspace paths ending in `.html`.",
|
|
57992
|
-
"- If the user names a file, path, or page type, use that explicit target.",
|
|
57993
|
-
"- Each turn's user message has already been rewritten with the current preview page and page edit mode when those matter.",
|
|
57994
|
-
'- If the user uses a relative page reference such as "this page", "current page", "here", "top", or "bottom", use the target page stated in the current user message when available.',
|
|
57995
|
-
"- If the user asks for a home, main, landing, or first page, use `index.html`.",
|
|
57996
|
-
"- If the user asks for a new named page, choose a semantic filename such as `login.html`, `settings.html`, or `pages/detail.html`.",
|
|
57997
|
-
"- If no target is specified and no multi-page structure is evident, default to `index.html`.",
|
|
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.",
|
|
57361
|
+
"The project has one previewable file: `index.html`.",
|
|
58000
57362
|
"",
|
|
58001
|
-
"
|
|
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
57386
|
"- Use `patch` for coordinated changes, repeated replacements, or multi-file edits.",
|
|
58018
|
-
"- Use `write` only for
|
|
58019
|
-
"- Do not use `write`
|
|
58020
|
-
"- Use `
|
|
58021
|
-
"- Use `
|
|
57387
|
+
"- Use `write` only for deliberate full-file replacement or non-preview support files.",
|
|
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
|
-
"For HTML
|
|
58024
|
-
|
|
58025
|
-
"-
|
|
58026
|
-
"-
|
|
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
|
+
"For Single HTML creation:",
|
|
57393
|
+
'- Call `createHtml({ path: "index.html" })` when `index.html` is missing.',
|
|
57394
|
+
"- After `createHtml`, read `index.html`.",
|
|
57395
|
+
"- Replace the default placeholder markup, CSS, and script with a complete designed prototype.",
|
|
58030
57396
|
"",
|
|
58031
|
-
"
|
|
58032
|
-
"- If `
|
|
58033
|
-
"-
|
|
57397
|
+
"For Single HTML updates:",
|
|
57398
|
+
"- If `index.html` exists, read it before editing and do not call `createHtml`.",
|
|
57399
|
+
"- Keep visible page structure, styling, and local interactions in `index.html`.",
|
|
57400
|
+
"- Use internal views for multi-screen workflows instead of additional HTML files.",
|
|
58034
57401
|
"",
|
|
58035
|
-
"
|
|
58036
|
-
"-
|
|
58037
|
-
"-
|
|
57402
|
+
"After page changes:",
|
|
57403
|
+
"- Use `previewRefresh` when the current preview page changed and should reload.",
|
|
57404
|
+
"- Call exactly one `previewRefresh` after successful previewable changes.",
|
|
57405
|
+
"",
|
|
57406
|
+
"Recover from tool failures:",
|
|
57407
|
+
"- If an edit fails, read the file again and retry with a smaller edit or patch.",
|
|
57408
|
+
"- If a generated prototype becomes too large or brittle, simplify the file while preserving visible quality."
|
|
58038
57409
|
].join("\n");
|
|
58039
57410
|
}
|
|
58040
57411
|
function buildResourcePolicyPrompt(resources) {
|
|
@@ -58047,17 +57418,22 @@ function buildResourcePolicyPrompt(resources) {
|
|
|
58047
57418
|
"Use these global resource settings when designing HTML preview pages.",
|
|
58048
57419
|
defaultFontLibrary ? `Default font library: ${defaultFontLibrary.name}.` : "Default font library: none configured.",
|
|
58049
57420
|
defaultIconLibrary ? `Default icon library: ${defaultIconLibrary.name}.` : "Default icon library: none configured.",
|
|
58050
|
-
"
|
|
58051
|
-
"
|
|
58052
|
-
"
|
|
58053
|
-
"
|
|
58054
|
-
"
|
|
57421
|
+
"The default HTML template already configures Inter and Noto Sans SC on the `html` element.",
|
|
57422
|
+
"Unless the user explicitly asks for a different typeface, do not change `font-family`; adjust typography with size, weight, line-height, spacing, and hierarchy.",
|
|
57423
|
+
"Lucide icons are already configured by the default HTML template.",
|
|
57424
|
+
'Use Lucide icons with `<i data-lucide="menu"></i>` syntax, replacing `menu` with the appropriate Lucide icon name.',
|
|
57425
|
+
"Do not use other icon systems, inline SVG icons, emoji icons, or decorative emoji as UI icons.",
|
|
57426
|
+
"When styling Lucide icons, do not target `i`, `i[data-lucide]`, or tag selectors because Lucide replaces the placeholder with inline `svg` elements.",
|
|
57427
|
+
"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; }`.",
|
|
57428
|
+
"If JavaScript dynamically inserts markup that contains Lucide placeholders, call `lucide.createIcons()` after updating the DOM.",
|
|
57429
|
+
"Prefer configured resources and local CSS before adding any external resource.",
|
|
57430
|
+
"Add an extra external resource only when the user explicitly requests it or when it is necessary for the prototype quality.",
|
|
57431
|
+
"When a configured library has no CDN, follow the library choice in CSS naming only.",
|
|
58055
57432
|
"Configured font libraries:",
|
|
58056
57433
|
fontLines.length ? fontLines.join("\n") : "- none",
|
|
58057
57434
|
"Configured icon libraries:",
|
|
58058
57435
|
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."
|
|
57436
|
+
"Use regular inline CSS as the primary styling method."
|
|
58061
57437
|
].join("\n");
|
|
58062
57438
|
}
|
|
58063
57439
|
function buildApprovedCdnUrls(resources) {
|
|
@@ -58075,75 +57451,6 @@ function formatResourceLibraryList(libraries) {
|
|
|
58075
57451
|
);
|
|
58076
57452
|
}
|
|
58077
57453
|
|
|
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
57454
|
// ../core/src/preview/preview-server-manager.ts
|
|
58148
57455
|
import { access, readFile as readFile2 } from "node:fs/promises";
|
|
58149
57456
|
import path5 from "node:path";
|
|
@@ -58167,9 +57474,13 @@ var PreviewServerManager = class {
|
|
|
58167
57474
|
}
|
|
58168
57475
|
async ensure(projectId, clientId, previewPath) {
|
|
58169
57476
|
const entry = await this.getOrStartEntry(projectId, clientId);
|
|
58170
|
-
const files = await
|
|
57477
|
+
const [files, pageManifest] = await Promise.all([
|
|
57478
|
+
this.workspaceStore.listProjectHtmlFiles(projectId),
|
|
57479
|
+
this.workspaceStore.readProjectHtmlPageManifest(projectId)
|
|
57480
|
+
]);
|
|
58171
57481
|
const activePath = resolveActivePreviewPath(
|
|
58172
57482
|
files,
|
|
57483
|
+
pageManifest,
|
|
58173
57484
|
previewPath ?? entry.activePath
|
|
58174
57485
|
);
|
|
58175
57486
|
entry.activePath = activePath;
|
|
@@ -58178,6 +57489,7 @@ var PreviewServerManager = class {
|
|
|
58178
57489
|
return {
|
|
58179
57490
|
...activePath ? { activePath } : {},
|
|
58180
57491
|
files,
|
|
57492
|
+
pageManifest,
|
|
58181
57493
|
url: buildPreviewUrl(entry.baseUrl, activePath)
|
|
58182
57494
|
};
|
|
58183
57495
|
}
|
|
@@ -58211,9 +57523,7 @@ var PreviewServerManager = class {
|
|
|
58211
57523
|
return this.entries.size;
|
|
58212
57524
|
}
|
|
58213
57525
|
getLeaseCount(projectId) {
|
|
58214
|
-
return Array.from(this.entries.values()).filter(
|
|
58215
|
-
(entry) => entry.projectId === projectId
|
|
58216
|
-
).length;
|
|
57526
|
+
return Array.from(this.entries.values()).filter((entry) => entry.projectId === projectId).length;
|
|
58217
57527
|
}
|
|
58218
57528
|
async cleanupExpiredLeases() {
|
|
58219
57529
|
const now2 = this.now();
|
|
@@ -58253,24 +57563,21 @@ var PreviewServerManager = class {
|
|
|
58253
57563
|
key,
|
|
58254
57564
|
projectId
|
|
58255
57565
|
};
|
|
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
|
-
);
|
|
57566
|
+
app2.get("/", async () => readIndexHtmlOrNotFound(workspaceDirectory, entry));
|
|
57567
|
+
app2.get("/index.html", async () => readIndexHtmlOrNotFound(workspaceDirectory, entry));
|
|
58264
57568
|
app2.use("*", async (context2, next) => {
|
|
58265
57569
|
context2.header("Cache-Control", PREVIEW_CACHE_CONTROL);
|
|
58266
57570
|
await next();
|
|
58267
57571
|
});
|
|
58268
|
-
app2.use(
|
|
58269
|
-
|
|
58270
|
-
|
|
58271
|
-
|
|
58272
|
-
|
|
58273
|
-
|
|
57572
|
+
app2.use(
|
|
57573
|
+
"*",
|
|
57574
|
+
serveStatic({
|
|
57575
|
+
onFound: (filePath) => {
|
|
57576
|
+
recordServedStaticPath(entry, workspaceDirectory, filePath);
|
|
57577
|
+
},
|
|
57578
|
+
root: workspaceDirectory
|
|
57579
|
+
})
|
|
57580
|
+
);
|
|
58274
57581
|
const server2 = await listenOnRandomPort(app2);
|
|
58275
57582
|
entry.server = server2.server;
|
|
58276
57583
|
entry.baseUrl = server2.baseUrl;
|
|
@@ -58349,123 +57656,32 @@ function getPreviewServerManager(workspaceStore) {
|
|
|
58349
57656
|
});
|
|
58350
57657
|
return globalThis.__owndesignPreviewServerManager;
|
|
58351
57658
|
}
|
|
58352
|
-
async function
|
|
57659
|
+
async function readIndexHtmlOrNotFound(workspaceDirectory, entry) {
|
|
58353
57660
|
const indexPath = path5.join(workspaceDirectory, "index.html");
|
|
58354
57661
|
try {
|
|
58355
57662
|
await access(indexPath);
|
|
58356
57663
|
entry.activePath = "index.html";
|
|
58357
|
-
return readFile2(indexPath, "utf8");
|
|
57664
|
+
return htmlResponse(await readFile2(indexPath, "utf8"));
|
|
58358
57665
|
} 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) {
|
|
57666
|
+
return new Response(null, {
|
|
57667
|
+
headers: {
|
|
57668
|
+
"Cache-Control": PREVIEW_CACHE_CONTROL
|
|
57669
|
+
},
|
|
57670
|
+
status: 404
|
|
57671
|
+
});
|
|
57672
|
+
}
|
|
57673
|
+
}
|
|
57674
|
+
function resolveActivePreviewPath(files, pageManifest, previewPath) {
|
|
58463
57675
|
if (previewPath && files.includes(previewPath)) {
|
|
58464
57676
|
return previewPath;
|
|
58465
57677
|
}
|
|
58466
57678
|
if (files.includes("index.html")) {
|
|
58467
57679
|
return "index.html";
|
|
58468
57680
|
}
|
|
57681
|
+
const manifestPath = pageManifest.pages.find((page) => files.includes(page.htmlPath))?.htmlPath;
|
|
57682
|
+
if (manifestPath) {
|
|
57683
|
+
return manifestPath;
|
|
57684
|
+
}
|
|
58469
57685
|
return files[0];
|
|
58470
57686
|
}
|
|
58471
57687
|
function buildPreviewUrl(baseUrl, previewPath) {
|
|
@@ -58493,11 +57709,7 @@ function recordServedStaticPath(entry, workspaceDirectory, servedPath) {
|
|
|
58493
57709
|
}
|
|
58494
57710
|
|
|
58495
57711
|
// ../core/src/navigation.ts
|
|
58496
|
-
function buildWorkspaceHref({
|
|
58497
|
-
conversationId,
|
|
58498
|
-
previewPath,
|
|
58499
|
-
projectId
|
|
58500
|
-
}) {
|
|
57712
|
+
function buildWorkspaceHref({ conversationId, previewPath, projectId }) {
|
|
58501
57713
|
if (!projectId) {
|
|
58502
57714
|
return "/";
|
|
58503
57715
|
}
|
|
@@ -58548,11 +57760,7 @@ var ConversationService = class {
|
|
|
58548
57760
|
titleManuallySet: true,
|
|
58549
57761
|
updatedAt: this.now()
|
|
58550
57762
|
};
|
|
58551
|
-
return this.workspaceStore.updateConversation(
|
|
58552
|
-
projectId,
|
|
58553
|
-
conversationId,
|
|
58554
|
-
updatedConversation
|
|
58555
|
-
);
|
|
57763
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58556
57764
|
}
|
|
58557
57765
|
async switchConversation(projectId, conversationId) {
|
|
58558
57766
|
return this.workspaceStore.getConversation(projectId, conversationId);
|
|
@@ -58571,7 +57779,7 @@ var ConversationService = class {
|
|
|
58571
57779
|
};
|
|
58572
57780
|
const agentResult = await this.generateProjectOutputSafely({
|
|
58573
57781
|
content,
|
|
58574
|
-
|
|
57782
|
+
projectType: project.projectType ?? "single_html",
|
|
58575
57783
|
projectId
|
|
58576
57784
|
});
|
|
58577
57785
|
const mockReply = {
|
|
@@ -58579,11 +57787,7 @@ var ConversationService = class {
|
|
|
58579
57787
|
content: agentResult.content,
|
|
58580
57788
|
createdAt: timestamp
|
|
58581
57789
|
};
|
|
58582
|
-
const messages = [
|
|
58583
|
-
...existingConversation.messages,
|
|
58584
|
-
userMessage,
|
|
58585
|
-
mockReply
|
|
58586
|
-
];
|
|
57790
|
+
const messages = [...existingConversation.messages, userMessage, mockReply];
|
|
58587
57791
|
const updatedConversation = {
|
|
58588
57792
|
...existingConversation,
|
|
58589
57793
|
title: !existingConversation.titleManuallySet && existingConversation.title === DEFAULT_CONVERSATION_TITLE && existingConversation.messages.length === 0 ? summarizeConversationTitle(content) : existingConversation.title,
|
|
@@ -58596,11 +57800,7 @@ var ConversationService = class {
|
|
|
58596
57800
|
updatedAt: timestamp
|
|
58597
57801
|
};
|
|
58598
57802
|
await this.workspaceStore.updateProject(projectId, updatedProject);
|
|
58599
|
-
return this.workspaceStore.updateConversation(
|
|
58600
|
-
projectId,
|
|
58601
|
-
conversationId,
|
|
58602
|
-
updatedConversation
|
|
58603
|
-
);
|
|
57803
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58604
57804
|
}
|
|
58605
57805
|
async saveUIMessageStream(projectId, conversationId, messages) {
|
|
58606
57806
|
const existingConversation = await this.workspaceStore.getConversation(
|
|
@@ -58622,22 +57822,13 @@ var ConversationService = class {
|
|
|
58622
57822
|
updatedAt: timestamp
|
|
58623
57823
|
};
|
|
58624
57824
|
await this.workspaceStore.updateProject(projectId, updatedProject);
|
|
58625
|
-
return this.workspaceStore.updateConversation(
|
|
58626
|
-
projectId,
|
|
58627
|
-
conversationId,
|
|
58628
|
-
updatedConversation
|
|
58629
|
-
);
|
|
57825
|
+
return this.workspaceStore.updateConversation(projectId, conversationId, updatedConversation);
|
|
58630
57826
|
}
|
|
58631
57827
|
async deleteConversation(projectId, conversationId, defaultTitle) {
|
|
58632
57828
|
await this.workspaceStore.deleteConversation(projectId, conversationId);
|
|
58633
|
-
let remainingConversations = await this.workspaceStore.listConversations(
|
|
58634
|
-
projectId
|
|
58635
|
-
);
|
|
57829
|
+
let remainingConversations = await this.workspaceStore.listConversations(projectId);
|
|
58636
57830
|
if (remainingConversations.length === 0) {
|
|
58637
|
-
const replacementConversation = await this.createConversation(
|
|
58638
|
-
projectId,
|
|
58639
|
-
defaultTitle
|
|
58640
|
-
);
|
|
57831
|
+
const replacementConversation = await this.createConversation(projectId, defaultTitle);
|
|
58641
57832
|
remainingConversations = [replacementConversation];
|
|
58642
57833
|
}
|
|
58643
57834
|
return remainingConversations;
|
|
@@ -58676,11 +57867,16 @@ var ProjectService = class {
|
|
|
58676
57867
|
this.previewServerManager = options.previewServerManager;
|
|
58677
57868
|
}
|
|
58678
57869
|
async createProject(input) {
|
|
57870
|
+
const projectType = input.projectType ?? "single_html";
|
|
57871
|
+
if (projectType === "react") {
|
|
57872
|
+
throw new Error("React project type is reserved but not supported yet.");
|
|
57873
|
+
}
|
|
58679
57874
|
const timestamp = this.now();
|
|
58680
57875
|
const project = {
|
|
58681
57876
|
id: this.createId(),
|
|
58682
57877
|
name: input.name,
|
|
58683
57878
|
description: input.description,
|
|
57879
|
+
projectType,
|
|
58684
57880
|
outputType: "html",
|
|
58685
57881
|
createdAt: timestamp,
|
|
58686
57882
|
updatedAt: timestamp
|
|
@@ -58694,6 +57890,11 @@ var ProjectService = class {
|
|
|
58694
57890
|
messages: []
|
|
58695
57891
|
};
|
|
58696
57892
|
await this.workspaceStore.createProject(project);
|
|
57893
|
+
await this.workspaceStore.writeProjectWorkspaceFile(
|
|
57894
|
+
project.id,
|
|
57895
|
+
"index.html",
|
|
57896
|
+
buildSingleHtmlTemplate({ title: input.name })
|
|
57897
|
+
);
|
|
58697
57898
|
await this.workspaceStore.createConversation(conversation);
|
|
58698
57899
|
return { conversation, project };
|
|
58699
57900
|
}
|
|
@@ -58720,15 +57921,7 @@ var ProjectService = class {
|
|
|
58720
57921
|
};
|
|
58721
57922
|
|
|
58722
57923
|
// ../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";
|
|
57924
|
+
import { copyFile, lstat, mkdir as mkdir2, readdir, readFile as readFile4, rm, stat as stat3, writeFile as writeFile2 } from "node:fs/promises";
|
|
58732
57925
|
import os5 from "node:os";
|
|
58733
57926
|
import path13 from "node:path";
|
|
58734
57927
|
import process12 from "node:process";
|
|
@@ -58744,7 +57937,7 @@ function normalizePositiveInteger(value, fallback, name21) {
|
|
|
58744
57937
|
}
|
|
58745
57938
|
return value;
|
|
58746
57939
|
}
|
|
58747
|
-
function
|
|
57940
|
+
function countOccurrences(content, needle) {
|
|
58748
57941
|
if (!needle) {
|
|
58749
57942
|
return 0;
|
|
58750
57943
|
}
|
|
@@ -58757,27 +57950,25 @@ function applyTextEdit(content, oldText, newText, replaceAll = false, relativePa
|
|
|
58757
57950
|
if (oldText === newText) {
|
|
58758
57951
|
throw new Error("No changes to apply: oldText and newText are identical.");
|
|
58759
57952
|
}
|
|
58760
|
-
const normalizedOldText =
|
|
58761
|
-
const normalizedNewText =
|
|
57953
|
+
const normalizedOldText = convertToLineEnding(oldText, detectLineEnding(content));
|
|
57954
|
+
const normalizedNewText = convertToLineEnding(newText, detectLineEnding(content));
|
|
58762
57955
|
const firstIndex = content.indexOf(normalizedOldText);
|
|
58763
57956
|
if (firstIndex === -1) {
|
|
58764
57957
|
throw new Error(`oldText was not found in Project Workspace file: ${relativePath}`);
|
|
58765
57958
|
}
|
|
58766
|
-
const replacements =
|
|
57959
|
+
const replacements = countOccurrences(content, normalizedOldText);
|
|
58767
57960
|
if (!replaceAll && replacements > 1) {
|
|
58768
|
-
throw new Error(
|
|
58769
|
-
`oldText appears more than once in Project Workspace file: ${relativePath}`
|
|
58770
|
-
);
|
|
57961
|
+
throw new Error(`oldText appears more than once in Project Workspace file: ${relativePath}`);
|
|
58771
57962
|
}
|
|
58772
57963
|
return {
|
|
58773
57964
|
content: replaceAll ? content.split(normalizedOldText).join(normalizedNewText) : content.slice(0, firstIndex) + normalizedNewText + content.slice(firstIndex + normalizedOldText.length),
|
|
58774
57965
|
replacements: replaceAll ? replacements : 1
|
|
58775
57966
|
};
|
|
58776
57967
|
}
|
|
58777
|
-
function
|
|
57968
|
+
function detectLineEnding(text2) {
|
|
58778
57969
|
return text2.includes("\r\n") ? "\r\n" : "\n";
|
|
58779
57970
|
}
|
|
58780
|
-
function
|
|
57971
|
+
function convertToLineEnding(text2, ending) {
|
|
58781
57972
|
const normalized = text2.replaceAll("\r\n", "\n").replaceAll("\r", "\n");
|
|
58782
57973
|
return ending === "\n" ? normalized : normalized.replaceAll("\n", "\r\n");
|
|
58783
57974
|
}
|
|
@@ -58832,6 +58023,39 @@ function buildUnifiedDiff(oldContent, newContent, relativePath) {
|
|
|
58832
58023
|
return lines.join("\n");
|
|
58833
58024
|
}
|
|
58834
58025
|
|
|
58026
|
+
// ../core/src/html-page-manifest.ts
|
|
58027
|
+
var HTML_PAGE_MANIFEST_PATH = ".owndesign-pages.json";
|
|
58028
|
+
var EMPTY_HTML_PAGE_MANIFEST = {
|
|
58029
|
+
pages: []
|
|
58030
|
+
};
|
|
58031
|
+
function parseHtmlPageManifest(content) {
|
|
58032
|
+
if (!content) {
|
|
58033
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58034
|
+
}
|
|
58035
|
+
let value;
|
|
58036
|
+
try {
|
|
58037
|
+
value = JSON.parse(content);
|
|
58038
|
+
} catch {
|
|
58039
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58040
|
+
}
|
|
58041
|
+
if (!isRecord2(value) || !Array.isArray(value.pages)) {
|
|
58042
|
+
return EMPTY_HTML_PAGE_MANIFEST;
|
|
58043
|
+
}
|
|
58044
|
+
const pages = value.pages.filter(isRecord2).map((page) => ({
|
|
58045
|
+
componentSource: typeof page.componentSource === "string" ? page.componentSource.trim() : "",
|
|
58046
|
+
componentTag: typeof page.componentTag === "string" ? page.componentTag.trim() : "",
|
|
58047
|
+
displayName: typeof page.displayName === "string" ? page.displayName.trim() : "",
|
|
58048
|
+
htmlPath: typeof page.htmlPath === "string" ? page.htmlPath.trim() : "",
|
|
58049
|
+
slug: typeof page.slug === "string" ? page.slug.trim() : ""
|
|
58050
|
+
})).filter(
|
|
58051
|
+
(page) => page.slug && page.displayName && page.htmlPath && page.componentTag && page.componentSource
|
|
58052
|
+
);
|
|
58053
|
+
return { pages };
|
|
58054
|
+
}
|
|
58055
|
+
function isRecord2(value) {
|
|
58056
|
+
return typeof value === "object" && value !== null;
|
|
58057
|
+
}
|
|
58058
|
+
|
|
58835
58059
|
// ../core/src/workspace-store/files.ts
|
|
58836
58060
|
import { open, readFile as readFile3, stat as stat2 } from "node:fs/promises";
|
|
58837
58061
|
|
|
@@ -59153,10 +58377,10 @@ var isSymlinkSync = isTypeSync.bind(void 0, "lstatSync", "isSymbolicLink");
|
|
|
59153
58377
|
// ../../node_modules/.pnpm/unicorn-magic@0.3.0/node_modules/unicorn-magic/node.js
|
|
59154
58378
|
import { promisify } from "node:util";
|
|
59155
58379
|
import { execFile as execFileCallback, execFileSync as execFileSyncOriginal } from "node:child_process";
|
|
59156
|
-
import { fileURLToPath as
|
|
58380
|
+
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
59157
58381
|
var execFileOriginal = promisify(execFileCallback);
|
|
59158
58382
|
function toPath(urlOrPath) {
|
|
59159
|
-
return urlOrPath instanceof URL ?
|
|
58383
|
+
return urlOrPath instanceof URL ? fileURLToPath3(urlOrPath) : urlOrPath;
|
|
59160
58384
|
}
|
|
59161
58385
|
var TEN_MEGABYTES_IN_BYTES = 10 * 1024 * 1024;
|
|
59162
58386
|
|
|
@@ -59543,14 +58767,7 @@ if ($item.PSIsContainer) {
|
|
|
59543
58767
|
`;
|
|
59544
58768
|
await execFileAsync(
|
|
59545
58769
|
"powershell.exe",
|
|
59546
|
-
[
|
|
59547
|
-
"-NoProfile",
|
|
59548
|
-
"-NonInteractive",
|
|
59549
|
-
"-ExecutionPolicy",
|
|
59550
|
-
"Bypass",
|
|
59551
|
-
"-Command",
|
|
59552
|
-
recycleScript
|
|
59553
|
-
],
|
|
58770
|
+
["-NoProfile", "-NonInteractive", "-ExecutionPolicy", "Bypass", "-Command", recycleScript],
|
|
59554
58771
|
{
|
|
59555
58772
|
env: {
|
|
59556
58773
|
...process11.env,
|
|
@@ -59604,7 +58821,7 @@ var WorkspaceStore = class {
|
|
|
59604
58821
|
path13.join(projectsRoot, entry.name, "project.json"),
|
|
59605
58822
|
"utf8"
|
|
59606
58823
|
);
|
|
59607
|
-
return JSON.parse(projectJson);
|
|
58824
|
+
return normalizeProjectRecord(JSON.parse(projectJson));
|
|
59608
58825
|
})
|
|
59609
58826
|
);
|
|
59610
58827
|
return projects.sort(
|
|
@@ -59622,7 +58839,7 @@ var WorkspaceStore = class {
|
|
|
59622
58839
|
path13.join(this.getProjectDirectory(projectId), "project.json"),
|
|
59623
58840
|
"utf8"
|
|
59624
58841
|
);
|
|
59625
|
-
return JSON.parse(projectJson);
|
|
58842
|
+
return normalizeProjectRecord(JSON.parse(projectJson));
|
|
59626
58843
|
}
|
|
59627
58844
|
async updateProject(projectId, project) {
|
|
59628
58845
|
await writeFile2(
|
|
@@ -59685,6 +58902,70 @@ var WorkspaceStore = class {
|
|
|
59685
58902
|
);
|
|
59686
58903
|
return conversation;
|
|
59687
58904
|
}
|
|
58905
|
+
async createCheckpoint(input) {
|
|
58906
|
+
assertSafeCheckpointId(input.id);
|
|
58907
|
+
const record2 = {
|
|
58908
|
+
...input,
|
|
58909
|
+
files: ["index.html"]
|
|
58910
|
+
};
|
|
58911
|
+
const checkpointDirectory = this.getCheckpointDirectory(input.projectId, input.id);
|
|
58912
|
+
const filesDirectory = path13.join(checkpointDirectory, "files");
|
|
58913
|
+
const sourceFilePath = await this.resolveProjectWorkspacePath(input.projectId, "index.html", {
|
|
58914
|
+
checkTargetSymlink: true
|
|
58915
|
+
});
|
|
58916
|
+
await mkdir2(filesDirectory, { recursive: true });
|
|
58917
|
+
await copyFile(sourceFilePath, path13.join(filesDirectory, "index.html"));
|
|
58918
|
+
await writeFile2(
|
|
58919
|
+
path13.join(checkpointDirectory, "meta.json"),
|
|
58920
|
+
`${JSON.stringify(record2, null, 2)}
|
|
58921
|
+
`,
|
|
58922
|
+
"utf8"
|
|
58923
|
+
);
|
|
58924
|
+
return record2;
|
|
58925
|
+
}
|
|
58926
|
+
async listCheckpoints(projectId) {
|
|
58927
|
+
const checkpointsDirectory = this.getCheckpointsDirectory(projectId);
|
|
58928
|
+
try {
|
|
58929
|
+
const entries = await readdir(checkpointsDirectory, { withFileTypes: true });
|
|
58930
|
+
const checkpoints = await Promise.all(
|
|
58931
|
+
entries.filter((entry) => entry.isDirectory()).map(async (entry) => this.readCheckpoint(projectId, entry.name))
|
|
58932
|
+
);
|
|
58933
|
+
return checkpoints.sort(
|
|
58934
|
+
(left, right) => new Date(right.createdAt).getTime() - new Date(left.createdAt).getTime()
|
|
58935
|
+
);
|
|
58936
|
+
} catch (error51) {
|
|
58937
|
+
if (isMissingPathError3(error51)) {
|
|
58938
|
+
return [];
|
|
58939
|
+
}
|
|
58940
|
+
throw error51;
|
|
58941
|
+
}
|
|
58942
|
+
}
|
|
58943
|
+
async readCheckpoint(projectId, checkpointId) {
|
|
58944
|
+
assertSafeCheckpointId(checkpointId);
|
|
58945
|
+
const checkpointJson = await readFile4(
|
|
58946
|
+
path13.join(this.getCheckpointDirectory(projectId, checkpointId), "meta.json"),
|
|
58947
|
+
"utf8"
|
|
58948
|
+
);
|
|
58949
|
+
const checkpoint = JSON.parse(checkpointJson);
|
|
58950
|
+
if (checkpoint.projectId !== projectId || checkpoint.id !== checkpointId) {
|
|
58951
|
+
throw new Error("Checkpoint metadata does not match the requested project.");
|
|
58952
|
+
}
|
|
58953
|
+
return checkpoint;
|
|
58954
|
+
}
|
|
58955
|
+
async restoreCheckpointFiles(projectId, checkpointId) {
|
|
58956
|
+
const checkpoint = await this.readCheckpoint(projectId, checkpointId);
|
|
58957
|
+
const checkpointDirectory = this.getCheckpointDirectory(projectId, checkpointId);
|
|
58958
|
+
for (const file2 of checkpoint.files) {
|
|
58959
|
+
const sourcePath = path13.join(checkpointDirectory, "files", file2);
|
|
58960
|
+
const targetPath = await this.resolveProjectWorkspacePath(projectId, file2, {
|
|
58961
|
+
checkTargetSymlink: true,
|
|
58962
|
+
targetMayBeMissing: true
|
|
58963
|
+
});
|
|
58964
|
+
await mkdir2(path13.dirname(targetPath), { recursive: true });
|
|
58965
|
+
await copyFile(sourcePath, targetPath);
|
|
58966
|
+
}
|
|
58967
|
+
return checkpoint;
|
|
58968
|
+
}
|
|
59688
58969
|
async writeProjectOutput(projectId, outputType, content) {
|
|
59689
58970
|
const outputPath = this.getProjectOutputFilePath(projectId, outputType);
|
|
59690
58971
|
await mkdir2(path13.dirname(outputPath), { recursive: true });
|
|
@@ -59721,18 +59002,24 @@ var WorkspaceStore = class {
|
|
|
59721
59002
|
return left.localeCompare(right);
|
|
59722
59003
|
});
|
|
59723
59004
|
}
|
|
59005
|
+
async readProjectHtmlPageManifest(projectId) {
|
|
59006
|
+
try {
|
|
59007
|
+
return parseHtmlPageManifest(
|
|
59008
|
+
await this.readProjectWorkspaceFile(projectId, HTML_PAGE_MANIFEST_PATH)
|
|
59009
|
+
);
|
|
59010
|
+
} catch (error51) {
|
|
59011
|
+
if (isMissingPathError3(error51)) {
|
|
59012
|
+
return parseHtmlPageManifest(void 0);
|
|
59013
|
+
}
|
|
59014
|
+
throw error51;
|
|
59015
|
+
}
|
|
59016
|
+
}
|
|
59724
59017
|
async readProjectWorkspaceEntry(projectId, relativePath, options = {}) {
|
|
59725
59018
|
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
|
-
);
|
|
59019
|
+
const limit = normalizePositiveInteger(options.limit, DEFAULT_READ_LIMIT, "limit");
|
|
59020
|
+
const targetPath = relativePath === "." ? this.getProjectWorkspaceDirectory(projectId) : await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59021
|
+
checkTargetSymlink: true
|
|
59022
|
+
});
|
|
59736
59023
|
const targetStats = await lstat(targetPath);
|
|
59737
59024
|
const normalizedPath = normalizeWorkspaceRelativePath(relativePath);
|
|
59738
59025
|
if (targetStats.isSymbolicLink()) {
|
|
@@ -59752,15 +59039,11 @@ var WorkspaceStore = class {
|
|
|
59752
59039
|
return void 0;
|
|
59753
59040
|
}
|
|
59754
59041
|
return {
|
|
59755
|
-
path: normalizeWorkspaceRelativePath(
|
|
59756
|
-
path13.relative(rootPath, absolutePath)
|
|
59757
|
-
),
|
|
59042
|
+
path: normalizeWorkspaceRelativePath(path13.relative(rootPath, absolutePath)),
|
|
59758
59043
|
type: entryStats.isDirectory() ? "directory" : "file"
|
|
59759
59044
|
};
|
|
59760
59045
|
})
|
|
59761
|
-
)).filter(
|
|
59762
|
-
(entry) => Boolean(entry)
|
|
59763
|
-
).sort((left, right) => left.path.localeCompare(right.path));
|
|
59046
|
+
)).filter((entry) => Boolean(entry)).sort((left, right) => left.path.localeCompare(right.path));
|
|
59764
59047
|
const start2 = offset - 1;
|
|
59765
59048
|
const sliced = visibleEntries.slice(start2, start2 + limit);
|
|
59766
59049
|
return {
|
|
@@ -59833,20 +59116,16 @@ var WorkspaceStore = class {
|
|
|
59833
59116
|
const startPath = relativePath && relativePath !== "." ? relativePath : "";
|
|
59834
59117
|
const matcher = globToRegExp(pattern);
|
|
59835
59118
|
const matches = [];
|
|
59836
|
-
await this.walkProjectWorkspace(
|
|
59837
|
-
|
|
59838
|
-
|
|
59839
|
-
|
|
59840
|
-
|
|
59841
|
-
|
|
59842
|
-
|
|
59843
|
-
|
|
59844
|
-
type: entry.type,
|
|
59845
|
-
updatedAt: entry.updatedAt
|
|
59846
|
-
});
|
|
59847
|
-
}
|
|
59119
|
+
await this.walkProjectWorkspace(projectId, startPath, async (entry) => {
|
|
59120
|
+
const pathFromStart = startPath ? normalizeWorkspaceRelativePath(path13.relative(startPath, entry.path)) : entry.path;
|
|
59121
|
+
if (matcher.test(pathFromStart) || matcher.test(path13.basename(entry.path))) {
|
|
59122
|
+
matches.push({
|
|
59123
|
+
path: entry.path,
|
|
59124
|
+
type: entry.type,
|
|
59125
|
+
updatedAt: entry.updatedAt
|
|
59126
|
+
});
|
|
59848
59127
|
}
|
|
59849
|
-
);
|
|
59128
|
+
});
|
|
59850
59129
|
const sortedMatches = matches.sort(
|
|
59851
59130
|
(left, right) => new Date(right.updatedAt).getTime() - new Date(left.updatedAt).getTime()
|
|
59852
59131
|
);
|
|
@@ -59944,11 +59223,7 @@ var WorkspaceStore = class {
|
|
|
59944
59223
|
if (!changes.length) {
|
|
59945
59224
|
throw new Error("Project Workspace patch must include at least one change.");
|
|
59946
59225
|
}
|
|
59947
|
-
const prepared = await this.prepareProjectWorkspacePatch(
|
|
59948
|
-
projectId,
|
|
59949
|
-
changes,
|
|
59950
|
-
options
|
|
59951
|
-
);
|
|
59226
|
+
const prepared = await this.prepareProjectWorkspacePatch(projectId, changes, options);
|
|
59952
59227
|
for (const change of prepared) {
|
|
59953
59228
|
if (change.operation === "delete") {
|
|
59954
59229
|
await rm(change.absolutePath, { force: false, recursive: true });
|
|
@@ -59978,26 +59253,14 @@ var WorkspaceStore = class {
|
|
|
59978
59253
|
}) : this.getProjectWorkspaceDirectory(projectId);
|
|
59979
59254
|
const startStats = await stat3(startPath);
|
|
59980
59255
|
if (startStats.isFile()) {
|
|
59981
|
-
await this.searchWorkspaceFile(
|
|
59982
|
-
projectId,
|
|
59983
|
-
startPath,
|
|
59984
|
-
query,
|
|
59985
|
-
matches,
|
|
59986
|
-
skippedFiles
|
|
59987
|
-
);
|
|
59256
|
+
await this.searchWorkspaceFile(projectId, startPath, query, matches, skippedFiles);
|
|
59988
59257
|
} else if (startStats.isDirectory()) {
|
|
59989
59258
|
await this.walkProjectWorkspace(
|
|
59990
59259
|
projectId,
|
|
59991
59260
|
relativePath === "." ? "" : relativePath,
|
|
59992
59261
|
async (entry, absolutePath) => {
|
|
59993
59262
|
if (entry.type === "file") {
|
|
59994
|
-
await this.searchWorkspaceFile(
|
|
59995
|
-
projectId,
|
|
59996
|
-
absolutePath,
|
|
59997
|
-
query,
|
|
59998
|
-
matches,
|
|
59999
|
-
skippedFiles
|
|
60000
|
-
);
|
|
59263
|
+
await this.searchWorkspaceFile(projectId, absolutePath, query, matches, skippedFiles);
|
|
60001
59264
|
}
|
|
60002
59265
|
}
|
|
60003
59266
|
);
|
|
@@ -60011,11 +59274,9 @@ var WorkspaceStore = class {
|
|
|
60011
59274
|
};
|
|
60012
59275
|
}
|
|
60013
59276
|
async readProjectWorkspaceFile(projectId, relativePath) {
|
|
60014
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60015
|
-
|
|
60016
|
-
|
|
60017
|
-
{ checkTargetSymlink: true }
|
|
60018
|
-
);
|
|
59277
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59278
|
+
checkTargetSymlink: true
|
|
59279
|
+
});
|
|
60019
59280
|
const fileStats = await stat3(filePath);
|
|
60020
59281
|
if (!fileStats.isFile()) {
|
|
60021
59282
|
throw new Error(`Project Workspace path is not a file: ${relativePath}`);
|
|
@@ -60023,11 +59284,9 @@ var WorkspaceStore = class {
|
|
|
60023
59284
|
return readFile4(filePath, "utf8");
|
|
60024
59285
|
}
|
|
60025
59286
|
async readProjectWorkspaceFileBuffer(projectId, relativePath) {
|
|
60026
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60027
|
-
|
|
60028
|
-
|
|
60029
|
-
{ checkTargetSymlink: true }
|
|
60030
|
-
);
|
|
59287
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59288
|
+
checkTargetSymlink: true
|
|
59289
|
+
});
|
|
60031
59290
|
const fileStats = await stat3(filePath);
|
|
60032
59291
|
if (!fileStats.isFile()) {
|
|
60033
59292
|
throw new Error(`Project Workspace path is not a file: ${relativePath}`);
|
|
@@ -60035,11 +59294,10 @@ var WorkspaceStore = class {
|
|
|
60035
59294
|
return readFile4(filePath);
|
|
60036
59295
|
}
|
|
60037
59296
|
async writeProjectWorkspaceFile(projectId, relativePath, content) {
|
|
60038
|
-
const filePath = await this.resolveProjectWorkspacePath(
|
|
60039
|
-
|
|
60040
|
-
|
|
60041
|
-
|
|
60042
|
-
);
|
|
59297
|
+
const filePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59298
|
+
checkTargetSymlink: true,
|
|
59299
|
+
targetMayBeMissing: true
|
|
59300
|
+
});
|
|
60043
59301
|
const previousContent = await readTextFileIfExists(filePath);
|
|
60044
59302
|
await mkdir2(path13.dirname(filePath), { recursive: true });
|
|
60045
59303
|
await writeFile2(filePath, content, "utf8");
|
|
@@ -60074,21 +59332,15 @@ var WorkspaceStore = class {
|
|
|
60074
59332
|
);
|
|
60075
59333
|
await this.writeProjectWorkspaceFile(projectId, relativePath, updatedContent);
|
|
60076
59334
|
return {
|
|
60077
|
-
diff: buildUnifiedDiff(
|
|
60078
|
-
content,
|
|
60079
|
-
updatedContent,
|
|
60080
|
-
normalizeWorkspaceRelativePath(relativePath)
|
|
60081
|
-
),
|
|
59335
|
+
diff: buildUnifiedDiff(content, updatedContent, normalizeWorkspaceRelativePath(relativePath)),
|
|
60082
59336
|
path: normalizeWorkspaceRelativePath(relativePath),
|
|
60083
59337
|
replacements: replaceAll ? replacements : 1
|
|
60084
59338
|
};
|
|
60085
59339
|
}
|
|
60086
59340
|
async deleteProjectWorkspacePath(projectId, relativePath) {
|
|
60087
|
-
const targetPath = await this.resolveProjectWorkspacePath(
|
|
60088
|
-
|
|
60089
|
-
|
|
60090
|
-
{ checkTargetSymlink: true }
|
|
60091
|
-
);
|
|
59341
|
+
const targetPath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59342
|
+
checkTargetSymlink: true
|
|
59343
|
+
});
|
|
60092
59344
|
await rm(targetPath, { force: false, recursive: true });
|
|
60093
59345
|
return {
|
|
60094
59346
|
deleted: true,
|
|
@@ -60096,9 +59348,7 @@ var WorkspaceStore = class {
|
|
|
60096
59348
|
};
|
|
60097
59349
|
}
|
|
60098
59350
|
async deleteConversation(projectId, conversationId) {
|
|
60099
|
-
await this.moveToTrash(
|
|
60100
|
-
this.getConversationFilePath(projectId, conversationId)
|
|
60101
|
-
);
|
|
59351
|
+
await this.moveToTrash(this.getConversationFilePath(projectId, conversationId));
|
|
60102
59352
|
}
|
|
60103
59353
|
async deleteProject(projectId) {
|
|
60104
59354
|
await this.moveToTrash(this.getProjectDirectory(projectId));
|
|
@@ -60112,17 +59362,17 @@ var WorkspaceStore = class {
|
|
|
60112
59362
|
getConversationsDirectory(projectId) {
|
|
60113
59363
|
return path13.join(this.getProjectDirectory(projectId), "conversations");
|
|
60114
59364
|
}
|
|
59365
|
+
getCheckpointsDirectory(projectId) {
|
|
59366
|
+
return path13.join(this.getProjectDirectory(projectId), "checkpoints");
|
|
59367
|
+
}
|
|
59368
|
+
getCheckpointDirectory(projectId, checkpointId) {
|
|
59369
|
+
return path13.join(this.getCheckpointsDirectory(projectId), checkpointId);
|
|
59370
|
+
}
|
|
60115
59371
|
getProjectOutputFilePath(projectId, outputType) {
|
|
60116
|
-
return path13.join(
|
|
60117
|
-
this.getProjectWorkspaceDirectory(projectId),
|
|
60118
|
-
`index.${outputType}`
|
|
60119
|
-
);
|
|
59372
|
+
return path13.join(this.getProjectWorkspaceDirectory(projectId), `index.${outputType}`);
|
|
60120
59373
|
}
|
|
60121
59374
|
getConversationFilePath(projectId, conversationId) {
|
|
60122
|
-
return path13.join(
|
|
60123
|
-
this.getConversationsDirectory(projectId),
|
|
60124
|
-
`${conversationId}.json`
|
|
60125
|
-
);
|
|
59375
|
+
return path13.join(this.getConversationsDirectory(projectId), `${conversationId}.json`);
|
|
60126
59376
|
}
|
|
60127
59377
|
async walkProjectWorkspace(projectId, relativePath, visit2) {
|
|
60128
59378
|
const rootPath = this.getProjectWorkspaceDirectory(projectId);
|
|
@@ -60224,25 +59474,20 @@ var WorkspaceStore = class {
|
|
|
60224
59474
|
if (state.has(relativePath)) {
|
|
60225
59475
|
return state.get(relativePath);
|
|
60226
59476
|
}
|
|
60227
|
-
const absolutePath = await this.resolveProjectWorkspacePath(
|
|
60228
|
-
|
|
60229
|
-
|
|
60230
|
-
|
|
60231
|
-
);
|
|
59477
|
+
const absolutePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59478
|
+
checkTargetSymlink: true,
|
|
59479
|
+
targetMayBeMissing: true
|
|
59480
|
+
});
|
|
60232
59481
|
const content = await readTextFileIfExists(absolutePath);
|
|
60233
59482
|
state.set(relativePath, content);
|
|
60234
59483
|
return content;
|
|
60235
59484
|
};
|
|
60236
59485
|
for (const change of changes) {
|
|
60237
59486
|
const relativePath = normalizeWorkspaceRelativePath(change.path);
|
|
60238
|
-
const absolutePath = await this.resolveProjectWorkspacePath(
|
|
60239
|
-
|
|
60240
|
-
|
|
60241
|
-
|
|
60242
|
-
checkTargetSymlink: true,
|
|
60243
|
-
targetMayBeMissing: change.operation !== "delete"
|
|
60244
|
-
}
|
|
60245
|
-
);
|
|
59487
|
+
const absolutePath = await this.resolveProjectWorkspacePath(projectId, relativePath, {
|
|
59488
|
+
checkTargetSymlink: true,
|
|
59489
|
+
targetMayBeMissing: change.operation !== "delete"
|
|
59490
|
+
});
|
|
60246
59491
|
if (change.operation === "delete") {
|
|
60247
59492
|
const targetStats = await lstat(absolutePath);
|
|
60248
59493
|
const previousContent2 = targetStats.isFile() ? await readCurrentContent(relativePath) : void 0;
|
|
@@ -60313,11 +59558,7 @@ var WorkspaceStore = class {
|
|
|
60313
59558
|
if (!relativeFromWorkspace || relativeFromWorkspace.startsWith("..") || path13.isAbsolute(relativeFromWorkspace)) {
|
|
60314
59559
|
throw new Error(`Project Workspace path escapes workspace: ${relativePath}`);
|
|
60315
59560
|
}
|
|
60316
|
-
await this.assertNoWorkspaceSymlinkPath(
|
|
60317
|
-
workspaceDirectory,
|
|
60318
|
-
relativeFromWorkspace,
|
|
60319
|
-
options
|
|
60320
|
-
);
|
|
59561
|
+
await this.assertNoWorkspaceSymlinkPath(workspaceDirectory, relativeFromWorkspace, options);
|
|
60321
59562
|
return targetPath;
|
|
60322
59563
|
}
|
|
60323
59564
|
async assertNoWorkspaceSymlinkPath(workspaceDirectory, relativeFromWorkspace, options) {
|
|
@@ -60341,6 +59582,17 @@ var WorkspaceStore = class {
|
|
|
60341
59582
|
}
|
|
60342
59583
|
}
|
|
60343
59584
|
};
|
|
59585
|
+
function normalizeProjectRecord(project) {
|
|
59586
|
+
return {
|
|
59587
|
+
...project,
|
|
59588
|
+
projectType: project.projectType ?? "single_html"
|
|
59589
|
+
};
|
|
59590
|
+
}
|
|
59591
|
+
function assertSafeCheckpointId(checkpointId) {
|
|
59592
|
+
if (!/^[A-Za-z0-9_-]+$/.test(checkpointId)) {
|
|
59593
|
+
throw new Error(`Invalid checkpoint id: ${checkpointId}`);
|
|
59594
|
+
}
|
|
59595
|
+
}
|
|
60344
59596
|
|
|
60345
59597
|
// src/services.ts
|
|
60346
59598
|
function createWorkspaceStore(options = {}) {
|
|
@@ -60371,9 +59623,7 @@ function createOwnDesignServices(options = {}) {
|
|
|
60371
59623
|
function sanitizePublicConversation(conversation) {
|
|
60372
59624
|
return {
|
|
60373
59625
|
...conversation,
|
|
60374
|
-
messages: Array.isArray(conversation.messages) ? conversation.messages.map(
|
|
60375
|
-
(message) => sanitizePublicUIMessage(message)
|
|
60376
|
-
) : conversation.messages
|
|
59626
|
+
messages: Array.isArray(conversation.messages) ? conversation.messages.map((message) => sanitizePublicUIMessage(message)) : conversation.messages
|
|
60377
59627
|
};
|
|
60378
59628
|
}
|
|
60379
59629
|
function sanitizePublicUIMessage(message) {
|
|
@@ -60592,10 +59842,14 @@ var ChatRunManager = class {
|
|
|
60592
59842
|
} else {
|
|
60593
59843
|
run.status = "failed";
|
|
60594
59844
|
this.flushPendingLiveChunks(run);
|
|
60595
|
-
this.publish(
|
|
60596
|
-
|
|
60597
|
-
|
|
60598
|
-
|
|
59845
|
+
this.publish(
|
|
59846
|
+
run,
|
|
59847
|
+
{
|
|
59848
|
+
errorText: error51 instanceof Error ? error51.message : "\u751F\u6210\u5931\u8D25\uFF1AUnknown error",
|
|
59849
|
+
type: "error"
|
|
59850
|
+
},
|
|
59851
|
+
{ immediate: true }
|
|
59852
|
+
);
|
|
60599
59853
|
}
|
|
60600
59854
|
} finally {
|
|
60601
59855
|
run.completedAt = run.completedAt ?? (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -60615,10 +59869,7 @@ var ChatRunManager = class {
|
|
|
60615
59869
|
message: getLastAssistantMessage(run.initialMessages),
|
|
60616
59870
|
stream: stream2
|
|
60617
59871
|
})) {
|
|
60618
|
-
run.latestMessages = mergeResponseMessage(
|
|
60619
|
-
run.initialMessages,
|
|
60620
|
-
responseMessage
|
|
60621
|
-
);
|
|
59872
|
+
run.latestMessages = mergeResponseMessage(run.initialMessages, responseMessage);
|
|
60622
59873
|
if (isRunAtResumableBoundary(run)) {
|
|
60623
59874
|
run.safeMessages = run.latestMessages;
|
|
60624
59875
|
run.safeSnapshotChunkIndex = run.safeResumeChunkIndex;
|
|
@@ -60812,25 +60063,19 @@ function createOwnDesignApp(options = {}) {
|
|
|
60812
60063
|
activeConversationId: activeConversation?.id,
|
|
60813
60064
|
activeProject,
|
|
60814
60065
|
activeRun: activeProject ? chatRunManager.getActiveRun(activeProject.id) : void 0,
|
|
60815
|
-
conversations: conversationState.conversations.map(
|
|
60816
|
-
sanitizePublicConversation
|
|
60817
|
-
),
|
|
60066
|
+
conversations: conversationState.conversations.map(sanitizePublicConversation),
|
|
60818
60067
|
projects: projectState.projects,
|
|
60819
60068
|
settings
|
|
60820
60069
|
});
|
|
60821
60070
|
});
|
|
60822
60071
|
app2.get("/api/settings", async (context2) => {
|
|
60823
|
-
return context2.json(
|
|
60824
|
-
await createOwnDesignServices(options).settingsService.getPublicSettings()
|
|
60825
|
-
);
|
|
60072
|
+
return context2.json(await createOwnDesignServices(options).settingsService.getPublicSettings());
|
|
60826
60073
|
});
|
|
60827
60074
|
app2.put("/api/settings", async (context2) => {
|
|
60828
60075
|
try {
|
|
60829
60076
|
const body = await context2.req.json();
|
|
60830
60077
|
return context2.json(
|
|
60831
|
-
await createOwnDesignServices(options).settingsService.updatePublicSettings(
|
|
60832
|
-
body
|
|
60833
|
-
)
|
|
60078
|
+
await createOwnDesignServices(options).settingsService.updatePublicSettings(body)
|
|
60834
60079
|
);
|
|
60835
60080
|
} catch (error51) {
|
|
60836
60081
|
return context2.text(
|
|
@@ -60872,17 +60117,20 @@ function createOwnDesignApp(options = {}) {
|
|
|
60872
60117
|
app2.post("/api/projects", async (context2) => {
|
|
60873
60118
|
const body = await context2.req.json();
|
|
60874
60119
|
const trimmedName = asNonEmptyString(body.name);
|
|
60875
|
-
|
|
60120
|
+
const projectType = parseProjectType(body.projectType);
|
|
60121
|
+
if (!trimmedName || !projectType) {
|
|
60876
60122
|
return context2.json({}, 400);
|
|
60877
60123
|
}
|
|
60124
|
+
if (projectType === "react") {
|
|
60125
|
+
return context2.text("React project type is reserved but not supported yet.", 400);
|
|
60126
|
+
}
|
|
60878
60127
|
const services = createOwnDesignServices(options);
|
|
60879
60128
|
const settings = await services.settingsService.getSettings();
|
|
60880
60129
|
const result = await services.projectService.createProject({
|
|
60881
|
-
defaultConversationTitle: getDefaultConversationTitle(
|
|
60882
|
-
settings.interfaceLanguage
|
|
60883
|
-
),
|
|
60130
|
+
defaultConversationTitle: getDefaultConversationTitle(settings.interfaceLanguage),
|
|
60884
60131
|
name: trimmedName,
|
|
60885
|
-
description: asNonEmptyString(body.description)
|
|
60132
|
+
description: asNonEmptyString(body.description),
|
|
60133
|
+
projectType
|
|
60886
60134
|
});
|
|
60887
60135
|
return context2.json({
|
|
60888
60136
|
href: buildWorkspaceHref({
|
|
@@ -60909,9 +60157,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
60909
60157
|
await createProjectService(options).deleteProject(projectId);
|
|
60910
60158
|
const projectState = await createProjectService(options).getProjectState();
|
|
60911
60159
|
const fallbackProject = projectState.projects[0];
|
|
60912
|
-
const fallbackConversation = fallbackProject ? (await createConversationService(options).getConversationState(
|
|
60913
|
-
fallbackProject.id
|
|
60914
|
-
)).conversations[0] : void 0;
|
|
60160
|
+
const fallbackConversation = fallbackProject ? (await createConversationService(options).getConversationState(fallbackProject.id)).conversations[0] : void 0;
|
|
60915
60161
|
return context2.json({
|
|
60916
60162
|
href: buildWorkspaceHref({
|
|
60917
60163
|
conversationId: fallbackConversation?.id,
|
|
@@ -60934,76 +60180,58 @@ function createOwnDesignApp(options = {}) {
|
|
|
60934
60180
|
})
|
|
60935
60181
|
});
|
|
60936
60182
|
});
|
|
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,
|
|
60183
|
+
app2.post("/api/projects/:projectId/conversations/:conversationId/select", async (context2) => {
|
|
60184
|
+
const projectId = context2.req.param("projectId");
|
|
60185
|
+
const conversationId = context2.req.param("conversationId");
|
|
60186
|
+
await createConversationService(options).switchConversation(projectId, conversationId);
|
|
60187
|
+
return context2.json({
|
|
60188
|
+
href: buildWorkspaceHref({
|
|
60982
60189
|
conversationId,
|
|
60983
|
-
|
|
60984
|
-
)
|
|
60985
|
-
|
|
60986
|
-
|
|
60987
|
-
|
|
60988
|
-
|
|
60989
|
-
|
|
60990
|
-
|
|
60991
|
-
|
|
60190
|
+
projectId
|
|
60191
|
+
})
|
|
60192
|
+
});
|
|
60193
|
+
});
|
|
60194
|
+
app2.patch("/api/projects/:projectId/conversations/:conversationId", async (context2) => {
|
|
60195
|
+
const projectId = context2.req.param("projectId");
|
|
60196
|
+
const conversationId = context2.req.param("conversationId");
|
|
60197
|
+
const body = await context2.req.json();
|
|
60198
|
+
const trimmedTitle = asNonEmptyString(body.title);
|
|
60199
|
+
if (!trimmedTitle) {
|
|
60200
|
+
return context2.json({}, 400);
|
|
60992
60201
|
}
|
|
60993
|
-
|
|
60202
|
+
await createConversationService(options).renameConversation(projectId, conversationId, {
|
|
60203
|
+
title: trimmedTitle
|
|
60204
|
+
});
|
|
60205
|
+
return context2.json({});
|
|
60206
|
+
});
|
|
60207
|
+
app2.delete("/api/projects/:projectId/conversations/:conversationId", async (context2) => {
|
|
60208
|
+
const projectId = context2.req.param("projectId");
|
|
60209
|
+
const conversationId = context2.req.param("conversationId");
|
|
60210
|
+
const currentConversationId = context2.req.query("currentConversationId");
|
|
60211
|
+
const services = createOwnDesignServices(options);
|
|
60212
|
+
const settings = await services.settingsService.getSettings();
|
|
60213
|
+
const remainingConversations = await services.conversationService.deleteConversation(
|
|
60214
|
+
projectId,
|
|
60215
|
+
conversationId,
|
|
60216
|
+
getDefaultConversationTitle(settings.interfaceLanguage)
|
|
60217
|
+
);
|
|
60218
|
+
const nextConversationId = currentConversationId === conversationId ? remainingConversations[0]?.id : currentConversationId;
|
|
60219
|
+
return context2.json({
|
|
60220
|
+
href: buildWorkspaceHref({
|
|
60221
|
+
conversationId: nextConversationId,
|
|
60222
|
+
projectId
|
|
60223
|
+
})
|
|
60224
|
+
});
|
|
60225
|
+
});
|
|
60994
60226
|
app2.post("/api/chat", async (context2) => {
|
|
60995
60227
|
const body = await context2.req.json();
|
|
60996
60228
|
const projectId = asNonEmptyString(body.projectId);
|
|
60997
60229
|
const conversationId = asNonEmptyString(body.conversationId);
|
|
60998
60230
|
const requestedPreviewPath = asNonEmptyString(body.previewPath);
|
|
60999
|
-
const pageEditMode = parsePageEditMode(body.pageEditMode);
|
|
61000
60231
|
const currentUserMessage = createCurrentUserMessage(body.message);
|
|
61001
60232
|
if (!projectId || !conversationId || !currentUserMessage) {
|
|
61002
60233
|
return context2.text("Invalid chat request.", 400);
|
|
61003
60234
|
}
|
|
61004
|
-
if (!pageEditMode) {
|
|
61005
|
-
return context2.text("Invalid page edit mode.", 400);
|
|
61006
|
-
}
|
|
61007
60235
|
const workspaceStore = createWorkspaceStore(options);
|
|
61008
60236
|
const project = await workspaceStore.getProject(projectId);
|
|
61009
60237
|
const previewPath = await resolveExistingPreviewPath(
|
|
@@ -61014,29 +60242,29 @@ function createOwnDesignApp(options = {}) {
|
|
|
61014
60242
|
if (chatRunManager.getActiveRun(projectId)) {
|
|
61015
60243
|
return context2.text("\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4EFB\u52A1\u6B63\u5728\u6267\u884C\u3002", 409);
|
|
61016
60244
|
}
|
|
61017
|
-
|
|
60245
|
+
await workspaceStore.createCheckpoint({
|
|
60246
|
+
id: createCheckpointId(),
|
|
60247
|
+
conversationId,
|
|
60248
|
+
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
61018
60249
|
projectId,
|
|
61019
|
-
|
|
61020
|
-
|
|
60250
|
+
userMessageId: currentUserMessage.id,
|
|
60251
|
+
userPrompt: getUIMessageText(currentUserMessage)
|
|
60252
|
+
});
|
|
60253
|
+
let conversation = await workspaceStore.getConversation(projectId, conversationId);
|
|
61021
60254
|
const storedMessages = normalizeConversationMessages(
|
|
61022
60255
|
conversation.messages
|
|
61023
60256
|
);
|
|
61024
|
-
let messages = [
|
|
61025
|
-
...storedMessages,
|
|
61026
|
-
currentUserMessage
|
|
61027
|
-
];
|
|
60257
|
+
let messages = [...storedMessages, currentUserMessage];
|
|
61028
60258
|
let agentContext;
|
|
61029
60259
|
try {
|
|
61030
60260
|
agentContext = await createDesignPageAgentContext({
|
|
61031
60261
|
currentPreviewPath: previewPath,
|
|
61032
60262
|
frontendTabId: asNonEmptyString(body.frontendTabId),
|
|
61033
60263
|
modelConfigurationId: asNonEmptyString(body.modelConfigurationId),
|
|
61034
|
-
|
|
61035
|
-
pageEditMode,
|
|
60264
|
+
projectType: project.projectType ?? "single_html",
|
|
61036
60265
|
projectId,
|
|
61037
|
-
providerOptionsSelection: parseProviderOptionsSelection(
|
|
61038
|
-
|
|
61039
|
-
),
|
|
60266
|
+
providerOptionsSelection: parseProviderOptionsSelection(body.providerOptionsSelection),
|
|
60267
|
+
settingsPath: options.settingsPath,
|
|
61040
60268
|
workspaceStore
|
|
61041
60269
|
});
|
|
61042
60270
|
} catch (error51) {
|
|
@@ -61046,33 +60274,13 @@ function createOwnDesignApp(options = {}) {
|
|
|
61046
60274
|
);
|
|
61047
60275
|
}
|
|
61048
60276
|
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
|
|
60277
|
+
conversation = await workspaceStore.updateConversation(projectId, conversationId, {
|
|
60278
|
+
...conversation,
|
|
60279
|
+
agentInstructions: buildDesignPageConversationInstructions(agentContext.resources),
|
|
60280
|
+
agentPromptVersion: DESIGN_PAGE_AGENT_PROMPT_VERSION
|
|
61069
60281
|
});
|
|
61070
|
-
} catch (error51) {
|
|
61071
|
-
return context2.text(
|
|
61072
|
-
error51 instanceof Error ? error51.message : "Failed to rewrite user prompt.",
|
|
61073
|
-
500
|
|
61074
|
-
);
|
|
61075
60282
|
}
|
|
60283
|
+
agentContext.agentInstructions = conversation.agentInstructions;
|
|
61076
60284
|
const agent = createDesignPageAgent(agentContext);
|
|
61077
60285
|
let latestStepUsage;
|
|
61078
60286
|
const run = chatRunManager.startRun({
|
|
@@ -61124,6 +60332,49 @@ function createOwnDesignApp(options = {}) {
|
|
|
61124
60332
|
}
|
|
61125
60333
|
return createChatRunStreamResponse(run.stream);
|
|
61126
60334
|
});
|
|
60335
|
+
app2.get("/api/projects/:projectId/checkpoints", async (context2) => {
|
|
60336
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60337
|
+
const projectId = context2.req.param("projectId");
|
|
60338
|
+
await workspaceStore.getProject(projectId);
|
|
60339
|
+
return context2.json(await workspaceStore.listCheckpoints(projectId));
|
|
60340
|
+
});
|
|
60341
|
+
app2.post("/api/projects/:projectId/checkpoints/:checkpointId/restore", async (context2) => {
|
|
60342
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60343
|
+
const projectId = context2.req.param("projectId");
|
|
60344
|
+
const checkpointId = context2.req.param("checkpointId");
|
|
60345
|
+
const body = await readJson(context2.req.raw);
|
|
60346
|
+
const mode = parseCheckpointRestoreMode(body?.mode);
|
|
60347
|
+
if (!mode) {
|
|
60348
|
+
return context2.text("Invalid checkpoint restore request.", 400);
|
|
60349
|
+
}
|
|
60350
|
+
if (chatRunManager.getActiveRun(projectId)) {
|
|
60351
|
+
return context2.text("\u5F53\u524D\u9879\u76EE\u5DF2\u6709\u4EFB\u52A1\u6B63\u5728\u6267\u884C\u3002", 409);
|
|
60352
|
+
}
|
|
60353
|
+
try {
|
|
60354
|
+
const checkpoint = mode === "conversation" ? await workspaceStore.readCheckpoint(projectId, checkpointId) : await workspaceStore.restoreCheckpointFiles(projectId, checkpointId);
|
|
60355
|
+
if (mode === "conversation" || mode === "both") {
|
|
60356
|
+
await restoreCheckpointConversation({
|
|
60357
|
+
options,
|
|
60358
|
+
workspaceStore,
|
|
60359
|
+
checkpoint
|
|
60360
|
+
});
|
|
60361
|
+
}
|
|
60362
|
+
return context2.json({
|
|
60363
|
+
href: buildWorkspaceHref({
|
|
60364
|
+
conversationId: checkpoint.conversationId,
|
|
60365
|
+
projectId
|
|
60366
|
+
})
|
|
60367
|
+
});
|
|
60368
|
+
} catch (error51) {
|
|
60369
|
+
if (isMissingPathError4(error51)) {
|
|
60370
|
+
return context2.text("Checkpoint not found.", 404);
|
|
60371
|
+
}
|
|
60372
|
+
return context2.text(
|
|
60373
|
+
error51 instanceof Error ? error51.message : "Checkpoint restore failed.",
|
|
60374
|
+
400
|
|
60375
|
+
);
|
|
60376
|
+
}
|
|
60377
|
+
});
|
|
61127
60378
|
app2.get("/api/projects/:projectId/runs/active", async (context2) => {
|
|
61128
60379
|
const activeRun = chatRunManager.getActiveRun(context2.req.param("projectId"));
|
|
61129
60380
|
if (!activeRun) {
|
|
@@ -61132,9 +60383,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
61132
60383
|
return context2.json(activeRun);
|
|
61133
60384
|
});
|
|
61134
60385
|
app2.delete("/api/projects/:projectId/runs/active", async (context2) => {
|
|
61135
|
-
const activeRun = chatRunManager.cancelActiveRun(
|
|
61136
|
-
context2.req.param("projectId")
|
|
61137
|
-
);
|
|
60386
|
+
const activeRun = chatRunManager.cancelActiveRun(context2.req.param("projectId"));
|
|
61138
60387
|
if (!activeRun) {
|
|
61139
60388
|
return new Response(null, { status: 204 });
|
|
61140
60389
|
}
|
|
@@ -61143,10 +60392,7 @@ function createOwnDesignApp(options = {}) {
|
|
|
61143
60392
|
app2.get(
|
|
61144
60393
|
"/api/projects/:projectId/conversations/:conversationId/runs/active/stream",
|
|
61145
60394
|
async (context2) => {
|
|
61146
|
-
const afterChunkIndex = Number.parseInt(
|
|
61147
|
-
context2.req.query("after") ?? "0",
|
|
61148
|
-
10
|
|
61149
|
-
);
|
|
60395
|
+
const afterChunkIndex = Number.parseInt(context2.req.query("after") ?? "0", 10);
|
|
61150
60396
|
const stream2 = chatRunManager.subscribeActiveRun(
|
|
61151
60397
|
context2.req.param("projectId"),
|
|
61152
60398
|
context2.req.param("conversationId"),
|
|
@@ -61197,57 +60443,51 @@ function createOwnDesignApp(options = {}) {
|
|
|
61197
60443
|
await manager.release(context2.req.param("projectId"), clientId);
|
|
61198
60444
|
return new Response(null, { status: 204 });
|
|
61199
60445
|
});
|
|
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);
|
|
60446
|
+
app2.post("/api/projects/:projectId/preview-session/heartbeat", async (context2) => {
|
|
60447
|
+
const body = await readJson(context2.req.raw);
|
|
60448
|
+
const clientId = asNonEmptyString(body?.clientId);
|
|
60449
|
+
if (!clientId) {
|
|
60450
|
+
return context2.text("Invalid preview heartbeat request.", 400);
|
|
61216
60451
|
}
|
|
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
|
-
|
|
60452
|
+
const workspaceStore = createWorkspaceStore(options);
|
|
60453
|
+
const manager = getPreviewServerManager(workspaceStore);
|
|
60454
|
+
const session = await manager.heartbeat(
|
|
60455
|
+
context2.req.param("projectId"),
|
|
60456
|
+
clientId,
|
|
60457
|
+
asNonEmptyString(body?.previewPath)
|
|
60458
|
+
);
|
|
60459
|
+
return context2.json(session);
|
|
60460
|
+
});
|
|
60461
|
+
app2.get("/api/projects/:projectId/frontend-capabilities/stream", async (context2) => {
|
|
60462
|
+
const projectId = context2.req.param("projectId");
|
|
60463
|
+
const tabId = context2.req.query("tabId")?.trim();
|
|
60464
|
+
if (!tabId) {
|
|
60465
|
+
return context2.text("Invalid frontend capability stream request.", 400);
|
|
60466
|
+
}
|
|
60467
|
+
await createWorkspaceStore(options).getProject(projectId);
|
|
60468
|
+
context2.header("Cache-Control", "no-cache, no-transform");
|
|
60469
|
+
context2.header("Connection", "keep-alive");
|
|
60470
|
+
context2.header("Content-Type", "text/event-stream; charset=utf-8");
|
|
60471
|
+
return stream(context2, async (streamApi) => {
|
|
60472
|
+
const commandStream = registerFrontendConnection({
|
|
60473
|
+
frontendTabId: tabId,
|
|
60474
|
+
projectId,
|
|
60475
|
+
signal: context2.req.raw.signal
|
|
60476
|
+
});
|
|
60477
|
+
const reader = commandStream.getReader();
|
|
60478
|
+
try {
|
|
60479
|
+
while (true) {
|
|
60480
|
+
const { done, value } = await reader.read();
|
|
60481
|
+
if (done) {
|
|
60482
|
+
break;
|
|
61244
60483
|
}
|
|
61245
|
-
|
|
61246
|
-
reader.releaseLock();
|
|
60484
|
+
await streamApi.write(value);
|
|
61247
60485
|
}
|
|
61248
|
-
}
|
|
61249
|
-
|
|
61250
|
-
|
|
60486
|
+
} finally {
|
|
60487
|
+
reader.releaseLock();
|
|
60488
|
+
}
|
|
60489
|
+
});
|
|
60490
|
+
});
|
|
61251
60491
|
app2.get("/api/projects/:projectId/download", async (context2) => {
|
|
61252
60492
|
const workspaceStore = createWorkspaceStore(options);
|
|
61253
60493
|
const projectId = context2.req.param("projectId");
|
|
@@ -61327,15 +60567,10 @@ async function downloadCurrentHtml(workspaceStore, projectId, previewPath) {
|
|
|
61327
60567
|
return new Response("Invalid download request.", { status: 400 });
|
|
61328
60568
|
}
|
|
61329
60569
|
try {
|
|
61330
|
-
const content = await workspaceStore.readProjectWorkspaceFileBuffer(
|
|
61331
|
-
projectId,
|
|
61332
|
-
previewPath
|
|
61333
|
-
);
|
|
60570
|
+
const content = await workspaceStore.readProjectWorkspaceFileBuffer(projectId, previewPath);
|
|
61334
60571
|
return new Response(content, {
|
|
61335
60572
|
headers: {
|
|
61336
|
-
"Content-Disposition": createAttachmentDisposition(
|
|
61337
|
-
path14.basename(previewPath)
|
|
61338
|
-
),
|
|
60573
|
+
"Content-Disposition": createAttachmentDisposition(path14.basename(previewPath)),
|
|
61339
60574
|
"Content-Type": "text/html; charset=utf-8"
|
|
61340
60575
|
},
|
|
61341
60576
|
status: 200
|
|
@@ -61348,15 +60583,10 @@ async function downloadWorkspaceZip(workspaceStore, projectId) {
|
|
|
61348
60583
|
let tempDirectory;
|
|
61349
60584
|
try {
|
|
61350
60585
|
const project = await workspaceStore.getProject(projectId);
|
|
61351
|
-
tempDirectory = await mkdtemp(
|
|
61352
|
-
path14.join(os6.tmpdir(), "owndesign-project-download-")
|
|
61353
|
-
);
|
|
60586
|
+
tempDirectory = await mkdtemp(path14.join(os6.tmpdir(), "owndesign-project-download-"));
|
|
61354
60587
|
const zipPath = path14.join(tempDirectory, "workspace.zip");
|
|
61355
60588
|
await writeWorkspaceZip(workspaceStore, projectId, zipPath);
|
|
61356
|
-
const [zipStats, zipBuffer] = await Promise.all([
|
|
61357
|
-
stat4(zipPath),
|
|
61358
|
-
readFile5(zipPath)
|
|
61359
|
-
]);
|
|
60589
|
+
const [zipStats, zipBuffer] = await Promise.all([stat4(zipPath), readFile5(zipPath)]);
|
|
61360
60590
|
await rm2(tempDirectory, { force: true, recursive: true });
|
|
61361
60591
|
tempDirectory = void 0;
|
|
61362
60592
|
return new Response(zipBuffer, {
|
|
@@ -61391,10 +60621,7 @@ async function writeWorkspaceZip(workspaceStore, projectId, zipPath) {
|
|
|
61391
60621
|
if (entry.type !== "file") {
|
|
61392
60622
|
continue;
|
|
61393
60623
|
}
|
|
61394
|
-
const content = await workspaceStore.readProjectWorkspaceFileBuffer(
|
|
61395
|
-
projectId,
|
|
61396
|
-
entry.path
|
|
61397
|
-
);
|
|
60624
|
+
const content = await workspaceStore.readProjectWorkspaceFileBuffer(projectId, entry.path);
|
|
61398
60625
|
zipFile.addBuffer(content, entry.path);
|
|
61399
60626
|
}
|
|
61400
60627
|
zipFile.end();
|
|
@@ -61448,16 +60675,13 @@ async function readJson(request) {
|
|
|
61448
60675
|
}
|
|
61449
60676
|
}
|
|
61450
60677
|
function createCurrentUserMessage(value) {
|
|
61451
|
-
if (!
|
|
60678
|
+
if (!isRecord3(value)) {
|
|
61452
60679
|
return void 0;
|
|
61453
60680
|
}
|
|
61454
60681
|
const id = asNonEmptyString(value.id);
|
|
61455
60682
|
const text2 = typeof value.text === "string" ? value.text : "";
|
|
61456
60683
|
const files = Array.isArray(value.files) ? value.files.filter(isFileUIPart2) : [];
|
|
61457
|
-
const parts = [
|
|
61458
|
-
...text2 ? [{ text: text2, type: "text" }] : [],
|
|
61459
|
-
...files
|
|
61460
|
-
];
|
|
60684
|
+
const parts = [...text2 ? [{ text: text2, type: "text" }] : [], ...files];
|
|
61461
60685
|
if (!id || parts.length === 0) {
|
|
61462
60686
|
return void 0;
|
|
61463
60687
|
}
|
|
@@ -61468,93 +60692,9 @@ function createCurrentUserMessage(value) {
|
|
|
61468
60692
|
};
|
|
61469
60693
|
}
|
|
61470
60694
|
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";
|
|
60695
|
+
return isRecord3(value) && value.type === "file";
|
|
61556
60696
|
}
|
|
61557
|
-
function
|
|
60697
|
+
function isRecord3(value) {
|
|
61558
60698
|
return typeof value === "object" && value !== null;
|
|
61559
60699
|
}
|
|
61560
60700
|
async function resolveExistingPreviewPath(workspaceStore, projectId, previewPath) {
|
|
@@ -61567,8 +60707,20 @@ async function resolveExistingPreviewPath(workspaceStore, projectId, previewPath
|
|
|
61567
60707
|
function asNonEmptyString(value) {
|
|
61568
60708
|
return typeof value === "string" && value.trim() ? value.trim() : void 0;
|
|
61569
60709
|
}
|
|
60710
|
+
function parseProjectType(value) {
|
|
60711
|
+
if (value === void 0 || value === null || value === "") {
|
|
60712
|
+
return "single_html";
|
|
60713
|
+
}
|
|
60714
|
+
if (value === "single_html" || value === "react") {
|
|
60715
|
+
return value;
|
|
60716
|
+
}
|
|
60717
|
+
return void 0;
|
|
60718
|
+
}
|
|
60719
|
+
function parseCheckpointRestoreMode(value) {
|
|
60720
|
+
return value === "files" || value === "conversation" || value === "both" ? value : void 0;
|
|
60721
|
+
}
|
|
61570
60722
|
function parseProviderOptionsSelection(value) {
|
|
61571
|
-
if (!
|
|
60723
|
+
if (!isRecord3(value)) {
|
|
61572
60724
|
return void 0;
|
|
61573
60725
|
}
|
|
61574
60726
|
const deepseek2 = parseDeepSeekThinkingMode(value.deepseek);
|
|
@@ -61581,6 +60733,36 @@ function parseProviderOptionsSelection(value) {
|
|
|
61581
60733
|
...deepseek2 ? { deepseek: deepseek2 } : {}
|
|
61582
60734
|
};
|
|
61583
60735
|
}
|
|
60736
|
+
function createCheckpointId() {
|
|
60737
|
+
const id = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : `${Date.now()}-${Math.random().toString(36).slice(2)}`;
|
|
60738
|
+
return `cp_${id.replace(/[^A-Za-z0-9_-]/g, "_")}`;
|
|
60739
|
+
}
|
|
60740
|
+
async function restoreCheckpointConversation({
|
|
60741
|
+
checkpoint,
|
|
60742
|
+
options,
|
|
60743
|
+
workspaceStore
|
|
60744
|
+
}) {
|
|
60745
|
+
const conversation = await workspaceStore.getConversation(
|
|
60746
|
+
checkpoint.projectId,
|
|
60747
|
+
checkpoint.conversationId
|
|
60748
|
+
);
|
|
60749
|
+
const messages = normalizeConversationMessages(conversation.messages);
|
|
60750
|
+
const targetIndex = messages.findIndex((message) => message.id === checkpoint.userMessageId);
|
|
60751
|
+
if (targetIndex < 0) {
|
|
60752
|
+
throw new Error("Checkpoint user message was not found in the conversation.");
|
|
60753
|
+
}
|
|
60754
|
+
const nextMessages = messages.slice(0, targetIndex);
|
|
60755
|
+
const settings = await createOwnDesignServices(options).settingsService.getSettings();
|
|
60756
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
60757
|
+
const lastMessage = nextMessages.at(-1);
|
|
60758
|
+
await workspaceStore.updateConversation(checkpoint.projectId, checkpoint.conversationId, {
|
|
60759
|
+
...conversation,
|
|
60760
|
+
lastMessageAt: lastMessage ? timestamp : void 0,
|
|
60761
|
+
messages: nextMessages,
|
|
60762
|
+
title: !conversation.titleManuallySet && nextMessages.length === 0 ? getDefaultConversationTitle(settings.interfaceLanguage) : conversation.title,
|
|
60763
|
+
updatedAt: timestamp
|
|
60764
|
+
});
|
|
60765
|
+
}
|
|
61584
60766
|
|
|
61585
60767
|
// src/index.ts
|
|
61586
60768
|
var DEFAULT_HOST = "127.0.0.1";
|