isorite 0.8.1 → 0.10.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.
Files changed (112) hide show
  1. package/dist/core.js +84 -10
  2. package/dist/main.js +692 -99
  3. package/docs/setup-for-agents.md +8 -5
  4. package/docs/setup.md +31 -4
  5. package/docs/terminal.md +9 -3
  6. package/notes/algorithms/the-quadtree/subdivision.svg +15 -0
  7. package/notes/algorithms/the-quadtree.md +2 -0
  8. package/package.json +1 -1
  9. package/plugin/server.ts +1 -1
  10. package/plugin/tui.tsx +6 -0
  11. package/web/_app/immutable/assets/{0.CTbO0owi.css → 0.CPW9fjPu.css} +1 -1
  12. package/web/_app/immutable/assets/NoteEditor.Wt5vU9Tb.css +1 -0
  13. package/web/_app/immutable/chunks/{8wVGBFSs.js → -2Meesge.js} +3 -3
  14. package/web/_app/immutable/chunks/{C_ER1Any.js → 6RXH8WsD.js} +1 -1
  15. package/web/_app/immutable/chunks/{BL3mLym4.js → 9z49435t.js} +1 -1
  16. package/web/_app/immutable/chunks/B0A4Snxv.js +6 -0
  17. package/web/_app/immutable/chunks/B8Qvvm53.js +1 -0
  18. package/web/_app/immutable/chunks/{DMAYXnpq.js → BA8Hpxhg.js} +1 -1
  19. package/web/_app/immutable/chunks/{CKSRTWxH.js → BAclEN0O.js} +1 -1
  20. package/web/_app/immutable/chunks/BJo70SOc.js +1 -0
  21. package/web/_app/immutable/chunks/{DECNRCf2.js → BLmF1B2i.js} +1 -1
  22. package/web/_app/immutable/chunks/{CiVjR8gq.js → BTclWEfx.js} +1 -1
  23. package/web/_app/immutable/chunks/{Cp_JbuGh.js → BWVMfAMh.js} +1 -1
  24. package/web/_app/immutable/chunks/{D4fLEcOQ.js → BXAOBcPb.js} +1 -1
  25. package/web/_app/immutable/chunks/BYSDTLqw.js +1 -0
  26. package/web/_app/immutable/chunks/{Cgml88Pl.js → BcgO-fBX.js} +1 -1
  27. package/web/_app/immutable/chunks/BimZp6R0.js +523 -0
  28. package/web/_app/immutable/chunks/{CO2Y5y64.js → Bq2GBAJ0.js} +1 -1
  29. package/web/_app/immutable/chunks/BqrMZ9MX.js +1 -0
  30. package/web/_app/immutable/chunks/{BN6xhG8e.js → Bt7VOT5H.js} +1 -1
  31. package/web/_app/immutable/chunks/{BGbXxNFa.js → BuUzVkG2.js} +1 -1
  32. package/web/_app/immutable/chunks/{Brxvm_b1.js → By4S_gy5.js} +1 -1
  33. package/web/_app/immutable/chunks/{CRIvE37b.js → BymwHy7o.js} +1 -1
  34. package/web/_app/immutable/chunks/{B4sg4e8i.js → C5MPRibb.js} +1 -1
  35. package/web/_app/immutable/chunks/CBkjDkEN.js +151 -0
  36. package/web/_app/immutable/chunks/{BrqJKzQU.js → CD6xPodA.js} +1 -1
  37. package/web/_app/immutable/chunks/{CEufJyoj.js → CQd9D8Nc.js} +1 -1
  38. package/web/_app/immutable/chunks/{BrGmYbJT.js → CT_Ry4q8.js} +1 -1
  39. package/web/_app/immutable/chunks/{CQadubS9.js → C_amgxV1.js} +1 -1
  40. package/web/_app/immutable/chunks/CiU6tYJv.js +1 -0
  41. package/web/_app/immutable/chunks/{spNKdrPy.js → CjtKPNlv.js} +1 -1
  42. package/web/_app/immutable/chunks/{DxLkKbK2.js → Cl5zRP_n.js} +1 -1
  43. package/web/_app/immutable/chunks/{yXUzBjUq.js → CsRPJjQS.js} +1 -1
  44. package/web/_app/immutable/chunks/{CETSRtnV.js → CyFLqlvP.js} +1 -1
  45. package/web/_app/immutable/chunks/{Bq5hCPe1.js → Czz9qOh8.js} +1 -1
  46. package/web/_app/immutable/chunks/{BguXRgvc.js → D3-rqfsM.js} +1 -1
  47. package/web/_app/immutable/chunks/{bcQIrid8.js → D5XlJBy8.js} +1 -1
  48. package/web/_app/immutable/chunks/{TuFg0KqZ.js → D5vocsTl.js} +1 -1
  49. package/web/_app/immutable/chunks/{CTscJvp6.js → D95RKsvN.js} +1 -1
  50. package/web/_app/immutable/chunks/{BzI3yqBQ.js → DBC2xjOo.js} +1 -1
  51. package/web/_app/immutable/chunks/{C1hqerMA.js → DCD8_jrW.js} +1 -1
  52. package/web/_app/immutable/chunks/{BsLNwr5A.js → DF89zyH-.js} +1 -1
  53. package/web/_app/immutable/chunks/{DsIcKd8x.js → DQjIi5Jv.js} +1 -1
  54. package/web/_app/immutable/chunks/{C-dfcq9W.js → DRX-TQzj.js} +1 -1
  55. package/web/_app/immutable/chunks/{BunrC_8P.js → DX4bJJO0.js} +1 -1
  56. package/web/_app/immutable/chunks/{EQVRMnZU.js → DXK7PB4g.js} +1 -1
  57. package/web/_app/immutable/chunks/{mbLqADPr.js → DXTK-eyo.js} +1 -1
  58. package/web/_app/immutable/chunks/{wCTXGvXm.js → DbNETcPs.js} +1 -1
  59. package/web/_app/immutable/chunks/{CX-xckzu.js → DfCZPwp1.js} +1 -1
  60. package/web/_app/immutable/chunks/{DKNOMI4Y.js → Dh1lBxfx.js} +1 -1
  61. package/web/_app/immutable/chunks/{BgczuZKA.js → DkxkvOjx.js} +1 -1
  62. package/web/_app/immutable/chunks/DlKQFacy.js +1 -0
  63. package/web/_app/immutable/chunks/{0M1khDs2.js → DlXrOzlh.js} +1 -1
  64. package/web/_app/immutable/chunks/{B85D_PlV.js → Dpa4Syyy.js} +1 -1
  65. package/web/_app/immutable/chunks/DshHzxgH.js +1 -0
  66. package/web/_app/immutable/chunks/{CdY1YAit.js → EMo1IeTW.js} +1 -1
  67. package/web/_app/immutable/chunks/Iqr2CudW.js +3 -0
  68. package/web/_app/immutable/chunks/{CoyQYage.js → RFxekmX-.js} +1 -1
  69. package/web/_app/immutable/chunks/{vk5Wkr31.js → RlApGeew.js} +1 -1
  70. package/web/_app/immutable/chunks/{CLVUDRRk.js → Xm0YTnxV.js} +1 -1
  71. package/web/_app/immutable/chunks/c7PFFMl4.js +1 -0
  72. package/web/_app/immutable/chunks/{CZ8wTb_M.js → gPtCGHiy.js} +1 -1
  73. package/web/_app/immutable/chunks/{D4SKbj9K.js → oWM_kgYq.js} +1 -1
  74. package/web/_app/immutable/chunks/{wj7G6pU5.js → rghE0CVz.js} +1 -1
  75. package/web/_app/immutable/chunks/{B9YLdnR_.js → tUSDgbpy.js} +1 -1
  76. package/web/_app/immutable/chunks/{DTdlqvEb.js → vfDvz3qP.js} +1 -1
  77. package/web/_app/immutable/chunks/{BRKS-CCX.js → whhiiiga.js} +1 -1
  78. package/web/_app/immutable/entry/app.iw6ZIOh2.js +2 -0
  79. package/web/_app/immutable/entry/start.CFnKMSWs.js +1 -0
  80. package/web/_app/immutable/nodes/0.BzEgwgsa.js +26 -0
  81. package/web/_app/immutable/nodes/1.rzuq9VRh.js +1 -0
  82. package/web/_app/immutable/nodes/2.D_jWsQLW.js +1 -0
  83. package/web/_app/immutable/nodes/3.BzRx3SiD.js +1 -0
  84. package/web/_app/immutable/nodes/4.DP2MGav1.js +2 -0
  85. package/web/_app/immutable/nodes/5.BPS-CCQT.js +5 -0
  86. package/web/_app/immutable/nodes/6.DQMCyNJ3.js +1 -0
  87. package/web/_app/immutable/nodes/7.MWEn-qPC.js +1 -0
  88. package/web/_app/version.json +1 -1
  89. package/web/index.html +17 -17
  90. package/web/_app/immutable/assets/NoteEditor.8wWtZK_A.css +0 -1
  91. package/web/_app/immutable/chunks/B2TCcw-P.js +0 -6
  92. package/web/_app/immutable/chunks/BAkGB2fM.js +0 -1
  93. package/web/_app/immutable/chunks/CHbKgHy3.js +0 -1
  94. package/web/_app/immutable/chunks/CMTjeXEe.js +0 -1
  95. package/web/_app/immutable/chunks/CurmVJyp.js +0 -1
  96. package/web/_app/immutable/chunks/D29fKEzc.js +0 -1
  97. package/web/_app/immutable/chunks/D3BEa5-_.js +0 -673
  98. package/web/_app/immutable/chunks/DPnfDiTn.js +0 -1
  99. package/web/_app/immutable/chunks/DZYaqCwi.js +0 -1
  100. package/web/_app/immutable/chunks/D_19S_Iu.js +0 -1
  101. package/web/_app/immutable/chunks/DtPULAe0.js +0 -1
  102. package/web/_app/immutable/chunks/nMarIA7J.js +0 -3
  103. package/web/_app/immutable/entry/app.idRgnoYp.js +0 -2
  104. package/web/_app/immutable/entry/start.CEx_UQO6.js +0 -1
  105. package/web/_app/immutable/nodes/0.BUd_gY_8.js +0 -26
  106. package/web/_app/immutable/nodes/1.DHK7VmG0.js +0 -1
  107. package/web/_app/immutable/nodes/2.CDAt-6SJ.js +0 -1
  108. package/web/_app/immutable/nodes/3.4Wv5nmaw.js +0 -1
  109. package/web/_app/immutable/nodes/4.Ceb5g4Ps.js +0 -2
  110. package/web/_app/immutable/nodes/5.DioYOANs.js +0 -5
  111. package/web/_app/immutable/nodes/6.CzYfNb6g.js +0 -1
  112. package/web/_app/immutable/nodes/7.BxQaF3lD.js +0 -1
