@vkenliu/adit-cloud 0.2.0

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.
Files changed (98) hide show
  1. package/LICENSE +21 -0
  2. package/dist/auth/credentials.d.ts +62 -0
  3. package/dist/auth/credentials.d.ts.map +1 -0
  4. package/dist/auth/credentials.js +151 -0
  5. package/dist/auth/credentials.js.map +1 -0
  6. package/dist/auth/device-auth.d.ts +40 -0
  7. package/dist/auth/device-auth.d.ts.map +1 -0
  8. package/dist/auth/device-auth.js +84 -0
  9. package/dist/auth/device-auth.js.map +1 -0
  10. package/dist/config.d.ts +48 -0
  11. package/dist/config.d.ts.map +1 -0
  12. package/dist/config.js +80 -0
  13. package/dist/config.js.map +1 -0
  14. package/dist/http/client.d.ts +28 -0
  15. package/dist/http/client.d.ts.map +1 -0
  16. package/dist/http/client.js +229 -0
  17. package/dist/http/client.js.map +1 -0
  18. package/dist/http/errors.d.ts +19 -0
  19. package/dist/http/errors.d.ts.map +1 -0
  20. package/dist/http/errors.js +31 -0
  21. package/dist/http/errors.js.map +1 -0
  22. package/dist/index.d.ts +20 -0
  23. package/dist/index.d.ts.map +1 -0
  24. package/dist/index.js +25 -0
  25. package/dist/index.js.map +1 -0
  26. package/dist/project-link/auto-link.d.ts +30 -0
  27. package/dist/project-link/auto-link.d.ts.map +1 -0
  28. package/dist/project-link/auto-link.js +91 -0
  29. package/dist/project-link/auto-link.js.map +1 -0
  30. package/dist/project-link/bulk-task.d.ts +15 -0
  31. package/dist/project-link/bulk-task.d.ts.map +1 -0
  32. package/dist/project-link/bulk-task.js +107 -0
  33. package/dist/project-link/bulk-task.js.map +1 -0
  34. package/dist/project-link/cache.d.ts +22 -0
  35. package/dist/project-link/cache.d.ts.map +1 -0
  36. package/dist/project-link/cache.js +82 -0
  37. package/dist/project-link/cache.js.map +1 -0
  38. package/dist/project-link/doc-discovery.d.ts +35 -0
  39. package/dist/project-link/doc-discovery.d.ts.map +1 -0
  40. package/dist/project-link/doc-discovery.js +260 -0
  41. package/dist/project-link/doc-discovery.js.map +1 -0
  42. package/dist/project-link/git-collector.d.ts +88 -0
  43. package/dist/project-link/git-collector.d.ts.map +1 -0
  44. package/dist/project-link/git-collector.js +250 -0
  45. package/dist/project-link/git-collector.js.map +1 -0
  46. package/dist/project-link/index.d.ts +15 -0
  47. package/dist/project-link/index.d.ts.map +1 -0
  48. package/dist/project-link/index.js +20 -0
  49. package/dist/project-link/index.js.map +1 -0
  50. package/dist/project-link/intent-command.d.ts +23 -0
  51. package/dist/project-link/intent-command.d.ts.map +1 -0
  52. package/dist/project-link/intent-command.js +104 -0
  53. package/dist/project-link/intent-command.js.map +1 -0
  54. package/dist/project-link/link-command.d.ts +26 -0
  55. package/dist/project-link/link-command.d.ts.map +1 -0
  56. package/dist/project-link/link-command.js +350 -0
  57. package/dist/project-link/link-command.js.map +1 -0
  58. package/dist/project-link/qualify.d.ts +25 -0
  59. package/dist/project-link/qualify.d.ts.map +1 -0
  60. package/dist/project-link/qualify.js +45 -0
  61. package/dist/project-link/qualify.js.map +1 -0
  62. package/dist/project-link/types.d.ts +254 -0
  63. package/dist/project-link/types.d.ts.map +1 -0
  64. package/dist/project-link/types.js +8 -0
  65. package/dist/project-link/types.js.map +1 -0
  66. package/dist/sync/auto-sync.d.ts +42 -0
  67. package/dist/sync/auto-sync.d.ts.map +1 -0
  68. package/dist/sync/auto-sync.js +136 -0
  69. package/dist/sync/auto-sync.js.map +1 -0
  70. package/dist/sync/conflicts.d.ts +27 -0
  71. package/dist/sync/conflicts.d.ts.map +1 -0
  72. package/dist/sync/conflicts.js +28 -0
  73. package/dist/sync/conflicts.js.map +1 -0
  74. package/dist/sync/engine.d.ts +76 -0
  75. package/dist/sync/engine.d.ts.map +1 -0
  76. package/dist/sync/engine.js +152 -0
  77. package/dist/sync/engine.js.map +1 -0
  78. package/dist/sync/serializer.d.ts +123 -0
  79. package/dist/sync/serializer.d.ts.map +1 -0
  80. package/dist/sync/serializer.js +280 -0
  81. package/dist/sync/serializer.js.map +1 -0
  82. package/dist/transcript/auto-upload.d.ts +25 -0
  83. package/dist/transcript/auto-upload.d.ts.map +1 -0
  84. package/dist/transcript/auto-upload.js +75 -0
  85. package/dist/transcript/auto-upload.js.map +1 -0
  86. package/dist/transcript/index.d.ts +4 -0
  87. package/dist/transcript/index.d.ts.map +1 -0
  88. package/dist/transcript/index.js +4 -0
  89. package/dist/transcript/index.js.map +1 -0
  90. package/dist/transcript/manager.d.ts +63 -0
  91. package/dist/transcript/manager.d.ts.map +1 -0
  92. package/dist/transcript/manager.js +143 -0
  93. package/dist/transcript/manager.js.map +1 -0
  94. package/dist/transcript/uploader.d.ts +135 -0
  95. package/dist/transcript/uploader.d.ts.map +1 -0
  96. package/dist/transcript/uploader.js +235 -0
  97. package/dist/transcript/uploader.js.map +1 -0
  98. package/package.json +29 -0
