@drakon-systems/ekho-sdk 0.2.1

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.
@@ -0,0 +1,36 @@
1
+ import type { AgentCredentials, InboxMessage, ControlMessage, SendMessagePayload, ProposeActionPayload, ActionResultPayload } from "./types";
2
+ export type AdapterHooks = {
3
+ onMessage?: (message: InboxMessage, adapter: EkhoAgentAdapter) => Promise<void>;
4
+ beforeAction?: (action: ProposeActionPayload, adapter: EkhoAgentAdapter) => Promise<void>;
5
+ onControl?: (control: ControlMessage, adapter: EkhoAgentAdapter) => Promise<void>;
6
+ onApprovalPending?: (approvalId: string, adapter: EkhoAgentAdapter) => Promise<void>;
7
+ };
8
+ export declare class EkhoAgentAdapter {
9
+ private readonly client;
10
+ private readonly hooks;
11
+ private running;
12
+ private paused;
13
+ private activeConversationIds;
14
+ constructor(credentials: AgentCredentials, hooks?: AdapterHooks);
15
+ get agentId(): string;
16
+ start(): Promise<void>;
17
+ stop(): void;
18
+ send(payload: SendMessagePayload): Promise<{
19
+ message_id: string;
20
+ status: string;
21
+ queued_at: string;
22
+ }>;
23
+ proposeAction(action: ProposeActionPayload): Promise<{
24
+ decision: "allow";
25
+ } | {
26
+ decision: "pending_approval";
27
+ approval_id: string;
28
+ }>;
29
+ reportActionResult(payload: ActionResultPayload): Promise<{
30
+ ok: boolean;
31
+ }>;
32
+ private heartbeatLoop;
33
+ private inboxLoop;
34
+ private handleControl;
35
+ }
36
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,YAAY,GAAG;IACzB,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAChF,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,oBAAoB,EAAE,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1F,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAClF,iBAAiB,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,EAAE,gBAAgB,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtF,CAAC;AAMF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,qBAAqB,CAAqB;gBAEtC,WAAW,EAAE,gBAAgB,EAAE,KAAK,GAAE,YAAiB;IAKnE,IAAI,OAAO,WAAkC;IAEvC,KAAK;IAOX,IAAI;IAEE,IAAI,CAAC,OAAO,EAAE,kBAAkB;;;;;IAIhC,aAAa,CAAC,MAAM,EAAE,oBAAoB;;;;;;IAqB1C,kBAAkB,CAAC,OAAO,EAAE,mBAAmB;;;YAIvC,aAAa;YAeb,SAAS;YAmBT,aAAa;CAK5B"}
@@ -0,0 +1,102 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EkhoAgentAdapter = void 0;
4
+ const client_1 = require("./client");
5
+ function sleep(ms) {
6
+ return new Promise((resolve) => setTimeout(resolve, ms));
7
+ }
8
+ class EkhoAgentAdapter {
9
+ client;
10
+ hooks;
11
+ running = false;
12
+ paused = false;
13
+ activeConversationIds = new Set();
14
+ constructor(credentials, hooks = {}) {
15
+ this.client = new client_1.EkhoAgentClient(credentials);
16
+ this.hooks = hooks;
17
+ }
18
+ get agentId() { return this.client.agentId; }
19
+ async start() {
20
+ if (this.running)
21
+ return;
22
+ this.running = true;
23
+ void this.heartbeatLoop();
24
+ void this.inboxLoop();
25
+ }
26
+ stop() { this.running = false; }
27
+ async send(payload) {
28
+ return this.client.sendMessage(payload);
29
+ }
30
+ async proposeAction(action) {
31
+ if (this.hooks.beforeAction)
32
+ await this.hooks.beforeAction(action, this);
33
+ if (this.paused)
34
+ throw new Error("agent is paused by control plane");
35
+ const decision = await this.client.proposeAction(action);
36
+ if (decision.decision === "allow")
37
+ return decision;
38
+ if (decision.decision === "deny")
39
+ throw new Error("action denied by Ekho policy");
40
+ if (this.hooks.onApprovalPending)
41
+ await this.hooks.onApprovalPending(decision.approval_id, this);
42
+ while (this.running) {
43
+ const approval = await this.client.getApproval(decision.approval_id);
44
+ if (approval.status === "approved" || approval.status === "executed")
45
+ return decision;
46
+ if (approval.status === "rejected" || approval.status === "cancelled" || approval.status === "expired") {
47
+ throw new Error(`action ${approval.status} by operator`);
48
+ }
49
+ await sleep(1500);
50
+ }
51
+ throw new Error("adapter stopped while waiting for approval");
52
+ }
53
+ async reportActionResult(payload) {
54
+ return this.client.actionResult(payload);
55
+ }
56
+ async heartbeatLoop() {
57
+ while (this.running) {
58
+ try {
59
+ await this.client.heartbeat({
60
+ status: this.paused ? "degraded" : "healthy",
61
+ active_conversation_ids: [...this.activeConversationIds],
62
+ metrics: { paused: this.paused }
63
+ });
64
+ }
65
+ catch (error) {
66
+ console.error("[ekho-adapter] heartbeat failed", error);
67
+ }
68
+ await sleep(this.client.heartbeatIntervalSeconds * 1000);
69
+ }
70
+ }
71
+ async inboxLoop() {
72
+ while (this.running) {
73
+ try {
74
+ const inbox = await this.client.getInbox();
75
+ for (const control of inbox.controls)
76
+ await this.handleControl(control);
77
+ for (const raw of inbox.messages) {
78
+ this.activeConversationIds.add(raw.conversation_id);
79
+ if (this.hooks.onMessage)
80
+ await this.hooks.onMessage(raw, this);
81
+ await this.client.ackMessages([
82
+ { message_id: raw.message_id, status: "received", received_at: new Date().toISOString() }
83
+ ]);
84
+ }
85
+ }
86
+ catch (error) {
87
+ console.error("[ekho-adapter] inbox loop failed", error);
88
+ }
89
+ await sleep(this.client.pollIntervalSeconds * 1000);
90
+ }
91
+ }
92
+ async handleControl(control) {
93
+ if (control.action === "pause" || control.action === "quarantine")
94
+ this.paused = true;
95
+ if (control.action === "resume")
96
+ this.paused = false;
97
+ if (this.hooks.onControl)
98
+ await this.hooks.onControl(control, this);
99
+ }
100
+ }
101
+ exports.EkhoAgentAdapter = EkhoAgentAdapter;
102
+ //# sourceMappingURL=adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.js","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,44 @@
1
+ import type { AgentCredentials, ActionDecision, SendMessagePayload, HeartbeatPayload, ProposeActionPayload, ActionResultPayload } from "./types";
2
+ export declare class EkhoAgentClient {
3
+ private readonly credentials;
4
+ constructor(credentials: AgentCredentials);
5
+ private signedHeaders;
6
+ private request;
7
+ get agentId(): string;
8
+ get pollIntervalSeconds(): number;
9
+ get heartbeatIntervalSeconds(): number;
10
+ sendMessage(payload: SendMessagePayload): Promise<{
11
+ message_id: string;
12
+ status: string;
13
+ queued_at: string;
14
+ }>;
15
+ getInbox(limit?: number): Promise<{
16
+ messages: Array<Record<string, unknown>>;
17
+ controls: Array<Record<string, unknown>>;
18
+ }>;
19
+ ackMessages(acks: Array<{
20
+ message_id: string;
21
+ status: "received";
22
+ received_at: string;
23
+ }>): Promise<{
24
+ updated: number;
25
+ }>;
26
+ heartbeat(payload: HeartbeatPayload): Promise<{
27
+ ok: boolean;
28
+ next_heartbeat_due_seconds: number;
29
+ }>;
30
+ proposeAction(payload: ProposeActionPayload): Promise<ActionDecision>;
31
+ getApproval(approvalId: string): Promise<{
32
+ id: string;
33
+ status: string;
34
+ action_type: string;
35
+ risk_level: string;
36
+ summary: string;
37
+ requested_at: string;
38
+ resolved_at: string | null;
39
+ }>;
40
+ actionResult(payload: ActionResultPayload): Promise<{
41
+ ok: boolean;
42
+ }>;
43
+ }
44
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC;AASjB,qBAAa,eAAe;IACd,OAAO,CAAC,QAAQ,CAAC,WAAW;gBAAX,WAAW,EAAE,gBAAgB;IAE1D,OAAO,CAAC,aAAa;YAeP,OAAO;IAiBrB,IAAI,OAAO,WAAuC;IAClD,IAAI,mBAAmB,WAA4E;IACnG,IAAI,wBAAwB,WAAsF;IAElH,WAAW,CAAC,OAAO,EAAE,kBAAkB;oBACH,MAAM;gBAAU,MAAM;mBAAa,MAAM;;IAG7E,QAAQ,CAAC,KAAK,SAAK;kBACe,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;kBAAY,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;;IAG1G,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC;QAAE,UAAU,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,UAAU,CAAC;QAAC,WAAW,EAAE,MAAM,CAAA;KAAE,CAAC;iBACvD,MAAM;;IAGvC,SAAS,CAAC,OAAO,EAAE,gBAAgB;YACP,OAAO;oCAA8B,MAAM;;IAGvE,aAAa,CAAC,OAAO,EAAE,oBAAoB;IAI3C,WAAW,CAAC,UAAU,EAAE,MAAM;YAEtB,MAAM;gBAAU,MAAM;qBAAe,MAAM;oBAAc,MAAM;iBAC1D,MAAM;sBAAgB,MAAM;qBAAe,MAAM,GAAG,IAAI;;IAIrE,YAAY,CAAC,OAAO,EAAE,mBAAmB;YACb,OAAO;;CAEpC"}
package/dist/client.js ADDED
@@ -0,0 +1,72 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EkhoAgentClient = void 0;
7
+ const node_crypto_1 = __importDefault(require("node:crypto"));
8
+ const DEFAULT_POLL_INTERVAL = 5;
9
+ const DEFAULT_HEARTBEAT_INTERVAL = 30;
10
+ function sha256(input) {
11
+ return node_crypto_1.default.createHash("sha256").update(input).digest("hex");
12
+ }
13
+ class EkhoAgentClient {
14
+ credentials;
15
+ constructor(credentials) {
16
+ this.credentials = credentials;
17
+ }
18
+ signedHeaders(method, signaturePath, body) {
19
+ const timestamp = new Date().toISOString();
20
+ const nonce = node_crypto_1.default.randomUUID();
21
+ const payload = `${method}\n${signaturePath}\n${timestamp}\n${nonce}\n${sha256(body)}`;
22
+ const signature = node_crypto_1.default.createHmac("sha256", this.credentials.secret).update(payload).digest("hex");
23
+ return {
24
+ "content-type": "application/json",
25
+ "x-ekho-agent-id": this.credentials.agentId,
26
+ "x-ekho-agent-secret": this.credentials.secret,
27
+ "x-ekho-timestamp": timestamp,
28
+ "x-ekho-nonce": nonce,
29
+ "x-ekho-signature": signature
30
+ };
31
+ }
32
+ async request(method, routePath, payload) {
33
+ const body = payload ? JSON.stringify(payload) : "";
34
+ const signaturePath = routePath.split("?")[0] ?? routePath;
35
+ const response = await fetch(`${this.credentials.relayBaseUrl}${routePath}`, {
36
+ method,
37
+ headers: this.signedHeaders(method, signaturePath, body),
38
+ body: method === "GET" ? undefined : body
39
+ });
40
+ if (!response.ok) {
41
+ const text = await response.text();
42
+ throw new Error(`Ekho request failed for ${routePath}: ${response.status} ${text}`);
43
+ }
44
+ return response.json();
45
+ }
46
+ get agentId() { return this.credentials.agentId; }
47
+ get pollIntervalSeconds() { return this.credentials.pollIntervalSeconds ?? DEFAULT_POLL_INTERVAL; }
48
+ get heartbeatIntervalSeconds() { return this.credentials.heartbeatIntervalSeconds ?? DEFAULT_HEARTBEAT_INTERVAL; }
49
+ sendMessage(payload) {
50
+ return this.request("POST", "/v1/messages", payload);
51
+ }
52
+ getInbox(limit = 25) {
53
+ return this.request("GET", `/v1/inbox?limit=${limit}`);
54
+ }
55
+ ackMessages(acks) {
56
+ return this.request("POST", "/v1/acks", { acks });
57
+ }
58
+ heartbeat(payload) {
59
+ return this.request("POST", "/v1/heartbeats", payload);
60
+ }
61
+ proposeAction(payload) {
62
+ return this.request("POST", "/v1/actions/propose", payload);
63
+ }
64
+ getApproval(approvalId) {
65
+ return this.request("GET", `/v1/actions/${approvalId}`);
66
+ }
67
+ actionResult(payload) {
68
+ return this.request("POST", "/v1/actions/result", payload);
69
+ }
70
+ }
71
+ exports.EkhoAgentClient = EkhoAgentClient;
72
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export { EkhoAgentClient } from "./client";
2
+ export { EkhoAgentAdapter } from "./adapter";
3
+ export type { AdapterHooks } from "./adapter";
4
+ export type { AgentCredentials, ActionDecision, InboxMessage, ControlMessage, SendMessagePayload, HeartbeatPayload, ProposeActionPayload, ActionResultPayload } from "./types";
5
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,YAAY,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,YAAY,EACV,gBAAgB,EAChB,cAAc,EACd,YAAY,EACZ,cAAc,EACd,kBAAkB,EAClB,gBAAgB,EAChB,oBAAoB,EACpB,mBAAmB,EACpB,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.EkhoAgentAdapter = exports.EkhoAgentClient = void 0;
4
+ var client_1 = require("./client");
5
+ Object.defineProperty(exports, "EkhoAgentClient", { enumerable: true, get: function () { return client_1.EkhoAgentClient; } });
6
+ var adapter_1 = require("./adapter");
7
+ Object.defineProperty(exports, "EkhoAgentAdapter", { enumerable: true, get: function () { return adapter_1.EkhoAgentAdapter; } });
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAAA,mCAA2C;AAAlC,yGAAA,eAAe,OAAA;AACxB,qCAA6C;AAApC,2GAAA,gBAAgB,OAAA"}
@@ -0,0 +1,65 @@
1
+ export type AgentCredentials = {
2
+ agentId: string;
3
+ secret: string;
4
+ relayBaseUrl: string;
5
+ heartbeatIntervalSeconds?: number;
6
+ pollIntervalSeconds?: number;
7
+ };
8
+ export type ActionDecision = {
9
+ decision: "allow";
10
+ } | {
11
+ decision: "deny";
12
+ } | {
13
+ decision: "pending_approval";
14
+ approval_id: string;
15
+ };
16
+ export type InboxMessage = {
17
+ message_id: string;
18
+ conversation_id: string;
19
+ correlation_id: string;
20
+ sender_agent_id: string;
21
+ message_type: string;
22
+ priority: string;
23
+ body: Record<string, unknown>;
24
+ metadata: Record<string, unknown>;
25
+ created_at: string;
26
+ deadline_at: string;
27
+ };
28
+ export type ControlMessage = {
29
+ control_id: string;
30
+ action: string;
31
+ reason: string;
32
+ };
33
+ export type SendMessagePayload = {
34
+ recipient: {
35
+ kind: "agent" | "group" | "broadcast";
36
+ id?: string;
37
+ };
38
+ message_type: "direct" | "broadcast" | "alert" | "handoff" | "claim" | "complete" | "heartbeat" | "control";
39
+ priority?: "low" | "normal" | "high" | "urgent";
40
+ ttl_seconds?: number;
41
+ requires_approval?: boolean;
42
+ body: Record<string, unknown>;
43
+ metadata?: Record<string, unknown>;
44
+ conversation_id: string;
45
+ correlation_id: string;
46
+ };
47
+ export type HeartbeatPayload = {
48
+ status: "healthy" | "degraded" | "busy" | "idle";
49
+ active_conversation_ids?: string[];
50
+ metrics?: Record<string, unknown>;
51
+ };
52
+ export type ProposeActionPayload = {
53
+ conversation_id: string;
54
+ action_type: string;
55
+ summary: string;
56
+ risk_level: "low" | "medium" | "high" | "critical";
57
+ payload: Record<string, unknown>;
58
+ };
59
+ export type ActionResultPayload = {
60
+ approval_id: string;
61
+ result: "executed" | "cancelled" | "failed";
62
+ completed_at: string;
63
+ output?: Record<string, unknown>;
64
+ };
65
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,gBAAgB,GAAG;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,wBAAwB,CAAC,EAAE,MAAM,CAAC;IAClC,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,cAAc,GACtB;IAAE,QAAQ,EAAE,OAAO,CAAA;CAAE,GACrB;IAAE,QAAQ,EAAE,MAAM,CAAA;CAAE,GACpB;IAAE,QAAQ,EAAE,kBAAkB,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,MAAM,MAAM,YAAY,GAAG;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;IACvB,eAAe,EAAE,MAAM,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAClC,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAC3B,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE;QAAE,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,WAAW,CAAC;QAAC,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAClE,YAAY,EAAE,QAAQ,GAAG,WAAW,GAAG,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,WAAW,GAAG,SAAS,CAAC;IAC5G,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC;IAChD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,eAAe,EAAE,MAAM,CAAC;IACxB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,MAAM,MAAM,gBAAgB,GAAG;IAC7B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,MAAM,GAAG,MAAM,CAAC;IACjD,uBAAuB,CAAC,EAAE,MAAM,EAAE,CAAC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACnC,CAAC;AAEF,MAAM,MAAM,oBAAoB,GAAG;IACjC,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,UAAU,CAAC;IACnD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC;AAEF,MAAM,MAAM,mBAAmB,GAAG;IAChC,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,WAAW,GAAG,QAAQ,CAAC;IAC5C,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAClC,CAAC"}
package/dist/types.js ADDED
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,39 @@
1
+ {
2
+ "name": "@drakon-systems/ekho-sdk",
3
+ "version": "0.2.1",
4
+ "description": "Agent SDK for Ekho — the private communication layer for distributed AI agents.",
5
+ "license": "MIT",
6
+ "author": "Drakon Systems <hello@drakonsystems.com> (https://drakonsystems.com)",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/Drakon-Systems-Ltd/ekho.git",
10
+ "directory": "packages/sdk"
11
+ },
12
+ "homepage": "https://drakonsystems.com/products/ekho",
13
+ "keywords": [
14
+ "ai",
15
+ "agents",
16
+ "messaging",
17
+ "relay",
18
+ "sdk",
19
+ "ekho",
20
+ "tailscale"
21
+ ],
22
+ "main": "dist/index.js",
23
+ "types": "dist/index.d.ts",
24
+ "files": [
25
+ "dist"
26
+ ],
27
+ "scripts": {
28
+ "build": "tsc",
29
+ "typecheck": "tsc --noEmit",
30
+ "test": "vitest run",
31
+ "prepublishOnly": "npm run build"
32
+ },
33
+ "publishConfig": {
34
+ "access": "public"
35
+ },
36
+ "devDependencies": {
37
+ "@types/node": "^25.5.0"
38
+ }
39
+ }