@meso.ai/client 0.1.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/__tests__/client.test.d.ts +1 -0
- package/dist/confirm.d.ts +21 -0
- package/dist/index.cjs +3 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +148 -0
- package/dist/replay.d.ts +3 -0
- package/dist/session.d.ts +23 -0
- package/dist/store.d.ts +23 -0
- package/dist/transport.d.ts +16 -0
- package/package.json +39 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export interface ToolConfirmRequest {
|
|
2
|
+
tool_call_id: string;
|
|
3
|
+
approved: boolean;
|
|
4
|
+
session_id?: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ToolConfirmChannel {
|
|
7
|
+
confirm(request: ToolConfirmRequest): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export interface FetchConfirmChannelOptions {
|
|
10
|
+
/** Endpoint that receives tool approval decisions. Default /api/tools/confirm */
|
|
11
|
+
url?: string;
|
|
12
|
+
headers?: Record<string, string>;
|
|
13
|
+
}
|
|
14
|
+
/** POST tool confirm decisions to a backend endpoint. */
|
|
15
|
+
export declare class FetchConfirmChannel implements ToolConfirmChannel {
|
|
16
|
+
private url;
|
|
17
|
+
private headers;
|
|
18
|
+
constructor(options?: FetchConfirmChannelOptions);
|
|
19
|
+
confirm(request: ToolConfirmRequest): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
export declare function confirmTool(channel: ToolConfirmChannel, toolCallId: string, approved: boolean, sessionId?: string): Promise<void>;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const l=require("@meso.ai/types");class p{constructor(e){this.data={...(e==null?void 0:e.initial)??{}}}async getMessages(e){return[...this.data[e]??[]]}async saveMessages(e,s){this.data[e]=[...s]}}class M{async stream(e,s){const d=e.method??(e.body?"POST":"GET"),o=await fetch(e.url,{method:d,headers:{...d==="POST"?{"Content-Type":"application/json"}:{},...e.headers},body:e.body?JSON.stringify(e.body):void 0,signal:e.signal});if(!o.ok)throw new Error(`HTTP ${o.status}`);const y=o.body.getReader(),f=new TextDecoder;let t="",n={...l.createInitialStreamState(),status:"streaming"};for(;;){const{done:c,value:r}=await y.read();if(c)break;t+=f.decode(r,{stream:!0});const u=t.split(`
|
|
2
|
+
`);t=u.pop()??"";for(const h of u){const i=l.parseSSELine(h);if(i&&(n=l.applyEvent(n,i),s(i,n),i.type==="done"||i.type==="error"))return n}}return n}}class b{constructor(e){this.url=(e==null?void 0:e.url)??"/api/tools/confirm",this.headers=(e==null?void 0:e.headers)??{}}async confirm(e){const s=await fetch(this.url,{method:"POST",headers:{"Content-Type":"application/json",...this.headers},body:JSON.stringify(e)});if(!s.ok)throw new Error(`Tool confirm failed: HTTP ${s.status}`)}}async function I(a,e,s,d){await a.confirm({tool_call_id:e,approved:s,session_id:d})}let T=0;function S(a){return T+=1,`${a}-${T}`}function O(a){const{sessionId:e,streamUrl:s,transport:d=new M,store:o=new p,confirmChannel:y=new b,headers:f,onStreamState:t}=a;let n=[],c=l.createInitialStreamState(),r=null;const u=async()=>{await o.saveMessages(e,n)};return{sessionId:e,get messages(){return n},get streaming(){return c},async load(){n=await o.getMessages(e)},resetStream(){r==null||r.abort(),c=l.createInitialStreamState(),t==null||t(c)},async sendMessage(i){r==null||r.abort(),r=new AbortController;const g={id:S("user"),role:"user",content:i,timestamp:new Date().toISOString()};n=[...n,g],await u(),c={...l.createInitialStreamState(),status:"streaming"},t==null||t(c);const m=await d.stream({url:s,method:"POST",headers:f,body:{session_id:e,message:i},signal:r.signal},(E,w)=>{c=w,t==null||t(w)});c=m,t==null||t(m);const v={id:S("assistant"),role:"assistant",content:m.textContent,streamState:m,timestamp:new Date().toISOString()};n=[...n,v],await u()},async confirmToolCall(i,g){await I(y,i,g,e)}}}function C(a){return a.split(`
|
|
3
|
+
`).reduce((s,d)=>{const o=l.parseSSELine(d);return o?l.applyEvent(s,o):s},{...l.createInitialStreamState(),status:"streaming"})}exports.FetchConfirmChannel=b;exports.FetchMesoTransport=M;exports.InMemorySessionStore=p;exports.confirmTool=I;exports.createMesoSession=O;exports.replayTurn=C;
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export { createMesoSession } from './session';
|
|
2
|
+
export type { CreateMesoSessionOptions, MesoSession } from './session';
|
|
3
|
+
export { InMemorySessionStore } from './store';
|
|
4
|
+
export type { MesoMessage, MesoSessionStore } from './store';
|
|
5
|
+
export { FetchMesoTransport } from './transport';
|
|
6
|
+
export type { MesoTransport, MesoTransportRequest } from './transport';
|
|
7
|
+
export { FetchConfirmChannel, confirmTool } from './confirm';
|
|
8
|
+
export type { ToolConfirmChannel, ToolConfirmRequest } from './confirm';
|
|
9
|
+
export { replayTurn } from './replay';
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
import { createInitialStreamState as u, parseSSELine as M, applyEvent as b } from "@meso.ai/types";
|
|
2
|
+
class O {
|
|
3
|
+
constructor(e) {
|
|
4
|
+
this.data = { ...(e == null ? void 0 : e.initial) ?? {} };
|
|
5
|
+
}
|
|
6
|
+
async getMessages(e) {
|
|
7
|
+
return [...this.data[e] ?? []];
|
|
8
|
+
}
|
|
9
|
+
async saveMessages(e, t) {
|
|
10
|
+
this.data[e] = [...t];
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
class C {
|
|
14
|
+
async stream(e, t) {
|
|
15
|
+
const l = e.method ?? (e.body ? "POST" : "GET"), o = await fetch(e.url, {
|
|
16
|
+
method: l,
|
|
17
|
+
headers: {
|
|
18
|
+
...l === "POST" ? { "Content-Type": "application/json" } : {},
|
|
19
|
+
...e.headers
|
|
20
|
+
},
|
|
21
|
+
body: e.body ? JSON.stringify(e.body) : void 0,
|
|
22
|
+
signal: e.signal
|
|
23
|
+
});
|
|
24
|
+
if (!o.ok) throw new Error(`HTTP ${o.status}`);
|
|
25
|
+
const g = o.body.getReader(), h = new TextDecoder();
|
|
26
|
+
let s = "", n = { ...u(), status: "streaming" };
|
|
27
|
+
for (; ; ) {
|
|
28
|
+
const { done: c, value: r } = await g.read();
|
|
29
|
+
if (c) break;
|
|
30
|
+
s += h.decode(r, { stream: !0 });
|
|
31
|
+
const d = s.split(`
|
|
32
|
+
`);
|
|
33
|
+
s = d.pop() ?? "";
|
|
34
|
+
for (const y of d) {
|
|
35
|
+
const i = M(y);
|
|
36
|
+
if (i && (n = b(n, i), t(i, n), i.type === "done" || i.type === "error"))
|
|
37
|
+
return n;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return n;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
class I {
|
|
44
|
+
constructor(e) {
|
|
45
|
+
this.url = (e == null ? void 0 : e.url) ?? "/api/tools/confirm", this.headers = (e == null ? void 0 : e.headers) ?? {};
|
|
46
|
+
}
|
|
47
|
+
async confirm(e) {
|
|
48
|
+
const t = await fetch(this.url, {
|
|
49
|
+
method: "POST",
|
|
50
|
+
headers: { "Content-Type": "application/json", ...this.headers },
|
|
51
|
+
body: JSON.stringify(e)
|
|
52
|
+
});
|
|
53
|
+
if (!t.ok) throw new Error(`Tool confirm failed: HTTP ${t.status}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
async function P(a, e, t, l) {
|
|
57
|
+
await a.confirm({
|
|
58
|
+
tool_call_id: e,
|
|
59
|
+
approved: t,
|
|
60
|
+
session_id: l
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
let T = 0;
|
|
64
|
+
function p(a) {
|
|
65
|
+
return T += 1, `${a}-${T}`;
|
|
66
|
+
}
|
|
67
|
+
function _(a) {
|
|
68
|
+
const {
|
|
69
|
+
sessionId: e,
|
|
70
|
+
streamUrl: t,
|
|
71
|
+
transport: l = new C(),
|
|
72
|
+
store: o = new O(),
|
|
73
|
+
confirmChannel: g = new I(),
|
|
74
|
+
headers: h,
|
|
75
|
+
onStreamState: s
|
|
76
|
+
} = a;
|
|
77
|
+
let n = [], c = u(), r = null;
|
|
78
|
+
const d = async () => {
|
|
79
|
+
await o.saveMessages(e, n);
|
|
80
|
+
};
|
|
81
|
+
return {
|
|
82
|
+
sessionId: e,
|
|
83
|
+
get messages() {
|
|
84
|
+
return n;
|
|
85
|
+
},
|
|
86
|
+
get streaming() {
|
|
87
|
+
return c;
|
|
88
|
+
},
|
|
89
|
+
async load() {
|
|
90
|
+
n = await o.getMessages(e);
|
|
91
|
+
},
|
|
92
|
+
resetStream() {
|
|
93
|
+
r == null || r.abort(), c = u(), s == null || s(c);
|
|
94
|
+
},
|
|
95
|
+
async sendMessage(i) {
|
|
96
|
+
r == null || r.abort(), r = new AbortController();
|
|
97
|
+
const m = {
|
|
98
|
+
id: p("user"),
|
|
99
|
+
role: "user",
|
|
100
|
+
content: i,
|
|
101
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
102
|
+
};
|
|
103
|
+
n = [...n, m], await d(), c = { ...u(), status: "streaming" }, s == null || s(c);
|
|
104
|
+
const f = await l.stream(
|
|
105
|
+
{
|
|
106
|
+
url: t,
|
|
107
|
+
method: "POST",
|
|
108
|
+
headers: h,
|
|
109
|
+
body: { session_id: e, message: i },
|
|
110
|
+
signal: r.signal
|
|
111
|
+
},
|
|
112
|
+
(E, w) => {
|
|
113
|
+
c = w, s == null || s(w);
|
|
114
|
+
}
|
|
115
|
+
);
|
|
116
|
+
c = f, s == null || s(f);
|
|
117
|
+
const v = {
|
|
118
|
+
id: p("assistant"),
|
|
119
|
+
role: "assistant",
|
|
120
|
+
content: f.textContent,
|
|
121
|
+
streamState: f,
|
|
122
|
+
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
123
|
+
};
|
|
124
|
+
n = [...n, v], await d();
|
|
125
|
+
},
|
|
126
|
+
async confirmToolCall(i, m) {
|
|
127
|
+
await P(g, i, m, e);
|
|
128
|
+
}
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
function $(a) {
|
|
132
|
+
return a.split(`
|
|
133
|
+
`).reduce(
|
|
134
|
+
(t, l) => {
|
|
135
|
+
const o = M(l);
|
|
136
|
+
return o ? b(t, o) : t;
|
|
137
|
+
},
|
|
138
|
+
{ ...u(), status: "streaming" }
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
export {
|
|
142
|
+
I as FetchConfirmChannel,
|
|
143
|
+
C as FetchMesoTransport,
|
|
144
|
+
O as InMemorySessionStore,
|
|
145
|
+
P as confirmTool,
|
|
146
|
+
_ as createMesoSession,
|
|
147
|
+
$ as replayTurn
|
|
148
|
+
};
|
package/dist/replay.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type StreamState } from '@meso.ai/types';
|
|
2
|
+
import type { MesoMessage, MesoSessionStore } from './store';
|
|
3
|
+
import { type MesoTransport } from './transport';
|
|
4
|
+
import { type ToolConfirmChannel } from './confirm';
|
|
5
|
+
export interface CreateMesoSessionOptions {
|
|
6
|
+
sessionId: string;
|
|
7
|
+
streamUrl: string;
|
|
8
|
+
transport?: MesoTransport;
|
|
9
|
+
store?: MesoSessionStore;
|
|
10
|
+
confirmChannel?: ToolConfirmChannel;
|
|
11
|
+
headers?: Record<string, string>;
|
|
12
|
+
onStreamState?: (state: StreamState) => void;
|
|
13
|
+
}
|
|
14
|
+
export interface MesoSession {
|
|
15
|
+
sessionId: string;
|
|
16
|
+
messages: MesoMessage[];
|
|
17
|
+
streaming: StreamState;
|
|
18
|
+
sendMessage(text: string): Promise<void>;
|
|
19
|
+
confirmToolCall(toolCallId: string, approved: boolean): Promise<void>;
|
|
20
|
+
load(): Promise<void>;
|
|
21
|
+
resetStream(): void;
|
|
22
|
+
}
|
|
23
|
+
export declare function createMesoSession(options: CreateMesoSessionOptions): MesoSession;
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { StreamState } from '@meso.ai/types';
|
|
2
|
+
export interface MesoMessage {
|
|
3
|
+
id: string;
|
|
4
|
+
role: 'user' | 'assistant';
|
|
5
|
+
content: string;
|
|
6
|
+
/** Snapshot of StreamState for assistant turns (optional). */
|
|
7
|
+
streamState?: StreamState;
|
|
8
|
+
timestamp?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface MesoSessionStore {
|
|
11
|
+
getMessages(sessionId: string): Promise<MesoMessage[]>;
|
|
12
|
+
saveMessages(sessionId: string, messages: MesoMessage[]): Promise<void>;
|
|
13
|
+
}
|
|
14
|
+
export interface InMemorySessionStoreOptions {
|
|
15
|
+
initial?: Record<string, MesoMessage[]>;
|
|
16
|
+
}
|
|
17
|
+
/** Simple in-memory store for demos and tests. */
|
|
18
|
+
export declare class InMemorySessionStore implements MesoSessionStore {
|
|
19
|
+
private data;
|
|
20
|
+
constructor(options?: InMemorySessionStoreOptions);
|
|
21
|
+
getMessages(sessionId: string): Promise<MesoMessage[]>;
|
|
22
|
+
saveMessages(sessionId: string, messages: MesoMessage[]): Promise<void>;
|
|
23
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type StreamState, type SSEEvent } from '@meso.ai/types';
|
|
2
|
+
export interface MesoTransportRequest {
|
|
3
|
+
url: string;
|
|
4
|
+
method?: 'GET' | 'POST';
|
|
5
|
+
headers?: Record<string, string>;
|
|
6
|
+
body?: Record<string, unknown>;
|
|
7
|
+
signal?: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
export interface MesoTransport {
|
|
10
|
+
/** Open an SSE stream and invoke onEvent for each parsed event. */
|
|
11
|
+
stream(request: MesoTransportRequest, onEvent: (event: SSEEvent, state: StreamState) => void): Promise<StreamState>;
|
|
12
|
+
}
|
|
13
|
+
/** Default fetch-based transport for browser and Node 18+. */
|
|
14
|
+
export declare class FetchMesoTransport implements MesoTransport {
|
|
15
|
+
stream(request: MesoTransportRequest, onEvent: (event: SSEEvent, state: StreamState) => void): Promise<StreamState>;
|
|
16
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@meso.ai/client",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Meso session layer — turn management, transport, tool confirm, replay",
|
|
5
|
+
"repository": {
|
|
6
|
+
"type": "git",
|
|
7
|
+
"url": "https://github.com/Grant-Huang/Meso.git",
|
|
8
|
+
"directory": "packages/meso-client"
|
|
9
|
+
},
|
|
10
|
+
"type": "module",
|
|
11
|
+
"main": "./dist/index.cjs",
|
|
12
|
+
"module": "./dist/index.js",
|
|
13
|
+
"types": "./dist/index.d.ts",
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"import": "./dist/index.js",
|
|
17
|
+
"require": "./dist/index.cjs",
|
|
18
|
+
"types": "./dist/index.d.ts"
|
|
19
|
+
}
|
|
20
|
+
},
|
|
21
|
+
"files": ["dist"],
|
|
22
|
+
"publishConfig": {
|
|
23
|
+
"access": "public"
|
|
24
|
+
},
|
|
25
|
+
"scripts": {
|
|
26
|
+
"build": "vite build && tsc -p tsconfig.build.json",
|
|
27
|
+
"type-check": "tsc --noEmit",
|
|
28
|
+
"test": "vitest run"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"@meso.ai/types": "workspace:*"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"typescript": "^5.6.3",
|
|
35
|
+
"vite": "^5.4.11",
|
|
36
|
+
"vite-plugin-dts": "^4.3.0",
|
|
37
|
+
"vitest": "^2.1.9"
|
|
38
|
+
}
|
|
39
|
+
}
|