synartesis 0.6.0 → 0.6.10
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/CHANGELOG.md +246 -0
- package/README.md +22 -4
- package/package.json +7 -1
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,252 @@
|
|
|
2
2
|
|
|
3
3
|
What changed, and why it mattered. Dates are release dates.
|
|
4
4
|
|
|
5
|
+
## 0.6.10 — 2026-09-13
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- **Every model is told where it is before anybody says anything.** A model
|
|
10
|
+
arrives knowing how to call tools and nothing about why these particular
|
|
11
|
+
ones behave the way they do -- so a held call reads as a malfunction and it
|
|
12
|
+
goes looking for a way around it. That is the one behaviour this product
|
|
13
|
+
cannot tolerate, and it was not the model's fault: nobody had told it. Now
|
|
14
|
+
it is told, in the same terms for Claude, Gemini, and anything on an
|
|
15
|
+
OpenAI-compatible endpoint, local models included. What Synartesis is, what
|
|
16
|
+
the recording is for, what the four classes mean, and the one rule -- never
|
|
17
|
+
reach for a different tool that does the same thing without being held.
|
|
18
|
+
- **Each tool carries its own class, in its own description.** `write_file`
|
|
19
|
+
now says it is reversible and that what it replaces is copied first;
|
|
20
|
+
`move_file` says it cannot be undone and will be held for approval; a tool
|
|
21
|
+
the policy does not describe says it is treated as the worst case. On the
|
|
22
|
+
tool rather than in the prompt, because that is where a model looks when it
|
|
23
|
+
is choosing between two tools that do nearly the same thing -- a note at the
|
|
24
|
+
top of a conversation is read once, this is read every time the list is.
|
|
25
|
+
- **The briefing is particular, not general.** It names the servers actually
|
|
26
|
+
connected, the session this conversation is recorded as, today's date, and
|
|
27
|
+
the calls that will stop and wait -- by name. "Some calls are held" cannot
|
|
28
|
+
be planned around; "fs.move_file is held" can.
|
|
29
|
+
|
|
30
|
+
## 0.6.9 — 2026-09-13
|
|
31
|
+
|
|
32
|
+
### Added
|
|
33
|
+
|
|
34
|
+
- **A rate limit is waited out rather than handed over.** Every hosted
|
|
35
|
+
provider refuses when requests arrive too fast, and every one of them says
|
|
36
|
+
how long to wait. A turn that fails on that has not gone wrong, it has
|
|
37
|
+
arrived early, and reading a paragraph of JSON and pressing send again is
|
|
38
|
+
the application failing to do something it knows exactly how to do. It now
|
|
39
|
+
waits the stated time and tries again, at most twice, and says so on its own
|
|
40
|
+
line while it waits -- a window that silently stalls for a minute is
|
|
41
|
+
indistinguishable from one that has hung. It will not retry after the model
|
|
42
|
+
has started speaking: a retry replays the request from the beginning, and
|
|
43
|
+
words already on screen would be said twice.
|
|
44
|
+
|
|
45
|
+
### Changed
|
|
46
|
+
|
|
47
|
+
- **A quota of zero is not a rate limit, and the difference is the whole
|
|
48
|
+
point.** A free Google key asking for a Pro model is told `limit: 0` and
|
|
49
|
+
"please retry in 23s" in the same breath. Both are true and only one is
|
|
50
|
+
useful: there is no allowance to come back to, so that retry succeeds on no
|
|
51
|
+
schedule at all. The window now separates them -- a spent quota says how
|
|
52
|
+
long to wait, a quota that was never there says to turn on billing or pick
|
|
53
|
+
another model, and nothing waits for it.
|
|
54
|
+
- **The presets start on models a new key can actually use.** Gemini pointed
|
|
55
|
+
at a Pro preview and Mistral at `mistral-large-latest`; a free Gemini key is
|
|
56
|
+
allowed none of the former and an entry Mistral key is refused the latter
|
|
57
|
+
outright. A preset is a first impression, and greeting somebody with a quota
|
|
58
|
+
refusal on their first message is a poor one. Gemini starts at
|
|
59
|
+
`gemini-3.8-flash` and Mistral at `mistral-small-latest`, with a note saying
|
|
60
|
+
what billing buys. Anyone already set up keeps what they chose.
|
|
61
|
+
- **Refusals name the model, not the adapter.** They read
|
|
62
|
+
"gemini-3.1-pro-preview", not "gemini:gemini-3.1-pro-preview".
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
|
|
66
|
+
- The Gemini adapter's fallback model was `gemini-3-pro-preview`, which Google
|
|
67
|
+
retired. A default nobody set has to be one that answers.
|
|
68
|
+
|
|
69
|
+
## 0.6.8 — 2026-09-13
|
|
70
|
+
|
|
71
|
+
### Added
|
|
72
|
+
|
|
73
|
+
- **The model name can be changed in the window.** Every provider retires
|
|
74
|
+
models on its own schedule, and when one goes the request fails with a 404
|
|
75
|
+
naming its replacement. Until now the only way out was editing a JSON file
|
|
76
|
+
with the application closed, to keep using a service already paid for. The
|
|
77
|
+
sheet -- **Models and keys** now, since it does two jobs -- shows the name
|
|
78
|
+
each model points at and lets it be retyped. The key stays: it belongs to
|
|
79
|
+
the account, not to the model name.
|
|
80
|
+
|
|
81
|
+
### Changed
|
|
82
|
+
|
|
83
|
+
- **A provider's refusal arrives as a sentence.** Each of them says no in its
|
|
84
|
+
own dialect wrapped in its own JSON, and the window showed the wrapper. The
|
|
85
|
+
three that happen in practice now read plainly: a retired model says what
|
|
86
|
+
replaced it, a model the plan does not include says it is the plan, and a
|
|
87
|
+
refused key points at where keys are kept. The original text is kept
|
|
88
|
+
underneath, because a guess dressed as an explanation is worse than both.
|
|
89
|
+
|
|
90
|
+
Anything unrecognised is passed through exactly as it arrived.
|
|
91
|
+
|
|
92
|
+
- **Gemini's default is `gemini-3.1-pro-preview`**, which is what Google
|
|
93
|
+
replaced `gemini-3-pro-preview` with.
|
|
94
|
+
|
|
95
|
+
## 0.6.7 — 2026-09-13
|
|
96
|
+
|
|
97
|
+
### Fixed
|
|
98
|
+
|
|
99
|
+
- **A card no longer says a refused call cannot be undone.** A call that was
|
|
100
|
+
denied, or is still waiting for a person, changed nothing -- and the card
|
|
101
|
+
said "no way back recorded" about it, which reads as damage nobody can put
|
|
102
|
+
back. It now says nothing was applied, and why: refused before it reached
|
|
103
|
+
the system, or held and waiting for a decision. On this product, of all
|
|
104
|
+
products, that sentence has to be right.
|
|
105
|
+
|
|
106
|
+
- **The site could render blank where nothing is looking at it.** Sections
|
|
107
|
+
arrive as they are scrolled to, which an IntersectionObserver decides -- and
|
|
108
|
+
an observer only fires while the page is actually being rendered. A tab
|
|
109
|
+
loaded in the background is not: the browser suspends the lifecycle, the
|
|
110
|
+
callback never runs, and every hidden state stays hidden. Harmless when
|
|
111
|
+
somebody switches to the tab, and not harmless for anything that renders a
|
|
112
|
+
page without showing it. Three seconds with nothing arrived now shows the
|
|
113
|
+
page whole, finishing the states rather than starting them, since a
|
|
114
|
+
suspended tab freezes a transition where it stands.
|
|
115
|
+
|
|
116
|
+
### Changed
|
|
117
|
+
|
|
118
|
+
- **The logo in the empty room is the pale one**, so it sits on the page
|
|
119
|
+
rather than on a dark tile stuck to it. Same artwork, same generator.
|
|
120
|
+
|
|
121
|
+
- **A thousand lines of generated coordinates are gone.** Nothing had drawn
|
|
122
|
+
the mark from them since the logo became a file; the window, the icon and
|
|
123
|
+
the cards all show the picture now.
|
|
124
|
+
|
|
125
|
+
## 0.6.6 — 2026-09-13
|
|
126
|
+
|
|
127
|
+
### Changed
|
|
128
|
+
|
|
129
|
+
- **The logo is a file now, and every surface shows that file.** 0.6.5 made
|
|
130
|
+
the drawings agree; this stops there being drawings. `brand/synartesis-mark-1080.png`
|
|
131
|
+
is the logo -- the framed mark with its fringe, on its ground -- and the
|
|
132
|
+
window, the site masthead, the favicon, the touch icon and the cards all
|
|
133
|
+
display it rather than rendering their own version at their own weight.
|
|
134
|
+
|
|
135
|
+
The window's mark stops spinning while a turn runs and breathes instead: a
|
|
136
|
+
frame going round and round reads as a fault rather than as work.
|
|
137
|
+
|
|
138
|
+
## 0.6.5 — 2026-09-13
|
|
139
|
+
|
|
140
|
+
### Changed
|
|
141
|
+
|
|
142
|
+
- **One logo, everywhere.** The mark is generated -- one set of numbers behind
|
|
143
|
+
the window, the application icon, the site and the cards on the README --
|
|
144
|
+
but three surfaces had been drawing their own version of it instead: the
|
|
145
|
+
rail beside the wordmark, the site masthead and favicon, and the brand PNGs
|
|
146
|
+
each had a hand-drawn circle with an arrow that resembled the mark without
|
|
147
|
+
being it.
|
|
148
|
+
|
|
149
|
+
They now all show the generated one. Where the fan of five hundred
|
|
150
|
+
hairlines cannot survive -- a favicon, a 22px rail -- the generator emits
|
|
151
|
+
the identical geometry filled rather than combed, so it is the same glyph at
|
|
152
|
+
a different weight rather than a different drawing. `brand/mark.html` draws
|
|
153
|
+
nothing of its own any more; it displays `synartesis-logo.svg`, which the
|
|
154
|
+
generator writes.
|
|
155
|
+
|
|
156
|
+
## 0.6.4 — 2026-09-13
|
|
157
|
+
|
|
158
|
+
### Changed
|
|
159
|
+
|
|
160
|
+
- **The API keys sheet gives the key a line of its own.** Somebody opens that
|
|
161
|
+
sheet to do exactly one thing, and the field for it was squeezed into a
|
|
162
|
+
column beside a paragraph of prose, sharing a row with the model's name and
|
|
163
|
+
its note -- while a key is sixty characters or more. The row now explains
|
|
164
|
+
itself on top and the field runs the full width underneath, with a Cancel
|
|
165
|
+
that did not exist before, Escape to leave, a wider sheet and room between
|
|
166
|
+
the rows.
|
|
167
|
+
|
|
168
|
+
### Added
|
|
169
|
+
|
|
170
|
+
- **A test for the half the other key tests did not cover.** They prove a key
|
|
171
|
+
never reaches disk, a log, or the window -- all of which would still be true
|
|
172
|
+
of a key quietly dropped on the way to the provider. This one follows it in
|
|
173
|
+
through the sheet, through the keychain seam, and back out as the value the
|
|
174
|
+
request is built with.
|
|
175
|
+
|
|
176
|
+
### Fixed
|
|
177
|
+
|
|
178
|
+
- **A transient API error no longer sinks a release.** Nine installers built
|
|
179
|
+
and none were published, because the single call that creates the release
|
|
180
|
+
answered 500 once. Creating and uploading are retried.
|
|
181
|
+
|
|
182
|
+
## 0.6.3 — 2026-09-13
|
|
183
|
+
|
|
184
|
+
### Fixed
|
|
185
|
+
|
|
186
|
+
- **The packaged desktop application could not start.** It opened and died on
|
|
187
|
+
its first import with `Cannot find package '@modelcontextprotocol/sdk'`.
|
|
188
|
+
The bundler keeps a package.json's `dependencies` out of the bundle, which
|
|
189
|
+
is right for a library -- whoever installs it gets them -- and wrong for an
|
|
190
|
+
application that ships as one file plus one native binding. The MCP SDK,
|
|
191
|
+
`yaml` and `zod` were left as bare imports and nothing supplied them. Every
|
|
192
|
+
0.6.2 installer has this; this release is the fix.
|
|
193
|
+
|
|
194
|
+
The packaging script now refuses to pack a bundle whose top-level imports
|
|
195
|
+
are not shipped with it. Electron, the native binding and node builtins are
|
|
196
|
+
supplied; anything else has to be inside. Only top-level imports are
|
|
197
|
+
checked, deliberately: bundled libraries carry guarded `require`s for
|
|
198
|
+
optional native accelerators, and those are allowed to be absent.
|
|
199
|
+
|
|
200
|
+
## 0.6.2 — 2026-09-12
|
|
201
|
+
|
|
202
|
+
### Fixed
|
|
203
|
+
|
|
204
|
+
- **The application could not be built on Windows or Linux at all**, which the
|
|
205
|
+
first release build found out the hard way. On Windows, pnpm compiles
|
|
206
|
+
better-sqlite3 from source -- ignoring the `gypfile: false` that tells npm
|
|
207
|
+
not to bother -- and a runner whose Visual Studio is newer than node-gyp
|
|
208
|
+
knows about simply fails. It never needed compiling: the package ships a
|
|
209
|
+
prebuilt binary for every platform it supports, and its loader prefers one
|
|
210
|
+
over anything built locally, so what node-gyp produced here was never
|
|
211
|
+
loaded. On Linux, dpkg refuses to build a `.deb` without a maintainer, and
|
|
212
|
+
nothing named one.
|
|
213
|
+
|
|
214
|
+
- **The release workflow can be rehearsed.** Run with the tag box empty, it
|
|
215
|
+
builds the branch on all three platforms and publishes nothing. Finding out
|
|
216
|
+
whether a build works should not cost a version number each time.
|
|
217
|
+
|
|
218
|
+
## 0.6.1 — 2026-09-12
|
|
219
|
+
|
|
220
|
+
### Added
|
|
221
|
+
|
|
222
|
+
- **A `release` workflow** builds the application on macOS, Windows and Linux --
|
|
223
|
+
each on its own machine, since an installer cannot honestly be built anywhere
|
|
224
|
+
else -- and attaches the `.dmg`, `.exe`, AppImage and `.deb` to the release
|
|
225
|
+
for a `v*` tag. It signs and notarises where the secrets exist and produces
|
|
226
|
+
unsigned builds where they do not, so a fork of this repository can still
|
|
227
|
+
build it.
|
|
228
|
+
|
|
229
|
+
### Fixed
|
|
230
|
+
|
|
231
|
+
- **The packaging script could not have run on Windows.** It started
|
|
232
|
+
electron-builder through the shim in `node_modules/.bin`, which is a `.cmd`
|
|
233
|
+
there and something node will not spawn without a shell. It runs the
|
|
234
|
+
builder's own entry file instead -- the same file on every platform -- and
|
|
235
|
+
the check that refuses a stale bundle now knows where Windows and Linux keep
|
|
236
|
+
the archive as well as where macOS does.
|
|
237
|
+
|
|
238
|
+
- **An empty secret is not a certificate.** A CI job passes every secret it was
|
|
239
|
+
told about whether the repository holds one or not, so a build with no
|
|
240
|
+
signing certificate was handed `CSC_LINK=""`. electron-builder reads
|
|
241
|
+
"defined" as "use it": it took the empty string for the path to a
|
|
242
|
+
certificate, resolved it against the project directory, and stopped with
|
|
243
|
+
"`<repo>/app not a file`" -- a message with no visible relationship to its
|
|
244
|
+
cause. Blank credentials are dropped before the builder starts, so a build
|
|
245
|
+
without a certificate is simply unsigned.
|
|
246
|
+
|
|
247
|
+
- **A `.DS_Store` could make a current bundle look stale.** Finder leaves one in
|
|
248
|
+
any directory somebody has looked at, and the staleness check was counting it
|
|
249
|
+
as input to the bundle even though nothing packs it.
|
|
250
|
+
|
|
5
251
|
## 0.6.0 — 2026-09-12
|
|
6
252
|
|
|
7
253
|
### Added
|
package/README.md
CHANGED
|
@@ -110,8 +110,25 @@ the journal or a log. There is a parchment and a dark setting:
|
|
|
110
110
|
**Getting it.** `synartesis desktop` opens it, and says where to get it if it is
|
|
111
111
|
not installed. It is a separate download on purpose: shipping a browser engine
|
|
112
112
|
inside a CLI would put 200 MB into every install of a command that is a few
|
|
113
|
-
hundred kilobytes.
|
|
114
|
-
|
|
113
|
+
hundred kilobytes.
|
|
114
|
+
|
|
115
|
+
On macOS it installs the way anything does — open the `.dmg`, drag Synartesis to
|
|
116
|
+
Applications — and on Windows the `.exe` installer puts it where the Start menu
|
|
117
|
+
can find it. After that, either the icon or `synartesis desktop` opens it; the
|
|
118
|
+
command looks where each platform actually installs things rather than asking
|
|
119
|
+
you to remember a path.
|
|
120
|
+
|
|
121
|
+
**The builds are not signed yet, and the first launch says so.** macOS refuses
|
|
122
|
+
an application it cannot check with Apple: open System Settings → Privacy &
|
|
123
|
+
Security and press *Open Anyway*, or `xattr -dr com.apple.quarantine
|
|
124
|
+
/Applications/Synartesis.app` to say the same thing in one line. Windows shows
|
|
125
|
+
a SmartScreen warning, behind *More info*. Both of those are the operating
|
|
126
|
+
system telling you the truth — nobody has vouched for this binary — and the
|
|
127
|
+
honest fix is a Developer ID certificate rather than a page telling you to
|
|
128
|
+
click past it. Building from the clone below avoids the question entirely,
|
|
129
|
+
since an application you built is one you have already vouched for.
|
|
130
|
+
|
|
131
|
+
To build it yourself instead:
|
|
115
132
|
|
|
116
133
|
```bash
|
|
117
134
|
pnpm install && pnpm app:dist
|
|
@@ -121,8 +138,9 @@ That writes an installer for the machine it runs on to `app/release` — a `.dmg
|
|
|
121
138
|
and a `.app` on macOS, an `.exe` on Windows, an AppImage and a `.deb` on Linux.
|
|
122
139
|
It is unsigned, so it runs where it was built and Gatekeeper refuses it
|
|
123
140
|
anywhere it has been downloaded to: signing and notarisation need an Apple
|
|
124
|
-
developer account, and [`app/README.md`](app/README.md) lists
|
|
125
|
-
|
|
141
|
+
developer account, and [`app/README.md`](app/README.md) lists exactly what they
|
|
142
|
+
want. The `release` workflow builds all three platforms on their own machines
|
|
143
|
+
and attaches the installers to the release for a tag. Both the window and the terminal share
|
|
126
144
|
one journal, so either can undo what the other did.
|
|
127
145
|
|
|
128
146
|
## What it can and cannot do
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "synartesis",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.10",
|
|
4
4
|
"description": "An undo layer for AI agents.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"private": false,
|
|
@@ -66,6 +66,12 @@
|
|
|
66
66
|
"yaml": "^2.9.0",
|
|
67
67
|
"zod": "^4.4.3"
|
|
68
68
|
},
|
|
69
|
+
"//pnpm": "better-sqlite3 ships a prebuilt binary for every platform it supports, and its loader prefers one over anything compiled locally -- so what node-gyp builds here is never loaded. npm knows not to bother, because the package sets gypfile: false; pnpm builds it anyway, which needs a C toolchain on every machine that installs this and fails outright on a Windows runner whose Visual Studio is newer than node-gyp.",
|
|
70
|
+
"pnpm": {
|
|
71
|
+
"neverBuiltDependencies": [
|
|
72
|
+
"better-sqlite3"
|
|
73
|
+
]
|
|
74
|
+
},
|
|
69
75
|
"devDependencies": {
|
|
70
76
|
"@anthropic-ai/sdk": "^0.125.0",
|
|
71
77
|
"@electron/notarize": "^3.1.1",
|