@aixle/insights 0.2.2-staging → 0.2.4-staging
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/cli.js +3 -0
- package/dist/hooks/cursor-hooks-mapper.d.ts +1 -1
- package/dist/hooks/cursor-hooks-mapper.js +3 -1
- package/dist/hooks/cursor-hooks-reader.d.ts +10 -1
- package/dist/hooks/cursor-hooks-reader.js +10 -2
- package/dist/lib/project-resolver.d.ts +8 -0
- package/dist/lib/project-resolver.js +18 -13
- package/dist/readers/claude.d.ts +2 -0
- package/dist/readers/claude.js +3 -1
- package/dist/readers/cursor.d.ts +1 -0
- package/dist/server.js +3 -1
- package/dist/sync.d.ts +8 -0
- package/dist/sync.js +63 -26
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -377,10 +377,12 @@ export async function runOnce(deps, options) {
|
|
|
377
377
|
const lookupToken = pickProjectLookupToken(creds);
|
|
378
378
|
let projectId = null;
|
|
379
379
|
let projectIdSource = "none";
|
|
380
|
+
let repositoryId = null;
|
|
380
381
|
if (lookupToken) {
|
|
381
382
|
const resolution = await runtime.resolveProjectId(undefined, undefined, creds.host, lookupToken, false, creds.insecureHttpAllowed === true);
|
|
382
383
|
projectId = resolution.projectId;
|
|
383
384
|
projectIdSource = resolution.source;
|
|
385
|
+
repositoryId = resolution.repositoryId;
|
|
384
386
|
mcpLog.info("project_attribution_resolved", { project_id: resolution.projectId, source: resolution.source }, false);
|
|
385
387
|
}
|
|
386
388
|
const result = await runtime.syncTelemetryTools({
|
|
@@ -389,6 +391,7 @@ export async function runOnce(deps, options) {
|
|
|
389
391
|
verbose: false,
|
|
390
392
|
projectId,
|
|
391
393
|
projectIdSource,
|
|
394
|
+
repositoryId,
|
|
392
395
|
projectLookupToken: lookupToken,
|
|
393
396
|
pricing: runtime.pricing,
|
|
394
397
|
cursorPricing: resolveCursorPricing(undefined, appDirRuntime),
|
|
@@ -19,4 +19,4 @@ export declare function warnOnCursorVersion(event: HookLogEvent, verbose: boolea
|
|
|
19
19
|
* Map a validated hook event to the CursorPayload contract.
|
|
20
20
|
* Call shouldIngestHookEvent() before this — it does not re-validate.
|
|
21
21
|
*/
|
|
22
|
-
export declare function mapHookEventToPayload(event: HookLogEvent, projectId?: string | null): CursorPayload;
|
|
22
|
+
export declare function mapHookEventToPayload(event: HookLogEvent, projectId?: string | null, repositoryId?: string | null): CursorPayload;
|
|
@@ -50,7 +50,7 @@ export function warnOnCursorVersion(event, verbose) {
|
|
|
50
50
|
* Map a validated hook event to the CursorPayload contract.
|
|
51
51
|
* Call shouldIngestHookEvent() before this — it does not re-validate.
|
|
52
52
|
*/
|
|
53
|
-
export function mapHookEventToPayload(event, projectId) {
|
|
53
|
+
export function mapHookEventToPayload(event, projectId, repositoryId) {
|
|
54
54
|
const workspace = Array.isArray(event.workspace_roots) && typeof event.workspace_roots[0] === "string"
|
|
55
55
|
? event.workspace_roots[0]
|
|
56
56
|
: "unknown";
|
|
@@ -80,5 +80,7 @@ export function mapHookEventToPayload(event, projectId) {
|
|
|
80
80
|
};
|
|
81
81
|
if (projectId)
|
|
82
82
|
payload.project_id = projectId;
|
|
83
|
+
if (repositoryId)
|
|
84
|
+
payload.repository_id = repositoryId;
|
|
83
85
|
return payload;
|
|
84
86
|
}
|
|
@@ -14,7 +14,16 @@ export interface ProcessHooksQueueParams {
|
|
|
14
14
|
on429: (retryAfter: number, quotaExceeded: boolean) => void;
|
|
15
15
|
/** If true, skip events already in state.sessions. */
|
|
16
16
|
skipSeen?: boolean;
|
|
17
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Resolve project + repository attribution for a workspace path. Returning a
|
|
19
|
+
* repositoryId lets hook events carry the same repository_id the sync path
|
|
20
|
+
* stamps. A null repositoryId (or an older resolver returning only a string)
|
|
21
|
+
* simply omits it.
|
|
22
|
+
*/
|
|
23
|
+
resolveProjectId?: (workspace: string) => Promise<{
|
|
24
|
+
projectId: string | null;
|
|
25
|
+
repositoryId: string | null;
|
|
26
|
+
} | string | null>;
|
|
18
27
|
verbose?: boolean;
|
|
19
28
|
}
|
|
20
29
|
export interface ProcessHooksResult {
|
|
@@ -100,10 +100,18 @@ export async function processHooksQueue(params) {
|
|
|
100
100
|
continue;
|
|
101
101
|
}
|
|
102
102
|
let projectId;
|
|
103
|
+
let repositoryId;
|
|
103
104
|
if (resolveProjectId && workspace) {
|
|
104
|
-
|
|
105
|
+
const resolved = await resolveProjectId(workspace);
|
|
106
|
+
if (typeof resolved === "string" || resolved === null) {
|
|
107
|
+
projectId = resolved;
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
projectId = resolved.projectId;
|
|
111
|
+
repositoryId = resolved.repositoryId;
|
|
112
|
+
}
|
|
105
113
|
}
|
|
106
|
-
const payload = mapHookEventToPayload(event, projectId);
|
|
114
|
+
const payload = mapHookEventToPayload(event, projectId, repositoryId);
|
|
107
115
|
const ok = await postEvent(payload, host, token, { on429, allowInsecureHttp });
|
|
108
116
|
if (ok) {
|
|
109
117
|
totalSent++;
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
export interface ProjectResolution {
|
|
2
2
|
projectId: string | null;
|
|
3
|
+
/**
|
|
4
|
+
* Repository that owns the resolved project's attribution, when the API
|
|
5
|
+
* resolved one from the git remote. Only populated on auto-detect (the API
|
|
6
|
+
* only knows the repository via the remote lookup). Null for flag/config
|
|
7
|
+
* attribution — an explicit project id carries no repository context.
|
|
8
|
+
*/
|
|
9
|
+
repositoryId: string | null;
|
|
3
10
|
source: "flag" | "config" | "auto-detect" | "auto-detect-not-found" | "none";
|
|
4
11
|
}
|
|
5
12
|
export interface LookupResult {
|
|
6
13
|
project_id: string;
|
|
14
|
+
repository_id?: string | null;
|
|
7
15
|
name: string;
|
|
8
16
|
}
|
|
9
17
|
export declare function resolveProjectId(flagValue: string | undefined, configValue: string | undefined, host: string, token: string, verbose: boolean, allowInsecureHttp?: boolean): Promise<ProjectResolution>;
|
|
@@ -10,29 +10,31 @@ export async function resolveProjectId(flagValue, configValue, host, token, verb
|
|
|
10
10
|
const flag = coerce(flagValue);
|
|
11
11
|
const config = coerce(configValue);
|
|
12
12
|
if (flag !== undefined)
|
|
13
|
-
return { projectId: flag, source: "flag" };
|
|
13
|
+
return { projectId: flag, repositoryId: null, source: "flag" };
|
|
14
14
|
if (config !== undefined)
|
|
15
|
-
return { projectId: config, source: "config" };
|
|
15
|
+
return { projectId: config, repositoryId: null, source: "config" };
|
|
16
16
|
const gitRemote = getGitRemote(verbose);
|
|
17
17
|
if (gitRemote === null)
|
|
18
|
-
return { projectId: null, source: "none" };
|
|
18
|
+
return { projectId: null, repositoryId: null, source: "none" };
|
|
19
19
|
const result = await lookupProjectByRemote(gitRemote, host, token, verbose, allowInsecureHttp);
|
|
20
20
|
if (result === "not-found")
|
|
21
|
-
return { projectId: null, source: "auto-detect-not-found" };
|
|
22
|
-
if (result !== null)
|
|
23
|
-
return { projectId: result.project_id, source: "auto-detect" };
|
|
24
|
-
|
|
21
|
+
return { projectId: null, repositoryId: null, source: "auto-detect-not-found" };
|
|
22
|
+
if (result !== null) {
|
|
23
|
+
return { projectId: result.project_id, repositoryId: result.repository_id ?? null, source: "auto-detect" };
|
|
24
|
+
}
|
|
25
|
+
return { projectId: null, repositoryId: null, source: "none" };
|
|
25
26
|
}
|
|
26
27
|
export async function resolveProjectIdForRepoPath(repoPath, host, token, verbose, allowInsecureHttp = false) {
|
|
27
28
|
const gitRemote = getGitRemoteForPath(repoPath, verbose);
|
|
28
29
|
if (gitRemote === null)
|
|
29
|
-
return { projectId: null, source: "none" };
|
|
30
|
+
return { projectId: null, repositoryId: null, source: "none" };
|
|
30
31
|
const result = await lookupProjectByRemote(gitRemote, host, token, verbose, allowInsecureHttp);
|
|
31
32
|
if (result === "not-found")
|
|
32
|
-
return { projectId: null, source: "auto-detect-not-found" };
|
|
33
|
-
if (result !== null)
|
|
34
|
-
return { projectId: result.project_id, source: "auto-detect" };
|
|
35
|
-
|
|
33
|
+
return { projectId: null, repositoryId: null, source: "auto-detect-not-found" };
|
|
34
|
+
if (result !== null) {
|
|
35
|
+
return { projectId: result.project_id, repositoryId: result.repository_id ?? null, source: "auto-detect" };
|
|
36
|
+
}
|
|
37
|
+
return { projectId: null, repositoryId: null, source: "none" };
|
|
36
38
|
}
|
|
37
39
|
export function getGitRemote(verbose) {
|
|
38
40
|
try {
|
|
@@ -145,7 +147,10 @@ function isLookupResponse(body) {
|
|
|
145
147
|
if (typeof d !== "object" || d === null)
|
|
146
148
|
return false;
|
|
147
149
|
const data = d;
|
|
148
|
-
|
|
150
|
+
if (typeof data.project_id !== "string" || typeof data.name !== "string")
|
|
151
|
+
return false;
|
|
152
|
+
// repository_id is optional (older servers omit it) but must be a string when present.
|
|
153
|
+
return data.repository_id == null || typeof data.repository_id === "string";
|
|
149
154
|
}
|
|
150
155
|
/**
|
|
151
156
|
* Cursor `recentCommit.repoName` is typically `owner/repo` (GitHub-style slug), not a full
|
package/dist/readers/claude.d.ts
CHANGED
|
@@ -72,6 +72,7 @@ export interface ClaudePayload extends IngestPayload {
|
|
|
72
72
|
cost_usd: number | null;
|
|
73
73
|
occurred_at: string;
|
|
74
74
|
project_id?: string;
|
|
75
|
+
repository_id?: string;
|
|
75
76
|
metadata: {
|
|
76
77
|
session_id: string;
|
|
77
78
|
claude_session_id: string;
|
|
@@ -121,6 +122,7 @@ export type ClaudeMappedPayload = ClaudePayload | ClaudeDerivativePayload;
|
|
|
121
122
|
/** Options for mapTranscriptTurn. */
|
|
122
123
|
export interface ToClaudePayloadOptions {
|
|
123
124
|
projectId?: string | null;
|
|
125
|
+
repositoryId?: string | null;
|
|
124
126
|
pricing?: PricingTable;
|
|
125
127
|
}
|
|
126
128
|
/** Finds all *.jsonl transcript files across both Claude project directory roots. */
|
package/dist/readers/claude.js
CHANGED
|
@@ -395,7 +395,7 @@ export async function parseTranscriptFile(filePath, verbose = false) {
|
|
|
395
395
|
}
|
|
396
396
|
/** Converts a Claude transcript turn to parent chat and derivative tool-use payloads. */
|
|
397
397
|
export function mapTranscriptTurn(turn, options) {
|
|
398
|
-
const { projectId, pricing } = options ?? {};
|
|
398
|
+
const { projectId, repositoryId, pricing } = options ?? {};
|
|
399
399
|
const baseInputTokens = Math.max(0, turn.tokensIn - turn.cacheWriteTokens - turn.cacheReadTokens);
|
|
400
400
|
const cost = pricing
|
|
401
401
|
? calculateCost(turn.model, baseInputTokens, turn.tokensOut, turn.cacheWriteTokens, turn.cacheReadTokens, pricing)
|
|
@@ -438,6 +438,8 @@ export function mapTranscriptTurn(turn, options) {
|
|
|
438
438
|
}
|
|
439
439
|
if (projectId)
|
|
440
440
|
payload.project_id = projectId;
|
|
441
|
+
if (repositoryId)
|
|
442
|
+
payload.repository_id = repositoryId;
|
|
441
443
|
const derivatives = turn.toolUses.map((toolUse) => {
|
|
442
444
|
const derivative = {
|
|
443
445
|
tool_name: "claude_code",
|
package/dist/readers/cursor.d.ts
CHANGED
|
@@ -122,6 +122,7 @@ export interface CursorPayload extends IngestPayload {
|
|
|
122
122
|
cost_usd: number;
|
|
123
123
|
occurred_at: string;
|
|
124
124
|
project_id?: string;
|
|
125
|
+
repository_id?: string;
|
|
125
126
|
metadata: CursorPayloadMetadata;
|
|
126
127
|
}
|
|
127
128
|
export declare function toEpochMs(timestamp: number | string | null | undefined): number | null;
|
package/dist/server.js
CHANGED
|
@@ -80,7 +80,7 @@ let cachedProjectResolution = null;
|
|
|
80
80
|
async function getProjectResolutionForSync(creds) {
|
|
81
81
|
const token = pickProjectLookupToken(creds);
|
|
82
82
|
if (!token)
|
|
83
|
-
return { projectId: null, source: "none" };
|
|
83
|
+
return { projectId: null, repositoryId: null, source: "none" };
|
|
84
84
|
const gitRemote = getGitRemote(false) ?? "no-remote";
|
|
85
85
|
const cacheKey = `${creds.host}|${token}|${gitRemote}`;
|
|
86
86
|
if (cachedProjectResolution?.key === cacheKey) {
|
|
@@ -112,6 +112,7 @@ async function executeSync(parsed) {
|
|
|
112
112
|
verbose: false,
|
|
113
113
|
projectId: projectResolution.projectId,
|
|
114
114
|
projectIdSource: projectResolution.source,
|
|
115
|
+
repositoryId: projectResolution.repositoryId,
|
|
115
116
|
projectLookupToken: pickProjectLookupToken(creds),
|
|
116
117
|
pricing: defaultPricing(),
|
|
117
118
|
cursorPricing: cursorPricingForSync(),
|
|
@@ -246,6 +247,7 @@ export async function startServer() {
|
|
|
246
247
|
verbose: false,
|
|
247
248
|
projectId: projectResolution.projectId,
|
|
248
249
|
projectIdSource: projectResolution.source,
|
|
250
|
+
repositoryId: projectResolution.repositoryId,
|
|
249
251
|
projectLookupToken: pickProjectLookupToken(creds),
|
|
250
252
|
pricing: defaultPricing(),
|
|
251
253
|
scopeDir: process.cwd(),
|
package/dist/sync.d.ts
CHANGED
|
@@ -26,6 +26,12 @@ export interface SyncOptions {
|
|
|
26
26
|
projectIdSource?: ProjectResolution["source"];
|
|
27
27
|
/** Mirrors StoredCredentials.insecureHttpAllowed — set when `init --insecure` was used for this host. */
|
|
28
28
|
allowInsecureHttp?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Repository resolved from the same remote lookup as the scoped `projectId`.
|
|
31
|
+
* Only meaningful alongside a pre-resolved scoped `projectId` — carries the
|
|
32
|
+
* repository attribution the lookup returned so scoped turns don't lose it.
|
|
33
|
+
*/
|
|
34
|
+
repositoryId?: string | null;
|
|
29
35
|
pricing: PricingTable;
|
|
30
36
|
appDir?: string;
|
|
31
37
|
transcriptBaseDirs?: string[];
|
|
@@ -44,6 +50,8 @@ export interface MultiSyncOptions {
|
|
|
44
50
|
verbose: boolean;
|
|
45
51
|
projectId: string | null;
|
|
46
52
|
projectIdSource?: ProjectResolution["source"];
|
|
53
|
+
/** See SyncOptions.repositoryId. */
|
|
54
|
+
repositoryId?: string | null;
|
|
47
55
|
/** Token for GET /projects/lookup (defaults to cursor ingest token in cursor slice). */
|
|
48
56
|
projectLookupToken?: string | null;
|
|
49
57
|
pricing: PricingTable;
|
package/dist/sync.js
CHANGED
|
@@ -103,21 +103,24 @@ function explicitProjectId(projectId, projectIdSource) {
|
|
|
103
103
|
? projectId
|
|
104
104
|
: undefined;
|
|
105
105
|
}
|
|
106
|
-
async function
|
|
106
|
+
async function resolveAttributionForRepoPathCached(repoPath, host, token, verbose, cache, allowInsecureHttp = false) {
|
|
107
|
+
const empty = { projectId: null, repositoryId: null };
|
|
107
108
|
const normalized = normalizeRepoPathCandidate(repoPath);
|
|
108
109
|
if (normalized === null)
|
|
109
|
-
return
|
|
110
|
+
return empty;
|
|
110
111
|
if (cache.has(normalized))
|
|
111
|
-
return cache.get(normalized) ??
|
|
112
|
+
return cache.get(normalized) ?? empty;
|
|
112
113
|
const canonicalRemote = getGitRemoteForPath(normalized, verbose);
|
|
113
114
|
if (!canonicalRemote) {
|
|
114
|
-
cache.set(normalized,
|
|
115
|
-
return
|
|
115
|
+
cache.set(normalized, empty);
|
|
116
|
+
return empty;
|
|
116
117
|
}
|
|
117
118
|
const result = await lookupProjectByRemote(canonicalRemote, host, token, verbose, allowInsecureHttp);
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
119
|
+
const resolved = result && typeof result === "object" && "project_id" in result
|
|
120
|
+
? { projectId: result.project_id, repositoryId: result.repository_id ?? null }
|
|
121
|
+
: empty;
|
|
122
|
+
cache.set(normalized, resolved);
|
|
123
|
+
return resolved;
|
|
121
124
|
}
|
|
122
125
|
/**
|
|
123
126
|
* The repo path for a Cursor payload, normalized and safe to hand to project
|
|
@@ -143,6 +146,7 @@ export function cursorRepoPathFromPayload(payload) {
|
|
|
143
146
|
}
|
|
144
147
|
async function runClaudeSlice(options) {
|
|
145
148
|
const { token, host, dryRun, verbose, projectId, pricing, allowInsecureHttp = false } = options;
|
|
149
|
+
const preResolvedRepositoryId = options.repositoryId ?? undefined;
|
|
146
150
|
const appDir = options.appDir ?? getAppDir();
|
|
147
151
|
const backoffKey = credentialStateKey(host, token);
|
|
148
152
|
const errors = [];
|
|
@@ -233,14 +237,22 @@ async function runClaudeSlice(options) {
|
|
|
233
237
|
// (e.g. MCP server launched from a non-git cwd, or stuck null in module cache),
|
|
234
238
|
// fall back to per-turn cwd lookup. The lookup cache dedupes by path so this is
|
|
235
239
|
// effectively one network call per unique cwd per sync.
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
240
|
+
// The scoped pre-resolve comes from the same remote lookup as projectId, so it
|
|
241
|
+
// carries repository_id too. An explicit flag/config projectId carries no
|
|
242
|
+
// repository context, so repository stays undefined there.
|
|
243
|
+
const preResolved = scopeDir ? projectId : explicitProject;
|
|
244
|
+
let resolvedProjectId = preResolved ?? undefined;
|
|
245
|
+
let resolvedRepositoryId = scopeDir && preResolved != null ? preResolvedRepositoryId : undefined;
|
|
246
|
+
if (resolvedProjectId === undefined) {
|
|
247
|
+
const attribution = await resolveAttributionForRepoPathCached(turn.cwd, host, token, verbose, projectLookupCache, allowInsecureHttp);
|
|
248
|
+
resolvedProjectId = attribution.projectId ?? undefined;
|
|
249
|
+
resolvedRepositoryId = attribution.repositoryId ?? undefined;
|
|
250
|
+
}
|
|
251
|
+
const payloads = mapClaudeTranscriptTurn(turn, {
|
|
252
|
+
projectId: resolvedProjectId,
|
|
253
|
+
repositoryId: resolvedRepositoryId,
|
|
254
|
+
pricing,
|
|
255
|
+
});
|
|
244
256
|
if (!payloads?.length)
|
|
245
257
|
continue;
|
|
246
258
|
const parentPayload = payloads[0];
|
|
@@ -315,6 +327,7 @@ async function runClaudeSlice(options) {
|
|
|
315
327
|
}
|
|
316
328
|
async function runCursorSlice(params) {
|
|
317
329
|
const { token, host, dryRun, verbose, projectId, projectIdSource, projectLookupToken, allowInsecureHttp = false, appDir, cursorBaseDir, cursorTranscriptProjectDirs, scopeDir, fullScan = false, cursorPricing = resolveCursorPricing(undefined, appDir), } = params;
|
|
330
|
+
const preResolvedRepositoryId = params.repositoryId ?? undefined;
|
|
318
331
|
const backoffKey = credentialStateKey(host, token);
|
|
319
332
|
// Read state first so we can restore a persisted rate-limit backoff from a prior process.
|
|
320
333
|
const stateBefore = readState(appDir, host, token);
|
|
@@ -369,12 +382,26 @@ async function runCursorSlice(params) {
|
|
|
369
382
|
if (ws && isRepoPathWithinRoot(ws, scopeDir)) {
|
|
370
383
|
// Same fallback as Claude: when the pre-resolved projectId is null, do a
|
|
371
384
|
// per-payload lookup from the payload's workspace. Cache dedupes by path.
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
if (
|
|
375
|
-
payload.project_id =
|
|
376
|
-
|
|
377
|
-
|
|
385
|
+
// The scoped pre-resolve comes from the same remote lookup as projectId,
|
|
386
|
+
// so it carries repository_id too; a fresh lookup sets it otherwise.
|
|
387
|
+
if (projectId) {
|
|
388
|
+
payload.project_id = projectId;
|
|
389
|
+
if (preResolvedRepositoryId)
|
|
390
|
+
payload.repository_id = preResolvedRepositoryId;
|
|
391
|
+
else
|
|
392
|
+
delete payload.repository_id;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
const attribution = await resolveAttributionForRepoPathCached(ws, host, lookupToken, verbose, projectLookupCache, allowInsecureHttp);
|
|
396
|
+
if (attribution.projectId)
|
|
397
|
+
payload.project_id = attribution.projectId;
|
|
398
|
+
else
|
|
399
|
+
delete payload.project_id;
|
|
400
|
+
if (attribution.repositoryId)
|
|
401
|
+
payload.repository_id = attribution.repositoryId;
|
|
402
|
+
else
|
|
403
|
+
delete payload.repository_id;
|
|
404
|
+
}
|
|
378
405
|
inScope.push(payload);
|
|
379
406
|
}
|
|
380
407
|
else if (verbose) {
|
|
@@ -390,11 +417,15 @@ async function runCursorSlice(params) {
|
|
|
390
417
|
continue;
|
|
391
418
|
for (const payload of group.payloads) {
|
|
392
419
|
const repoPath = cursorRepoPathFromPayload(payload);
|
|
393
|
-
const
|
|
394
|
-
if (
|
|
395
|
-
payload.project_id =
|
|
420
|
+
const attribution = await resolveAttributionForRepoPathCached(repoPath, host, lookupToken, verbose, projectLookupCache, allowInsecureHttp);
|
|
421
|
+
if (attribution.projectId)
|
|
422
|
+
payload.project_id = attribution.projectId;
|
|
396
423
|
else
|
|
397
424
|
delete payload.project_id;
|
|
425
|
+
if (attribution.repositoryId)
|
|
426
|
+
payload.repository_id = attribution.repositoryId;
|
|
427
|
+
else
|
|
428
|
+
delete payload.repository_id;
|
|
398
429
|
}
|
|
399
430
|
}
|
|
400
431
|
}
|
|
@@ -530,7 +561,7 @@ async function runCursorSlice(params) {
|
|
|
530
561
|
on429,
|
|
531
562
|
resolveProjectId: explicitProject
|
|
532
563
|
? undefined
|
|
533
|
-
: (workspace) =>
|
|
564
|
+
: (workspace) => resolveAttributionForRepoPathCached(workspace, host, lookupToken, verbose, projectLookupCache, allowInsecureHttp),
|
|
534
565
|
verbose,
|
|
535
566
|
});
|
|
536
567
|
totalSent += hooksResult.sent;
|
|
@@ -578,6 +609,7 @@ export async function syncTelemetryTools(options) {
|
|
|
578
609
|
}
|
|
579
610
|
try {
|
|
580
611
|
const { credentials, dryRun, verbose, projectId, projectIdSource, projectLookupToken, pricing, scopeDir } = options;
|
|
612
|
+
const repositoryId = options.repositoryId ?? null;
|
|
581
613
|
const host = credentials.host;
|
|
582
614
|
const appDirResolved = options.appDir ?? getAppDir();
|
|
583
615
|
const cursorPricing = options.cursorPricing ?? resolveCursorPricing(undefined, appDirResolved);
|
|
@@ -617,6 +649,7 @@ export async function syncTelemetryTools(options) {
|
|
|
617
649
|
verbose,
|
|
618
650
|
projectId,
|
|
619
651
|
allowInsecureHttp: credentials.insecureHttpAllowed === true,
|
|
652
|
+
repositoryId,
|
|
620
653
|
pricing,
|
|
621
654
|
appDir,
|
|
622
655
|
transcriptBaseDirs: options.transcriptBaseDirs,
|
|
@@ -632,6 +665,7 @@ export async function syncTelemetryTools(options) {
|
|
|
632
665
|
verbose,
|
|
633
666
|
projectId,
|
|
634
667
|
projectIdSource,
|
|
668
|
+
repositoryId,
|
|
635
669
|
projectLookupToken,
|
|
636
670
|
allowInsecureHttp: credentials.insecureHttpAllowed === true,
|
|
637
671
|
appDir,
|
|
@@ -699,9 +733,12 @@ export async function syncOnce(options) {
|
|
|
699
733
|
dryRun: options.dryRun,
|
|
700
734
|
verbose: options.verbose,
|
|
701
735
|
projectId: options.projectId,
|
|
736
|
+
projectIdSource: options.projectIdSource,
|
|
737
|
+
repositoryId: options.repositoryId,
|
|
702
738
|
pricing: options.pricing,
|
|
703
739
|
appDir: options.appDir,
|
|
704
740
|
transcriptBaseDirs: options.transcriptBaseDirs,
|
|
741
|
+
scopeDir: options.scopeDir,
|
|
705
742
|
tools: ["claude_code"],
|
|
706
743
|
});
|
|
707
744
|
}
|
package/package.json
CHANGED