pi-harness-runtime 1.1.150 → 1.1.152
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/CHANGELOG.md +7 -0
- package/harness/key-loader.ts +84 -0
- package/harness/langchain/agents.ts +65 -15
- package/harness/langchain/daemon.ts +58 -30
- package/harness/langchain/graph.ts +55 -7
- package/harness/langchain/jev-logger.ts +274 -0
- package/harness/langchain/run.ts +64 -161
- package/harness/langchain/surge.test.ts +42 -0
- package/harness/langchain/surge.ts +22 -1
- package/index.ts +24 -0
- package/package.json +1 -1
- package/packages/a2a-adapter/package.json +1 -1
- package/packages/agent-policy/dist/extension.d.ts +19 -0
- package/packages/agent-policy/dist/extension.d.ts.map +1 -0
- package/packages/agent-policy/dist/extension.js +322 -0
- package/packages/agent-policy/dist/extension.js.map +1 -0
- package/packages/agent-policy/dist/index.d.ts +25 -0
- package/packages/agent-policy/dist/index.d.ts.map +1 -0
- package/packages/agent-policy/dist/index.js +27 -0
- package/packages/agent-policy/dist/index.js.map +1 -0
- package/packages/agent-policy/dist/policy-loader.d.ts +90 -0
- package/packages/agent-policy/dist/policy-loader.d.ts.map +1 -0
- package/packages/agent-policy/dist/policy-loader.js +331 -0
- package/packages/agent-policy/dist/policy-loader.js.map +1 -0
- package/packages/agent-policy/dist/policy-renderer.d.ts +42 -0
- package/packages/agent-policy/dist/policy-renderer.d.ts.map +1 -0
- package/packages/agent-policy/dist/policy-renderer.js +295 -0
- package/packages/agent-policy/dist/policy-renderer.js.map +1 -0
- package/packages/agent-policy/dist/policy-store.d.ts +99 -0
- package/packages/agent-policy/dist/policy-store.d.ts.map +1 -0
- package/packages/agent-policy/dist/policy-store.js +244 -0
- package/packages/agent-policy/dist/policy-store.js.map +1 -0
- package/packages/agent-policy/dist/types.d.ts +237 -0
- package/packages/agent-policy/dist/types.d.ts.map +1 -0
- package/packages/agent-policy/dist/types.js +130 -0
- package/packages/agent-policy/dist/types.js.map +1 -0
- package/packages/agent-policy/package.json +45 -0
- package/packages/agent-policy/src/extension.ts +413 -0
- package/packages/agent-policy/src/index.ts +52 -0
- package/packages/agent-policy/src/policy-loader.ts +398 -0
- package/packages/agent-policy/src/policy-renderer.ts +362 -0
- package/packages/agent-policy/src/policy-store.ts +319 -0
- package/packages/agent-policy/src/types.ts +385 -0
- package/packages/agent-policy/test/policy.test.ts +383 -0
- package/packages/architecture-generator/package.json +1 -1
- package/packages/auth/package.json +1 -1
- package/packages/autonomous-refactor/package.json +1 -1
- package/packages/autonomous-runtime/package.json +1 -1
- package/packages/cache-strategy/package.json +1 -1
- package/packages/capability-registry/package.json +1 -1
- package/packages/checkpoint/package.json +1 -1
- package/packages/cli-plugin-sdk/package.json +1 -1
- package/packages/clipboard/package.json +1 -1
- package/packages/clipboard-plugin/package.json +1 -1
- package/packages/code-generation/package.json +1 -1
- package/packages/code-review/package.json +1 -1
- package/packages/codex-adapter/package.json +1 -1
- package/packages/codex-watcher/dist/src/parser.d.ts.map +1 -1
- package/packages/codex-watcher/dist/src/parser.js +35 -0
- package/packages/codex-watcher/dist/src/parser.js.map +1 -1
- package/packages/codex-watcher/package.json +1 -1
- package/packages/codex-watcher/src/parser.ts +41 -0
- package/packages/config-capture/package.json +1 -1
- package/packages/context-compiler/package.json +1 -1
- package/packages/context-discovery/package.json +1 -1
- package/packages/context-manager/package.json +1 -1
- package/packages/cookie-sanitizer/package.json +1 -1
- package/packages/cost-optimizer/package.json +1 -1
- package/packages/dependency-analyzer/package.json +1 -1
- package/packages/django-plugin/package.json +1 -1
- package/packages/doc-generator/package.json +1 -1
- package/packages/evaluation-engine/package.json +1 -1
- package/packages/evaluation-runner/package.json +1 -1
- package/packages/event-bus/package.json +1 -1
- package/packages/event-store/package.json +1 -1
- package/packages/experience-replay/package.json +1 -1
- package/packages/feedback-collector/package.json +1 -1
- package/packages/file-copy-helper/package.json +1 -1
- package/packages/framework-detector/package.json +1 -1
- package/packages/framework-plugin-sdk/package.json +1 -1
- package/packages/frappe-plugin/package.json +1 -1
- package/packages/generic-web-plugin/package.json +1 -1
- package/packages/health-monitor/package.json +1 -1
- package/packages/intent-analyzer/package.json +1 -1
- package/packages/jev-judge/package.json +1 -1
- package/packages/knowledge-graph/package.json +1 -1
- package/packages/knowledge-retrieval/package.json +1 -1
- package/packages/laravel-plugin/package.json +1 -1
- package/packages/learning-engine/package.json +1 -1
- package/packages/mcp-adapter/package.json +1 -1
- package/packages/memory-engine/package.json +1 -1
- package/packages/milestone-manager/package.json +1 -1
- package/packages/model-registry/package.json +1 -1
- package/packages/nextjs-plugin/package.json +1 -1
- package/packages/notification/dist/adapters/telegram-adapter.d.ts +5 -0
- package/packages/notification/dist/adapters/telegram-adapter.d.ts.map +1 -1
- package/packages/notification/dist/adapters/telegram-adapter.js +54 -0
- package/packages/notification/dist/adapters/telegram-adapter.js.map +1 -1
- package/packages/notification/dist/notification-center.d.ts +13 -0
- package/packages/notification/dist/notification-center.d.ts.map +1 -1
- package/packages/notification/dist/notification-center.js +36 -0
- package/packages/notification/dist/notification-center.js.map +1 -1
- package/packages/notification/package.json +1 -1
- package/packages/notification/src/adapters/telegram-adapter.ts +71 -0
- package/packages/notification/src/notification-center.ts +53 -0
- package/packages/observability/package.json +1 -1
- package/packages/okf-indexer/package.json +1 -1
- package/packages/paperclip-integration/package.json +1 -1
- package/packages/performance-optimizer/package.json +1 -1
- package/packages/privilege-broker/package.json +1 -1
- package/packages/project-analyzer/package.json +1 -1
- package/packages/project-bootstrap/package.json +1 -1
- package/packages/projection-engine/package.json +1 -1
- package/packages/prompt-compiler/package.json +1 -1
- package/packages/prompt-versioning/package.json +1 -1
- package/packages/provider-adapter-sdk/package.json +1 -1
- package/packages/provider-router/package.json +1 -1
- package/packages/provider-selector/package.json +1 -1
- package/packages/providers/package.json +1 -1
- package/packages/qdrant-skills/package.json +1 -1
- package/packages/quota-manager/package.json +1 -1
- package/packages/rate-limiter/package.json +1 -1
- package/packages/react-vite-plugin/package.json +1 -1
- package/packages/release-manager/package.json +1 -1
- package/packages/requirement-compiler/package.json +1 -1
- package/packages/runtime/package.json +1 -1
- package/packages/scheduler/package.json +1 -1
- package/packages/scheduler-adapter/package.json +1 -1
- package/packages/session/package.json +1 -1
- package/packages/session-api/package.json +1 -1
- package/packages/session-export/package.json +1 -1
- package/packages/shared-context/package.json +1 -1
- package/packages/skill-mcp-client/package.json +1 -1
- package/packages/skill-registry/package.json +1 -1
- package/packages/skills/package.json +1 -1
- package/packages/sprint-planner/package.json +1 -1
- package/packages/subscription-engine/package.json +1 -1
- package/packages/task-compiler/package.json +1 -1
- package/packages/tencentdb-memory/package.json +1 -1
- package/packages/tencentdb-sync/package.json +1 -1
- package/packages/test-data-generator/package.json +1 -1
- package/packages/test-generator/package.json +1 -1
- package/packages/todo-bd-sync/package.json +1 -1
- package/packages/token-estimation/package.json +1 -1
- package/packages/token-optimizer/package.json +1 -1
- package/packages/trajectory/package.json +1 -1
- package/packages/tui/package.json +1 -1
- package/packages/types/package.json +1 -1
- package/packages/workflow-events/package.json +1 -1
- package/packages/workspace-scanner/package.json +1 -1
- package/packages/worktree/package.json +1 -1
- package/packages/write-review/package.json +1 -1
- package/proactive-compact.ts +2 -2
- package/scripts/debug-codex-integration.ts +203 -0
- package/scripts/sync-keys-from-pi.ts +188 -0
- package/scripts/test-codex-session.ts +23 -0
- package/scripts/test-openai.ts +14 -0
- package/scripts/test-telegram.ts +34 -0
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Debug Codex Integration Script
|
|
4
|
+
*
|
|
5
|
+
* Tests the PING-PONG Codex watcher pipeline:
|
|
6
|
+
* 1. Checks if Codex sessions exist in ~/.codex/
|
|
7
|
+
* 2. Tests classifyMessage() function
|
|
8
|
+
* 3. Verifies CodexWatcher is finding sessions
|
|
9
|
+
* 4. Shows PING-PONG decisions for found messages
|
|
10
|
+
*
|
|
11
|
+
* Usage:
|
|
12
|
+
* bun run scripts/debug-codex-integration.ts
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
import { existsSync, readdirSync, readFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import { homedir } from "node:os";
|
|
18
|
+
import { classifyMessage } from "../packages/codex-watcher/dist/src/parser.js";
|
|
19
|
+
import { analyzePingPongDecision } from "../packages/intent-analyzer/dist/src/ping-pong.js";
|
|
20
|
+
import { scanCodebaseComplexity } from "../packages/intent-analyzer/dist/src/ping-pong.js";
|
|
21
|
+
|
|
22
|
+
const CODEX_DIR = join(homedir(), ".codex");
|
|
23
|
+
const SESSIONS_DIR = join(CODEX_DIR, "sessions");
|
|
24
|
+
|
|
25
|
+
console.log("=".repeat(60));
|
|
26
|
+
console.log("CODEX INTEGRATION DEBUG");
|
|
27
|
+
console.log("=".repeat(60));
|
|
28
|
+
|
|
29
|
+
// 1. Check Codex directory
|
|
30
|
+
console.log("\n[1] Checking Codex directory...");
|
|
31
|
+
if (!existsSync(CODEX_DIR)) {
|
|
32
|
+
console.log(` ❌ ~/.codex/ not found at ${CODEX_DIR}`);
|
|
33
|
+
console.log(" → Install Codex CLI or set CODEX_DIR env var");
|
|
34
|
+
process.exit(1);
|
|
35
|
+
}
|
|
36
|
+
console.log(` ✓ ~/.codex/ exists at ${CODEX_DIR}`);
|
|
37
|
+
|
|
38
|
+
// 2. Check sessions directory
|
|
39
|
+
console.log("\n[2] Checking sessions directory...");
|
|
40
|
+
if (!existsSync(SESSIONS_DIR)) {
|
|
41
|
+
console.log(` ⚠️ ~/.codex/sessions/ not found`);
|
|
42
|
+
console.log(" → No active Codex sessions yet");
|
|
43
|
+
} else {
|
|
44
|
+
const years = readdirSync(SESSIONS_DIR).filter(f => /^\d{4}$/.test(f));
|
|
45
|
+
console.log(` ✓ Found ${years.length} year(s): ${years.join(", ")}`);
|
|
46
|
+
|
|
47
|
+
let totalSessions = 0;
|
|
48
|
+
let totalMessages = 0;
|
|
49
|
+
|
|
50
|
+
for (const year of years) {
|
|
51
|
+
const yearPath = join(SESSIONS_DIR, year);
|
|
52
|
+
const months = readdirSync(yearPath).filter(f => /^\d{2}$/.test(f));
|
|
53
|
+
|
|
54
|
+
for (const month of months) {
|
|
55
|
+
const monthPath = join(SESSIONS_DIR, year, month);
|
|
56
|
+
const days = readdirSync(monthPath).filter(f => /^\d{2}$/.test(f));
|
|
57
|
+
|
|
58
|
+
for (const day of days) {
|
|
59
|
+
const dayPath = join(SESSIONS_DIR, year, month, day);
|
|
60
|
+
const files = readdirSync(dayPath).filter(f => f.includes("rollout") && f.endsWith(".jsonl"));
|
|
61
|
+
totalSessions += files.length;
|
|
62
|
+
|
|
63
|
+
for (const file of files) {
|
|
64
|
+
const content = readFileSync(join(dayPath, file), "utf8");
|
|
65
|
+
const lines = content.split("\n").filter(l => l.trim());
|
|
66
|
+
totalMessages += lines.length;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log(` ✓ Found ${totalSessions} session file(s) with ${totalMessages} message(s)`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// 3. Test classifyMessage function
|
|
76
|
+
console.log("\n[3] Testing classifyMessage() function...");
|
|
77
|
+
const testMessages = [
|
|
78
|
+
{ text: "Let me implement the feature", expected: "plan" },
|
|
79
|
+
{ text: "I need to fix this bug", expected: "plan" },
|
|
80
|
+
{ text: "The code has an issue in the auth module", expected: "plan" },
|
|
81
|
+
{ text: "I will refactor the database layer", expected: "plan" },
|
|
82
|
+
{ text: "What is the current status?", expected: "other" },
|
|
83
|
+
{ text: "Show me the logs", expected: "other" },
|
|
84
|
+
{ text: "Let me explain the architecture", expected: "other" },
|
|
85
|
+
];
|
|
86
|
+
|
|
87
|
+
for (const { text, expected } of testMessages) {
|
|
88
|
+
const result = classifyMessage(text);
|
|
89
|
+
const icon = result === expected ? "✓" : "✗";
|
|
90
|
+
console.log(` ${icon} "${text.slice(0, 40)}..." → ${result} (expected: ${expected})`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// 4. Find actual plan messages in sessions
|
|
94
|
+
console.log("\n[4] Scanning for plan messages in sessions...");
|
|
95
|
+
let planCount = 0;
|
|
96
|
+
const planMessages: Array<{ session: string; text: string; classification: string }> = [];
|
|
97
|
+
|
|
98
|
+
if (existsSync(SESSIONS_DIR)) {
|
|
99
|
+
const scanDir = (dir: string, depth = 0) => {
|
|
100
|
+
if (depth > 4 || planCount >= 10) return; // Limit scan
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
const entries = readdirSync(dir);
|
|
104
|
+
for (const entry of entries) {
|
|
105
|
+
if (planCount >= 10) break;
|
|
106
|
+
|
|
107
|
+
const fullPath = join(dir, entry);
|
|
108
|
+
if (entry.endsWith(".jsonl") && entry.includes("rollout")) {
|
|
109
|
+
const content = readFileSync(fullPath, "utf8");
|
|
110
|
+
const lines = content.split("\n").filter(l => l.trim());
|
|
111
|
+
|
|
112
|
+
for (const line of lines) {
|
|
113
|
+
try {
|
|
114
|
+
const msg = JSON.parse(line);
|
|
115
|
+
if (msg.text && typeof msg.text === "string") {
|
|
116
|
+
const cls = classifyMessage(msg.text);
|
|
117
|
+
if (cls === "plan") {
|
|
118
|
+
planCount++;
|
|
119
|
+
planMessages.push({
|
|
120
|
+
session: entry,
|
|
121
|
+
text: msg.text.slice(0, 100),
|
|
122
|
+
classification: cls
|
|
123
|
+
});
|
|
124
|
+
if (planCount >= 10) break;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
} catch {
|
|
128
|
+
// Ignore parse errors for non-JSON lines
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
} else if (!entry.includes(".")) {
|
|
132
|
+
// Likely a directory, recurse
|
|
133
|
+
scanDir(fullPath, depth + 1);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} catch {}
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
scanDir(SESSIONS_DIR);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
if (planCount === 0) {
|
|
143
|
+
console.log(" ⚠️ No plan messages found (Codex might not be running)");
|
|
144
|
+
} else {
|
|
145
|
+
console.log(` ✓ Found ${planCount} plan message(s):`);
|
|
146
|
+
for (const msg of planMessages) {
|
|
147
|
+
console.log(` - [${msg.session}] "${msg.text}..."`);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
// 5. Test PING-PONG decision for sample messages
|
|
152
|
+
console.log("\n[5] Testing PING-PONG decisions for sample messages...");
|
|
153
|
+
const sampleRequests = [
|
|
154
|
+
"Good plan, then write down plan to wiki/ then I will ask Minimax to write code then you review",
|
|
155
|
+
"analyze why the loop is quiet, do not edit code",
|
|
156
|
+
"implement user authentication with JWT tokens",
|
|
157
|
+
"fix the memory leak in the worker process",
|
|
158
|
+
];
|
|
159
|
+
|
|
160
|
+
for (const request of sampleRequests) {
|
|
161
|
+
const result = analyzePingPongDecision(request, {
|
|
162
|
+
codebase: scanCodebaseComplexity(process.cwd())
|
|
163
|
+
});
|
|
164
|
+
console.log(`\n Request: "${request.slice(0, 50)}..."`);
|
|
165
|
+
console.log(` Decision: ${result.decision}`);
|
|
166
|
+
console.log(` Score: ${result.score} (run>=9, suggest>=6)`);
|
|
167
|
+
console.log(` Reasons: ${result.reasons.slice(0, 3).join("; ")}`);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
// 6. Summary
|
|
171
|
+
console.log("\n" + "=".repeat(60));
|
|
172
|
+
console.log("SUMMARY");
|
|
173
|
+
console.log("=".repeat(60));
|
|
174
|
+
|
|
175
|
+
const issues: string[] = [];
|
|
176
|
+
|
|
177
|
+
if (!existsSync(SESSIONS_DIR)) {
|
|
178
|
+
issues.push("No sessions directory - Codex CLI not running or not set up");
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
if (planCount === 0) {
|
|
182
|
+
issues.push("No plan messages found - Codex might not have generated any plans yet");
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (issues.length === 0) {
|
|
186
|
+
console.log("✓ All checks passed!");
|
|
187
|
+
console.log("\nTo verify PING-PONG is working:");
|
|
188
|
+
console.log(" 1. Start Codex CLI in one terminal: codex");
|
|
189
|
+
console.log(" 2. Ask Codex to make a plan (e.g., 'implement X')");
|
|
190
|
+
console.log(" 3. Check daemon logs for:");
|
|
191
|
+
console.log(" [codex-watcher] Session started:");
|
|
192
|
+
console.log(" [daemon] Ping-pong decision for [codex]:");
|
|
193
|
+
} else {
|
|
194
|
+
console.log("⚠️ Issues found:");
|
|
195
|
+
for (const issue of issues) {
|
|
196
|
+
console.log(` - ${issue}`);
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
console.log("\nTo manually test PING-PONG:");
|
|
201
|
+
console.log(" 1. Create a task file in /tmp/herdr-workspace/inbox/");
|
|
202
|
+
console.log(" 2. Or use the API directly:");
|
|
203
|
+
console.log(" curl -X POST http://localhost:8100/api/ping-pong -d '{\"request\": \"implement X\"}'");
|
|
@@ -0,0 +1,188 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
/**
|
|
3
|
+
* Sync Keys from pi.dev to ~/.pi-harness-runtime/keys/
|
|
4
|
+
*
|
|
5
|
+
* This script reads API keys from ~/.pi/agent/auth.json and syncs them
|
|
6
|
+
* to ~/.pi-harness-runtime/keys/ so the daemon can use them.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* bun run scripts/sync-keys-from-pi.ts
|
|
10
|
+
*
|
|
11
|
+
* Or import and call:
|
|
12
|
+
* import { syncAllKeys } from "./sync-keys-from-pi.ts";
|
|
13
|
+
* syncAllKeys();
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from "node:fs";
|
|
17
|
+
import { join } from "node:path";
|
|
18
|
+
import { homedir } from "node:os";
|
|
19
|
+
|
|
20
|
+
// Paths
|
|
21
|
+
const PI_AUTH_FILE = join(homedir(), ".pi", "agent", "auth.json");
|
|
22
|
+
const KEYS_DIR = join(homedir(), ".pi-harness-runtime", "keys");
|
|
23
|
+
|
|
24
|
+
// Key mappings: pi provider name -> key file name
|
|
25
|
+
// Note: openai-codex uses OAuth access token (not api_key)
|
|
26
|
+
const KEY_MAPPINGS: Record<string, string> = {
|
|
27
|
+
// Model API keys (for daemon loop)
|
|
28
|
+
minimax: "minimax-api-key.txt",
|
|
29
|
+
zai: "glm-api-key.txt", // zai = GLM for review
|
|
30
|
+
"openai-codex": "planner-api-key.txt", // OpenAI OAuth access token as planner
|
|
31
|
+
|
|
32
|
+
// Other services
|
|
33
|
+
qdrant: "qdrant-api-key.txt",
|
|
34
|
+
paperclip: "paperclip-api-key.txt",
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
// Environment variable mappings: key file name -> env variable name
|
|
38
|
+
const ENV_MAPPINGS: Record<string, string> = {
|
|
39
|
+
"minimax-api-key.txt": "MINIMAX_API_KEY",
|
|
40
|
+
"glm-api-key.txt": "GLM_API_KEY",
|
|
41
|
+
"planner-api-key.txt": "PLANNER_API_KEY",
|
|
42
|
+
"planner-model.txt": "PLANNER_MODEL",
|
|
43
|
+
"planner-base-url.txt": "PLANNER_BASE_URL",
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Read pi.dev auth.json
|
|
48
|
+
*/
|
|
49
|
+
function readPiAuth(): Record<string, { type?: string; key?: string; access?: string }> | null {
|
|
50
|
+
try {
|
|
51
|
+
if (!existsSync(PI_AUTH_FILE)) {
|
|
52
|
+
console.log(`[sync-keys] pi.dev auth file not found: ${PI_AUTH_FILE}`);
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
const content = readFileSync(PI_AUTH_FILE, "utf8");
|
|
56
|
+
return JSON.parse(content);
|
|
57
|
+
} catch (err) {
|
|
58
|
+
console.error(`[sync-keys] Failed to read pi.dev auth: ${err}`);
|
|
59
|
+
return null;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Get API key from auth entry
|
|
65
|
+
*/
|
|
66
|
+
function getKeyFromEntry(entry: { type?: string; key?: string; access?: string }): string | null {
|
|
67
|
+
if (entry.type === "api_key" && entry.key) {
|
|
68
|
+
return entry.key;
|
|
69
|
+
}
|
|
70
|
+
if (entry.type === "oauth" && entry.access) {
|
|
71
|
+
return entry.access; // Use OAuth access token
|
|
72
|
+
}
|
|
73
|
+
return null;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Sync a single key file
|
|
78
|
+
*/
|
|
79
|
+
function syncKey(providerName: string, filename: string): boolean {
|
|
80
|
+
const auth = readPiAuth();
|
|
81
|
+
if (!auth) return false;
|
|
82
|
+
|
|
83
|
+
// Try different case variations of provider name
|
|
84
|
+
const keys = [providerName, providerName.toLowerCase(), providerName.replace(/-/g, "").toLowerCase()];
|
|
85
|
+
|
|
86
|
+
for (const key of keys) {
|
|
87
|
+
if (auth[key]?.key) {
|
|
88
|
+
const entry = auth[key];
|
|
89
|
+
const apiKey = getKeyFromEntry(entry);
|
|
90
|
+
if (apiKey) {
|
|
91
|
+
const filepath = join(KEYS_DIR, filename);
|
|
92
|
+
const currentKey = existsSync(filepath) ? readFileSync(filepath, "utf8").trim() : null;
|
|
93
|
+
|
|
94
|
+
if (currentKey !== apiKey) {
|
|
95
|
+
writeFileSync(filepath, apiKey);
|
|
96
|
+
const envVar = ENV_MAPPINGS[filename];
|
|
97
|
+
console.log(`[sync-keys] Synced ${providerName} -> ${filename}${envVar ? ` (${envVar})` : ""}`);
|
|
98
|
+
return true;
|
|
99
|
+
} else {
|
|
100
|
+
console.log(`[sync-keys] ${filename} already up to date`);
|
|
101
|
+
return true;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
console.log(`[sync-keys] No key found for ${providerName} in pi.dev auth`);
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Create default config files for required but missing keys
|
|
113
|
+
*/
|
|
114
|
+
function createDefaultConfigs(): void {
|
|
115
|
+
// Planner defaults
|
|
116
|
+
const plannerModelFile = join(KEYS_DIR, "planner-model.txt");
|
|
117
|
+
if (!existsSync(plannerModelFile)) {
|
|
118
|
+
writeFileSync(plannerModelFile, "gpt-4o");
|
|
119
|
+
console.log(`[sync-keys] Created ${plannerModelFile} (default: gpt-4o)`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
const plannerBaseUrlFile = join(KEYS_DIR, "planner-base-url.txt");
|
|
123
|
+
if (!existsSync(plannerBaseUrlFile)) {
|
|
124
|
+
writeFileSync(plannerBaseUrlFile, "https://api.openai.com/v1");
|
|
125
|
+
console.log(`[sync-keys] Created ${plannerBaseUrlFile} (default: OpenAI)`);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// GLM defaults (zai)
|
|
129
|
+
const glmModelFile = join(KEYS_DIR, "glm-model.txt");
|
|
130
|
+
if (!existsSync(glmModelFile)) {
|
|
131
|
+
writeFileSync(glmModelFile, "glm-4");
|
|
132
|
+
console.log(`[sync-keys] Created ${glmModelFile} (default: glm-4)`);
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const glmBaseUrlFile = join(KEYS_DIR, "glm-base-url.txt");
|
|
136
|
+
if (!existsSync(glmBaseUrlFile)) {
|
|
137
|
+
writeFileSync(glmBaseUrlFile, "https://api.z.ai/api/v1");
|
|
138
|
+
console.log(`[sync-keys] Created ${glmBaseUrlFile} (default: z.ai)`);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// MiniMax defaults (OpenAI-compatible API)
|
|
142
|
+
const minimaxModelFile = join(KEYS_DIR, "minimax-model.txt");
|
|
143
|
+
if (!existsSync(minimaxModelFile)) {
|
|
144
|
+
writeFileSync(minimaxModelFile, "MiniMax-M2.7");
|
|
145
|
+
console.log(`[sync-keys] Created ${minimaxModelFile} (default: MiniMax-M2.7)`);
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const minimaxBaseUrlFile = join(KEYS_DIR, "minimax-base-url.txt");
|
|
149
|
+
if (!existsSync(minimaxBaseUrlFile)) {
|
|
150
|
+
writeFileSync(minimaxBaseUrlFile, "https://api.minimax.io/v1");
|
|
151
|
+
console.log(`[sync-keys] Created ${minimaxBaseUrlFile} (default: api.minimax.io/v1 OpenAI-compatible)`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* Sync all keys from pi.dev to keys directory
|
|
157
|
+
*/
|
|
158
|
+
export function syncAllKeys(): void {
|
|
159
|
+
console.log("=== Sync Keys from pi.dev ===");
|
|
160
|
+
console.log(`Keys directory: ${KEYS_DIR}`);
|
|
161
|
+
|
|
162
|
+
// Ensure keys directory exists
|
|
163
|
+
if (!existsSync(KEYS_DIR)) {
|
|
164
|
+
mkdirSync(KEYS_DIR, { recursive: true });
|
|
165
|
+
console.log(`[sync-keys] Created keys directory`);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Sync each key
|
|
169
|
+
let synced = 0;
|
|
170
|
+
for (const [provider, filename] of Object.entries(KEY_MAPPINGS)) {
|
|
171
|
+
if (syncKey(provider, filename)) {
|
|
172
|
+
synced++;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Create default configs for missing required keys
|
|
177
|
+
createDefaultConfigs();
|
|
178
|
+
|
|
179
|
+
console.log(`\n=== Done: ${synced} key(s) synced ===`);
|
|
180
|
+
console.log("\nNext steps:");
|
|
181
|
+
console.log("1. Add PLANNER_API_KEY manually if using OpenAI as planner:");
|
|
182
|
+
console.log(" echo 'sk-xxx' > ~/.pi-harness-runtime/keys/planner-api-key.txt");
|
|
183
|
+
console.log("2. Restart the daemon:");
|
|
184
|
+
console.log(" bun run harness/langchain/run.ts --daemon");
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Auto-run if executed directly
|
|
188
|
+
syncAllKeys();
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { getLatestSession, getVisibleMessages, classifyMessage } from '../packages/codex-watcher/dist/src/index.js';
|
|
3
|
+
|
|
4
|
+
const session = getLatestSession();
|
|
5
|
+
console.log('Latest session:', session?.id, session?.threadName);
|
|
6
|
+
|
|
7
|
+
if (session) {
|
|
8
|
+
console.log('Rollout path:', session.rolloutPath);
|
|
9
|
+
const messages = await getVisibleMessages(session.rolloutPath, { limit: 10 });
|
|
10
|
+
console.log('Total messages:', messages.length);
|
|
11
|
+
|
|
12
|
+
const recentMsgs = messages.slice(-10);
|
|
13
|
+
for (const msg of recentMsgs) {
|
|
14
|
+
const cls = classifyMessage(msg.text);
|
|
15
|
+
console.log(` [${msg.role}] ${cls}: "${msg.text.slice(0, 80)}..."`);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Check for plan messages
|
|
19
|
+
const planMessages = recentMsgs.filter((m: { text: string }) => classifyMessage(m.text) === 'plan');
|
|
20
|
+
console.log('\nPlan messages found:', planMessages.length);
|
|
21
|
+
} else {
|
|
22
|
+
console.log('No active session found');
|
|
23
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { ChatOpenAI } from "@langchain/openai";
|
|
3
|
+
|
|
4
|
+
const model = new ChatOpenAI({
|
|
5
|
+
model: "gpt-4o-mini",
|
|
6
|
+
apiKey: process.env.PLANNER_API_KEY,
|
|
7
|
+
temperature: 0.2,
|
|
8
|
+
});
|
|
9
|
+
|
|
10
|
+
console.log("Testing OpenAI with LangChain...");
|
|
11
|
+
|
|
12
|
+
const response = await model.invoke("Say hello");
|
|
13
|
+
console.log("Success:", response.content);
|
|
14
|
+
process.exit(0);
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import { NotificationCenter } from '../packages/notification/dist/notification-center.js';
|
|
3
|
+
import type { NotificationContext } from '../packages/notification/dist/types.js';
|
|
4
|
+
|
|
5
|
+
const nc = new NotificationCenter({
|
|
6
|
+
channels: [
|
|
7
|
+
{
|
|
8
|
+
id: "telegram",
|
|
9
|
+
type: "telegram",
|
|
10
|
+
enabled: true,
|
|
11
|
+
config: {
|
|
12
|
+
botToken: "8998964845:AAGD2h8wWDRCc4EOY_ChZNuQLmHqmEB6sak",
|
|
13
|
+
chatId: "8833690740",
|
|
14
|
+
parseMode: "HTML" as const // Use HTML mode instead of MarkdownV2
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.log("Sending test Telegram notification...");
|
|
21
|
+
|
|
22
|
+
const context: NotificationContext = {
|
|
23
|
+
jobId: "test-123",
|
|
24
|
+
requirement: "Testing Telegram notification",
|
|
25
|
+
taskTitle: "Test"
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
nc.notify("HumanReviewNeeded", context).then((results) => {
|
|
29
|
+
console.log("Results:", JSON.stringify(results, null, 2));
|
|
30
|
+
process.exit(0);
|
|
31
|
+
}).catch((e: unknown) => {
|
|
32
|
+
console.error("Error:", e);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
});
|