@@ -22,7 +22,7 @@ turn off certificate checking (`NODE_TLS_REJECT_UNAUTHORIZED=0`).
22
22
  | `isorite memory [<folder>]` | The agent's memory: a base (`~/isorite-memory` unless named), a git repository of its own, with its practice in `AGENTS.md`, listed in `bases.toml` as `memory`, lent. Run again, says where it is and changes nothing. |
23
23
  | `isorite bases [lend\|keep <name>]` | The bases this machine knows, as `bases.toml` lists them; `lend` lends one to every session, `keep` stops. |
24
24
  | `isorite guide [<folder>]` | The guide, a knowledge base about isorite, written into `~/isorite-guide` (or the folder named) and served. With no provider set up, Iso is the guide's finder: no key or network needed. Good to check the install alone. `isorite --tutorial` is another name for it. |
25
- | `isorite model [--from <folder>]` | Optional: the model for search by meaning. Says which is installed and where, else fetches it (53 MB) from npm, a GitHub release, then Hugging Face, saying why each failed. `--from`: granite's files, or any compatible model (below). |
25
+ | `isorite model [--from <folder\|.tgz>] [--url <url>]` | Optional: the model for search by meaning. Says which is installed and where, else fetches it (53 MB) from `ISORITE_MODEL_BASE_URL` (a mirror: the folder `isorite-model-granite-1.0.0.tgz` is in), npm, a GitHub release, then Hugging Face, saying why each failed. `--url`: that address only. `--from`: the release's `.tgz` fetched by hand (checked by its SHA-256), granite's files, or any compatible model (below). |
26
26
  | `isorite help setup` | Prints this. |
