@band-ai/sdk 0.1.6 → 0.2.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/README.md +372 -0
- package/dist/{ClaudeSDKAdapter-CRq4R-WB.d.cts → ClaudeSDKAdapter-BY4zEbCl.d.cts} +14 -10
- package/dist/{ClaudeSDKAdapter-BHOkjN3X.d.ts → ClaudeSDKAdapter-Cna5P1dR.d.ts} +14 -10
- package/dist/{acp-server-B1Da7L6u.d.ts → acp-server-CiUqN3G3.d.ts} +2 -2
- package/dist/{acp-server-BdRz9_UN.d.cts → acp-server-Dlj7D563.d.cts} +2 -2
- package/dist/adapters.cjs +734 -279
- package/dist/adapters.d.cts +21 -19
- package/dist/adapters.d.ts +21 -19
- package/dist/adapters.js +65 -44
- package/dist/backends-D-dBdDm-.d.ts +27 -0
- package/dist/backends-ZLxmQrTZ.d.cts +27 -0
- package/dist/{chunk-MSL6CWHY.js → chunk-4IAXZBXX.js} +77 -37
- package/dist/{chunk-SG4WLD2H.js → chunk-EAI2M3WM.js} +38 -94
- package/dist/{chunk-YR3BOQNW.js → chunk-JY75VSQK.js} +7 -7
- package/dist/{chunk-INA6YZTZ.js → chunk-LBWKISBS.js} +51 -31
- package/dist/{chunk-I5EZG52P.js → chunk-N2QTUMGO.js} +532 -327
- package/dist/{chunk-RHVH2GZR.js → chunk-NMZLX7TP.js} +110 -56
- package/dist/{chunk-EDPKUUJL.js → chunk-NT7TBFX2.js} +9 -1
- package/dist/{chunk-GVEQ3RAH.js → chunk-RV76SKFT.js} +169 -54
- package/dist/{chunk-W5NDZSYE.js → chunk-TLBCKDQO.js} +23 -23
- package/dist/chunk-US226AS4.js +130 -0
- package/dist/{chunk-IZPV6QS6.js → chunk-WL2HNJZ6.js} +38 -11
- package/dist/chunk-WLCM2OXG.js +181 -0
- package/dist/config.cjs +40 -13
- package/dist/config.d.cts +7 -1
- package/dist/config.d.ts +7 -1
- package/dist/config.js +2 -2
- package/dist/converters.cjs +491 -35
- package/dist/converters.d.cts +5 -5
- package/dist/converters.d.ts +5 -5
- package/dist/converters.js +4 -3
- package/dist/core.cjs +53 -10
- package/dist/core.d.cts +10 -9
- package/dist/core.d.ts +10 -9
- package/dist/core.js +8 -4
- package/dist/disconnectReason-IuADl6TH.d.cts +34 -0
- package/dist/disconnectReason-IuADl6TH.d.ts +34 -0
- package/dist/{dtos-DUpbIu8k.d.ts → dtos-B8KU_q4d.d.cts} +26 -6
- package/dist/{dtos-DUpbIu8k.d.cts → dtos-B8KU_q4d.d.ts} +26 -6
- package/dist/index.cjs +1510 -735
- package/dist/index.d.cts +18 -16
- package/dist/index.d.ts +18 -16
- package/dist/index.js +21 -13
- package/dist/linear.cjs +1044 -112
- package/dist/linear.d.cts +146 -16
- package/dist/linear.d.ts +146 -16
- package/dist/linear.js +1031 -110
- package/dist/mcp-claude.cjs +338 -66
- package/dist/mcp-claude.d.cts +3 -3
- package/dist/mcp-claude.d.ts +3 -3
- package/dist/mcp-claude.js +215 -16
- package/dist/mcp.cjs +414 -105
- package/dist/mcp.d.cts +29 -16
- package/dist/mcp.d.ts +29 -16
- package/dist/mcp.js +14 -14
- package/dist/{opencode-BBcDchcN.d.cts → opencode-2YdscIc1.d.cts} +5 -5
- package/dist/{opencode-DthQQUsZ.d.ts → opencode-Bld62x5t.d.ts} +5 -5
- package/dist/{pagination-CcDkVFxK.d.ts → pagination-BgEx-HeL.d.ts} +2 -2
- package/dist/{pagination-BPiys10t.d.cts → pagination-DqdkQArT.d.cts} +2 -2
- package/dist/{protocols-DrhzOH6K.d.ts → protocols-Bwwcql0h.d.ts} +1 -1
- package/dist/{protocols-CInhtFpA.d.cts → protocols-Bz1rxcUg.d.cts} +1 -1
- package/dist/rest.cjs +41 -97
- package/dist/rest.d.cts +7 -7
- package/dist/rest.d.ts +7 -7
- package/dist/rest.js +2 -2
- package/dist/runtime.cjs +998 -620
- package/dist/runtime.d.cts +22 -29
- package/dist/runtime.d.ts +22 -29
- package/dist/runtime.js +19 -67
- package/dist/{schemas-BpEBkq5V.d.cts → schemas-BotL3ZLH.d.cts} +51 -56
- package/dist/{schemas-vos1AaBc.d.ts → schemas-DBsC4J1g.d.ts} +51 -56
- package/dist/{sdk-CwTAxhwI.d.cts → sdk-BTciSLRQ.d.cts} +35 -5
- package/dist/{sdk-CcnQ5OUC.d.ts → sdk-qKJtMma_.d.ts} +35 -5
- package/dist/{simpleAdapter-9OE_p6QW.d.ts → simpleAdapter--wznuoOw.d.ts} +1 -1
- package/dist/{simpleAdapter-DqhvjsGr.d.cts → simpleAdapter-BpT4XbZC.d.cts} +1 -1
- package/dist/testing.d.cts +3 -3
- package/dist/testing.d.ts +3 -3
- package/dist/{types-7jVzOeOP.d.ts → types-BTN_ZETM.d.ts} +2 -2
- package/dist/{types-CxII3XkA.d.ts → types-BgYFd_Yw.d.cts} +5 -5
- package/dist/{types-CSHFipIc.d.cts → types-BivGO7I9.d.ts} +5 -5
- package/dist/{types-CovcHpYf.d.cts → types-D958TC71.d.cts} +2 -2
- package/package.json +25 -23
- package/dist/backends-CzDbiQar.d.ts +0 -20
- package/dist/backends-SVMT-7l4.d.cts +0 -20
- package/dist/chunk-SFVKOEQH.js +0 -103
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// src/platform/streaming/disconnectReason.ts
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
var UPGRADE_CODES = [
|
|
4
|
+
"invalid_on_conflict",
|
|
5
|
+
"connection_conflict",
|
|
6
|
+
"too_many_requests",
|
|
7
|
+
"tracking_failed"
|
|
8
|
+
];
|
|
9
|
+
var UPGRADE_REASONS = {
|
|
10
|
+
invalid_on_conflict: {
|
|
11
|
+
status: 400,
|
|
12
|
+
message: "Invalid websocket conflict policy.",
|
|
13
|
+
retryable: false
|
|
14
|
+
},
|
|
15
|
+
connection_conflict: {
|
|
16
|
+
status: 409,
|
|
17
|
+
message: "Websocket connection conflict.",
|
|
18
|
+
retryable: false
|
|
19
|
+
},
|
|
20
|
+
too_many_requests: {
|
|
21
|
+
status: 429,
|
|
22
|
+
message: "Too many websocket connection attempts.",
|
|
23
|
+
retryable: true
|
|
24
|
+
},
|
|
25
|
+
tracking_failed: {
|
|
26
|
+
status: 503,
|
|
27
|
+
message: "Websocket connection tracking failed.",
|
|
28
|
+
retryable: true
|
|
29
|
+
}
|
|
30
|
+
};
|
|
31
|
+
var upgradeErrorSchema = z.object({
|
|
32
|
+
status: z.number(),
|
|
33
|
+
body: z.preprocess(
|
|
34
|
+
(body) => {
|
|
35
|
+
if (typeof body !== "string") {
|
|
36
|
+
return body;
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
return JSON.parse(body);
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
},
|
|
44
|
+
z.object({
|
|
45
|
+
error: z.object({
|
|
46
|
+
code: z.enum(UPGRADE_CODES),
|
|
47
|
+
message: z.string().optional(),
|
|
48
|
+
retry_after: z.number().nullable().optional(),
|
|
49
|
+
request_id: z.string().nullable().optional()
|
|
50
|
+
})
|
|
51
|
+
})
|
|
52
|
+
),
|
|
53
|
+
headers: z.record(z.unknown()).optional()
|
|
54
|
+
});
|
|
55
|
+
var WebSocketDisconnectError = class extends Error {
|
|
56
|
+
reason;
|
|
57
|
+
constructor(reason) {
|
|
58
|
+
super(reason.message);
|
|
59
|
+
this.name = "WebSocketDisconnectError";
|
|
60
|
+
this.reason = reason;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
function parseSupersedeDisconnectReason(payload) {
|
|
64
|
+
if (typeof payload.reason !== "string" || typeof payload.message !== "string") {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return {
|
|
68
|
+
source: "agent_control",
|
|
69
|
+
code: payload.reason,
|
|
70
|
+
message: payload.message,
|
|
71
|
+
retryable: false,
|
|
72
|
+
retryAfter: typeof payload.retry_after === "number" ? payload.retry_after : null,
|
|
73
|
+
targetSocketId: typeof payload.target_socket_id === "string" ? payload.target_socket_id : null,
|
|
74
|
+
correlationId: typeof payload.correlation_id === "string" ? payload.correlation_id : null
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
function parseUpgradeDisconnectReason(event) {
|
|
78
|
+
const parsed = upgradeErrorSchema.safeParse(event);
|
|
79
|
+
if (!parsed.success) {
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
const { status, body, headers } = parsed.data;
|
|
83
|
+
const {
|
|
84
|
+
code,
|
|
85
|
+
message,
|
|
86
|
+
retry_after: retryAfter,
|
|
87
|
+
request_id: requestId
|
|
88
|
+
} = body.error;
|
|
89
|
+
const reason = UPGRADE_REASONS[code];
|
|
90
|
+
if (status !== reason.status) {
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return {
|
|
94
|
+
source: "upgrade",
|
|
95
|
+
status: reason.status,
|
|
96
|
+
code,
|
|
97
|
+
message: message ?? reason.message,
|
|
98
|
+
retryable: reason.retryable,
|
|
99
|
+
retryAfter: retryAfter ?? retryAfterFromHeaders(headers),
|
|
100
|
+
requestId: requestId ?? null
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
function genericCloseReason(event) {
|
|
104
|
+
return {
|
|
105
|
+
source: "websocket_close",
|
|
106
|
+
code: "websocket.closed",
|
|
107
|
+
message: "Phoenix socket closed without a platform disconnect reason.",
|
|
108
|
+
retryable: true,
|
|
109
|
+
closeCode: typeof event?.code === "number" ? event.code : null,
|
|
110
|
+
closeReason: typeof event?.reason === "string" && event.reason.length > 0 ? event.reason : null
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function retryAfterFromHeaders(headers) {
|
|
114
|
+
const value = headers?.["retry-after"] ?? headers?.["Retry-After"];
|
|
115
|
+
if (typeof value === "number") {
|
|
116
|
+
return value;
|
|
117
|
+
}
|
|
118
|
+
if (typeof value === "string" && value.trim() !== "") {
|
|
119
|
+
const seconds = Number(value);
|
|
120
|
+
return Number.isFinite(seconds) ? seconds : null;
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export {
|
|
126
|
+
WebSocketDisconnectError,
|
|
127
|
+
parseSupersedeDisconnectReason,
|
|
128
|
+
parseUpgradeDisconnectReason,
|
|
129
|
+
genericCloseReason
|
|
130
|
+
};
|
|
@@ -1,12 +1,26 @@
|
|
|
1
1
|
import {
|
|
2
2
|
ValidationError
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-JY75VSQK.js";
|
|
4
4
|
|
|
5
5
|
// src/config/loader.ts
|
|
6
6
|
import { readFileSync } from "fs";
|
|
7
7
|
import yaml from "js-yaml";
|
|
8
8
|
var DEFAULT_CONFIG_PATH = "./agent_config.yaml";
|
|
9
|
-
var DEFAULT_ENV_PREFIX = "
|
|
9
|
+
var DEFAULT_ENV_PREFIX = "BAND_";
|
|
10
|
+
var LEGACY_ENV_PREFIX = "THENVOI_";
|
|
11
|
+
var _warnedLegacyEnvVars = /* @__PURE__ */ new Set();
|
|
12
|
+
function readBandFirstEnv(env, field) {
|
|
13
|
+
const bandVar = `${DEFAULT_ENV_PREFIX}${field}`;
|
|
14
|
+
const bandValue = env[bandVar];
|
|
15
|
+
if (bandValue !== void 0) return bandValue;
|
|
16
|
+
const legacyVar = `${LEGACY_ENV_PREFIX}${field}`;
|
|
17
|
+
const legacyValue = env[legacyVar];
|
|
18
|
+
if (legacyValue !== void 0 && !_warnedLegacyEnvVars.has(legacyVar)) {
|
|
19
|
+
_warnedLegacyEnvVars.add(legacyVar);
|
|
20
|
+
console.warn(`[band] ${legacyVar} is deprecated; use ${bandVar} instead`);
|
|
21
|
+
}
|
|
22
|
+
return legacyValue;
|
|
23
|
+
}
|
|
10
24
|
var REQUIRED_FIELDS = ["agent_id", "api_key"];
|
|
11
25
|
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype", "toString", "valueOf"]);
|
|
12
26
|
function toSnakeCase(key) {
|
|
@@ -90,19 +104,32 @@ function loadAgentConfig(agentKey, configPath) {
|
|
|
90
104
|
}
|
|
91
105
|
function loadAgentConfigFromEnv(options) {
|
|
92
106
|
const env = options?.env ?? process.env;
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
107
|
+
let section;
|
|
108
|
+
let requiredHint;
|
|
109
|
+
if (options?.prefix === void 0) {
|
|
110
|
+
section = normalizeKeys({
|
|
111
|
+
agent_id: readBandFirstEnv(env, "AGENT_ID"),
|
|
112
|
+
api_key: readBandFirstEnv(env, "API_KEY"),
|
|
113
|
+
ws_url: readBandFirstEnv(env, "WS_URL"),
|
|
114
|
+
rest_url: readBandFirstEnv(env, "REST_URL")
|
|
115
|
+
});
|
|
116
|
+
requiredHint = `${DEFAULT_ENV_PREFIX}AGENT_ID and ${DEFAULT_ENV_PREFIX}API_KEY (legacy ${LEGACY_ENV_PREFIX}* still accepted)`;
|
|
117
|
+
} else {
|
|
118
|
+
const prefix = options.prefix === "" || options.prefix.endsWith("_") ? options.prefix : `${options.prefix}_`;
|
|
119
|
+
section = normalizeKeys({
|
|
120
|
+
agent_id: env[`${prefix}AGENT_ID`],
|
|
121
|
+
api_key: env[`${prefix}API_KEY`],
|
|
122
|
+
ws_url: env[`${prefix}WS_URL`],
|
|
123
|
+
rest_url: env[`${prefix}REST_URL`]
|
|
124
|
+
});
|
|
125
|
+
requiredHint = `${prefix}AGENT_ID and ${prefix}API_KEY`;
|
|
126
|
+
}
|
|
100
127
|
try {
|
|
101
|
-
return toAgentConfigResult(section, `environment variables (${
|
|
128
|
+
return toAgentConfigResult(section, `environment variables (${requiredHint})`);
|
|
102
129
|
} catch (error) {
|
|
103
130
|
if (error instanceof ValidationError) {
|
|
104
131
|
throw new ValidationError(
|
|
105
|
-
`${error.message}. Set ${
|
|
132
|
+
`${error.message}. Set ${requiredHint}, or use loadAgentConfig() for agent_config.yaml.`
|
|
106
133
|
);
|
|
107
134
|
}
|
|
108
135
|
throw error;
|
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
import {
|
|
2
|
+
MEMORY_SEGMENT,
|
|
3
|
+
MEMORY_STORE_SCOPE,
|
|
4
|
+
MEMORY_SYSTEM,
|
|
5
|
+
MEMORY_SYSTEM_TYPES,
|
|
6
|
+
MEMORY_TYPE,
|
|
7
|
+
TOOL_MODELS
|
|
8
|
+
} from "./chunk-RV76SKFT.js";
|
|
9
|
+
|
|
10
|
+
// src/runtime/prompts/base.ts
|
|
11
|
+
var ENVIRONMENT_SECTION = `
|
|
12
|
+
## Environment
|
|
13
|
+
|
|
14
|
+
Multi-participant chat. Messages show sender: [Name]: content.
|
|
15
|
+
Messages prefixed with [System]: are platform updates (participant changes, contact updates, etc.) \u2014 not messages from users.
|
|
16
|
+
Use \`band_send_message(content, mentions)\` to respond. Plain text output is not delivered.
|
|
17
|
+
Mentions use handles: @<username> for users, @<username>/<agent-name> for agents.`;
|
|
18
|
+
var MULTI_AGENT_RULES_SECTION = `## CRITICAL: Delegate When You Cannot Help Directly
|
|
19
|
+
|
|
20
|
+
You have NO internet access and NO real-time data. When asked about weather, news, stock prices,
|
|
21
|
+
or any current information you cannot answer directly:
|
|
22
|
+
|
|
23
|
+
1. Call \`band_lookup_peers()\` to find available specialized agents
|
|
24
|
+
2. If a relevant agent exists, call \`band_add_participant(name)\` to add them
|
|
25
|
+
3. Ask that agent using \`band_send_message(question, mentions=[agent_handle])\`
|
|
26
|
+
4. Wait for their response and relay it back to the user
|
|
27
|
+
|
|
28
|
+
NEVER say "I can't do that" without first checking if another agent can help via \`band_lookup_peers()\`.
|
|
29
|
+
|
|
30
|
+
## CRITICAL: Do NOT Remove Agents Automatically
|
|
31
|
+
|
|
32
|
+
After adding an agent to help with a task:
|
|
33
|
+
1. Ask your question and wait for their response
|
|
34
|
+
2. Relay their response back to the original requester
|
|
35
|
+
3. **Do NOT remove the agent** - they stay silent unless mentioned and may be useful for follow-ups
|
|
36
|
+
|
|
37
|
+
Only remove agents if the user explicitly requests it.
|
|
38
|
+
|
|
39
|
+
## CRITICAL: Always Relay Information Back to the Requester
|
|
40
|
+
|
|
41
|
+
When someone asks you to get information from another agent:
|
|
42
|
+
1. Ask the other agent for the information
|
|
43
|
+
2. When you receive the response, IMMEDIATELY relay it back to the ORIGINAL REQUESTER
|
|
44
|
+
3. Do NOT just thank the helper agent - the requester is waiting for their answer!`;
|
|
45
|
+
var THINKING_SECTION = `## IMPORTANT: Always Share Your Thinking
|
|
46
|
+
|
|
47
|
+
You MUST call \`band_send_event(content, message_type="thought")\` BEFORE every action.
|
|
48
|
+
This is required so users can see your reasoning process.`;
|
|
49
|
+
var EXAMPLES_SECTION = `## Examples
|
|
50
|
+
|
|
51
|
+
### Simple question - answer directly
|
|
52
|
+
[John Doe]: What's 2+2?
|
|
53
|
+
-> band_send_event("Simple arithmetic, answering directly.", message_type="thought")
|
|
54
|
+
-> band_send_message("4", mentions=["@john"])
|
|
55
|
+
|
|
56
|
+
### User asks about weather (you cannot answer directly)
|
|
57
|
+
[John Doe]: What's the weather in Tokyo?
|
|
58
|
+
-> band_send_event("I can't check weather directly. Looking for a Weather Agent.", message_type="thought")
|
|
59
|
+
-> band_lookup_peers()
|
|
60
|
+
-> band_send_event("Found Weather Agent. Adding to room.", message_type="thought")
|
|
61
|
+
-> band_add_participant("Weather Agent")
|
|
62
|
+
-> band_send_message("What's the weather in Tokyo?", mentions=["@john/weather-agent"])
|
|
63
|
+
|
|
64
|
+
[Weather Agent]: Tokyo is 15\xB0C and cloudy.
|
|
65
|
+
-> band_send_event("Got weather response. Relaying back to John Doe.", message_type="thought")
|
|
66
|
+
-> band_send_message("The weather in Tokyo is 15\xB0C and cloudy.", mentions=["@john"])
|
|
67
|
+
|
|
68
|
+
### No suitable agent available
|
|
69
|
+
[John Doe]: What's the stock price of AAPL?
|
|
70
|
+
-> band_send_event("I can't check stock prices. Looking for a Stock Agent.", message_type="thought")
|
|
71
|
+
-> band_lookup_peers()
|
|
72
|
+
-> band_send_event("No stock agent available. Must inform user.", message_type="thought")
|
|
73
|
+
-> band_send_message("I don't have access to stock prices, and there's no specialized agent available to help with that.", mentions=["@john"])
|
|
74
|
+
|
|
75
|
+
### Follow-up question in same conversation
|
|
76
|
+
[John Doe]: What about London?
|
|
77
|
+
-> band_send_event("Follow-up weather question. Asking Weather Agent.", message_type="thought")
|
|
78
|
+
-> band_send_message("What's the weather in London?", mentions=["@john/weather-agent"])
|
|
79
|
+
|
|
80
|
+
[Weather Agent]: London is 8\xB0C and rainy.
|
|
81
|
+
-> band_send_event("Got London weather. Relaying to John Doe.", message_type="thought")
|
|
82
|
+
-> band_send_message("London is 8\xB0C and rainy.", mentions=["@john"])`;
|
|
83
|
+
var BASE_INSTRUCTIONS = [
|
|
84
|
+
ENVIRONMENT_SECTION,
|
|
85
|
+
MULTI_AGENT_RULES_SECTION,
|
|
86
|
+
THINKING_SECTION,
|
|
87
|
+
EXAMPLES_SECTION
|
|
88
|
+
].join("\n\n") + "\n";
|
|
89
|
+
|
|
90
|
+
// src/runtime/prompts/memory.ts
|
|
91
|
+
var MEMORY_INTRO = `## Memory Tools
|
|
92
|
+
|
|
93
|
+
You have access to memory tools for storing and retrieving information
|
|
94
|
+
across conversations. Use \`band_store_memory\` to persist important
|
|
95
|
+
information and \`band_list_memories\` / \`band_get_memory\` to recall it.
|
|
96
|
+
Use \`band_supersede_memory\` to mark outdated memories and
|
|
97
|
+
\`band_archive_memory\` to hide memories that should be preserved.`;
|
|
98
|
+
function longTermPattern(label, type, segment, scope) {
|
|
99
|
+
return {
|
|
100
|
+
label,
|
|
101
|
+
system: MEMORY_SYSTEM.long_term,
|
|
102
|
+
type,
|
|
103
|
+
segment,
|
|
104
|
+
scope
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
var COMMON_MEMORY_PATTERNS = [
|
|
108
|
+
longTermPattern("Facts learned about a specific agent/entity", MEMORY_TYPE.semantic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
|
|
109
|
+
longTermPattern("Events involving a specific person/agent", MEMORY_TYPE.episodic, MEMORY_SEGMENT.agent, MEMORY_STORE_SCOPE.subject),
|
|
110
|
+
longTermPattern("A user's preferences or profile info", MEMORY_TYPE.semantic, MEMORY_SEGMENT.user, MEMORY_STORE_SCOPE.subject),
|
|
111
|
+
longTermPattern("Org-wide knowledge or how to perform a task", MEMORY_TYPE.procedural, MEMORY_SEGMENT.tool, MEMORY_STORE_SCOPE.organization)
|
|
112
|
+
];
|
|
113
|
+
function renderMemoryPattern(pattern) {
|
|
114
|
+
return `- ${pattern.label}: \`system="${pattern.system}"\`, \`type="${pattern.type}"\`, \`segment="${pattern.segment}"\`, \`scope="${pattern.scope}"\``;
|
|
115
|
+
}
|
|
116
|
+
var MEMORY_COMMON_PATTERNS = [
|
|
117
|
+
"Common patterns:",
|
|
118
|
+
...COMMON_MEMORY_PATTERNS.map(renderMemoryPattern)
|
|
119
|
+
].join("\n");
|
|
120
|
+
var MEMORY_SCOPE_GUIDANCE = `Prefer \`scope="${MEMORY_STORE_SCOPE.subject}"\` whenever the memory is about a specific person or agent, so it
|
|
121
|
+
stays attached to that subject rather than leaking org-wide. Storing with \`scope="${MEMORY_STORE_SCOPE.subject}"\` requires a
|
|
122
|
+
real \`subject_id\` UUID, so resolve it first via \`band_lookup_peers\` or the participant list.
|
|
123
|
+
Reserve \`scope="${MEMORY_STORE_SCOPE.organization}"\` for knowledge that is genuinely shared across the whole organization and
|
|
124
|
+
is not about any one subject.`;
|
|
125
|
+
function quoteChoices(values) {
|
|
126
|
+
return values.map((value) => `\`"${value}"\``).join(" | ");
|
|
127
|
+
}
|
|
128
|
+
function memoryTypeLines() {
|
|
129
|
+
return Object.entries(MEMORY_SYSTEM_TYPES).map(([system, types]) => ` - ${system}: ${quoteChoices(types)}`).join("\n");
|
|
130
|
+
}
|
|
131
|
+
function buildMemorySection() {
|
|
132
|
+
const storeMemoryProps = TOOL_MODELS.band_store_memory.properties;
|
|
133
|
+
const systems = storeMemoryProps.system.enum;
|
|
134
|
+
const segments = storeMemoryProps.segment.enum;
|
|
135
|
+
const scopes = storeMemoryProps.scope.enum;
|
|
136
|
+
const fieldRules = `When calling \`band_store_memory\`, the \`system\`, \`type\`, \`segment\`, and \`scope\` fields
|
|
137
|
+
must use these exact values (case-sensitive):
|
|
138
|
+
|
|
139
|
+
- **system**: ${quoteChoices(systems)}
|
|
140
|
+
- **type** (must match the chosen system):
|
|
141
|
+
${memoryTypeLines()}
|
|
142
|
+
- **segment**: ${quoteChoices(segments)}
|
|
143
|
+
- **scope**: ${quoteChoices(scopes)}`;
|
|
144
|
+
return [MEMORY_INTRO, fieldRules, MEMORY_COMMON_PATTERNS, MEMORY_SCOPE_GUIDANCE].join("\n\n");
|
|
145
|
+
}
|
|
146
|
+
var MEMORY_SECTION = buildMemorySection();
|
|
147
|
+
|
|
148
|
+
// src/runtime/prompts/templates.ts
|
|
149
|
+
var TEMPLATES = {
|
|
150
|
+
default: `You are {agent_name}, {agent_description}.
|
|
151
|
+
|
|
152
|
+
{custom_section}
|
|
153
|
+
` + BASE_INSTRUCTIONS
|
|
154
|
+
};
|
|
155
|
+
function renderSystemPrompt(options) {
|
|
156
|
+
const agentName = options?.agentName ?? "Agent";
|
|
157
|
+
const agentDescription = options?.agentDescription ?? "An AI assistant";
|
|
158
|
+
const customSection = options?.customSection ?? "";
|
|
159
|
+
const includeBaseInstructions = options?.includeBaseInstructions ?? true;
|
|
160
|
+
if (!includeBaseInstructions) {
|
|
161
|
+
return `You are ${agentName}, ${agentDescription}.
|
|
162
|
+
|
|
163
|
+
${customSection}`.trim();
|
|
164
|
+
}
|
|
165
|
+
const template = options?.template ?? "default";
|
|
166
|
+
const templateString = TEMPLATES[template] ?? TEMPLATES.default;
|
|
167
|
+
const parts = [
|
|
168
|
+
templateString.replaceAll("{agent_name}", agentName).replaceAll("{agent_description}", agentDescription).replaceAll("{custom_section}", customSection)
|
|
169
|
+
];
|
|
170
|
+
if (options?.capabilities?.memory) {
|
|
171
|
+
parts.push(MEMORY_SECTION);
|
|
172
|
+
}
|
|
173
|
+
return parts.join("\n\n");
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export {
|
|
177
|
+
BASE_INSTRUCTIONS,
|
|
178
|
+
MEMORY_SECTION,
|
|
179
|
+
TEMPLATES,
|
|
180
|
+
renderSystemPrompt
|
|
181
|
+
};
|
package/dist/config.cjs
CHANGED
|
@@ -40,13 +40,13 @@ var import_node_fs = require("fs");
|
|
|
40
40
|
var import_js_yaml = __toESM(require("js-yaml"), 1);
|
|
41
41
|
|
|
42
42
|
// src/core/errors.ts
|
|
43
|
-
var
|
|
43
|
+
var BandSdkError = class extends Error {
|
|
44
44
|
constructor(message, cause) {
|
|
45
45
|
super(message, cause !== void 0 ? { cause } : void 0);
|
|
46
|
-
this.name = "
|
|
46
|
+
this.name = "BandSdkError";
|
|
47
47
|
}
|
|
48
48
|
};
|
|
49
|
-
var ValidationError = class extends
|
|
49
|
+
var ValidationError = class extends BandSdkError {
|
|
50
50
|
constructor(message, cause) {
|
|
51
51
|
super(message, cause);
|
|
52
52
|
this.name = "ValidationError";
|
|
@@ -55,7 +55,21 @@ var ValidationError = class extends ThenvoiSdkError {
|
|
|
55
55
|
|
|
56
56
|
// src/config/loader.ts
|
|
57
57
|
var DEFAULT_CONFIG_PATH = "./agent_config.yaml";
|
|
58
|
-
var DEFAULT_ENV_PREFIX = "
|
|
58
|
+
var DEFAULT_ENV_PREFIX = "BAND_";
|
|
59
|
+
var LEGACY_ENV_PREFIX = "THENVOI_";
|
|
60
|
+
var _warnedLegacyEnvVars = /* @__PURE__ */ new Set();
|
|
61
|
+
function readBandFirstEnv(env, field) {
|
|
62
|
+
const bandVar = `${DEFAULT_ENV_PREFIX}${field}`;
|
|
63
|
+
const bandValue = env[bandVar];
|
|
64
|
+
if (bandValue !== void 0) return bandValue;
|
|
65
|
+
const legacyVar = `${LEGACY_ENV_PREFIX}${field}`;
|
|
66
|
+
const legacyValue = env[legacyVar];
|
|
67
|
+
if (legacyValue !== void 0 && !_warnedLegacyEnvVars.has(legacyVar)) {
|
|
68
|
+
_warnedLegacyEnvVars.add(legacyVar);
|
|
69
|
+
console.warn(`[band] ${legacyVar} is deprecated; use ${bandVar} instead`);
|
|
70
|
+
}
|
|
71
|
+
return legacyValue;
|
|
72
|
+
}
|
|
59
73
|
var REQUIRED_FIELDS = ["agent_id", "api_key"];
|
|
60
74
|
var UNSAFE_KEYS = /* @__PURE__ */ new Set(["__proto__", "constructor", "prototype", "toString", "valueOf"]);
|
|
61
75
|
function toSnakeCase(key) {
|
|
@@ -139,19 +153,32 @@ function loadAgentConfig(agentKey, configPath) {
|
|
|
139
153
|
}
|
|
140
154
|
function loadAgentConfigFromEnv(options) {
|
|
141
155
|
const env = options?.env ?? process.env;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
156
|
+
let section;
|
|
157
|
+
let requiredHint;
|
|
158
|
+
if (options?.prefix === void 0) {
|
|
159
|
+
section = normalizeKeys({
|
|
160
|
+
agent_id: readBandFirstEnv(env, "AGENT_ID"),
|
|
161
|
+
api_key: readBandFirstEnv(env, "API_KEY"),
|
|
162
|
+
ws_url: readBandFirstEnv(env, "WS_URL"),
|
|
163
|
+
rest_url: readBandFirstEnv(env, "REST_URL")
|
|
164
|
+
});
|
|
165
|
+
requiredHint = `${DEFAULT_ENV_PREFIX}AGENT_ID and ${DEFAULT_ENV_PREFIX}API_KEY (legacy ${LEGACY_ENV_PREFIX}* still accepted)`;
|
|
166
|
+
} else {
|
|
167
|
+
const prefix = options.prefix === "" || options.prefix.endsWith("_") ? options.prefix : `${options.prefix}_`;
|
|
168
|
+
section = normalizeKeys({
|
|
169
|
+
agent_id: env[`${prefix}AGENT_ID`],
|
|
170
|
+
api_key: env[`${prefix}API_KEY`],
|
|
171
|
+
ws_url: env[`${prefix}WS_URL`],
|
|
172
|
+
rest_url: env[`${prefix}REST_URL`]
|
|
173
|
+
});
|
|
174
|
+
requiredHint = `${prefix}AGENT_ID and ${prefix}API_KEY`;
|
|
175
|
+
}
|
|
149
176
|
try {
|
|
150
|
-
return toAgentConfigResult(section, `environment variables (${
|
|
177
|
+
return toAgentConfigResult(section, `environment variables (${requiredHint})`);
|
|
151
178
|
} catch (error) {
|
|
152
179
|
if (error instanceof ValidationError) {
|
|
153
180
|
throw new ValidationError(
|
|
154
|
-
`${error.message}. Set ${
|
|
181
|
+
`${error.message}. Set ${requiredHint}, or use loadAgentConfig() for agent_config.yaml.`
|
|
155
182
|
);
|
|
156
183
|
}
|
|
157
184
|
throw error;
|
package/dist/config.d.cts
CHANGED
|
@@ -13,7 +13,13 @@ interface LoadAgentConfigFromEnvOptions {
|
|
|
13
13
|
}
|
|
14
14
|
/** Load agent credentials from a YAML config file (defaults to `./agent_config.yaml`). */
|
|
15
15
|
declare function loadAgentConfig(agentKey?: string, configPath?: string): AgentConfigResult;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Load agent credentials from environment variables. With no explicit prefix the
|
|
18
|
+
* default is `BAND_` with a per-field fallback to the legacy `THENVOI_` variable
|
|
19
|
+
* (Band wins independently for each of AGENT_ID/API_KEY/WS_URL/REST_URL, and each
|
|
20
|
+
* legacy variable used warns once per process). An explicit prefix — including an
|
|
21
|
+
* empty string — is used exactly, with no fallback or warning.
|
|
22
|
+
*/
|
|
17
23
|
declare function loadAgentConfigFromEnv(options?: LoadAgentConfigFromEnvOptions): AgentCredentials;
|
|
18
24
|
|
|
19
25
|
export { type AgentConfigResult, type AgentCredentials, type LoadAgentConfigFromEnvOptions, loadAgentConfig, loadAgentConfigFromEnv };
|
package/dist/config.d.ts
CHANGED
|
@@ -13,7 +13,13 @@ interface LoadAgentConfigFromEnvOptions {
|
|
|
13
13
|
}
|
|
14
14
|
/** Load agent credentials from a YAML config file (defaults to `./agent_config.yaml`). */
|
|
15
15
|
declare function loadAgentConfig(agentKey?: string, configPath?: string): AgentConfigResult;
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* Load agent credentials from environment variables. With no explicit prefix the
|
|
18
|
+
* default is `BAND_` with a per-field fallback to the legacy `THENVOI_` variable
|
|
19
|
+
* (Band wins independently for each of AGENT_ID/API_KEY/WS_URL/REST_URL, and each
|
|
20
|
+
* legacy variable used warns once per process). An explicit prefix — including an
|
|
21
|
+
* empty string — is used exactly, with no fallback or warning.
|
|
22
|
+
*/
|
|
17
23
|
declare function loadAgentConfigFromEnv(options?: LoadAgentConfigFromEnvOptions): AgentCredentials;
|
|
18
24
|
|
|
19
25
|
export { type AgentConfigResult, type AgentCredentials, type LoadAgentConfigFromEnvOptions, loadAgentConfig, loadAgentConfigFromEnv };
|
package/dist/config.js
CHANGED