take-blip-mcp 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 +21 -0
- package/README.md +424 -0
- package/dist/blip-client.d.ts +69 -0
- package/dist/blip-client.d.ts.map +1 -0
- package/dist/blip-client.js +187 -0
- package/dist/blip-client.js.map +1 -0
- package/dist/config.d.ts +37 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +197 -0
- package/dist/config.js.map +1 -0
- package/dist/env-file.d.ts +16 -0
- package/dist/env-file.d.ts.map +1 -0
- package/dist/env-file.js +70 -0
- package/dist/env-file.js.map +1 -0
- package/dist/errors.d.ts +49 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +74 -0
- package/dist/errors.js.map +1 -0
- package/dist/flow-map.d.ts +48 -0
- package/dist/flow-map.d.ts.map +1 -0
- package/dist/flow-map.js +209 -0
- package/dist/flow-map.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +143 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +18 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +42 -0
- package/dist/logger.js.map +1 -0
- package/dist/tools/ai.d.ts +3 -0
- package/dist/tools/ai.d.ts.map +1 -0
- package/dist/tools/ai.js +51 -0
- package/dist/tools/ai.js.map +1 -0
- package/dist/tools/broadcast.d.ts +3 -0
- package/dist/tools/broadcast.d.ts.map +1 -0
- package/dist/tools/broadcast.js +46 -0
- package/dist/tools/broadcast.js.map +1 -0
- package/dist/tools/buckets.d.ts +3 -0
- package/dist/tools/buckets.d.ts.map +1 -0
- package/dist/tools/buckets.js +49 -0
- package/dist/tools/buckets.js.map +1 -0
- package/dist/tools/command.d.ts +3 -0
- package/dist/tools/command.d.ts.map +1 -0
- package/dist/tools/command.js +41 -0
- package/dist/tools/command.js.map +1 -0
- package/dist/tools/contacts.d.ts +3 -0
- package/dist/tools/contacts.d.ts.map +1 -0
- package/dist/tools/contacts.js +119 -0
- package/dist/tools/contacts.js.map +1 -0
- package/dist/tools/context.d.ts +3 -0
- package/dist/tools/context.d.ts.map +1 -0
- package/dist/tools/context.js +50 -0
- package/dist/tools/context.js.map +1 -0
- package/dist/tools/events.d.ts +3 -0
- package/dist/tools/events.d.ts.map +1 -0
- package/dist/tools/events.js +48 -0
- package/dist/tools/events.js.map +1 -0
- package/dist/tools/flow-tools.d.ts +3 -0
- package/dist/tools/flow-tools.d.ts.map +1 -0
- package/dist/tools/flow-tools.js +77 -0
- package/dist/tools/flow-tools.js.map +1 -0
- package/dist/tools/flow.d.ts +3 -0
- package/dist/tools/flow.d.ts.map +1 -0
- package/dist/tools/flow.js +33 -0
- package/dist/tools/flow.js.map +1 -0
- package/dist/tools/index.d.ts +5 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/messages.d.ts +3 -0
- package/dist/tools/messages.d.ts.map +1 -0
- package/dist/tools/messages.js +31 -0
- package/dist/tools/messages.js.map +1 -0
- package/dist/tools/schedules.d.ts +3 -0
- package/dist/tools/schedules.d.ts.map +1 -0
- package/dist/tools/schedules.js +25 -0
- package/dist/tools/schedules.js.map +1 -0
- package/dist/tools/shared.d.ts +55 -0
- package/dist/tools/shared.d.ts.map +1 -0
- package/dist/tools/shared.js +67 -0
- package/dist/tools/shared.js.map +1 -0
- package/dist/tools/threads.d.ts +3 -0
- package/dist/tools/threads.d.ts.map +1 -0
- package/dist/tools/threads.js +39 -0
- package/dist/tools/threads.js.map +1 -0
- package/package.json +60 -0
package/dist/errors.js
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error types and secret redaction for blip-mcp.
|
|
3
|
+
*
|
|
4
|
+
* Redaction is defensive: even if a token somehow lands in an error message or
|
|
5
|
+
* a response body, {@link redactSecrets} scrubs it before it can reach a log
|
|
6
|
+
* line or a tool result.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* Remove known secrets and any `Key <token>` authorization header from a string.
|
|
10
|
+
* Safe to call on arbitrary text (log lines, HTTP bodies, error messages).
|
|
11
|
+
*/
|
|
12
|
+
export function redactSecrets(text, secrets = []) {
|
|
13
|
+
let out = text;
|
|
14
|
+
for (const secret of secrets) {
|
|
15
|
+
if (secret && secret.length >= 4) {
|
|
16
|
+
out = out.split(secret).join("«redacted»");
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Belt-and-suspenders: scrub anything shaped like a Blip authorization header.
|
|
20
|
+
out = out.replace(/\bKey\s+[A-Za-z0-9+/=._-]{6,}/gi, "Key «redacted»");
|
|
21
|
+
return out;
|
|
22
|
+
}
|
|
23
|
+
/** Base class for every error this package throws on purpose. */
|
|
24
|
+
export class BlipError extends Error {
|
|
25
|
+
constructor(message, options) {
|
|
26
|
+
super(message, options);
|
|
27
|
+
this.name = new.target.name;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/** Configuration / environment problem (missing credentials, bad host, etc.). */
|
|
31
|
+
export class BlipConfigError extends BlipError {
|
|
32
|
+
}
|
|
33
|
+
/** A request exceeded the configured timeout. */
|
|
34
|
+
export class BlipTimeoutError extends BlipError {
|
|
35
|
+
timeoutMs;
|
|
36
|
+
constructor(timeoutMs) {
|
|
37
|
+
super(`Request to Blip timed out after ${timeoutMs}ms`);
|
|
38
|
+
this.timeoutMs = timeoutMs;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/** A non-2xx HTTP response from the Blip API (e.g. 401 auth, 500 server). */
|
|
42
|
+
export class BlipHttpError extends BlipError {
|
|
43
|
+
status;
|
|
44
|
+
bodyExcerpt;
|
|
45
|
+
constructor(status, bodyExcerpt = "") {
|
|
46
|
+
super(`Blip API responded with HTTP ${status}${bodyExcerpt ? `: ${bodyExcerpt}` : ""}`);
|
|
47
|
+
this.status = status;
|
|
48
|
+
this.bodyExcerpt = bodyExcerpt;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A command was delivered but Blip answered with `status: "failure"`.
|
|
53
|
+
* Carries the structured `reason` so callers get a clear message.
|
|
54
|
+
*/
|
|
55
|
+
export class BlipCommandError extends BlipError {
|
|
56
|
+
code;
|
|
57
|
+
description;
|
|
58
|
+
method;
|
|
59
|
+
uri;
|
|
60
|
+
constructor(params) {
|
|
61
|
+
const reason = [
|
|
62
|
+
params.code != null ? `code ${params.code}` : null,
|
|
63
|
+
params.description ?? null,
|
|
64
|
+
]
|
|
65
|
+
.filter((part) => Boolean(part))
|
|
66
|
+
.join(" — ");
|
|
67
|
+
super(`Blip command failed (${params.method.toUpperCase()} ${params.uri})${reason ? `: ${reason}` : ""}`);
|
|
68
|
+
this.code = params.code;
|
|
69
|
+
this.description = params.description;
|
|
70
|
+
this.method = params.method;
|
|
71
|
+
this.uri = params.uri;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY,EAAE,UAAiC,EAAE;IAC7E,IAAI,GAAG,GAAG,IAAI,CAAC;IACf,KAAK,MAAM,MAAM,IAAI,OAAO,EAAE,CAAC;QAC7B,IAAI,MAAM,IAAI,MAAM,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACjC,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;QAC7C,CAAC;IACH,CAAC;IACD,+EAA+E;IAC/E,GAAG,GAAG,GAAG,CAAC,OAAO,CAAC,iCAAiC,EAAE,gBAAgB,CAAC,CAAC;IACvE,OAAO,GAAG,CAAC;AACb,CAAC;AAED,iEAAiE;AACjE,MAAM,OAAO,SAAU,SAAQ,KAAK;IAClC,YAAY,OAAe,EAAE,OAA6B;QACxD,KAAK,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;QACxB,IAAI,CAAC,IAAI,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC;IAC9B,CAAC;CACF;AAED,iFAAiF;AACjF,MAAM,OAAO,eAAgB,SAAQ,SAAS;CAAG;AAEjD,iDAAiD;AACjD,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IACpC,SAAS,CAAS;IAC3B,YAAY,SAAiB;QAC3B,KAAK,CAAC,mCAAmC,SAAS,IAAI,CAAC,CAAC;QACxD,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC;IAC7B,CAAC;CACF;AAED,6EAA6E;AAC7E,MAAM,OAAO,aAAc,SAAQ,SAAS;IACjC,MAAM,CAAS;IACf,WAAW,CAAS;IAC7B,YAAY,MAAc,EAAE,WAAW,GAAG,EAAE;QAC1C,KAAK,CAAC,gCAAgC,MAAM,GAAG,WAAW,CAAC,CAAC,CAAC,KAAK,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACxF,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;CACF;AAED;;;GAGG;AACH,MAAM,OAAO,gBAAiB,SAAQ,SAAS;IACpC,IAAI,CAAqB;IACzB,WAAW,CAAqB;IAChC,MAAM,CAAS;IACf,GAAG,CAAS;IACrB,YAAY,MAKX;QACC,MAAM,MAAM,GAAG;YACb,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;YAClD,MAAM,CAAC,WAAW,IAAI,IAAI;SAC3B;aACE,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;aAC/C,IAAI,CAAC,KAAK,CAAC,CAAC;QACf,KAAK,CACH,wBAAwB,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,MAAM,CAAC,GAAG,IAAI,MAAM,CAAC,CAAC,CAAC,KAAK,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,CACnG,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC;QACxB,IAAI,CAAC,WAAW,GAAG,MAAM,CAAC,WAAW,CAAC;QACtC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;QAC5B,IAAI,CAAC,GAAG,GAAG,MAAM,CAAC,GAAG,CAAC;IACxB,CAAC;CACF"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure (no I/O) flow componentizer.
|
|
3
|
+
*
|
|
4
|
+
* Turns a Blip Builder flow definition (the bucket resource) into a structured
|
|
5
|
+
* map and a set of small Markdown/JSON files — one per block — so a large flow
|
|
6
|
+
* becomes browsable instead of one giant blob.
|
|
7
|
+
*/
|
|
8
|
+
type Any = any;
|
|
9
|
+
export interface FlowAction {
|
|
10
|
+
kind: string;
|
|
11
|
+
title: string;
|
|
12
|
+
}
|
|
13
|
+
export interface FlowRoute {
|
|
14
|
+
when: string;
|
|
15
|
+
target: string;
|
|
16
|
+
targetLabel: string;
|
|
17
|
+
}
|
|
18
|
+
export interface FlowIncoming {
|
|
19
|
+
from: string;
|
|
20
|
+
fromLabel: string;
|
|
21
|
+
when: string;
|
|
22
|
+
}
|
|
23
|
+
export interface FlowBlockInfo {
|
|
24
|
+
key: string;
|
|
25
|
+
blockId: string | undefined;
|
|
26
|
+
title: string;
|
|
27
|
+
type: "block" | "subflow" | "desk";
|
|
28
|
+
root: boolean;
|
|
29
|
+
capturesInto: string[];
|
|
30
|
+
messages: string[];
|
|
31
|
+
enteringActions: FlowAction[];
|
|
32
|
+
leavingActions: FlowAction[];
|
|
33
|
+
routes: FlowRoute[];
|
|
34
|
+
incoming: FlowIncoming[];
|
|
35
|
+
}
|
|
36
|
+
export interface FlowMapResult {
|
|
37
|
+
flowKey: string;
|
|
38
|
+
blockCount: number;
|
|
39
|
+
subflows: Record<string, string | null>;
|
|
40
|
+
blocks: FlowBlockInfo[];
|
|
41
|
+
}
|
|
42
|
+
export declare function buildFlowMap(flowKey: string, resource: Any, options?: {
|
|
43
|
+
full?: boolean;
|
|
44
|
+
}): FlowMapResult;
|
|
45
|
+
/** Render the componentized files. Keys are relative paths under the flow folder. */
|
|
46
|
+
export declare function renderFlowFiles(map: FlowMapResult): Record<string, string>;
|
|
47
|
+
export {};
|
|
48
|
+
//# sourceMappingURL=flow-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-map.d.ts","sourceRoot":"","sources":["../src/flow-map.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,KAAK,GAAG,GAAG,GAAG,CAAC;AAEf,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,WAAW,EAAE,MAAM,CAAC;CACrB;AACD,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AACD,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,GAAG,SAAS,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,OAAO,GAAG,SAAS,GAAG,MAAM,CAAC;IACnC,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB,eAAe,EAAE,UAAU,EAAE,CAAC;IAC9B,cAAc,EAAE,UAAU,EAAE,CAAC;IAC7B,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AACD,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC,CAAC;IACxC,MAAM,EAAE,aAAa,EAAE,CAAC;CACzB;AAoFD,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,OAAO,GAAE;IAAE,IAAI,CAAC,EAAE,OAAO,CAAA;CAAO,GAAG,aAAa,CAiC5G;AAgDD,qFAAqF;AACrF,wBAAgB,eAAe,CAAC,GAAG,EAAE,aAAa,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA0C1E"}
|
package/dist/flow-map.js
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
function blockType(key) {
|
|
2
|
+
if (key.startsWith("subflow:"))
|
|
3
|
+
return "subflow";
|
|
4
|
+
if (key.startsWith("desk:"))
|
|
5
|
+
return "desk";
|
|
6
|
+
return "block";
|
|
7
|
+
}
|
|
8
|
+
function titleOf(flow, key) {
|
|
9
|
+
const t = flow?.[key]?.$title;
|
|
10
|
+
return typeof t === "string" && t ? t : key;
|
|
11
|
+
}
|
|
12
|
+
function labelOf(flow, key) {
|
|
13
|
+
const t = titleOf(flow, key);
|
|
14
|
+
const type = blockType(key);
|
|
15
|
+
if (type === "subflow")
|
|
16
|
+
return `SUBFLUXO "${t}"`;
|
|
17
|
+
if (type === "desk")
|
|
18
|
+
return `DESK "${t}"`;
|
|
19
|
+
return `"${t}"`;
|
|
20
|
+
}
|
|
21
|
+
function fmtCondition(c) {
|
|
22
|
+
if (!c || typeof c !== "object")
|
|
23
|
+
return String(c);
|
|
24
|
+
const variable = c.variable ?? c.source ?? "?";
|
|
25
|
+
const comparison = c.comparison ?? "?";
|
|
26
|
+
const values = Array.isArray(c.values) ? c.values.join(" | ") : c.values ?? "";
|
|
27
|
+
return `${variable} ${comparison} [${values}]`;
|
|
28
|
+
}
|
|
29
|
+
function extractMessages(contentActions, full) {
|
|
30
|
+
const out = [];
|
|
31
|
+
for (const ca of Array.isArray(contentActions) ? contentActions : []) {
|
|
32
|
+
const content = ca?.$cardContent ?? ca?.content ?? ca?.$content;
|
|
33
|
+
if (content == null)
|
|
34
|
+
continue;
|
|
35
|
+
let text;
|
|
36
|
+
if (typeof content === "string")
|
|
37
|
+
text = content;
|
|
38
|
+
else if (typeof content === "object")
|
|
39
|
+
text = content.text ?? content.$content ?? content.title ?? JSON.stringify(content);
|
|
40
|
+
else
|
|
41
|
+
text = String(content);
|
|
42
|
+
text = String(text).replace(/\s+/g, " ").trim();
|
|
43
|
+
if (!text)
|
|
44
|
+
continue;
|
|
45
|
+
out.push(full ? text : text.slice(0, 140));
|
|
46
|
+
}
|
|
47
|
+
return out;
|
|
48
|
+
}
|
|
49
|
+
function extractCaptures(contentActions) {
|
|
50
|
+
const out = [];
|
|
51
|
+
for (const ca of Array.isArray(contentActions) ? contentActions : []) {
|
|
52
|
+
const v = ca?.input?.variable;
|
|
53
|
+
if (typeof v === "string" && v)
|
|
54
|
+
out.push(v);
|
|
55
|
+
}
|
|
56
|
+
return out;
|
|
57
|
+
}
|
|
58
|
+
function extractActions(arr) {
|
|
59
|
+
return (Array.isArray(arr) ? arr : []).map((a) => ({
|
|
60
|
+
kind: String(a?.type ?? a?.action?.type ?? "Action"),
|
|
61
|
+
title: String(a?.$title ?? a?.name ?? ""),
|
|
62
|
+
}));
|
|
63
|
+
}
|
|
64
|
+
function routesOf(block, flow) {
|
|
65
|
+
const routes = [];
|
|
66
|
+
for (const o of Array.isArray(block?.$conditionOutputs) ? block.$conditionOutputs : []) {
|
|
67
|
+
const conds = Array.isArray(o?.conditions) ? o.conditions.map(fmtCondition).join(" E ") : "(sem condição)";
|
|
68
|
+
const target = String(o?.stateId ?? "?");
|
|
69
|
+
routes.push({ when: conds, target, targetLabel: labelOf(flow, target) });
|
|
70
|
+
}
|
|
71
|
+
const def = block?.$defaultOutput;
|
|
72
|
+
if (def && def.stateId) {
|
|
73
|
+
routes.push({ when: "(default)", target: String(def.stateId), targetLabel: labelOf(flow, def.stateId) });
|
|
74
|
+
}
|
|
75
|
+
return routes;
|
|
76
|
+
}
|
|
77
|
+
function isBlock(v) {
|
|
78
|
+
return (v != null &&
|
|
79
|
+
typeof v === "object" &&
|
|
80
|
+
("$title" in v || "$conditionOutputs" in v || "$contentActions" in v || "$defaultOutput" in v));
|
|
81
|
+
}
|
|
82
|
+
export function buildFlowMap(flowKey, resource, options = {}) {
|
|
83
|
+
const full = options.full ?? false;
|
|
84
|
+
const entries = Object.entries(resource ?? {}).filter(([, v]) => isBlock(v));
|
|
85
|
+
const subflows = {};
|
|
86
|
+
const blocks = [];
|
|
87
|
+
for (const [key, b] of entries) {
|
|
88
|
+
if (key.startsWith("subflow:"))
|
|
89
|
+
subflows[key] = b.$title ?? null;
|
|
90
|
+
blocks.push({
|
|
91
|
+
key,
|
|
92
|
+
blockId: typeof b.id === "string" ? b.id : undefined,
|
|
93
|
+
title: titleOf(resource, key),
|
|
94
|
+
type: blockType(key),
|
|
95
|
+
root: Boolean(b.root),
|
|
96
|
+
capturesInto: extractCaptures(b.$contentActions),
|
|
97
|
+
messages: extractMessages(b.$contentActions, full),
|
|
98
|
+
enteringActions: extractActions(b.$enteringCustomActions),
|
|
99
|
+
leavingActions: extractActions(b.$leavingCustomActions),
|
|
100
|
+
routes: routesOf(b, resource),
|
|
101
|
+
incoming: [],
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
// reverse edges
|
|
105
|
+
const byKey = new Map(blocks.map((b) => [b.key, b]));
|
|
106
|
+
for (const b of blocks) {
|
|
107
|
+
for (const r of b.routes) {
|
|
108
|
+
const tgt = byKey.get(r.target);
|
|
109
|
+
if (tgt)
|
|
110
|
+
tgt.incoming.push({ from: b.key, fromLabel: labelOf(resource, b.key), when: r.when });
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
return { flowKey, blockCount: blocks.length, subflows, blocks };
|
|
114
|
+
}
|
|
115
|
+
function slugify(s) {
|
|
116
|
+
const out = s
|
|
117
|
+
.toLowerCase()
|
|
118
|
+
.normalize("NFD")
|
|
119
|
+
.replace(/[̀-ͯ]/g, "")
|
|
120
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
121
|
+
.replace(/^-+|-+$/g, "")
|
|
122
|
+
.slice(0, 60);
|
|
123
|
+
return out || "bloco";
|
|
124
|
+
}
|
|
125
|
+
function renderBlock(b) {
|
|
126
|
+
const lines = [];
|
|
127
|
+
const tags = [b.type, b.root ? "raiz/entrada" : null].filter(Boolean).join(", ");
|
|
128
|
+
lines.push(`# ${b.title}`, "");
|
|
129
|
+
lines.push(`- key: \`${b.key}\``);
|
|
130
|
+
if (b.blockId)
|
|
131
|
+
lines.push(`- id: \`${b.blockId}\``);
|
|
132
|
+
lines.push(`- tipo: ${tags}`, "");
|
|
133
|
+
lines.push("## O que faz", "");
|
|
134
|
+
lines.push(`**Mensagens enviadas:** ${b.messages.length ? "" : "—"}`);
|
|
135
|
+
for (const m of b.messages)
|
|
136
|
+
lines.push(`- ${m}`);
|
|
137
|
+
lines.push("");
|
|
138
|
+
lines.push(`**Captura entrada em:** ${b.capturesInto.length ? b.capturesInto.map((v) => `\`${v}\``).join(", ") : "—"}`);
|
|
139
|
+
lines.push("");
|
|
140
|
+
const acts = (label, arr) => {
|
|
141
|
+
lines.push(`**${label}:** ${arr.length ? "" : "—"}`);
|
|
142
|
+
for (const a of arr)
|
|
143
|
+
lines.push(`- ${a.kind}${a.title ? `: "${a.title}"` : ""}`);
|
|
144
|
+
lines.push("");
|
|
145
|
+
};
|
|
146
|
+
acts("Ações ao entrar", b.enteringActions);
|
|
147
|
+
acts("Ações ao sair", b.leavingActions);
|
|
148
|
+
lines.push("## Saídas (roteamento)", "");
|
|
149
|
+
if (b.routes.length === 0)
|
|
150
|
+
lines.push("- (nenhuma saída)");
|
|
151
|
+
for (const r of b.routes)
|
|
152
|
+
lines.push(`- ${r.when === "(default)" ? "SENÃO (padrão)" : `SE ${r.when}`} → ${r.targetLabel}`);
|
|
153
|
+
lines.push("");
|
|
154
|
+
lines.push("## Entradas (quem aponta pra cá)", "");
|
|
155
|
+
if (b.incoming.length === 0)
|
|
156
|
+
lines.push("- (nenhum bloco aponta pra cá / ponto de entrada)");
|
|
157
|
+
for (const inc of b.incoming)
|
|
158
|
+
lines.push(`- ${inc.fromLabel}${inc.when === "(default)" ? " (padrão)" : ` (SE ${inc.when})`}`);
|
|
159
|
+
lines.push("");
|
|
160
|
+
lines.push("[← índice](../index.md)");
|
|
161
|
+
return lines.join("\n");
|
|
162
|
+
}
|
|
163
|
+
/** Render the componentized files. Keys are relative paths under the flow folder. */
|
|
164
|
+
export function renderFlowFiles(map) {
|
|
165
|
+
const files = {};
|
|
166
|
+
const used = new Map();
|
|
167
|
+
const fileOf = new Map();
|
|
168
|
+
for (const b of map.blocks) {
|
|
169
|
+
const base = slugify(b.title || b.key);
|
|
170
|
+
const n = (used.get(base) ?? 0) + 1;
|
|
171
|
+
used.set(base, n);
|
|
172
|
+
fileOf.set(b.key, `blocks/${n === 1 ? base : `${base}-${n}`}.md`);
|
|
173
|
+
}
|
|
174
|
+
const esc = (s) => s.replace(/\|/g, "\|");
|
|
175
|
+
const idx = [];
|
|
176
|
+
idx.push(`# Flow: ${map.flowKey}`, "");
|
|
177
|
+
idx.push(`Blocos: ${map.blockCount} · Subfluxos: ${Object.keys(map.subflows).length}`, "");
|
|
178
|
+
idx.push("> Gerado por \`blip_map_flow\`. Reexecute após editar o fluxo no Builder.", "");
|
|
179
|
+
idx.push("## Subfluxos", "");
|
|
180
|
+
const subEntries = Object.entries(map.subflows);
|
|
181
|
+
if (subEntries.length === 0)
|
|
182
|
+
idx.push("- (nenhum)");
|
|
183
|
+
for (const [id, name] of subEntries)
|
|
184
|
+
idx.push(`- "${name ?? "(sem título)"}" \`${id}\``);
|
|
185
|
+
idx.push("");
|
|
186
|
+
idx.push("## Blocos", "", "| Bloco | Tipo | Saídas | Entradas | Arquivo |", "|---|---|---|---|---|");
|
|
187
|
+
for (const b of map.blocks) {
|
|
188
|
+
const file = fileOf.get(b.key);
|
|
189
|
+
const name = esc(b.title) + (b.root ? " (raiz)" : "");
|
|
190
|
+
idx.push(`| ${name} | ${b.type} | ${b.routes.length} | ${b.incoming.length} | [${file}](${file}) |`);
|
|
191
|
+
}
|
|
192
|
+
idx.push("");
|
|
193
|
+
idx.push("## Grafo (bloco → alvos)", "");
|
|
194
|
+
for (const b of map.blocks) {
|
|
195
|
+
const targets = b.routes.map((r) => r.targetLabel).join(", ") || "(sem saída)";
|
|
196
|
+
idx.push(`- ${labelLink(b, fileOf)} → ${targets}`);
|
|
197
|
+
}
|
|
198
|
+
idx.push("");
|
|
199
|
+
files["index.md"] = idx.join("\n");
|
|
200
|
+
files["index.json"] = JSON.stringify(map, null, 2);
|
|
201
|
+
for (const b of map.blocks)
|
|
202
|
+
files[fileOf.get(b.key)] = renderBlock(b);
|
|
203
|
+
return files;
|
|
204
|
+
}
|
|
205
|
+
function labelLink(b, fileOf) {
|
|
206
|
+
const file = fileOf.get(b.key);
|
|
207
|
+
return `[${b.title}](${file})`;
|
|
208
|
+
}
|
|
209
|
+
//# sourceMappingURL=flow-map.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flow-map.js","sourceRoot":"","sources":["../src/flow-map.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* blip-mcp — MCP server for the Take Blip platform (stdio transport).
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* blip-mcp start the MCP server on stdio (default)
|
|
7
|
+
* blip-mcp --self-test validate credentials with a tiny read and exit
|
|
8
|
+
* blip-mcp --health alias for --self-test
|
|
9
|
+
* blip-mcp --version print version
|
|
10
|
+
* blip-mcp --help print this help
|
|
11
|
+
*/
|
|
12
|
+
import { createRequire } from "node:module";
|
|
13
|
+
import { McpServer } from "@modelcontextprotocol/sdk/server/mcp.js";
|
|
14
|
+
import { StdioServerTransport } from "@modelcontextprotocol/sdk/server/stdio.js";
|
|
15
|
+
import { BlipClient } from "./blip-client.js";
|
|
16
|
+
import { configSecrets, describeConfig, loadConfig, resolveFlow, } from "./config.js";
|
|
17
|
+
import { BlipConfigError } from "./errors.js";
|
|
18
|
+
import { createLogger } from "./logger.js";
|
|
19
|
+
import { loadEnvFile, resolveEnvFile } from "./env-file.js";
|
|
20
|
+
import { registerAllTools } from "./tools/index.js";
|
|
21
|
+
const require = createRequire(import.meta.url);
|
|
22
|
+
const pkg = require("../package.json");
|
|
23
|
+
function printHelp() {
|
|
24
|
+
process.stdout.write([
|
|
25
|
+
`blip-mcp v${pkg.version} — MCP server for Take Blip (stdio)`,
|
|
26
|
+
"",
|
|
27
|
+
"Usage:",
|
|
28
|
+
" blip-mcp start the MCP server on stdio (default)",
|
|
29
|
+
" blip-mcp --self-test validate credentials with a tiny read and exit",
|
|
30
|
+
" blip-mcp --health alias for --self-test",
|
|
31
|
+
" blip-mcp --version print version and exit",
|
|
32
|
+
" blip-mcp --help print this help and exit",
|
|
33
|
+
"",
|
|
34
|
+
"Configuration is read from environment variables (see README / .env.example).",
|
|
35
|
+
"",
|
|
36
|
+
].join("\n"));
|
|
37
|
+
}
|
|
38
|
+
function makeClient(flowBaseUrl, authorization, config, logger) {
|
|
39
|
+
return new BlipClient({
|
|
40
|
+
baseUrl: flowBaseUrl,
|
|
41
|
+
authorization,
|
|
42
|
+
timeoutMs: config.timeoutMs,
|
|
43
|
+
maxRetries: config.maxRetries,
|
|
44
|
+
logger,
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
function buildServer(config, logger) {
|
|
48
|
+
const server = new McpServer({ name: "blip-mcp", version: pkg.version });
|
|
49
|
+
const cache = new Map();
|
|
50
|
+
const getClient = (flowName) => {
|
|
51
|
+
const flow = resolveFlow(config, flowName);
|
|
52
|
+
let client = cache.get(flow.name);
|
|
53
|
+
if (!client) {
|
|
54
|
+
client = makeClient(flow.baseUrl, flow.authorization, config, logger);
|
|
55
|
+
cache.set(flow.name, client);
|
|
56
|
+
}
|
|
57
|
+
return client;
|
|
58
|
+
};
|
|
59
|
+
const ctx = {
|
|
60
|
+
server,
|
|
61
|
+
client: getClient(),
|
|
62
|
+
getClient,
|
|
63
|
+
config,
|
|
64
|
+
flows: config.flows,
|
|
65
|
+
flowsDir: config.flowsDir,
|
|
66
|
+
logger,
|
|
67
|
+
secrets: configSecrets(config),
|
|
68
|
+
};
|
|
69
|
+
registerAllTools(ctx);
|
|
70
|
+
return server;
|
|
71
|
+
}
|
|
72
|
+
/** Validate credentials with a 1-item contact read. Returns a process exit code. */
|
|
73
|
+
async function runSelfTest(config, logger) {
|
|
74
|
+
process.stdout.write(`blip-mcp v${pkg.version} — self-test\n\n${describeConfig(config)}\n\n`);
|
|
75
|
+
const client = makeClient(config.baseUrl, config.authorization, config, logger);
|
|
76
|
+
try {
|
|
77
|
+
const res = await client.sendCommand({
|
|
78
|
+
method: "get",
|
|
79
|
+
to: "postmaster@crm.msging.net",
|
|
80
|
+
uri: "/contacts?$take=1",
|
|
81
|
+
});
|
|
82
|
+
const resource = res.resource;
|
|
83
|
+
const total = resource?.total ?? resource?.items?.length ?? 0;
|
|
84
|
+
process.stdout.write(`OK — credentials valid. Sample read returned total=${total}.\n`);
|
|
85
|
+
return 0;
|
|
86
|
+
}
|
|
87
|
+
catch (err) {
|
|
88
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
89
|
+
process.stdout.write(`FAILED — ${message}\n`);
|
|
90
|
+
process.stdout.write("\nCheck BLIP_AUTHORIZATION (or BLIP_BOT_IDENTIFIER/BLIP_ACCESS_KEY) and BLIP_CONTRACT_ID.\n");
|
|
91
|
+
return 1;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async function startServer(config, logger) {
|
|
95
|
+
const server = buildServer(config, logger);
|
|
96
|
+
const transport = new StdioServerTransport();
|
|
97
|
+
await server.connect(transport);
|
|
98
|
+
logger.info(`ready — base=${config.baseUrl} flows=${config.flows.length} ` +
|
|
99
|
+
`writes=${config.allowWrites ? "ENABLED" : "read-only"} (v${pkg.version})`);
|
|
100
|
+
}
|
|
101
|
+
async function main() {
|
|
102
|
+
const argv = process.argv.slice(2);
|
|
103
|
+
if (argv.includes("--help") || argv.includes("-h")) {
|
|
104
|
+
printHelp();
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
if (argv.includes("--version") || argv.includes("-v")) {
|
|
108
|
+
process.stdout.write(`${pkg.version}\n`);
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
// Optionally load a blip.env file (real env always wins).
|
|
112
|
+
const envFile = resolveEnvFile();
|
|
113
|
+
if (envFile) {
|
|
114
|
+
const applied = loadEnvFile(envFile);
|
|
115
|
+
if (applied.length > 0)
|
|
116
|
+
process.stderr.write(`[blip-mcp] loaded ${applied.length} variable(s) from ${envFile}
|
|
117
|
+
`);
|
|
118
|
+
}
|
|
119
|
+
let config;
|
|
120
|
+
try {
|
|
121
|
+
config = loadConfig();
|
|
122
|
+
}
|
|
123
|
+
catch (err) {
|
|
124
|
+
if (err instanceof BlipConfigError) {
|
|
125
|
+
process.stderr.write(`\n[blip-mcp] configuration error:\n${err.message}\n\n`);
|
|
126
|
+
process.exitCode = 1;
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
throw err;
|
|
130
|
+
}
|
|
131
|
+
const logger = createLogger({ level: config.logLevel, secrets: configSecrets(config) });
|
|
132
|
+
if (argv.includes("--self-test") || argv.includes("--health")) {
|
|
133
|
+
process.exitCode = await runSelfTest(config, logger);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
await startServer(config, logger);
|
|
137
|
+
}
|
|
138
|
+
main().catch((err) => {
|
|
139
|
+
const message = err instanceof Error ? err.stack ?? err.message : String(err);
|
|
140
|
+
process.stderr.write(`[blip-mcp] fatal: ${message}\n`);
|
|
141
|
+
process.exit(1);
|
|
142
|
+
});
|
|
143
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
export type LogLevel = "error" | "warn" | "info" | "debug";
|
|
2
|
+
export interface Logger {
|
|
3
|
+
error(message: string, meta?: unknown): void;
|
|
4
|
+
warn(message: string, meta?: unknown): void;
|
|
5
|
+
info(message: string, meta?: unknown): void;
|
|
6
|
+
debug(message: string, meta?: unknown): void;
|
|
7
|
+
}
|
|
8
|
+
export interface LoggerOptions {
|
|
9
|
+
level?: LogLevel;
|
|
10
|
+
/** Known secret strings to scrub from every line. */
|
|
11
|
+
secrets?: ReadonlyArray<string>;
|
|
12
|
+
/** Sink override (defaults to process.stderr). Used by tests. */
|
|
13
|
+
write?: (line: string) => void;
|
|
14
|
+
}
|
|
15
|
+
export declare function createLogger(options?: LoggerOptions): Logger;
|
|
16
|
+
/** A logger that drops everything. Handy for tests. */
|
|
17
|
+
export declare const silentLogger: Logger;
|
|
18
|
+
//# sourceMappingURL=logger.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,QAAQ,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC;AAI3D,MAAM,WAAW,MAAM;IACrB,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC7C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;IAC5C,KAAK,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9C;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,QAAQ,CAAC;IACjB,qDAAqD;IACrD,OAAO,CAAC,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC;IAChC,iEAAiE;IACjE,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CAChC;AAED,wBAAgB,YAAY,CAAC,OAAO,GAAE,aAAkB,GAAG,MAAM,CAwBhE;AAED,uDAAuD;AACvD,eAAO,MAAM,YAAY,EAAE,MAK1B,CAAC"}
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tiny leveled logger that writes to **stderr only**.
|
|
3
|
+
*
|
|
4
|
+
* This is critical: in a stdio MCP server, stdout is the JSON-RPC channel.
|
|
5
|
+
* Anything written to stdout that is not a protocol message corrupts the
|
|
6
|
+
* connection, so every diagnostic goes to stderr and is redacted first.
|
|
7
|
+
*/
|
|
8
|
+
import { redactSecrets } from "./errors.js";
|
|
9
|
+
const LEVEL_RANK = { error: 0, warn: 1, info: 2, debug: 3 };
|
|
10
|
+
export function createLogger(options = {}) {
|
|
11
|
+
const threshold = LEVEL_RANK[options.level ?? "info"];
|
|
12
|
+
const secrets = options.secrets ?? [];
|
|
13
|
+
const sink = options.write ?? ((line) => void process.stderr.write(line));
|
|
14
|
+
const emit = (level, message, meta) => {
|
|
15
|
+
if (LEVEL_RANK[level] > threshold)
|
|
16
|
+
return;
|
|
17
|
+
let line = `[blip-mcp] ${level.toUpperCase().padEnd(5)} ${message}`;
|
|
18
|
+
if (meta !== undefined) {
|
|
19
|
+
try {
|
|
20
|
+
line += ` ${JSON.stringify(meta)}`;
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
line += " [meta not serializable]";
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
sink(`${redactSecrets(line, secrets)}\n`);
|
|
27
|
+
};
|
|
28
|
+
return {
|
|
29
|
+
error: (message, meta) => emit("error", message, meta),
|
|
30
|
+
warn: (message, meta) => emit("warn", message, meta),
|
|
31
|
+
info: (message, meta) => emit("info", message, meta),
|
|
32
|
+
debug: (message, meta) => emit("debug", message, meta),
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
/** A logger that drops everything. Handy for tests. */
|
|
36
|
+
export const silentLogger = {
|
|
37
|
+
error: () => undefined,
|
|
38
|
+
warn: () => undefined,
|
|
39
|
+
info: () => undefined,
|
|
40
|
+
debug: () => undefined,
|
|
41
|
+
};
|
|
42
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAI5C,MAAM,UAAU,GAA6B,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAiBtF,MAAM,UAAU,YAAY,CAAC,UAAyB,EAAE;IACtD,MAAM,SAAS,GAAG,UAAU,CAAC,OAAO,CAAC,KAAK,IAAI,MAAM,CAAC,CAAC;IACtD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,EAAE,CAAC;IACtC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,IAAI,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAElF,MAAM,IAAI,GAAG,CAAC,KAAe,EAAE,OAAe,EAAE,IAAc,EAAQ,EAAE;QACtE,IAAI,UAAU,CAAC,KAAK,CAAC,GAAG,SAAS;YAAE,OAAO;QAC1C,IAAI,IAAI,GAAG,cAAc,KAAK,CAAC,WAAW,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,OAAO,EAAE,CAAC;QACpE,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,IAAI,CAAC;gBACH,IAAI,IAAI,IAAI,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC;YACrC,CAAC;YAAC,MAAM,CAAC;gBACP,IAAI,IAAI,0BAA0B,CAAC;YACrC,CAAC;QACH,CAAC;QACD,IAAI,CAAC,GAAG,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,CAAC,CAAC;IAEF,OAAO;QACL,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;QACtD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;QACpD,IAAI,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,EAAE,OAAO,EAAE,IAAI,CAAC;QACpD,KAAK,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;KACvD,CAAC;AACJ,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,MAAM,YAAY,GAAW;IAClC,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;IACtB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,IAAI,EAAE,GAAG,EAAE,CAAC,SAAS;IACrB,KAAK,EAAE,GAAG,EAAE,CAAC,SAAS;CACvB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ai.d.ts","sourceRoot":"","sources":["../../src/tools/ai.ts"],"names":[],"mappings":"AAYA,OAAO,EAAuB,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAKpE,wBAAgB,eAAe,CAAC,GAAG,EAAE,WAAW,GAAG,IAAI,CAwCtD"}
|
package/dist/tools/ai.js
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* AI / knowledge-base tool — the "ask my AI" requirement (EXPERIMENTAL).
|
|
3
|
+
*
|
|
4
|
+
* Target postmaster: postmaster@ai.msging.net
|
|
5
|
+
* - mode "knowledge": SET /content/analysis -> smart-content / knowledge base answer
|
|
6
|
+
* - mode "intent": SET /analysis -> intentions + entities of the sentence
|
|
7
|
+
*
|
|
8
|
+
* Both are read-only in effect (pure analysis, no message is sent to anyone),
|
|
9
|
+
* so they run regardless of BLIP_ALLOW_WRITES. The exact content-analysis
|
|
10
|
+
* contract can vary per account, hence EXPERIMENTAL.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from "zod";
|
|
13
|
+
import { attempt, jsonResult } from "./shared.js";
|
|
14
|
+
const AI = "postmaster@ai.msging.net";
|
|
15
|
+
const ANALYSIS_REQUEST_MIME = "application/vnd.iris.ai.analysis-request+json";
|
|
16
|
+
export function registerAiTools(ctx) {
|
|
17
|
+
const { server, client } = ctx;
|
|
18
|
+
server.registerTool("blip_ask_ai", {
|
|
19
|
+
title: "Ask your bot's AI / knowledge base (experimental)",
|
|
20
|
+
description: "EXPERIMENTAL. Send a sentence to your bot's AI extension and get a result. " +
|
|
21
|
+
"mode='knowledge' (default) queries the knowledge base / smart content; " +
|
|
22
|
+
"mode='intent' returns detected intentions and entities. No message is sent " +
|
|
23
|
+
"to any user — this only analyzes text.",
|
|
24
|
+
inputSchema: {
|
|
25
|
+
text: z.string().min(1).describe("The sentence/question to analyze."),
|
|
26
|
+
mode: z
|
|
27
|
+
.enum(["knowledge", "intent"])
|
|
28
|
+
.default("knowledge")
|
|
29
|
+
.describe("knowledge = knowledge base answer; intent = intentions/entities."),
|
|
30
|
+
modelId: z
|
|
31
|
+
.string()
|
|
32
|
+
.optional()
|
|
33
|
+
.describe("Optional AI model id; defaults to the last published model."),
|
|
34
|
+
},
|
|
35
|
+
annotations: { readOnlyHint: true, openWorldHint: true },
|
|
36
|
+
}, async (args) => attempt(ctx, async () => {
|
|
37
|
+
const uri = args.mode === "knowledge" ? "/content/analysis" : "/analysis";
|
|
38
|
+
const resource = { text: args.text };
|
|
39
|
+
if (args.modelId)
|
|
40
|
+
resource["modelId"] = args.modelId;
|
|
41
|
+
const res = await client.sendCommand({
|
|
42
|
+
method: "set",
|
|
43
|
+
to: AI,
|
|
44
|
+
uri,
|
|
45
|
+
type: ANALYSIS_REQUEST_MIME,
|
|
46
|
+
resource,
|
|
47
|
+
});
|
|
48
|
+
return jsonResult(res.resource ?? res);
|
|
49
|
+
}));
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=ai.js.map
|