27
27
 
28
28
  ## Files
@@ -54,6 +54,7 @@ name = "work" # optional; what isorite calls the provide
54
54
  url = "https://…/v1" # OpenAI-compatible; /chat/completions and /models are added. Absent: OpenRouter
55
55
  key = "…" # the key; also settable in Iso's settings in the browser
56
56
  key_header = "api-key" # send the key in this header, as it is, instead of Authorization: Bearer
57
+ key_prefix = "Bearer " # what goes before the key in key_header (default: "Bearer " in Authorization, else "")
57
58
  stream_usage = false # don't send stream_options (some gateways answer 400 to it)
58
59
  max_tokens = 16000 # the least output budget any call gets, for models that think at length
59
60
  cache_marks = true # send Anthropic cache marks (OpenRouter-style gateways only)
@@ -149,16 +150,18 @@ Rules:
149
150
  | `ENOTFOUND` | The host name isn't found. | Check `url`. The name may resolve only on the company's network or VPN. |
150
151
  | `ECONNREFUSED` | Nothing listens there. | Check the URL's port. |
151
152
  | `ETIMEDOUT`, `UND_ERR_CONNECT_TIMEOUT` | No answer: often a proxy is needed. | Set `HTTPS_PROXY` (and `NO_PROXY` for internal hosts reached directly). |
