@mercury-fw/channel-http 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/CHANGELOG.md CHANGED
@@ -1,5 +1,19 @@
1
1
  # @mercury-fw/channel-http
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7a76257: - `GET /version` also answers the app's own version when its config declares one: `{ ok: true, version, app: { version } }`. Still no token; without one the body is the same as before.
8
+ - Needs the framework at 0.65 or later (peer range raised).
9
+
10
+ ## 0.13.2
11
+
12
+ ### Patch Changes
13
+
14
+ - 1e7fdeb: - `POST /turn { resume: true }` with nothing left to resume streams a single `final` whose text says the answer is no longer available, instead of an empty one, which a UI shows like any answer; an empty `final` now always means the model had nothing to add.
15
+ - Needs the framework at 0.61 or later (peer range raised).
16
+
3
17
  ## 0.13.1
4
18
 
5
19
  ### Patch Changes
package/README.md CHANGED
@@ -4,7 +4,7 @@ Gives a [Mercury](https://github.com/lucabro81/mercury-fw) agent an HTTP surface
4
4
 
5
5
  On Mercury's documentation site: [its page](https://lucabro81.github.io/mercury-fw/plugins/channel-http/).
6
6
 
7
- This version is written for version 6 of the channel contract, the one that brings the channels' texts in the person's language, and needs the framework at 0.59 or later, the first whose core gives channels its version (`GET /version`). A core with an older contract skips it, and the log says why.
7
+ This version is written for version 6 of the channel contract, the one that brings the channels' texts in the person's language, and needs the framework at 0.65 or later, the first whose core gives channels the app's version (`GET /version`); since 0.61 the core says when a resumed turn's answer is no longer available (`resume` below). A core with an older contract skips it, and the log says why.
8
8
 
9
9
  ```bash
10
10
  bun add @mercury-fw/channel-http
@@ -51,7 +51,7 @@ Runs one conversational turn; the reply streams back as Server-Sent Events.
51
51
  |---|---|---|---|
52
52
  | `text` | string | yes, unless `opening` or `resume` | The user message. A bare confirmation token here confirms a staged action (see the `pending` event) without invoking the model; when the action hands its result back to the model, the model's answer streams on this same request. |
53
53
  | `opening` | `true` | no | The assistant speaks first, before the person writes anything: what a UI asks right after someone signs in, when `GET /me` says the assistant doesn't know their name. It introduces itself and asks how to call them, and saves the answer once they give it. For someone it already knows, the stream is a single `final` with an empty text. Needs `conversationId`; `text` is ignored. |
54
- | `resume` | `true` | no | The turn a `POST /confirm` answered `resume: true` for: the model answers on what the confirmed action handed back. Needs `conversationId`; `text` is ignored. With nothing to resume, the stream is a single `final` with an empty text. |
54
+ | `resume` | `true` | no | The turn a `POST /confirm` answered `resume: true` for: the model answers on what the confirmed action handed back. Needs `conversationId`; `text` is ignored. With nothing left to resume (more than five minutes after the confirmation, a restart in between, or a turn already resumed), the stream is a single `final` whose text says the answer is no longer available, in the person's language. |
55
55
  | `conversationId` | string | no | Opaque, client-owned id that continues one of your conversations: letters, digits, `-` and `_`, up to 128 characters (a UUID fits) once surrounding whitespace is trimmed, `400` otherwise. Sent again, however long after, it continues that conversation, rebuilt from the archive if Mercury had freed it (see `HTTP_SURFACE_RESUME_MAX_CHARS`). Omitted ⇒ a fresh one-off session that can't be continued. |
56
56
 
57
57
  **Responses**: `200 text/event-stream` (the events below); `400` if `text` is missing, an opening has no `conversationId`, the body isn't JSON, or `conversationId` has other characters than the ones above.
@@ -117,11 +117,11 @@ All `GET`, all JSON, all reporting state already held in-process. They need an a
117
117
  | `GET /wiki/list` | `{ files: [...] }` — `curated/...` and `personal/...` paths |
118
118
  | `GET /wiki/read?path=<path>` | `{ content }` — a path as `/wiki/list` gives it; `400` if `path` is missing, `404` if it isn't among yours |
119
119
  | `GET /wiki/grep?pattern=<regex>` | `{ matches: [...] }` — `400` if `pattern` is missing |
120
- | `GET /memory/scroll?collection=<name>&limit=<n>&offset=<cursor>` | one page of your points in a collection kept per person (verbatim archive, episodic memory, semantic facts); `400` for any other collection |
120
+ | `GET /memory/scroll?collection=<name>&limit=<n>&offset=<cursor>` | one page of your points in a collection kept per person (verbatim archive, episodic memory, semantic facts), each with its whole payload (a verbatim answer's `displays` and `calls` included); `400` for any other collection |
121
121
  | `GET /openapi.yaml` | the OpenAPI document for this surface (`text/yaml`) |
122
122
 
123
123
  Conversation history and the conversation list are backed by the durable verbatim archive; they degrade to empty when the vector store is unreachable.
124
124
 
125
125
  ## `GET /version`
126
126
 
127
- Which Mercury this is, for a UI to show: `{ ok: true, version }`, the framework's version as `major.minor.patch` (`"0.59.0"`), the one of `@mercury-fw/core`, not this channel's own. It needs no token.
127
+ Which Mercury this is, for a UI to show: `{ ok: true, version }`, the framework's version as `major.minor.patch` (`"0.59.0"`), the one of `@mercury-fw/core`, not this channel's own. When the app's config declares its own version (`version` in `mercury.config.ts`, its `package.json`'s, as a scaffolded app does), it comes too, as it is: `{ ok: true, version: "0.65.0", app: { version: "1.2.0" } }`. The app moves that number itself, and a new one shows once the app is rebuilt. It needs no token, so anyone who reaches the port sees both.
@@ -44,6 +44,8 @@ export type HttpProviderDeps = {
44
44
  i18n?: ChannelI18n;
45
45
  /** The framework's version, served on `/version` (`ctx.frameworkVersion`). */
46
46
  version?: string;
47
+ /** The app's own version, served on `/version` next to it (`ctx.appVersion`). */
48
+ appVersion?: string;
47
49
  };
48
50
  export declare function createHttpProvider(deps: HttpProviderDeps): Provider & {
49
51
  stop(): Promise<void>;
@@ -159,6 +159,8 @@ export type HttpServerDeps = TurnRequestDeps & {
159
159
  assistantName?: string;
160
160
  /** The framework's version; `/version` is mounted only with it. */
161
161
  version?: string;
162
+ /** The app's own version, served on `/version` next to the framework's. */
163
+ appVersion?: string;
162
164
  };
163
165
  /** Starts the HTTP surface: `POST /turn` (4a) plus the read-only routes (4b)
164
166
  * when `reads` is supplied. */
package/http-provider.ts CHANGED
@@ -41,6 +41,8 @@ export type HttpProviderDeps = {
41
41
  i18n?: ChannelI18n;
42
42
  /** The framework's version, served on `/version` (`ctx.frameworkVersion`). */
43
43
  version?: string;
44
+ /** The app's own version, served on `/version` next to it (`ctx.appVersion`). */
45
+ appVersion?: string;
44
46
  };
45
47
 
46
48
  export function createHttpProvider(deps: HttpProviderDeps): Provider & { stop(): Promise<void> } {
@@ -63,6 +65,7 @@ export function createHttpProvider(deps: HttpProviderDeps): Provider & { stop():
63
65
  ...(deps.assistantName === undefined ? {} : { assistantName: deps.assistantName }),
64
66
  ...(deps.i18n === undefined ? {} : { i18n: deps.i18n }),
65
67
  ...(deps.version === undefined ? {} : { version: deps.version }),
68
+ ...(deps.appVersion === undefined ? {} : { appVersion: deps.appVersion }),
66
69
  });
67
70
  deps.logins?.accept(deps.logins.callbackUrl);
68
71
  },
package/http-server.ts CHANGED
@@ -580,13 +580,15 @@ export function readRoutes(
580
580
  }
581
581
 
582
582
  /**
583
- * `GET /version`: which Mercury this is (the framework's version), for any
584
- * front end to show. Nobody is asked who they are, like `/openapi.yaml`.
583
+ * `GET /version`: which Mercury this is (the framework's version, and the
584
+ * app's own when it declares one), for any front end to show. Nobody is asked
585
+ * who they are, like `/openapi.yaml`.
585
586
  */
586
- function versionRoutes(version: string, corsOrigin = "*"): Record<string, ReadRoute> {
587
+ function versionRoutes(version: string, appVersion: string | undefined, corsOrigin = "*"): Record<string, ReadRoute> {
588
+ const body = appVersion === undefined ? { ok: true, version } : { ok: true, version, app: { version: appVersion } };
587
589
  return {
588
590
  "/version": {
589
- GET: () => Response.json({ ok: true, version }, { headers: corsHeaders(corsOrigin) }),
591
+ GET: () => Response.json(body, { headers: corsHeaders(corsOrigin) }),
590
592
  OPTIONS: () => preflight(corsOrigin),
591
593
  },
592
594
  };
@@ -607,6 +609,8 @@ export type HttpServerDeps = TurnRequestDeps & {
607
609
  assistantName?: string;
608
610
  /** The framework's version; `/version` is mounted only with it. */
609
611
  version?: string;
612
+ /** The app's own version, served on `/version` next to the framework's. */
613
+ appVersion?: string;
610
614
  };
611
615
 
612
616
  /** Starts the HTTP surface: `POST /turn` (4a) plus the read-only routes (4b)
@@ -638,7 +642,7 @@ export function startHttpServer(deps: HttpServerDeps): ReturnType<typeof Bun.ser
638
642
  OPTIONS: () => preflight(origin),
639
643
  },
640
644
  "/openapi.yaml": { GET: () => openApiResponse(origin), OPTIONS: () => preflight(origin) },
641
- ...(deps.version === undefined ? {} : versionRoutes(deps.version, origin)),
645
+ ...(deps.version === undefined ? {} : versionRoutes(deps.version, deps.appVersion, origin)),
642
646
  ...(deps.reads ? readRoutes(deps.reads, deps.authenticate, origin, deps.admit, deps.settings) : {}),
643
647
  ...(deps.completeLogin ? loginRoutes(deps.completeLogin, deps.assistantName, deps.i18n) : {}),
644
648
  ...(deps.linking ? linkRoutes({ ...deps, start: deps.linking.start, corsOrigin: origin }) : {}),
package/index.ts CHANGED
@@ -52,6 +52,7 @@ export const httpChannel: ChannelPlugin = {
52
52
  ...(resumeMaxChars === undefined ? {} : { resumeMaxChars }),
53
53
  ...(ctx.assistantName === undefined ? {} : { assistantName: ctx.assistantName }),
54
54
  ...(ctx.frameworkVersion === undefined ? {} : { version: ctx.frameworkVersion }),
55
+ ...(ctx.appVersion === undefined ? {} : { appVersion: ctx.appVersion }),
55
56
  ...(logins ? { logins: { callbackUrl: `${publicUrl}/login/callback`, accept: logins.accept, complete: logins.complete } } : {}),
56
57
  });
57
58
  },
package/openapi.yaml CHANGED
@@ -80,7 +80,9 @@ info:
80
80
  (a page read after the caller allowed it, for example). Confirming one by
81
81
  `POST /turn` streams the model's answer on that same stream; `POST /confirm`
82
82
  answers `resume: true`, and the client then opens
83
- `POST /turn { resume: true, conversationId }` to hear it.
83
+ `POST /turn { resume: true, conversationId }` to hear it. The answer waits
84
+ five minutes and is heard once: later, after a restart, or a second time,
85
+ that `final`'s text says it's no longer available.
84
86
  security:
85
87
  - bearerAuth: []
86
88
  servers:
@@ -593,12 +595,13 @@ paths:
593
595
  get:
594
596
  summary: Which Mercury this is
595
597
  description: >
596
- The framework's version, `major.minor.patch`, for a UI to show. Needs
597
- no bearer token.
598
+ The framework's version, `major.minor.patch`, for a UI to show, and
599
+ the app's own when its config declares one (`app.version`, its
600
+ `package.json`'s, shown as the app has it). Needs no bearer token.
598
601
  security: []
599
602
  responses:
600
603
  "200":
601
- description: The framework's version.
604
+ description: The framework's version, and the app's when it declares one.
602
605
  content:
603
606
  application/json:
604
607
  schema:
@@ -610,6 +613,15 @@ paths:
610
613
  type: string
611
614
  pattern: '^\d+\.\d+\.\d+$'
612
615
  examples: ["0.59.0"]
616
+ app:
617
+ type: object
618
+ description: The app's own version; absent when the app declares none.
619
+ required: [version]
620
+ properties:
621
+ version:
622
+ type: string
623
+ description: As the app's `package.json` has it, not checked.
624
+ examples: ["1.2.0"]
613
625
  /openapi.yaml:
614
626
  get:
615
627
  summary: This OpenAPI document
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mercury-fw/channel-http",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -18,11 +18,11 @@
18
18
  "access": "public"
19
19
  },
20
20
  "peerDependencies": {
21
- "@mercury-fw/channel-types": ">=0.59.0 <1.0.0"
21
+ "@mercury-fw/channel-types": ">=0.65.0 <1.0.0"
22
22
  },
23
23
  "devDependencies": {
24
- "@mercury-fw/channel-types": "0.59.2",
25
- "@mercury-fw/plugin-types": "0.59.2",
24
+ "@mercury-fw/channel-types": "0.65.0",
25
+ "@mercury-fw/plugin-types": "0.65.0",
26
26
  "@mercury-fw/typescript-config": "*",
27
27
  "@types/bun": "^1.4.2",
28
28
  "typescript": "^6.0.3"