@dana4/sdk 0.1.0 → 0.5.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 +5 -3
- package/dist/agent.d.ts +40 -4
- package/dist/agent.js +82 -18
- package/dist/ai.d.ts +4 -4
- package/dist/ai.js +170 -37
- package/dist/cli.js +11 -2
- package/dist/client.d.ts +54 -0
- package/dist/client.js +38 -10
- package/dist/cloudflare.js +10 -3
- package/dist/enroll.js +13 -4
- package/dist/run.js +7 -2
- package/dist/schema.d.ts +3733 -3503
- package/package.json +14 -3
package/dist/client.js
CHANGED
|
@@ -57,9 +57,13 @@ export class Dana4Client {
|
|
|
57
57
|
active: () => this.request("GET", "/tasks/active"),
|
|
58
58
|
assigned: () => this.request("GET", "/tasks/assigned"),
|
|
59
59
|
unassigned: () => this.request("GET", "/tasks/unassigned"),
|
|
60
|
-
claim: (taskId, capability) => this.request("POST", `/tasks/${taskId}/claim`, {
|
|
60
|
+
claim: (taskId, capability) => this.request("POST", `/tasks/${taskId}/claim`, {
|
|
61
|
+
body: { capability },
|
|
62
|
+
}),
|
|
61
63
|
/** Start a one-step journey (e.g. `read_message`); answers its task id. */
|
|
62
|
-
start: (body) => this.request("POST", "/tasks", {
|
|
64
|
+
start: (body) => this.request("POST", "/tasks", {
|
|
65
|
+
body: { params: null, ...body },
|
|
66
|
+
}),
|
|
63
67
|
update: (taskId, body) => this.request("PATCH", `/tasks/${taskId}`, { body }),
|
|
64
68
|
/** Workspace params merged with the journey's params. */
|
|
65
69
|
params: (taskId) => this.request("GET", `/tasks/${taskId}/params`),
|
|
@@ -73,23 +77,40 @@ export class Dana4Client {
|
|
|
73
77
|
source: (documentId) => this.request("GET", `/documents/${documentId}/source`),
|
|
74
78
|
search: (workspaceId, q, limit) => this.request("GET", `/workspaces/${workspaceId}/documents/search`, { query: { q, limit } }),
|
|
75
79
|
/** Every thread on a document; the root discussion has no `parent_channel_id`. */
|
|
76
|
-
messages: (documentId, range = {}) => this.request("GET", `/documents/${documentId}/messages`, {
|
|
80
|
+
messages: (documentId, range = {}) => this.request("GET", `/documents/${documentId}/messages`, {
|
|
81
|
+
query: range,
|
|
82
|
+
}),
|
|
77
83
|
create: (body) => this.request("POST", "/documents", { body }),
|
|
78
84
|
replace: (body) => this.request("POST", "/documents/replace", { body }),
|
|
79
85
|
append: (body) => this.request("POST", "/documents/append", { body }),
|
|
80
|
-
edit: (body) => this.request("POST", "/documents/edit", {
|
|
81
|
-
|
|
86
|
+
edit: (body) => this.request("POST", "/documents/edit", {
|
|
87
|
+
body,
|
|
88
|
+
}),
|
|
89
|
+
presence: (documentId, activity) => this.request("PUT", `/documents/${documentId}/presence`, {
|
|
90
|
+
body: { activity },
|
|
91
|
+
}),
|
|
82
92
|
};
|
|
83
93
|
chat = {
|
|
84
94
|
/** The next channel with unread messages for this agent. Marks them read:
|
|
85
95
|
* delivery is at-most-once. `channel_id` is "" when there is nothing. */
|
|
86
96
|
take: () => this.request("POST", "/chats/take"),
|
|
87
|
-
messages: (channelId, range = {}) => this.request("GET", `/channels/${channelId}/messages`, {
|
|
97
|
+
messages: (channelId, range = {}) => this.request("GET", `/channels/${channelId}/messages`, {
|
|
98
|
+
query: range,
|
|
99
|
+
}),
|
|
88
100
|
send: (body) => this.request("POST", "/messages", { body }),
|
|
89
101
|
privateChannels: (workspaceId) => this.request("GET", `/workspaces/${workspaceId}/private-channels`),
|
|
90
|
-
setPlan: (channelId, plan) => this.request("PUT", `/channels/${channelId}/plan`, {
|
|
91
|
-
|
|
92
|
-
|
|
102
|
+
setPlan: (channelId, plan) => this.request("PUT", `/channels/${channelId}/plan`, {
|
|
103
|
+
body: { plan },
|
|
104
|
+
}),
|
|
105
|
+
setMemory: (channelId, memory) => this.request("PUT", `/channels/${channelId}/memory`, {
|
|
106
|
+
body: { memory },
|
|
107
|
+
}),
|
|
108
|
+
completePlanItem: (channelId, item) => this.request("POST", `/channels/${channelId}/plan/complete`, {
|
|
109
|
+
body: { item },
|
|
110
|
+
}),
|
|
111
|
+
addPlanItem: (channelId, item) => this.request("POST", `/channels/${channelId}/plan/items`, {
|
|
112
|
+
body: { item },
|
|
113
|
+
}),
|
|
93
114
|
};
|
|
94
115
|
workspaces = {
|
|
95
116
|
list: () => this.request("GET", "/workspaces"),
|
|
@@ -104,6 +125,11 @@ export class Dana4Client {
|
|
|
104
125
|
create: (body) => this.request("POST", "/automations", { body }),
|
|
105
126
|
delete: (automationId) => this.request("DELETE", `/automations/${automationId}`),
|
|
106
127
|
};
|
|
128
|
+
tickets = {
|
|
129
|
+
/** Put a ticket on the workspace's board. Tickets are referred to by their
|
|
130
|
+
* per-workspace number (`blocked_by: [12]` means #12). */
|
|
131
|
+
create: (body) => this.request("POST", "/tickets", { body }),
|
|
132
|
+
};
|
|
107
133
|
workflows = {
|
|
108
134
|
create: (body) => this.request("POST", "/workflows", { body }),
|
|
109
135
|
};
|
|
@@ -117,7 +143,9 @@ export class Dana4Client {
|
|
|
117
143
|
const put = await this.#fetch(url, { method: "PUT", body: data });
|
|
118
144
|
if (!put.ok)
|
|
119
145
|
throw new Dana4Error(put.status, await put.text(), "asset upload");
|
|
120
|
-
const assetId = await this.request("POST", "/assets", {
|
|
146
|
+
const assetId = await this.request("POST", "/assets", {
|
|
147
|
+
body: { task_id: taskId, key },
|
|
148
|
+
});
|
|
121
149
|
return { key, assetId, url: `dana4-asset://${key}` };
|
|
122
150
|
},
|
|
123
151
|
};
|
package/dist/cloudflare.js
CHANGED
|
@@ -21,17 +21,24 @@ export class Dana4Agent extends Agent {
|
|
|
21
21
|
pollInterval = 5;
|
|
22
22
|
#runtime;
|
|
23
23
|
get runtime() {
|
|
24
|
-
this.#runtime ??= new AgentRuntime(this.agent, new Dana4Client({
|
|
24
|
+
this.#runtime ??= new AgentRuntime(this.agent, new Dana4Client({
|
|
25
|
+
apiKey: this.env.DANA4_API_KEY,
|
|
26
|
+
url: this.env.DANA4_URL,
|
|
27
|
+
}));
|
|
25
28
|
return this.#runtime;
|
|
26
29
|
}
|
|
27
30
|
async onStart() {
|
|
28
31
|
// Idempotent: one schedule however often the object wakes.
|
|
29
32
|
await this.scheduleEvery(this.pollInterval, "poll");
|
|
30
|
-
await this.runtime
|
|
33
|
+
await this.runtime
|
|
34
|
+
.register()
|
|
35
|
+
.catch((e) => console.error("dana4: register failed:", e));
|
|
31
36
|
// A fresh instance runs no tasks yet, so any still active were stranded by
|
|
32
37
|
// an eviction, e.g. between `tasks/take` and their fiber's first stash.
|
|
33
38
|
// Fibers recovered just before this already re-queued theirs (idempotent).
|
|
34
|
-
await this.runtime
|
|
39
|
+
await this.runtime
|
|
40
|
+
.requeueActive()
|
|
41
|
+
.catch((e) => console.error("dana4: re-queuing failed:", e));
|
|
35
42
|
}
|
|
36
43
|
/** One round: take work, run each item in its own fiber. Overlapping rounds
|
|
37
44
|
* are skipped by the scheduler, and fibers aren't awaited, so a long task
|
package/dist/enroll.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { Dana4Error, DEFAULT_URL } from "./client.js";
|
|
2
2
|
/** Get an API key for a new agent through the device flow. `onLink` gets the
|
|
3
3
|
* link (and code) for a person to open; once they sign in and approve, the
|
|
4
4
|
* agent exists, owned by them, in the workspaces they picked, and this answers
|
|
5
5
|
* its key. The key is shown once: store it (e.g. as `DANA4_API_KEY`). */
|
|
6
6
|
export async function enroll(opts) {
|
|
7
7
|
const base = `${(opts.url ?? DEFAULT_URL).replace(/\/+$/, "")}/api-sdk/v1/agents/enroll`;
|
|
8
|
-
const post = (path, body) => fetch(base + path, {
|
|
9
|
-
|
|
8
|
+
const post = (path, body) => fetch(base + path, {
|
|
9
|
+
method: "POST",
|
|
10
|
+
headers: { "Content-Type": "application/json" },
|
|
11
|
+
body: JSON.stringify(body),
|
|
12
|
+
});
|
|
13
|
+
const r = await post("", {
|
|
14
|
+
username: opts.username,
|
|
15
|
+
bio: opts.bio,
|
|
16
|
+
description: opts.description,
|
|
17
|
+
});
|
|
10
18
|
if (!r.ok)
|
|
11
19
|
throw new Dana4Error(r.status, await r.text(), "enroll");
|
|
12
20
|
const start = (await r.json());
|
|
13
|
-
(opts.onLink ??
|
|
21
|
+
(opts.onLink ??
|
|
22
|
+
((link, code) => console.log(`To connect @${opts.username}, open\n\n ${link}\n\nand check the code ${code}. Waiting for approval...`)))(start.verification_uri_complete, start.user_code);
|
|
14
23
|
const deadline = Date.now() + start.expires_in * 1000;
|
|
15
24
|
while (Date.now() < deadline) {
|
|
16
25
|
await new Promise((resolve) => setTimeout(resolve, start.interval * 1000));
|
package/dist/run.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AgentRuntime } from "./agent.js";
|
|
2
2
|
import { Dana4Client } from "./client.js";
|
|
3
|
-
const env = (name) => globalThis
|
|
3
|
+
const env = (name) => globalThis
|
|
4
|
+
.process?.env[name];
|
|
4
5
|
/** Run an agent as a long-lived process (Node, Bun, Deno): register, re-queue
|
|
5
6
|
* tasks a previous crash left open, then poll every `interval` seconds until
|
|
6
7
|
* `signal` aborts. Work runs concurrently, so a long task never delays chat.
|
|
@@ -8,7 +9,11 @@ const env = (name) => globalThis.process?.env[name];
|
|
|
8
9
|
* `apiKey` and `url` default to `DANA4_API_KEY` and `DANA4_URL`. */
|
|
9
10
|
export async function run(agent, opts = {}) {
|
|
10
11
|
const { interval = 5, signal, log = console, ...client } = opts;
|
|
11
|
-
const rt = new AgentRuntime(agent, new Dana4Client({
|
|
12
|
+
const rt = new AgentRuntime(agent, new Dana4Client({
|
|
13
|
+
apiKey: client.apiKey ?? env("DANA4_API_KEY") ?? "",
|
|
14
|
+
url: client.url ?? env("DANA4_URL"),
|
|
15
|
+
fetch: client.fetch,
|
|
16
|
+
}), log);
|
|
12
17
|
log.info(`dana4: connected as @${await rt.register()}`);
|
|
13
18
|
await rt.requeueActive();
|
|
14
19
|
while (!signal?.aborted) {
|