agentrace 0.0.7 → 0.0.8
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 +41 -8
- package/dist/commands/init.d.ts +1 -0
- package/dist/commands/init.js +16 -0
- package/dist/config/manager.d.ts +1 -0
- package/dist/index.js +2 -1
- package/dist/mcp/plan-document-client.js +3 -0
- package/dist/utils/http.js +4 -0
- package/dist/utils/proxy.d.ts +11 -0
- package/dist/utils/proxy.js +29 -0
- package/dist/utils/proxy.test.d.ts +1 -0
- package/dist/utils/proxy.test.js +116 -0
- package/package.json +6 -2
package/README.md
CHANGED
|
@@ -31,14 +31,15 @@ That's it! When you use Claude Code, sessions will be automatically sent to Agen
|
|
|
31
31
|
|
|
32
32
|
## Commands
|
|
33
33
|
|
|
34
|
-
| Command
|
|
35
|
-
|
|
|
36
|
-
| `agentrace init --url <url>`
|
|
37
|
-
| `agentrace
|
|
38
|
-
| `agentrace
|
|
39
|
-
| `agentrace
|
|
40
|
-
| `agentrace
|
|
41
|
-
| `agentrace
|
|
34
|
+
| Command | Description |
|
|
35
|
+
| -------------------------------------------- | -------------------------------------- |
|
|
36
|
+
| `agentrace init --url <url>` | Initial setup + hooks installation |
|
|
37
|
+
| `agentrace init --url <url> --proxy <proxy>` | Setup with proxy |
|
|
38
|
+
| `agentrace login` | Open the web dashboard |
|
|
39
|
+
| `agentrace send` | Send transcript diff (used by hooks) |
|
|
40
|
+
| `agentrace on` | Enable hooks |
|
|
41
|
+
| `agentrace off` | Disable hooks |
|
|
42
|
+
| `agentrace uninstall` | Remove hooks and configuration |
|
|
42
43
|
|
|
43
44
|
## Command Details
|
|
44
45
|
|
|
@@ -122,6 +123,38 @@ Configuration is stored in the following locations:
|
|
|
122
123
|
- Only the transcript diff is sent to the server when a Claude Code conversation ends
|
|
123
124
|
- Errors do not block Claude Code's operation by design
|
|
124
125
|
|
|
126
|
+
## Proxy Configuration
|
|
127
|
+
|
|
128
|
+
If you need to connect through an HTTP proxy, you can configure it in several ways:
|
|
129
|
+
|
|
130
|
+
### 1. Using the `--proxy` Option
|
|
131
|
+
|
|
132
|
+
```bash
|
|
133
|
+
npx agentrace init --url http://localhost:9080 --proxy http://proxy.example.com:8080
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
For proxies requiring authentication:
|
|
137
|
+
|
|
138
|
+
```bash
|
|
139
|
+
npx agentrace init --url http://localhost:9080 --proxy http://user:pass@proxy.example.com:8080
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### 2. Using Environment Variables
|
|
143
|
+
|
|
144
|
+
If `proxy_url` is not set in the config file, the CLI will check the following environment variables (in order):
|
|
145
|
+
|
|
146
|
+
1. `HTTPS_PROXY`
|
|
147
|
+
2. `https_proxy`
|
|
148
|
+
3. `HTTP_PROXY`
|
|
149
|
+
4. `http_proxy`
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
export HTTPS_PROXY=http://proxy.example.com:8080
|
|
153
|
+
npx agentrace send
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
**Priority:** Config file > Environment variables
|
|
157
|
+
|
|
125
158
|
## Requirements
|
|
126
159
|
|
|
127
160
|
- Node.js 18 or later
|
package/dist/commands/init.d.ts
CHANGED
package/dist/commands/init.js
CHANGED
|
@@ -25,6 +25,18 @@ export async function initCommand(options = {}) {
|
|
|
25
25
|
console.error("Error: Invalid URL format");
|
|
26
26
|
process.exit(1);
|
|
27
27
|
}
|
|
28
|
+
// Validate proxy URL if provided
|
|
29
|
+
if (options.proxy) {
|
|
30
|
+
try {
|
|
31
|
+
new URL(options.proxy);
|
|
32
|
+
}
|
|
33
|
+
catch {
|
|
34
|
+
console.error("Error: Invalid proxy URL format");
|
|
35
|
+
console.error("Example: http://proxy.example.com:8080");
|
|
36
|
+
console.error(" http://user:pass@proxy.example.com:8080");
|
|
37
|
+
process.exit(1);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
28
40
|
console.log("AgenTrace Setup\n");
|
|
29
41
|
if (options.dev) {
|
|
30
42
|
console.log("[Dev Mode] Using local CLI for hooks\n");
|
|
@@ -61,8 +73,12 @@ export async function initCommand(options = {}) {
|
|
|
61
73
|
saveConfig({
|
|
62
74
|
server_url: serverUrlStr,
|
|
63
75
|
api_key: result.apiKey,
|
|
76
|
+
...(options.proxy && { proxy_url: options.proxy }),
|
|
64
77
|
});
|
|
65
78
|
console.log(`✓ Config saved to ${getConfigPath()}`);
|
|
79
|
+
if (options.proxy) {
|
|
80
|
+
console.log(` Proxy: ${options.proxy}`);
|
|
81
|
+
}
|
|
66
82
|
// Determine hook command
|
|
67
83
|
let hookCommand;
|
|
68
84
|
if (options.dev) {
|
package/dist/config/manager.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -13,9 +13,10 @@ program
|
|
|
13
13
|
.command("init")
|
|
14
14
|
.description("Initialize agentrace configuration and hooks")
|
|
15
15
|
.requiredOption("--url <url>", "Server URL (required)")
|
|
16
|
+
.option("--proxy <url>", "HTTP/HTTPS proxy URL")
|
|
16
17
|
.option("--dev", "Use local CLI path for development")
|
|
17
18
|
.action(async (options) => {
|
|
18
|
-
await initCommand({ url: options.url, dev: options.dev });
|
|
19
|
+
await initCommand({ url: options.url, proxy: options.proxy, dev: options.dev });
|
|
19
20
|
});
|
|
20
21
|
program
|
|
21
22
|
.command("login")
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { fetch } from "undici";
|
|
1
2
|
import { loadConfig } from "../config/manager.js";
|
|
3
|
+
import { createDispatcher } from "../utils/proxy.js";
|
|
2
4
|
export class PlanDocumentClient {
|
|
3
5
|
serverUrl;
|
|
4
6
|
apiKey;
|
|
@@ -20,6 +22,7 @@ export class PlanDocumentClient {
|
|
|
20
22
|
method,
|
|
21
23
|
headers,
|
|
22
24
|
body: body ? JSON.stringify(body) : undefined,
|
|
25
|
+
dispatcher: createDispatcher(),
|
|
23
26
|
});
|
|
24
27
|
if (!response.ok) {
|
|
25
28
|
const errorText = await response.text();
|
package/dist/utils/http.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
+
import { fetch } from "undici";
|
|
1
2
|
import { loadConfig } from "../config/manager.js";
|
|
3
|
+
import { createDispatcher } from "./proxy.js";
|
|
2
4
|
function getBaseUrl(config) {
|
|
3
5
|
return config.server_url.replace(/\/+$/, '');
|
|
4
6
|
}
|
|
@@ -16,6 +18,7 @@ export async function sendIngest(payload) {
|
|
|
16
18
|
Authorization: `Bearer ${config.api_key}`,
|
|
17
19
|
},
|
|
18
20
|
body: JSON.stringify(payload),
|
|
21
|
+
dispatcher: createDispatcher(),
|
|
19
22
|
});
|
|
20
23
|
if (!response.ok) {
|
|
21
24
|
const text = await response.text();
|
|
@@ -41,6 +44,7 @@ export async function createWebSession() {
|
|
|
41
44
|
"Content-Type": "application/json",
|
|
42
45
|
Authorization: `Bearer ${config.api_key}`,
|
|
43
46
|
},
|
|
47
|
+
dispatcher: createDispatcher(),
|
|
44
48
|
});
|
|
45
49
|
if (!response.ok) {
|
|
46
50
|
const text = await response.text();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ProxyAgent } from 'undici';
|
|
2
|
+
/**
|
|
3
|
+
* プロキシURLを取得する
|
|
4
|
+
* 優先順位: 設定ファイル > 環境変数(HTTPS_PROXY > HTTP_PROXY)
|
|
5
|
+
*/
|
|
6
|
+
export declare function getProxyUrl(): string | undefined;
|
|
7
|
+
/**
|
|
8
|
+
* undici の dispatcher を生成する
|
|
9
|
+
* プロキシ設定がない場合は undefined を返す(デフォルト動作)
|
|
10
|
+
*/
|
|
11
|
+
export declare function createDispatcher(): ProxyAgent | undefined;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProxyAgent } from 'undici';
|
|
2
|
+
import { loadConfig } from '../config/manager.js';
|
|
3
|
+
/**
|
|
4
|
+
* プロキシURLを取得する
|
|
5
|
+
* 優先順位: 設定ファイル > 環境変数(HTTPS_PROXY > HTTP_PROXY)
|
|
6
|
+
*/
|
|
7
|
+
export function getProxyUrl() {
|
|
8
|
+
const config = loadConfig();
|
|
9
|
+
// 設定ファイル優先
|
|
10
|
+
if (config?.proxy_url) {
|
|
11
|
+
return config.proxy_url;
|
|
12
|
+
}
|
|
13
|
+
// 環境変数フォールバック(大文字・小文字両方サポート)
|
|
14
|
+
return process.env.HTTPS_PROXY
|
|
15
|
+
|| process.env.https_proxy
|
|
16
|
+
|| process.env.HTTP_PROXY
|
|
17
|
+
|| process.env.http_proxy;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* undici の dispatcher を生成する
|
|
21
|
+
* プロキシ設定がない場合は undefined を返す(デフォルト動作)
|
|
22
|
+
*/
|
|
23
|
+
export function createDispatcher() {
|
|
24
|
+
const proxyUrl = getProxyUrl();
|
|
25
|
+
if (!proxyUrl) {
|
|
26
|
+
return undefined;
|
|
27
|
+
}
|
|
28
|
+
return new ProxyAgent(proxyUrl);
|
|
29
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
|
|
2
|
+
import { ProxyAgent } from 'undici';
|
|
3
|
+
// モックを設定
|
|
4
|
+
vi.mock('../config/manager.js', () => ({
|
|
5
|
+
loadConfig: vi.fn(),
|
|
6
|
+
}));
|
|
7
|
+
import { getProxyUrl, createDispatcher } from './proxy.js';
|
|
8
|
+
import { loadConfig } from '../config/manager.js';
|
|
9
|
+
const mockedLoadConfig = vi.mocked(loadConfig);
|
|
10
|
+
describe('proxy', () => {
|
|
11
|
+
const originalEnv = process.env;
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
// 環境変数をリセット
|
|
14
|
+
process.env = { ...originalEnv };
|
|
15
|
+
delete process.env.HTTPS_PROXY;
|
|
16
|
+
delete process.env.https_proxy;
|
|
17
|
+
delete process.env.HTTP_PROXY;
|
|
18
|
+
delete process.env.http_proxy;
|
|
19
|
+
// モックをリセット
|
|
20
|
+
vi.clearAllMocks();
|
|
21
|
+
});
|
|
22
|
+
afterEach(() => {
|
|
23
|
+
process.env = originalEnv;
|
|
24
|
+
});
|
|
25
|
+
describe('getProxyUrl', () => {
|
|
26
|
+
it('設定ファイルにproxy_urlがある場合、それを返す', () => {
|
|
27
|
+
mockedLoadConfig.mockReturnValue({
|
|
28
|
+
server_url: 'http://localhost:8080',
|
|
29
|
+
api_key: 'test-key',
|
|
30
|
+
proxy_url: 'http://proxy.example.com:8080',
|
|
31
|
+
});
|
|
32
|
+
expect(getProxyUrl()).toBe('http://proxy.example.com:8080');
|
|
33
|
+
});
|
|
34
|
+
it('設定ファイルにproxy_urlがなく、HTTPS_PROXYがある場合、それを返す', () => {
|
|
35
|
+
mockedLoadConfig.mockReturnValue({
|
|
36
|
+
server_url: 'http://localhost:8080',
|
|
37
|
+
api_key: 'test-key',
|
|
38
|
+
});
|
|
39
|
+
process.env.HTTPS_PROXY = 'http://https-proxy.example.com:8080';
|
|
40
|
+
expect(getProxyUrl()).toBe('http://https-proxy.example.com:8080');
|
|
41
|
+
});
|
|
42
|
+
it('設定ファイルにproxy_urlがなく、https_proxy(小文字)がある場合、それを返す', () => {
|
|
43
|
+
mockedLoadConfig.mockReturnValue({
|
|
44
|
+
server_url: 'http://localhost:8080',
|
|
45
|
+
api_key: 'test-key',
|
|
46
|
+
});
|
|
47
|
+
process.env.https_proxy = 'http://https-proxy-lower.example.com:8080';
|
|
48
|
+
expect(getProxyUrl()).toBe('http://https-proxy-lower.example.com:8080');
|
|
49
|
+
});
|
|
50
|
+
it('設定ファイルにproxy_urlがなく、HTTP_PROXYがある場合、それを返す', () => {
|
|
51
|
+
mockedLoadConfig.mockReturnValue({
|
|
52
|
+
server_url: 'http://localhost:8080',
|
|
53
|
+
api_key: 'test-key',
|
|
54
|
+
});
|
|
55
|
+
process.env.HTTP_PROXY = 'http://http-proxy.example.com:8080';
|
|
56
|
+
expect(getProxyUrl()).toBe('http://http-proxy.example.com:8080');
|
|
57
|
+
});
|
|
58
|
+
it('設定ファイルにproxy_urlがなく、http_proxy(小文字)がある場合、それを返す', () => {
|
|
59
|
+
mockedLoadConfig.mockReturnValue({
|
|
60
|
+
server_url: 'http://localhost:8080',
|
|
61
|
+
api_key: 'test-key',
|
|
62
|
+
});
|
|
63
|
+
process.env.http_proxy = 'http://http-proxy-lower.example.com:8080';
|
|
64
|
+
expect(getProxyUrl()).toBe('http://http-proxy-lower.example.com:8080');
|
|
65
|
+
});
|
|
66
|
+
it('設定ファイルも環境変数もない場合、undefinedを返す', () => {
|
|
67
|
+
mockedLoadConfig.mockReturnValue({
|
|
68
|
+
server_url: 'http://localhost:8080',
|
|
69
|
+
api_key: 'test-key',
|
|
70
|
+
});
|
|
71
|
+
expect(getProxyUrl()).toBeUndefined();
|
|
72
|
+
});
|
|
73
|
+
it('設定ファイルがnullの場合、環境変数にフォールバックする', () => {
|
|
74
|
+
mockedLoadConfig.mockReturnValue(null);
|
|
75
|
+
process.env.HTTPS_PROXY = 'http://env-proxy.example.com:8080';
|
|
76
|
+
expect(getProxyUrl()).toBe('http://env-proxy.example.com:8080');
|
|
77
|
+
});
|
|
78
|
+
it('設定ファイルが環境変数より優先される', () => {
|
|
79
|
+
mockedLoadConfig.mockReturnValue({
|
|
80
|
+
server_url: 'http://localhost:8080',
|
|
81
|
+
api_key: 'test-key',
|
|
82
|
+
proxy_url: 'http://config-proxy.example.com:8080',
|
|
83
|
+
});
|
|
84
|
+
process.env.HTTPS_PROXY = 'http://env-proxy.example.com:8080';
|
|
85
|
+
expect(getProxyUrl()).toBe('http://config-proxy.example.com:8080');
|
|
86
|
+
});
|
|
87
|
+
it('HTTPS_PROXYがHTTP_PROXYより優先される', () => {
|
|
88
|
+
mockedLoadConfig.mockReturnValue({
|
|
89
|
+
server_url: 'http://localhost:8080',
|
|
90
|
+
api_key: 'test-key',
|
|
91
|
+
});
|
|
92
|
+
process.env.HTTPS_PROXY = 'http://https-proxy.example.com:8080';
|
|
93
|
+
process.env.HTTP_PROXY = 'http://http-proxy.example.com:8080';
|
|
94
|
+
expect(getProxyUrl()).toBe('http://https-proxy.example.com:8080');
|
|
95
|
+
});
|
|
96
|
+
});
|
|
97
|
+
describe('createDispatcher', () => {
|
|
98
|
+
it('プロキシURLがある場合、ProxyAgentを返す', () => {
|
|
99
|
+
mockedLoadConfig.mockReturnValue({
|
|
100
|
+
server_url: 'http://localhost:8080',
|
|
101
|
+
api_key: 'test-key',
|
|
102
|
+
proxy_url: 'http://proxy.example.com:8080',
|
|
103
|
+
});
|
|
104
|
+
const dispatcher = createDispatcher();
|
|
105
|
+
expect(dispatcher).toBeInstanceOf(ProxyAgent);
|
|
106
|
+
});
|
|
107
|
+
it('プロキシURLがない場合、undefinedを返す', () => {
|
|
108
|
+
mockedLoadConfig.mockReturnValue({
|
|
109
|
+
server_url: 'http://localhost:8080',
|
|
110
|
+
api_key: 'test-key',
|
|
111
|
+
});
|
|
112
|
+
const dispatcher = createDispatcher();
|
|
113
|
+
expect(dispatcher).toBeUndefined();
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "agentrace",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.8",
|
|
4
4
|
"description": "CLI for AgenTrace - Claude Code session tracker",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -13,6 +13,8 @@
|
|
|
13
13
|
"scripts": {
|
|
14
14
|
"build": "tsc",
|
|
15
15
|
"dev": "tsx src/index.ts",
|
|
16
|
+
"test": "vitest run",
|
|
17
|
+
"test:watch": "vitest",
|
|
16
18
|
"prepublishOnly": "npm run build"
|
|
17
19
|
},
|
|
18
20
|
"keywords": [
|
|
@@ -38,12 +40,14 @@
|
|
|
38
40
|
"@modelcontextprotocol/sdk": "^1.0.0",
|
|
39
41
|
"commander": "^12.0.0",
|
|
40
42
|
"diff-match-patch-es": "^1.0.0",
|
|
43
|
+
"undici": "^7.18.2",
|
|
41
44
|
"zod": "^3.25.0"
|
|
42
45
|
},
|
|
43
46
|
"devDependencies": {
|
|
44
47
|
"@types/node": "^20.0.0",
|
|
45
48
|
"tsx": "^4.0.0",
|
|
46
|
-
"typescript": "^5.0.0"
|
|
49
|
+
"typescript": "^5.0.0",
|
|
50
|
+
"vitest": "^4.0.17"
|
|
47
51
|
},
|
|
48
52
|
"engines": {
|
|
49
53
|
"node": ">=18.0.0"
|