152
- | `said 401` / `said 403` | The key, or where it's sent, isn't accepted. | Check the key, `key_header`, and any header the gateway wants. The gateway's own message usually names it. |
153
+ | `said 401` / `said 403` | The key, or how it's sent, isn't accepted. `doctor` says how it was sent (`sent as X-Gateway-Auth: <41 characters>`) and quotes the gateway. | Check the key, `key_header`, and any header the gateway wants. A message like "missing Bearer prefix" means `key_prefix = "Bearer "`. |
154
+ | `Proxy response (407) … The proxy (HTTPS_PROXY), not the provider, refused with 407` | The company's proxy wants credentials of its own. Not the gateway's 401. | Credentials in `HTTPS_PROXY` (`http://user:password@proxy:port`), or the proxy's own sign-in. A proxy that signs in by Kerberos or NTLM can't be answered by isorite. |
153
155
  | `said 404 … no model called X, which is OpenRouter's name for it` | No `[tiers]`. | Name the gateway's models under `[tiers]`. `doctor` lists the models `/models` offers. |
154
156
  | `… is unavailable (503 …), tried 4 times over N s: it is likely …, not your settings` | The gateway, or the model behind it, is down. | Wait, and send it again (↻ under the turn). If it lasts, the gateway's status page or owner. |
155
157
  | `… used its whole output budget (N tokens) thinking, and wrote nothing` | A reasoning model ran out of room before it wrote. | A lower tier, or `max_tokens` under `[provider]`. |
156
- | `! search by meaning: no model …` | Not installed (optional). | `isorite model`. Its failures name each source; offline, `isorite model --from <folder>` with a copy. |
157
- | `The model could not be fetched:` and a line for npm, GitHub, Hugging Face | None reachable from here. | Copy the model's folder from a machine that has it (`isorite model` there says where), then `isorite model --from <folder>`; or any compatible model. |
158
+ | `! search by meaning: no model …` | Not installed (optional). `doctor` says whether the release (or the mirror) answers from here. | `isorite model`. Its failures name each source; offline, `isorite model --from <the .tgz>` with the file it names. |
159
+ | `The model could not be fetched:` and a line for each source | None reachable from here. | Fetch the file it prints another way, check its SHA-256, and `isorite model --from <the .tgz>`. Or set `ISORITE_MODEL_BASE_URL` to a mirror's folder, or `isorite model --url <address>`. Or copy the model's folder from a machine that has it, then `isorite model --from <folder>`. |
158
160
  | `said 400: … stream_options` | The gateway refuses `stream_options`. | `stream_usage = false`. |