@@ -0,0 +1,229 @@
1
+ /**
2
+ * HTTP client for adit-cloud API.
3
+ *
4
+ * Handles Bearer auth, automatic token refresh, and exponential
5
+ * backoff retry on network errors and 429 rate limits.
6
+ */
7
+ import { isTokenExpired, saveCredentials } from "../auth/credentials.js";
8
+ import { CloudAuthError, CloudNetworkError, CloudApiError } from "./errors.js";
9
+ const MAX_RETRIES = 5;
10
+ const MAX_REDIRECTS = 5;
11
+ const INITIAL_BACKOFF_MS = 2000;
12
+ export class CloudClient {
13
+ credentials;
14
+ serverUrl;
15
+ constructor(serverUrl, credentials) {
16
+ this.serverUrl = serverUrl.replace(/\/$/, ""); // Strip trailing slash
17
+ this.credentials = credentials;
18
+ }
19
+ /** GET request with auth */
20
+ async get(path) {
21
+ return this.request("GET", path);
22
+ }
23
+ /** HEAD request with auth — returns headers only */
24
+ async head(path) {
25
+ // Refresh token if expired before making the request (skip for static tokens)
26
+ if (this.credentials.authType !== "token" && isTokenExpired(this.credentials)) {
27
+ await this.refreshToken();
28
+ }
29
+ const url = `${this.serverUrl}${path}`;
30
+ const headers = {
31
+ Authorization: `Bearer ${this.credentials.accessToken}`,
32
+ };
33
+ const response = await fetch(url, { method: "HEAD", headers });
34
+ if (response.status === 401 || response.status === 403) {
35
+ // Static tokens cannot be refreshed — fail immediately
36
+ if (this.credentials.authType === "token") {
37
+ throw new CloudAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
38
+ }
39
+ if (response.status === 401) {
40
+ await this.refreshToken();
41
+ // Retry once with new token
42
+ const retry = await fetch(url, {
43
+ method: "HEAD",
44
+ headers: {
45
+ Authorization: `Bearer ${this.credentials.accessToken}`,
46
+ },
47
+ });
48
+ if (!retry.ok) {
49
+ throw new CloudApiError(`HEAD ${path}: ${retry.status} ${retry.statusText}`, retry.status);
50
+ }
51
+ return headersToRecord(retry.headers);
52
+ }
53
+ throw new CloudAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
54
+ }
55
+ if (!response.ok) {
56
+ throw new CloudApiError(`HEAD ${path}: ${response.status} ${response.statusText}`, response.status);
57
+ }
58
+ return headersToRecord(response.headers);
59
+ }
60
+ /** POST request with auth and JSON body */
61
+ async post(path, body) {
62
+ return this.request("POST", path, body);
63
+ }
64
+ /** PATCH request with auth */
65
+ async patch(path, body) {
66
+ return this.request("PATCH", path, body);
67
+ }
68
+ /** DELETE request with auth */
69
+ async delete(path) {
70
+ await this.request("DELETE", path);
71
+ }
72
+ /** Get the current credentials (may have been refreshed) */
73
+ getCredentials() {
74
+ return this.credentials;
75
+ }
76
+ async request(method, path, body, redirectCount = 0) {
77
+ // Refresh token if expired before making the request (skip for static tokens)
78
+ if (this.credentials.authType !== "token" && isTokenExpired(this.credentials)) {
79
+ await this.refreshToken();
80
+ }
81
+ let lastError;
82
+ let currentUrl = `${this.serverUrl}${path}`;
83
+ for (let attempt = 0; attempt <= MAX_RETRIES; attempt++) {
84
+ if (attempt > 0) {
85
+ const backoffMs = INITIAL_BACKOFF_MS * Math.pow(2, attempt - 1);
86
+ await sleep(backoffMs);
87
+ }
88
+ try {
89
+ let url = currentUrl;
90
+ const headers = {
91
+ Authorization: `Bearer ${this.credentials.accessToken}`,
92
+ "Content-Type": "application/json",
93
+ };
94
+ const response = await fetch(url, {
95
+ method,
96
+ headers,
97
+ body: body !== undefined ? JSON.stringify(body) : undefined,
98
+ });
99
+ // Handle 401 — static tokens cannot be refreshed, fail immediately
100
+ if (response.status === 401 && this.credentials.authType === "token") {
101
+ throw new CloudAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
102
+ }
103
+ // Handle 401 — try refreshing token once (device auth only)
104
+ if (response.status === 401 && attempt === 0) {
105
+ await this.refreshToken();
106
+ continue; // Retry with new token
107
+ }
108
+ // Handle 429 rate limit — respect Retry-After header
109
+ if (response.status === 429) {
110
+ const retryAfter = response.headers.get("Retry-After");
111
+ if (retryAfter) {
112
+ const waitMs = parseInt(retryAfter, 10) * 1000;
113
+ if (!isNaN(waitMs) && waitMs > 0) {
114
+ await sleep(Math.min(waitMs, 60_000));
115
+ }
116
+ }
117
+ continue; // Retry
118
+ }
119
+ // Handle redirects
120
+ if (response.status >= 300 && response.status < 400) {
121
+ const location = response.headers.get("Location");
122
+ if (!location) {
123
+ throw new CloudApiError(`Redirect missing Location header`, response.status);
124
+ }
125
+ if (redirectCount >= MAX_REDIRECTS) {
126
+ throw new CloudNetworkError(`Too many redirects (max ${MAX_REDIRECTS}) for ${method} ${path}`);
127
+ }
128
+ // Parse Location URL
129
+ const redirectUrl = new URL(location, url);
130
+ // For 303, always use GET method
131
+ const effectiveMethod = response.status === 303 ? "GET" : method;
132
+ // Update URL and continue the loop
133
+ currentUrl = redirectUrl.toString();
134
+ method = effectiveMethod;
135
+ // Clear body for GET/HEAD redirects after 303
136
+ if (response.status === 303 || effectiveMethod === "GET" || effectiveMethod === "HEAD") {
137
+ body = undefined;
138
+ }
139
+ // Increment redirect count for the next iteration
140
+ return this.request(method, path, body, redirectCount + 1);
141
+ }
142
+ if (!response.ok) {
143
+ // Read body as text first (always safe), then try to parse as JSON.
144
+ // This avoids the "Body is unusable: Body has already been read"
145
+ // error that occurs when response.json() fails on an empty body
146
+ // and then response.text() tries to read the already-consumed stream.
147
+ let responseBody;
148
+ try {
149
+ const text = await response.text();
150
+ try {
151
+ responseBody = JSON.parse(text);
152
+ }
153
+ catch {
154
+ responseBody = text || null;
155
+ }
156
+ }
157
+ catch {
158
+ responseBody = null;
159
+ }
160
+ if (response.status === 401 || response.status === 403) {
161
+ throw new CloudAuthError(`Authentication failed: ${response.status} ${response.statusText}`);
162
+ }
163
+ throw new CloudApiError(`API error: ${response.status} ${response.statusText}`, response.status, responseBody);
164
+ }
165
+ // 204 No Content
166
+ if (response.status === 204) {
167
+ return undefined;
168
+ }
169
+ return (await response.json());
170
+ }
171
+ catch (error) {
172
+ // Don't retry auth errors
173
+ if (error instanceof CloudAuthError)
174
+ throw error;
175
+ if (error instanceof CloudApiError)
176
+ throw error;
177
+ // Network error — retry with backoff
178
+ lastError =
179
+ error instanceof Error
180
+ ? error
181
+ : new Error(String(error));
182
+ }
183
+ }
184
+ throw new CloudNetworkError(`Request failed after ${MAX_RETRIES} retries: ${method} ${path}`, lastError);
185
+ }
186
+ /** Refresh the access token using the refresh token */
187
+ async refreshToken() {
188
+ if (this.credentials.authType === "token") {
189
+ throw new CloudAuthError("Cannot refresh a static token. Re-authenticate with a new token or use 'adit cloud login'.");
190
+ }
191
+ try {
192
+ const response = await fetch(`${this.serverUrl}/api/auth/token/refresh`, {
193
+ method: "POST",
194
+ headers: { "Content-Type": "application/json" },
195
+ body: JSON.stringify({
196
+ refreshToken: this.credentials.refreshToken,
197
+ }),
198
+ });
199
+ if (!response.ok) {
200
+ throw new CloudAuthError(`Token refresh failed: ${response.status}. Please re-authenticate with 'adit cloud login'.`);
201
+ }
202
+ const data = (await response.json());
203
+ this.credentials = {
204
+ ...this.credentials,
205
+ accessToken: data.accessToken,
206
+ refreshToken: data.refreshToken,
207
+ expiresAt: data.expiresAt,
208
+ };
209
+ // Persist the refreshed credentials
210
+ saveCredentials(this.credentials);
211
+ }
212
+ catch (error) {
213
+ if (error instanceof CloudAuthError)
214
+ throw error;
215
+ throw new CloudAuthError(`Token refresh failed: ${error instanceof Error ? error.message : String(error)}`);
216
+ }
217
+ }
218
+ }
219
+ function sleep(ms) {
220
+ return new Promise((resolve) => setTimeout(resolve, ms));
221
+ }
222
+ function headersToRecord(headers) {
223
+ const result = {};
224
+ headers.forEach((value, key) => {
225
+ result[key] = value;
226
+ });
227
+ return result;
228
+ }
229
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/http/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Typed error classes for cloud API operations.
3
+ */
4
+ /** Authentication failure (401, expired token, revoked) */
5
+ export declare class CloudAuthError extends Error {
6
+ constructor(message: string);
7
+ }
8
+ /** Network-level failure (timeout, DNS, connection refused) */
9
+ export declare class CloudNetworkError extends Error {
10
+ readonly cause?: Error;
11
+ constructor(message: string, cause?: Error);
12
+ }
13
+ /** Server returned a non-2xx response */
14
+ export declare class CloudApiError extends Error {
15
+ readonly status: number;
16
+ readonly body?: unknown;
17
+ constructor(message: string, status: number, body?: unknown);
18
+ }
19
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2DAA2D;AAC3D,qBAAa,cAAe,SAAQ,KAAK;gBAC3B,OAAO,EAAE,MAAM;CAI5B;AAED,+DAA+D;AAC/D,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,QAAQ,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC;gBAEX,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK;CAK3C;AAED,yCAAyC;AACzC,qBAAa,aAAc,SAAQ,KAAK;IACtC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEZ,OAAO,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO;CAM5D"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Typed error classes for cloud API operations.
3
+ */
4
+ /** Authentication failure (401, expired token, revoked) */
5
+ export class CloudAuthError extends Error {
6
+ constructor(message) {
7
+ super(message);
8
+ this.name = "CloudAuthError";
9
+ }
10
+ }
11
+ /** Network-level failure (timeout, DNS, connection refused) */
12
+ export class CloudNetworkError extends Error {
13
+ cause;
14
+ constructor(message, cause) {
15
+ super(message);
16
+ this.name = "CloudNetworkError";
17
+ this.cause = cause;
18
+ }
19
+ }
20
+ /** Server returned a non-2xx response */
21
+ export class CloudApiError extends Error {
22
+ status;
23
+ body;
24
+ constructor(message, status, body) {
25
+ super(message);
26
+ this.name = "CloudApiError";
27
+ this.status = status;
28
+ this.body = body;
29
+ }
30
+ }
31
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/http/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,2DAA2D;AAC3D,MAAM,OAAO,cAAe,SAAQ,KAAK;IACvC,YAAY,OAAe;QACzB,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,gBAAgB,CAAC;IAC/B,CAAC;CACF;AAED,+DAA+D;AAC/D,MAAM,OAAO,iBAAkB,SAAQ,KAAK;IACjC,KAAK,CAAS;IAEvB,YAAY,OAAe,EAAE,KAAa;QACxC,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,mBAAmB,CAAC;QAChC,IAAI,CAAC,KAAK,GAAG,KAAK,CAAC;IACrB,CAAC;CACF;AAED,yCAAyC;AACzC,MAAM,OAAO,aAAc,SAAQ,KAAK;IAC7B,MAAM,CAAS;IACf,IAAI,CAAW;IAExB,YAAY,OAAe,EAAE,MAAc,EAAE,IAAc;QACzD,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,eAAe,CAAC;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;CACF"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * @vkenliu/adit-cloud — Cloud sync client for ADIT.
3
+ *
4
+ * Provides device authorization, HTTP client with auto-refresh,
5
+ * cursor-based incremental sync engine, and conflict resolution.
6
+ */
7
+ export { loadCloudConfig, DEFAULT_SERVER_URL, type CloudConfig, type ProjectLinkConfig } from "./config.js";
8
+ export { loadCredentials, saveCredentials, clearCredentials, isTokenExpired, credentialsFromEnvToken, incrementSyncErrors, clearSyncErrors, isSyncDisabled, type CloudCredentials, } from "./auth/credentials.js";
9
+ export { requestDeviceCode, pollForToken, type DeviceCodeResponse, type TokenResponse, type DeviceAuthOptions, } from "./auth/device-auth.js";
10
+ export { CloudClient } from "./http/client.js";
11
+ export { CloudAuthError, CloudNetworkError, CloudApiError, } from "./http/errors.js";
12
+ export { SyncEngine, type SyncResult, type SyncConflict, } from "./sync/engine.js";
13
+ export { buildSyncBatch, countUnsyncedRecords, batchRecordCount, type SyncBatch, } from "./sync/serializer.js";
14
+ export { triggerAutoSync } from "./sync/auto-sync.js";
15
+ export { triggerTranscriptUpload, registerTranscript, processTranscriptUploads, uploadChunk, uploadFull, checkUploadStatus, lookupUploadByPath, type TranscriptManagerOptions, type TranscriptProcessResult, type SyncUploadType, type SyncUploadResponse, type SyncUploadStatus, type UploadChunkParams, } from "./transcript/index.js";
16
+ export { type TranscriptUploadConfig } from "./config.js";
17
+ export { linkCommand, intentCommand, formatIntentList, formatIntentDetail, triggerProjectLinkSync, checkQuality, formatQualityFeedback, collectRemoteUrl, collectBranches, collectCommitLogs, collectCommitCount, collectDefaultBranch, collectCurrentBranch, projectNameFromRemoteUrl, discoverDocuments, loadDocSettings, getProjectLinkCache, upsertProjectLinkCache, clearProjectLinkCache, type LinkResult, type IntentResult, type LinkOptions, type IntentOptions, type IntentSummary, type IntentDetail, type TaskSlice, type StepTiming, type GitBranch, type GitCommit, type DiscoveredDocument, type ProjectLinkCache, type QualifyResponse, } from "./project-link/index.js";
18
+ export { bulkTaskUpdateCommand } from "./project-link/bulk-task.js";
19
+ export type { BulkTaskFilter, BulkTaskUpdate, BulkTaskUpdateOptions, BulkTaskUpdateResult, } from "./project-link/types.js";
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAG5G,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,cAAc,EACd,KAAK,gBAAgB,GACtB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,YAAY,EACZ,KAAK,kBAAkB,EACvB,KAAK,aAAa,EAClB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EACL,UAAU,EACV,KAAK,UAAU,EACf,KAAK,YAAY,GAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,gBAAgB,EAChB,KAAK,SAAS,GACf,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAGtD,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,wBAAwB,EACxB,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,EAClB,KAAK,wBAAwB,EAC7B,KAAK,uBAAuB,EAC5B,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,GACvB,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAG1D,OAAO,EACL,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,EACrB,KAAK,UAAU,EACf,KAAK,YAAY,EACjB,KAAK,WAAW,EAChB,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,kBAAkB,EACvB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,yBAAyB,CAAC;AAGjC,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC;AACpE,YAAY,EACV,cAAc,EACd,cAAc,EACd,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,yBAAyB,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ /**
2
+ * @vkenliu/adit-cloud — Cloud sync client for ADIT.
3
+ *
4
+ * Provides device authorization, HTTP client with auto-refresh,
5
+ * cursor-based incremental sync engine, and conflict resolution.
6
+ */
7
+ // Config
8
+ export { loadCloudConfig, DEFAULT_SERVER_URL } from "./config.js";
9
+ // Auth
10
+ export { loadCredentials, saveCredentials, clearCredentials, isTokenExpired, credentialsFromEnvToken, incrementSyncErrors, clearSyncErrors, isSyncDisabled, } from "./auth/credentials.js";
11
+ export { requestDeviceCode, pollForToken, } from "./auth/device-auth.js";
12
+ // HTTP
13
+ export { CloudClient } from "./http/client.js";
14
+ export { CloudAuthError, CloudNetworkError, CloudApiError, } from "./http/errors.js";
15
+ // Sync
16
+ export { SyncEngine, } from "./sync/engine.js";
17
+ export { buildSyncBatch, countUnsyncedRecords, batchRecordCount, } from "./sync/serializer.js";
18
+ export { triggerAutoSync } from "./sync/auto-sync.js";
19
+ // Transcript / file upload
20
+ export { triggerTranscriptUpload, registerTranscript, processTranscriptUploads, uploadChunk, uploadFull, checkUploadStatus, lookupUploadByPath, } from "./transcript/index.js";
21
+ // Project Link
22
+ export { linkCommand, intentCommand, formatIntentList, formatIntentDetail, triggerProjectLinkSync, checkQuality, formatQualityFeedback, collectRemoteUrl, collectBranches, collectCommitLogs, collectCommitCount, collectDefaultBranch, collectCurrentBranch, projectNameFromRemoteUrl, discoverDocuments, loadDocSettings, getProjectLinkCache, upsertProjectLinkCache, clearProjectLinkCache, } from "./project-link/index.js";
23
+ // Bulk Task Update
24
+ export { bulkTaskUpdateCommand } from "./project-link/bulk-task.js";
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,SAAS;AACT,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAA4C,MAAM,aAAa,CAAC;AAE5G,OAAO;AACP,OAAO,EACL,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,uBAAuB,EACvB,mBAAmB,EACnB,eAAe,EACf,cAAc,GAEf,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EACL,iBAAiB,EACjB,YAAY,GAIb,MAAM,uBAAuB,CAAC;AAE/B,OAAO;AACP,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EACL,cAAc,EACd,iBAAiB,EACjB,aAAa,GACd,MAAM,kBAAkB,CAAC;AAE1B,OAAO;AACP,OAAO,EACL,UAAU,GAGX,MAAM,kBAAkB,CAAC;AAC1B,OAAO,EACL,cAAc,EACd,oBAAoB,EACpB,gBAAgB,GAEjB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAEtD,2BAA2B;AAC3B,OAAO,EACL,uBAAuB,EACvB,kBAAkB,EAClB,wBAAwB,EACxB,WAAW,EACX,UAAU,EACV,iBAAiB,EACjB,kBAAkB,GAOnB,MAAM,uBAAuB,CAAC;AAI/B,eAAe;AACf,OAAO,EACL,WAAW,EACX,aAAa,EACb,gBAAgB,EAChB,kBAAkB,EAClB,sBAAsB,EACtB,YAAY,EACZ,qBAAqB,EACrB,gBAAgB,EAChB,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,oBAAoB,EACpB,oBAAoB,EACpB,wBAAwB,EACxB,iBAAiB,EACjB,eAAe,EACf,mBAAmB,EACnB,sBAAsB,EACtB,qBAAqB,GActB,MAAM,yBAAyB,CAAC;AAEjC,mBAAmB;AACnB,OAAO,EAAE,qBAAqB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Automatic project-link sync — fire-and-forget on session-start.
3
+ *
4
+ * Spawns a detached child process to run the full project-link flow
5
+ * (branches, commits, documents) in the background. The process is
6
+ * independent of the hook — it won't be killed by the 10-second
7
+ * hook timeout and won't block the AI agent.
8
+ *
9
+ * Precondition checks (all must pass to trigger):
10
+ * 1. Auto-sync not disabled via ADIT_PROJECT_LINK_AUTO_SYNC=false
11
+ * 2. Valid credentials exist (env token or stored credentials)
12
+ * 3. Server URL is resolvable
13
+ * 4. Cached project-link data is stale (older than staleHours)
14
+ *
15
+ * The detached process runs `npx adit cloud link --json --skip-qualify`
16
+ * with inherited environment, so credentials and config are available.
17
+ */
18
+ import type Database from "better-sqlite3";
19
+ /**
20
+ * Trigger a background project-link sync if credentials exist and
21
+ * the cached link data is stale.
22
+ *
23
+ * This function is designed to be called as fire-and-forget:
24
+ * triggerProjectLinkSync(db, projectId, projectRoot).catch(() => {})
25
+ *
26
+ * It spawns a fully detached child process that outlives the hook
27
+ * process, so the 10-second hook timeout does not apply.
28
+ */
29
+ export declare function triggerProjectLinkSync(db: Database.Database, projectId: string, projectRoot: string): Promise<void>;
30
+ //# sourceMappingURL=auto-link.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-link.d.ts","sourceRoot":"","sources":["../../src/project-link/auto-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAGH,OAAO,KAAK,QAAQ,MAAM,gBAAgB,CAAC;AAS3C;;;;;;;;;GASG;AACH,wBAAsB,sBAAsB,CAC1C,EAAE,EAAE,QAAQ,CAAC,QAAQ,EACrB,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,OAAO,CAAC,IAAI,CAAC,CA8Df"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Automatic project-link sync — fire-and-forget on session-start.
3
+ *
4
+ * Spawns a detached child process to run the full project-link flow
5
+ * (branches, commits, documents) in the background. The process is
6
+ * independent of the hook — it won't be killed by the 10-second
7
+ * hook timeout and won't block the AI agent.
8
+ *
9
+ * Precondition checks (all must pass to trigger):
10
+ * 1. Auto-sync not disabled via ADIT_PROJECT_LINK_AUTO_SYNC=false
11
+ * 2. Valid credentials exist (env token or stored credentials)
12
+ * 3. Server URL is resolvable
13
+ * 4. Cached project-link data is stale (older than staleHours)
14
+ *
15
+ * The detached process runs `npx adit cloud link --json --skip-qualify`
16
+ * with inherited environment, so credentials and config are available.
17
+ */
18
+ import { spawn } from "node:child_process";
19
+ import { loadCloudConfig, DEFAULT_SERVER_URL } from "../config.js";
20
+ import { loadCredentials, credentialsFromEnvToken, isSyncDisabled, } from "../auth/credentials.js";
21
+ import { getProjectLinkCache } from "./cache.js";
22
+ /**
23
+ * Trigger a background project-link sync if credentials exist and
24
+ * the cached link data is stale.
25
+ *
26
+ * This function is designed to be called as fire-and-forget:
27
+ * triggerProjectLinkSync(db, projectId, projectRoot).catch(() => {})
28
+ *
29
+ * It spawns a fully detached child process that outlives the hook
30
+ * process, so the 10-second hook timeout does not apply.
31
+ */
32
+ export async function triggerProjectLinkSync(db, projectId, projectRoot) {
33
+ const cloudConfig = loadCloudConfig();
34
+ // 0. Check if project-link auto-sync is enabled
35
+ if (!cloudConfig.projectLink.autoSync)
36
+ return;
37
+ // 1. Circuit breaker — skip if cloud sync is disabled due to failures
38
+ if (isSyncDisabled())
39
+ return;
40
+ // 2. Check credentials exist (env token or stored) and resolve server URL
41
+ let serverUrl = null;
42
+ const storedCredentials = loadCredentials();
43
+ if (process.env.ADIT_AUTH_TOKEN) {
44
+ serverUrl = cloudConfig.serverUrl ?? DEFAULT_SERVER_URL;
45
+ const clientId = storedCredentials?.clientId ?? (await import("@vkenliu/adit-core")).loadConfig().clientId;
46
+ const creds = credentialsFromEnvToken(serverUrl, clientId);
47
+ if (!creds)
48
+ return;
49
+ }
50
+ else {
51
+ if (!storedCredentials)
52
+ return;
53
+ serverUrl = cloudConfig.serverUrl ?? storedCredentials.serverUrl;
54
+ // Single-server binding: don't send credentials to wrong server
55
+ if (cloudConfig.serverUrl && storedCredentials.serverUrl !== cloudConfig.serverUrl) {
56
+ return;
57
+ }
58
+ }
59
+ if (!serverUrl)
60
+ return;
61
+ // 3. Check staleness — skip if cached data is fresh enough
62
+ const cache = getProjectLinkCache(db, projectId, serverUrl);
63
+ if (cache?.lastBranchSyncAt) {
64
+ const staleMs = cloudConfig.projectLink.staleHours * 60 * 60 * 1000;
65
+ const lastSyncTime = new Date(cache.lastBranchSyncAt).getTime();
66
+ // Guard against corrupted date strings that produce NaN
67
+ if (!Number.isNaN(lastSyncTime)) {
68
+ const elapsed = Date.now() - lastSyncTime;
69
+ if (elapsed < staleMs)
70
+ return;
71
+ }
72
+ }
73
+ // 4. Spawn detached child process to run the full link flow.
74
+ // Uses `npx adit cloud link` which handles its own
75
+ // credential loading, database opening, and error handling.
76
+ try {
77
+ const child = spawn("npx", ["adit", "cloud", "link", "--json", "--skip-qualify"], {
78
+ cwd: projectRoot,
79
+ stdio: ["ignore", "ignore", "ignore"],
80
+ detached: true,
81
+ });
82
+ child.unref();
83
+ child.on("error", () => {
84
+ // fail-open
85
+ });
86
+ }
87
+ catch {
88
+ // fail-open — spawn itself may throw (e.g. npx not found)
89
+ }
90
+ }
91
+ //# sourceMappingURL=auto-link.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auto-link.js","sourceRoot":"","sources":["../../src/project-link/auto-link.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,OAAO,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,cAAc,CAAC;AACnE,OAAO,EACL,eAAe,EACf,uBAAuB,EACvB,cAAc,GACf,MAAM,wBAAwB,CAAC;AAChC,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,EAAqB,EACrB,SAAiB,EACjB,WAAmB;IAEnB,MAAM,WAAW,GAAG,eAAe,EAAE,CAAC;IAEtC,gDAAgD;IAChD,IAAI,CAAC,WAAW,CAAC,WAAW,CAAC,QAAQ;QAAE,OAAO;IAE9C,sEAAsE;IACtE,IAAI,cAAc,EAAE;QAAE,OAAO;IAE7B,0EAA0E;IAC1E,IAAI,SAAS,GAAkB,IAAI,CAAC;IACpC,MAAM,iBAAiB,GAAG,eAAe,EAAE,CAAC;IAE5C,IAAI,OAAO,CAAC,GAAG,CAAC,eAAe,EAAE,CAAC;QAChC,SAAS,GAAG,WAAW,CAAC,SAAS,IAAI,kBAAkB,CAAC;QACxD,MAAM,QAAQ,GAAG,iBAAiB,EAAE,QAAQ,IAAI,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,UAAU,EAAE,CAAC,QAAQ,CAAC;QAC3G,MAAM,KAAK,GAAG,uBAAuB,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;QAC3D,IAAI,CAAC,KAAK;YAAE,OAAO;IACrB,CAAC;SAAM,CAAC;QACN,IAAI,CAAC,iBAAiB;YAAE,OAAO;QAC/B,SAAS,GAAG,WAAW,CAAC,SAAS,IAAI,iBAAiB,CAAC,SAAS,CAAC;QAEjE,gEAAgE;QAChE,IAAI,WAAW,CAAC,SAAS,IAAI,iBAAiB,CAAC,SAAS,KAAK,WAAW,CAAC,SAAS,EAAE,CAAC;YACnF,OAAO;QACT,CAAC;IACH,CAAC;IAED,IAAI,CAAC,SAAS;QAAE,OAAO;IAEvB,2DAA2D;IAC3D,MAAM,KAAK,GAAG,mBAAmB,CAAC,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,CAAC;IAC5D,IAAI,KAAK,EAAE,gBAAgB,EAAE,CAAC;QAC5B,MAAM,OAAO,GAAG,WAAW,CAAC,WAAW,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;QACpE,MAAM,YAAY,GAAG,IAAI,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,OAAO,EAAE,CAAC;QAChE,wDAAwD;QACxD,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,YAAY,CAAC;YAC1C,IAAI,OAAO,GAAG,OAAO;gBAAE,OAAO;QAChC,CAAC;IACH,CAAC;IAED,6DAA6D;IAC7D,sDAAsD;IACtD,+DAA+D;IAC/D,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,KAAK,CACjB,KAAK,EACL,CAAC,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,CAAC,EACrD;YACE,GAAG,EAAE,WAAW;YAChB,KAAK,EAAE,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,CAAC;YACrC,QAAQ,EAAE,IAAI;SACf,CACF,CAAC;QACF,KAAK,CAAC,KAAK,EAAE,CAAC;QACd,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,YAAY;QACd,CAAC,CAAC,CAAC;IACL,CAAC;IAAC,MAAM,CAAC;QACP,0DAA0D;IAC5D,CAAC;AACH,CAAC"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Bulk task status update command.
3
+ *
4
+ * Implements the bulk task status update functionality by calling
5
+ * the /api/task-slices/bulk endpoint.
6
+ */
7
+ import { CloudClient } from "../http/client.js";
8
+ import type { BulkTaskUpdateOptions, BulkTaskUpdateResult } from "./types.js";
9
+ /**
10
+ * Bulk task status update command
11
+ *
12
+ * Updates task status in bulk using the /api/task-slices/bulk endpoint.
13
+ */
14
+ export declare function bulkTaskUpdateCommand(client: CloudClient, _projectId: string, options: BulkTaskUpdateOptions): Promise<BulkTaskUpdateResult>;
15
+ //# sourceMappingURL=bulk-task.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-task.d.ts","sourceRoot":"","sources":["../../src/project-link/bulk-task.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,KAAK,EAAE,qBAAqB,EAAE,oBAAoB,EAAE,MAAM,YAAY,CAAC;AA2F9E;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,MAAM,EAAE,WAAW,EACnB,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,oBAAoB,CAAC,CAwC/B"}
@@ -0,0 +1,107 @@
1
+ /**
2
+ * Bulk task status update command.
3
+ *
4
+ * Implements the bulk task status update functionality by calling
5
+ * the /api/task-slices/bulk endpoint.
6
+ */
7
+ import { CloudAuthError, CloudNetworkError, CloudApiError } from "../http/errors.js";
8
+ /**
9
+ * Build the request body for bulk task update API
10
+ */
11
+ function buildRequestBody(options) {
12
+ const { intentId, taskId, status, filters } = options;
13
+ // If specific task IDs are provided, create updates for each
14
+ const updates = taskId && taskId.length > 0
15
+ ? taskId.map(taskId => ({
16
+ taskId,
17
+ status: status ?? "completed",
18
+ }))
19
+ : // Otherwise, create a single update to apply to all tasks
20
+ [
21
+ {
22
+ taskId: "*", // This will be handled by the server to update all tasks
23
+ status: status ?? "completed",
24
+ },
25
+ ];
26
+ // Build the request body
27
+ const body = {
28
+ intentId,
29
+ updates,
30
+ };
31
+ // Add filters if provided
32
+ if (filters) {
33
+ body.filters = {};
34
+ if (filters.phase !== undefined)
35
+ body.filters.phase = filters.phase;
36
+ if (filters.status !== undefined)
37
+ body.filters.status = filters.status;
38
+ if (filters.featureTag !== undefined)
39
+ body.filters.featureTag = filters.featureTag;
40
+ if (filters.wave !== undefined)
41
+ body.filters.wave = filters.wave;
42
+ }
43
+ return body;
44
+ }
45
+ /**
46
+ * Validate options and prepare for API call
47
+ */
48
+ function validateOptions(options) {
49
+ if (!options.intentId) {
50
+ throw new Error("intentId is required");
51
+ }
52
+ // Validate intentId format (basic UUID check)
53
+ if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(options.intentId)) {
54
+ throw new Error("Invalid intentId format");
55
+ }
56
+ // Validate status if provided
57
+ if (options.status && !["pending", "approved", "in_progress", "completed", "rejected"].includes(options.status)) {
58
+ throw new Error(`Invalid status: ${options.status}. Must be one of: pending, approved, in_progress, completed, rejected`);
59
+ }
60
+ // Validate filters
61
+ if (options.filters) {
62
+ const { filters } = options;
63
+ if (filters.phase && (filters.phase < 1 || filters.phase > 99)) {
64
+ throw new Error("Phase must be between 1 and 99");
65
+ }
66
+ if (filters.status && !["pending", "approved", "in_progress", "completed", "rejected"].includes(filters.status)) {
67
+ throw new Error(`Invalid filter status: ${filters.status}. Must be one of: pending, approved, in_progress, completed, rejected`);
68
+ }
69
+ if (filters.wave && filters.wave < 1) {
70
+ throw new Error("Wave must be greater than 0");
71
+ }
72
+ }
73
+ }
74
+ /**
75
+ * Bulk task status update command
76
+ *
77
+ * Updates task status in bulk using the /api/task-slices/bulk endpoint.
78
+ */
79
+ export async function bulkTaskUpdateCommand(client, _projectId, options) {
80
+ try {
81
+ // Validate options first
82
+ validateOptions(options);
83
+ // Build request body
84
+ const body = buildRequestBody(options);
85
+ // Make the API request
86
+ const result = await client.patch(`/api/task-slices/bulk`, body);
87
+ return result;
88
+ }
89
+ catch (error) {
90
+ if (error instanceof CloudAuthError) {
91
+ throw error;
92
+ }
93
+ if (error instanceof CloudNetworkError) {
94
+ throw error;
95
+ }
96
+ if (error instanceof CloudApiError) {
97
+ // Enhance API error with more context
98
+ throw new CloudApiError(`Bulk task update failed: ${error.message}`, error.status, error.body);
99
+ }
100
+ // Re-throw validation errors
101
+ if (error instanceof Error) {
102
+ throw error;
103
+ }
104
+ throw new CloudApiError("Bulk task update failed with unknown error", 500);
105
+ }
106
+ }
107
+ //# sourceMappingURL=bulk-task.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bulk-task.js","sourceRoot":"","sources":["../../src/project-link/bulk-task.ts"],"names":[],"mappings":"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"}