codeep 3.2.0 → 3.2.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/dist/renderer/agentExecution.js +10 -3
- package/dist/renderer/main.js +5 -1
- package/dist/utils/codeepCloud.d.ts +10 -3
- package/dist/utils/codeepCloud.js +45 -2
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -456,14 +456,17 @@ export async function executeAgentTask(task, dryRun, ctx) {
|
|
|
456
456
|
// even if the user switched model mid-session. Only this run's delta
|
|
457
457
|
// (since tokenReportStart) is reported; the cumulative store is preserved.
|
|
458
458
|
const costBreakdown = getCostBreakdown(tokenReportStart);
|
|
459
|
+
// Consumed exactly once per run, before anything branches on it: the notice
|
|
460
|
+
// path is conditional (no credentials, or a run too short to notify), and
|
|
461
|
+
// reading it inside that branch left the stat blind on every run that did
|
|
462
|
+
// not send a notification.
|
|
463
|
+
const startedFromPhone = takeRunFromPhone();
|
|
459
464
|
// Told once the run is over, and only when it ran long enough that you
|
|
460
465
|
// could plausibly have stopped watching. Awaited so the process does not
|
|
461
466
|
// exit from under the request, but never allowed to fail the run.
|
|
462
467
|
if (noticeCredentials) {
|
|
463
468
|
const elapsedMs = Date.now() - runStartedAt;
|
|
464
|
-
|
|
465
|
-
// the flag set for whatever the terminal does next.
|
|
466
|
-
const fromPhone = takeRunFromPhone();
|
|
469
|
+
const fromPhone = startedFromPhone;
|
|
467
470
|
// The one-minute threshold exists so a phone is not buzzed about work you
|
|
468
471
|
// watched finish. It has no business gating a run the phone itself asked
|
|
469
472
|
// for: that answer was wanted whether it took ten seconds or ten minutes,
|
|
@@ -486,6 +489,10 @@ export async function executeAgentTask(task, dryRun, ctx) {
|
|
|
486
489
|
}
|
|
487
490
|
}
|
|
488
491
|
const sharedFields = {
|
|
492
|
+
// `fromPhone` is read above, where the notice consumes it. Captured here
|
|
493
|
+
// too because the stats event is the only place it can answer anything
|
|
494
|
+
// later — see docs/ios-decision.md.
|
|
495
|
+
fromPhone: startedFromPhone,
|
|
489
496
|
sessionId,
|
|
490
497
|
sessionName: displayName,
|
|
491
498
|
messageCount: app.getMessages().length,
|
package/dist/renderer/main.js
CHANGED
|
@@ -17,7 +17,7 @@ import { getCurrentVersion, checkForUpdates, getUpdateInstructions } from '../ut
|
|
|
17
17
|
import { getProviderList, isNoApiKeyProvider, resolveReasoningTier } from '../config/providers.js';
|
|
18
18
|
import { getSessionStats, getCostBreakdown, getRecordCount } from '../utils/tokenTracker.js';
|
|
19
19
|
import { getGitStatus, isGitRepository } from '../utils/git.js';
|
|
20
|
-
import { reportStats, syncSession, generateProjectId } from '../utils/codeepCloud.js';
|
|
20
|
+
import { reportStats, syncSession, generateProjectId, ensureDeviceRegistered } from '../utils/codeepCloud.js';
|
|
21
21
|
import { expandFileAndFolderMentions, expandGitMentions } from '../utils/mentions.js';
|
|
22
22
|
import { expandWebMentions } from '../utils/webFetch.js';
|
|
23
23
|
import { handleCommand as dispatchCommand } from './commands.js';
|
|
@@ -627,6 +627,10 @@ Commands (in chat):
|
|
|
627
627
|
return;
|
|
628
628
|
}
|
|
629
629
|
await loadAllApiKeys();
|
|
630
|
+
// Re-announce this device to the dashboard. Cheap, fire-and-forget, and it
|
|
631
|
+
// repairs a machine whose one registration at link time happened to fail —
|
|
632
|
+
// which until now left it syncing, unlisted, and impossible to revoke.
|
|
633
|
+
ensureDeviceRegistered();
|
|
630
634
|
let apiKey = await loadApiKey();
|
|
631
635
|
if (!apiKey && !isNoApiKeyProvider(config.get('provider'))) {
|
|
632
636
|
const newKey = await showLoginFlow();
|
|
@@ -23,6 +23,15 @@ export interface StatsPayload {
|
|
|
23
23
|
projectId?: string;
|
|
24
24
|
language?: string;
|
|
25
25
|
isGit?: boolean;
|
|
26
|
+
/**
|
|
27
|
+
* Whether this run was started from a phone rather than at the terminal.
|
|
28
|
+
*
|
|
29
|
+
* Recorded to answer whether a Codeep iOS app is worth building with
|
|
30
|
+
* behaviour instead of opinion: "would you like an iOS app?" costs nothing
|
|
31
|
+
* to say yes to, while actually driving a run from a phone — which the
|
|
32
|
+
* Telegram inbox has allowed since 3.1.0 — is a thing somebody did.
|
|
33
|
+
*/
|
|
34
|
+
fromPhone?: boolean;
|
|
26
35
|
inputTokens?: number;
|
|
27
36
|
outputTokens?: number;
|
|
28
37
|
/** Anthropic prompt caching: tokens written to cache (billed ~1.25× input).
|
|
@@ -33,9 +42,7 @@ export interface StatsPayload {
|
|
|
33
42
|
cacheReadTokens?: number;
|
|
34
43
|
estimatedCost?: number;
|
|
35
44
|
}
|
|
36
|
-
|
|
37
|
-
* Generate a stable project ID from the project root path.
|
|
38
|
-
*/
|
|
45
|
+
export declare function ensureDeviceRegistered(): void;
|
|
39
46
|
export declare function generateProjectId(projectRoot: string): string;
|
|
40
47
|
/**
|
|
41
48
|
* Fire-and-forget stats report. Only sends if github_id is configured.
|
|
@@ -51,10 +51,18 @@ export async function runAccountFlow() {
|
|
|
51
51
|
console.error('\n Could not reach codeep.dev. Check your internet connection.\n');
|
|
52
52
|
return;
|
|
53
53
|
}
|
|
54
|
+
// Say that the browser can be somewhere else, because it can and nothing
|
|
55
|
+
// said so. On a server there is no browser to open, and "paste the URL
|
|
56
|
+
// manually" reads as "into this machine's browser" — which is how people
|
|
57
|
+
// end up signing in to GitHub on a box they did not want their account on.
|
|
58
|
+
// The code grants nothing by itself: it is claimed by whoever opens it while
|
|
59
|
+
// already signed in, and it expires in five minutes.
|
|
54
60
|
const url = `${API_BASE}/auth/cli?code=${code}`;
|
|
55
|
-
console.log('\n
|
|
61
|
+
console.log('\n Open this link to approve — on this machine, or any device');
|
|
62
|
+
console.log(' where you are already signed in to codeep.dev:\n');
|
|
56
63
|
console.log(` ${url}\n`);
|
|
57
|
-
console.log('
|
|
64
|
+
console.log(' The link expires in 5 minutes. This machine then gets its own');
|
|
65
|
+
console.log(' token, revocable from Settings -> Connected devices.\n');
|
|
58
66
|
openBrowser(url);
|
|
59
67
|
// Poll for authorization
|
|
60
68
|
process.stdout.write(' Waiting for GitHub login');
|
|
@@ -100,6 +108,41 @@ export async function runAccountFlow() {
|
|
|
100
108
|
/**
|
|
101
109
|
* Generate a stable project ID from the project root path.
|
|
102
110
|
*/
|
|
111
|
+
/**
|
|
112
|
+
* Tell the server this device exists, on every start.
|
|
113
|
+
*
|
|
114
|
+
* Registration used to happen once, at link time, inside a `catch {}` that
|
|
115
|
+
* ignored failures — so a network blip during `codeep account` left a machine
|
|
116
|
+
* with a working token and no `user_devices` row. It synced fine, did not
|
|
117
|
+
* appear under Connected devices, and could not be revoked, because Revoke
|
|
118
|
+
* deletes a row that was never written. That is the worst of the three
|
|
119
|
+
* outcomes: working, invisible, and permanent.
|
|
120
|
+
*
|
|
121
|
+
* Repeating it makes a missed registration self-heal on the next run, and
|
|
122
|
+
* turns `last_seen` into something true — it previously only moved at link
|
|
123
|
+
* time, so the dashboard's "last seen" was really "linked".
|
|
124
|
+
*
|
|
125
|
+
* Once per process, fire-and-forget: it is a heartbeat, not a gate, and must
|
|
126
|
+
* never delay or fail a start. The next start retries it anyway.
|
|
127
|
+
*/
|
|
128
|
+
let deviceRegistered = false;
|
|
129
|
+
export function ensureDeviceRegistered() {
|
|
130
|
+
if (deviceRegistered)
|
|
131
|
+
return;
|
|
132
|
+
const syncToken = getSyncToken();
|
|
133
|
+
if (!syncToken)
|
|
134
|
+
return; // not linked; nothing to register
|
|
135
|
+
deviceRegistered = true;
|
|
136
|
+
void fetch(`${API_BASE}/api/auth/cli/device`, {
|
|
137
|
+
method: 'POST',
|
|
138
|
+
headers: { 'Content-Type': 'application/json', 'x-sync-token': syncToken },
|
|
139
|
+
body: JSON.stringify({ deviceId: getDeviceId(), hostname: hostname() }),
|
|
140
|
+
}).catch(() => {
|
|
141
|
+
// Allow the next call in this process to try again — a start that fails
|
|
142
|
+
// here should not mark the device as registered for good.
|
|
143
|
+
deviceRegistered = false;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
103
146
|
export function generateProjectId(projectRoot) {
|
|
104
147
|
// Normalize: remove trailing slash, resolve to real path format
|
|
105
148
|
const normalized = projectRoot.replace(/\/+$/, '').toLowerCase();
|
package/dist/version.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const VERSION = "3.2.
|
|
1
|
+
export declare const VERSION = "3.2.2";
|
package/dist/version.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
// AUTO-GENERATED by scripts/gen-version.js — do not edit by hand.
|
|
2
2
|
// Baked from package.json at build time so the bun-compiled binary reports
|
|
3
3
|
// the right version (it has no package.json on disk to read at runtime).
|
|
4
|
-
export const VERSION = '3.2.
|
|
4
|
+
export const VERSION = '3.2.2';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "codeep",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.2",
|
|
4
4
|
"description": "AI-powered coding assistant built for the terminal. Multiple LLM providers, project-aware context, and a seamless development workflow.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|