159
161
  | `✗ tools: … answered without calling the tool` | The model or gateway drops tools. | Choose a model that supports tool calls. Iso and the terminal need them. |
160
162
  | `isorite: starting…` and then nothing, or `waiting for OpenCode's server` | Something it starts is stalled. isorite runs no `git` to start (0.8.1); OpenCode may, and a company's `git` wrapper that waits on the network stalls it. | Read the log the line names. Check `git --version` answers at once in that folder; if not, the wrapper is the cause. |
161
- | `isorite term needs OpenCode 2` | OpenCode 1, or none. | `npm i -g @opencode/cli`, or `ISORITE_OPENCODE=…`. |
163
+ | The browser asks for a user and password (realm "Secure Area") | That's OpenCode's own web page, on the port `isorite term` names, not isorite's: a pairing link (`/pair`) used twice, or its address opened directly. | Open isorite's page (the link `isorite term` prints, or `/web` in the terminal). |
164
+ | `isorite term needs OpenCode 2` | OpenCode 1, or none. | `isorite opencode` installs OpenCode 2 in `~/.config/isorite/opencode-cli`, leaving the global prefix alone; or `ISORITE_OPENCODE=…` names one. `isorite term` offers to install it when run in a terminal. |
162
165
  | `port 4767 is serving <other>, not <notes>` | Another base is served there. | Stop it, or `--port`. |
163
166
  | The link doesn't open, over SSH | `localhost` is the remote machine. | `ssh -L 4767:localhost:4767 <host>` from the person's own machine. |
164
167
  | The terminal works but uses an unexpected model | Check the line `isorite term` prints: `config.toml`, `ISORITE_GATEWAY_URL`, or OpenCode's own (no key or certificate). | Fix what it names. |
package/docs/setup.md CHANGED
@@ -5,9 +5,32 @@ run `isorite doctor`: it checks each step and says what to change.
5
5
 
6
6
  ## 1. Install
7
7
 
8
+ Either one file, with Node inside it:
9
+
10
+ - **isorite**, as one executable for Linux, macOS or Windows, checked against the release's SHA256SUMS:
11
+ ```sh
12
+ curl -fsSL https://github.com/lachlanjs/isorite/releases/latest/download/install.sh | sh
13
+ ```
14
+ It goes in `~/.local/bin` (`--dir` for another folder). Each address it fetches is printed, so a machine that
15
+ can't reach GitHub can fetch the same files another way, or from a mirror with `--url <the executable's address>`.
16
+ It unpacks itself into `~/.cache/isorite/<version>/` the first time it runs. Run the installer again to update.
17
+
18
+ On Windows, in PowerShell:
19
+ ```powershell
20
+ irm https://github.com/lachlanjs/isorite/releases/latest/download/install.ps1 | iex
21
+ ```
22
+ It goes in `%LOCALAPPDATA%\isorite`, which it adds to your PATH (open a new terminal after), and unpacks itself
23
+ into `%LOCALAPPDATA%\isorite\<version>\` the first time it runs. The executable isn't signed, so Windows may say
24
+ it's from an unknown publisher. isorite's own settings are in `%USERPROFILE%\.config\isorite\`. Use Windows
25
+ Terminal for `isorite term`. `isorite opencode` needs npm, so Node 24 as well.
26
+
27
+ Or from npm:
28
+
8
29
  - **Node 24** or later (`node --version`).
9
30
  - **isorite**: `npm i -g isorite`.
10
- - For the terminal, **OpenCode 2**: `npm i -g @opencode/cli`.
31
+
32
+ Then, for the terminal, **OpenCode 2**: `isorite opencode` installs it for isorite alone (in
33
+ `~/.config/isorite/opencode-cli`), leaving your global npm prefix, and any OpenCode 1 you use, as they are.
11
34
 
12
35
  `isorite guide` now opens the guide, a knowledge base about isorite with things to do in it. Until a provider is set up, Iso there is the guide's finder: no key, nothing sent anywhere.
13
36
 
@@ -58,6 +81,8 @@ Gateways inside companies often want more than a key. Each of these is optional:
58
81
  url = "https://llm-gateway.corp.example/v1"
59
82
  key = "…"
60
83
  key_header = "api-key" # the header the key goes in, as it is, instead of Authorization: Bearer
84
+ # key_prefix = "Bearer " # what goes before the key: for Bearer in another header, as
85
+ # # key_header = "X-Gateway-Auth"; Authorization has Bearer unless key_prefix = ""
61
86
  stream_usage = false # for a gateway that refuses stream_options; the gauge then counts nothing
62
87
  max_tokens = 16000 # the least room a reply is given, for models that think at length
63
88
 
@@ -145,9 +170,11 @@ isorite model
145
170
  ```
