codecane 1.0.207 → 1.0.237
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/background-process-manager.d.ts +50 -0
- package/dist/background-process-manager.js +320 -0
- package/dist/background-process-manager.js.map +1 -0
- package/dist/browser-runner.js +40 -34
- package/dist/browser-runner.js.map +1 -1
- package/dist/checkpoints/checkpoint-manager.d.ts +30 -9
- package/dist/checkpoints/checkpoint-manager.js +119 -32
- package/dist/checkpoints/checkpoint-manager.js.map +1 -1
- package/dist/checkpoints/file-manager.js +14 -6
- package/dist/checkpoints/file-manager.js.map +1 -1
- package/dist/cli-handlers/api-key.d.ts +25 -0
- package/dist/cli-handlers/api-key.js +66 -0
- package/dist/cli-handlers/api-key.js.map +1 -0
- package/dist/cli-handlers/checkpoint.d.ts +18 -0
- package/dist/cli-handlers/checkpoint.js +195 -0
- package/dist/cli-handlers/checkpoint.js.map +1 -0
- package/dist/cli-handlers/diff.d.ts +2 -0
- package/dist/cli-handlers/diff.js +31 -0
- package/dist/cli-handlers/diff.js.map +1 -0
- package/dist/cli-handlers/easter-egg.d.ts +1 -0
- package/dist/cli-handlers/easter-egg.js +126 -0
- package/dist/cli-handlers/easter-egg.js.map +1 -0
- package/dist/cli-handlers/inititalization-flow.d.ts +1 -0
- package/dist/cli-handlers/inititalization-flow.js +24 -0
- package/dist/cli-handlers/inititalization-flow.js.map +1 -0
- package/dist/cli.d.ts +8 -11
- package/dist/cli.js +171 -320
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +34 -124
- package/dist/client.js +395 -154
- package/dist/client.js.map +1 -1
- package/dist/code-map/languages.d.ts +0 -1
- package/dist/code-map/languages.js +23 -224
- package/dist/code-map/languages.js.map +1 -1
- package/dist/code-map/parse.js +1 -0
- package/dist/code-map/parse.js.map +1 -1
- package/dist/code-map/tsconfig.tsbuildinfo +1 -1
- package/dist/common/actions.d.ts +369 -826
- package/dist/common/actions.js +25 -31
- package/dist/common/actions.js.map +1 -1
- package/dist/common/api-keys/constants.d.ts +8 -0
- package/dist/common/api-keys/constants.js +26 -0
- package/dist/common/api-keys/constants.js.map +1 -0
- package/dist/common/api-keys/crypto.d.ts +24 -0
- package/dist/common/api-keys/crypto.js +186 -0
- package/dist/common/api-keys/crypto.js.map +1 -0
- package/dist/common/bigquery/client.d.ts +15 -0
- package/dist/common/bigquery/client.js +246 -0
- package/dist/common/bigquery/client.js.map +1 -0
- package/dist/common/bigquery/schema.d.ts +55 -0
- package/dist/common/bigquery/schema.js +24 -0
- package/dist/common/bigquery/schema.js.map +1 -0
- package/dist/common/billing/auto-topup.d.ts +8 -0
- package/dist/common/billing/auto-topup.js +192 -0
- package/dist/common/billing/auto-topup.js.map +1 -0
- package/dist/common/billing/balance-calculator.d.ts +57 -0
- package/dist/common/billing/balance-calculator.js +218 -0
- package/dist/common/billing/balance-calculator.js.map +1 -0
- package/dist/common/billing/conversion.d.ts +9 -0
- package/dist/common/billing/conversion.js +20 -0
- package/dist/common/billing/conversion.js.map +1 -0
- package/dist/common/billing/credit-conversion.d.ts +24 -0
- package/dist/common/billing/credit-conversion.js +48 -0
- package/dist/common/billing/credit-conversion.js.map +1 -0
- package/dist/common/billing/grant-credits.d.ts +43 -0
- package/dist/common/billing/grant-credits.js +266 -0
- package/dist/common/billing/grant-credits.js.map +1 -0
- package/dist/common/billing/plans.d.ts +13 -0
- package/dist/common/billing/plans.js +44 -0
- package/dist/common/billing/plans.js.map +1 -0
- package/dist/common/browser-actions.d.ts +1 -1
- package/dist/common/browser-actions.js +4 -4
- package/dist/common/browser-actions.js.map +1 -1
- package/dist/common/constants/grant-priorities.d.ts +2 -0
- package/dist/common/constants/grant-priorities.js +10 -0
- package/dist/common/constants/grant-priorities.js.map +1 -0
- package/dist/common/constants/tools.d.ts +2 -0
- package/dist/common/constants/tools.js +24 -3
- package/dist/common/constants/tools.js.map +1 -1
- package/dist/common/constants.d.ts +93 -5
- package/dist/common/constants.js +111 -10
- package/dist/common/constants.js.map +1 -1
- package/dist/common/db/env.mjs +5 -5
- package/dist/common/db/env.mjs.map +1 -1
- package/dist/common/db/schema.d.ts +413 -83
- package/dist/common/db/schema.js +70 -9
- package/dist/common/db/schema.js.map +1 -1
- package/dist/common/db/transaction.d.ts +12 -0
- package/dist/common/db/transaction.js +36 -0
- package/dist/common/db/transaction.js.map +1 -0
- package/dist/common/env.mjs +11 -8
- package/dist/common/env.mjs.map +1 -1
- package/dist/common/json-config/__tests__/__snapshots__/stringify-schema.test.js.snap +66 -0
- package/dist/common/json-config/__tests__/stringify-schema.test.d.ts +1 -0
- package/dist/common/json-config/__tests__/stringify-schema.test.js +66 -0
- package/dist/common/json-config/__tests__/stringify-schema.test.js.map +1 -0
- package/dist/common/json-config/constants.d.ts +82 -0
- package/dist/common/json-config/constants.js +48 -0
- package/dist/common/json-config/constants.js.map +1 -0
- package/dist/common/json-config/parser.d.ts +7 -0
- package/dist/common/json-config/parser.js +51 -0
- package/dist/common/json-config/parser.js.map +1 -0
- package/dist/common/json-config/stringify-schema.d.ts +10 -0
- package/dist/common/json-config/stringify-schema.js +102 -0
- package/dist/common/json-config/stringify-schema.js.map +1 -0
- package/dist/common/project-file-tree.d.ts +2 -1
- package/dist/common/project-file-tree.js +59 -27
- package/dist/common/project-file-tree.js.map +1 -1
- package/dist/common/types/agent-state.d.ts +25 -22
- package/dist/common/types/agent-state.js +2 -0
- package/dist/common/types/agent-state.js.map +1 -1
- package/dist/common/types/grant.d.ts +2 -0
- package/dist/common/types/grant.js +10 -0
- package/dist/common/types/grant.js.map +1 -0
- package/dist/common/types/usage.d.ts +37 -18
- package/dist/common/types/usage.js +9 -6
- package/dist/common/types/usage.js.map +1 -1
- package/dist/common/util/__tests__/saxy.test.d.ts +1 -0
- package/dist/common/util/__tests__/saxy.test.js +262 -0
- package/dist/common/util/__tests__/saxy.test.js.map +1 -0
- package/dist/common/util/__tests__/string.test.js +2 -3
- package/dist/common/util/__tests__/string.test.js.map +1 -1
- package/dist/common/util/changes.d.ts +1 -0
- package/dist/common/util/changes.js +8 -2
- package/dist/common/util/changes.js.map +1 -1
- package/dist/common/util/dates.d.ts +10 -1
- package/dist/common/util/dates.js +11 -2
- package/dist/common/util/dates.js.map +1 -1
- package/dist/common/util/file.d.ts +10 -9
- package/dist/common/util/file.js +12 -4
- package/dist/common/util/file.js.map +1 -1
- package/dist/common/util/logger.d.ts +8 -0
- package/dist/common/util/logger.js +52 -0
- package/dist/common/util/logger.js.map +1 -0
- package/dist/common/util/lru-cache.d.ts +23 -2
- package/dist/common/util/lru-cache.js +44 -18
- package/dist/common/util/lru-cache.js.map +1 -1
- package/dist/common/util/messages.d.ts +3 -0
- package/dist/common/util/messages.js +50 -3
- package/dist/common/util/messages.js.map +1 -1
- package/dist/common/util/min-heap.js +2 -2
- package/dist/common/util/min-heap.js.map +1 -1
- package/dist/common/util/promise.d.ts +1 -1
- package/dist/common/util/promise.js +2 -2
- package/dist/common/util/promise.js.map +1 -1
- package/dist/common/util/saxy.d.ts +8 -0
- package/dist/common/util/saxy.js +35 -12
- package/dist/common/util/saxy.js.map +1 -1
- package/dist/common/util/string.d.ts +7 -1
- package/dist/common/util/string.js +20 -4
- package/dist/common/util/string.js.map +1 -1
- package/dist/common/util/stripe.d.ts +1 -0
- package/dist/common/util/stripe.js +10 -7
- package/dist/common/util/stripe.js.map +1 -1
- package/dist/common/util/sync-failure.d.ts +1 -0
- package/dist/common/util/sync-failure.js +57 -0
- package/dist/common/util/sync-failure.js.map +1 -0
- package/dist/common/websockets/websocket-client.d.ts +2 -1
- package/dist/common/websockets/websocket-client.js +34 -6
- package/dist/common/websockets/websocket-client.js.map +1 -1
- package/dist/common/websockets/websocket-schema.d.ts +1440 -2642
- package/dist/config.d.ts +2 -1
- package/dist/config.js +6 -3
- package/dist/config.js.map +1 -1
- package/dist/credentials.js +3 -2
- package/dist/credentials.js.map +1 -1
- package/dist/dev-process-manager.d.ts +10 -0
- package/dist/dev-process-manager.js +54 -0
- package/dist/dev-process-manager.js.map +1 -0
- package/dist/fingerprint.js +7 -2
- package/dist/fingerprint.js.map +1 -1
- package/dist/index.js +79 -74
- package/dist/index.js.map +1 -1
- package/dist/menu.js +20 -13
- package/dist/menu.js.map +1 -1
- package/dist/project-files.d.ts +10 -6
- package/dist/project-files.js +55 -32
- package/dist/project-files.js.map +1 -1
- package/dist/startup-process-handler.d.ts +2 -0
- package/dist/startup-process-handler.js +21 -0
- package/dist/startup-process-handler.js.map +1 -0
- package/dist/tool-handlers.d.ts +1 -0
- package/dist/tool-handlers.js +46 -23
- package/dist/tool-handlers.js.map +1 -1
- package/dist/types.d.ts +2 -0
- package/dist/update-codebuff.js +3 -1
- package/dist/update-codebuff.js.map +1 -1
- package/dist/utils/__tests__/background-process-manager.test.d.ts +1 -0
- package/dist/utils/__tests__/background-process-manager.test.js +289 -0
- package/dist/utils/__tests__/background-process-manager.test.js.map +1 -0
- package/dist/utils/__tests__/response-example-4-files.txt +621 -0
- package/dist/utils/__tests__/tool-renderers.test.d.ts +1 -0
- package/dist/utils/__tests__/tool-renderers.test.js +51 -0
- package/dist/utils/__tests__/tool-renderers.test.js.map +1 -0
- package/dist/utils/__tests__/xml-stream-parser.test.js +29 -21
- package/dist/utils/__tests__/xml-stream-parser.test.js.map +1 -1
- package/dist/utils/terminal.d.ts +12 -1
- package/dist/utils/terminal.js +148 -23
- package/dist/utils/terminal.js.map +1 -1
- package/dist/utils/tool-renderers.js +45 -17
- package/dist/utils/tool-renderers.js.map +1 -1
- package/dist/workers/checkpoint-worker.js +4 -3
- package/dist/workers/checkpoint-worker.js.map +1 -1
- package/package.json +20 -35
- package/dist/common/billing/quota-manager.d.ts +0 -29
- package/dist/common/billing/quota-manager.js +0 -213
- package/dist/common/billing/quota-manager.js.map +0 -1
- package/dist/common/util/tools.d.ts +0 -2
- package/dist/common/util/tools.js +0 -13
- package/dist/common/util/tools.js.map +0 -1
- package/dist/utils/logger.d.ts +0 -2
- package/dist/utils/logger.js +0 -33
- package/dist/utils/logger.js.map +0 -1
package/dist/client.js
CHANGED
|
@@ -1,43 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
2
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
26
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
27
4
|
};
|
|
28
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
29
6
|
exports.Client = void 0;
|
|
30
7
|
const child_process_1 = require("child_process");
|
|
31
|
-
const
|
|
8
|
+
const fs_1 = require("fs");
|
|
32
9
|
const path_1 = __importDefault(require("path"));
|
|
33
|
-
const picocolors_1 = require("picocolors");
|
|
34
|
-
const ts_pattern_1 = require("ts-pattern");
|
|
35
10
|
const actions_1 = require("./common/actions");
|
|
36
|
-
const constants_1 = require("./common/constants");
|
|
11
|
+
const constants_1 = require("./common/api-keys/constants");
|
|
12
|
+
const constants_2 = require("./common/constants");
|
|
13
|
+
const constants_3 = require("./common/json-config/constants");
|
|
37
14
|
const agent_state_1 = require("./common/types/agent-state");
|
|
15
|
+
const string_1 = require("./common/util/string");
|
|
38
16
|
const websocket_client_1 = require("./common/websockets/websocket-client");
|
|
39
|
-
const
|
|
17
|
+
const picocolors_1 = require("picocolors");
|
|
18
|
+
const ts_pattern_1 = require("ts-pattern");
|
|
19
|
+
const zod_1 = require("zod");
|
|
20
|
+
const background_process_manager_1 = require("./background-process-manager");
|
|
40
21
|
const browser_runner_1 = require("./browser-runner");
|
|
22
|
+
const chat_storage_1 = require("./chat-storage");
|
|
41
23
|
const checkpoint_manager_1 = require("./checkpoints/checkpoint-manager");
|
|
42
24
|
const config_1 = require("./config");
|
|
43
25
|
const credentials_1 = require("./credentials");
|
|
@@ -46,37 +28,81 @@ const menu_1 = require("./menu");
|
|
|
46
28
|
const project_files_1 = require("./project-files");
|
|
47
29
|
const tool_handlers_1 = require("./tool-handlers");
|
|
48
30
|
const spinner_1 = require("./utils/spinner");
|
|
49
|
-
const xml_stream_parser_1 = require("./utils/xml-stream-parser");
|
|
50
31
|
const tool_renderers_1 = require("./utils/tool-renderers");
|
|
32
|
+
const xml_stream_parser_1 = require("./utils/xml-stream-parser");
|
|
33
|
+
const web_scraper_1 = require("./web-scraper");
|
|
34
|
+
const web_scraper_2 = require("./web-scraper");
|
|
35
|
+
const array_1 = require("./common/util/array");
|
|
36
|
+
const LOW_BALANCE_THRESHOLD = 100;
|
|
37
|
+
const WARNING_CONFIG = {
|
|
38
|
+
[constants_2.UserState.LOGGED_OUT]: {
|
|
39
|
+
message: () => `Type "login" to unlock full access and get free credits!`,
|
|
40
|
+
threshold: 100,
|
|
41
|
+
},
|
|
42
|
+
[constants_2.UserState.DEPLETED]: {
|
|
43
|
+
message: () => [
|
|
44
|
+
(0, picocolors_1.red)(`\n❌ You have used all your credits.`),
|
|
45
|
+
`Visit ${(0, picocolors_1.bold)((0, picocolors_1.blue)(config_1.websiteUrl + '/usage'))} to add more credits and continue coding.`,
|
|
46
|
+
].join('\n'),
|
|
47
|
+
threshold: 100,
|
|
48
|
+
},
|
|
49
|
+
[constants_2.UserState.CRITICAL]: {
|
|
50
|
+
message: (credits) => [
|
|
51
|
+
(0, picocolors_1.yellow)(`\n🪫 Only ${(0, picocolors_1.bold)((0, string_1.pluralize)(credits, 'credit'))} remaining!`),
|
|
52
|
+
(0, picocolors_1.yellow)(`Visit ${(0, picocolors_1.bold)(config_1.websiteUrl + '/usage')} to add more credits.`),
|
|
53
|
+
].join('\n'),
|
|
54
|
+
threshold: 85,
|
|
55
|
+
},
|
|
56
|
+
[constants_2.UserState.ATTENTION_NEEDED]: {
|
|
57
|
+
message: (credits) => [
|
|
58
|
+
(0, picocolors_1.yellow)(`\n⚠️ ${(0, picocolors_1.bold)((0, string_1.pluralize)(credits, 'credit'))} remaining. Consider topping up soon.`),
|
|
59
|
+
].join('\n'),
|
|
60
|
+
threshold: 75,
|
|
61
|
+
},
|
|
62
|
+
[constants_2.UserState.GOOD_STANDING]: {
|
|
63
|
+
message: () => '',
|
|
64
|
+
threshold: 0,
|
|
65
|
+
},
|
|
66
|
+
};
|
|
51
67
|
class Client {
|
|
52
68
|
webSocket;
|
|
53
69
|
returnControlToUser;
|
|
70
|
+
reconnectWhenNextIdle;
|
|
54
71
|
fingerprintId;
|
|
55
72
|
costMode;
|
|
73
|
+
hadFileChanges = false;
|
|
74
|
+
git;
|
|
75
|
+
rl;
|
|
76
|
+
responseComplete = false;
|
|
77
|
+
pendingTopUpMessageAmount = null;
|
|
78
|
+
oneTimeFlags = Object.fromEntries(constants_2.ONE_TIME_LABELS.map((tag) => [tag, false]));
|
|
79
|
+
usageData = {
|
|
80
|
+
usage: 0,
|
|
81
|
+
remainingBalance: 0,
|
|
82
|
+
balanceBreakdown: undefined,
|
|
83
|
+
next_quota_reset: null,
|
|
84
|
+
nextMonthlyGrant: 0,
|
|
85
|
+
};
|
|
56
86
|
fileContext;
|
|
57
87
|
lastChanges = [];
|
|
58
88
|
agentState;
|
|
59
89
|
originalFileVersions = {};
|
|
90
|
+
creditsByPromptId = {};
|
|
60
91
|
user;
|
|
61
92
|
lastWarnedPct = 0;
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
subscription_active = false;
|
|
65
|
-
lastRequestCredits = 0;
|
|
66
|
-
sessionCreditsUsed = 0;
|
|
67
|
-
nextQuotaReset = null;
|
|
68
|
-
hadFileChanges = false;
|
|
69
|
-
git;
|
|
70
|
-
rl;
|
|
93
|
+
nextMonthlyGrant = 0;
|
|
94
|
+
storedApiKeyTypes = [];
|
|
71
95
|
lastToolResults = [];
|
|
72
|
-
|
|
73
|
-
constructor(websocketUrl, onWebSocketError, onWebSocketReconnect, returnControlToUser, costMode, git, rl) {
|
|
96
|
+
model;
|
|
97
|
+
constructor(websocketUrl, onWebSocketError, onWebSocketReconnect, returnControlToUser, reconnectWhenNextIdle, costMode, git, rl, model) {
|
|
74
98
|
this.costMode = costMode;
|
|
99
|
+
this.model = model;
|
|
75
100
|
this.git = git;
|
|
76
101
|
this.webSocket = new websocket_client_1.APIRealtimeClient(websocketUrl, onWebSocketError, onWebSocketReconnect);
|
|
77
102
|
this.user = this.getUser();
|
|
78
|
-
this.
|
|
103
|
+
this.initFingerprintId();
|
|
79
104
|
this.returnControlToUser = returnControlToUser;
|
|
105
|
+
this.reconnectWhenNextIdle = reconnectWhenNextIdle;
|
|
80
106
|
this.rl = rl;
|
|
81
107
|
}
|
|
82
108
|
async exit() {
|
|
@@ -89,25 +115,104 @@ class Client {
|
|
|
89
115
|
this.agentState = (0, agent_state_1.getInitialAgentState)(projectFileContext);
|
|
90
116
|
this.fileContext = projectFileContext;
|
|
91
117
|
}
|
|
92
|
-
|
|
93
|
-
if (this.fingerprintId) {
|
|
94
|
-
|
|
118
|
+
initFingerprintId() {
|
|
119
|
+
if (!this.fingerprintId) {
|
|
120
|
+
this.fingerprintId = this.user?.fingerprintId ?? (0, fingerprint_1.calculateFingerprint)();
|
|
95
121
|
}
|
|
96
|
-
this.fingerprintId =
|
|
97
|
-
this.user?.fingerprintId ?? (await (0, fingerprint_1.calculateFingerprint)());
|
|
98
122
|
return this.fingerprintId;
|
|
99
123
|
}
|
|
100
124
|
getUser() {
|
|
101
|
-
if (!
|
|
125
|
+
if (!(0, fs_1.existsSync)(credentials_1.CREDENTIALS_PATH)) {
|
|
102
126
|
return;
|
|
103
127
|
}
|
|
104
|
-
const credentialsFile =
|
|
128
|
+
const credentialsFile = (0, fs_1.readFileSync)(credentials_1.CREDENTIALS_PATH, 'utf8');
|
|
105
129
|
const user = (0, credentials_1.userFromJson)(credentialsFile);
|
|
106
130
|
return user;
|
|
107
131
|
}
|
|
108
132
|
async connect() {
|
|
109
133
|
await this.webSocket.connect();
|
|
110
134
|
this.setupSubscriptions();
|
|
135
|
+
await this.fetchStoredApiKeyTypes();
|
|
136
|
+
}
|
|
137
|
+
async fetchStoredApiKeyTypes() {
|
|
138
|
+
if (!this.user || !this.user.authToken) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
const TIMEOUT_MS = 5_000;
|
|
142
|
+
// try {
|
|
143
|
+
// const timeoutPromise = new Promise<Response>((_, reject) => {
|
|
144
|
+
// setTimeout(() => reject(new Error('Request timed out')), TIMEOUT_MS)
|
|
145
|
+
// })
|
|
146
|
+
// const fetchPromise = fetch(
|
|
147
|
+
// `${process.env.NEXT_PUBLIC_APP_URL}/api/api-keys`,
|
|
148
|
+
// {
|
|
149
|
+
// method: 'GET',
|
|
150
|
+
// headers: {
|
|
151
|
+
// 'Content-Type': 'application/json',
|
|
152
|
+
// Cookie: `next-auth.session-token=${this.user.authToken}`,
|
|
153
|
+
// Authorization: `Bearer ${this.user.authToken}`,
|
|
154
|
+
// },
|
|
155
|
+
// }
|
|
156
|
+
// )
|
|
157
|
+
// const response = await Promise.race([fetchPromise, timeoutPromise])
|
|
158
|
+
// if (response.ok) {
|
|
159
|
+
// const { keyTypes } = await response.json()
|
|
160
|
+
// this.storedApiKeyTypes = keyTypes as ApiKeyType[]
|
|
161
|
+
// } else {
|
|
162
|
+
// this.storedApiKeyTypes = []
|
|
163
|
+
// }
|
|
164
|
+
// } catch (error) {
|
|
165
|
+
// if (process.env.NODE_ENV !== 'production') {
|
|
166
|
+
// console.error(
|
|
167
|
+
// 'Error fetching stored API key types (is there something else on port 3000?):',
|
|
168
|
+
// error
|
|
169
|
+
// )
|
|
170
|
+
// }
|
|
171
|
+
// this.storedApiKeyTypes = []
|
|
172
|
+
// }
|
|
173
|
+
this.storedApiKeyTypes = [];
|
|
174
|
+
}
|
|
175
|
+
async handleAddApiKey(keyType, apiKey) {
|
|
176
|
+
if (!this.user || !this.user.authToken) {
|
|
177
|
+
console.log((0, picocolors_1.yellow)("Please log in first using 'login'."));
|
|
178
|
+
this.returnControlToUser();
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const readableKeyType = constants_1.READABLE_NAME[keyType];
|
|
182
|
+
spinner_1.Spinner.get().start();
|
|
183
|
+
try {
|
|
184
|
+
const response = await fetch(`${process.env.NEXT_PUBLIC_APP_URL}/api/api-keys`, {
|
|
185
|
+
method: 'POST',
|
|
186
|
+
headers: {
|
|
187
|
+
'Content-Type': 'application/json',
|
|
188
|
+
Cookie: `next-auth.session-token=${this.user.authToken}`,
|
|
189
|
+
},
|
|
190
|
+
body: JSON.stringify({
|
|
191
|
+
keyType,
|
|
192
|
+
apiKey,
|
|
193
|
+
authToken: this.user.authToken,
|
|
194
|
+
}),
|
|
195
|
+
});
|
|
196
|
+
spinner_1.Spinner.get().stop();
|
|
197
|
+
const respJson = await response.json();
|
|
198
|
+
if (response.ok) {
|
|
199
|
+
console.log((0, picocolors_1.green)(`Successfully added ${readableKeyType} API key.`));
|
|
200
|
+
if (!this.storedApiKeyTypes.includes(keyType)) {
|
|
201
|
+
this.storedApiKeyTypes.push(keyType);
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
throw new Error(respJson.message);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (e) {
|
|
209
|
+
spinner_1.Spinner.get().stop();
|
|
210
|
+
const error = e;
|
|
211
|
+
console.error((0, picocolors_1.red)('Error adding API key: ' + error.message));
|
|
212
|
+
}
|
|
213
|
+
finally {
|
|
214
|
+
this.returnControlToUser();
|
|
215
|
+
}
|
|
111
216
|
}
|
|
112
217
|
async handleReferralCode(referralCode) {
|
|
113
218
|
if (this.user) {
|
|
@@ -127,7 +232,7 @@ class Client {
|
|
|
127
232
|
if (redeemReferralResp.ok) {
|
|
128
233
|
console.log([
|
|
129
234
|
(0, picocolors_1.green)(`Noice, you've earned an extra ${respJson.credits_redeemed} credits!`),
|
|
130
|
-
`(pssst: you can also refer new users and earn ${
|
|
235
|
+
`(pssst: you can also refer new users and earn ${constants_2.CREDITS_REFERRAL_BONUS} credits for each referral at: ${process.env.NEXT_PUBLIC_APP_URL}/referrals)`,
|
|
131
236
|
].join('\n'));
|
|
132
237
|
this.getUsage();
|
|
133
238
|
}
|
|
@@ -148,7 +253,7 @@ class Client {
|
|
|
148
253
|
async logout() {
|
|
149
254
|
if (this.user) {
|
|
150
255
|
try {
|
|
151
|
-
const response = await fetch(`${config_1.
|
|
256
|
+
const response = await fetch(`${config_1.websiteUrl}/api/auth/cli/logout`, {
|
|
152
257
|
method: 'POST',
|
|
153
258
|
headers: { 'Content-Type': 'application/json' },
|
|
154
259
|
body: JSON.stringify({
|
|
@@ -163,9 +268,18 @@ class Client {
|
|
|
163
268
|
console.error((0, picocolors_1.red)('Failed to log out: ' + error));
|
|
164
269
|
}
|
|
165
270
|
try {
|
|
166
|
-
|
|
271
|
+
(0, fs_1.unlinkSync)(credentials_1.CREDENTIALS_PATH);
|
|
167
272
|
console.log(`You (${this.user.name}) have been logged out.`);
|
|
168
273
|
this.user = undefined;
|
|
274
|
+
this.pendingTopUpMessageAmount = null;
|
|
275
|
+
this.usageData = {
|
|
276
|
+
usage: 0,
|
|
277
|
+
remainingBalance: 0,
|
|
278
|
+
balanceBreakdown: undefined,
|
|
279
|
+
next_quota_reset: null,
|
|
280
|
+
nextMonthlyGrant: 0,
|
|
281
|
+
};
|
|
282
|
+
this.oneTimeFlags = Object.fromEntries(constants_2.ONE_TIME_LABELS.map((tag) => [tag, false]));
|
|
169
283
|
}
|
|
170
284
|
catch (error) {
|
|
171
285
|
console.error('Error removing credentials file:', error);
|
|
@@ -183,11 +297,11 @@ class Client {
|
|
|
183
297
|
return;
|
|
184
298
|
}
|
|
185
299
|
try {
|
|
186
|
-
const response = await fetch(`${config_1.
|
|
300
|
+
const response = await fetch(`${config_1.websiteUrl}/api/auth/cli/code`, {
|
|
187
301
|
method: 'POST',
|
|
188
302
|
headers: { 'Content-Type': 'application/json' },
|
|
189
303
|
body: JSON.stringify({
|
|
190
|
-
fingerprintId: await this.
|
|
304
|
+
fingerprintId: await this.fingerprintId,
|
|
191
305
|
referralCode,
|
|
192
306
|
}),
|
|
193
307
|
});
|
|
@@ -197,7 +311,7 @@ class Client {
|
|
|
197
311
|
this.returnControlToUser();
|
|
198
312
|
return;
|
|
199
313
|
}
|
|
200
|
-
const { loginUrl, fingerprintHash } = await response.json();
|
|
314
|
+
const { loginUrl, fingerprintHash, expiresAt } = await response.json();
|
|
201
315
|
const responseToUser = [
|
|
202
316
|
'\n',
|
|
203
317
|
`Press ${(0, picocolors_1.blue)('ENTER')} to open your browser and finish logging in...`,
|
|
@@ -207,7 +321,7 @@ class Client {
|
|
|
207
321
|
this.rl.once('line', () => {
|
|
208
322
|
if (shouldRequestLogin) {
|
|
209
323
|
(0, child_process_1.spawn)(`open ${loginUrl}`, { shell: true });
|
|
210
|
-
console.log(
|
|
324
|
+
console.log("Opened a browser window to log you in! If it doesn't open automatically, you can click this link:");
|
|
211
325
|
console.log();
|
|
212
326
|
console.log((0, picocolors_1.blue)((0, picocolors_1.bold)((0, picocolors_1.underline)(loginUrl))));
|
|
213
327
|
}
|
|
@@ -226,7 +340,7 @@ class Client {
|
|
|
226
340
|
return;
|
|
227
341
|
}
|
|
228
342
|
try {
|
|
229
|
-
const statusResponse = await fetch(`${config_1.
|
|
343
|
+
const statusResponse = await fetch(`${config_1.websiteUrl}/api/auth/cli/status?fingerprintId=${await this.fingerprintId}&fingerprintHash=${fingerprintHash}&expiresAt=${expiresAt}`);
|
|
230
344
|
if (!statusResponse.ok) {
|
|
231
345
|
if (statusResponse.status !== 401) {
|
|
232
346
|
// Ignore 401s during polling
|
|
@@ -239,16 +353,17 @@ class Client {
|
|
|
239
353
|
shouldRequestLogin = false;
|
|
240
354
|
this.user = user;
|
|
241
355
|
const credentialsPathDir = path_1.default.dirname(credentials_1.CREDENTIALS_PATH);
|
|
242
|
-
|
|
243
|
-
|
|
356
|
+
(0, fs_1.mkdirSync)(credentialsPathDir, { recursive: true });
|
|
357
|
+
(0, fs_1.writeFileSync)(credentials_1.CREDENTIALS_PATH, JSON.stringify({ default: user }));
|
|
244
358
|
const referralLink = `${process.env.NEXT_PUBLIC_APP_URL}/referrals`;
|
|
245
359
|
const responseToUser = [
|
|
246
360
|
'Authentication successful! 🎉',
|
|
247
361
|
(0, picocolors_1.bold)(`Hey there, ${user.name}.`),
|
|
248
|
-
`Refer new users and earn ${
|
|
362
|
+
`Refer new users and earn ${constants_2.CREDITS_REFERRAL_BONUS} credits per month: ${(0, picocolors_1.blueBright)(referralLink)}`,
|
|
249
363
|
];
|
|
250
364
|
console.log('\n' + responseToUser.join('\n'));
|
|
251
365
|
this.lastWarnedPct = 0;
|
|
366
|
+
this.oneTimeFlags = Object.fromEntries(constants_2.ONE_TIME_LABELS.map((tag) => [tag, false]));
|
|
252
367
|
(0, menu_1.displayGreeting)(this.costMode, null);
|
|
253
368
|
clearInterval(pollInterval);
|
|
254
369
|
this.returnControlToUser();
|
|
@@ -264,19 +379,25 @@ class Client {
|
|
|
264
379
|
this.returnControlToUser();
|
|
265
380
|
}
|
|
266
381
|
}
|
|
267
|
-
setUsage(
|
|
268
|
-
this.
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
this.
|
|
272
|
-
if (!!session_credits_used && !this.pendingRequestId) {
|
|
273
|
-
this.lastRequestCredits = Math.max(session_credits_used - this.sessionCreditsUsed, 0);
|
|
274
|
-
this.sessionCreditsUsed = session_credits_used;
|
|
275
|
-
}
|
|
382
|
+
setUsage(usageData) {
|
|
383
|
+
this.usageData = usageData;
|
|
384
|
+
}
|
|
385
|
+
reconnect() {
|
|
386
|
+
this.webSocket.forceReconnect();
|
|
276
387
|
}
|
|
277
388
|
setupSubscriptions() {
|
|
278
389
|
this.webSocket.subscribe('action-error', (action) => {
|
|
279
|
-
|
|
390
|
+
if (action.error === 'Insufficient credits') {
|
|
391
|
+
console.error(['', (0, picocolors_1.red)(`Error: ${action.message}`)].join('\n'));
|
|
392
|
+
console.error(`Visit ${(0, picocolors_1.blue)((0, picocolors_1.bold)(process.env.NEXT_PUBLIC_APP_URL + '/usage'))} to add credits.`);
|
|
393
|
+
}
|
|
394
|
+
else if (action.error === 'Auto top-up disabled') {
|
|
395
|
+
console.error(['', (0, picocolors_1.red)(`Error: ${action.message}`)].join('\n'));
|
|
396
|
+
console.error((0, picocolors_1.yellow)(`Visit ${(0, picocolors_1.blue)((0, picocolors_1.bold)(process.env.NEXT_PUBLIC_APP_URL + '/usage'))} to update your payment settings.`));
|
|
397
|
+
}
|
|
398
|
+
else {
|
|
399
|
+
console.error(['', (0, picocolors_1.red)(`Error: ${action.message}`)].join('\n'));
|
|
400
|
+
}
|
|
280
401
|
this.returnControlToUser();
|
|
281
402
|
return;
|
|
282
403
|
});
|
|
@@ -295,45 +416,61 @@ class Client {
|
|
|
295
416
|
console.warn((0, picocolors_1.yellow)(`\nThere's a new version of Codebuff! Please update to ensure proper functionality.\nUpdate now by running: npm install -g codebuff`));
|
|
296
417
|
}
|
|
297
418
|
});
|
|
298
|
-
this.webSocket.subscribe('
|
|
299
|
-
const parsedAction = actions_1.
|
|
419
|
+
this.webSocket.subscribe('message-cost-response', (action) => {
|
|
420
|
+
const parsedAction = actions_1.MessageCostResponseSchema.safeParse(action);
|
|
300
421
|
if (!parsedAction.success)
|
|
301
422
|
return;
|
|
302
|
-
const
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
423
|
+
const response = parsedAction.data;
|
|
424
|
+
// Store credits used for this prompt
|
|
425
|
+
if (!this.creditsByPromptId[response.promptId]) {
|
|
426
|
+
this.creditsByPromptId[response.promptId] = [];
|
|
427
|
+
}
|
|
428
|
+
this.creditsByPromptId[response.promptId].push(response.credits);
|
|
307
429
|
});
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
? `Visit ${(0, picocolors_1.blue)((0, picocolors_1.bold)(process.env.NEXT_PUBLIC_APP_URL + '/pricing'))} to upgrade – or refer a new user and earn ${constants_1.CREDITS_REFERRAL_BONUS} credits per month: ${(0, picocolors_1.blue)((0, picocolors_1.bold)(process.env.NEXT_PUBLIC_APP_URL + '/referrals'))}`
|
|
313
|
-
: (0, picocolors_1.green)('Type "login" below to sign up and get more credits!'),
|
|
314
|
-
].join('\n');
|
|
315
|
-
const pct = (0, ts_pattern_1.match)(Math.floor((this.usage / this.limit) * 100))
|
|
316
|
-
.with(ts_pattern_1.P.number.gte(100), () => 100)
|
|
317
|
-
.with(ts_pattern_1.P.number.gte(75), () => 75)
|
|
318
|
-
.otherwise(() => 0);
|
|
319
|
-
if (pct >= 100) {
|
|
320
|
-
this.lastWarnedPct = 100;
|
|
321
|
-
if (!this.subscription_active) {
|
|
322
|
-
console.error([(0, picocolors_1.red)('You have reached your monthly usage limit.'), errorCopy].join('\n'));
|
|
430
|
+
this.webSocket.subscribe('usage-response', (action) => {
|
|
431
|
+
const parsedAction = actions_1.UsageReponseSchema.safeParse(action);
|
|
432
|
+
if (!parsedAction.success) {
|
|
433
|
+
console.error((0, picocolors_1.red)('Received invalid usage data from server:'), parsedAction.error.errors);
|
|
323
434
|
return;
|
|
324
435
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
436
|
+
this.setUsage(parsedAction.data);
|
|
437
|
+
// Store auto-topup info if it occurred
|
|
438
|
+
if (parsedAction.data.autoTopupAdded) {
|
|
439
|
+
this.pendingTopUpMessageAmount = parsedAction.data.autoTopupAdded;
|
|
328
440
|
}
|
|
441
|
+
// Only show warning if the response is complete
|
|
442
|
+
if (this.responseComplete) {
|
|
443
|
+
this.showUsageWarning();
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
// Used to handle server restarts gracefully
|
|
447
|
+
this.webSocket.subscribe('request-reconnect', () => {
|
|
448
|
+
this.reconnectWhenNextIdle();
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
showUsageWarning() {
|
|
452
|
+
// Determine user state based on login status and credit balance
|
|
453
|
+
const state = (0, ts_pattern_1.match)({
|
|
454
|
+
isLoggedIn: !!this.user,
|
|
455
|
+
credits: this.usageData.remainingBalance,
|
|
456
|
+
})
|
|
457
|
+
.with({ isLoggedIn: false }, () => constants_2.UserState.LOGGED_OUT)
|
|
458
|
+
.with({ credits: ts_pattern_1.P.number.gte(100) }, () => constants_2.UserState.GOOD_STANDING)
|
|
459
|
+
.with({ credits: ts_pattern_1.P.number.gte(20) }, () => constants_2.UserState.ATTENTION_NEEDED)
|
|
460
|
+
.with({ credits: ts_pattern_1.P.number.gte(1) }, () => constants_2.UserState.CRITICAL)
|
|
461
|
+
.otherwise(() => constants_2.UserState.DEPLETED);
|
|
462
|
+
const config = WARNING_CONFIG[state];
|
|
463
|
+
// Reset warning percentage if in good standing
|
|
464
|
+
if (state === constants_2.UserState.GOOD_STANDING) {
|
|
465
|
+
this.lastWarnedPct = 0;
|
|
466
|
+
return;
|
|
329
467
|
}
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
this.lastWarnedPct = pct;
|
|
468
|
+
// Show warning if we haven't warned at this threshold yet
|
|
469
|
+
if (this.lastWarnedPct < config.threshold) {
|
|
470
|
+
const message = config.message(this.usageData.remainingBalance);
|
|
471
|
+
console.warn(message);
|
|
472
|
+
this.lastWarnedPct = config.threshold;
|
|
473
|
+
this.returnControlToUser();
|
|
337
474
|
}
|
|
338
475
|
}
|
|
339
476
|
async generateCommitMessage(stagedChanges) {
|
|
@@ -344,7 +481,7 @@ class Client {
|
|
|
344
481
|
});
|
|
345
482
|
this.webSocket.sendAction({
|
|
346
483
|
type: 'generate-commit-message',
|
|
347
|
-
fingerprintId: await this.
|
|
484
|
+
fingerprintId: await this.fingerprintId,
|
|
348
485
|
authToken: this.user?.authToken,
|
|
349
486
|
stagedChanges,
|
|
350
487
|
});
|
|
@@ -355,7 +492,6 @@ class Client {
|
|
|
355
492
|
throw new Error('Agent state not initialized');
|
|
356
493
|
}
|
|
357
494
|
const userInputId = `mc-input-` + Math.random().toString(36).substring(2, 15);
|
|
358
|
-
this.pendingRequestId = userInputId;
|
|
359
495
|
const { responsePromise, stopResponse } = this.subscribeToResponse((chunk) => {
|
|
360
496
|
spinner_1.Spinner.get().stop();
|
|
361
497
|
process.stdout.write(chunk);
|
|
@@ -363,16 +499,26 @@ class Client {
|
|
|
363
499
|
spinner_1.Spinner.get().stop();
|
|
364
500
|
process.stdout.write((0, picocolors_1.green)((0, picocolors_1.underline)('\nCodebuff') + ':') + ' ');
|
|
365
501
|
}, prompt);
|
|
502
|
+
const urls = (0, web_scraper_2.parseUrlsFromContent)(prompt);
|
|
503
|
+
const scrapedBlocks = await (0, web_scraper_1.getScrapedContentBlocks)(urls);
|
|
504
|
+
const scrapedContent = scrapedBlocks.length > 0 ? scrapedBlocks.join('\n\n') + '\n\n' : '';
|
|
505
|
+
// Append process updates to existing tool results
|
|
506
|
+
const toolResults = (0, array_1.buildArray)(...(this.lastToolResults || []), ...(0, background_process_manager_1.getBackgroundProcessUpdates)(), scrapedContent && {
|
|
507
|
+
id: 'scraped-content',
|
|
508
|
+
name: 'web-scraper',
|
|
509
|
+
result: scrapedContent,
|
|
510
|
+
});
|
|
366
511
|
spinner_1.Spinner.get().start();
|
|
367
512
|
this.webSocket.sendAction({
|
|
368
513
|
type: 'prompt',
|
|
369
514
|
promptId: userInputId,
|
|
370
515
|
prompt,
|
|
371
516
|
agentState: this.agentState,
|
|
372
|
-
toolResults
|
|
373
|
-
fingerprintId: await this.
|
|
517
|
+
toolResults,
|
|
518
|
+
fingerprintId: await this.fingerprintId,
|
|
374
519
|
authToken: this.user?.authToken,
|
|
375
520
|
costMode: this.costMode,
|
|
521
|
+
model: this.model,
|
|
376
522
|
});
|
|
377
523
|
return {
|
|
378
524
|
responsePromise,
|
|
@@ -393,11 +539,11 @@ class Client {
|
|
|
393
539
|
});
|
|
394
540
|
const stopResponse = () => {
|
|
395
541
|
responseStopped = true;
|
|
396
|
-
// Only unsubscribe from chunks, keep listening for final credits
|
|
397
542
|
unsubscribeChunks();
|
|
543
|
+
unsubscribeComplete();
|
|
398
544
|
const assistantMessage = {
|
|
399
|
-
role: '
|
|
400
|
-
content: responseBuffer
|
|
545
|
+
role: 'user',
|
|
546
|
+
content: `Received output:\n${responseBuffer}[RESPONSE_CANCELED_BY_USER]`,
|
|
401
547
|
};
|
|
402
548
|
// Update the agent state with just the assistant's response
|
|
403
549
|
const { messageHistory } = this.agentState;
|
|
@@ -424,6 +570,21 @@ class Client {
|
|
|
424
570
|
if (a.userInputId !== userInputId)
|
|
425
571
|
return;
|
|
426
572
|
const { chunk } = a;
|
|
573
|
+
const trimmed = chunk.trim();
|
|
574
|
+
for (const tag of constants_2.ONE_TIME_TAGS) {
|
|
575
|
+
if (trimmed.startsWith(`<${tag}>`) && trimmed.endsWith(`</${tag}>`)) {
|
|
576
|
+
if (this.oneTimeFlags[tag]) {
|
|
577
|
+
return;
|
|
578
|
+
}
|
|
579
|
+
spinner_1.Spinner.get().stop();
|
|
580
|
+
const warningMessage = trimmed
|
|
581
|
+
.replace(`<${tag}>`, '')
|
|
582
|
+
.replace(`</${tag}>`, '');
|
|
583
|
+
console.warn((0, picocolors_1.yellow)(`\n${warningMessage}`));
|
|
584
|
+
this.oneTimeFlags[tag] = true;
|
|
585
|
+
return;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
427
588
|
if (chunk && chunk.trim()) {
|
|
428
589
|
if (!streamStarted && chunk.trim()) {
|
|
429
590
|
streamStarted = true;
|
|
@@ -444,45 +605,51 @@ class Client {
|
|
|
444
605
|
if (action.promptId !== userInputId)
|
|
445
606
|
return;
|
|
446
607
|
const a = parsedAction.data;
|
|
447
|
-
// Only process usage data if this is our pending request
|
|
448
|
-
const usageData = actions_1.UsageReponseSchema.omit({ type: true }).safeParse(a);
|
|
449
|
-
if (usageData.success) {
|
|
450
|
-
this.pendingRequestId = null;
|
|
451
|
-
this.setUsage(usageData.data);
|
|
452
|
-
}
|
|
453
|
-
if (responseStopped) {
|
|
454
|
-
unsubscribeComplete();
|
|
455
|
-
xmlStreamParser.end();
|
|
456
|
-
return;
|
|
457
|
-
}
|
|
458
|
-
this.agentState = a.agentState;
|
|
459
|
-
spinner_1.Spinner.get().stop();
|
|
460
608
|
let isComplete = false;
|
|
609
|
+
spinner_1.Spinner.get().stop();
|
|
610
|
+
this.agentState = a.agentState;
|
|
461
611
|
const toolResults = [...a.toolResults];
|
|
462
612
|
for (const toolCall of a.toolCalls) {
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
613
|
+
try {
|
|
614
|
+
if (toolCall.name === 'end_turn') {
|
|
615
|
+
this.responseComplete = true;
|
|
616
|
+
isComplete = true;
|
|
617
|
+
continue;
|
|
618
|
+
}
|
|
619
|
+
if (toolCall.name === 'write_file') {
|
|
620
|
+
// Save lastChanges for `diff` command
|
|
621
|
+
this.lastChanges.push(actions_1.FileChangeSchema.parse(toolCall.parameters));
|
|
622
|
+
this.hadFileChanges = true;
|
|
623
|
+
}
|
|
624
|
+
if (toolCall.name === 'run_terminal_command' &&
|
|
625
|
+
toolCall.parameters.mode === 'user') {
|
|
626
|
+
// Special case: when terminal command is run it as a user command, then no need to reprompt assistant.
|
|
627
|
+
this.responseComplete = true;
|
|
628
|
+
isComplete = true;
|
|
629
|
+
}
|
|
630
|
+
if (toolCall.name === 'run_terminal_command' &&
|
|
631
|
+
toolCall.parameters.mode === 'assistant' &&
|
|
632
|
+
toolCall.parameters.process_type === 'BACKGROUND') {
|
|
633
|
+
this.oneTimeFlags[constants_2.SHOULD_ASK_CONFIG] = true;
|
|
634
|
+
}
|
|
635
|
+
const toolResult = await (0, tool_handlers_1.handleToolCall)(toolCall, (0, project_files_1.getProjectRoot)());
|
|
636
|
+
toolResults.push(toolResult);
|
|
471
637
|
}
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
// Special case: when terminal command is run it as a user command, then no need to reprompt assistant.
|
|
475
|
-
isComplete = true;
|
|
638
|
+
catch (error) {
|
|
639
|
+
console.error((0, picocolors_1.red)(`Error parsing tool call ${toolCall.name}:\n${error}`));
|
|
476
640
|
}
|
|
477
|
-
|
|
478
|
-
|
|
641
|
+
}
|
|
642
|
+
if (toolResults.length > 0 ||
|
|
643
|
+
a.toolCalls.some((call) => call.name === 'end_turn')) {
|
|
644
|
+
console.log();
|
|
479
645
|
}
|
|
480
646
|
// If we had any file changes, update the project context
|
|
481
647
|
if (this.hadFileChanges) {
|
|
482
648
|
this.fileContext = await (0, project_files_1.getProjectFileContext)((0, project_files_1.getProjectRoot)(), {});
|
|
483
649
|
}
|
|
484
650
|
if (!isComplete) {
|
|
485
|
-
|
|
651
|
+
// Append process updates to existing tool results
|
|
652
|
+
toolResults.push(...(0, background_process_manager_1.getBackgroundProcessUpdates)());
|
|
486
653
|
// Continue the prompt with the tool results.
|
|
487
654
|
this.webSocket.sendAction({
|
|
488
655
|
type: 'prompt',
|
|
@@ -490,41 +657,117 @@ class Client {
|
|
|
490
657
|
prompt: undefined,
|
|
491
658
|
agentState: this.agentState,
|
|
492
659
|
toolResults,
|
|
493
|
-
fingerprintId: await this.
|
|
660
|
+
fingerprintId: await this.fingerprintId,
|
|
494
661
|
authToken: this.user?.authToken,
|
|
495
662
|
costMode: this.costMode,
|
|
663
|
+
model: this.model,
|
|
496
664
|
});
|
|
497
665
|
return;
|
|
498
666
|
}
|
|
499
667
|
this.lastToolResults = toolResults;
|
|
500
668
|
xmlStreamParser.end();
|
|
669
|
+
askConfig: if (this.oneTimeFlags[constants_2.SHOULD_ASK_CONFIG] &&
|
|
670
|
+
!this.oneTimeFlags[constants_2.ASKED_CONFIG]) {
|
|
671
|
+
this.oneTimeFlags[constants_2.ASKED_CONFIG] = true;
|
|
672
|
+
if ((0, fs_1.existsSync)(path_1.default.join((0, project_files_1.getProjectRoot)(), constants_3.codebuffConfigFile))) {
|
|
673
|
+
break askConfig;
|
|
674
|
+
}
|
|
675
|
+
console.log((0, picocolors_1.yellow)(`✨ Recommended: run the 'init' command in order to create a configuration file!
|
|
676
|
+
|
|
677
|
+
If you would like background processes (like this one) to run automatically whenever codebuff starts, creating a ${constants_3.codebuffConfigFile} config file can improve your workflow.
|
|
678
|
+
Go to https://www.codebuff.com/config for more information.
|
|
679
|
+
`));
|
|
680
|
+
}
|
|
501
681
|
if (this.agentState) {
|
|
502
682
|
(0, chat_storage_1.setMessages)(this.agentState.messageHistory);
|
|
503
683
|
}
|
|
504
|
-
this
|
|
684
|
+
// Show total credits used for this prompt if significant
|
|
685
|
+
const credits = this.creditsByPromptId[userInputId]?.reduce((a, b) => a + b, 0) ?? 0;
|
|
686
|
+
if (credits >= constants_2.REQUEST_CREDIT_SHOW_THRESHOLD) {
|
|
687
|
+
console.log(`${(0, string_1.pluralize)(credits, 'credit')} used for this request.`);
|
|
688
|
+
}
|
|
689
|
+
// Show auto top-up success message if it occurred during this response
|
|
690
|
+
if (this.pendingTopUpMessageAmount) {
|
|
691
|
+
console.log((0, picocolors_1.green)(`Auto top-up successful! ${this.pendingTopUpMessageAmount.toLocaleString()} credits added.`));
|
|
692
|
+
this.pendingTopUpMessageAmount = null;
|
|
693
|
+
}
|
|
505
694
|
if (this.hadFileChanges) {
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
695
|
+
let checkpointAddendum = '';
|
|
696
|
+
try {
|
|
697
|
+
checkpointAddendum = ` or "checkpoint ${checkpoint_manager_1.checkpointManager.getLatestCheckpoint().id}" to revert`;
|
|
698
|
+
}
|
|
699
|
+
catch (error) {
|
|
700
|
+
// No latest checkpoint, don't show addendum
|
|
701
|
+
}
|
|
702
|
+
console.log(`\nComplete! Type "diff" to review changes${checkpointAddendum}.`);
|
|
511
703
|
this.hadFileChanges = false;
|
|
704
|
+
this.returnControlToUser();
|
|
512
705
|
}
|
|
513
706
|
unsubscribeChunks();
|
|
514
707
|
unsubscribeComplete();
|
|
515
708
|
resolveResponse({ ...a, wasStoppedByUser: false });
|
|
516
709
|
});
|
|
710
|
+
// Reset flags at the start of each response
|
|
711
|
+
this.responseComplete = false;
|
|
517
712
|
return {
|
|
518
713
|
responsePromise,
|
|
519
714
|
stopResponse,
|
|
520
715
|
};
|
|
521
716
|
}
|
|
522
717
|
async getUsage() {
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
718
|
+
try {
|
|
719
|
+
const response = await fetch(`${config_1.backendUrl}/api/usage`, {
|
|
720
|
+
method: 'POST',
|
|
721
|
+
headers: {
|
|
722
|
+
'Content-Type': 'application/json',
|
|
723
|
+
},
|
|
724
|
+
body: JSON.stringify({
|
|
725
|
+
fingerprintId: await this.fingerprintId,
|
|
726
|
+
authToken: this.user?.authToken,
|
|
727
|
+
}),
|
|
728
|
+
});
|
|
729
|
+
const data = await response.json();
|
|
730
|
+
// Use zod schema to validate response
|
|
731
|
+
const parsedResponse = actions_1.UsageReponseSchema.parse(data);
|
|
732
|
+
if (data.type === 'action-error') {
|
|
733
|
+
console.error((0, picocolors_1.red)(data.message));
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
this.setUsage(parsedResponse);
|
|
737
|
+
const usageLink = `${config_1.websiteUrl}/usage`;
|
|
738
|
+
const remainingColor = this.usageData.remainingBalance <= 0
|
|
739
|
+
? picocolors_1.red
|
|
740
|
+
: this.usageData.remainingBalance <= LOW_BALANCE_THRESHOLD
|
|
741
|
+
? picocolors_1.red
|
|
742
|
+
: picocolors_1.green;
|
|
743
|
+
const totalCreditsUsedThisSession = Object.values(this.creditsByPromptId)
|
|
744
|
+
.flat()
|
|
745
|
+
.reduce((sum, credits) => sum + credits, 0);
|
|
746
|
+
console.log(`Session usage: ${totalCreditsUsedThisSession.toLocaleString()}. Credits Remaining: ${remainingColor(this.usageData.remainingBalance.toLocaleString())}`);
|
|
747
|
+
if (this.usageData.next_quota_reset) {
|
|
748
|
+
const resetDate = new Date(this.usageData.next_quota_reset);
|
|
749
|
+
const today = new Date();
|
|
750
|
+
const isToday = resetDate.toDateString() === today.toDateString();
|
|
751
|
+
const dateDisplay = isToday
|
|
752
|
+
? resetDate.toLocaleString() // Show full date and time for today
|
|
753
|
+
: resetDate.toLocaleDateString(); // Just show date otherwise
|
|
754
|
+
console.log(`Free credits will renew on ${dateDisplay}. Details: ${(0, picocolors_1.underline)((0, picocolors_1.blue)(usageLink))}`);
|
|
755
|
+
}
|
|
756
|
+
this.showUsageWarning();
|
|
757
|
+
}
|
|
758
|
+
catch (error) {
|
|
759
|
+
console.error((0, picocolors_1.red)(`Error checking usage: Please reach out to ${process.env.NEXT_PUBLIC_SUPPORT_EMAIL} for help.`));
|
|
760
|
+
// Check if it's a ZodError for more specific feedback
|
|
761
|
+
if (error instanceof zod_1.z.ZodError) {
|
|
762
|
+
console.error((0, picocolors_1.red)('Data validation failed:'), error.errors);
|
|
763
|
+
}
|
|
764
|
+
else {
|
|
765
|
+
console.error(error);
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
finally {
|
|
769
|
+
this.returnControlToUser();
|
|
770
|
+
}
|
|
528
771
|
}
|
|
529
772
|
async warmContextCache() {
|
|
530
773
|
const fileContext = await (0, project_files_1.getProjectFileContext)((0, project_files_1.getProjectRoot)(), {});
|
|
@@ -532,18 +775,16 @@ class Client {
|
|
|
532
775
|
const parsedAction = actions_1.InitResponseSchema.safeParse(a);
|
|
533
776
|
if (!parsedAction.success)
|
|
534
777
|
return;
|
|
778
|
+
// Set initial usage data from the init response
|
|
535
779
|
this.setUsage(parsedAction.data);
|
|
536
780
|
});
|
|
537
|
-
this.webSocket
|
|
538
|
-
.sendAction({
|
|
781
|
+
this.webSocket.sendAction({
|
|
539
782
|
type: 'init',
|
|
540
|
-
fingerprintId: await this.
|
|
783
|
+
fingerprintId: await this.fingerprintId,
|
|
541
784
|
authToken: this.user?.authToken,
|
|
542
785
|
fileContext,
|
|
543
|
-
})
|
|
544
|
-
.catch((e) => {
|
|
545
|
-
// console.error('Error warming context cache', e)
|
|
546
786
|
});
|
|
787
|
+
await this.fetchStoredApiKeyTypes();
|
|
547
788
|
}
|
|
548
789
|
}
|
|
549
790
|
exports.Client = Client;
|