profclaw 0.0.1-beta.1 → 0.0.1-beta.2
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 +1 -1
- package/dist/adapters/openclaw.js +1 -1
- package/dist/agents/executor.js +38 -6
- package/dist/auth/auth-service.js +8 -6
- package/dist/auth/device-identity.js +7 -5
- package/dist/auth/github-oauth.js +3 -1
- package/dist/auth/pairing-codes.js +6 -4
- package/dist/browser/service.js +5 -3
- package/dist/chat/execution/guardrails.js +3 -1
- package/dist/chat/execution/workflows/executor.js +4 -2
- package/dist/chat/memory.js +3 -1
- package/dist/chat/proactive/index.js +13 -11
- package/dist/chat/tools.js +8 -7
- package/dist/cli/commands/auth.js +22 -13
- package/dist/cli/commands/onboard.js +248 -59
- package/dist/cli/commands/setup.js +180 -104
- package/dist/cron/issue-poller.js +1 -1
- package/dist/hooks/agent-webhook.js +10 -7
- package/dist/hooks/prompt-submit.js +5 -6
- package/dist/hooks/session-end.js +10 -6
- package/dist/hooks/tool-use.js +9 -6
- package/dist/integrations/github-ticket-sync.js +8 -6
- package/dist/integrations/github.js +8 -6
- package/dist/integrations/jira.js +5 -3
- package/dist/mcp/server.js +12 -9
- package/dist/memory/experience-store.js +15 -14
- package/dist/notifications/slack.js +4 -2
- package/dist/providers/types.d.ts +2 -2
- package/dist/queue/failure-handler.js +15 -13
- package/dist/queue/index.js +6 -4
- package/dist/queue/memory-queue.js +23 -27
- package/dist/queue/task-queue.js +18 -22
- package/dist/routes/agents.js +3 -1
- package/dist/routes/auth.js +11 -9
- package/dist/routes/devices.js +17 -15
- package/dist/routes/gateway.js +3 -1
- package/dist/routes/hooks.js +7 -5
- package/dist/routes/import.js +10 -8
- package/dist/routes/labels.js +11 -9
- package/dist/routes/oobe.js +8 -6
- package/dist/routes/openapi.js +1 -1
- package/dist/routes/projects.js +27 -25
- package/dist/routes/settings.js +7 -5
- package/dist/routes/setup.js +12 -11
- package/dist/routes/slack.js +28 -27
- package/dist/routes/stats.js +6 -4
- package/dist/routes/summaries.js +4 -3
- package/dist/routes/sync.js +7 -5
- package/dist/routes/tasks.js +10 -8
- package/dist/routes/tickets.js +26 -26
- package/dist/routes/tokens.js +5 -3
- package/dist/routes/users.js +14 -12
- package/dist/routes/webhooks.js +5 -3
- package/dist/settings/index.js +3 -1
- package/dist/storage/index.d.ts +2 -1
- package/dist/storage/index.js +9 -4
- package/dist/storage/libsql.js +29 -21
- package/dist/storage/schema.d.ts +107 -46
- package/dist/summaries/storage.js +3 -1
- package/dist/tickets/index.js +10 -8
- package/dist/utils/circuit-breaker.js +10 -5
- package/dist/utils/logger.d.ts +5 -1
- package/dist/utils/logger.js +23 -7
- package/package.json +4 -3
- package/ui/dist/assets/{ActivityView-CkPgKhwm.js → ActivityView-DIPQSJ_d.js} +1 -1
- package/ui/dist/assets/{AgentList-C3SVdeEz.js → AgentList-CqyaYrcq.js} +1 -1
- package/ui/dist/assets/{AnalyticsDashboard-DVU--vlP.js → AnalyticsDashboard-C-mjuGHT.js} +1 -1
- package/ui/dist/assets/{AreaChart-B5qMEGWj.js → AreaChart-CfYWmbtr.js} +1 -1
- package/ui/dist/assets/{CartesianChart-B50bcUJi.js → CartesianChart-BaQ3It0c.js} +1 -1
- package/ui/dist/assets/{ChatView-BZFJs7w_.js → ChatView-DxxQy6pl.js} +1 -1
- package/ui/dist/assets/CostsDashboard-CDBBcGkg.js +1 -0
- package/ui/dist/assets/{EstimateSelect-CLpB4NQO.js → EstimateSelect-CDjf5qKl.js} +1 -1
- package/ui/dist/assets/{FloatingChatbot-CBzBY9a0.js → FloatingChatbot-CZHjvJIe.js} +1 -1
- package/ui/dist/assets/{InviteCodeManagement-DsbdPa6W.js → InviteCodeManagement-DTm-IPTm.js} +1 -1
- package/ui/dist/assets/{ProjectDetail-BEM3tFXg.js → ProjectDetail-DlYUcOss.js} +1 -1
- package/ui/dist/assets/{ProjectIcon-CN1FmFAk.js → ProjectIcon-BMRpnM04.js} +1 -1
- package/ui/dist/assets/{ProjectList-DSDaNhxQ.js → ProjectList-D85TN0i0.js} +1 -1
- package/ui/dist/assets/{Settings-dPVcqC_d.js → Settings-CgPqzUvj.js} +3 -3
- package/ui/dist/assets/{StatusIndicator-DA3NAo_b.js → StatusIndicator-yig0uZEA.js} +1 -1
- package/ui/dist/assets/{SummaryDetail-Bjnf9lT8.js → SummaryDetail-CwLAfHgJ.js} +1 -1
- package/ui/dist/assets/{SummaryList-ENwKDBKW.js → SummaryList-BvS5Idnu.js} +1 -1
- package/ui/dist/assets/{TaskDetail-DnwG6MzB.js → TaskDetail-zarC1fOt.js} +1 -1
- package/ui/dist/assets/{TaskList-D9Ug_HiV.js → TaskList-CyJq3ANE.js} +1 -1
- package/ui/dist/assets/{TicketBoard-CviH1571.js → TicketBoard-BlWr3-iH.js} +1 -1
- package/ui/dist/assets/{TicketDetail-8Jk8O-33.js → TicketDetail-DmqWKj2W.js} +1 -1
- package/ui/dist/assets/{TicketList-B-iV4rRA.js → TicketList-Scj4pMWa.js} +1 -1
- package/ui/dist/assets/{UserManagement-CPZ8s7s2.js → UserManagement-BH7uG7dw.js} +1 -1
- package/ui/dist/assets/{ViewSwitcher-BUyOOWDI.js → ViewSwitcher-3HzZUdWn.js} +1 -1
- package/ui/dist/assets/{alert-dialog-BOmnTkN-.js → alert-dialog-DWPb2IfQ.js} +1 -1
- package/ui/dist/assets/{archive-D5my9zOG.js → archive-CGck7gxR.js} +1 -1
- package/ui/dist/assets/{badge-B4ov81_m.js → badge-DEmc3Z_l.js} +1 -1
- package/ui/dist/assets/{brain-C53ElFLD.js → brain-CfFdLVqb.js} +1 -1
- package/ui/dist/assets/{bug-D0TJoCYn.js → bug-DqSGPUUE.js} +1 -1
- package/ui/dist/assets/{calendar-BkWIhKa1.js → calendar-BuZ4zbPW.js} +1 -1
- package/ui/dist/assets/{chevron-up-BRTtndUZ.js → chevron-up-DcJ4LL_N.js} +1 -1
- package/ui/dist/assets/{circle-x-BN89YhbS.js → circle-x-C78PNZjF.js} +1 -1
- package/ui/dist/assets/{constants-fc7TFI7u.js → constants-DhDjZe4P.js} +1 -1
- package/ui/dist/assets/{cpu-B41x1-vV.js → cpu-Ck6AoG8c.js} +1 -1
- package/ui/dist/assets/{database-D9Cnfmzj.js → database-CA2w8Lvt.js} +1 -1
- package/ui/dist/assets/{dialog-DrWB4EYD.js → dialog-BOdGWhgE.js} +1 -1
- package/ui/dist/assets/{ellipsis-NuUWekvu.js → ellipsis-FhHKRbfl.js} +1 -1
- package/ui/dist/assets/{ellipsis-vertical-BueMfuCw.js → ellipsis-vertical-CO0UqE4-.js} +1 -1
- package/ui/dist/assets/{file-code-HR9829Jc.js → file-code-ChnhYYj1.js} +1 -1
- package/ui/dist/assets/{folder-open-C_7oYEqe.js → folder-open-CHwA1-ve.js} +1 -1
- package/ui/dist/assets/{funnel-B5gmNXGf.js → funnel-ByEjRFNB.js} +1 -1
- package/ui/dist/assets/{git-branch-BRMiJmV3.js → git-branch-GTOPQgU4.js} +1 -1
- package/ui/dist/assets/{git-commit-horizontal-CXOUQeJI.js → git-commit-horizontal-F5M84Kut.js} +1 -1
- package/ui/dist/assets/{globe-CCspjvus.js → globe-CQWfr7hT.js} +1 -1
- package/ui/dist/assets/{hash-g3102kPC.js → hash-nKC9gtLg.js} +1 -1
- package/ui/dist/assets/{history-CNqcBBrV.js → history-DfFSA9xJ.js} +1 -1
- package/ui/dist/assets/{index-kb4AJXUB.js → index--JkIxVXb.js} +3 -3
- package/ui/dist/assets/index-Ca3vk7Gq.js +1 -0
- package/ui/dist/assets/{index-C9jNQXzL.js → index-DHGvP9mp.js} +1 -1
- package/ui/dist/assets/index-DeI8lKRR.js +1 -0
- package/ui/dist/assets/{index-DURTouJI.js → index-Z4-RtZcs.js} +1 -1
- package/ui/dist/assets/{index-CEZ6R2Uw.js → index-a4Fxq0Hb.js} +1 -1
- package/ui/dist/assets/{layers-CLXiHN6o.js → layers-DFeLExSa.js} +1 -1
- package/ui/dist/assets/{layout-dashboard-B07MFhBs.js → layout-dashboard-WmgjMhWF.js} +1 -1
- package/ui/dist/assets/{lightbulb-B2dgG5ks.js → lightbulb-Bo8hEr7B.js} +1 -1
- package/ui/dist/assets/{link-2-BxNmr9hL.js → link-2-YqrpQXBH.js} +1 -1
- package/ui/dist/assets/{markdown-renderer-CjU6hBcW.js → markdown-renderer-Croje6Xe.js} +1 -1
- package/ui/dist/assets/{message-square-Bf2-CVbt.js → message-square-CD0H5hot.js} +1 -1
- package/ui/dist/assets/{pencil-D096Ey62.js → pencil-DpFnj5dn.js} +1 -1
- package/ui/dist/assets/{play-DfdcSI3x.js → play-DVgea_jT.js} +1 -1
- package/ui/dist/assets/{popover-BV0QJDQq.js → popover-JXecfWG5.js} +1 -1
- package/ui/dist/assets/{progress-DjPEDJfI.js → progress-C1ghf1Fu.js} +1 -1
- package/ui/dist/assets/{rocket-CPsTc-5G.js → rocket-BFxPYGx9.js} +1 -1
- package/ui/dist/assets/{select-LsO16slr.js → select-MADP8m6Q.js} +1 -1
- package/ui/dist/assets/{send-BDYBZDUZ.js → send-eYnW_7n-.js} +1 -1
- package/ui/dist/assets/{server-B3k6noce.js → server-CPMaysH8.js} +1 -1
- package/ui/dist/assets/{settings-2-Cu4xTjhG.js → settings-2-scXUOuE_.js} +1 -1
- package/ui/dist/assets/{sheet-BScLnPKX.js → sheet-r6NSOxi-.js} +1 -1
- package/ui/dist/assets/{shield-check-CQqkwufI.js → shield-check-PEr7nmVw.js} +1 -1
- package/ui/dist/assets/{shield-off-ZFruH9KO.js → shield-off-CLtXio62.js} +1 -1
- package/ui/dist/assets/{skeleton-CtkIA_MU.js → skeleton-C9oEzNlU.js} +1 -1
- package/ui/dist/assets/{smartphone-DnoksVkc.js → smartphone-DusFfY0U.js} +1 -1
- package/ui/dist/assets/{square-uD9ZHMfW.js → square-e1yxB2eR.js} +1 -1
- package/ui/dist/assets/{switch-MQPnwGJK.js → switch-tNs0n-kz.js} +1 -1
- package/ui/dist/assets/{table-B8cqlywA.js → table-CXxtLicg.js} +1 -1
- package/ui/dist/assets/{tag-wEJQRWlV.js → tag-tAwMmQ9G.js} +1 -1
- package/ui/dist/assets/{textarea-D5LJCOGl.js → textarea-BjiEeIWh.js} +1 -1
- package/ui/dist/assets/{timer-mbGHegmr.js → timer-Vel1N3RP.js} +1 -1
- package/ui/dist/assets/{tooltip-Df1CunSp.js → tooltip-ZMwtfr1J.js} +1 -1
- package/ui/dist/assets/{trash-2-B4oAXsX-.js → trash-2-eM-CNwsZ.js} +1 -1
- package/ui/dist/assets/{trending-up-BGWxvlmZ.js → trending-up-BGafmjRo.js} +1 -1
- package/ui/dist/assets/{wand-sparkles-CZy4xvL3.js → wand-sparkles-DPvcd9Pi.js} +1 -1
- package/ui/dist/assets/{wrench-ByZkjO6m.js → wrench-B8s3zYVV.js} +1 -1
- package/ui/dist/index.html +1 -1
- package/ui/dist/assets/CostsDashboard-ChfH8BlG.js +0 -1
- package/ui/dist/assets/index-27mTPKuh.js +0 -1
- package/ui/dist/assets/index-BMx3fH-e.js +0 -1
package/README.md
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
</p>
|
|
12
12
|
|
|
13
13
|
<p align="center">
|
|
14
|
-
<a href="https://profclaw.
|
|
14
|
+
<a href="https://profclaw.ai/docs"><b>Docs</b></a> ·
|
|
15
15
|
<a href="https://github.com/profclaw/profclaw/issues"><b>Report Bug</b></a> ·
|
|
16
16
|
<a href="https://discord.gg/profclaw"><b>Discord</b></a>
|
|
17
17
|
</p>
|
package/dist/agents/executor.js
CHANGED
|
@@ -42,6 +42,38 @@ function getStringArray(value) {
|
|
|
42
42
|
function toToolArgs(input) {
|
|
43
43
|
return getRecord(input) ?? {};
|
|
44
44
|
}
|
|
45
|
+
function getUsageInputTokens(usage) {
|
|
46
|
+
const usageRecord = getRecord(usage);
|
|
47
|
+
if (!usageRecord)
|
|
48
|
+
return 0;
|
|
49
|
+
const inputTokens = usageRecord.inputTokens;
|
|
50
|
+
if (typeof inputTokens === "number")
|
|
51
|
+
return inputTokens;
|
|
52
|
+
const promptTokens = usageRecord.promptTokens;
|
|
53
|
+
return typeof promptTokens === "number" ? promptTokens : 0;
|
|
54
|
+
}
|
|
55
|
+
function getUsageOutputTokens(usage) {
|
|
56
|
+
const usageRecord = getRecord(usage);
|
|
57
|
+
if (!usageRecord)
|
|
58
|
+
return 0;
|
|
59
|
+
const outputTokens = usageRecord.outputTokens;
|
|
60
|
+
if (typeof outputTokens === "number")
|
|
61
|
+
return outputTokens;
|
|
62
|
+
const completionTokens = usageRecord.completionTokens;
|
|
63
|
+
return typeof completionTokens === "number" ? completionTokens : 0;
|
|
64
|
+
}
|
|
65
|
+
function getToolCallInput(toolCall) {
|
|
66
|
+
const toolCallRecord = getRecord(toolCall);
|
|
67
|
+
if (!toolCallRecord)
|
|
68
|
+
return {};
|
|
69
|
+
return toToolArgs(toolCallRecord.input ?? toolCallRecord.args);
|
|
70
|
+
}
|
|
71
|
+
function getToolResultOutput(toolResult) {
|
|
72
|
+
const toolResultRecord = getRecord(toolResult);
|
|
73
|
+
if (!toolResultRecord)
|
|
74
|
+
return undefined;
|
|
75
|
+
return toolResultRecord.output ?? toolResultRecord.result;
|
|
76
|
+
}
|
|
45
77
|
function toContextProject(value) {
|
|
46
78
|
const id = getString(value.id);
|
|
47
79
|
const key = getString(value.key);
|
|
@@ -164,8 +196,8 @@ export class AgentExecutor extends EventEmitter {
|
|
|
164
196
|
this.state.currentStep++;
|
|
165
197
|
this.state.updatedAt = Date.now();
|
|
166
198
|
// Track token budget (AI SDK v6 uses inputTokens/outputTokens)
|
|
167
|
-
const stepInput = step.usage
|
|
168
|
-
const stepOutput = step.usage
|
|
199
|
+
const stepInput = getUsageInputTokens(step.usage);
|
|
200
|
+
const stepOutput = getUsageOutputTokens(step.usage);
|
|
169
201
|
const tokensUsed = stepInput + stepOutput;
|
|
170
202
|
this.state.usedBudget += tokensUsed;
|
|
171
203
|
this.state.inputTokensUsed += stepInput;
|
|
@@ -179,14 +211,14 @@ export class AgentExecutor extends EventEmitter {
|
|
|
179
211
|
const record = {
|
|
180
212
|
id: tc.toolCallId ?? randomUUID(),
|
|
181
213
|
name: tc.toolName,
|
|
182
|
-
args:
|
|
214
|
+
args: getToolCallInput(tc),
|
|
183
215
|
status: "pending",
|
|
184
216
|
startedAt: Date.now(),
|
|
185
217
|
};
|
|
186
218
|
// Find the matching tool result
|
|
187
219
|
const tr = (step.toolResults ?? []).find((toolResult) => toolResult.toolCallId === tc.toolCallId);
|
|
188
220
|
if (tr) {
|
|
189
|
-
record.result = tr
|
|
221
|
+
record.result = getToolResultOutput(tr);
|
|
190
222
|
record.completedAt = Date.now();
|
|
191
223
|
// Check if the tool result indicates a failure
|
|
192
224
|
if (typeof record.result === "object" && record.result !== null) {
|
|
@@ -243,8 +275,8 @@ export class AgentExecutor extends EventEmitter {
|
|
|
243
275
|
// Update budget from total usage (AI SDK v6 uses inputTokens/outputTokens)
|
|
244
276
|
const totalUsage = result.totalUsage;
|
|
245
277
|
if (totalUsage) {
|
|
246
|
-
const totalInput = totalUsage
|
|
247
|
-
const totalOutput = totalUsage
|
|
278
|
+
const totalInput = getUsageInputTokens(totalUsage);
|
|
279
|
+
const totalOutput = getUsageOutputTokens(totalUsage);
|
|
248
280
|
// totalUsage is the authoritative sum; overwrite our step-by-step estimate
|
|
249
281
|
this.state.usedBudget = totalInput + totalOutput;
|
|
250
282
|
this.state.inputTokensUsed = totalInput;
|
|
@@ -13,6 +13,8 @@ import { getDb } from '../storage/index.js';
|
|
|
13
13
|
import { users, sessions, oauthAccounts, userPreferences, githubTokens, } from '../storage/schema.js';
|
|
14
14
|
import { getGitHubOAuthConfig, getSettingsRaw } from '../settings/index.js';
|
|
15
15
|
import { hashPassword, verifyPassword as verifyPw } from './password.js';
|
|
16
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
17
|
+
const log = createContextualLogger('AuthService');
|
|
16
18
|
/**
|
|
17
19
|
* Hash a session token for secure storage.
|
|
18
20
|
* Uses SHA256 which is fast and sufficient for random 32-byte tokens.
|
|
@@ -42,7 +44,7 @@ async function upgradePasswordHash(userId, password) {
|
|
|
42
44
|
.update(users)
|
|
43
45
|
.set({ passwordHash: newHash, updatedAt: new Date() })
|
|
44
46
|
.where(eq(users.id, userId));
|
|
45
|
-
|
|
47
|
+
log.info(`Upgraded password hash to scrypt for user ${userId}`);
|
|
46
48
|
}
|
|
47
49
|
// SESSION MANAGEMENT
|
|
48
50
|
export async function createSession(userId, userAgent, ipAddress) {
|
|
@@ -197,7 +199,7 @@ export async function signInWithEmail(email, password) {
|
|
|
197
199
|
// Transparently upgrade legacy SHA256 hash to scrypt
|
|
198
200
|
if (needsUpgrade) {
|
|
199
201
|
upgradePasswordHash(user.id, password).catch((err) => {
|
|
200
|
-
|
|
202
|
+
log.error('Failed to upgrade password hash', err instanceof Error ? err : new Error(String(err)));
|
|
201
203
|
});
|
|
202
204
|
}
|
|
203
205
|
// Check if suspended
|
|
@@ -258,7 +260,7 @@ export async function exchangeGitHubCode(code) {
|
|
|
258
260
|
});
|
|
259
261
|
const data = (await response.json());
|
|
260
262
|
if (data.error || !data.access_token) {
|
|
261
|
-
|
|
263
|
+
log.error('GitHub token exchange failed', { error: data.error });
|
|
262
264
|
return null;
|
|
263
265
|
}
|
|
264
266
|
return {
|
|
@@ -275,7 +277,7 @@ export async function getGitHubUser(accessToken) {
|
|
|
275
277
|
},
|
|
276
278
|
});
|
|
277
279
|
if (!response.ok) {
|
|
278
|
-
|
|
280
|
+
log.error('Failed to fetch GitHub user', { status: response.status });
|
|
279
281
|
return null;
|
|
280
282
|
}
|
|
281
283
|
return response.json();
|
|
@@ -293,7 +295,7 @@ export async function getGitHubPrimaryEmail(accessToken) {
|
|
|
293
295
|
},
|
|
294
296
|
});
|
|
295
297
|
if (!response.ok) {
|
|
296
|
-
|
|
298
|
+
log.error('Failed to fetch GitHub emails', { status: response.status });
|
|
297
299
|
return null;
|
|
298
300
|
}
|
|
299
301
|
const emails = (await response.json());
|
|
@@ -305,7 +307,7 @@ export async function getGitHubPrimaryEmail(accessToken) {
|
|
|
305
307
|
return primaryEmail || null;
|
|
306
308
|
}
|
|
307
309
|
catch (error) {
|
|
308
|
-
|
|
310
|
+
log.error('Error fetching GitHub emails', error instanceof Error ? error : new Error(String(error)));
|
|
309
311
|
return null;
|
|
310
312
|
}
|
|
311
313
|
}
|
|
@@ -13,6 +13,8 @@ import { generateKeyPairSync, createSign, createVerify, createHash, randomUUID,
|
|
|
13
13
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, chmodSync } from 'fs';
|
|
14
14
|
import { join } from 'path';
|
|
15
15
|
import { homedir } from 'os';
|
|
16
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
17
|
+
const log = createContextualLogger('DeviceIdentity');
|
|
16
18
|
/**
|
|
17
19
|
* Default identity file path
|
|
18
20
|
*/
|
|
@@ -77,10 +79,10 @@ export function loadOrCreateDeviceIdentity(identityDir = DEFAULT_IDENTITY_DIR, o
|
|
|
77
79
|
const data = JSON.parse(content);
|
|
78
80
|
// Validate version
|
|
79
81
|
if (data.version !== 1) {
|
|
80
|
-
|
|
82
|
+
log.warn('Unknown version, creating new identity', { version: data.version });
|
|
81
83
|
}
|
|
82
84
|
else {
|
|
83
|
-
|
|
85
|
+
log.info('Loaded existing identity', { deviceIdPrefix: data.deviceId.slice(0, 8) });
|
|
84
86
|
return {
|
|
85
87
|
deviceId: data.deviceId,
|
|
86
88
|
publicKeyPem: data.publicKeyPem,
|
|
@@ -92,11 +94,11 @@ export function loadOrCreateDeviceIdentity(identityDir = DEFAULT_IDENTITY_DIR, o
|
|
|
92
94
|
}
|
|
93
95
|
}
|
|
94
96
|
catch (error) {
|
|
95
|
-
|
|
97
|
+
log.warn('Failed to load identity, creating new one', { error: error instanceof Error ? error.message : String(error) });
|
|
96
98
|
}
|
|
97
99
|
}
|
|
98
100
|
// Create new identity
|
|
99
|
-
|
|
101
|
+
log.info('Creating new device identity');
|
|
100
102
|
const { publicKey, privateKey } = generateKeyPair();
|
|
101
103
|
const deviceId = deriveDeviceId(publicKey);
|
|
102
104
|
const identity = {
|
|
@@ -114,7 +116,7 @@ export function loadOrCreateDeviceIdentity(identityDir = DEFAULT_IDENTITY_DIR, o
|
|
|
114
116
|
...identity,
|
|
115
117
|
};
|
|
116
118
|
writeSecureFile(filePath, JSON.stringify(fileData, null, 2));
|
|
117
|
-
|
|
119
|
+
log.info('Created new identity', { deviceIdPrefix: deviceId.slice(0, 8) });
|
|
118
120
|
return identity;
|
|
119
121
|
}
|
|
120
122
|
/**
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { getGitHubOAuthConfig } from '../settings/index.js';
|
|
2
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
3
|
+
const log = createContextualLogger('OAuth');
|
|
2
4
|
/**
|
|
3
5
|
* Redirect user to GitHub for OAuth
|
|
4
6
|
*/
|
|
@@ -52,7 +54,7 @@ export async function handleGitHubCallback(c) {
|
|
|
52
54
|
});
|
|
53
55
|
}
|
|
54
56
|
catch (error) {
|
|
55
|
-
|
|
57
|
+
log.error('GitHub callback error', error instanceof Error ? error : new Error(String(error)));
|
|
56
58
|
return c.json({ error: 'Internal server error' }, 500);
|
|
57
59
|
}
|
|
58
60
|
}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { randomBytes, randomUUID } from 'crypto';
|
|
14
14
|
import { getStorage } from '../storage/index.js';
|
|
15
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
16
|
+
const log = createContextualLogger('PairingCodes');
|
|
15
17
|
// Code generation alphabet (no ambiguous chars: 0O1I)
|
|
16
18
|
const PAIRING_CODE_ALPHABET = 'ABCDEFGHJKLMNPQRSTUVWXYZ23456789';
|
|
17
19
|
const PAIRING_CODE_LENGTH = 8;
|
|
@@ -117,7 +119,7 @@ export async function requestPairingCode(params) {
|
|
|
117
119
|
now,
|
|
118
120
|
now,
|
|
119
121
|
]);
|
|
120
|
-
|
|
122
|
+
log.info('Created pairing code', { code, requesterId: params.requesterId });
|
|
121
123
|
return {
|
|
122
124
|
code,
|
|
123
125
|
expiresAt: new Date(expiresAt * 1000),
|
|
@@ -133,7 +135,7 @@ export async function approvePairingCode(params) {
|
|
|
133
135
|
const rows = await storage.query(`SELECT * FROM pairing_requests
|
|
134
136
|
WHERE code = ? AND status = 'pending' AND expires_at > ?`, [params.code.toUpperCase(), Math.floor(Date.now() / 1000)]);
|
|
135
137
|
if (rows.length === 0) {
|
|
136
|
-
|
|
138
|
+
log.info('Code not found or expired', { code: params.code });
|
|
137
139
|
return null;
|
|
138
140
|
}
|
|
139
141
|
const row = rows[0];
|
|
@@ -143,7 +145,7 @@ export async function approvePairingCode(params) {
|
|
|
143
145
|
await storage.execute(`UPDATE pairing_requests
|
|
144
146
|
SET status = 'approved', resolved_by = ?, resolved_at = ?, token = ?
|
|
145
147
|
WHERE id = ?`, [params.approvedBy, now, token, row.id]);
|
|
146
|
-
|
|
148
|
+
log.info('Code approved', { code: params.code, approvedBy: params.approvedBy });
|
|
147
149
|
return {
|
|
148
150
|
request: {
|
|
149
151
|
id: row.id,
|
|
@@ -175,7 +177,7 @@ export async function rejectPairingCode(params) {
|
|
|
175
177
|
await storage.execute(`UPDATE pairing_requests
|
|
176
178
|
SET status = 'rejected', resolved_by = ?, resolved_at = ?
|
|
177
179
|
WHERE code = ? AND status = 'pending'`, [params.rejectedBy, now, params.code.toUpperCase()]);
|
|
178
|
-
|
|
180
|
+
log.info('Code rejected', { code: params.code, rejectedBy: params.rejectedBy });
|
|
179
181
|
return true;
|
|
180
182
|
}
|
|
181
183
|
/**
|
package/dist/browser/service.js
CHANGED
|
@@ -8,6 +8,8 @@ import { chromium } from 'playwright-core';
|
|
|
8
8
|
import { captureSnapshot, formatSnapshotResponse } from './snapshot.js';
|
|
9
9
|
import { searchSnapshot, formatSearchResponse } from './search.js';
|
|
10
10
|
import { getRefTracker, resetRefTracker, clearAllTrackers } from './refs.js';
|
|
11
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
12
|
+
const log = createContextualLogger('Browser');
|
|
11
13
|
// Default configuration
|
|
12
14
|
const DEFAULT_CONFIG = {
|
|
13
15
|
headless: process.env.BROWSER_HEADLESS !== 'false',
|
|
@@ -34,7 +36,7 @@ class BrowserService {
|
|
|
34
36
|
*/
|
|
35
37
|
async ensureBrowser() {
|
|
36
38
|
if (!this.browser || !this.browser.isConnected()) {
|
|
37
|
-
|
|
39
|
+
log.info('Launching browser');
|
|
38
40
|
this.browser = await chromium.launch({
|
|
39
41
|
headless: this.config.headless,
|
|
40
42
|
executablePath: this.config.executablePath,
|
|
@@ -48,7 +50,7 @@ class BrowserService {
|
|
|
48
50
|
viewport: { width: 1280, height: 720 },
|
|
49
51
|
userAgent: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36',
|
|
50
52
|
});
|
|
51
|
-
|
|
53
|
+
log.info('Browser launched');
|
|
52
54
|
}
|
|
53
55
|
return this.browser;
|
|
54
56
|
}
|
|
@@ -312,7 +314,7 @@ class BrowserService {
|
|
|
312
314
|
this.browser = null;
|
|
313
315
|
}
|
|
314
316
|
clearAllTrackers();
|
|
315
|
-
|
|
317
|
+
log.info('Browser closed');
|
|
316
318
|
}
|
|
317
319
|
/**
|
|
318
320
|
* Check if browser is running
|
|
@@ -9,6 +9,8 @@
|
|
|
9
9
|
* 8.3 Safety Bounds
|
|
10
10
|
* 8.4 Quality Scoring
|
|
11
11
|
*/
|
|
12
|
+
import { createContextualLogger } from '../../utils/logger.js';
|
|
13
|
+
const log = createContextualLogger('Guardrails');
|
|
12
14
|
// 8.1 Output Validation
|
|
13
15
|
const MAX_RESPONSE_CHARS = 50_000;
|
|
14
16
|
const STUTTER_THRESHOLD = 3; // same sentence repeated 3+ times
|
|
@@ -533,7 +535,7 @@ export async function runGuardrails(response, toolCalls, context) {
|
|
|
533
535
|
}
|
|
534
536
|
}
|
|
535
537
|
if (!passed) {
|
|
536
|
-
|
|
538
|
+
log.warn('Guardrail check failed', {
|
|
537
539
|
validationIssues: validation.issues.length,
|
|
538
540
|
hallucinationFlags: hallucination.flags.length,
|
|
539
541
|
safetyBlocked: safety.blocked.length,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { createContextualLogger } from '../../../utils/logger.js';
|
|
2
|
+
const log = createContextualLogger('Workflow');
|
|
1
3
|
// Map from executionId -> AbortController for cancellation
|
|
2
4
|
const activeExecutions = new Map();
|
|
3
5
|
/**
|
|
@@ -231,7 +233,7 @@ export class WorkflowExecutor {
|
|
|
231
233
|
]);
|
|
232
234
|
}
|
|
233
235
|
catch (error) {
|
|
234
|
-
|
|
236
|
+
log.error('Step timed out', error instanceof Error ? error : new Error(String(error)), { stepId: step.id });
|
|
235
237
|
return {
|
|
236
238
|
success: false,
|
|
237
239
|
error: {
|
|
@@ -245,7 +247,7 @@ export class WorkflowExecutor {
|
|
|
245
247
|
return await context.toolExecutor(step.tool, params);
|
|
246
248
|
}
|
|
247
249
|
catch (error) {
|
|
248
|
-
|
|
250
|
+
log.error('Step threw error', error instanceof Error ? error : new Error(String(error)), { stepId: step.id });
|
|
249
251
|
return {
|
|
250
252
|
success: false,
|
|
251
253
|
error: {
|
package/dist/chat/memory.js
CHANGED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* - Sliding window with importance scoring
|
|
13
13
|
*/
|
|
14
14
|
import { MODEL_CATALOG } from '../providers/core/models.js';
|
|
15
|
+
import { createContextualLogger } from '../utils/logger.js';
|
|
16
|
+
const log = createContextualLogger('Memory');
|
|
15
17
|
export const DEFAULT_MEMORY_CONFIG = {
|
|
16
18
|
compactThreshold: 0.7,
|
|
17
19
|
preserveRecentCount: 6, // Keep last 3 exchanges (user + assistant)
|
|
@@ -215,7 +217,7 @@ SUMMARY:`;
|
|
|
215
217
|
}
|
|
216
218
|
catch (error) {
|
|
217
219
|
// Fallback to simple truncation if AI fails
|
|
218
|
-
|
|
220
|
+
log.warn('AI summarization failed, using truncation', { error: error instanceof Error ? error.message : String(error) });
|
|
219
221
|
return `Previous conversation summary (${messages.length} messages): ${messages
|
|
220
222
|
.slice(-3)
|
|
221
223
|
.map((m) => m.content.slice(0, 100))
|
|
@@ -12,6 +12,8 @@ import { randomUUID } from 'node:crypto';
|
|
|
12
12
|
import { EventEmitter } from 'node:events';
|
|
13
13
|
import { freemem, totalmem } from 'node:os';
|
|
14
14
|
import { statfs } from 'node:fs/promises';
|
|
15
|
+
import { createContextualLogger } from '../../utils/logger.js';
|
|
16
|
+
const log = createContextualLogger('Proactive');
|
|
15
17
|
/**
|
|
16
18
|
* Evaluates a simple condition string against a data record.
|
|
17
19
|
* Supports: <key> <op> <value> where op is >, <, >=, <=, ==, !=
|
|
@@ -53,16 +55,16 @@ function executeAction(action, data) {
|
|
|
53
55
|
const message = action.template ? interpolate(action.template, data) : '';
|
|
54
56
|
switch (action.type) {
|
|
55
57
|
case 'notify':
|
|
56
|
-
|
|
58
|
+
log.info('Notify action', { target: action.target ?? 'broadcast', message });
|
|
57
59
|
return `notified ${action.target ?? 'broadcast'}: ${message}`;
|
|
58
60
|
case 'message':
|
|
59
|
-
|
|
61
|
+
log.info('Message action', { target: action.target, message });
|
|
60
62
|
return `message sent to ${action.target}: ${message}`;
|
|
61
63
|
case 'workflow':
|
|
62
|
-
|
|
64
|
+
log.info('Workflow triggered', { workflowId: action.workflowId });
|
|
63
65
|
return `workflow ${action.workflowId} triggered`;
|
|
64
66
|
case 'log':
|
|
65
|
-
|
|
67
|
+
log.info('Log action', { message });
|
|
66
68
|
return `logged: ${message}`;
|
|
67
69
|
}
|
|
68
70
|
}
|
|
@@ -125,7 +127,7 @@ export class TriggerManager {
|
|
|
125
127
|
results.push({ ruleId: rule.id, executed: true, output });
|
|
126
128
|
}
|
|
127
129
|
catch (error) {
|
|
128
|
-
|
|
130
|
+
log.error('TriggerManager action failed', error instanceof Error ? error : new Error(String(error)), { ruleId: rule.id });
|
|
129
131
|
results.push({
|
|
130
132
|
ruleId: rule.id,
|
|
131
133
|
executed: false,
|
|
@@ -402,7 +404,7 @@ export class HealthMonitor extends EventEmitter {
|
|
|
402
404
|
const wasOk = !previous || previous.status === 'healthy';
|
|
403
405
|
const isNowBad = result.status === 'degraded' || result.status === 'down';
|
|
404
406
|
if (wasOk && isNowBad) {
|
|
405
|
-
|
|
407
|
+
log.warn('Health degraded', { service, message: result.message ?? result.status });
|
|
406
408
|
this.emit('degraded', result);
|
|
407
409
|
}
|
|
408
410
|
}
|
|
@@ -414,7 +416,7 @@ export class HealthMonitor extends EventEmitter {
|
|
|
414
416
|
message: `Checker threw: ${error instanceof Error ? error.message : 'Unknown'}`,
|
|
415
417
|
};
|
|
416
418
|
this.latest.set(service, bad);
|
|
417
|
-
|
|
419
|
+
log.error('Health check error', error instanceof Error ? error : new Error(String(error)), { service });
|
|
418
420
|
this.emit('degraded', bad);
|
|
419
421
|
}
|
|
420
422
|
}
|
|
@@ -510,7 +512,7 @@ async function gatherFileContext(keywords) {
|
|
|
510
512
|
return sources;
|
|
511
513
|
}
|
|
512
514
|
catch (error) {
|
|
513
|
-
|
|
515
|
+
log.error('gatherFileContext failed', error instanceof Error ? error : new Error(String(error)));
|
|
514
516
|
return [];
|
|
515
517
|
}
|
|
516
518
|
}
|
|
@@ -678,7 +680,7 @@ export class BackgroundResearcher {
|
|
|
678
680
|
return;
|
|
679
681
|
}
|
|
680
682
|
const terms = extractSearchTerms(query);
|
|
681
|
-
|
|
683
|
+
log.info('Research started', { id, terms });
|
|
682
684
|
// Build placeholder results; real results injected via inject()
|
|
683
685
|
const pending = buildPendingResults(query, terms);
|
|
684
686
|
if (signal?.aborted) {
|
|
@@ -694,13 +696,13 @@ export class BackgroundResearcher {
|
|
|
694
696
|
results: pending,
|
|
695
697
|
completedAt: Date.now(),
|
|
696
698
|
});
|
|
697
|
-
|
|
699
|
+
log.info('Research completed', { id, resultCount: pending.length });
|
|
698
700
|
}
|
|
699
701
|
catch (error) {
|
|
700
702
|
const current = this.tasks.get(id);
|
|
701
703
|
if (!current)
|
|
702
704
|
return;
|
|
703
|
-
|
|
705
|
+
log.error('Research failed', error instanceof Error ? error : new Error(String(error)), { id });
|
|
704
706
|
this.tasks.set(id, {
|
|
705
707
|
...current,
|
|
706
708
|
status: 'failed',
|
package/dist/chat/tools.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
*/
|
|
7
7
|
import { z } from 'zod';
|
|
8
8
|
import { randomUUID } from 'node:crypto';
|
|
9
|
-
import {
|
|
9
|
+
import { getDb } from '../storage/index.js';
|
|
10
10
|
import { projects, tickets, sprints } from '../storage/schema.js';
|
|
11
11
|
import { eq, sql } from 'drizzle-orm';
|
|
12
12
|
import { logger } from '../utils/logger.js';
|
|
@@ -235,7 +235,7 @@ function getProviderDisplayName(provider) {
|
|
|
235
235
|
*/
|
|
236
236
|
async function executeCreateProject(input) {
|
|
237
237
|
try {
|
|
238
|
-
const db =
|
|
238
|
+
const db = getDb();
|
|
239
239
|
const id = randomUUID();
|
|
240
240
|
const key = input.key.toUpperCase();
|
|
241
241
|
// Check if key already exists
|
|
@@ -285,7 +285,7 @@ async function executeCreateProject(input) {
|
|
|
285
285
|
*/
|
|
286
286
|
async function executeCreateTicket(input) {
|
|
287
287
|
try {
|
|
288
|
-
const db =
|
|
288
|
+
const db = getDb();
|
|
289
289
|
// Find the project by key
|
|
290
290
|
const project = await db
|
|
291
291
|
.select()
|
|
@@ -319,7 +319,8 @@ async function executeCreateTicket(input) {
|
|
|
319
319
|
status: 'backlog',
|
|
320
320
|
priority: input.priority || 'medium',
|
|
321
321
|
labels: input.labels || [],
|
|
322
|
-
|
|
322
|
+
estimate: input.storyPoints,
|
|
323
|
+
estimateUnit: input.storyPoints !== undefined ? 'points' : undefined,
|
|
323
324
|
});
|
|
324
325
|
logger.info(`[ChatTools] Created ticket: ${ticketKey}`, { component: 'ChatTools' });
|
|
325
326
|
return {
|
|
@@ -349,7 +350,7 @@ async function executeCreateTicket(input) {
|
|
|
349
350
|
*/
|
|
350
351
|
async function executeCreateSprint(input) {
|
|
351
352
|
try {
|
|
352
|
-
const db =
|
|
353
|
+
const db = getDb();
|
|
353
354
|
// Find the project by key
|
|
354
355
|
const project = await db
|
|
355
356
|
.select()
|
|
@@ -409,7 +410,7 @@ async function executeCreateSprint(input) {
|
|
|
409
410
|
*/
|
|
410
411
|
async function executeListProjects(input) {
|
|
411
412
|
try {
|
|
412
|
-
const db =
|
|
413
|
+
const db = getDb();
|
|
413
414
|
let query = db.select().from(projects);
|
|
414
415
|
if (input.status !== 'all') {
|
|
415
416
|
query = query.where(eq(projects.status, input.status));
|
|
@@ -442,7 +443,7 @@ async function executeListProjects(input) {
|
|
|
442
443
|
*/
|
|
443
444
|
async function executeSearchTickets(input) {
|
|
444
445
|
try {
|
|
445
|
-
const db =
|
|
446
|
+
const db = getDb();
|
|
446
447
|
let ticketList = await db.select().from(tickets).limit(input.limit).all();
|
|
447
448
|
// Apply filters
|
|
448
449
|
if (input.projectKey) {
|
|
@@ -163,19 +163,28 @@ export function authCommands() {
|
|
|
163
163
|
.action(async (options) => {
|
|
164
164
|
try {
|
|
165
165
|
const db = await ensureDb();
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
166
|
+
const query = options.status
|
|
167
|
+
? db
|
|
168
|
+
.select({
|
|
169
|
+
id: users.id,
|
|
170
|
+
email: users.email,
|
|
171
|
+
name: users.name,
|
|
172
|
+
role: users.role,
|
|
173
|
+
status: users.status,
|
|
174
|
+
createdAt: users.createdAt,
|
|
175
|
+
})
|
|
176
|
+
.from(users)
|
|
177
|
+
.where(eq(users.status, options.status))
|
|
178
|
+
: db
|
|
179
|
+
.select({
|
|
180
|
+
id: users.id,
|
|
181
|
+
email: users.email,
|
|
182
|
+
name: users.name,
|
|
183
|
+
role: users.role,
|
|
184
|
+
status: users.status,
|
|
185
|
+
createdAt: users.createdAt,
|
|
186
|
+
})
|
|
187
|
+
.from(users);
|
|
179
188
|
const allUsers = await query.orderBy(users.createdAt);
|
|
180
189
|
if (options.json) {
|
|
181
190
|
console.log(JSON.stringify(allUsers, null, 2));
|