@bendyline/gezel-service 0.1.0 → 1.0.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/dist/NOTICE.md +1 -1
- package/dist/bin/gezeld.js +51635 -50059
- package/dist/handboek-content/README.md +24 -2
- package/dist/handboek-content/conceptual/connected-apps.md +2 -0
- package/dist/handboek-content/technical/building-connected-apps-with-gezel-app-sdk.md +144 -0
- package/dist/handboek-content/technical/cli-reference.md +11 -0
- package/dist/handboek-content/technical/how-we-test-models.md +57 -9
- package/dist/handboek-content/technical/model-scorecard.md +27 -9
- package/dist/handboek-content/technical/npm-packages.md +67 -0
- package/dist/handboek-content/technical/security-model.md +18 -1
- package/dist/handboek-content/technical/where-files-live.md +3 -0
- package/dist/handboek-content/technical/writing-scripts-with-gezel-sdk.md +106 -0
- package/dist/handboek-content/whats-new/1.26223.md +82 -0
- package/dist/handboek-content/whats-new/whats-new-index.md +28 -0
- package/dist/handboek.d.ts +53 -26
- package/dist/handboek.js +103 -26
- package/dist/index-store/static-index-worker.js +476 -82
- package/dist/index.d.ts +206 -11
- package/dist/index.js +51615 -50051
- package/dist/ui/assets/{TerminalCodeEditor-CB-AXtKI.js → TerminalCodeEditor-DQICIlaI.js} +2 -2
- package/dist/ui/assets/{_.contribution-C6KlZ1yR.js → _.contribution-BXBGjh98.js} +1 -1
- package/dist/ui/assets/{chunk-6N2J7C2B-DIF7DJtk.js → chunk-6N2J7C2B-Du7clJkV.js} +1 -1
- package/dist/ui/assets/chunk-ILCJ3WFD-fHFoZ9wm.js +4 -0
- package/dist/ui/assets/{chunk-S5PCVMKU-CmFF6ff9.js → chunk-S5PCVMKU-DopU3Q9j.js} +2 -2
- package/dist/ui/assets/chunk-USU6HTKB-B-ElCUQS.js +1 -0
- package/dist/ui/assets/{chunk-WATAOG4Y-perfmDXF.js → chunk-WATAOG4Y-BnCgSncI.js} +1 -1
- package/dist/ui/assets/{cpp.contribution-BBBWN3Dm.js → cpp.contribution-UC-hXlnG.js} +1 -1
- package/dist/ui/assets/{csharp.contribution-jBA6TWhG.js → csharp.contribution-VSLdDbxa.js} +1 -1
- package/dist/ui/assets/{css.contribution-DQSNU6vC.js → css.contribution-DC9uQgZx.js} +1 -1
- package/dist/ui/assets/{cssMode-68UP_lrS.js → cssMode-DZsXawIN.js} +1 -1
- package/dist/ui/assets/{csv-Ctux8fO7.js → csv-RAgECoUg.js} +1 -1
- package/dist/ui/assets/dist-D6I_6t8i.js +195 -0
- package/dist/ui/assets/dist-a57vyaRu.js +2 -0
- package/dist/ui/assets/{doc-BdMAKGDm.js → doc-B7NXSLxH.js} +33 -23
- package/dist/ui/assets/{dockerfile.contribution-CSpSPKgK.js → dockerfile.contribution-PUE2MRJF.js} +1 -1
- package/dist/ui/assets/docx-IZY6hX8A.js +2 -0
- package/dist/ui/assets/{epub-oLed1tAU.js → epub-00L2M424.js} +1 -1
- package/dist/ui/assets/extract-UTAOG7LV-BZ_L7lLL.js +1 -0
- package/dist/ui/assets/{go.contribution-BjibqVfF.js → go.contribution-CsrBAk1W.js} +1 -1
- package/dist/ui/assets/{handlebars-Dq5dJ5WJ.js → handlebars-Bqyi6xyi.js} +1 -1
- package/dist/ui/assets/handlebars.contribution-C6VLDI51.js +2 -0
- package/dist/ui/assets/{html-fQ6X2xaa.js → html-Cgejr9YM.js} +24 -24
- package/dist/ui/assets/{html-Bgyk9kiZ.js → html-NLb64cMt.js} +1 -1
- package/dist/ui/assets/html.contribution-BP2a6izy.js +2 -0
- package/dist/ui/assets/{htmlMode-D5UKInqK.js → htmlMode-Utzysyes.js} +1 -1
- package/dist/ui/assets/{index-CPXp6BEZ.js → index-B_NFDPxp.js} +197 -195
- package/dist/ui/assets/index-CgP6VwNS.css +1 -0
- package/dist/ui/assets/infer-v-bCXeT9.js +2 -0
- package/dist/ui/assets/{ini.contribution-BiJ4T5K-.js → ini.contribution-CfehzoVj.js} +1 -1
- package/dist/ui/assets/{java.contribution-B8o1lBqP.js → java.contribution-CXk8bwAp.js} +1 -1
- package/dist/ui/assets/{javascript-COWkS1tr.js → javascript-BcbxETop.js} +1 -1
- package/dist/ui/assets/javascript.contribution-BRDuHf7J.js +2 -0
- package/dist/ui/assets/{jsonMode-CWWZvfzr.js → jsonMode-BORbF5qz.js} +1 -1
- package/dist/ui/assets/{kotlin.contribution-CxSOPQ6P.js → kotlin.contribution-CbKeqa_3.js} +1 -1
- package/dist/ui/assets/layouts-2A7QNF6Y-D94iKLLQ.js +1 -0
- package/dist/ui/assets/{less.contribution-Cthyflev.js → less.contribution-BgNGBZAo.js} +1 -1
- package/dist/ui/assets/{lua.contribution-894DRgPR.js → lua.contribution-CtZNsqOj.js} +1 -1
- package/dist/ui/assets/{markdown.contribution-d_TBTsNA.js → markdown.contribution-CNyxmHy1.js} +1 -1
- package/dist/ui/assets/{monaco-PebRhLpo.js → monaco-Ryh-SF_b.js} +3 -3
- package/dist/ui/assets/{monaco-base-4S0M5BiY.js → monaco-base-C-4W0je-.js} +1 -1
- package/dist/ui/assets/{monaco-setup-7hp0Z9jn.js → monaco-setup-BW0DQ8MV.js} +1 -1
- package/dist/ui/assets/{monaco.contribution-DQjPk7Rx.js → monaco.contribution-279M9-Uu.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-CKDvyGVE.js → monaco.contribution-Bu1oyef5.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-BL_zgiu2.js → monaco.contribution-C57BAnnI.js} +2 -2
- package/dist/ui/assets/{monaco.contribution-D61txvUB.js → monaco.contribution-o3cuP4Wp.js} +2 -2
- package/dist/ui/assets/{pdf-CwJ6ZJmB.js → pdf-66KslaXf.js} +1 -1
- package/dist/ui/assets/{php.contribution-B8kn8QoR.js → php.contribution-BulxzIpe.js} +1 -1
- package/dist/ui/assets/pptx-CsdVR0xn.js +6 -0
- package/dist/ui/assets/{python-CHygH1eM.js → python-D4zGC71G.js} +1 -1
- package/dist/ui/assets/python.contribution-CDI1t73R.js +2 -0
- package/dist/ui/assets/{ruby.contribution-BQdPKFM2.js → ruby.contribution-DVOdhLt8.js} +1 -1
- package/dist/ui/assets/{rust.contribution-D7wKqShc.js → rust.contribution-DLR9kg2m.js} +1 -1
- package/dist/ui/assets/{scss.contribution-kSTLMoty.js → scss.contribution-CYIIxBxH.js} +1 -1
- package/dist/ui/assets/{shell.contribution-BQnT3BBJ.js → shell.contribution-D0KjHQ5E.js} +1 -1
- package/dist/ui/assets/{sql.contribution-C9z55nWb.js → sql.contribution-CKhLelqr.js} +1 -1
- package/dist/ui/assets/{swift.contribution-BZoW5ZZj.js → swift.contribution-DiAAMfJp.js} +1 -1
- package/dist/ui/assets/{terminal-monaco-setup-DbSXji0d.js → terminal-monaco-setup-Dhxpm7Z8.js} +1 -1
- package/dist/ui/assets/{tsMode-jPpKNC6E.js → tsMode-DFEqg3P9.js} +1 -1
- package/dist/ui/assets/{typescript-Djn_8BHF.js → typescript-X_x8S3Dp.js} +1 -1
- package/dist/ui/assets/typescript.contribution-jI3BakLa.js +2 -0
- package/dist/ui/assets/xlsx-CdLmEC42.js +4 -0
- package/dist/ui/assets/{xml-DmE4Aqa-.js → xml-ANmRi8ZZ.js} +1 -1
- package/dist/ui/assets/xml.contribution-D5t83zAi.js +2 -0
- package/dist/ui/assets/{yaml-BjmK3C-c.js → yaml-R4WpJved.js} +1 -1
- package/dist/ui/assets/yaml.contribution-DV8dAjKa.js +2 -0
- package/dist/ui/index.html +15 -15
- package/package.json +13 -15
- package/dist/postinstall.d.ts +0 -2
- package/dist/postinstall.js +0 -40
- package/dist/ui/assets/chunk-ILCJ3WFD-uwKSpQd8.js +0 -4
- package/dist/ui/assets/chunk-USU6HTKB-hbaA8KyS.js +0 -1
- package/dist/ui/assets/dist-i9jV8CX8.js +0 -2
- package/dist/ui/assets/dist-jh33rACm.js +0 -195
- package/dist/ui/assets/docx-CNW-xqHT.js +0 -2
- package/dist/ui/assets/extract-UTAOG7LV-WxmEnrrc.js +0 -1
- package/dist/ui/assets/handlebars.contribution-DDSQBNPu.js +0 -2
- package/dist/ui/assets/html.contribution-DrClfj2L.js +0 -2
- package/dist/ui/assets/index-Caz-FRQy.css +0 -1
- package/dist/ui/assets/infer-Cc7ks6NX.js +0 -2
- package/dist/ui/assets/javascript.contribution-DMEzq0y4.js +0 -2
- package/dist/ui/assets/layouts-2A7QNF6Y-DR7-KboS.js +0 -1
- package/dist/ui/assets/pptx-Bmj2v9CT.js +0 -6
- package/dist/ui/assets/python.contribution-CmwCxp-v.js +0 -2
- package/dist/ui/assets/typescript.contribution-D4JmB9tz.js +0 -2
- package/dist/ui/assets/xlsx-BCnO44v8.js +0 -4
- package/dist/ui/assets/xml.contribution-BepqhMeK.js +0 -2
- package/dist/ui/assets/yaml.contribution-BwT8qEVt.js +0 -2
- package/postinstall.mjs +0 -8
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: whats-new/1.26223
|
|
3
|
+
title: 1.26223 — 11 August 2026
|
|
4
|
+
order: -26223
|
|
5
|
+
summary: Measured model scores, per-model memory controls, editable Office documents, and much stricter rules about what a gezel may install.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# 1.26223 — 11 August 2026
|
|
9
|
+
|
|
10
|
+
This is the first release with written release notes, so it covers everything since **1.26219** on 7 August. It is a big one: four days of work, and most of it is visible the moment you open the app.
|
|
11
|
+
|
|
12
|
+
If you read only one thing: gezel now publishes **measured scores** for the models it ships, your gezellen are much more tightly fenced in about what they may install on your machine, and Word, PowerPoint, Excel and PDF files in a project can now be edited as ordinary text.
|
|
13
|
+
|
|
14
|
+
## Model scores you can actually check
|
|
15
|
+
|
|
16
|
+
Choosing a local model used to mean guessing. Now there is a scoreboard.
|
|
17
|
+
|
|
18
|
+
The new **Model scorecard** in the Technical section of this Handboek lists every model we have tested and how many jobs it actually finished correctly — writing a small working program, fixing a bug from its symptoms, following a procedure and stopping when something is wrong, turning a pile of documents into one summary, and a set of everyday office and knowledge tasks. Each job is run three times on a real machine and checked by a program, not by an opinion. A companion article, **How we test models**, explains what was counted and what the numbers do not tell you.
|
|
19
|
+
|
|
20
|
+
The first published set covers four models measured on an M4 Max: gemma4-e4b, gemma4-12b, gemma4-31b and ornith-9b, on both task sets. Alongside the pass counts you now also get speed, how much memory a model needed in practice, and a separate quality read from a judging pass.
|
|
21
|
+
|
|
22
|
+
Two rules keep the board honest. A model that was only partly measured is **withheld** rather than shown with a flattering gap, and earlier rounds of testing are kept visible separately instead of being quietly overwritten.
|
|
23
|
+
|
|
24
|
+
## Your gezellen are on a shorter leash
|
|
25
|
+
|
|
26
|
+
A gezel that can install software is useful. A gezel that can install *anything, anywhere* is not something you should have to think about. This release closes that gap.
|
|
27
|
+
|
|
28
|
+
- **Installing packages is now registry-only and tied to one project.** A gezel can ask for a published package by name and version, into a project that already exists, and nothing else. Names, versions and destinations are all checked before anything runs.
|
|
29
|
+
- **Approving a command now approves that exact command.** Previously, approving a script meant approving the words in it. Now gezel takes a fingerprint of the actual files the command would read — the script, its wrapper, the files it imports — so an approval you gave yesterday cannot be reused tomorrow for a script whose contents have changed underneath it.
|
|
30
|
+
- **Names are checked everywhere.** Gezel, project, session and document identifiers now go through one shared rule, applied on disk, in the schemas, and on every web request, so a hand-crafted name cannot walk out of the folder it belongs in.
|
|
31
|
+
- **On Linux and macOS, gezel's home folder is now locked to your account** (`0700`). Other accounts on the same machine can no longer read your conversations or files.
|
|
32
|
+
|
|
33
|
+
None of this changes anything you do day to day. It changes what happens when something goes wrong.
|
|
34
|
+
|
|
35
|
+
## Word, PowerPoint, Excel and PDF files are editable now
|
|
36
|
+
|
|
37
|
+
Open a project and select a `.docx`, `.pptx`, `.xlsx`, `.pdf` or `.html` file, and gezel shows you its contents as clean Markdown you can read and search. The original file stays exactly where it was.
|
|
38
|
+
|
|
39
|
+
Editing is deliberately a second step. The imported text is read-only until you choose **Allow editing via markdown** from the file's menu, and the first time you do, gezel takes a copy of the untouched original and keeps it. It is opt-in because rewriting someone's PowerPoint should never be something that happens by accident.
|
|
40
|
+
|
|
41
|
+
## Real control over local models and memory
|
|
42
|
+
|
|
43
|
+
If you run models on your own machine, this is the release where the machine stops being a mystery.
|
|
44
|
+
|
|
45
|
+
- **Set the context size per model.** A slider in each model manager, instead of one setting for everything.
|
|
46
|
+
- **Set a memory budget**, decide whether a model may **spill into ordinary RAM** when it does not fit on the graphics card, and have models **unload themselves when idle** so a forgotten model stops holding your machine hostage.
|
|
47
|
+
- **An emergency stop.** The engine pill now has a "stop everything" action that cancels every chat in flight, clears anything queued, and drops gezel back into reactive mode — one place to press when something has run away from you.
|
|
48
|
+
- Behind those controls, gezel is better at fitting a model into the memory you actually have: it will trade parallel capacity down to two lanes when doing so buys a meaningfully larger context, rather than refusing or thrashing.
|
|
49
|
+
|
|
50
|
+
## Threads that are easier to follow
|
|
51
|
+
|
|
52
|
+
- **Thread titles are derived the same way everywhere.** The name you see in the sidebar, in search and in the thread list is now the same name, worked out once instead of three times slightly differently.
|
|
53
|
+
- **Recent threads appear as pills** above the conversation, so hopping between the two or three things you have going takes one click and puts you back where you were looking. Threads that are working, or that hit an error, are shown first — you should not have to go hunting for the one that needs you.
|
|
54
|
+
- **Terminal threads show their last command** in the list, so you can tell them apart at a glance.
|
|
55
|
+
- Chat references are more compact, the file tree and sidebar behave more predictably, and the Handboek's own table of contents now collapses by section, with craftbooks grouped into shelves rather than one long list.
|
|
56
|
+
|
|
57
|
+
## Connecting gezel to other things
|
|
58
|
+
|
|
59
|
+
- **Codex CLI can now use your local models.** A setup card in Settings writes a dedicated profile for the OpenAI Codex command-line tool that points it at gezel, so a coding tool you already use can run against a model on your own machine.
|
|
60
|
+
- **New GitHub connectors** bring pull requests, releases and wiki pages in as project material, alongside the existing Google Calendar connector. Connector output now lands in the project's artifacts, where the rest of your work lives.
|
|
61
|
+
- **The OpenAI-compatible endpoint speaks the Responses API**, including streaming — so apps built against the newer OpenAI shape work against gezel without a translation layer of their own.
|
|
62
|
+
- Four new Handboek articles document all of this for developers: the npm package map, writing scripts with the gezel SDK, building connected apps with the app SDK, and how we test models.
|
|
63
|
+
|
|
64
|
+
## Catalog updates without an app update
|
|
65
|
+
|
|
66
|
+
Gezel's descriptions of models, craftbooks and roles — the *gilde* content — can now be refreshed on its own, without waiting for a new version of the app. It checks about once a day, verifies what it downloads, and only switches over after confirming that everything that worked before still works.
|
|
67
|
+
|
|
68
|
+
It is **off unless you turn it on**, under Settings → About → Catalog content, and it will never touch a machine that has been pointed at a local content folder.
|
|
69
|
+
|
|
70
|
+
## Smaller things
|
|
71
|
+
|
|
72
|
+
- Windows machines without a working CUDA setup no longer get probed for one.
|
|
73
|
+
- The Nemotron model family is recognized under its aliases and given the right tool format.
|
|
74
|
+
- Installing gezel from npm no longer runs any install-time scripts; a permission repair that used to happen at install time now happens once, lazily, the first time it is needed.
|
|
75
|
+
- Refreshed underlying editor and content packages (squisq 2.7.1, gilde 0.1.21).
|
|
76
|
+
- A large set of new automated tests covering everyday office work — meeting follow-ups, research briefs, document round-trips, and whether a gezel reaches for the right tool — so regressions in ordinary tasks get caught before you meet them.
|
|
77
|
+
|
|
78
|
+
## Anything to do?
|
|
79
|
+
|
|
80
|
+
No. Update when you are offered it. Your gezellen, projects, threads and files are ordinary files on your disk and are read as-is by the new version.
|
|
81
|
+
|
|
82
|
+
If you run local models and have been fighting for memory, it is worth a visit to the model manager for the new per-model context and memory settings. And if you want to see which model to trust with what, start at the [Model scorecard](../technical/model-scorecard.md).
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: whats-new-index
|
|
3
|
+
title: What's new
|
|
4
|
+
order: -999999
|
|
5
|
+
summary: Every gezel release, in plain language — what changed and what it means for you.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# What's new
|
|
9
|
+
|
|
10
|
+
Gezel changes often. This section is the running record of those changes, one article per release, newest first.
|
|
11
|
+
|
|
12
|
+
## Recent releases
|
|
13
|
+
|
|
14
|
+
::handboek-whats-new-list
|
|
15
|
+
|
|
16
|
+
Each article is written for the person using gezel, not for the person who wrote the code. It says what is different now, what you can do that you could not do before, and what — if anything — you need to do about it. Where a change is only interesting to developers, it is marked as such so you can skip it.
|
|
17
|
+
|
|
18
|
+
## How to read a version number
|
|
19
|
+
|
|
20
|
+
A gezel version looks like **1.26223.47**. The middle part is the date: `26` is the year 2026, and `223` is the day of that year — so `26223` is 11 August 2026. The last part is the build number for that day. You can always tell how old your copy of gezel is by reading the middle number.
|
|
21
|
+
|
|
22
|
+
Your installed version is shown in **Settings → About**.
|
|
23
|
+
|
|
24
|
+
## Updating
|
|
25
|
+
|
|
26
|
+
Packaged installs check for new releases on their own and offer the update when one is ready. Nothing in your work is touched by an update: your gezellen, projects, threads, memories and files all live in ordinary files on your disk, and a new version simply reads the same files.
|
|
27
|
+
|
|
28
|
+
Separately from app releases, gezel can pick up new catalog content — model descriptions, craftbooks, role templates — without a full update. That is the **Catalog content** setting under Settings → About, and it is off unless you turn it on.
|
package/dist/handboek.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Poppetje, ModelTier, CatalogKind, CatalogItemSummary, CatalogItemDetail, HandboekRenderMode, HandboekFigure,
|
|
1
|
+
import { Poppetje, ModelTier, HandboekArea, CatalogKind, CatalogItemSummary, CatalogItemDetail, HandboekRenderMode, HandboekFigure, HandboekToc, HandboekArticle } from '@bendyline/gezel';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* What the handboek engine may know about *this install* when rendering
|
|
@@ -37,6 +37,51 @@ interface HandboekDeviceInfo {
|
|
|
37
37
|
/** Device info for `site`/`agent-less` contexts: nothing personal to tell. */
|
|
38
38
|
declare const siteDeviceInfo: HandboekDeviceInfo;
|
|
39
39
|
|
|
40
|
+
/** Area folder order — also the TOC order. */
|
|
41
|
+
declare const HANDBOEK_AREAS: readonly HandboekArea[];
|
|
42
|
+
declare const HANDBOEK_AREA_TITLES: Record<HandboekArea, string>;
|
|
43
|
+
/**
|
|
44
|
+
* The `whats-new` section index. Excluded from its own release list, and
|
|
45
|
+
* the one article in that area whose `order` is not a negated calendar
|
|
46
|
+
* line — see `docs/handboek/README.md`.
|
|
47
|
+
*/
|
|
48
|
+
declare const WHATS_NEW_INDEX_ID = "whats-new-index";
|
|
49
|
+
/** One release, as the `whats-new-list` macro renders it. */
|
|
50
|
+
interface ReleaseNoteEntry {
|
|
51
|
+
/** Article id — link targets resolve ids directly in app and site. */
|
|
52
|
+
id: string;
|
|
53
|
+
title: string;
|
|
54
|
+
/** The tweet-sized line. Absent only if an author forgot one. */
|
|
55
|
+
summary?: string;
|
|
56
|
+
}
|
|
57
|
+
interface CuratedArticle {
|
|
58
|
+
id: string;
|
|
59
|
+
area: HandboekArea;
|
|
60
|
+
title: string;
|
|
61
|
+
order: number;
|
|
62
|
+
summary?: string;
|
|
63
|
+
/** Article body — squisq-flavored markdown, macros not yet expanded. */
|
|
64
|
+
body: string;
|
|
65
|
+
/** Per-block seconds override for video playback. */
|
|
66
|
+
defaultDuration?: number;
|
|
67
|
+
/** When false, the CLI static-site export skips the article. */
|
|
68
|
+
siteVisible: boolean;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Locate the shipped handboek content tree. Same probe-chain shape as
|
|
72
|
+
* `findBundledUi()` in bin/gezeld.ts: an env override for tests and
|
|
73
|
+
* operators, the tsup-copied `dist/handboek-content/` in built trees,
|
|
74
|
+
* and the repo `docs/handboek/` when running from source (vitest, tsx).
|
|
75
|
+
*/
|
|
76
|
+
declare function findHandboekContent(): string | null;
|
|
77
|
+
/**
|
|
78
|
+
* Release-note articles, newest first. Release `order` is the negated
|
|
79
|
+
* calendar line (`1.26223` → `-26223`), so the area's own ascending sort
|
|
80
|
+
* already puts the newest release on top; this only drops the section
|
|
81
|
+
* index out of the list it introduces.
|
|
82
|
+
*/
|
|
83
|
+
declare function listReleaseNotes(articles: CuratedArticle[]): ReleaseNoteEntry[];
|
|
84
|
+
|
|
40
85
|
/** The slice of CatalogService the handboek needs — stubbable in tests. */
|
|
41
86
|
interface HandboekCatalog {
|
|
42
87
|
list(kind: CatalogKind): Promise<CatalogItemSummary[]>;
|
|
@@ -46,6 +91,12 @@ interface MacroContext {
|
|
|
46
91
|
mode: HandboekRenderMode;
|
|
47
92
|
catalog: HandboekCatalog;
|
|
48
93
|
device: HandboekDeviceInfo;
|
|
94
|
+
/**
|
|
95
|
+
* Release-note articles, newest first. Supplied by the engine from the
|
|
96
|
+
* curated tree rather than read here, so the `whats-new-list` macro
|
|
97
|
+
* stays a pure renderer and the tests can stub a release history.
|
|
98
|
+
*/
|
|
99
|
+
releases: ReleaseNoteEntry[];
|
|
49
100
|
/** Figures referenced by expanded markdown accumulate here. */
|
|
50
101
|
figures: HandboekFigure[];
|
|
51
102
|
}
|
|
@@ -73,30 +124,6 @@ declare function expandMacros(source: string, ctx: Omit<MacroContext, 'figures'>
|
|
|
73
124
|
/** Parse `key=value key2="quoted value"` attribute syntax. */
|
|
74
125
|
declare function parseAttrs(raw: string): Record<string, string>;
|
|
75
126
|
|
|
76
|
-
/** Area folder order — also the TOC order. */
|
|
77
|
-
declare const HANDBOEK_AREAS: readonly HandboekArea[];
|
|
78
|
-
declare const HANDBOEK_AREA_TITLES: Record<HandboekArea, string>;
|
|
79
|
-
interface CuratedArticle {
|
|
80
|
-
id: string;
|
|
81
|
-
area: HandboekArea;
|
|
82
|
-
title: string;
|
|
83
|
-
order: number;
|
|
84
|
-
summary?: string;
|
|
85
|
-
/** Article body — squisq-flavored markdown, macros not yet expanded. */
|
|
86
|
-
body: string;
|
|
87
|
-
/** Per-block seconds override for video playback. */
|
|
88
|
-
defaultDuration?: number;
|
|
89
|
-
/** When false, the CLI static-site export skips the article. */
|
|
90
|
-
siteVisible: boolean;
|
|
91
|
-
}
|
|
92
|
-
/**
|
|
93
|
-
* Locate the shipped handboek content tree. Same probe-chain shape as
|
|
94
|
-
* `findBundledUi()` in bin/gezeld.ts: an env override for tests and
|
|
95
|
-
* operators, the tsup-copied `dist/handboek-content/` in built trees,
|
|
96
|
-
* and the repo `docs/handboek/` when running from source (vitest, tsx).
|
|
97
|
-
*/
|
|
98
|
-
declare function findHandboekContent(): string | null;
|
|
99
|
-
|
|
100
127
|
interface HandboekEngineOptions {
|
|
101
128
|
catalog: HandboekCatalog;
|
|
102
129
|
device: HandboekDeviceInfo;
|
|
@@ -131,4 +158,4 @@ interface HandboekEngine {
|
|
|
131
158
|
*/
|
|
132
159
|
declare function createHandboekEngine(opts: HandboekEngineOptions): HandboekEngine;
|
|
133
160
|
|
|
134
|
-
export { type CuratedArticle, HANDBOEK_AREAS, HANDBOEK_AREA_TITLES, type HandboekArticleOptions, type HandboekCatalog, type HandboekDeviceInfo, type HandboekEngine, type HandboekEngineOptions, type HandboekGezelInfo, type HandboekHardwareInfo, type HandboekHardwareTier, type HandboekModelInfo, MACROS, createHandboekEngine, expandMacros, findHandboekContent, parseAttrs, siteDeviceInfo };
|
|
161
|
+
export { type CuratedArticle, HANDBOEK_AREAS, HANDBOEK_AREA_TITLES, type HandboekArticleOptions, type HandboekCatalog, type HandboekDeviceInfo, type HandboekEngine, type HandboekEngineOptions, type HandboekGezelInfo, type HandboekHardwareInfo, type HandboekHardwareTier, type HandboekModelInfo, MACROS, type ReleaseNoteEntry, WHATS_NEW_INDEX_ID, createHandboekEngine, expandMacros, findHandboekContent, listReleaseNotes, parseAttrs, siteDeviceInfo };
|
package/dist/handboek.js
CHANGED
|
@@ -15,15 +15,18 @@ var HANDBOEK_AREAS = [
|
|
|
15
15
|
"gezel-roles",
|
|
16
16
|
"craftbooks",
|
|
17
17
|
"project-types",
|
|
18
|
-
"technical"
|
|
18
|
+
"technical",
|
|
19
|
+
"whats-new"
|
|
19
20
|
];
|
|
20
21
|
var HANDBOEK_AREA_TITLES = {
|
|
21
22
|
conceptual: "Concepts",
|
|
22
23
|
"gezel-roles": "Gezel Roles",
|
|
23
24
|
craftbooks: "Craftbooks",
|
|
24
25
|
"project-types": "Project Types",
|
|
25
|
-
technical: "Technical"
|
|
26
|
+
technical: "Technical",
|
|
27
|
+
"whats-new": "What's New"
|
|
26
28
|
};
|
|
29
|
+
var WHATS_NEW_INDEX_ID = "whats-new-index";
|
|
27
30
|
function findHandboekContent() {
|
|
28
31
|
const override = process.env.GEZEL_HANDBOEK_DIR?.trim();
|
|
29
32
|
if (override) return existsSync(override) ? resolve(override) : null;
|
|
@@ -66,6 +69,9 @@ function loadCuratedArticles(contentDir) {
|
|
|
66
69
|
out.sort((a, b) => a.area === b.area ? a.order - b.order : 0);
|
|
67
70
|
return out;
|
|
68
71
|
}
|
|
72
|
+
function listReleaseNotes(articles) {
|
|
73
|
+
return articles.filter((a) => a.area === "whats-new" && a.id !== WHATS_NEW_INDEX_ID).sort((a, b) => a.order - b.order).map((a) => ({ id: a.id, title: a.title, summary: a.summary }));
|
|
74
|
+
}
|
|
69
75
|
function parseCuratedArticle(source, area, filename) {
|
|
70
76
|
HandboekAreaSchema.parse(area);
|
|
71
77
|
const { frontmatter, body } = splitFrontmatterBlock(source);
|
|
@@ -90,7 +96,7 @@ function titleFromBody(body, fallback) {
|
|
|
90
96
|
}
|
|
91
97
|
|
|
92
98
|
// src/handboek/generated.ts
|
|
93
|
-
import { ROLES } from "@bendyline/gezel";
|
|
99
|
+
import { CRAFTBOOK_ROLE_META, ROLES } from "@bendyline/gezel";
|
|
94
100
|
function firstSentence(text) {
|
|
95
101
|
const s = text.trim().split(/\.\s/)[0]?.replace(/\.$/, "").trim();
|
|
96
102
|
return s ? `${s}.` : void 0;
|
|
@@ -115,12 +121,20 @@ async function listGeneratedSummaries(catalog) {
|
|
|
115
121
|
});
|
|
116
122
|
const craftbooks = (await catalog.list("craftbook-template")).map((s) => s.manifest).sort((a, b) => a.name.localeCompare(b.name));
|
|
117
123
|
for (const book of craftbooks) {
|
|
124
|
+
const role = book.role ?? "general";
|
|
125
|
+
const roleIndex = CRAFTBOOK_ROLE_META.findIndex((item) => item.id === role);
|
|
126
|
+
const roleMeta = CRAFTBOOK_ROLE_META[roleIndex] ?? CRAFTBOOK_ROLE_META.at(-1);
|
|
118
127
|
out.push({
|
|
119
128
|
id: `craftbook/${book.id}`,
|
|
120
129
|
area: "craftbooks",
|
|
121
130
|
title: book.name,
|
|
122
131
|
order: 10,
|
|
123
|
-
summary: firstSentence(book.description)
|
|
132
|
+
summary: firstSentence(book.description),
|
|
133
|
+
subcategory: {
|
|
134
|
+
id: roleMeta.id,
|
|
135
|
+
title: roleMeta.label,
|
|
136
|
+
order: roleIndex < 0 ? CRAFTBOOK_ROLE_META.length : roleIndex
|
|
137
|
+
}
|
|
124
138
|
});
|
|
125
139
|
}
|
|
126
140
|
out.push({
|
|
@@ -245,6 +259,7 @@ import {
|
|
|
245
259
|
describeProvenance,
|
|
246
260
|
provenanceDifferences,
|
|
247
261
|
resolveRoleId as resolveRoleId2,
|
|
262
|
+
scoreModel,
|
|
248
263
|
toolsetGroupsForRole as toolsetGroupsForRole2
|
|
249
264
|
} from "@bendyline/gezel";
|
|
250
265
|
import { BUILTIN_TOOLSETS as BUILTIN_TOOLSETS2 } from "@bendyline/gezel-catalog";
|
|
@@ -599,8 +614,10 @@ var MACROS = {
|
|
|
599
614
|
"installed-models": installedModels,
|
|
600
615
|
"model-scorecard": modelScorecard,
|
|
601
616
|
"project-type-composition": projectTypeComposition,
|
|
602
|
-
"suggested-work": suggestedWork
|
|
617
|
+
"suggested-work": suggestedWork,
|
|
618
|
+
"whats-new-list": whatsNewList
|
|
603
619
|
};
|
|
620
|
+
var WHATS_NEW_LIST_DEFAULT_LIMIT = 12;
|
|
604
621
|
var DIRECTIVE_RE = /^::handboek-([a-z0-9-]+)(?:\{([^}]*)\})?\s*$/;
|
|
605
622
|
async function expandMacros(source, ctx) {
|
|
606
623
|
const figures = [];
|
|
@@ -904,6 +921,16 @@ async function craftbookList(attrs, ctx) {
|
|
|
904
921
|
});
|
|
905
922
|
return ["| Craftbook | What it does |", "| --- | --- |", ...rows].join("\n");
|
|
906
923
|
}
|
|
924
|
+
async function whatsNewList(attrs, ctx) {
|
|
925
|
+
const parsed = Number.parseInt(attrs.limit ?? "", 10);
|
|
926
|
+
const limit = Number.isFinite(parsed) && parsed > 0 ? parsed : WHATS_NEW_LIST_DEFAULT_LIMIT;
|
|
927
|
+
const releases = ctx.releases.slice(0, limit);
|
|
928
|
+
if (releases.length === 0) return "No releases have been written up yet.";
|
|
929
|
+
return releases.map((r) => {
|
|
930
|
+
const line = `- **[${r.title}](${r.id})**`;
|
|
931
|
+
return r.summary ? `${line} \u2014 ${r.summary}` : line;
|
|
932
|
+
}).join("\n");
|
|
933
|
+
}
|
|
907
934
|
async function deviceHardware(_attrs, ctx) {
|
|
908
935
|
if (ctx.mode === "site") {
|
|
909
936
|
return "Gezel classifies each device as tiny, small, medium, or large from the memory available to local models. Open this page in the app to see the current device.";
|
|
@@ -944,6 +971,8 @@ function renderScorecardMarkdown(dataset, suiteId, opts) {
|
|
|
944
971
|
].join("\n");
|
|
945
972
|
}
|
|
946
973
|
const lines = [];
|
|
974
|
+
const publishable = board.scores.filter((score) => score.unmeasuredScenarios.length === 0);
|
|
975
|
+
const withheld = board.scores.filter((score) => score.unmeasuredScenarios.length > 0);
|
|
947
976
|
lines.push(
|
|
948
977
|
`**${describeProvenance(
|
|
949
978
|
board.run,
|
|
@@ -951,33 +980,75 @@ function renderScorecardMarkdown(dataset, suiteId, opts) {
|
|
|
951
980
|
)}**`
|
|
952
981
|
);
|
|
953
982
|
lines.push("");
|
|
954
|
-
lines.push(
|
|
955
|
-
|
|
956
|
-
for (const score of board.scores) {
|
|
957
|
-
const discarded = score.discardedTrials > 0 ? `${score.discardedTrials} run${score.discardedTrials === 1 ? "" : "s"} lost to the machine` : "\u2014";
|
|
958
|
-
lines.push(
|
|
959
|
-
`| ${score.result.label} | ${score.result.parameterSize ?? score.result.tier} | ${score.claim} | ${discarded} |`
|
|
960
|
-
);
|
|
961
|
-
}
|
|
962
|
-
if (board.otherRunScores.length > 0) {
|
|
983
|
+
lines.push(...scoreTable(publishable));
|
|
984
|
+
if (withheld.length > 0) {
|
|
963
985
|
lines.push("");
|
|
964
|
-
lines.push("
|
|
986
|
+
lines.push("Not published \u2014 some tasks could not be measured on this round:");
|
|
965
987
|
lines.push("");
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
for (const entry of board.otherRunScores) {
|
|
969
|
-
const why = provenanceDifferences(board.run, entry.run);
|
|
970
|
-
lines.push(
|
|
971
|
-
`| ${entry.result.label} | ${entry.claim} | ${why.length > 0 ? why.join(", ") : "earlier round"} |`
|
|
972
|
-
);
|
|
988
|
+
for (const score of withheld) {
|
|
989
|
+
lines.push(`- ${score.result.label}: ${score.unmeasuredScenarios.length} task(s) unmeasured`);
|
|
973
990
|
}
|
|
974
991
|
}
|
|
992
|
+
const priorRuns = dataset.runs.filter((run) => run.id !== board.run.id && run.suites.includes(suiteId)).slice(0, PRIOR_ROUNDS_SHOWN);
|
|
993
|
+
for (const run of priorRuns) {
|
|
994
|
+
const scores = dataset.results.filter((result) => result.runId === run.id && result.suiteId === suiteId).map((result) => scoreModel(result, run.provenance.count)).filter((score) => score.unmeasuredScenarios.length === 0).sort((a, b) => b.successes / b.attributableTrials - a.successes / a.attributableTrials);
|
|
995
|
+
if (scores.length === 0) continue;
|
|
996
|
+
const why = provenanceDifferences(board.run, run);
|
|
997
|
+
lines.push("");
|
|
998
|
+
lines.push(`### Earlier round \u2014 ${run.provenance.startedAt.slice(0, 10)}`);
|
|
999
|
+
lines.push("");
|
|
1000
|
+
lines.push(
|
|
1001
|
+
`**${describeProvenance(
|
|
1002
|
+
run,
|
|
1003
|
+
scores.map((s) => s.result.engine)
|
|
1004
|
+
)}**${why.length > 0 ? ` \u2014 ${why.join(", ")}` : ""}`
|
|
1005
|
+
);
|
|
1006
|
+
lines.push("");
|
|
1007
|
+
lines.push(...scoreTable(scores));
|
|
1008
|
+
}
|
|
975
1009
|
if (opts.includeTaskCount) {
|
|
976
1010
|
lines.push("");
|
|
977
1011
|
lines.push(`Tasks in this set: ${board.scenarioIds.length}.`);
|
|
978
1012
|
}
|
|
979
1013
|
return lines.join("\n");
|
|
980
1014
|
}
|
|
1015
|
+
var PRIOR_ROUNDS_SHOWN = 2;
|
|
1016
|
+
function scoreTable(scores) {
|
|
1017
|
+
const anySpeed = scores.some((score) => !!score.result.performance);
|
|
1018
|
+
const anyRuntime = scores.some((score) => !!score.result.runtime);
|
|
1019
|
+
const anyJudge = scores.some((score) => !!score.result.judge);
|
|
1020
|
+
const cols = ["Model", "Size", "Tasks passed"];
|
|
1021
|
+
if (anyJudge) cols.push("Quality");
|
|
1022
|
+
if (anySpeed) cols.push("Reads at", "Writes at");
|
|
1023
|
+
if (anyRuntime) cols.push("Context", "Memory used");
|
|
1024
|
+
const rows = scores.map((score) => {
|
|
1025
|
+
const cells = [
|
|
1026
|
+
score.result.label,
|
|
1027
|
+
score.result.parameterSize ?? score.result.tier,
|
|
1028
|
+
score.claim
|
|
1029
|
+
];
|
|
1030
|
+
if (anyJudge) {
|
|
1031
|
+
const judge = score.result.judge;
|
|
1032
|
+
cells.push(judge ? `${judge.meanScore}/10 (${judge.artifacts} pieces)` : "\u2014");
|
|
1033
|
+
}
|
|
1034
|
+
if (anySpeed) {
|
|
1035
|
+
const perf = score.result.performance;
|
|
1036
|
+
cells.push(
|
|
1037
|
+
perf ? `${perf.prefillTokensPerSec.toLocaleString()} tok/s` : "\u2014",
|
|
1038
|
+
perf ? `${perf.decodeTokensPerSec} tok/s` : "\u2014"
|
|
1039
|
+
);
|
|
1040
|
+
}
|
|
1041
|
+
if (anyRuntime) {
|
|
1042
|
+
const runtime = score.result.runtime;
|
|
1043
|
+
cells.push(
|
|
1044
|
+
runtime ? `${Math.round(runtime.contextTokens / 1024)}K` : "\u2014",
|
|
1045
|
+
runtime ? `${(runtime.peakMemoryMb / 1024).toFixed(1)} GB` : "\u2014"
|
|
1046
|
+
);
|
|
1047
|
+
}
|
|
1048
|
+
return `| ${cells.join(" | ")} |`;
|
|
1049
|
+
});
|
|
1050
|
+
return [`| ${cols.join(" | ")} |`, `| ${cols.map(() => "---").join(" | ")} |`, ...rows];
|
|
1051
|
+
}
|
|
981
1052
|
async function projectTypeComposition(attrs, ctx) {
|
|
982
1053
|
if (!attrs.id) return "";
|
|
983
1054
|
const detail = await ctx.catalog.get("project-type", attrs.id);
|
|
@@ -1076,7 +1147,8 @@ function createHandboekEngine(opts) {
|
|
|
1076
1147
|
order: g.order,
|
|
1077
1148
|
summary: g.summary,
|
|
1078
1149
|
generated: true,
|
|
1079
|
-
siteVisible: true
|
|
1150
|
+
siteVisible: true,
|
|
1151
|
+
subcategory: g.subcategory
|
|
1080
1152
|
}))
|
|
1081
1153
|
].sort((a, b) => a.order - b.order || a.title.localeCompare(b.title));
|
|
1082
1154
|
return { area, title: HANDBOEK_AREA_TITLES[area], entries };
|
|
@@ -1085,12 +1157,14 @@ function createHandboekEngine(opts) {
|
|
|
1085
1157
|
},
|
|
1086
1158
|
async article(id, articleOpts) {
|
|
1087
1159
|
const mode = articleOpts?.mode ?? "app";
|
|
1088
|
-
const
|
|
1160
|
+
const curatedArticles = curated();
|
|
1161
|
+
const curatedMatch = curatedArticles.find((a) => a.id === id);
|
|
1089
1162
|
if (curatedMatch) {
|
|
1090
1163
|
const { markdown: markdown2, figures: figures2 } = await expandMacros(curatedMatch.body, {
|
|
1091
1164
|
mode,
|
|
1092
1165
|
catalog: opts.catalog,
|
|
1093
|
-
device: opts.device
|
|
1166
|
+
device: opts.device,
|
|
1167
|
+
releases: listReleaseNotes(curatedArticles)
|
|
1094
1168
|
});
|
|
1095
1169
|
return {
|
|
1096
1170
|
id,
|
|
@@ -1117,7 +1191,8 @@ function createHandboekEngine(opts) {
|
|
|
1117
1191
|
const { markdown, figures } = await expandMacros(body, {
|
|
1118
1192
|
mode,
|
|
1119
1193
|
catalog: opts.catalog,
|
|
1120
|
-
device: opts.device
|
|
1194
|
+
device: opts.device,
|
|
1195
|
+
releases: listReleaseNotes(curatedArticles)
|
|
1121
1196
|
});
|
|
1122
1197
|
return {
|
|
1123
1198
|
id,
|
|
@@ -1210,9 +1285,11 @@ export {
|
|
|
1210
1285
|
HANDBOEK_AREAS,
|
|
1211
1286
|
HANDBOEK_AREA_TITLES,
|
|
1212
1287
|
MACROS,
|
|
1288
|
+
WHATS_NEW_INDEX_ID,
|
|
1213
1289
|
createHandboekEngine,
|
|
1214
1290
|
expandMacros,
|
|
1215
1291
|
findHandboekContent,
|
|
1292
|
+
listReleaseNotes,
|
|
1216
1293
|
parseAttrs,
|
|
1217
1294
|
siteDeviceInfo
|
|
1218
1295
|
};
|