@buda-ai/connector 0.1.35 → 0.1.36
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.
|
@@ -64,19 +64,18 @@ If a user hits a plan limit (e.g., they ask for a cron schedule or an interval l
|
|
|
64
64
|
1. Parse the user's request to determine:
|
|
65
65
|
- **What** the task should do → becomes `taskTemplate.prompt` (the `name` is also used as `taskTemplate.title` automatically)
|
|
66
66
|
- **When** it should run → becomes `scheduleType` + schedule config
|
|
67
|
-
- **
|
|
68
|
-
-
|
|
69
|
-
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
67
|
+
- **Where the result belongs**:
|
|
68
|
+
- When created from a conversation, the tool pins execution to that exact current session.
|
|
69
|
+
- Without a current session, each run creates a new session.
|
|
70
|
+
- Return normal assistant text in the execution session; a bound external conversation receives that reply automatically.
|
|
71
|
+
- Do not configure `taskTemplate.delivery`, use a channel's most recent chat, or call `deliver_to_channel` for the automation's normal result.
|
|
72
|
+
- To change the execution conversation later, use the automation settings in the Buda UI to choose a fixed conversation or a new conversation per run.
|
|
73
73
|
2. Choose the right schedule type (see [Schedule types](#schedule-types) below)
|
|
74
74
|
3. Call the `create_automation` tool. Example for an interval schedule:
|
|
75
75
|
- `name`: "Daily News Briefing"
|
|
76
76
|
- `scheduleType`: "interval"
|
|
77
77
|
- `intervalMinutes`: 1440
|
|
78
78
|
- `taskTemplate.prompt`: "Search today's financial news and generate a summary"
|
|
79
|
-
- `taskTemplate.delivery.mode`: "session"
|
|
80
79
|
|
|
81
80
|
Example for a cron schedule:
|
|
82
81
|
- `name`: "Morning News"
|
|
@@ -84,16 +83,6 @@ If a user hits a plan limit (e.g., they ask for a cron schedule or an interval l
|
|
|
84
83
|
- `cronExpression`: "0 9 * * *"
|
|
85
84
|
- `timezone`: "Asia/Shanghai"
|
|
86
85
|
- `taskTemplate.prompt`: "Search today's financial news and generate a summary"
|
|
87
|
-
- `taskTemplate.delivery.mode`: "session"
|
|
88
|
-
|
|
89
|
-
Example only when the user explicitly asks to push results to a connected chat/group/DM:
|
|
90
|
-
- `name`: "Morning News to Team Group"
|
|
91
|
-
- `scheduleType`: "cron"
|
|
92
|
-
- `cronExpression`: "0 9 * * *"
|
|
93
|
-
- `timezone`: "Asia/Shanghai"
|
|
94
|
-
- `taskTemplate.prompt`: "Search today's financial news and generate a summary"
|
|
95
|
-
- `taskTemplate.delivery.mode`: "notify"
|
|
96
|
-
- `taskTemplate.delivery.sessionId`: "tsk_xxxxxxxxxxxxxxxx"
|
|
97
86
|
|
|
98
87
|
4. Report the result to the user, including the automation name and next run time.
|
|
99
88
|
|
package/dist/cli.js
CHANGED
|
@@ -454,7 +454,7 @@ function parseLaunchConfig(raw) {
|
|
|
454
454
|
bunnyDaemonPort
|
|
455
455
|
};
|
|
456
456
|
}
|
|
457
|
-
const CONNECTOR_RUNTIME_VERSION = "0.1.
|
|
457
|
+
const CONNECTOR_RUNTIME_VERSION = "0.1.36";
|
|
458
458
|
const DEFAULT_CONTROL_REQUEST_TIMEOUT_MS = 3e3;
|
|
459
459
|
const getDaemonControlMetadataPath = (config, configRoot) => `${getConnectorDaemonLockTarget(config.serverUrl, config.connectorId, configRoot)}.control.json`;
|
|
460
460
|
const writeMetadata = async (metadataPath, metadata) => {
|
|
@@ -3455,7 +3455,7 @@ async function stopEmbeddedBunnyDaemon(daemon) {
|
|
|
3455
3455
|
const MIGRATION_VERSION = 1;
|
|
3456
3456
|
const MIGRATION_DIRECTORY = path.join(".buda", "migrations", "legacy-workspace-v1");
|
|
3457
3457
|
const JOURNAL_FILENAME = "journal.json";
|
|
3458
|
-
const IMMUTABLE_ID_PATTERN$1 = /^[A-Za-z0-
|
|
3458
|
+
const IMMUTABLE_ID_PATTERN$1 = /^[A-Za-z0-9_-]{1,128}$/;
|
|
3459
3459
|
const LEGACY_TEMPLATE_FILES = [
|
|
3460
3460
|
"AGENTS.md",
|
|
3461
3461
|
"HEARTBEAT.md",
|
|
@@ -4534,6 +4534,7 @@ function startConnectorRelay(config, bunnyDaemon, relayProtocol, workspaceRegist
|
|
|
4534
4534
|
let activeTerminalTunnels = 0;
|
|
4535
4535
|
const replayGuard = new ConnectorExecutionReplayGuard();
|
|
4536
4536
|
const htmlPreviews = new HtmlPreviewServerRegistry();
|
|
4537
|
+
const workspaceHandlers = new WorkspaceDaemonHandlerStore();
|
|
4537
4538
|
const clearTimers = () => {
|
|
4538
4539
|
if (pingTimer) {
|
|
4539
4540
|
clearInterval(pingTimer);
|
|
@@ -4640,7 +4641,7 @@ function startConnectorRelay(config, bunnyDaemon, relayProtocol, workspaceRegist
|
|
|
4640
4641
|
onTerminalClose: () => {
|
|
4641
4642
|
activeTerminalTunnels = Math.max(0, activeTerminalTunnels - 1);
|
|
4642
4643
|
}
|
|
4643
|
-
}, htmlPreviews);
|
|
4644
|
+
}, htmlPreviews, workspaceHandlers);
|
|
4644
4645
|
});
|
|
4645
4646
|
ws.on("close", (code) => {
|
|
4646
4647
|
detach();
|
|
@@ -4649,6 +4650,7 @@ function startConnectorRelay(config, bunnyDaemon, relayProtocol, workspaceRegist
|
|
|
4649
4650
|
htmlPreviews.closeAll();
|
|
4650
4651
|
if (code === CONNECTOR_SOCKET_REPLACED_CLOSE_CODE) {
|
|
4651
4652
|
stopped = true;
|
|
4653
|
+
workspaceHandlers.clear();
|
|
4652
4654
|
writeLog("warn", "relay replaced by another process for this connector");
|
|
4653
4655
|
} else {
|
|
4654
4656
|
suspendedForAccessRevocation = true;
|
|
@@ -4703,12 +4705,14 @@ function startConnectorRelay(config, bunnyDaemon, relayProtocol, workspaceRegist
|
|
|
4703
4705
|
reconnectTimer = null;
|
|
4704
4706
|
}
|
|
4705
4707
|
clearTimers();
|
|
4708
|
+
for (const controller of currentInflight.values()) controller.abort();
|
|
4709
|
+
workspaceHandlers.clear();
|
|
4706
4710
|
socket?.close();
|
|
4707
4711
|
htmlPreviews.closeAll();
|
|
4708
4712
|
}
|
|
4709
4713
|
};
|
|
4710
4714
|
}
|
|
4711
|
-
async function handleRelayMessage(socket, bunnyDaemon, raw, inflight, expectedConnectorId, relayProtocol, replayGuard, workspaceRegistry, serverUrl, localDaemonBaseUrl, activity, htmlPreviews) {
|
|
4715
|
+
async function handleRelayMessage(socket, bunnyDaemon, raw, inflight, expectedConnectorId, relayProtocol, replayGuard, workspaceRegistry, serverUrl, localDaemonBaseUrl, activity, htmlPreviews, workspaceHandlers) {
|
|
4712
4716
|
if (!socket || socket.readyState !== WebSocket.OPEN) return;
|
|
4713
4717
|
let message;
|
|
4714
4718
|
try {
|
|
@@ -4824,7 +4828,7 @@ async function handleRelayMessage(socket, bunnyDaemon, raw, inflight, expectedCo
|
|
|
4824
4828
|
workdirRoot: mounts?.mountRoot
|
|
4825
4829
|
});
|
|
4826
4830
|
} else if (isHtmlPreviewRequest && mounts && htmlPreviews) response = await handleHtmlPreviewRequest(message.request, mounts, htmlPreviews);
|
|
4827
|
-
else if (descriptor && mounts) response = await handleWorkspaceDaemonRequest(message.request, mounts, controller.signal);
|
|
4831
|
+
else if (descriptor && mounts) response = await handleWorkspaceDaemonRequest(message.request, mounts, controller.signal, workspaceHandlers);
|
|
4828
4832
|
else {
|
|
4829
4833
|
const requestUrl = new URL(requestPath, bunnyDaemon.baseUrl);
|
|
4830
4834
|
if (requestUrl.origin !== new URL(bunnyDaemon.baseUrl).origin) throw new Error("Relay request must target the embedded bunny daemon.");
|
|
@@ -4912,9 +4916,25 @@ async function handleRelayMessage(socket, bunnyDaemon, raw, inflight, expectedCo
|
|
|
4912
4916
|
inflight.delete(message.requestId);
|
|
4913
4917
|
}
|
|
4914
4918
|
}
|
|
4915
|
-
|
|
4919
|
+
/** One owner per Relay, retained across socket reconnects and released on stop. */
|
|
4920
|
+
var WorkspaceDaemonHandlerStore = class {
|
|
4921
|
+
handlers = /* @__PURE__ */ new Map();
|
|
4922
|
+
get(mountRoot) {
|
|
4923
|
+
const root = path.resolve(mountRoot);
|
|
4924
|
+
let handler = this.handlers.get(root);
|
|
4925
|
+
if (!handler) {
|
|
4926
|
+
handler = createNextHandler({ root });
|
|
4927
|
+
this.handlers.set(root, handler);
|
|
4928
|
+
}
|
|
4929
|
+
return handler;
|
|
4930
|
+
}
|
|
4931
|
+
clear() {
|
|
4932
|
+
this.handlers.clear();
|
|
4933
|
+
}
|
|
4934
|
+
};
|
|
4935
|
+
const handleWorkspaceDaemonRequest = async (request, mounts, signal, handlers) => {
|
|
4916
4936
|
const normalized = normalizeWorkspaceRequest(request, mounts);
|
|
4917
|
-
const handler = createNextHandler({ root: mounts.mountRoot });
|
|
4937
|
+
const handler = handlers?.get(mounts.mountRoot) ?? createNextHandler({ root: mounts.mountRoot });
|
|
4918
4938
|
if (getHeaderValue(normalized.headers, "x-buda-relay-body-encoding") === "base64") {
|
|
4919
4939
|
if (new URL(normalized.path, "http://connector.workspace").pathname !== "/api/fs/write-stream") throw new Error("Base64 relay bodies are only supported for filesystem write streams.");
|
|
4920
4940
|
if (typeof normalized.body !== "string") throw new Error("Invalid base64 filesystem write body.");
|
|
@@ -5059,7 +5079,7 @@ async function ensureSymlink(target, linkPath) {
|
|
|
5059
5079
|
const REGISTRY_VERSION = 1;
|
|
5060
5080
|
const REGISTRY_DIRECTORY = ".buda";
|
|
5061
5081
|
const REGISTRY_FILENAME = "workspace-registry.json";
|
|
5062
|
-
const IMMUTABLE_ID_PATTERN = /^[A-Za-z0-
|
|
5082
|
+
const IMMUTABLE_ID_PATTERN = /^[A-Za-z0-9_-]{1,128}$/;
|
|
5063
5083
|
const UNSAFE_FILESYSTEM_TYPES = /* @__PURE__ */ new Set([
|
|
5064
5084
|
26985,
|
|
5065
5085
|
20859,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@buda-ai/connector",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.36",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"publishConfig": {
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
"lint:err": "biome format . --write && biome check . --write --diagnostic-level=error"
|
|
28
28
|
},
|
|
29
29
|
"dependencies": {
|
|
30
|
-
"@bunny-agent/daemon": "0.
|
|
30
|
+
"@bunny-agent/daemon": "0.10.2",
|
|
31
31
|
"@clack/prompts": "^1.0.0",
|
|
32
32
|
"playwright-core": "^1.52.0",
|
|
33
33
|
"ws": "^8.21.0"
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"node-pty": "^1.1.0"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@types/node": "^
|
|
39
|
+
"@types/node": "^26.3.0",
|
|
40
40
|
"@types/ws": "^8.18.1",
|
|
41
41
|
"relaylib": "workspace:*",
|
|
42
42
|
"tsdown": "^0.22.14",
|