diff --git a/.changeset/knowledge-manifest-turso-origin.md b/.changeset/knowledge-manifest-turso-origin.md new file mode 100644 index 0000000000..926f407b71 --- /dev/null +++ b/.changeset/knowledge-manifest-turso-origin.md @@ -0,0 +1,36 @@ +--- +'@objectstack/service-settings': patch +--- + +Tell the operator where `@objectstack/knowledge-turso` comes from instead of +naming a package this repo does not build + +An operator who selects the `turso` knowledge adapter in **Settings → AI & +Embedder** and runs the connection test was told: "Mount +`@objectstack/knowledge-turso` to exercise live calls." That package is in no +directory of this repo (0 path hits on `main`; `knowledge-memory` and +`knowledge-ragflow` return 8 each under the identical command, so the zero is +real), and the message said nothing about where it does come from — leaving the +instruction un-followable at exactly the moment it is read. + +The prior question the card turned on — *is it published anywhere?* — is now +measured rather than assumed. Against the public npm registry on 2026-08-23, +with `@objectstack/spec` and `@objectstack/cli` as positive controls and +`@objectstack/security-enterprise` as a known-private negative control: +`@objectstack/knowledge-turso` **is published**, `latest` 6.9.0 (2026-05-27), +nine versions from 6.4.0. So the option stays — dropping it would have deleted a +working adapter. + +What it is *not* is co-installable with this platform version: 6.9.0 exact-pins +`@objectstack/spec@6.9.0` while this repo ships 17.2.0, so mounting it resolves a +second spec rather than reusing this one. The runtime message now names the +package, says this platform does not ship it, points at the ObjectStack Cloud +monorepo where it is built, and tells the operator to check for a release +matching their platform version — the framework#3366 discipline that an install +hint must carry its own edition/version boundary. + +The manifest's adapter-list comment loses the undated "mirrors the plugin +packages currently published" claim that stopped being true with nothing to +catch it, and gains the measurement with its date and method so the next reader +can re-run it. No behaviour change: `ok` and `severity` are untouched on every +branch of the test action. diff --git a/packages/services/service-settings/src/manifests/knowledge.manifest.test.ts b/packages/services/service-settings/src/manifests/knowledge.manifest.test.ts index 654be2503b..7eb2e25c3d 100644 --- a/packages/services/service-settings/src/manifests/knowledge.manifest.test.ts +++ b/packages/services/service-settings/src/manifests/knowledge.manifest.test.ts @@ -97,6 +97,40 @@ describe('knowledgeTestActionHandler', () => { expect(r.ok).toBe(true); }); + // The turso adapter's plugin package is NOT built in this repo, so the live-call + // hint an operator reads in Settings -> AI & Embedder cannot be a bare "Mount + // @objectstack/knowledge-turso": that instruction was un-followable — it named a + // package with no directory here and no statement of where it comes from. Pinned + // as a property (names the package AND where it ships), not as a literal, so the + // wording can be improved without the guard going stale. + it('turso live-call hint says where the out-of-repo package comes from', async () => { + const r = await knowledgeTestActionHandler({ + values: { adapter: 'turso', turso_url: 'file:./knowledge.db' }, + } as any); + expect(r.ok).toBe(true); + const message = String(r.message); + expect(message).toContain('@objectstack/knowledge-turso'); + expect(message).toMatch(/ObjectStack Cloud monorepo/); + // the un-followable form this card retired: named, with no origin stated + expect(message).not.toMatch(/Mount @objectstack\/knowledge-turso to exercise live calls/); + }); + + // Contrast, so the assertion above cannot be satisfied by blanket-rewording every + // hint: ragflow's plugin IS built here, and its hint stays the plain mount line. + it('ragflow live-call hint stays a plain mount line (its plugin is built here)', async () => { + const r = await knowledgeTestActionHandler({ + values: { + adapter: 'ragflow', + ragflow_base_url: 'http://localhost:9380', + ragflow_api_key: 'k', + }, + } as any); + expect(r.ok).toBe(true); + expect(String(r.message)).toContain( + 'Mount @objectstack/knowledge-ragflow to exercise live calls', + ); + }); + it('rejects ragflow without base URL', async () => { const r = await knowledgeTestActionHandler({ values: { adapter: 'ragflow', ragflow_api_key: 'k' }, diff --git a/packages/services/service-settings/src/manifests/knowledge.manifest.ts b/packages/services/service-settings/src/manifests/knowledge.manifest.ts index fe223793ae..6edd7dad22 100644 --- a/packages/services/service-settings/src/manifests/knowledge.manifest.ts +++ b/packages/services/service-settings/src/manifests/knowledge.manifest.ts @@ -10,12 +10,25 @@ import type { SettingsActionHandler } from '../settings-service.types.js'; * knowledge sources and any future agent that needs to embed ad-hoc * inputs. * - * Adapter list mirrors the plugin packages currently published: - * - memory @objectstack/knowledge-memory (dev / test reference) - * - turso @objectstack/knowledge-turso (libSQL native F32_BLOB — - * works for cloud Turso AND - * local file mode) - * - ragflow @objectstack/knowledge-ragflow (external RAGFlow service) + * Adapter list — two of these plugin packages are built in this repo and one + * is not, which is the difference that matters to an operator told to mount + * one of them: + * - memory @objectstack/knowledge-memory built here (dev / test ref) + * - ragflow @objectstack/knowledge-ragflow built here (external RAGFlow) + * - turso @objectstack/knowledge-turso NOT built here — libSQL native + * F32_BLOB, works for cloud + * Turso AND local file mode + * + * Spelled out for `turso` because the undated claim that used to stand here — + * "mirrors the plugin packages currently published" — stopped being true and + * nothing caught it. The package IS published on the public npm registry, but + * on its own version track: `latest` was 6.9.0 (published 2026-05-27) while + * this repo shipped 17.2.0, and 6.9.0 exact-pins `@objectstack/spec@6.9.0`, so + * mounting it into an app on this platform version resolves a SECOND spec + * rather than reusing this one. Its source lives in the ObjectStack Cloud + * monorepo (see this repo's README). Measured against the registry on + * 2026-08-23 with `@objectstack/spec` + `@objectstack/cli` as positive + * controls; re-measure before treating those numbers as current. * * As with the AI manifest, the real adapter wiring happens in the * knowledge plugins; this manifest is the canonical settings surface @@ -155,7 +168,11 @@ export const knowledgeTestActionHandler: SettingsActionHandler = async ({ values return { ok: true, severity: 'info', - message: `Turso adapter configured (${u}). Mount @objectstack/knowledge-turso to exercise live calls.`, + message: + `Turso adapter configured (${u}). Live calls need @objectstack/knowledge-turso, ` + + 'which this platform does not ship: it is built in the ObjectStack Cloud monorepo ' + + 'and published on its own version track, so check that it offers a release ' + + 'compatible with your platform version before mounting it.', }; }