146
171
 
147
172
  It says which model is installed and where, or fetches it (53 MB, once): from npm, else from a release on GitHub,
148
- else from Hugging Face. Without it, Iso searches by words and follows links. Where none of those can be reached,
149
- copy the model's folder from a machine that has it (`isorite model` there says where it is) and run
150
- `isorite model --from <folder>`. Any compatible model works the same way: an ONNX model that gives 384 numbers,
173
+ else from Hugging Face. Without it, Iso searches by words and follows links. A mirror of the release is tried
174
+ first when `ISORITE_MODEL_BASE_URL` names the folder its `.tgz` is in, and `isorite model --url <address>` fetches
175
+ from that one address alone. Where none of those can be reached, `isorite model` prints the file's address and
176
+ SHA-256: fetch it another way, and run `isorite model --from <the .tgz>`. Or copy the model's folder from a machine
177
+ that has it (`isorite model` there says where it is) and run `isorite model --from <folder>`. Any compatible model works the same way: an ONNX model that gives 384 numbers,
151
178
  with its `tokenizer.json` (for example all-MiniLM-L6-v2, with `{"pooling": "mean"}` in an `isorite-model.json`
152
179
  beside it).
153
180
 
package/docs/terminal.md CHANGED
@@ -10,8 +10,10 @@ Setting isorite up the first time, or at work behind a company's gateway, is in
10
10
 
11
11
  - **Node 24** or later.
12
12
  - **isorite**: `npm i -g isorite`.
13
- - **OpenCode 2**: `npm i -g @opencode/cli`. It installs as `opencode2` and `opencode`. If an older OpenCode is your
14
- `opencode`, isorite finds `opencode2`; or name one with `ISORITE_OPENCODE=/path/to/opencode`.
13
+ - **OpenCode 2**: `isorite opencode` installs the version isorite is tested with in `~/.config/isorite/opencode-cli`,
14
+ for isorite alone, leaving the global npm prefix (and an OpenCode 1 you use) as it is. `isorite term` offers to
15
+ when it finds none. One installed yourself (`npm i -g @opencode/cli`, as `opencode2`) is found too, or name one
16
+ with `ISORITE_OPENCODE=/path/to/opencode`.
15
17
  - A model provider, set once in `~/.config/isorite/config.toml`: see [setup.md](setup.md). `isorite doctor` checks
16
18
  all of this.
17
19
 
@@ -58,7 +60,11 @@ works (`-L 9000:localhost:4767`, then `http://localhost:9000/`).
58
60
 
59
61
  ## In the browser
60
62
 
61
- Open the link. While the terminal runs, Iso's pane header has two more switches beside *Iso may edit the notes*:
63
+ Open the link, or type `/web` in the terminal. OpenCode runs a web page of its own as well, on another port. It
64
+ asks for a password nobody was given, so isorite's `/web` opens isorite's page instead (OpenCode's pairing is
65
+ `/pair`), and `isorite term` says on which port OpenCode's page is, so that you don't open it.
66
+
67
+ While the terminal runs, Iso's pane header has two more switches beside *Iso may edit the notes*:
62
68
  *Iso may edit the project's files* (Alt+F) and *Iso may run commands* (Alt+R). With either on, the pane is the
63
69
  terminal's session:
64
70
 
