@unfenced-ai/sdk 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/LICENSE +30 -0
- package/README.md +171 -0
- package/dist/client.d.ts +385 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +349 -0
- package/dist/client.js.map +1 -0
- package/dist/credentials.d.ts +14 -0
- package/dist/credentials.d.ts.map +1 -0
- package/dist/credentials.js +17 -0
- package/dist/credentials.js.map +1 -0
- package/dist/fetch.d.ts +16 -0
- package/dist/fetch.d.ts.map +1 -0
- package/dist/fetch.js +387 -0
- package/dist/fetch.js.map +1 -0
- package/dist/http.d.ts +76 -0
- package/dist/http.d.ts.map +1 -0
- package/dist/http.js +250 -0
- package/dist/http.js.map +1 -0
- package/dist/index.d.ts +53 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -0
- package/dist/library.d.ts +17 -0
- package/dist/library.d.ts.map +1 -0
- package/dist/library.js +25 -0
- package/dist/library.js.map +1 -0
- package/dist/memory.d.ts +13 -0
- package/dist/memory.d.ts.map +1 -0
- package/dist/memory.js +45 -0
- package/dist/memory.js.map +1 -0
- package/dist/permissions.d.ts +29 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +69 -0
- package/dist/permissions.js.map +1 -0
- package/dist/protocol.d.ts +296 -0
- package/dist/protocol.d.ts.map +1 -0
- package/dist/protocol.js +89 -0
- package/dist/protocol.js.map +1 -0
- package/dist/session.d.ts +97 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +88 -0
- package/dist/session.js.map +1 -0
- package/dist/sessions.d.ts +131 -0
- package/dist/sessions.d.ts.map +1 -0
- package/dist/sessions.js +197 -0
- package/dist/sessions.js.map +1 -0
- package/dist/token-usage.d.ts +11 -0
- package/dist/token-usage.d.ts.map +1 -0
- package/dist/token-usage.js +34 -0
- package/dist/token-usage.js.map +1 -0
- package/dist/types.d.ts +1409 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/url-identity.d.ts +8 -0
- package/dist/url-identity.d.ts.map +1 -0
- package/dist/url-identity.js +18 -0
- package/dist/url-identity.js.map +1 -0
- package/package.json +44 -0
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live-session tier: open a page, drive it, read it, close it.
|
|
3
|
+
*
|
|
4
|
+
* These are the bodies of the `Unfenced` methods under its `// ---- live
|
|
5
|
+
* sessions` heading, moved out and re-shaped from methods to functions that
|
|
6
|
+
* take a `Transport`. `open` and `switchAccount` also take the `client`, because
|
|
7
|
+
* they hand it to the `Session` they build. `this.request` became `http.request`
|
|
8
|
+
* and nothing else changed — the request paths, shapes, and comments are as they
|
|
9
|
+
* were.
|
|
10
|
+
*/
|
|
11
|
+
import { Transport } from "./http.js";
|
|
12
|
+
import { Session } from "./session.js";
|
|
13
|
+
import type { Unfenced } from "./client.js";
|
|
14
|
+
import type { ExtractedDoc } from "./protocol.js";
|
|
15
|
+
import type { Action, ActResult, ActExpectation, AtAction, DownloadInfo, Format, FormField, FormFillResult, OnAction, PageSnapshot, PendingApproval, ProviderSessionReason, ReadPage, SeenPage, SessionInfo } from "./types.js";
|
|
16
|
+
/**
|
|
17
|
+
* A session id, safe to splice into a path.
|
|
18
|
+
*
|
|
19
|
+
* Every call below builds `/session/<id>/...` by interpolation, and the id
|
|
20
|
+
* reaches the client from whatever asked for it — an MCP tool argument written
|
|
21
|
+
* by a model, a CLI flag, a caller's own storage. An id carrying `/`, `?`, `#`
|
|
22
|
+
* or `..` therefore chooses a DIFFERENT route on the worker while looking like
|
|
23
|
+
* a session that does not exist: `../../permissions` reads the allowlist,
|
|
24
|
+
* `x?account=other` appends a parameter the caller never passed. Nothing on
|
|
25
|
+
* this path validated it.
|
|
26
|
+
*
|
|
27
|
+
* Deliberately a shape check and not a format check. Ids are 8 hex characters
|
|
28
|
+
* today (`randomUUID().slice(0, 8)`), but pinning that here would make a
|
|
29
|
+
* perfectly reasonable change to the generator break every client; what has to
|
|
30
|
+
* hold is only that the value is ONE path segment. `encodeURIComponent` is
|
|
31
|
+
* belt to the braces — it would neutralise the traversal on its own, and the
|
|
32
|
+
* throw is what makes a bad id readable rather than a 404 from the worker.
|
|
33
|
+
*
|
|
34
|
+
* Every caller below is `async` so this arrives as a REJECTION. A promise-
|
|
35
|
+
* returning method that throws synchronously is caught by `await` and missed by
|
|
36
|
+
* `.catch()`, which is a difference no caller should have to know about.
|
|
37
|
+
*/
|
|
38
|
+
export declare function sessionPath(id: string): string;
|
|
39
|
+
export declare function open(client: Unfenced, http: Transport, url: string, options?: {
|
|
40
|
+
headless?: boolean;
|
|
41
|
+
profile?: "ephemeral" | "agent";
|
|
42
|
+
proxy?: string;
|
|
43
|
+
account?: string;
|
|
44
|
+
intent?: "read" | "act";
|
|
45
|
+
settleMs?: number;
|
|
46
|
+
}): Promise<Session & {
|
|
47
|
+
providerSession?: ProviderSessionReason;
|
|
48
|
+
reusedExistingSession?: boolean;
|
|
49
|
+
navigated?: boolean;
|
|
50
|
+
note?: string;
|
|
51
|
+
}>;
|
|
52
|
+
export declare function switchAccount(client: Unfenced, http: Transport, sessionId: string, account: string): Promise<{
|
|
53
|
+
session: Session;
|
|
54
|
+
restoredSession: boolean;
|
|
55
|
+
requestedAccount?: string;
|
|
56
|
+
observedIdentity?: string;
|
|
57
|
+
}>;
|
|
58
|
+
export declare function pendingApprovals(http: Transport): Promise<{
|
|
59
|
+
interrupts: PendingApproval[];
|
|
60
|
+
clearAt: string;
|
|
61
|
+
}>;
|
|
62
|
+
export declare function whoami(http: Transport, sessionId: string): Promise<{
|
|
63
|
+
identity: string | null;
|
|
64
|
+
source: string | null;
|
|
65
|
+
}>;
|
|
66
|
+
export declare function liveSessions(http: Transport): Promise<SessionInfo[]>;
|
|
67
|
+
export declare function observe(http: Transport, id: string, opts?: {
|
|
68
|
+
match?: string;
|
|
69
|
+
maxControls?: number;
|
|
70
|
+
maxLinks?: number;
|
|
71
|
+
excerptChars?: number;
|
|
72
|
+
media?: boolean;
|
|
73
|
+
}): Promise<PageSnapshot>;
|
|
74
|
+
/**
|
|
75
|
+
* Read the current page and the server's last provider-session continuity
|
|
76
|
+
* decision. Unlike `observe`, this keeps the small status envelope so a caller
|
|
77
|
+
* reconnecting after a network interruption can distinguish a carried login
|
|
78
|
+
* from a session that needs re-authentication.
|
|
79
|
+
*/
|
|
80
|
+
export declare function refresh(http: Transport, id: string, opts?: {
|
|
81
|
+
match?: string;
|
|
82
|
+
}): Promise<{
|
|
83
|
+
page: PageSnapshot;
|
|
84
|
+
providerSession?: ProviderSessionReason;
|
|
85
|
+
}>;
|
|
86
|
+
export declare function read(http: Transport, id: string, opts?: {
|
|
87
|
+
match?: string;
|
|
88
|
+
maxControls?: number;
|
|
89
|
+
maxLinks?: number;
|
|
90
|
+
excerptChars?: number;
|
|
91
|
+
media?: boolean;
|
|
92
|
+
}): Promise<ReadPage>;
|
|
93
|
+
export declare function act(http: Transport, id: string, action: Action | OnAction | AtAction, opts?: {
|
|
94
|
+
acceptDialog?: boolean;
|
|
95
|
+
dialogText?: string;
|
|
96
|
+
brief?: boolean;
|
|
97
|
+
see?: boolean;
|
|
98
|
+
expect?: ActExpectation;
|
|
99
|
+
}): Promise<ActResult>;
|
|
100
|
+
export declare function extract(http: Transport, id: string, format?: Format, maxWords?: number): Promise<{
|
|
101
|
+
doc: ExtractedDoc;
|
|
102
|
+
content: string;
|
|
103
|
+
url: string;
|
|
104
|
+
contentTruncated?: boolean;
|
|
105
|
+
/** Present when something was withheld: how many words the page held. */
|
|
106
|
+
totalWords?: number;
|
|
107
|
+
}>;
|
|
108
|
+
export declare function screenshot(http: Transport, id: string): Promise<string>;
|
|
109
|
+
export declare function see(http: Transport, id: string, opts?: {
|
|
110
|
+
links?: boolean;
|
|
111
|
+
maxMarks?: number;
|
|
112
|
+
}): Promise<SeenPage>;
|
|
113
|
+
export declare function fill(http: Transport, id: string, fields: readonly FormField[]): Promise<FormFillResult>;
|
|
114
|
+
export declare function park(http: Transport, id: string, minutes?: number, reason?: string): Promise<{
|
|
115
|
+
ok: boolean;
|
|
116
|
+
until?: string;
|
|
117
|
+
}>;
|
|
118
|
+
export declare function downloads(http: Transport, id: string): Promise<{
|
|
119
|
+
downloads: DownloadInfo[];
|
|
120
|
+
}>;
|
|
121
|
+
export declare function readDownload(http: Transport, id: string, filename: string): Promise<{
|
|
122
|
+
filename: string;
|
|
123
|
+
bytes: number;
|
|
124
|
+
content: string;
|
|
125
|
+
doc: ExtractedDoc;
|
|
126
|
+
}>;
|
|
127
|
+
export declare function closeSession(http: Transport, id: string): Promise<{
|
|
128
|
+
alreadyClosed?: boolean;
|
|
129
|
+
wasOpen?: boolean;
|
|
130
|
+
}>;
|
|
131
|
+
//# sourceMappingURL=sessions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.d.ts","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"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"}
|
package/dist/sessions.js
ADDED
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The live-session tier: open a page, drive it, read it, close it.
|
|
3
|
+
*
|
|
4
|
+
* These are the bodies of the `Unfenced` methods under its `// ---- live
|
|
5
|
+
* sessions` heading, moved out and re-shaped from methods to functions that
|
|
6
|
+
* take a `Transport`. `open` and `switchAccount` also take the `client`, because
|
|
7
|
+
* they hand it to the `Session` they build. `this.request` became `http.request`
|
|
8
|
+
* and nothing else changed — the request paths, shapes, and comments are as they
|
|
9
|
+
* were.
|
|
10
|
+
*/
|
|
11
|
+
import { UnfencedError } from "./http.js";
|
|
12
|
+
import { Session } from "./session.js";
|
|
13
|
+
/**
|
|
14
|
+
* A session id, safe to splice into a path.
|
|
15
|
+
*
|
|
16
|
+
* Every call below builds `/session/<id>/...` by interpolation, and the id
|
|
17
|
+
* reaches the client from whatever asked for it — an MCP tool argument written
|
|
18
|
+
* by a model, a CLI flag, a caller's own storage. An id carrying `/`, `?`, `#`
|
|
19
|
+
* or `..` therefore chooses a DIFFERENT route on the worker while looking like
|
|
20
|
+
* a session that does not exist: `../../permissions` reads the allowlist,
|
|
21
|
+
* `x?account=other` appends a parameter the caller never passed. Nothing on
|
|
22
|
+
* this path validated it.
|
|
23
|
+
*
|
|
24
|
+
* Deliberately a shape check and not a format check. Ids are 8 hex characters
|
|
25
|
+
* today (`randomUUID().slice(0, 8)`), but pinning that here would make a
|
|
26
|
+
* perfectly reasonable change to the generator break every client; what has to
|
|
27
|
+
* hold is only that the value is ONE path segment. `encodeURIComponent` is
|
|
28
|
+
* belt to the braces — it would neutralise the traversal on its own, and the
|
|
29
|
+
* throw is what makes a bad id readable rather than a 404 from the worker.
|
|
30
|
+
*
|
|
31
|
+
* Every caller below is `async` so this arrives as a REJECTION. A promise-
|
|
32
|
+
* returning method that throws synchronously is caught by `await` and missed by
|
|
33
|
+
* `.catch()`, which is a difference no caller should have to know about.
|
|
34
|
+
*/
|
|
35
|
+
export function sessionPath(id) {
|
|
36
|
+
// A standalone dot segment is normalized by URL parsers even when encoded.
|
|
37
|
+
// Embedded dots remain valid, but these two values cannot identify a session.
|
|
38
|
+
if (id === "." || id === ".." || !/^[A-Za-z0-9._~-]{1,128}$/.test(id)) {
|
|
39
|
+
throw new UnfencedError(400, `not a session id: ${JSON.stringify(id.slice(0, 40))}`, {
|
|
40
|
+
code: "bad-session-id",
|
|
41
|
+
remedy: "a session id is the `id` open_page returned - one path segment of letters, digits, dot, dash, underscore or tilde. Open a page and use the id it gives you",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
return encodeURIComponent(id);
|
|
45
|
+
}
|
|
46
|
+
export async function open(client, http, url, options = {}) {
|
|
47
|
+
const { id, page, providerSession, reusedExistingSession, navigated, note } = await http.request("POST", "/session", { url, ...options });
|
|
48
|
+
// Attached rather than returned separately, so every existing caller keeps
|
|
49
|
+
// working unchanged and a caller that wants to know WHY a page opened
|
|
50
|
+
// without the account's provider session can ask.
|
|
51
|
+
// Attached the same way `providerSession` is, and for the same reason: the
|
|
52
|
+
// server has always said when it handed back a page you already had, and
|
|
53
|
+
// this destructuring is where that sentence used to stop. An agent asking
|
|
54
|
+
// for a second page on a site got the first one with nothing saying so.
|
|
55
|
+
return Object.assign(new Session(client, id, page), {
|
|
56
|
+
providerSession,
|
|
57
|
+
...(reusedExistingSession ? { reusedExistingSession, navigated } : {}),
|
|
58
|
+
// Outside the reuse branch: an ordinary open can carry one too, and it was
|
|
59
|
+
// being dropped for every caller who had not reused a session.
|
|
60
|
+
...(note ? { note } : {}),
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
export async function switchAccount(client, http, sessionId, account) {
|
|
64
|
+
// `restoredSession` says whether this account had a STORED session to restore. When
|
|
65
|
+
// false the reopened page is logged out and the resulting identity is whatever a
|
|
66
|
+
// fresh OAuth resolves — NOT a guarantee it is `account`. `observedIdentity` is who
|
|
67
|
+
// the page is ACTUALLY signed in as, when the site is one the server can read —
|
|
68
|
+
// the truth to check against the requested name and across switches.
|
|
69
|
+
const { id, page, restoredSession, requestedAccount, observedIdentity } = await http.request("POST", `/session/${sessionPath(sessionId)}/switch`, { account });
|
|
70
|
+
return {
|
|
71
|
+
session: new Session(client, id, page),
|
|
72
|
+
restoredSession: Boolean(restoredSession),
|
|
73
|
+
requestedAccount,
|
|
74
|
+
observedIdentity,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
export function pendingApprovals(http) {
|
|
78
|
+
return http.request("GET", "/interrupts");
|
|
79
|
+
}
|
|
80
|
+
export async function whoami(http, sessionId) {
|
|
81
|
+
return http.request("GET", `/session/${sessionPath(sessionId)}/whoami`);
|
|
82
|
+
}
|
|
83
|
+
export function liveSessions(http) {
|
|
84
|
+
return http.request("GET", "/session").then((r) => r.sessions);
|
|
85
|
+
}
|
|
86
|
+
export async function observe(http, id, opts) {
|
|
87
|
+
return http
|
|
88
|
+
.request("POST", `/session/${sessionPath(id)}/observe`, opts ?? {})
|
|
89
|
+
.then((r) => r.page);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Read the current page and the server's last provider-session continuity
|
|
93
|
+
* decision. Unlike `observe`, this keeps the small status envelope so a caller
|
|
94
|
+
* reconnecting after a network interruption can distinguish a carried login
|
|
95
|
+
* from a session that needs re-authentication.
|
|
96
|
+
*/
|
|
97
|
+
export function refresh(http, id, opts) {
|
|
98
|
+
return http.request("GET", `/session/${sessionPath(id)}${opts?.match ? `?match=${encodeURIComponent(opts.match)}` : ""}`);
|
|
99
|
+
}
|
|
100
|
+
export async function read(http, id, opts) {
|
|
101
|
+
return http.request("POST", `/session/${sessionPath(id)}/observe`, opts ?? {});
|
|
102
|
+
}
|
|
103
|
+
export async function act(http, id, action, opts) {
|
|
104
|
+
// Merged into the body, because the wire is one object — the server reads
|
|
105
|
+
// `acceptDialog`/`dialogText` off it and hands them to the engine as call
|
|
106
|
+
// options rather than as part of the action.
|
|
107
|
+
return http.request("POST", `/session/${sessionPath(id)}/act`, {
|
|
108
|
+
...onTheWire(action),
|
|
109
|
+
...opts,
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The one place an action's field names are translated for the wire.
|
|
114
|
+
*
|
|
115
|
+
* A multi-select carried its options as an ARRAY under the SINGULAR key —
|
|
116
|
+
* `{kind:"select", ref, value:["Olive","Caper"]}` — and the server's parser
|
|
117
|
+
* reads the PLURAL key for arrays: `const many = b["values"]; if
|
|
118
|
+
* (Array.isArray(many)) …`, falling through otherwise to `String(b["value"])`,
|
|
119
|
+
* which is `"Olive,Caper"`. That string matches no option on any page, so
|
|
120
|
+
* multi-select failed on every call and failed in a way that looked like the
|
|
121
|
+
* site's fault. Reproduced end to end against the two real functions.
|
|
122
|
+
*
|
|
123
|
+
* Done HERE rather than in the MCP fold because this function is what writes
|
|
124
|
+
* the body: every caller — the connector, a typed SDK user, a script — goes
|
|
125
|
+
* through it, and a fix in one caller leaves the others broken. The action
|
|
126
|
+
* types keep `value: string | string[]`, which is what the idea actually is;
|
|
127
|
+
* the wire's two spellings are a wire detail and stop here.
|
|
128
|
+
*/
|
|
129
|
+
function onTheWire(action) {
|
|
130
|
+
const body = { ...action };
|
|
131
|
+
if (body["kind"] === "select" && Array.isArray(body["value"])) {
|
|
132
|
+
body["values"] = body["value"];
|
|
133
|
+
delete body["value"];
|
|
134
|
+
}
|
|
135
|
+
return body;
|
|
136
|
+
}
|
|
137
|
+
export async function extract(http, id, format = "markdown", maxWords) {
|
|
138
|
+
// `contentTruncated` is on the wire and was not in this type, so every typed
|
|
139
|
+
// caller lost it: the route sets it when `capExtractInput` cut the DOM at the
|
|
140
|
+
// 1 MB ceiling, with the comment "a cut page that claims to be whole is worse
|
|
141
|
+
// than a cut page", and a client that cannot see the field cannot pass it on.
|
|
142
|
+
//
|
|
143
|
+
// `maxWords` and `totalWords` are the SECOND ceiling, which had no parameter
|
|
144
|
+
// and no report: the route defaults to core's 25,000-word budget, so a long
|
|
145
|
+
// logged-in listing came back cut with `contentTruncated` set for a reason
|
|
146
|
+
// every description of this call attributed to the megabyte cut instead — and
|
|
147
|
+
// its only documented remedy, a smaller DOM, does nothing about it.
|
|
148
|
+
//
|
|
149
|
+
// Absent means the route's own default, which is what every existing caller
|
|
150
|
+
// already gets — adding the parameter changed nobody's result, only what a
|
|
151
|
+
// careful caller is able to ask for.
|
|
152
|
+
const budget = maxWords === undefined ? "" : `&maxWords=${encodeURIComponent(String(maxWords))}`;
|
|
153
|
+
return http.request("GET", `/session/${sessionPath(id)}/extract?format=${format}${budget}`);
|
|
154
|
+
}
|
|
155
|
+
export async function screenshot(http, id) {
|
|
156
|
+
return http
|
|
157
|
+
.request("GET", `/session/${sessionPath(id)}/screenshot`)
|
|
158
|
+
.then((r) => r.image);
|
|
159
|
+
}
|
|
160
|
+
export async function see(http, id, opts = {}) {
|
|
161
|
+
const query = new URLSearchParams({ marks: "1" });
|
|
162
|
+
if (opts.links)
|
|
163
|
+
query.set("links", "1");
|
|
164
|
+
if (opts.maxMarks !== undefined)
|
|
165
|
+
query.set("maxMarks", String(opts.maxMarks));
|
|
166
|
+
return http.request("GET", `/session/${sessionPath(id)}/screenshot?${query.toString()}`);
|
|
167
|
+
}
|
|
168
|
+
export async function fill(http, id, fields) {
|
|
169
|
+
return http.request("POST", `/session/${sessionPath(id)}/fill`, { fields });
|
|
170
|
+
}
|
|
171
|
+
export async function park(http, id, minutes, reason) {
|
|
172
|
+
return http.request("POST", `/session/${sessionPath(id)}/park`, {
|
|
173
|
+
...(minutes !== undefined ? { minutes } : {}),
|
|
174
|
+
...(reason !== undefined ? { reason } : {}),
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
export async function downloads(http, id) {
|
|
178
|
+
return http.request("GET", `/session/${sessionPath(id)}/downloads`);
|
|
179
|
+
}
|
|
180
|
+
export async function readDownload(http, id, filename) {
|
|
181
|
+
return http.request("GET", `/session/${sessionPath(id)}/downloads/${encodeURIComponent(filename)}`);
|
|
182
|
+
}
|
|
183
|
+
export async function closeSession(http, id) {
|
|
184
|
+
// The response type has to name every field that is read below, or the
|
|
185
|
+
// passthrough silently drops it again — which is the whole defect here.
|
|
186
|
+
return http
|
|
187
|
+
.request("DELETE", `/session/${sessionPath(id)}`)
|
|
188
|
+
.then((r) => ({
|
|
189
|
+
// Passed through rather than rebuilt. This mapped only `alreadyClosed`,
|
|
190
|
+
// so `wasOpen` — added so a mistyped id stops reading as success — was
|
|
191
|
+
// dropped here and the MCP tool reported `wasOpen: true` unconditionally.
|
|
192
|
+
// Its false branch was dead the day it shipped.
|
|
193
|
+
...(r.alreadyClosed ? { alreadyClosed: true } : {}),
|
|
194
|
+
...(typeof r.wasOpen === "boolean" ? { wasOpen: r.wasOpen } : {}),
|
|
195
|
+
}));
|
|
196
|
+
}
|
|
197
|
+
//# sourceMappingURL=sessions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sessions.js","sourceRoot":"","sources":["../src/sessions.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAa,aAAa,EAAE,MAAM,WAAW,CAAC;AACrD,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAqBvC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,WAAW,CAAC,EAAU;IACpC,2EAA2E;IAC3E,8EAA8E;IAC9E,IAAI,EAAE,KAAK,GAAG,IAAI,EAAE,KAAK,IAAI,IAAI,CAAC,0BAA0B,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,aAAa,CAAC,GAAG,EAAE,qBAAqB,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE;YACnF,IAAI,EAAE,gBAAgB;YACtB,MAAM,EACJ,4JAA4J;SAC/J,CAAC,CAAC;IACL,CAAC;IACD,OAAO,kBAAkB,CAAC,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,MAAgB,EAChB,IAAe,EACf,GAAW,EACX,UAOI,EAAE;IASN,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,qBAAqB,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAO7F,MAAM,EAAE,UAAU,EAAE,EAAE,GAAG,EAAE,GAAG,OAAO,EAAE,CAAC,CAAC;IAC5C,2EAA2E;IAC3E,sEAAsE;IACtE,kDAAkD;IAClD,2EAA2E;IAC3E,yEAAyE;IACzE,0EAA0E;IAC1E,wEAAwE;IACxE,OAAO,MAAM,CAAC,MAAM,CAAC,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,EAAE;QAClD,eAAe;QACf,GAAG,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAAE,qBAAqB,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACtE,2EAA2E;QAC3E,+DAA+D;QAC/D,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1B,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAgB,EAChB,IAAe,EACf,SAAiB,EACjB,OAAe;IAOf,oFAAoF;IACpF,iFAAiF;IACjF,oFAAoF;IACpF,gFAAgF;IAChF,qEAAqE;IACrE,MAAM,EAAE,EAAE,EAAE,IAAI,EAAE,eAAe,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,GAAG,MAAM,IAAI,CAAC,OAAO,CAMzF,MAAM,EAAE,YAAY,WAAW,CAAC,SAAS,CAAC,SAAS,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;IACrE,OAAO;QACL,OAAO,EAAE,IAAI,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC;QACtC,eAAe,EAAE,OAAO,CAAC,eAAe,CAAC;QACzC,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAC9B,IAAe;IAEf,OAAO,IAAI,CAAC,OAAO,CAAqD,KAAK,EAAE,aAAa,CAAC,CAAC;AAChG,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAC1B,IAAe,EACf,SAAiB;IAEjB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,YAAY,WAAW,CAAC,SAAS,CAAC,SAAS,CAC5C,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,IAAe;IAC1C,OAAO,IAAI,CAAC,OAAO,CAA8B,KAAK,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAe,EACf,EAAU,EACV,IAMC;IAED,OAAO,IAAI;SACR,OAAO,CAAyB,MAAM,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC;SAC1F,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,OAAO,CACrB,IAAe,EACf,EAAU,EACV,IAAyB;IAEzB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,YAAY,WAAW,CAAC,EAAE,CAAC,GAAG,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,UAAU,kBAAkB,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAC9F,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,IAAe,EACf,EAAU,EACV,IAMC;IAED,OAAO,IAAI,CAAC,OAAO,CAAW,MAAM,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,IAAe,EACf,EAAU,EACV,MAAoC,EACpC,IAMC;IAED,0EAA0E;IAC1E,0EAA0E;IAC1E,6CAA6C;IAC7C,OAAO,IAAI,CAAC,OAAO,CAAY,MAAM,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,MAAM,EAAE;QACxE,GAAG,SAAS,CAAC,MAAM,CAAC;QACpB,GAAG,IAAI;KACR,CAAC,CAAC;AACL,CAAC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,SAAS,SAAS,CAAC,MAAoC;IACrD,MAAM,IAAI,GAAG,EAAE,GAAG,MAAM,EAA6B,CAAC;IACtD,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QAC9D,IAAI,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC3B,IAAe,EACf,EAAU,EACV,SAAiB,UAAU,EAC3B,QAAiB;IAEjB,6EAA6E;IAC7E,8EAA8E;IAC9E,8EAA8E;IAC9E,8EAA8E;IAC9E,EAAE;IACF,6EAA6E;IAC7E,4EAA4E;IAC5E,2EAA2E;IAC3E,8EAA8E;IAC9E,oEAAoE;IACpE,EAAE;IACF,4EAA4E;IAC5E,2EAA2E;IAC3E,qCAAqC;IACrC,MAAM,MAAM,GAAG,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,aAAa,kBAAkB,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC;IACjG,OAAO,IAAI,CAAC,OAAO,CAOhB,KAAK,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,mBAAmB,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,IAAe,EAAE,EAAU;IAC1D,OAAO,IAAI;SACR,OAAO,CAAoB,KAAK,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,aAAa,CAAC;SAC3E,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CACvB,IAAe,EACf,EAAU,EACV,OAGI,EAAE;IAEN,MAAM,KAAK,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAC;IAClD,IAAI,IAAI,CAAC,KAAK;QAAE,KAAK,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IACxC,IAAI,IAAI,CAAC,QAAQ,KAAK,SAAS;QAAE,KAAK,CAAC,GAAG,CAAC,UAAU,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC9E,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,YAAY,WAAW,CAAC,EAAE,CAAC,eAAe,KAAK,CAAC,QAAQ,EAAE,EAAE,CAC7D,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,IAAe,EACf,EAAU,EACV,MAA4B;IAE5B,OAAO,IAAI,CAAC,OAAO,CAAiB,MAAM,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,CAAC,CAAC;AAC9F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,IAAe,EACf,EAAU,EACV,OAAgB,EAChB,MAAe;IAEf,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,YAAY,WAAW,CAAC,EAAE,CAAC,OAAO,EAAE;QAC9D,GAAG,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7C,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC5C,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAe,EACf,EAAU;IAEV,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,YAAY,WAAW,CAAC,EAAE,CAAC,YAAY,CACxC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAe,EACf,EAAU,EACV,QAAgB;IAEhB,OAAO,IAAI,CAAC,OAAO,CACjB,KAAK,EACL,YAAY,WAAW,CAAC,EAAE,CAAC,cAAc,kBAAkB,CAAC,QAAQ,CAAC,EAAE,CACxE,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,IAAe,EACf,EAAU;IAEV,uEAAuE;IACvE,wEAAwE;IACxE,OAAO,IAAI;SACR,OAAO,CACN,QAAQ,EACR,YAAY,WAAW,CAAC,EAAE,CAAC,EAAE,CAC9B;SACA,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACZ,wEAAwE;QACxE,uEAAuE;QACvE,0EAA0E;QAC1E,gDAAgD;QAChD,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACnD,GAAG,CAAC,OAAO,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAClE,CAAC,CAAC,CAAC;AACR,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** Text returned by a tool/API, not provider-billed model usage. */
|
|
2
|
+
export interface TokenUsage {
|
|
3
|
+
category: "fetch" | "session" | "other";
|
|
4
|
+
operation: string;
|
|
5
|
+
textChars: number;
|
|
6
|
+
imageCount: number;
|
|
7
|
+
sessionId?: string;
|
|
8
|
+
}
|
|
9
|
+
/** Count MCP text once; structuredContent duplicates text in our tool replies. */
|
|
10
|
+
export declare function toolTokenUsage(operation: string, input: unknown, result: unknown): TokenUsage;
|
|
11
|
+
//# sourceMappingURL=token-usage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.d.ts","sourceRoot":"","sources":["../src/token-usage.ts"],"names":[],"mappings":"AAAA,oEAAoE;AACpE,MAAM,WAAW,UAAU;IACzB,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,CAAC;IACxC,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,kFAAkF;AAClF,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,GAAG,UAAU,CA4B7F"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/** Count MCP text once; structuredContent duplicates text in our tool replies. */
|
|
2
|
+
export function toolTokenUsage(operation, input, result) {
|
|
3
|
+
const args = input;
|
|
4
|
+
let sessionId = typeof args?.sessionId === "string" ? args.sessionId : undefined;
|
|
5
|
+
let textChars = 0;
|
|
6
|
+
let imageCount = 0;
|
|
7
|
+
const blocks = result?.content;
|
|
8
|
+
if (Array.isArray(blocks)) {
|
|
9
|
+
for (const block of blocks) {
|
|
10
|
+
if (block?.type === "text" && typeof block.text === "string") {
|
|
11
|
+
textChars += block.text.length;
|
|
12
|
+
if (!sessionId) {
|
|
13
|
+
try {
|
|
14
|
+
const payload = JSON.parse(block.text);
|
|
15
|
+
if (typeof payload?.sessionId === "string")
|
|
16
|
+
sessionId = payload.sessionId;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
/* prose is also a valid text block */
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
else if (block?.type === "image")
|
|
24
|
+
imageCount++;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
const category = sessionId || operation === "open_page" || operation === "switch_account"
|
|
28
|
+
? "session"
|
|
29
|
+
: /^(fetch_page|fetch_batch|get_page_links)$/.test(operation)
|
|
30
|
+
? "fetch"
|
|
31
|
+
: "other";
|
|
32
|
+
return { category, operation, textChars, imageCount, ...(sessionId ? { sessionId } : {}) };
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=token-usage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-usage.js","sourceRoot":"","sources":["../src/token-usage.ts"],"names":[],"mappings":"AASA,kFAAkF;AAClF,MAAM,UAAU,cAAc,CAAC,SAAiB,EAAE,KAAc,EAAE,MAAe;IAC/E,MAAM,IAAI,GAAG,KAAuC,CAAC;IACrD,IAAI,SAAS,GAAG,OAAO,IAAI,EAAE,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC;IACjF,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,MAAM,MAAM,GAAI,MAAuC,EAAE,OAAO,CAAC;IACjE,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,EAAE,IAAI,KAAK,MAAM,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBAC7D,SAAS,IAAI,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC;gBAC/B,IAAI,CAAC,SAAS,EAAE,CAAC;oBACf,IAAI,CAAC;wBACH,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAA4B,CAAC;wBAClE,IAAI,OAAO,OAAO,EAAE,SAAS,KAAK,QAAQ;4BAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;oBAC5E,CAAC;oBAAC,MAAM,CAAC;wBACP,sCAAsC;oBACxC,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,IAAI,KAAK,EAAE,IAAI,KAAK,OAAO;gBAAE,UAAU,EAAE,CAAC;QACnD,CAAC;IACH,CAAC;IACD,MAAM,QAAQ,GACZ,SAAS,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,gBAAgB;QACtE,CAAC,CAAC,SAAS;QACX,CAAC,CAAC,2CAA2C,CAAC,IAAI,CAAC,SAAS,CAAC;YAC3D,CAAC,CAAC,OAAO;YACT,CAAC,CAAC,OAAO,CAAC;IAChB,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,GAAG,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC;AAC7F,CAAC"}
|