@qodeca/xezar 0.13.1 → 0.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/README.md +45 -15
- package/dist/agent-config/account-identity.d.ts +2 -8
- package/dist/agent-config/account-identity.js +54 -10
- package/dist/agent-config/account-identity.js.map +1 -1
- package/dist/agent-config/catalog.d.ts +49 -7
- package/dist/agent-config/catalog.js +107 -0
- package/dist/agent-config/catalog.js.map +1 -1
- package/dist/agent-config/model-settings/pi.d.ts +12 -6
- package/dist/agent-config/model-settings/pi.js +12 -6
- package/dist/agent-config/model-settings/pi.js.map +1 -1
- package/dist/agent-config/seed.js +10 -0
- package/dist/agent-config/seed.js.map +1 -1
- package/dist/contract/github.d.ts +15 -0
- package/dist/contract/index.d.ts +9 -0
- package/dist/contract/index.js +1527 -895
- package/dist/contract/mcp-api-reference.d.ts +174 -0
- package/dist/contract/mcp-audit.d.ts +103 -0
- package/dist/contract/mcp-discovery.d.ts +257 -0
- package/dist/contract/mcp-event-catalog.d.ts +121 -0
- package/dist/contract/mcp-event-catalog.test.d.ts +1 -0
- package/dist/contract/mcp-idempotency.d.ts +200 -0
- package/dist/contract/mcp-journal.d.ts +268 -0
- package/dist/contract/mcp-leader.d.ts +88 -0
- package/dist/contract/mcp-ownership.d.ts +78 -0
- package/dist/contract/mcp-versioning.d.ts +139 -0
- package/dist/contract/runs.d.ts +81 -0
- package/dist/core/agent-profiles.d.ts +15 -4
- package/dist/core/agent-profiles.js +22 -8
- package/dist/core/agent-profiles.js.map +1 -1
- package/dist/core/opencode-server-runner.js +71 -11
- package/dist/core/opencode-server-runner.js.map +1 -1
- package/dist/core/secret-redaction.d.ts +7 -1
- package/dist/core/secret-redaction.js +44 -10
- package/dist/core/secret-redaction.js.map +1 -1
- package/dist/index.js +138 -27
- package/dist/index.js.map +1 -1
- package/dist/machine-identity.d.ts +66 -0
- package/dist/machine-identity.js +96 -0
- package/dist/machine-identity.js.map +1 -0
- package/dist/mcp/adapters/claude-code.d.ts +41 -0
- package/dist/mcp/adapters/claude-code.js +40 -0
- package/dist/mcp/adapters/claude-code.js.map +1 -0
- package/dist/mcp/adapters/codex.d.ts +140 -0
- package/dist/mcp/adapters/codex.js +323 -0
- package/dist/mcp/adapters/codex.js.map +1 -0
- package/dist/mcp/adapters/opencode.d.ts +148 -0
- package/dist/mcp/adapters/opencode.js +528 -0
- package/dist/mcp/adapters/opencode.js.map +1 -0
- package/dist/mcp/adapters/pi-link.d.ts +102 -0
- package/dist/mcp/adapters/pi-link.js +235 -0
- package/dist/mcp/adapters/pi-link.js.map +1 -0
- package/dist/mcp/adapters/pi.d.ts +188 -0
- package/dist/mcp/adapters/pi.js +418 -0
- package/dist/mcp/adapters/pi.js.map +1 -0
- package/dist/mcp/api-reference.d.ts +26 -0
- package/dist/mcp/api-reference.js +133 -0
- package/dist/mcp/api-reference.js.map +1 -0
- package/dist/mcp/audit-trail.d.ts +162 -0
- package/dist/mcp/audit-trail.js +306 -0
- package/dist/mcp/audit-trail.js.map +1 -0
- package/dist/mcp/bridge.d.ts +81 -0
- package/dist/mcp/bridge.js +407 -0
- package/dist/mcp/bridge.js.map +1 -0
- package/dist/mcp/connection-file.d.ts +49 -0
- package/dist/mcp/connection-file.js +63 -0
- package/dist/mcp/connection-file.js.map +1 -0
- package/dist/mcp/echo-guard.d.ts +94 -0
- package/dist/mcp/echo-guard.js +160 -0
- package/dist/mcp/echo-guard.js.map +1 -0
- package/dist/mcp/event-catalog.d.ts +120 -0
- package/dist/mcp/event-catalog.js +306 -0
- package/dist/mcp/event-catalog.js.map +1 -0
- package/dist/mcp/event-controller.d.ts +230 -0
- package/dist/mcp/event-controller.js +596 -0
- package/dist/mcp/event-controller.js.map +1 -0
- package/dist/mcp/event-journal.d.ts +57 -0
- package/dist/mcp/event-journal.js +423 -0
- package/dist/mcp/event-journal.js.map +1 -0
- package/dist/mcp/index.d.ts +63 -0
- package/dist/mcp/index.js +386 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/mcp/ipc.d.ts +202 -0
- package/dist/mcp/ipc.js +206 -0
- package/dist/mcp/ipc.js.map +1 -0
- package/dist/mcp/leader-delivery.d.ts +119 -0
- package/dist/mcp/leader-delivery.js +450 -0
- package/dist/mcp/leader-delivery.js.map +1 -0
- package/dist/mcp/operation-receipts.d.ts +210 -0
- package/dist/mcp/operation-receipts.js +723 -0
- package/dist/mcp/operation-receipts.js.map +1 -0
- package/dist/mcp/project-catalogs.d.ts +23 -0
- package/dist/mcp/project-catalogs.js +25 -0
- package/dist/mcp/project-catalogs.js.map +1 -0
- package/dist/mcp/project-leaders.d.ts +26 -0
- package/dist/mcp/project-leaders.js +17 -0
- package/dist/mcp/project-leaders.js.map +1 -0
- package/dist/mcp/protocol.d.ts +50 -0
- package/dist/mcp/protocol.js +47 -0
- package/dist/mcp/protocol.js.map +1 -0
- package/dist/mcp/reconnect.d.ts +297 -0
- package/dist/mcp/reconnect.js +465 -0
- package/dist/mcp/reconnect.js.map +1 -0
- package/dist/mcp/resource-ownership.d.ts +228 -0
- package/dist/mcp/resource-ownership.js +390 -0
- package/dist/mcp/resource-ownership.js.map +1 -0
- package/dist/mcp/service-adapter.d.ts +16488 -0
- package/dist/mcp/service-adapter.js +148 -0
- package/dist/mcp/service-adapter.js.map +1 -0
- package/dist/mcp/service.d.ts +83 -0
- package/dist/mcp/service.js +233 -0
- package/dist/mcp/service.js.map +1 -0
- package/dist/mcp/session-binding.d.ts +105 -0
- package/dist/mcp/session-binding.js +163 -0
- package/dist/mcp/session-binding.js.map +1 -0
- package/dist/mcp/stale-write.d.ts +145 -0
- package/dist/mcp/stale-write.js +219 -0
- package/dist/mcp/stale-write.js.map +1 -0
- package/dist/mcp/tool.d.ts +48 -0
- package/dist/mcp/tool.js +24 -0
- package/dist/mcp/tool.js.map +1 -0
- package/dist/mcp/tools/discovery.d.ts +40 -0
- package/dist/mcp/tools/discovery.js +232 -0
- package/dist/mcp/tools/discovery.js.map +1 -0
- package/dist/mcp/tools/execution-control.d.ts +171 -0
- package/dist/mcp/tools/execution-control.js +513 -0
- package/dist/mcp/tools/execution-control.js.map +1 -0
- package/dist/mcp/tools/handoff-git.d.ts +26 -0
- package/dist/mcp/tools/handoff-git.js +544 -0
- package/dist/mcp/tools/handoff-git.js.map +1 -0
- package/dist/mcp/tools/index.d.ts +2 -0
- package/dist/mcp/tools/index.js +23 -0
- package/dist/mcp/tools/index.js.map +1 -0
- package/dist/mcp/tools/leader-events.d.ts +46 -0
- package/dist/mcp/tools/leader-events.js +126 -0
- package/dist/mcp/tools/leader-events.js.map +1 -0
- package/dist/mcp/tools/local-handoff.d.ts +102 -0
- package/dist/mcp/tools/local-handoff.js +306 -0
- package/dist/mcp/tools/local-handoff.js.map +1 -0
- package/dist/mcp/tools/project-config.d.ts +340 -0
- package/dist/mcp/tools/project-config.js +1075 -0
- package/dist/mcp/tools/project-config.js.map +1 -0
- package/dist/mcp/tools/results-evidence.d.ts +112 -0
- package/dist/mcp/tools/results-evidence.js +1045 -0
- package/dist/mcp/tools/results-evidence.js.map +1 -0
- package/dist/mcp/tools/task-create.d.ts +70 -0
- package/dist/mcp/tools/task-create.js +473 -0
- package/dist/mcp/tools/task-create.js.map +1 -0
- package/dist/mcp/tools/task-reads.d.ts +102 -0
- package/dist/mcp/tools/task-reads.js +689 -0
- package/dist/mcp/tools/task-reads.js.map +1 -0
- package/dist/mcp/tools/work-organisation.d.ts +2 -0
- package/dist/mcp/tools/work-organisation.js +502 -0
- package/dist/mcp/tools/work-organisation.js.map +1 -0
- package/dist/paths.d.ts +17 -7
- package/dist/paths.js +18 -8
- package/dist/paths.js.map +1 -1
- package/dist/runs/project-writer.js +76 -11
- package/dist/runs/project-writer.js.map +1 -1
- package/dist/runs/retention.d.ts +24 -1
- package/dist/runs/retention.js +62 -1
- package/dist/runs/retention.js.map +1 -1
- package/dist/server/forge/github.js +44 -0
- package/dist/server/forge/github.js.map +1 -1
- package/dist/server/forge/types.d.ts +16 -0
- package/dist/server/project-context.d.ts +81 -8
- package/dist/server/project-context.js +143 -35
- package/dist/server/project-context.js.map +1 -1
- package/dist/server/server.d.ts +1050 -53
- package/dist/server/server.js +326 -120
- package/dist/server/server.js.map +1 -1
- package/dist/server/validators.d.ts +26 -6
- package/dist/server/validators.js +17 -0
- package/dist/server/validators.js.map +1 -1
- package/dist/skills-remote.js +64 -6
- package/dist/skills-remote.js.map +1 -1
- package/dist/workflows/run.d.ts +277 -12
- package/dist/workflows/run.js +554 -59
- package/dist/workflows/run.js.map +1 -1
- package/dist/workspace/agent-profiles.d.ts +30 -3
- package/dist/workspace/agent-profiles.js +39 -4
- package/dist/workspace/agent-profiles.js.map +1 -1
- package/dist/workspace/config.js +25 -4
- package/dist/workspace/config.js.map +1 -1
- package/dist/workspace/project-owner.d.ts +210 -0
- package/dist/workspace/project-owner.js +518 -0
- package/dist/workspace/project-owner.js.map +1 -0
- package/package.json +5 -3
- package/scripts/pi-leader-extension.ts +420 -0
- package/scripts/sync-readme.mjs +83 -2
- package/web/dist/assets/{alert-dialog-BVsVcbFy.js → alert-dialog-D6rP6d39.js} +1 -1
- package/web/dist/assets/arrow-down-DMOfFIzW.js +1 -0
- package/web/dist/assets/arrow-left-C4Ec2BUg.js +1 -0
- package/web/dist/assets/{centered-state-Djgly6Ni.js → centered-state-B0ZqrPaa.js} +12 -12
- package/web/dist/assets/chevron-right-mHJ-crvn.js +1 -0
- package/web/dist/assets/{collapsible-DZ4D-DHG.js → collapsible-DchEHgUM.js} +1 -1
- package/web/dist/assets/{commit-list-B-z1JL9G.js → commit-list-BpMim1Rv.js} +1 -1
- package/web/dist/assets/{compare-variants-D62m4j3B.js → compare-variants-D5ItQbAq.js} +1 -1
- package/web/dist/assets/{diff-BKew9rQX.js → diff-HqqZ_WDR.js} +2 -2
- package/web/dist/assets/{diff-stat-D0mc5V6Z.js → diff-stat-NsU-3ecr.js} +1 -1
- package/web/dist/assets/{diff-view-xpIcuLIC.js → diff-view-B7c11Xux.js} +1 -1
- package/web/dist/assets/{dropdown-menu-CEQziH7X.js → dropdown-menu-CtTpnyod.js} +1 -1
- package/web/dist/assets/{editable-title-BCX3T2BY.js → editable-title-BXtuGQry.js} +1 -1
- package/web/dist/assets/{ellipsis-vertical-ByVdDc4z.js → ellipsis-vertical-MHtGZSH6.js} +1 -1
- package/web/dist/assets/{file-xBSB5hXO.js → file-DKLw5SOb.js} +1 -1
- package/web/dist/assets/{folder-CldgbZ5A.js → folder-Drw6-ufH.js} +1 -1
- package/web/dist/assets/{git-toolbar-DJANqg7Y.js → git-toolbar-BQH8bORV.js} +1 -1
- package/web/dist/assets/github-ynnpKFCJ.js +1 -0
- package/web/dist/assets/{image-preview-Cv5mZr0n.js → image-preview-DLhMN_R9.js} +1 -1
- package/web/dist/assets/index-BEsrNdXt.js +29 -0
- package/web/dist/assets/index-Da8DOBau.css +2 -0
- package/web/dist/assets/{markdown-CgEEE2ND.js → markdown-q365eN6Y.js} +1 -1
- package/web/dist/assets/{new-task-form-1r2bgsdD.js → new-task-form-CW-hNIWQ.js} +1 -1
- package/web/dist/assets/{pill-q-x22_ej.js → pill-B_TFulXa.js} +1 -1
- package/web/dist/assets/{project-router-VDN4jQM8.js → project-router-CLPc-ImZ.js} +1 -1
- package/web/dist/assets/{prompt-templates-BmZtCe-L.js → prompt-templates-CLc4RxyO.js} +1 -1
- package/web/dist/assets/{repo-git-btG0sdbO.js → repo-git-Is7R6-Tj.js} +1 -1
- package/web/dist/assets/{run-diff-vguEMJzh.js → run-diff-DHMvDlVo.js} +2 -2
- package/web/dist/assets/run-header-DvZJbQ8I.js +1 -0
- package/web/dist/assets/{search-x-QmhaAbg5.js → search-x-Ce2MMetu.js} +1 -1
- package/web/dist/assets/{skill-empty-hint-BrzUwByZ.js → skill-empty-hint-C_xCSvzB.js} +1 -1
- package/web/dist/assets/skills-CivqD4si.js +1 -0
- package/web/dist/assets/{sparkles-CP8QDOgX.js → sparkles-BCqPoj5g.js} +1 -1
- package/web/dist/assets/{square-terminal-CGypshSD.js → square-terminal-ikj5g-oK.js} +1 -1
- package/web/dist/assets/{tab-link-D4lFzzI1.js → tab-link-VsEjFV1Y.js} +1 -1
- package/web/dist/assets/{task-changes-BtZId14z.js → task-changes-CH-E81-_.js} +1 -1
- package/web/dist/assets/{task-commits-BoeyJXrv.js → task-commits-DqfkMFxp.js} +1 -1
- package/web/dist/assets/{task-files-DIy2oUnj.js → task-files-D_nkHZ_a.js} +2 -2
- package/web/dist/assets/task-thread-bxQompxJ.js +9 -0
- package/web/dist/assets/{textarea-CyBCyKIk.js → textarea-xajuW1L_.js} +1 -1
- package/web/dist/assets/{thread-loading-Cuq2jchC.js → thread-loading-C3JQZbIE.js} +1 -1
- package/web/dist/assets/{trash-2-B6Dp3ZNs.js → trash-2-hJrBhpUD.js} +1 -1
- package/web/dist/assets/{triangle-alert-xBya8FUp.js → triangle-alert-D1u82y1a.js} +1 -1
- package/web/dist/assets/{upload-D6MXEB9p.js → upload-Bn6FBZ59.js} +1 -1
- package/web/dist/assets/{use-desktop-CPBwzQ7M.js → use-desktop-DOIMfHfY.js} +1 -1
- package/web/dist/assets/{use-submit-shortcut-JTpNzU-u.js → use-submit-shortcut-Dj4DHTdE.js} +1 -1
- package/web/dist/assets/utils-YwBpOoRN.js +64 -0
- package/web/dist/assets/{workflows-DG115scU.js → workflows-CTaAKz2m.js} +3 -3
- package/web/dist/assets/{zoomable-image-GTYwLtkS.js → zoomable-image-C1-6P3tg.js} +1 -1
- package/web/dist/index.html +23 -23
- package/web/dist/assets/arrow-down-CYgAlZtW.js +0 -1
- package/web/dist/assets/arrow-left-BOqE0a3k.js +0 -1
- package/web/dist/assets/chevron-right-Cc9BWnbN.js +0 -1
- package/web/dist/assets/github-D6vK0jFn.js +0 -1
- package/web/dist/assets/index-CkmR6h7s.css +0 -2
- package/web/dist/assets/index-DVDqF4bM.js +0 -9
- package/web/dist/assets/refresh-cw-DcNCj2nu.js +0 -1
- package/web/dist/assets/run-header-DM7MiKj9.js +0 -1
- package/web/dist/assets/skills-DMfxQtrD.js +0 -1
- package/web/dist/assets/task-thread-CbMPmrWq.js +0 -9
- package/web/dist/assets/utils--z9hRtl3.js +0 -64
|
@@ -30,12 +30,33 @@ export class ProjectContextError extends Error {
|
|
|
30
30
|
* construction — the boot project is built eagerly by the caller via
|
|
31
31
|
* `context(bootId)`; every other project on first API touch. Concurrent
|
|
32
32
|
* `context()` calls for the same id share one build (the in-flight promise is
|
|
33
|
-
* cached), so recovery never runs twice for a project
|
|
33
|
+
* cached), so recovery never runs twice for a project — unless the project was
|
|
34
|
+
* removed in between, which ends that build's claim on the id (`generations`).
|
|
34
35
|
*/
|
|
35
36
|
export class ProjectContexts {
|
|
36
37
|
deps;
|
|
37
38
|
contexts = new Map();
|
|
39
|
+
/** In-flight builds, each tagged with the REGISTRATION it was started for. See `generations`. */
|
|
38
40
|
building = new Map();
|
|
41
|
+
/**
|
|
42
|
+
* How many times each id's registration has ended in this process — bumped by `dispose()`,
|
|
43
|
+
* which is the only event that ends one.
|
|
44
|
+
*
|
|
45
|
+
* A build crosses several awaits (store open, orphan prune, retention sweep, `recover()`), and
|
|
46
|
+
* a removal can land inside any of them. Before this counter, `dispose()` read `contexts` only,
|
|
47
|
+
* so a removal mid-build tore down nothing and the build then published itself into the map
|
|
48
|
+
* AFTERWARDS — `context()` reads `contexts` first, so every scoped route for a removed project
|
|
49
|
+
* went on being served from a context holding an open store and this process's writer claim.
|
|
50
|
+
*
|
|
51
|
+
* A generation, rather than re-reading the registry once the build finishes: re-adding a folder
|
|
52
|
+
* hands back the same slug for the same root, so a registry re-read cannot tell "still the
|
|
53
|
+
* registration I started for" from "removed and re-added while I was building" — and it would
|
|
54
|
+
* add another await between the check and the publish for a removal to slip into. The counter
|
|
55
|
+
* answers exactly that question, and it is compared SYNCHRONOUSLY with the `contexts.set` that
|
|
56
|
+
* publishes, so nothing can come between them. Ids that were never disposed are absent and read
|
|
57
|
+
* as 0; the map only grows by one small entry per project actually removed.
|
|
58
|
+
*/
|
|
59
|
+
generations = new Map();
|
|
39
60
|
/** Live store-created subscribers; invoked before RunManager recovery. */
|
|
40
61
|
storeListeners = new Set();
|
|
41
62
|
/** Live `onContextBuilt` subscribers (workspace SSE, step 2.8). */
|
|
@@ -48,25 +69,61 @@ export class ProjectContexts {
|
|
|
48
69
|
this.semaphore = deps.semaphore ?? new WorkspaceSemaphore();
|
|
49
70
|
}
|
|
50
71
|
/** The built context for `projectId`, building it on first access.
|
|
51
|
-
* Throws `ProjectContextError` for unknown ids and missing roots
|
|
72
|
+
* Throws `ProjectContextError` for unknown ids and missing roots — including for a build the
|
|
73
|
+
* project's removal outlived, which reports the id as `unknown-project` (a 404) because by the
|
|
74
|
+
* time that build finished, that is what it was. */
|
|
52
75
|
async context(projectId) {
|
|
53
76
|
const existing = this.contexts.get(projectId);
|
|
54
77
|
if (existing)
|
|
55
78
|
return existing;
|
|
79
|
+
const generation = this.generation(projectId);
|
|
56
80
|
const inFlight = this.building.get(projectId);
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
81
|
+
// A build started for an EARLIER registration is never adopted: it is going to tear itself
|
|
82
|
+
// down rather than publish, so handing it to a caller asking about the current registration
|
|
83
|
+
// would answer "unknown project" for a project that exists. The re-added project gets its own
|
|
84
|
+
// build, running beside the one it superseded.
|
|
85
|
+
if (inFlight && inFlight.generation === generation)
|
|
86
|
+
return inFlight.promise;
|
|
87
|
+
const entry = { generation, promise: this.buildAndPublish(projectId, generation) };
|
|
88
|
+
this.building.set(projectId, entry);
|
|
61
89
|
try {
|
|
62
|
-
|
|
63
|
-
this.contexts.set(projectId, ctx);
|
|
64
|
-
this.notifyBuilt(ctx);
|
|
65
|
-
return ctx;
|
|
90
|
+
return await entry.promise;
|
|
66
91
|
}
|
|
67
92
|
finally {
|
|
68
|
-
|
|
93
|
+
// Identity-guarded: a superseded build must not evict the entry of the build that replaced
|
|
94
|
+
// it, and `dispose()` may already have cleared this one.
|
|
95
|
+
if (this.building.get(projectId) === entry)
|
|
96
|
+
this.building.delete(projectId);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/** The registration counter for `projectId`; 0 until its first `dispose()`. */
|
|
100
|
+
generation(projectId) {
|
|
101
|
+
return this.generations.get(projectId) ?? 0;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Build, then publish only if the registration this build was started for is still the current
|
|
105
|
+
* one. The check and the `contexts.set` are one synchronous block on purpose: an await between
|
|
106
|
+
* them is a window for the removal this whole method exists to catch.
|
|
107
|
+
*
|
|
108
|
+
* A build that lost is torn down HERE, inside the promise `building` holds, so there is exactly
|
|
109
|
+
* one place a losing context is released and `dispose()` gets that teardown simply by awaiting
|
|
110
|
+
* the same promise.
|
|
111
|
+
*/
|
|
112
|
+
async buildAndPublish(projectId, generation) {
|
|
113
|
+
const ctx = await this.build(projectId);
|
|
114
|
+
if (this.generation(projectId) !== generation) {
|
|
115
|
+
await teardown(ctx);
|
|
116
|
+
throw new ProjectContextError('unknown-project', projectId);
|
|
69
117
|
}
|
|
118
|
+
this.contexts.set(projectId, ctx);
|
|
119
|
+
// Armed only once the context is PUBLISHED, for the reason spelled out in `build()`: the
|
|
120
|
+
// lookup outlives the call, and a handle landing on a store whose lifecycle has ended would
|
|
121
|
+
// `touch()` its healed records — scheduling a debounced `runs.json` write from a context
|
|
122
|
+
// nobody owns. A build that loses its generation therefore never arms one at all, which is
|
|
123
|
+
// the only way to release something `armRepoHandle` gives no handle to cancel.
|
|
124
|
+
armRepoHandle(ctx.store, ctx.root);
|
|
125
|
+
this.notifyBuilt(ctx);
|
|
126
|
+
return ctx;
|
|
70
127
|
}
|
|
71
128
|
/**
|
|
72
129
|
* Subscribe to future context builds (multi-project spec, step 2.8): the
|
|
@@ -111,10 +168,30 @@ export class ProjectContexts {
|
|
|
111
168
|
}
|
|
112
169
|
}
|
|
113
170
|
}
|
|
114
|
-
/**
|
|
171
|
+
/**
|
|
172
|
+
* Already-built context, without triggering a build.
|
|
173
|
+
*
|
|
174
|
+
* Deliberately still `contexts`-only, and it has to be: this is synchronous, and an in-flight
|
|
175
|
+
* build has no context to return yet. What that costs the ONE caller which reads it as a
|
|
176
|
+
* question about the project rather than about the map — `activeRunCount`, behind
|
|
177
|
+
* `DELETE /projects/:id`'s running-tasks guard — is covered by `pending()` instead: a project
|
|
178
|
+
* mid-build is not a project with no runs, because its store opens with `keepLive` and
|
|
179
|
+
* `manager.recover()` re-queues or resumes every live-looking row.
|
|
180
|
+
*/
|
|
115
181
|
peek(projectId) {
|
|
116
182
|
return this.contexts.get(projectId);
|
|
117
183
|
}
|
|
184
|
+
/**
|
|
185
|
+
* The in-flight build for `projectId`, if one is running — never starts one.
|
|
186
|
+
*
|
|
187
|
+
* For callers that must not decide anything about a project while it is still opening. The
|
|
188
|
+
* promise rejects for a failed or superseded build, so await it defensively; the caller owns
|
|
189
|
+
* the deadline, because how long a request may wait is a property of the request and not of
|
|
190
|
+
* this map (`PROJECT_TEARDOWN_WAIT_MS` in server.ts).
|
|
191
|
+
*/
|
|
192
|
+
pending(projectId) {
|
|
193
|
+
return this.building.get(projectId)?.promise;
|
|
194
|
+
}
|
|
118
195
|
/** Ids of every built context (dispose bookkeeping, shutdown flush). */
|
|
119
196
|
ids() {
|
|
120
197
|
return [...this.contexts.keys()];
|
|
@@ -123,21 +200,54 @@ export class ProjectContexts {
|
|
|
123
200
|
* Tear down one project's context (project removal): the manager stops
|
|
124
201
|
* making moves on its own (`RunManager.dispose()` — usage-sampler
|
|
125
202
|
* unsubscribe, timers, queued state) and the store is closed — index
|
|
126
|
-
* flushed to disk, every event-bus subscriber detached. Returns false
|
|
127
|
-
*
|
|
203
|
+
* flushed to disk, every event-bus subscriber detached. Returns false only
|
|
204
|
+
* when this map held NOTHING for `projectId` — neither a built context nor a
|
|
205
|
+
* build in flight.
|
|
206
|
+
*
|
|
207
|
+
* Ends the id's registration first (`generations`), which is what makes this safe to call
|
|
208
|
+
* against a project whose context is still being built: that build now loses its publish check,
|
|
209
|
+
* tears itself down and rejects instead of installing itself into a map the removal has already
|
|
210
|
+
* been through. Awaiting it here is what lets this promise keep meaning "nothing this project
|
|
211
|
+
* opened is still holding a store or writing to it" in the one case where the dangerous handle
|
|
212
|
+
* is not in `contexts` yet.
|
|
213
|
+
*
|
|
214
|
+
* Async because `RunManager.dispose()` is: its promise settles the background writes it could
|
|
215
|
+
* not stop synchronously — a queue-watchdog rescue, a worktree-retention sweep — and dropping
|
|
216
|
+
* it made the guarantee inert exactly where it is worth most. The context is removed from the
|
|
217
|
+
* map SYNCHRONOUSLY, before the await, so no route can resolve a context that is being torn
|
|
218
|
+
* down; only the wait for its last writes is deferred. Order matters after that: the manager's
|
|
219
|
+
* writes must land before `flush()` + `removeAllListeners()`, or a stamp arriving later
|
|
220
|
+
* schedules a debounced `runs.json` write from a store nobody owns — the same hazard
|
|
221
|
+
* `armRepoHandle` is guarded against above, and the one that lets a re-added project's stale
|
|
222
|
+
* in-memory list overwrite the fresh one.
|
|
128
223
|
*/
|
|
129
|
-
dispose(projectId) {
|
|
224
|
+
async dispose(projectId) {
|
|
225
|
+
// Bumped BEFORE anything is awaited, so a build that has not reached its publish check yet is
|
|
226
|
+
// already a loser by the time it gets there — no window, no second removal path.
|
|
227
|
+
this.generations.set(projectId, this.generation(projectId) + 1);
|
|
228
|
+
const pending = this.building.get(projectId);
|
|
130
229
|
const ctx = this.contexts.get(projectId);
|
|
230
|
+
if (ctx)
|
|
231
|
+
this.contexts.delete(projectId); // synchronously, before any await — see below
|
|
232
|
+
if (pending) {
|
|
233
|
+
// It tears ITSELF down at its publish check and rejects — unless it had already published,
|
|
234
|
+
// in which case it resolves to the context taken out of the map above and `teardown` below
|
|
235
|
+
// is that context's one and only teardown.
|
|
236
|
+
await pending.promise.catch(() => undefined);
|
|
237
|
+
if (this.building.get(projectId) === pending)
|
|
238
|
+
this.building.delete(projectId);
|
|
239
|
+
}
|
|
131
240
|
if (!ctx)
|
|
132
|
-
return
|
|
133
|
-
|
|
134
|
-
teardown(ctx);
|
|
241
|
+
return pending !== undefined;
|
|
242
|
+
await teardown(ctx);
|
|
135
243
|
return true;
|
|
136
244
|
}
|
|
137
|
-
/** Tear down every built context (process shutdown).
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
245
|
+
/** Tear down every built context (process shutdown). Sequential rather than parallel: these
|
|
246
|
+
* are disk flushes, and the map is small. In-flight builds are included: a build that lands
|
|
247
|
+
* after shutdown would otherwise publish an open store into a map nobody disposes again. */
|
|
248
|
+
async disposeAll() {
|
|
249
|
+
for (const id of new Set([...this.ids(), ...this.building.keys()]))
|
|
250
|
+
await this.dispose(id);
|
|
141
251
|
}
|
|
142
252
|
async build(projectId) {
|
|
143
253
|
const projects = await this.deps.listProjects();
|
|
@@ -167,27 +277,25 @@ export class ProjectContexts {
|
|
|
167
277
|
await reclaimWorktrees(project.root, store, keep).catch(() => []);
|
|
168
278
|
}
|
|
169
279
|
await manager.recover();
|
|
170
|
-
// Which repository this project IS (#945)
|
|
171
|
-
//
|
|
172
|
-
//
|
|
173
|
-
//
|
|
174
|
-
//
|
|
175
|
-
//
|
|
176
|
-
// every listener, and a healed record would then `touch()` a store whose lifecycle had
|
|
177
|
-
// ended — scheduling a `runs.json` write from a context nobody owns any more.
|
|
178
|
-
armRepoHandle(store, project.root);
|
|
280
|
+
// Which repository this project IS (#945) is armed by `buildAndPublish`, NOT here: it is a
|
|
281
|
+
// fire-and-forget `gh` lookup that outlives the call, so it may only start once this
|
|
282
|
+
// context is one a route can reach. Arming beside `RunStore.open` would outlive a failed
|
|
283
|
+
// build, and arming on the way out of here would outlive a build the project's removal
|
|
284
|
+
// outlived — both end the same way, with a healed record `touch()`ing a store whose
|
|
285
|
+
// lifecycle has ended and scheduling a `runs.json` write from a context nobody owns.
|
|
179
286
|
return { id: project.id, root: project.root, dataDir, store, manager, automationStore, launchKey };
|
|
180
287
|
}
|
|
181
288
|
catch (err) {
|
|
182
289
|
// A failed build must not leak the half-built context's subscriptions.
|
|
183
|
-
teardown({ store, manager });
|
|
290
|
+
await teardown({ store, manager });
|
|
184
291
|
throw err;
|
|
185
292
|
}
|
|
186
293
|
}
|
|
187
294
|
}
|
|
188
|
-
/** Shared teardown for built and half-built contexts.
|
|
189
|
-
|
|
190
|
-
|
|
295
|
+
/** Shared teardown for built and half-built contexts. Awaits the manager BEFORE closing the
|
|
296
|
+
* store, because that promise is the only signal that its background writes are finished. */
|
|
297
|
+
async function teardown(ctx) {
|
|
298
|
+
await ctx.manager.dispose();
|
|
191
299
|
ctx.store.flush();
|
|
192
300
|
ctx.store.removeAllListeners();
|
|
193
301
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-context.js","sourceRoot":"","sources":["../../src/server/project-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AA2DvC;+BAC+B;AAC/B,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAEjC,MAAM;IACN,SAAS;IAFpB,YACW,MAA6B,EAC7B,SAAiB;QAE1B,KAAK,CACH,MAAM,KAAK,iBAAiB;YAC1B,CAAC,CAAC,oBAAoB,SAAS,EAAE;YACjC,CAAC,CAAC,4BAA4B,SAAS,EAAE,CAC5C,CAAC;sBAPO,MAAM;yBACN,SAAS;QAOlB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED
|
|
1
|
+
{"version":3,"file":"project-context.js","sourceRoot":"","sources":["../../src/server/project-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAE1D,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC1D,OAAO,EAAE,2BAA2B,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAE,0BAA0B,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AACpF,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AACxD,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AA2DvC;+BAC+B;AAC/B,MAAM,OAAO,mBAAoB,SAAQ,KAAK;IAEjC,MAAM;IACN,SAAS;IAFpB,YACW,MAA6B,EAC7B,SAAiB;QAE1B,KAAK,CACH,MAAM,KAAK,iBAAiB;YAC1B,CAAC,CAAC,oBAAoB,SAAS,EAAE;YACjC,CAAC,CAAC,4BAA4B,SAAS,EAAE,CAC5C,CAAC;sBAPO,MAAM;yBACN,SAAS;QAOlB,IAAI,CAAC,IAAI,GAAG,qBAAqB,CAAC;IACpC,CAAC;CACF;AAED;;;;;;;GAOG;AACH,MAAM,OAAO,eAAe;IA+BG,IAAI;IA9BhB,QAAQ,GAAG,IAAI,GAAG,EAA0B,CAAC;IAC9D,iGAAiG;IAChF,QAAQ,GAAG,IAAI,GAAG,EAAoE,CAAC;IACxG;;;;;;;;;;;;;;;;;OAiBG;IACc,WAAW,GAAG,IAAI,GAAG,EAAkB,CAAC;IACzD,0EAA0E;IACzD,cAAc,GAAG,IAAI,GAAG,EAA6B,CAAC;IACvE,mEAAmE;IAClD,cAAc,GAAG,IAAI,GAAG,EAAiC,CAAC;IAC3E;wCACoC;IACnB,SAAS,CAAqB;IAE/C,YAA6B,IAAwB;oBAAxB,IAAI;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,IAAI,kBAAkB,EAAE,CAAC;IAC9D,CAAC;IAED;;;yDAGqD;IACrD,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9C,IAAI,QAAQ;YAAE,OAAO,QAAQ,CAAC;QAC9B,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,CAAC;QAC9C,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC9C,2FAA2F;QAC3F,4FAA4F;QAC5F,8FAA8F;QAC9F,+CAA+C;QAC/C,IAAI,QAAQ,IAAI,QAAQ,CAAC,UAAU,KAAK,UAAU;YAAE,OAAO,QAAQ,CAAC,OAAO,CAAC;QAC5E,MAAM,KAAK,GAAG,EAAE,UAAU,EAAE,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;QACnF,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,OAAO,MAAM,KAAK,CAAC,OAAO,CAAC;QAC7B,CAAC;gBAAS,CAAC;YACT,2FAA2F;YAC3F,yDAAyD;YACzD,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,KAAK;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,+EAA+E;IACvE,UAAU,CAAC,SAAiB;QAClC,OAAO,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAED;;;;;;;;OAQG;IACK,KAAK,CAAC,eAAe,CAAC,SAAiB,EAAE,UAAkB;QACjE,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACxC,IAAI,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,KAAK,UAAU,EAAE,CAAC;YAC9C,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;YACpB,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAC9D,CAAC;QACD,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,EAAE,GAAG,CAAC,CAAC;QAClC,yFAAyF;QACzF,4FAA4F;QAC5F,yFAAyF;QACzF,2FAA2F;QAC3F,+EAA+E;QAC/E,aAAa,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,CAAC,IAAI,CAAC,CAAC;QACnC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;;;;;OAMG;IACH,cAAc,CAAC,QAAuC;QACpD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpD,CAAC;IAED;;;;;OAKG;IACH,cAAc,CAAC,QAAmC;QAChD,IAAI,CAAC,cAAc,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAClC,OAAO,GAAG,EAAE,CAAC,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;IACpD,CAAC;IAED,2EAA2E;IACnE,kBAAkB,CAAC,KAAe;QACxC,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC;gBACH,QAAQ,CAAC,KAAK,CAAC,CAAC;YAClB,CAAC;YAAC,MAAM,CAAC;gBACP,2DAA2D;YAC7D,CAAC;QACH,CAAC;IACH,CAAC;IAED,2EAA2E;IACnE,WAAW,CAAC,GAAmB;QACrC,KAAK,MAAM,QAAQ,IAAI,CAAC,GAAG,IAAI,CAAC,cAAc,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC;gBACH,QAAQ,CAAC,GAAG,CAAC,CAAC;YAChB,CAAC;YAAC,MAAM,CAAC;gBACP,6CAA6C;YAC/C,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;;;;;;;OASG;IACH,IAAI,CAAC,SAAiB;QACpB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;IACtC,CAAC;IAED;;;;;;;OAOG;IACH,OAAO,CAAC,SAAiB;QACvB,OAAO,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC;IAC/C,CAAC;IAED,wEAAwE;IACxE,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;IACnC,CAAC;IAED;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,KAAK,CAAC,OAAO,CAAC,SAAiB;QAC7B,8FAA8F;QAC9F,iFAAiF;QACjF,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,SAAS,EAAE,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC;QAChE,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QAC7C,MAAM,GAAG,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;QACzC,IAAI,GAAG;YAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,8CAA8C;QAExF,IAAI,OAAO,EAAE,CAAC;YACZ,2FAA2F;YAC3F,2FAA2F;YAC3F,2CAA2C;YAC3C,MAAM,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;YAC7C,IAAI,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,SAAS,CAAC,KAAK,OAAO;gBAAE,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC;QAChF,CAAC;QACD,IAAI,CAAC,GAAG;YAAE,OAAO,OAAO,KAAK,SAAS,CAAC;QACvC,MAAM,QAAQ,CAAC,GAAG,CAAC,CAAC;QACpB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;iGAE6F;IAC7F,KAAK,CAAC,UAAU;QACd,KAAK,MAAM,EAAE,IAAI,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC,CAAC;YAAE,MAAM,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7F,CAAC;IAEO,KAAK,CAAC,KAAK,CAAC,SAAiB;QACnC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,SAAS,CAAC,CAAC;QACzD,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,mBAAmB,CAAC,iBAAiB,EAAE,SAAS,CAAC,CAAC;QAC1E,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS;YAAE,MAAM,IAAI,mBAAmB,CAAC,cAAc,EAAE,SAAS,CAAC,CAAC;QAE3F,MAAM,OAAO,GAAG,cAAc,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QAC7C,cAAc,CAAC,OAAO,CAAC,CAAC;QACxB,yEAAyE;QACzE,qEAAqE;QACrE,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC;QACzD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,IAAI,CAAC;eACxE,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACnC,2BAA2B,CAAC,eAAe,EAAE,KAAK,CAAC,CAAC;QACpD,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;QAC/B,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;QACnF,IAAI,CAAC;YACH,MAAM,SAAS,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;YAC3C,yEAAyE;YACzE,0EAA0E;YAC1E,kCAAkC;YAClC,IAAI,MAAM,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;gBACpC,MAAM,YAAY,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAChF,GAAG,EAAE,CAAC,EAAc,CACrB,CAAC;gBACF,MAAM,IAAI,GAAG,MAAM,wBAAwB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,KAAK,CAC7D,GAAG,EAAE,CAAC,0BAA0B,CACjC,CAAC;gBACF,MAAM,gBAAgB,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAc,CAAC,CAAC;YAChF,CAAC;YACD,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;YACxB,2FAA2F;YAC3F,qFAAqF;YACrF,yFAAyF;YACzF,uFAAuF;YACvF,oFAAoF;YACpF,qFAAqF;YACrF,OAAO,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,eAAe,EAAE,SAAS,EAAE,CAAC;QACrG,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,uEAAuE;YACvE,MAAM,QAAQ,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC;YACnC,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC;CACF;AAED;8FAC8F;AAC9F,KAAK,UAAU,QAAQ,CAAC,GAA6C;IACnE,MAAM,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;IAC5B,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IAClB,GAAG,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;AACjC,CAAC"}
|