@@ -0,0 +1,15 @@
1
+ <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 260 260" width="260" height="260" font-family="sans-serif">
2
+ <rect x="2" y="2" width="256" height="256" fill="none" stroke="#7a8794" stroke-width="2"/>
3
+ <g fill="none" stroke="#7a8794" stroke-width="1.5">
4
+ <path d="M130 2V258M2 130H258"/>
5
+ <path d="M66 2V130M2 66H130"/>
6
+ <path d="M194 130V258M130 194H258"/>
7
+ <path d="M34 2V66M2 34H66"/>
8
+ </g>
9
+ <g fill="#3f7fbf">
10
+ <circle cx="16" cy="18" r="5"/><circle cx="50" cy="48" r="5"/><circle cx="20" cy="52" r="5"/>
11
+ <circle cx="98" cy="40" r="5"/><circle cx="96" cy="104" r="5"/><circle cx="200" cy="70" r="5"/>
12
+ <circle cx="40" cy="190" r="5"/><circle cx="160" cy="160" r="5"/><circle cx="226" cy="168" r="5"/>
13
+ <circle cx="170" cy="226" r="5"/>
14
+ </g>
15
+ </svg>
@@ -6,4 +6,6 @@ description: The plane split into squares, and each square into four, until each
6
6
 
7
7
  A tree over the bodies in 2D. The root is a square holding them all; a square with more than one body is split into four. Each node also keeps its [centre of mass](/algorithms/centre-of-mass.md "requires"). In 3D it is an octree, with eight children.
8
8
 
9
+ ![Ten bodies: the square split until each square holds at most one](the-quadtree/subdivision.svg)
10
+
9
11
  How is a body inserted, and what does each node keep? I don't have this straight yet.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "isorite",
3
- "version": "0.8.1",
3
+ "version": "0.10.0",
4
4
  "description": "An agentic harness for understanding: your notes as a knowledge base, an Atlas of them, an agent that reads them, and study.",
5
5
  "license": "MIT",
6
6
  "type": "module",
package/plugin/server.ts CHANGED
@@ -45,7 +45,7 @@ export default Plugin.define({
45
45
  await ctx.session.hook("context", (request) => {
46
46
  request.system.push({
47
47
  type: "text",
48
- text: `The person's knowledge base is the folder ${notes}: notes in Markdown with YAML frontmatter, linked to each other. Look things up in it with brief_base, search_notes, outline_note and read_note rather than reading its files. Never edit or write its files directly: change a note with edit_note or write_note, which write it at once and mark your words as yours for the person to see. Your edits to code and other files are yours to make as usual. In a note, and in what you say, a fenced block in the language mermaid is drawn as a diagram in isorite, and code fenced with its language is coloured: draw a diagram where it helps or when asked.${lent}\n\n${CITING}`,
48
+ text: `The person's knowledge base is the folder ${notes}: notes in Markdown with YAML frontmatter, linked to each other. Look things up in it with brief_base, search_notes, outline_note and read_note rather than reading its files. Never edit or write its files directly: change a note with edit_note or write_note, which write it at once and mark your words as yours for the person to see. Your edits to code and other files are yours to make as usual. In a note, and in what you say, a fenced block in the language mermaid is drawn as a diagram in isorite, and code fenced with its language is coloured: draw a diagram where it helps or when asked. A picture in a note is ![what it shows](path), drawn in isorite: you have only its words, so keep its line when you edit around it.${lent}\n\n${CITING}`,
49
49
  });
50
50
  });
51
51
  // A write or an edit to a note anyway is made the same change through isorite, so it is entered and marked.
package/plugin/tui.tsx CHANGED
@@ -446,6 +446,12 @@ export default Plugin.define({
446
446
  if (words && !id) { ctx.ui.toast?.show?.({ message: `no note matches “${words}”`, variant: "warning" }); return; }
447
447
  openAtlas(id ?? "");
448
448
  },
449
+ }, {
450
+ // OpenCode's own /web pairs a browser with its page, by a link that works once; opened again, that page asks
451
+ // for a password nobody was given (M21). isorite's /web, listed before it, opens isorite's page; OpenCode's
452
+ // pairing is still /pair.
453
+ id: "isorite.web", title: "isorite in the browser (OpenCode's pairing: /pair)", palette: true, slash: { name: "web" },
454
+ run: () => openInBrowser(Isorite.url + "/"),
449
455
  }, {
450
456
  id: "isorite.note.open", title: "Open a note of the knowledge base", palette: true, slash: { name: "note", arguments: true },
451
457
  run: async (input) => {