@maudecode/talaria-web 1.12.1 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +22 -0
- package/_release.json +4 -4
- package/dist/api/sessions-router.d.ts +5 -0
- package/dist/api/sessions-router.js +4 -0
- package/dist/api/sessions-router.js.map +1 -1
- package/dist/api/settings-router.d.ts +10 -0
- package/dist/api/tools-router.d.ts +114 -0
- package/dist/api/tools-router.js +10 -8
- package/dist/api/tools-router.js.map +1 -1
- package/dist/app.d.ts +129 -0
- package/dist/auth/passkeys.js +1 -1
- package/dist/auth/passkeys.js.map +1 -1
- package/dist/cli/ctl.d.ts +6 -3
- package/dist/cli/ctl.js +25 -16
- package/dist/cli/ctl.js.map +1 -1
- package/dist/cli/launcher.js +2 -2
- package/dist/cli/launcher.js.map +1 -1
- package/dist/mcp/server.js +1 -1
- package/dist/mcp/server.js.map +1 -1
- package/dist/runtime.js +3 -2
- package/dist/runtime.js.map +1 -1
- package/dist/server.js +4 -1
- package/dist/server.js.map +1 -1
- package/dist/sessions/export.js +1 -1
- package/dist/sessions/export.js.map +1 -1
- package/dist/sessions/journal.d.ts +27 -12
- package/dist/sessions/journal.js +115 -40
- package/dist/sessions/journal.js.map +1 -1
- package/dist/sessions/merge.d.ts +7 -0
- package/dist/sessions/merge.js +11 -0
- package/dist/sessions/merge.js.map +1 -1
- package/dist/sessions/relay.d.ts +11 -1
- package/dist/sessions/relay.js +62 -14
- package/dist/sessions/relay.js.map +1 -1
- package/dist/sessions/service.js +3 -3
- package/dist/sessions/service.js.map +1 -1
- package/dist/sessions/turn.js +4 -4
- package/dist/sessions/turn.js.map +1 -1
- package/dist/settings.js +2 -0
- package/dist/settings.js.map +1 -1
- package/dist/tools/hygiene.d.ts +11 -3
- package/dist/tools/hygiene.js +32 -14
- package/dist/tools/hygiene.js.map +1 -1
- package/dist/tools/update-notifications.d.ts +15 -2
- package/dist/tools/update-notifications.js +28 -8
- package/dist/tools/update-notifications.js.map +1 -1
- package/dist/tools/updates.d.ts +6 -15
- package/dist/tools/updates.js +16 -319
- package/dist/tools/updates.js.map +1 -1
- package/package.json +3 -2
- package/static/dist/FILES.txt +120 -119
- package/static/dist/THIRD_PARTY_LICENSES.md +5170 -0
- package/static/dist/assets/AppShell-haqi9qzu.js +1 -0
- package/static/dist/assets/ChatPage-hjyu2g64.js +22 -0
- package/static/dist/assets/HubRoute-gkd8o1vg.js +2 -0
- package/static/dist/assets/{Markdown-j2hlu30v.js → Markdown-emii55o0.js} +7 -7
- package/static/dist/assets/RightPanel-o73y98dn.js +1 -0
- package/static/dist/assets/Select-jld3yeni.js +1 -0
- package/static/dist/assets/SessionListPanel-d3qx4ric.js +1 -0
- package/static/dist/assets/{SettingsLayout-b0idn649.js → SettingsLayout-lnn2wo2s.js} +1 -1
- package/static/dist/assets/States-e5hv6gdh.js +1 -0
- package/static/dist/assets/{Toaster-h49pk1hy.js → Toaster-c4jq1i26.js} +1 -1
- package/static/dist/assets/_app-bnip2pjg.js +1 -0
- package/static/dist/assets/_app.ext._extensionId-egptzrfy.js +1 -0
- package/static/dist/assets/_app.index-vdz13ul5.js +1 -0
- package/static/dist/assets/_app.insights-lgjshsba.js +1 -0
- package/static/dist/assets/_app.kanban-c18cjrpz.js +1 -0
- package/static/dist/assets/_app.logs-ezhojgeg.js +1 -0
- package/static/dist/assets/_app.memory-i00paisv.js +1 -0
- package/static/dist/assets/_app.profiles-kd02bwjx.js +1 -0
- package/static/dist/assets/{_app.session._sessionId-hhpcqih4.js → _app.session._sessionId-m6nx9g8t.js} +1 -1
- package/static/dist/assets/_app.settings-giaudkuk.js +1 -0
- package/static/dist/assets/_app.settings._section-k4qtlexk.js +1 -0
- package/static/dist/assets/_app.skills-bby2uvl8.js +1 -0
- package/static/dist/assets/_app.tasks-1kz9bosm.js +2 -0
- package/static/dist/assets/_app.todos-izjdbkm2.js +1 -0
- package/static/dist/assets/_app.workspaces-lfh2kw7s.js +1 -0
- package/static/dist/assets/{abnfDiagram-VCTEODGH-egykbz8h.js → abnfDiagram-VCTEODGH-kejgxpil.js} +1 -1
- package/static/dist/assets/architecture-7GRP2DOG-b4u9z1w3.js +1 -0
- package/static/dist/assets/{architectureDiagram-5GKGNRK7-b2e0wk3y.js → architectureDiagram-5GKGNRK7-hqnf84fc.js} +1 -1
- package/static/dist/assets/{blockDiagram-I7D4REHJ-i3cq67dn.js → blockDiagram-I7D4REHJ-l1466a7j.js} +1 -1
- package/static/dist/assets/{c4Diagram-7LVT6UL2-lg1p1s7a.js → c4Diagram-7LVT6UL2-gg3aq3sr.js} +1 -1
- package/static/dist/assets/channel-o77ioktg.js +1 -0
- package/static/dist/assets/{chunk-4HAMMTFA-i0s1s7zi.js → chunk-4HAMMTFA-oalgz5l8.js} +1 -1
- package/static/dist/assets/{chunk-75Z2AOVW-kwinpapo.js → chunk-75Z2AOVW-babmzhdg.js} +1 -1
- package/static/dist/assets/{chunk-DU6HZSFF-hb8qrbc3.js → chunk-DU6HZSFF-lagu350c.js} +3 -3
- package/static/dist/assets/{chunk-F27PBJKO-dy2tqtcs.js → chunk-F27PBJKO-gjh2tqif.js} +1 -1
- package/static/dist/assets/{chunk-GMAD6QVW-fqox5yvt.js → chunk-GMAD6QVW-ipdgja5c.js} +1 -1
- package/static/dist/assets/{chunk-GVQU2GXP-bo3x6ze4.js → chunk-GVQU2GXP-j8wkn1at.js} +1 -1
- package/static/dist/assets/{chunk-IMKFNOWR-nxs6rrcq.js → chunk-IMKFNOWR-k00laqyk.js} +1 -1
- package/static/dist/assets/{chunk-L3NEJ4N5-f9yeq1fi.js → chunk-L3NEJ4N5-fju6xqj4.js} +1 -1
- package/static/dist/assets/{chunk-OSK3NFVY-c7df44qv.js → chunk-OSK3NFVY-bi6widqt.js} +1 -1
- package/static/dist/assets/{chunk-P2QGCYS3-eyjzf5o5.js → chunk-P2QGCYS3-czr4tebv.js} +1 -1
- package/static/dist/assets/{chunk-POPQ4Y6H-iy3hp9rc.js → chunk-POPQ4Y6H-ktdhn67w.js} +1 -1
- package/static/dist/assets/{chunk-PWAF6VOD-co2yoefz.js → chunk-PWAF6VOD-ii4dsu0d.js} +1 -1
- package/static/dist/assets/{chunk-SHT3W25Y-obzqmn9k.js → chunk-SHT3W25Y-fpwk3xxp.js} +1 -1
- package/static/dist/assets/{chunk-SVP7TREG-hqwdo6vt.js → chunk-SVP7TREG-k0jrvhei.js} +1 -1
- package/static/dist/assets/{chunk-TICWLB2K-l8t1mdfd.js → chunk-TICWLB2K-nkqv9ot0.js} +1 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-f5rvod26.js +1 -0
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-f5rvod26.js +1 -0
- package/static/dist/assets/{copied-hurn8vn4.js → copied-gpchexqu.js} +1 -1
- package/static/dist/assets/{cynefin-OW5HDTMX-ngx2ihay.js → cynefin-OW5HDTMX-lqxt8rs3.js} +1 -1
- package/static/dist/assets/{cynefinDiagram-5FMLGOSQ-fiyooys3.js → cynefinDiagram-5FMLGOSQ-j9eqovf5.js} +1 -1
- package/static/dist/assets/{dagre-GXQ25YYZ-fctryel6.js → dagre-GXQ25YYZ-m9agobjm.js} +1 -1
- package/static/dist/assets/{diagram-S7CK7UJ4-m27jopok.js → diagram-S7CK7UJ4-itodc50c.js} +1 -1
- package/static/dist/assets/{diagram-UQ7AKVKN-ojgkbmp4.js → diagram-UQ7AKVKN-n1h2t4ah.js} +1 -1
- package/static/dist/assets/{diagram-VSXAHHWV-gfafpgyj.js → diagram-VSXAHHWV-lvtvm9bj.js} +1 -1
- package/static/dist/assets/{diagram-VX7I27RA-daobicg4.js → diagram-VX7I27RA-cgas58sy.js} +1 -1
- package/static/dist/assets/{diagram-Z3DM3KII-mi475zvk.js → diagram-Z3DM3KII-d0aeps1q.js} +1 -1
- package/static/dist/assets/{ebnfDiagram-PWID7BFC-daf4zvsy.js → ebnfDiagram-PWID7BFC-md345fyq.js} +1 -1
- package/static/dist/assets/endpoints-e58saih3.js +9 -0
- package/static/dist/assets/{erDiagram-RLTQ6QDP-gxfhxvfp.js → erDiagram-RLTQ6QDP-i4rua63b.js} +1 -1
- package/static/dist/assets/eventmodeling-NTZA5JFV-bn3fjsaq.js +1 -0
- package/static/dist/assets/flowDiagram-HODETNUW-li70d120.js +1 -0
- package/static/dist/assets/{ganttDiagram-EL5Y4UJY-k3208e0p.js → ganttDiagram-EL5Y4UJY-geqx7zgl.js} +1 -1
- package/static/dist/assets/{gitGraph-4MIJSDKK-gjuhj4zk.js → gitGraph-4MIJSDKK-leoq0z8t.js} +1 -1
- package/static/dist/assets/{gitGraphDiagram-WWUBYQGX-jglxvux1.js → gitGraphDiagram-WWUBYQGX-llrlxfha.js} +1 -1
- package/static/dist/assets/{highlighted-body-KPVGNVTW-gh24xc9c.js → highlighted-body-KPVGNVTW-kq2cnw6q.js} +1 -1
- package/static/dist/assets/index-f9bzglkn.js +11 -0
- package/static/dist/assets/index-gkh7kum4.css +2 -0
- package/static/dist/assets/{info-A6RAGUB7-huf0xaoq.js → info-A6RAGUB7-lkly4xj6.js} +1 -1
- package/static/dist/assets/{infoDiagram-27XIBGKW-jk3n96ix.js → infoDiagram-27XIBGKW-oo7kdyte.js} +1 -1
- package/static/dist/assets/{ishikawaDiagram-5VMMS53U-o95uo5dx.js → ishikawaDiagram-5VMMS53U-hq6jf374.js} +1 -1
- package/static/dist/assets/{journeyDiagram-3NMN7TZE-h5ye2l70.js → journeyDiagram-3NMN7TZE-is03ntb0.js} +1 -1
- package/static/dist/assets/{kanban-definition-UXKFOSKX-lgrpk5yi.js → kanban-definition-UXKFOSKX-jmerizqb.js} +1 -1
- package/static/dist/assets/{lazyRouteComponent-owywngyt.js → lazyRouteComponent-b1h2ykmb.js} +1 -1
- package/static/dist/assets/{line-cihmc0pn.js → line-laaa8h99.js} +1 -1
- package/static/dist/assets/link-d8f0788e.js +1 -0
- package/static/dist/assets/login-llkohrcg.js +1 -0
- package/static/dist/assets/mermaid-HWGCJPDP-id0ffk2r.js +1 -0
- package/static/dist/assets/{mermaid-parser.core-d1609aga.js → mermaid-parser.core-ix4junux.js} +3 -3
- package/static/dist/assets/{mindmap-definition-YA3MSWOX-lbvtir31.js → mindmap-definition-YA3MSWOX-o0e0adl1.js} +1 -1
- package/static/dist/assets/onboarding-lx0d6b38.js +1 -0
- package/static/dist/assets/{packet-AYTQ26CC-o4cp5z3k.js → packet-AYTQ26CC-kl8pwsyg.js} +1 -1
- package/static/dist/assets/{pegDiagram-XKGWAZYB-e8xqu1qj.js → pegDiagram-XKGWAZYB-bbqn9jo4.js} +1 -1
- package/static/dist/assets/{pie-WAS4IAKB-hm9icuov.js → pie-WAS4IAKB-cpyo8bkr.js} +1 -1
- package/static/dist/assets/{pieDiagram-E7YTZNPT-hj96x7hn.js → pieDiagram-E7YTZNPT-pelug34f.js} +1 -1
- package/static/dist/assets/{quadrantDiagram-AXDQQJYC-80utbxhm.js → quadrantDiagram-AXDQQJYC-jds4jmr5.js} +1 -1
- package/static/dist/assets/{radar-RG4KPBEZ-k39b6100.js → radar-RG4KPBEZ-e02oxnvd.js} +1 -1
- package/static/dist/assets/{railroad-74A4TZTK-ewyqz67j.js → railroad-74A4TZTK-kz3delwo.js} +1 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-l13ped2z.js +1 -0
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-c7rg3g4g.js +1 -0
- package/static/dist/assets/railroad-peg-WCYAUIDC-od0b8niq.js +1 -0
- package/static/dist/assets/{railroadDiagram-O6MQD6OU-iwv9dby8.js → railroadDiagram-O6MQD6OU-jgroj2ew.js} +1 -1
- package/static/dist/assets/{refresh-cw-hjzomwlo.js → refresh-cw-k7yxjdn3.js} +1 -1
- package/static/dist/assets/{requirementDiagram-BXWQKSXE-cdgh5jha.js → requirementDiagram-BXWQKSXE-m4az5e0j.js} +1 -1
- package/static/dist/assets/{sankeyDiagram-P5KCCOFB-dbu6p97m.js → sankeyDiagram-P5KCCOFB-vlryqiv3.js} +1 -1
- package/static/dist/assets/{saved-feqhycco.js → saved-brdfjjnw.js} +1 -1
- package/static/dist/assets/{search-n3jdc20p.js → search-gt2ueyvg.js} +1 -1
- package/static/dist/assets/{sequenceDiagram-WJ2MYXX4-b0wchifg.js → sequenceDiagram-WJ2MYXX4-fr8hrpql.js} +1 -1
- package/static/dist/assets/{settings_section_extensions_title-mtyviexd.js → settings_section_extensions_title-l0zodj0b.js} +1 -1
- package/static/dist/assets/share._token-oyjv046r.js +2 -0
- package/static/dist/assets/{sliders-horizontal-i1lseyg0.js → sliders-horizontal-gcgscv8r.js} +1 -1
- package/static/dist/assets/{stateDiagram-D77RDMKH-mb4b38xh.js → stateDiagram-D77RDMKH-bg548iyr.js} +1 -1
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-j5v40qih.js +1 -0
- package/static/dist/assets/{swimlanes-42K2YHIH-ofrpfwj0.js → swimlanes-42K2YHIH-hk5z3efh.js} +1 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-grzefo9c.js +8 -0
- package/static/dist/assets/tabBuild-idliyw9f.js +56 -0
- package/static/dist/assets/{timeline-definition-24CTP7MA-hlw0jg6o.js → timeline-definition-24CTP7MA-olvknr62.js} +1 -1
- package/static/dist/assets/todoStore-j4c2xq0b.js +1 -0
- package/static/dist/assets/{treeView-Q6P3EWNA-d93wr19c.js → treeView-Q6P3EWNA-ovvjsxtf.js} +1 -1
- package/static/dist/assets/{treemap-WGGIJYW6-g7ezdedz.js → treemap-WGGIJYW6-ggkipj59.js} +1 -1
- package/static/dist/assets/{untitled-mqxhd1eh.js → untitled-c8ydw0bu.js} +1 -1
- package/static/dist/assets/useForm-kd759sjk.js +1 -0
- package/static/dist/assets/useLocale-hds4xmja.js +1 -0
- package/static/dist/assets/{useParams-gpbjxj8s.js → useParams-katwvzil.js} +1 -1
- package/static/dist/assets/{useSearch-bhdptos7.js → useSearch-c70sgau1.js} +1 -1
- package/static/dist/assets/{vennDiagram-4TSXK5OY-m5vgeba5.js → vennDiagram-4TSXK5OY-hzld7zt7.js} +1 -1
- package/static/dist/assets/{wardley-WFR3VGLG-gpao9bxv.js → wardley-WFR3VGLG-hxkeoms8.js} +1 -1
- package/static/dist/assets/{wardleyDiagram-VM6X3IG4-g2yzwshm.js → wardleyDiagram-VM6X3IG4-ljh90mb1.js} +1 -1
- package/static/dist/assets/{xychartDiagram-S5SC5T6Z-itakhpic.js → xychartDiagram-S5SC5T6Z-mnuaes03.js} +1 -1
- package/static/dist/index.html +1 -1
- package/static/dist/manifest.webmanifest +1 -1
- package/static/dist/sw.js +1 -1
- package/static/dist/assets/AppShell-m4w420jl.js +0 -1
- package/static/dist/assets/ChatPage-cuqcnisv.js +0 -20
- package/static/dist/assets/HubRoute-hqgqtm35.js +0 -2
- package/static/dist/assets/RightPanel-oid5q557.js +0 -1
- package/static/dist/assets/Select-ot2zr0il.js +0 -1
- package/static/dist/assets/SessionListPanel-o3sgjnrq.js +0 -1
- package/static/dist/assets/States-htz1oee5.js +0 -1
- package/static/dist/assets/_app-h7eaezs7.js +0 -1
- package/static/dist/assets/_app.ext._extensionId-h8oaqzsj.js +0 -1
- package/static/dist/assets/_app.index-xinao3xh.js +0 -1
- package/static/dist/assets/_app.insights-cxplvhkm.js +0 -1
- package/static/dist/assets/_app.kanban-hhli8h0h.js +0 -1
- package/static/dist/assets/_app.logs-f6srwjfl.js +0 -1
- package/static/dist/assets/_app.memory-lntcea85.js +0 -1
- package/static/dist/assets/_app.profiles-lftyp6of.js +0 -1
- package/static/dist/assets/_app.settings-rs93zpvw.js +0 -1
- package/static/dist/assets/_app.settings._section-nafqsbwm.js +0 -1
- package/static/dist/assets/_app.skills-jzoi1ivd.js +0 -1
- package/static/dist/assets/_app.tasks-ijphsw56.js +0 -2
- package/static/dist/assets/_app.todos-emyh8inv.js +0 -1
- package/static/dist/assets/_app.workspaces-fwr1cum8.js +0 -1
- package/static/dist/assets/architecture-7GRP2DOG-l6y92mbn.js +0 -1
- package/static/dist/assets/channel-gq8cwu71.js +0 -1
- package/static/dist/assets/classDiagram-ZZMXUADV-fg9sc5r8.js +0 -1
- package/static/dist/assets/classDiagram-v2-VYDZK3BY-fg9sc5r8.js +0 -1
- package/static/dist/assets/endpoints-cyjhnrbn.js +0 -64
- package/static/dist/assets/eventmodeling-NTZA5JFV-manga0bq.js +0 -1
- package/static/dist/assets/flowDiagram-HODETNUW-bpt13uny.js +0 -1
- package/static/dist/assets/index-gsg78cb4.css +0 -2
- package/static/dist/assets/index-jb47los5.js +0 -11
- package/static/dist/assets/link-ib4prsn5.js +0 -1
- package/static/dist/assets/login-g063apx6.js +0 -1
- package/static/dist/assets/mermaid-HWGCJPDP-okd1mnvj.js +0 -1
- package/static/dist/assets/onboarding-ngw0x0pr.js +0 -1
- package/static/dist/assets/railroad-abnf-HS5TGJTU-dx2q0evz.js +0 -1
- package/static/dist/assets/railroad-ebnf-LZEXJU2U-l8xt49t5.js +0 -1
- package/static/dist/assets/railroad-peg-WCYAUIDC-kuxha9yz.js +0 -1
- package/static/dist/assets/share._token-cwov8uqh.js +0 -2
- package/static/dist/assets/stateDiagram-v2-MP3YSRHH-cn1fnqrg.js +0 -1
- package/static/dist/assets/swimlanesDiagram-VR7AAH4N-d652ummv.js +0 -8
- package/static/dist/assets/todoStore-mfy9lpio.js +0 -1
- package/static/dist/assets/useForm-hh33yrwa.js +0 -1
- package/static/dist/assets/useLocale-cr30vl7r.js +0 -1
- package/static/dist/assets/useSelector-f2aak1ol.js +0 -1
package/dist/tools/updates.js
CHANGED
|
@@ -13,7 +13,7 @@
|
|
|
13
13
|
import { readCapped } from '../http/capped.js';
|
|
14
14
|
import { execFile } from 'node:child_process';
|
|
15
15
|
import { createHash } from 'node:crypto';
|
|
16
|
-
import { copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync,
|
|
16
|
+
import { copyFileSync, existsSync, lstatSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
|
|
17
17
|
import { delimiter, dirname, isAbsolute, join, resolve } from 'node:path';
|
|
18
18
|
import { dict } from '../config/agent-config.js';
|
|
19
19
|
import { validateReleaseInfo } from '../release.js';
|
|
@@ -23,9 +23,6 @@ export const REPOSITORY_URL = `https://github.com/${REPOSITORY}`;
|
|
|
23
23
|
export const API_ROOT = `https://api.github.com/repos/${REPOSITORY}`;
|
|
24
24
|
/** Anchored paths work from both the git root and Web's nested working directory. */
|
|
25
25
|
export const WEB_UPDATE_PATHS = [':(top)web/', ':(top)contracts/'];
|
|
26
|
-
/** Relative to the git root: the release stamp and the blobs it is verified against. */
|
|
27
|
-
export const RELEASE_STAMP = 'web/_release.json';
|
|
28
|
-
const RELEASE_BLOBS = ['sidecar/agent_dependency.json', 'contract_versions.json'];
|
|
29
26
|
export const CACHE_TTL_S = 1800;
|
|
30
27
|
export const AUTO_UPDATE_INTERVAL_MS = 5 * 60_000;
|
|
31
28
|
export const RESTART_MAX_WAIT_S = 300;
|
|
@@ -58,15 +55,9 @@ export const runGit = (args, cwd, timeoutMs = 10_000) => new Promise((done) => {
|
|
|
58
55
|
done({ out: err || out || `git exited with status ${String(e.code)}`, ok: false });
|
|
59
56
|
});
|
|
60
57
|
});
|
|
61
|
-
/** The steps a source checkout needs after its files change (README "From a source checkout"), run from `<root>/web`. */
|
|
62
|
-
export const WEB_BUILD_STEPS = [
|
|
63
|
-
['ci', '--workspace', 'packages/contracts', '--workspace', 'packages/server', '--include=dev'],
|
|
64
|
-
['run', 'build', '--workspace', 'packages/contracts'],
|
|
65
|
-
['run', 'build', '--workspace', 'packages/server'],
|
|
66
|
-
];
|
|
67
58
|
export const WEB_BUILD_TIMEOUT_MS = 10 * 60_000;
|
|
68
|
-
/**
|
|
69
|
-
export const
|
|
59
|
+
/** Source checkouts are contributor-only: they update with git, and the updater never mutates them (TAL-379). */
|
|
60
|
+
export const CONTRIBUTOR_CHECKOUT_MESSAGE = 'This is a contributor source checkout. Update it with git and rebuild Web (see web/README.md); only npm installs update automatically.';
|
|
70
61
|
const runNpmCommand = (args, cwd, timeoutMs, env) => new Promise((done) => {
|
|
71
62
|
// Prefer the npm beside the running node so a supervisor started with an absolute node path still finds it.
|
|
72
63
|
const beside = join(dirname(process.execPath), 'npm');
|
|
@@ -88,20 +79,7 @@ const runNpmCommand = (args, cwd, timeoutMs, env) => new Promise((done) => {
|
|
|
88
79
|
done({ out: (stderr.trim() || stdout.trim() || `npm exited with status ${String(e.code)}`).slice(-4000), ok: false });
|
|
89
80
|
});
|
|
90
81
|
});
|
|
91
|
-
export const runNpm = (args, cwd, timeoutMs) => runNpmCommand(args, cwd, timeoutMs, { ...process.env, NODE_ENV: 'development' });
|
|
92
82
|
export const runPackageNpm = (args, cwd, timeoutMs) => runNpmCommand(args, cwd, timeoutMs, process.env);
|
|
93
|
-
/** Install and build the checkout's Web packages; null on success, else the message for the caller. */
|
|
94
|
-
async function buildWeb(root, build) {
|
|
95
|
-
const cwd = join(root, 'web');
|
|
96
|
-
for (const step of WEB_BUILD_STEPS) {
|
|
97
|
-
const result = await build(step, cwd, WEB_BUILD_TIMEOUT_MS);
|
|
98
|
-
if (!result.ok)
|
|
99
|
-
return `\`npm ${step.join(' ')}\` failed: ${result.out || 'unknown error'}`;
|
|
100
|
-
}
|
|
101
|
-
if (!existsSync(join(cwd, WEB_SERVER_ENTRY)))
|
|
102
|
-
return `build finished without producing ${WEB_SERVER_ENTRY}`;
|
|
103
|
-
return null;
|
|
104
|
-
}
|
|
105
83
|
export const isGitLockError = (output) => { const l = output.toLowerCase(); return GIT_LOCK_SIGNATURES.some((s) => l.includes(s)); };
|
|
106
84
|
/** Python `_sanitize_git_diagnostic`: strip URL userinfo, GitHub token shapes, and secret query values. */
|
|
107
85
|
export function sanitizeGitDiagnostic(output, limit = 300) {
|
|
@@ -126,11 +104,6 @@ async function fetchWithRetry(git, args, cwd, timeoutMs) {
|
|
|
126
104
|
await new Promise((r) => setTimeout(r, FETCH_RETRY_MS));
|
|
127
105
|
return git(args, cwd, timeoutMs);
|
|
128
106
|
}
|
|
129
|
-
function gitFailure(out, message) {
|
|
130
|
-
if (isGitLockError(out))
|
|
131
|
-
return { ok: false, lock_conflict: true, message: 'Web update is blocked by a repository lock. Wait for the other Git operation or inspect the checkout manually.' };
|
|
132
|
-
return { ok: false, message };
|
|
133
|
-
}
|
|
134
107
|
function normalizeRemoteUrl(remote) {
|
|
135
108
|
let url = remote.trim();
|
|
136
109
|
if (!url)
|
|
@@ -459,135 +432,13 @@ async function checkNpmExperimental(result, installed, id, registry) {
|
|
|
459
432
|
const metadataRepair = !same(id.release(), disk);
|
|
460
433
|
return { ...result, current_sha: release.sourceRevision, behind: 0, metadata_repair: metadataRepair, ...(metadataRepair ? { message: 'The npm package is current; finish the update to restart with that version.' } : {}) };
|
|
461
434
|
}
|
|
462
|
-
/** Python `
|
|
463
|
-
export async function verifyReleaseSource(root, release, git) {
|
|
464
|
-
const files = {};
|
|
465
|
-
for (const name of RELEASE_BLOBS) {
|
|
466
|
-
const shown = await git(['show', `${release.sourceRevision}:web/${name}`], root);
|
|
467
|
-
if (!shown.ok)
|
|
468
|
-
throw new Error('missing release metadata');
|
|
469
|
-
files[name] = JSON.parse(shown.out);
|
|
470
|
-
}
|
|
471
|
-
const pin = dict(files['sidecar/agent_dependency.json']);
|
|
472
|
-
const versions = dict(files['contract_versions.json']);
|
|
473
|
-
const expected = {
|
|
474
|
-
tag: release.tag,
|
|
475
|
-
version: release.version,
|
|
476
|
-
sourceRevision: release.sourceRevision,
|
|
477
|
-
releaseSet: release.sourceRevision,
|
|
478
|
-
contracts: { appWeb: [dict(versions.appWeb).fixtureVersion], webRelay: [dict(versions.webRelay).protocolVersion] },
|
|
479
|
-
compatibleAgent: { ...dict(pin['x-talaria']), image: dict(dict(pin.services)['hermes-agent']).image },
|
|
480
|
-
};
|
|
481
|
-
if (!same(expected, release.runtime))
|
|
482
|
-
throw new Error('release metadata differs from source');
|
|
483
|
-
return expected;
|
|
484
|
-
}
|
|
485
|
-
const stampPath = (root) => join(root, RELEASE_STAMP);
|
|
486
|
-
const readStamp = (path) => {
|
|
487
|
-
if (!existsSync(path) && !isSymlink(path))
|
|
488
|
-
return null;
|
|
489
|
-
if (isSymlink(path))
|
|
490
|
-
throw new Error('local release stamp is a symbolic link');
|
|
491
|
-
return readFileSync(path, 'utf8');
|
|
492
|
-
};
|
|
493
|
-
const isSymlink = (path) => { try {
|
|
494
|
-
return lstatSync(path).isSymbolicLink();
|
|
495
|
-
}
|
|
496
|
-
catch {
|
|
497
|
-
return false;
|
|
498
|
-
} };
|
|
499
|
-
/** Python `_verified_release_stamp`: `[expected, installed]`; throws on a modified stamp. */
|
|
500
|
-
async function verifiedReleaseStamp(root, release, git, id) {
|
|
501
|
-
const expected = await verifyReleaseSource(root, release, git);
|
|
502
|
-
const raw = readStamp(stampPath(root));
|
|
503
|
-
const installed = raw === null ? null : JSON.parse(raw);
|
|
504
|
-
if (installed !== null && ![id.release(), id.stamped(), expected].some((c) => same(c, installed)))
|
|
505
|
-
throw new Error('local release stamp was modified');
|
|
506
|
-
return [expected, installed];
|
|
507
|
-
}
|
|
508
|
-
/** Python `_main_stamp`: the unchanged generated stamp bytes (to discard when leaving a release), else null. */
|
|
509
|
-
function mainStamp(root, id) {
|
|
510
|
-
const data = readStamp(stampPath(root));
|
|
511
|
-
if (data !== null && (!id.stamped().tag || !same(JSON.parse(data), id.stamped())))
|
|
512
|
-
throw new Error('local release stamp was modified');
|
|
513
|
-
return data;
|
|
514
|
-
}
|
|
515
|
-
async function mainRevision(root, git) {
|
|
516
|
-
const fetched = await fetchWithRetry(git, ['fetch', '--no-tags', 'origin', 'refs/heads/main:refs/remotes/origin/main'], root, 30_000);
|
|
517
|
-
if (!fetched.ok)
|
|
518
|
-
return [null, fetched.out];
|
|
519
|
-
// Single-branch clones never receive tags, so `git describe` would name a stale Web release.
|
|
520
|
-
// Best effort and unforced: a conflicting local tag is kept and never fails the main fetch.
|
|
521
|
-
await git(['fetch', '--no-tags', 'origin', 'refs/tags/web-v*:refs/tags/web-v*', 'refs/tags/web-exp-v*:refs/tags/web-exp-v*'], root, 30_000);
|
|
522
|
-
const source = await git(['rev-parse', 'refs/remotes/origin/main^{commit}'], root);
|
|
523
|
-
return source.ok && SHA.test(source.out) ? [source.out, ''] : [null, ''];
|
|
524
|
-
}
|
|
525
|
-
async function mainPathsDiffer(root, before, after, git) {
|
|
526
|
-
const files = await git(['diff', '--no-renames', '--name-only', before, after, '--', ...WEB_UPDATE_PATHS], root);
|
|
527
|
-
return files.ok ? Boolean(files.out) : null;
|
|
528
|
-
}
|
|
529
|
-
async function mainChangeCount(root, before, after, git) {
|
|
530
|
-
const changed = await mainPathsDiffer(root, before, after, git);
|
|
531
|
-
if (changed === null)
|
|
532
|
-
return null;
|
|
533
|
-
if (!changed)
|
|
534
|
-
return 0;
|
|
535
|
-
const count = await git(['rev-list', '--count', '--full-history', `${before}..${after}`, '--', ...WEB_UPDATE_PATHS], root);
|
|
536
|
-
const n = Number.parseInt(count.out, 10);
|
|
537
|
-
return count.ok && /^\d+$/.test(count.out) && n > 0 ? n : null;
|
|
538
|
-
}
|
|
539
|
-
async function mainRestartPending(root, head, git, id) {
|
|
540
|
-
const running = id.runningSourceRevision();
|
|
541
|
-
if (running === head)
|
|
542
|
-
return false;
|
|
543
|
-
if (!running)
|
|
544
|
-
return true;
|
|
545
|
-
return (await mainPathsDiffer(root, running, head, git)) !== false;
|
|
546
|
-
}
|
|
547
|
-
async function checkMainUpdate(root, result, git, id) {
|
|
548
|
-
Object.assign(result, { branch: 'origin/main', release_based: false });
|
|
549
|
-
if (root === null)
|
|
550
|
-
return { ...result, manual_update: true, message: 'Main updates require an authenticated Talaria source checkout with Web under web/.' };
|
|
551
|
-
const [source, error] = await mainRevision(root, git);
|
|
552
|
-
if (source === null) {
|
|
553
|
-
const detail = sanitizeGitDiagnostic(error);
|
|
554
|
-
return { ...result, stale_check: true, error: gitFailure(error, detail ? `Could not fetch origin/main: ${detail}` : 'Could not fetch origin/main; check Git read access.').message };
|
|
555
|
-
}
|
|
556
|
-
Object.assign(result, { latest_sha: source, latest_version: `main@${source.slice(0, 12)}` });
|
|
557
|
-
const head = await git(['rev-parse', 'HEAD'], root);
|
|
558
|
-
const status = await git(['status', '--porcelain', '--untracked-files=all'], root);
|
|
559
|
-
if (!head.ok || !SHA.test(head.out) || !status.ok)
|
|
560
|
-
return { ...result, manual_update: true, error: 'Could not verify the source checkout' };
|
|
561
|
-
Object.assign(result, { installed_sha: head.out, dirty: Boolean(status.out) });
|
|
562
|
-
const base = await git(['merge-base', head.out, source], root);
|
|
563
|
-
result.current_sha = base.ok && SHA.test(base.out) ? base.out : null;
|
|
564
|
-
if (result.current_sha)
|
|
565
|
-
result.compare_url = `${REPOSITORY_URL}/compare/${base.out}...${source}`;
|
|
566
|
-
if (!base.ok || base.out !== head.out)
|
|
567
|
-
return { ...result, manual_update: true, message: 'This checkout is ahead of or diverged from origin/main; reconcile it manually.' };
|
|
568
|
-
const count = await mainChangeCount(root, head.out, source, git);
|
|
569
|
-
if (count === null)
|
|
570
|
-
return { ...result, error: 'Could not compare the source checkout with origin/main' };
|
|
571
|
-
try {
|
|
572
|
-
mainStamp(root, id);
|
|
573
|
-
}
|
|
574
|
-
catch {
|
|
575
|
-
return { ...result, manual_update: true, error: 'Inspect the modified release stamp before updating.' };
|
|
576
|
-
}
|
|
577
|
-
Object.assign(result, { behind: count, metadata_repair: count === 0 && (await mainRestartPending(root, head.out, git, id)) });
|
|
578
|
-
if (status.out)
|
|
579
|
-
Object.assign(result, { manual_update: true, message: 'Commit or remove local changes before updating; Web updates never discard them.' });
|
|
580
|
-
else if (result.metadata_repair)
|
|
581
|
-
result.message = 'Source is current; finish the update to restart with that revision.';
|
|
582
|
-
return result;
|
|
583
|
-
}
|
|
584
|
-
/** Python `check_web_update`. */
|
|
435
|
+
/** Python `check_web_update`: npm and packaged installs; a source checkout is contributor-only (TAL-379). */
|
|
585
436
|
export async function checkWebUpdate(webRoot, currentVersion, channel, git, getJson, id, npmRun = runPackageNpm, registry) {
|
|
586
437
|
const root = await checkoutRoot(webRoot, git);
|
|
587
438
|
const npmInstall = root === null ? await npmInstallInfo(webRoot, npmRun) : null;
|
|
588
439
|
const result = { name: 'webui', channel, repo_url: REPOSITORY_URL, current_version: currentVersion, behind: null, no_git: root === null };
|
|
589
|
-
if (
|
|
590
|
-
return
|
|
440
|
+
if (root !== null)
|
|
441
|
+
return { ...result, manual_update: true, message: CONTRIBUTOR_CHECKOUT_MESSAGE };
|
|
591
442
|
if (channel === 'experimental' && npmInstall && registry)
|
|
592
443
|
return checkNpmExperimental(result, npmInstall, id, registry);
|
|
593
444
|
let release;
|
|
@@ -600,7 +451,7 @@ export async function checkWebUpdate(webRoot, currentVersion, channel, git, getJ
|
|
|
600
451
|
return { ...result, manual_update: true, error: 'Talaria release metadata is unavailable. Private repositories require TALARIA_RELEASE_TOKEN with Contents read access.' };
|
|
601
452
|
}
|
|
602
453
|
Object.assign(result, { latest_version: release.tag, latest_sha: release.sourceRevision, branch: release.tag, release_based: true, release_url: release.release_url, image: release.image });
|
|
603
|
-
|
|
454
|
+
{
|
|
604
455
|
if (npmInstall && channel === 'stable' && release.npm && npmInstallChannel(npmInstall, id) === 'experimental') {
|
|
605
456
|
// A channel switch installs the newest Stable package regardless of version order (TAL-343).
|
|
606
457
|
return { ...result, current_sha: id.release().sourceRevision ?? null, behind: 1, no_git: true, install_kind: 'npm', npm: release.npm, manual_update: false, channel_switch: true, message: `Switching to Stable installs npm release ${release.version}.` };
|
|
@@ -629,46 +480,6 @@ export async function checkWebUpdate(webRoot, currentVersion, channel, git, getJ
|
|
|
629
480
|
}
|
|
630
481
|
return { ...result, current_sha: current, behind, no_git: true, manual_update: true, message: 'Use the published Talaria Web image or authenticated monorepo installation; legacy checkouts require migration.' };
|
|
631
482
|
}
|
|
632
|
-
const head = await git(['rev-parse', 'HEAD'], root);
|
|
633
|
-
const status = await git(['status', '--porcelain', '--untracked-files=all'], root);
|
|
634
|
-
if (!head.ok || !SHA.test(head.out) || !status.ok)
|
|
635
|
-
return { ...result, manual_update: true, error: 'Could not verify the source checkout' };
|
|
636
|
-
const current = head.out;
|
|
637
|
-
Object.assign(result, { installed_sha: current, dirty: Boolean(status.out) });
|
|
638
|
-
let base;
|
|
639
|
-
let knownBase;
|
|
640
|
-
if (current === release.sourceRevision) {
|
|
641
|
-
try {
|
|
642
|
-
const [expected, installed] = await verifiedReleaseStamp(root, release, git, id);
|
|
643
|
-
result.behind = 0;
|
|
644
|
-
result.metadata_repair = !same(installed, expected) || !same(id.release(), expected);
|
|
645
|
-
if (result.metadata_repair)
|
|
646
|
-
result.message = 'Apply the selected release again to repair its metadata or restart with its recorded identity.';
|
|
647
|
-
}
|
|
648
|
-
catch {
|
|
649
|
-
Object.assign(result, { behind: null, manual_update: true, error: 'Could not verify local release provenance; inspect the release stamp before updating.' });
|
|
650
|
-
}
|
|
651
|
-
base = current;
|
|
652
|
-
knownBase = true;
|
|
653
|
-
}
|
|
654
|
-
else {
|
|
655
|
-
const contains = await git(['merge-base', '--is-ancestor', release.sourceRevision, current], root);
|
|
656
|
-
if (contains.ok)
|
|
657
|
-
return { ...result, behind: null, manual_update: true, current_sha: null, message: 'This checkout is ahead of the selected release. Manage it manually or check out the published release and restart Web.' };
|
|
658
|
-
result.behind = 1;
|
|
659
|
-
const mb = await git(['merge-base', current, release.sourceRevision], root);
|
|
660
|
-
base = mb.out;
|
|
661
|
-
knownBase = mb.ok;
|
|
662
|
-
if (knownBase && base !== current)
|
|
663
|
-
Object.assign(result, { manual_update: true, message: 'Reconcile divergent source history before updating Web.' });
|
|
664
|
-
}
|
|
665
|
-
// Local-only commits cannot appear in a GitHub comparison; omit unresolvable links.
|
|
666
|
-
result.current_sha = knownBase && SHA.test(base) ? base : null;
|
|
667
|
-
if (result.current_sha)
|
|
668
|
-
result.compare_url = `${REPOSITORY_URL}/compare/${base}...${release.sourceRevision}`;
|
|
669
|
-
if (status.out)
|
|
670
|
-
Object.assign(result, { manual_update: true, message: 'Commit or remove local changes before updating; Web updates never discard them.' });
|
|
671
|
-
return result;
|
|
672
483
|
}
|
|
673
484
|
export const CHANNEL_SWITCH_BACKUPS = 5;
|
|
674
485
|
/** Web's persisted stores (`settings.json`, the project store, the workspace store) as seen from the state dir. */
|
|
@@ -817,126 +628,12 @@ async function applyNpmWebUpdate(webRoot, channel, getJson, id, npmRun, canApply
|
|
|
817
628
|
return { ok: true, target: 'webui', channel, sourceRevision: target.sourceRevision, ...(target.npm ? { npm: target.npm } : {}),
|
|
818
629
|
...(switching ? { channel_switch: true, backup_dir: stores } : {}), message: `Updated Talaria Web to ${target.label}.${stores ? ` Settings were backed up to ${stores}.` : ''}` };
|
|
819
630
|
}
|
|
820
|
-
/** Python `apply_web_update`:
|
|
821
|
-
export async function applyWebUpdate(webRoot, channel, git, getJson, id,
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
const status = await git(['status', '--porcelain', '--untracked-files=all'], root);
|
|
826
|
-
if (!status.ok || status.out)
|
|
827
|
-
return { ok: false, dirty: true, message: 'Web update refused: the checkout must be clean, including untracked files.' };
|
|
828
|
-
for (const marker of ['MERGE_HEAD', 'CHERRY_PICK_HEAD', 'REVERT_HEAD', 'rebase-merge', 'rebase-apply', 'BISECT_LOG']) {
|
|
829
|
-
const path = await git(['rev-parse', '--git-path', marker], root);
|
|
830
|
-
if (!path.ok || existsSync(resolve(root, path.out)))
|
|
831
|
-
return { ok: false, message: 'Finish or abort the repository operation before updating Web.' };
|
|
832
|
-
}
|
|
833
|
-
const headRes = await git(['rev-parse', 'HEAD'], root);
|
|
834
|
-
if (!headRes.ok || !SHA.test(headRes.out))
|
|
835
|
-
return { ok: false, message: 'Could not verify the current source revision' };
|
|
836
|
-
const head = headRes.out;
|
|
837
|
-
const main = channel === 'experimental';
|
|
838
|
-
let source;
|
|
839
|
-
let tag;
|
|
840
|
-
let release = null;
|
|
841
|
-
if (main) {
|
|
842
|
-
const [revision, error] = await mainRevision(root, git);
|
|
843
|
-
if (revision === null)
|
|
844
|
-
return gitFailure(error, 'Could not fetch origin/main; check Git read access.');
|
|
845
|
-
source = revision;
|
|
846
|
-
tag = 'main';
|
|
847
|
-
}
|
|
848
|
-
else {
|
|
849
|
-
try {
|
|
850
|
-
release = await publishedWebRelease(channel, getJson);
|
|
851
|
-
}
|
|
852
|
-
catch {
|
|
853
|
-
return { ok: false, message: 'Cannot resolve a completed Talaria release. Check private-repository read access.' };
|
|
854
|
-
}
|
|
855
|
-
source = release.sourceRevision;
|
|
856
|
-
tag = release.tag;
|
|
857
|
-
}
|
|
858
|
-
if (head !== source && !main) {
|
|
859
|
-
// Fetch only this immutable tag; never force-replace a local tag or pull an unrecorded tip.
|
|
860
|
-
const fetched = await git(['fetch', '--no-tags', 'origin', `refs/tags/${tag}:refs/tags/${tag}`], root, 30_000);
|
|
861
|
-
if (!fetched.ok)
|
|
862
|
-
return gitFailure(fetched.out, 'Could not fetch the published Web tag. Check Git credentials or a conflicting local tag.');
|
|
863
|
-
const resolved = await git(['rev-parse', `refs/tags/${tag}^{commit}`], root);
|
|
864
|
-
if (!resolved.ok || resolved.out !== source)
|
|
865
|
-
return { ok: false, message: 'Published Web tag does not match the immutable release manifest' };
|
|
866
|
-
}
|
|
867
|
-
if (head !== source) {
|
|
868
|
-
const forward = await git(['merge-base', '--is-ancestor', head, source], root);
|
|
869
|
-
if (!forward.ok) {
|
|
870
|
-
const contains = await git(['merge-base', '--is-ancestor', source, head], root);
|
|
871
|
-
if (contains.ok)
|
|
872
|
-
return { ok: false, manual_update: true, target: 'webui', channel, message: 'This checkout is ahead of the selected source. Manage it manually; updates never rewind local work.' };
|
|
873
|
-
return { ok: false, message: 'Web update refused: source histories diverge; reconcile the checkout manually.' };
|
|
874
|
-
}
|
|
875
|
-
}
|
|
876
|
-
if (main) {
|
|
877
|
-
const count = await mainChangeCount(root, head, source, git);
|
|
878
|
-
if (count === null)
|
|
879
|
-
return { ok: false, message: 'Could not compare Web and contract changes against origin/main.' };
|
|
880
|
-
if (count === 0)
|
|
881
|
-
source = head; // No checkout mutation for App/Relay-only changes.
|
|
882
|
-
}
|
|
883
|
-
// Compare provenance with the immutable incoming files before modifying the checkout.
|
|
884
|
-
let expected = null;
|
|
885
|
-
let installed;
|
|
886
|
-
try {
|
|
887
|
-
if (main)
|
|
888
|
-
installed = mainStamp(root, id);
|
|
889
|
-
else
|
|
890
|
-
[expected, installed] = await verifiedReleaseStamp(root, release, git, id);
|
|
891
|
-
}
|
|
892
|
-
catch {
|
|
893
|
-
return { ok: false, message: 'Web update refused: source or local provenance does not match the release manifest.' };
|
|
894
|
-
}
|
|
895
|
-
const runtimeCurrent = main ? !(await mainRestartPending(root, head, git, id)) : same(installed, expected) && same(id.release(), expected);
|
|
896
|
-
if (head === source && runtimeCurrent)
|
|
897
|
-
return { ok: true, up_to_date: true, target: 'webui', channel, message: main ? 'Web and shared contracts are current on main.' : 'Talaria Web already contains the selected release.' };
|
|
898
|
-
const again = await git(['rev-parse', 'HEAD'], root);
|
|
899
|
-
const clean = await git(['status', '--porcelain', '--untracked-files=all'], root);
|
|
900
|
-
if (!again.ok || again.out !== head || !clean.ok || clean.out)
|
|
901
|
-
return { ok: false, message: 'The checkout changed during the update; retry after it is clean.' };
|
|
902
|
-
if (!canApply())
|
|
903
|
-
return { ok: false, message: 'Web update deferred because its settings or lifecycle changed.' };
|
|
904
|
-
if (head !== source) {
|
|
905
|
-
const merged = await git(['merge', '--ff-only', '--no-stat', '--no-overwrite-ignore', source], root, 30_000);
|
|
906
|
-
const actual = await git(['rev-parse', 'HEAD'], root);
|
|
907
|
-
if (!merged.ok || !actual.ok || actual.out !== source)
|
|
908
|
-
return gitFailure(merged.out, 'Web fast-forward failed; no local changes were discarded.');
|
|
909
|
-
}
|
|
910
|
-
// The supervisor re-executes the built artifact, so the checkout is installed and rebuilt before the stamp claims
|
|
911
|
-
// the new release; a failed build leaves the old stamp (and the running server) truthful.
|
|
912
|
-
const buildError = await buildWeb(root, build);
|
|
913
|
-
if (buildError !== null)
|
|
914
|
-
return { ok: false, build_failed: true, target: 'webui', channel, sourceRevision: source, message: `Source advanced to ${tag}, but the Web build failed: ${buildError}. Run \`npm ci\` and \`npm run build\` in web/ (see README), then restart Web.` };
|
|
915
|
-
const stamp = stampPath(root);
|
|
916
|
-
if (main && installed !== null) {
|
|
917
|
-
try {
|
|
918
|
-
if (isSymlink(stamp) || readFileSync(stamp, 'utf8') !== installed)
|
|
919
|
-
throw new Error('release stamp changed during update');
|
|
920
|
-
unlinkSync(stamp);
|
|
921
|
-
}
|
|
922
|
-
catch {
|
|
923
|
-
return { ok: false, message: 'Source advanced but its release stamp could not be cleared; inspect it before restarting Web.' };
|
|
924
|
-
}
|
|
925
|
-
}
|
|
926
|
-
else if (!main && !same(installed, expected)) {
|
|
927
|
-
const temporary = join(dirname(stamp), `.release-${String(process.pid)}-${String(Date.now())}`);
|
|
928
|
-
try {
|
|
929
|
-
writeFileSync(temporary, `${JSON.stringify(expected, null, 2)}\n`);
|
|
930
|
-
renameSync(temporary, stamp);
|
|
931
|
-
}
|
|
932
|
-
catch {
|
|
933
|
-
rmSync(temporary, { force: true });
|
|
934
|
-
return { ok: false, message: 'Source advanced, but release metadata could not be written. Repair file permissions before restarting Web.' };
|
|
935
|
-
}
|
|
936
|
-
}
|
|
937
|
-
return { ok: true, target: 'webui', channel, sourceRevision: source, message: `Updated Talaria Web to ${tag}.` };
|
|
631
|
+
/** Python `apply_web_update`: installs npm releases; a source checkout is never mutated (TAL-379). */
|
|
632
|
+
export async function applyWebUpdate(webRoot, channel, git, getJson, id, npmRun = runPackageNpm, canApply = () => true, packaged = {}) {
|
|
633
|
+
if (await checkoutRoot(webRoot, git) !== null)
|
|
634
|
+
return { ok: false, manual_update: true, target: 'webui', channel, message: CONTRIBUTOR_CHECKOUT_MESSAGE };
|
|
635
|
+
return applyNpmWebUpdate(webRoot, channel, getJson, id, npmRun, canApply, packaged);
|
|
938
636
|
}
|
|
939
|
-
// ── Agent checkout: independent Stable releases or Experimental default branch ──
|
|
940
637
|
async function releaseTags(path, git) {
|
|
941
638
|
const out = await git(['tag', '--list', AGENT_TAG_GLOB, '--sort=-v:refname'], path);
|
|
942
639
|
return out.ok ? out.out.split('\n').map((l) => l.trim()).filter((tag) => /^v\d+\.\d+\.\d+$/.test(tag)) : [];
|
|
@@ -1423,9 +1120,9 @@ export class UpdateService {
|
|
|
1423
1120
|
const result = await this.apply('webui', channel, stillEnabled);
|
|
1424
1121
|
if (notificationId) {
|
|
1425
1122
|
if (result.restart_blocked === true)
|
|
1426
|
-
this.deps.autoNotification?.transition(notificationId, 'blocked');
|
|
1123
|
+
this.deps.autoNotification?.transition(notificationId, 'blocked', null, undefined, result.message);
|
|
1427
1124
|
else if (result.ok !== true)
|
|
1428
|
-
this.deps.autoNotification?.transition(notificationId, 'failed');
|
|
1125
|
+
this.deps.autoNotification?.transition(notificationId, 'failed', null, undefined, result.message || result.error);
|
|
1429
1126
|
else if (result.restart_scheduled === true)
|
|
1430
1127
|
this.deps.autoNotification?.transition(notificationId, 'restarting', str(result.sourceRevision || result.candidate_revision));
|
|
1431
1128
|
else
|
|
@@ -1438,7 +1135,7 @@ export class UpdateService {
|
|
|
1438
1135
|
}
|
|
1439
1136
|
catch (error) {
|
|
1440
1137
|
if (notificationId)
|
|
1441
|
-
this.deps.autoNotification?.transition(notificationId, 'failed');
|
|
1138
|
+
this.deps.autoNotification?.transition(notificationId, 'failed', null, undefined, error.message);
|
|
1442
1139
|
this.deps.log(`[updates] automatic Web update failed: ${error.message}`);
|
|
1443
1140
|
return { ok: false, error: error.message };
|
|
1444
1141
|
}
|
|
@@ -1490,7 +1187,7 @@ export class UpdateService {
|
|
|
1490
1187
|
async applyInner(target, channel, canApply = () => true, agentOptions = {}) {
|
|
1491
1188
|
if (target === 'webui') {
|
|
1492
1189
|
const lifecycle = this.lifecycle;
|
|
1493
|
-
const result = await applyWebUpdate(this.deps.webRoot, channel, this.git, this.deps.getJson, this.deps.identity, this.deps.
|
|
1190
|
+
const result = await applyWebUpdate(this.deps.webRoot, channel, this.git, this.deps.getJson, this.deps.identity, this.deps.npm ?? runPackageNpm, canApply, { registry: this.deps.experimental, stateDir: this.deps.stateDir });
|
|
1494
1191
|
// Settings can cancel before mutation, but a committed replacement must finish restarting unless shutting down.
|
|
1495
1192
|
if (result.ok && !result.up_to_date && lifecycle === this.lifecycle) {
|
|
1496
1193
|
this.cache.checked_at = 0;
|