@agentmeshhq/agent 0.1.4 → 0.1.6
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/dist/__tests__/jwt.test.d.ts +1 -0
- package/dist/__tests__/jwt.test.js +83 -0
- package/dist/__tests__/jwt.test.js.map +1 -0
- package/dist/__tests__/loader.test.d.ts +1 -0
- package/dist/__tests__/loader.test.js +148 -0
- package/dist/__tests__/loader.test.js.map +1 -0
- package/dist/cli/index.js +37 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/token.d.ts +1 -0
- package/dist/cli/token.js +146 -0
- package/dist/cli/token.js.map +1 -0
- package/dist/cli/whoami.d.ts +1 -0
- package/dist/cli/whoami.js +98 -0
- package/dist/cli/whoami.js.map +1 -0
- package/dist/config/loader.d.ts +2 -1
- package/dist/config/loader.js +13 -1
- package/dist/config/loader.js.map +1 -1
- package/dist/core/daemon.js +50 -6
- package/dist/core/daemon.js.map +1 -1
- package/dist/core/heartbeat.d.ts +8 -0
- package/dist/core/heartbeat.js +50 -1
- package/dist/core/heartbeat.js.map +1 -1
- package/dist/core/tmux.d.ts +7 -1
- package/dist/core/tmux.js +31 -2
- package/dist/core/tmux.js.map +1 -1
- package/dist/utils/jwt.d.ts +36 -0
- package/dist/utils/jwt.js +70 -0
- package/dist/utils/jwt.js.map +1 -0
- package/package.json +6 -3
- package/src/__tests__/jwt.test.ts +112 -0
- package/src/__tests__/loader.test.ts +191 -0
- package/src/cli/index.ts +38 -5
- package/src/cli/token.ts +188 -0
- package/src/cli/whoami.ts +113 -0
- package/src/config/loader.ts +20 -7
- package/src/core/daemon.ts +64 -18
- package/src/core/heartbeat.ts +62 -1
- package/src/core/tmux.ts +46 -9
- package/src/utils/jwt.ts +87 -0
- package/vitest.config.ts +12 -0
package/dist/config/loader.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as fs from "node:fs";
|
|
2
2
|
import * as path from "node:path";
|
|
3
|
-
import { CONFIG_PATH,
|
|
3
|
+
import { CONFIG_PATH, DEFAULT_CONFIG, STATE_PATH, } from "./schema.js";
|
|
4
4
|
export function ensureConfigDir() {
|
|
5
5
|
const configDir = path.dirname(CONFIG_PATH);
|
|
6
6
|
if (!fs.existsSync(configDir)) {
|
|
@@ -55,6 +55,18 @@ export function getAgentState(name) {
|
|
|
55
55
|
const state = loadState();
|
|
56
56
|
return state.agents.find((a) => a.name === name);
|
|
57
57
|
}
|
|
58
|
+
export function updateAgentInState(name, updates) {
|
|
59
|
+
const state = loadState();
|
|
60
|
+
const agentIndex = state.agents.findIndex((a) => a.name === name);
|
|
61
|
+
if (agentIndex === -1) {
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
state.agents[agentIndex] = {
|
|
65
|
+
...state.agents[agentIndex],
|
|
66
|
+
...updates,
|
|
67
|
+
};
|
|
68
|
+
saveState(state);
|
|
69
|
+
}
|
|
58
70
|
export function createDefaultConfig(apiKey, workspace) {
|
|
59
71
|
return {
|
|
60
72
|
...DEFAULT_CONFIG,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,SAAS,CAAC;AAC9B,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAClC,OAAO,
|
|
1
|
+
{"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/config/loader.ts"],"names":[],"mappings":"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"}
|
package/dist/core/daemon.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AgentWebSocket } from "./websocket.js";
|
|
1
|
+
import { addAgentToState, getAgentState, loadConfig, removeAgentFromState, updateAgentInState, } from "../config/loader.js";
|
|
3
2
|
import { Heartbeat } from "./heartbeat.js";
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
3
|
+
import { handleWebSocketEvent, injectStartupMessage } from "./injector.js";
|
|
4
|
+
import { checkInbox, registerAgent } from "./registry.js";
|
|
5
|
+
import { createSession, destroySession, getSessionName, sessionExists, updateSessionEnvironment, } from "./tmux.js";
|
|
6
|
+
import { AgentWebSocket } from "./websocket.js";
|
|
7
7
|
export class AgentDaemon {
|
|
8
8
|
agentName;
|
|
9
9
|
config;
|
|
@@ -73,6 +73,12 @@ export class AgentDaemon {
|
|
|
73
73
|
this.agentId = registration.agentId;
|
|
74
74
|
this.token = registration.token;
|
|
75
75
|
console.log(`Registered as: ${this.agentId}`);
|
|
76
|
+
// Inject environment variables into tmux session
|
|
77
|
+
console.log("Injecting environment variables...");
|
|
78
|
+
updateSessionEnvironment(this.agentName, {
|
|
79
|
+
AGENT_TOKEN: this.token,
|
|
80
|
+
AGENTMESH_AGENT_ID: this.agentId,
|
|
81
|
+
});
|
|
76
82
|
// Save state
|
|
77
83
|
addAgentToState({
|
|
78
84
|
name: this.agentName,
|
|
@@ -82,15 +88,53 @@ export class AgentDaemon {
|
|
|
82
88
|
startedAt: new Date().toISOString(),
|
|
83
89
|
token: this.token,
|
|
84
90
|
});
|
|
85
|
-
// Start heartbeat
|
|
91
|
+
// Start heartbeat with auto-refresh
|
|
86
92
|
console.log("Starting heartbeat...");
|
|
87
93
|
this.heartbeat = new Heartbeat({
|
|
88
94
|
url: this.config.hubUrl,
|
|
89
95
|
token: this.token,
|
|
90
96
|
intervalMs: 30000,
|
|
97
|
+
agentName: this.agentName,
|
|
98
|
+
agentId: this.agentId,
|
|
99
|
+
apiKey: this.config.apiKey,
|
|
100
|
+
workspace: this.config.workspace,
|
|
91
101
|
onError: (error) => {
|
|
92
102
|
console.error("Heartbeat error:", error.message);
|
|
93
103
|
},
|
|
104
|
+
onTokenRefresh: (newToken) => {
|
|
105
|
+
this.token = newToken;
|
|
106
|
+
// Update state file
|
|
107
|
+
updateAgentInState(this.agentName, { token: newToken });
|
|
108
|
+
// Update tmux environment
|
|
109
|
+
updateSessionEnvironment(this.agentName, {
|
|
110
|
+
AGENT_TOKEN: newToken,
|
|
111
|
+
AGENTMESH_AGENT_ID: this.agentId,
|
|
112
|
+
});
|
|
113
|
+
// Reconnect WebSocket with new token
|
|
114
|
+
if (this.ws) {
|
|
115
|
+
this.ws.disconnect();
|
|
116
|
+
const wsUrl = this.config.hubUrl
|
|
117
|
+
.replace("https://", "wss://")
|
|
118
|
+
.replace("http://", "ws://");
|
|
119
|
+
this.ws = new AgentWebSocket({
|
|
120
|
+
url: `${wsUrl}/ws/v1`,
|
|
121
|
+
token: newToken,
|
|
122
|
+
onMessage: (event) => {
|
|
123
|
+
handleWebSocketEvent(this.agentName, event);
|
|
124
|
+
},
|
|
125
|
+
onConnect: () => {
|
|
126
|
+
console.log("WebSocket reconnected with new token");
|
|
127
|
+
},
|
|
128
|
+
onDisconnect: () => {
|
|
129
|
+
console.log("WebSocket disconnected");
|
|
130
|
+
},
|
|
131
|
+
onError: (error) => {
|
|
132
|
+
console.error("WebSocket error:", error.message);
|
|
133
|
+
},
|
|
134
|
+
});
|
|
135
|
+
this.ws.connect();
|
|
136
|
+
}
|
|
137
|
+
},
|
|
94
138
|
});
|
|
95
139
|
this.heartbeat.start();
|
|
96
140
|
// Connect WebSocket
|
package/dist/core/daemon.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/core/daemon.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"daemon.js","sourceRoot":"","sources":["../../src/core/daemon.ts"],"names":[],"mappings":"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"}
|
package/dist/core/heartbeat.d.ts
CHANGED
|
@@ -2,13 +2,21 @@ export interface HeartbeatConfig {
|
|
|
2
2
|
url: string;
|
|
3
3
|
token: string;
|
|
4
4
|
intervalMs: number;
|
|
5
|
+
agentName: string;
|
|
6
|
+
agentId: string;
|
|
7
|
+
apiKey: string;
|
|
8
|
+
workspace: string;
|
|
5
9
|
onError?: (error: Error) => void;
|
|
10
|
+
onTokenRefresh?: (newToken: string) => void;
|
|
6
11
|
}
|
|
7
12
|
export declare class Heartbeat {
|
|
8
13
|
private config;
|
|
14
|
+
private currentToken;
|
|
9
15
|
private intervalId;
|
|
10
16
|
constructor(config: HeartbeatConfig);
|
|
11
17
|
start(): void;
|
|
12
18
|
stop(): void;
|
|
19
|
+
getToken(): string;
|
|
13
20
|
private sendHeartbeat;
|
|
21
|
+
private refreshToken;
|
|
14
22
|
}
|
package/dist/core/heartbeat.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
import { getTokenTimeRemaining, isTokenExpiringSoon } from "../utils/jwt.js";
|
|
2
|
+
// Refresh token when less than 24 hours remain
|
|
3
|
+
const TOKEN_REFRESH_THRESHOLD_MS = 24 * 60 * 60 * 1000;
|
|
1
4
|
export class Heartbeat {
|
|
2
5
|
config;
|
|
6
|
+
currentToken;
|
|
3
7
|
intervalId = null;
|
|
4
8
|
constructor(config) {
|
|
5
9
|
this.config = config;
|
|
10
|
+
this.currentToken = config.token;
|
|
6
11
|
}
|
|
7
12
|
start() {
|
|
8
13
|
if (this.intervalId) {
|
|
@@ -21,17 +26,33 @@ export class Heartbeat {
|
|
|
21
26
|
this.intervalId = null;
|
|
22
27
|
}
|
|
23
28
|
}
|
|
29
|
+
getToken() {
|
|
30
|
+
return this.currentToken;
|
|
31
|
+
}
|
|
24
32
|
async sendHeartbeat() {
|
|
25
33
|
try {
|
|
34
|
+
// Check if token needs refresh before sending heartbeat
|
|
35
|
+
if (isTokenExpiringSoon(this.currentToken, TOKEN_REFRESH_THRESHOLD_MS)) {
|
|
36
|
+
const remaining = getTokenTimeRemaining(this.currentToken);
|
|
37
|
+
const hours = Math.floor(remaining / (1000 * 60 * 60));
|
|
38
|
+
console.log(`Token expiring in ${hours} hours, refreshing...`);
|
|
39
|
+
await this.refreshToken();
|
|
40
|
+
}
|
|
26
41
|
const response = await fetch(`${this.config.url}/api/v1/agents/heartbeat`, {
|
|
27
42
|
method: "POST",
|
|
28
43
|
headers: {
|
|
29
|
-
Authorization: `Bearer ${this.
|
|
44
|
+
Authorization: `Bearer ${this.currentToken}`,
|
|
30
45
|
"Content-Type": "application/json",
|
|
31
46
|
},
|
|
32
47
|
body: JSON.stringify({}),
|
|
33
48
|
});
|
|
34
49
|
if (!response.ok) {
|
|
50
|
+
// If unauthorized, try to refresh token
|
|
51
|
+
if (response.status === 401) {
|
|
52
|
+
console.log("Token rejected, attempting refresh...");
|
|
53
|
+
await this.refreshToken();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
35
56
|
throw new Error(`Heartbeat failed: ${response.status}`);
|
|
36
57
|
}
|
|
37
58
|
}
|
|
@@ -39,5 +60,33 @@ export class Heartbeat {
|
|
|
39
60
|
this.config.onError?.(error);
|
|
40
61
|
}
|
|
41
62
|
}
|
|
63
|
+
async refreshToken() {
|
|
64
|
+
try {
|
|
65
|
+
const response = await fetch(`${this.config.url}/api/v1/agents/register`, {
|
|
66
|
+
method: "POST",
|
|
67
|
+
headers: {
|
|
68
|
+
"Content-Type": "application/json",
|
|
69
|
+
"x-agentmesh-secret": this.config.apiKey,
|
|
70
|
+
},
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
agent_id: this.config.agentId,
|
|
73
|
+
workspace: this.config.workspace,
|
|
74
|
+
display_name: this.config.agentName,
|
|
75
|
+
model: "claude-sonnet-4",
|
|
76
|
+
}),
|
|
77
|
+
});
|
|
78
|
+
if (!response.ok) {
|
|
79
|
+
throw new Error(`Token refresh failed: ${response.status}`);
|
|
80
|
+
}
|
|
81
|
+
const data = (await response.json());
|
|
82
|
+
this.currentToken = data.token;
|
|
83
|
+
console.log("Token refreshed successfully");
|
|
84
|
+
this.config.onTokenRefresh?.(data.token);
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error("Failed to refresh token:", error.message);
|
|
88
|
+
this.config.onError?.(error);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
42
91
|
}
|
|
43
92
|
//# sourceMappingURL=heartbeat.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/core/heartbeat.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"heartbeat.js","sourceRoot":"","sources":["../../src/core/heartbeat.ts"],"names":[],"mappings":"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"}
|
package/dist/core/tmux.d.ts
CHANGED
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
export declare function getSessionName(agentName: string): string;
|
|
2
2
|
export declare function sessionExists(sessionName: string): boolean;
|
|
3
|
-
export
|
|
3
|
+
export interface SessionEnv {
|
|
4
|
+
AGENT_TOKEN?: string;
|
|
5
|
+
AGENTMESH_AGENT_ID?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function createSession(agentName: string, command: string, workdir?: string, env?: SessionEnv): boolean;
|
|
8
|
+
export declare function setSessionEnvironment(sessionName: string, env: SessionEnv): boolean;
|
|
9
|
+
export declare function updateSessionEnvironment(agentName: string, env: SessionEnv): boolean;
|
|
4
10
|
export declare function destroySession(agentName: string): boolean;
|
|
5
11
|
export declare function sendKeys(agentName: string, message: string): boolean;
|
|
6
12
|
export declare function attachSession(agentName: string): void;
|
package/dist/core/tmux.js
CHANGED
|
@@ -12,7 +12,7 @@ export function sessionExists(sessionName) {
|
|
|
12
12
|
return false;
|
|
13
13
|
}
|
|
14
14
|
}
|
|
15
|
-
export function createSession(agentName, command, workdir) {
|
|
15
|
+
export function createSession(agentName, command, workdir, env) {
|
|
16
16
|
const sessionName = getSessionName(agentName);
|
|
17
17
|
if (sessionExists(sessionName)) {
|
|
18
18
|
console.error(`Session ${sessionName} already exists`);
|
|
@@ -25,6 +25,10 @@ export function createSession(agentName, command, workdir) {
|
|
|
25
25
|
}
|
|
26
26
|
args.push(command);
|
|
27
27
|
execSync(`tmux ${args.join(" ")}`);
|
|
28
|
+
// Inject environment variables after session creation
|
|
29
|
+
if (env) {
|
|
30
|
+
setSessionEnvironment(sessionName, env);
|
|
31
|
+
}
|
|
28
32
|
return true;
|
|
29
33
|
}
|
|
30
34
|
catch (error) {
|
|
@@ -32,6 +36,29 @@ export function createSession(agentName, command, workdir) {
|
|
|
32
36
|
return false;
|
|
33
37
|
}
|
|
34
38
|
}
|
|
39
|
+
export function setSessionEnvironment(sessionName, env) {
|
|
40
|
+
try {
|
|
41
|
+
if (env.AGENT_TOKEN) {
|
|
42
|
+
execSync(`tmux set-environment -t "${sessionName}" AGENT_TOKEN "${env.AGENT_TOKEN}"`);
|
|
43
|
+
}
|
|
44
|
+
if (env.AGENTMESH_AGENT_ID) {
|
|
45
|
+
execSync(`tmux set-environment -t "${sessionName}" AGENTMESH_AGENT_ID "${env.AGENTMESH_AGENT_ID}"`);
|
|
46
|
+
}
|
|
47
|
+
return true;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error(`Failed to set session environment: ${error}`);
|
|
51
|
+
return false;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
export function updateSessionEnvironment(agentName, env) {
|
|
55
|
+
const sessionName = getSessionName(agentName);
|
|
56
|
+
if (!sessionExists(sessionName)) {
|
|
57
|
+
console.error(`Session ${sessionName} does not exist`);
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
return setSessionEnvironment(sessionName, env);
|
|
61
|
+
}
|
|
35
62
|
export function destroySession(agentName) {
|
|
36
63
|
const sessionName = getSessionName(agentName);
|
|
37
64
|
if (!sessionExists(sessionName)) {
|
|
@@ -104,7 +131,9 @@ export function getSessionInfo(agentName) {
|
|
|
104
131
|
return { exists: false };
|
|
105
132
|
}
|
|
106
133
|
try {
|
|
107
|
-
const command = execSync(`tmux list-panes -t "${sessionName}" -F "#{pane_current_command}"`, {
|
|
134
|
+
const command = execSync(`tmux list-panes -t "${sessionName}" -F "#{pane_current_command}"`, {
|
|
135
|
+
encoding: "utf-8",
|
|
136
|
+
}).trim();
|
|
108
137
|
return { exists: true, command };
|
|
109
138
|
}
|
|
110
139
|
catch {
|
package/dist/core/tmux.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../../src/core/tmux.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"tmux.js","sourceRoot":"","sources":["../../src/core/tmux.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT utilities for token management
|
|
3
|
+
* Note: We only decode the payload, we don't verify signatures here
|
|
4
|
+
* (verification happens on the hub side)
|
|
5
|
+
*/
|
|
6
|
+
export interface TokenPayload {
|
|
7
|
+
sub: string;
|
|
8
|
+
actorType: string;
|
|
9
|
+
workspaceScopes: string[];
|
|
10
|
+
iat: number;
|
|
11
|
+
exp: number;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Decode a JWT token without verifying the signature
|
|
15
|
+
*/
|
|
16
|
+
export declare function decodeToken(token: string): TokenPayload | null;
|
|
17
|
+
/**
|
|
18
|
+
* Get the expiration date from a token
|
|
19
|
+
*/
|
|
20
|
+
export declare function getTokenExpiry(token: string): Date | null;
|
|
21
|
+
/**
|
|
22
|
+
* Check if a token is expired
|
|
23
|
+
*/
|
|
24
|
+
export declare function isTokenExpired(token: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Check if a token will expire within the given milliseconds
|
|
27
|
+
*/
|
|
28
|
+
export declare function isTokenExpiringSoon(token: string, withinMs: number): boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Get the agent ID from a token
|
|
31
|
+
*/
|
|
32
|
+
export declare function getAgentIdFromToken(token: string): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Get time remaining until token expires in milliseconds
|
|
35
|
+
*/
|
|
36
|
+
export declare function getTokenTimeRemaining(token: string): number;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT utilities for token management
|
|
3
|
+
* Note: We only decode the payload, we don't verify signatures here
|
|
4
|
+
* (verification happens on the hub side)
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Decode a JWT token without verifying the signature
|
|
8
|
+
*/
|
|
9
|
+
export function decodeToken(token) {
|
|
10
|
+
try {
|
|
11
|
+
const parts = token.split(".");
|
|
12
|
+
if (parts.length !== 3) {
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
const payload = parts[1];
|
|
16
|
+
const decoded = Buffer.from(payload, "base64url").toString("utf-8");
|
|
17
|
+
return JSON.parse(decoded);
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Get the expiration date from a token
|
|
25
|
+
*/
|
|
26
|
+
export function getTokenExpiry(token) {
|
|
27
|
+
const payload = decodeToken(token);
|
|
28
|
+
if (!payload || !payload.exp) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
return new Date(payload.exp * 1000);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Check if a token is expired
|
|
35
|
+
*/
|
|
36
|
+
export function isTokenExpired(token) {
|
|
37
|
+
const expiry = getTokenExpiry(token);
|
|
38
|
+
if (!expiry) {
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
41
|
+
return expiry.getTime() <= Date.now();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if a token will expire within the given milliseconds
|
|
45
|
+
*/
|
|
46
|
+
export function isTokenExpiringSoon(token, withinMs) {
|
|
47
|
+
const expiry = getTokenExpiry(token);
|
|
48
|
+
if (!expiry) {
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
return expiry.getTime() <= Date.now() + withinMs;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Get the agent ID from a token
|
|
55
|
+
*/
|
|
56
|
+
export function getAgentIdFromToken(token) {
|
|
57
|
+
const payload = decodeToken(token);
|
|
58
|
+
return payload?.sub ?? null;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Get time remaining until token expires in milliseconds
|
|
62
|
+
*/
|
|
63
|
+
export function getTokenTimeRemaining(token) {
|
|
64
|
+
const expiry = getTokenExpiry(token);
|
|
65
|
+
if (!expiry) {
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
return Math.max(0, expiry.getTime() - Date.now());
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=jwt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.js","sourceRoot":"","sources":["../../src/utils/jwt.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH;;GAEG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC/B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACzB,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACpE,OAAO,IAAI,CAAC,KAAK,CAAC,OAAO,CAAiB,CAAC;IAC7C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACnC,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;QAC7B,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC;AACtC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,KAAa;IAC1C,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;AACxC,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa,EAAE,QAAgB;IACjE,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,IAAI,CAAC;IACd,CAAC;IAED,OAAO,MAAM,CAAC,OAAO,EAAE,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,CAAC;AACnD,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,mBAAmB,CAAC,KAAa;IAC/C,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,CAAC,CAAC;IACnC,OAAO,OAAO,EAAE,GAAG,IAAI,IAAI,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,KAAa;IACjD,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,OAAO,CAAC,CAAC;IACX,CAAC;IAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,EAAE,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;AACpD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentmeshhq/agent",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "AgentMesh Agent Wrapper - Turn any AI coding assistant into a dispatchable, nudge-able agent",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
"dev": "tsx watch src/cli/index.ts",
|
|
12
12
|
"build": "tsc -p tsconfig.json",
|
|
13
13
|
"lint": "biome check src",
|
|
14
|
-
"start": "node dist/cli/index.js"
|
|
14
|
+
"start": "node dist/cli/index.js",
|
|
15
|
+
"test": "vitest run",
|
|
16
|
+
"test:watch": "vitest"
|
|
15
17
|
},
|
|
16
18
|
"dependencies": {
|
|
17
19
|
"commander": "^12.0.0",
|
|
@@ -20,7 +22,8 @@
|
|
|
20
22
|
},
|
|
21
23
|
"devDependencies": {
|
|
22
24
|
"@types/node": "^22.15.21",
|
|
23
|
-
"@types/ws": "^8.5.10"
|
|
25
|
+
"@types/ws": "^8.5.10",
|
|
26
|
+
"vitest": "^2.1.0"
|
|
24
27
|
},
|
|
25
28
|
"keywords": [
|
|
26
29
|
"agentmesh",
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { describe, expect, it } from "vitest";
|
|
2
|
+
import {
|
|
3
|
+
decodeToken,
|
|
4
|
+
getAgentIdFromToken,
|
|
5
|
+
getTokenExpiry,
|
|
6
|
+
getTokenTimeRemaining,
|
|
7
|
+
isTokenExpired,
|
|
8
|
+
isTokenExpiringSoon,
|
|
9
|
+
} from "../utils/jwt.js";
|
|
10
|
+
|
|
11
|
+
// Sample JWT tokens for testing
|
|
12
|
+
// These are test tokens with known payloads
|
|
13
|
+
|
|
14
|
+
// Token payload: { sub: "test-agent-123", actorType: "agent", workspaceScopes: ["test"], iat: 1700000000, exp: 1700604800 }
|
|
15
|
+
const VALID_TOKEN =
|
|
16
|
+
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ0ZXN0LWFnZW50LTEyMyIsImFjdG9yVHlwZSI6ImFnZW50Iiwid29ya3NwYWNlU2NvcGVzIjpbInRlc3QiXSwiaWF0IjoxNzAwMDAwMDAwLCJleHAiOjE3MDA2MDQ4MDB9.fake_signature";
|
|
17
|
+
|
|
18
|
+
// Expired token (exp: 1600000000 - Sep 2020)
|
|
19
|
+
const EXPIRED_TOKEN =
|
|
20
|
+
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJleHBpcmVkLWFnZW50IiwiYWN0b3JUeXBlIjoiYWdlbnQiLCJ3b3Jrc3BhY2VTY29wZXMiOlsidGVzdCJdLCJpYXQiOjE1MDAwMDAwMDAsImV4cCI6MTYwMDAwMDAwMH0.fake_signature";
|
|
21
|
+
|
|
22
|
+
// Future token (exp: 2700000000 - ~2055)
|
|
23
|
+
const FUTURE_TOKEN =
|
|
24
|
+
"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJmdXR1cmUtYWdlbnQiLCJhY3RvclR5cGUiOiJhZ2VudCIsIndvcmtzcGFjZVNjb3BlcyI6WyJ0ZXN0Il0sImlhdCI6MTcwMDAwMDAwMCwiZXhwIjoyNzAwMDAwMDAwfQ.fake_signature";
|
|
25
|
+
|
|
26
|
+
describe("JWT Utils", () => {
|
|
27
|
+
describe("decodeToken", () => {
|
|
28
|
+
it("should decode a valid JWT token", () => {
|
|
29
|
+
const payload = decodeToken(VALID_TOKEN);
|
|
30
|
+
expect(payload).not.toBeNull();
|
|
31
|
+
expect(payload?.sub).toBe("test-agent-123");
|
|
32
|
+
expect(payload?.actorType).toBe("agent");
|
|
33
|
+
expect(payload?.workspaceScopes).toEqual(["test"]);
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it("should return null for invalid token format", () => {
|
|
37
|
+
expect(decodeToken("invalid")).toBeNull();
|
|
38
|
+
expect(decodeToken("")).toBeNull();
|
|
39
|
+
expect(decodeToken("a.b")).toBeNull();
|
|
40
|
+
});
|
|
41
|
+
|
|
42
|
+
it("should return null for malformed base64", () => {
|
|
43
|
+
expect(decodeToken("a.!!!invalid!!!.c")).toBeNull();
|
|
44
|
+
});
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
describe("getTokenExpiry", () => {
|
|
48
|
+
it("should return expiry date for valid token", () => {
|
|
49
|
+
const expiry = getTokenExpiry(VALID_TOKEN);
|
|
50
|
+
expect(expiry).toBeInstanceOf(Date);
|
|
51
|
+
expect(expiry?.getTime()).toBe(1700604800 * 1000);
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
it("should return null for invalid token", () => {
|
|
55
|
+
expect(getTokenExpiry("invalid")).toBeNull();
|
|
56
|
+
});
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
describe("isTokenExpired", () => {
|
|
60
|
+
it("should return true for expired token", () => {
|
|
61
|
+
expect(isTokenExpired(EXPIRED_TOKEN)).toBe(true);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
it("should return false for future token", () => {
|
|
65
|
+
expect(isTokenExpired(FUTURE_TOKEN)).toBe(false);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
it("should return true for invalid token", () => {
|
|
69
|
+
expect(isTokenExpired("invalid")).toBe(true);
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("isTokenExpiringSoon", () => {
|
|
74
|
+
it("should return true for expired token", () => {
|
|
75
|
+
expect(isTokenExpiringSoon(EXPIRED_TOKEN, 1000)).toBe(true);
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
it("should return false for future token with short threshold", () => {
|
|
79
|
+
// Future token expires in ~2055, so any reasonable threshold should return false
|
|
80
|
+
expect(isTokenExpiringSoon(FUTURE_TOKEN, 24 * 60 * 60 * 1000)).toBe(false);
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
it("should return true for invalid token", () => {
|
|
84
|
+
expect(isTokenExpiringSoon("invalid", 1000)).toBe(true);
|
|
85
|
+
});
|
|
86
|
+
});
|
|
87
|
+
|
|
88
|
+
describe("getAgentIdFromToken", () => {
|
|
89
|
+
it("should return agent ID from valid token", () => {
|
|
90
|
+
expect(getAgentIdFromToken(VALID_TOKEN)).toBe("test-agent-123");
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("should return null for invalid token", () => {
|
|
94
|
+
expect(getAgentIdFromToken("invalid")).toBeNull();
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
describe("getTokenTimeRemaining", () => {
|
|
99
|
+
it("should return 0 for expired token", () => {
|
|
100
|
+
expect(getTokenTimeRemaining(EXPIRED_TOKEN)).toBe(0);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("should return positive value for future token", () => {
|
|
104
|
+
const remaining = getTokenTimeRemaining(FUTURE_TOKEN);
|
|
105
|
+
expect(remaining).toBeGreaterThan(0);
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
it("should return 0 for invalid token", () => {
|
|
109
|
+
expect(getTokenTimeRemaining("invalid")).toBe(0);
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
});
|