@wirecat/drive-cli 0.0.0-stage → 0.1.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 (127) hide show
  1. package/LICENSE +204 -0
  2. package/README.md +194 -2
  3. package/dist/api-contract.d.ts +7 -0
  4. package/dist/api-contract.d.ts.map +1 -0
  5. package/dist/api-contract.js +42 -0
  6. package/dist/api-contract.js.map +1 -0
  7. package/dist/bin/drive.d.ts +3 -0
  8. package/dist/bin/drive.d.ts.map +1 -0
  9. package/dist/bin/drive.js +41 -0
  10. package/dist/bin/drive.js.map +1 -0
  11. package/dist/config.d.ts +74 -0
  12. package/dist/config.d.ts.map +1 -0
  13. package/dist/config.js +83 -0
  14. package/dist/config.js.map +1 -0
  15. package/dist/documents.d.ts +4 -0
  16. package/dist/documents.d.ts.map +1 -0
  17. package/dist/documents.js +36 -0
  18. package/dist/documents.js.map +1 -0
  19. package/dist/errors.d.ts +3 -0
  20. package/dist/errors.d.ts.map +1 -0
  21. package/dist/errors.js +39 -0
  22. package/dist/errors.js.map +1 -0
  23. package/dist/extraction.d.ts +14 -0
  24. package/dist/extraction.d.ts.map +1 -0
  25. package/dist/extraction.js +49 -0
  26. package/dist/extraction.js.map +1 -0
  27. package/dist/generated/definitions.d.ts +3 -0
  28. package/dist/generated/definitions.d.ts.map +1 -0
  29. package/dist/generated/definitions.js +9798 -0
  30. package/dist/generated/definitions.js.map +1 -0
  31. package/dist/generated/manifest.d.ts +3 -0
  32. package/dist/generated/manifest.d.ts.map +1 -0
  33. package/dist/generated/manifest.js +8346 -0
  34. package/dist/generated/manifest.js.map +1 -0
  35. package/dist/generated/metadata.d.ts +74 -0
  36. package/dist/generated/metadata.d.ts.map +1 -0
  37. package/dist/generated/metadata.js +342 -0
  38. package/dist/generated/metadata.js.map +1 -0
  39. package/dist/generated/schemas.d.ts +649 -0
  40. package/dist/generated/schemas.d.ts.map +1 -0
  41. package/dist/generated/schemas.js +2602 -0
  42. package/dist/generated/schemas.js.map +1 -0
  43. package/dist/generated/types.d.ts +3940 -0
  44. package/dist/generated/types.d.ts.map +1 -0
  45. package/dist/generated/types.js +5 -0
  46. package/dist/generated/types.js.map +1 -0
  47. package/dist/google-api.d.ts +15 -0
  48. package/dist/google-api.d.ts.map +1 -0
  49. package/dist/google-api.js +94 -0
  50. package/dist/google-api.js.map +1 -0
  51. package/dist/google.d.ts +8 -0
  52. package/dist/google.d.ts.map +1 -0
  53. package/dist/google.js +173 -0
  54. package/dist/google.js.map +1 -0
  55. package/dist/index.d.ts +9 -0
  56. package/dist/index.d.ts.map +1 -0
  57. package/dist/index.js +7 -0
  58. package/dist/index.js.map +1 -0
  59. package/dist/knowledge-commands.d.ts +19 -0
  60. package/dist/knowledge-commands.d.ts.map +1 -0
  61. package/dist/knowledge-commands.js +155 -0
  62. package/dist/knowledge-commands.js.map +1 -0
  63. package/dist/knowledge.d.ts +38 -0
  64. package/dist/knowledge.d.ts.map +1 -0
  65. package/dist/knowledge.js +222 -0
  66. package/dist/knowledge.js.map +1 -0
  67. package/dist/login.d.ts +25 -0
  68. package/dist/login.d.ts.map +1 -0
  69. package/dist/login.js +116 -0
  70. package/dist/login.js.map +1 -0
  71. package/dist/mcp.d.ts +35 -0
  72. package/dist/mcp.d.ts.map +1 -0
  73. package/dist/mcp.js +147 -0
  74. package/dist/mcp.js.map +1 -0
  75. package/dist/model.d.ts +100 -0
  76. package/dist/model.d.ts.map +1 -0
  77. package/dist/model.js +3 -0
  78. package/dist/model.js.map +1 -0
  79. package/dist/oauth-application.d.ts +5 -0
  80. package/dist/oauth-application.d.ts.map +1 -0
  81. package/dist/oauth-application.js +8 -0
  82. package/dist/oauth-application.js.map +1 -0
  83. package/dist/policy.d.ts +16 -0
  84. package/dist/policy.d.ts.map +1 -0
  85. package/dist/policy.js +65 -0
  86. package/dist/policy.js.map +1 -0
  87. package/dist/profile-lock.d.ts +5 -0
  88. package/dist/profile-lock.d.ts.map +1 -0
  89. package/dist/profile-lock.js +27 -0
  90. package/dist/profile-lock.js.map +1 -0
  91. package/dist/program.d.ts +20 -0
  92. package/dist/program.d.ts.map +1 -0
  93. package/dist/program.js +653 -0
  94. package/dist/program.js.map +1 -0
  95. package/dist/registry.d.ts +7 -0
  96. package/dist/registry.d.ts.map +1 -0
  97. package/dist/registry.js +15 -0
  98. package/dist/registry.js.map +1 -0
  99. package/dist/remote-commands.d.ts +10 -0
  100. package/dist/remote-commands.d.ts.map +1 -0
  101. package/dist/remote-commands.js +169 -0
  102. package/dist/remote-commands.js.map +1 -0
  103. package/dist/schema.d.ts +6 -0
  104. package/dist/schema.d.ts.map +1 -0
  105. package/dist/schema.js +77 -0
  106. package/dist/schema.js.map +1 -0
  107. package/dist/state.d.ts +11 -0
  108. package/dist/state.d.ts.map +1 -0
  109. package/dist/state.js +90 -0
  110. package/dist/state.js.map +1 -0
  111. package/dist/store.d.ts +5 -0
  112. package/dist/store.d.ts.map +1 -0
  113. package/dist/store.js +135 -0
  114. package/dist/store.js.map +1 -0
  115. package/dist/sync.d.ts +20 -0
  116. package/dist/sync.d.ts.map +1 -0
  117. package/dist/sync.js +278 -0
  118. package/dist/sync.js.map +1 -0
  119. package/dist/tokens.d.ts +26 -0
  120. package/dist/tokens.d.ts.map +1 -0
  121. package/dist/tokens.js +83 -0
  122. package/dist/tokens.js.map +1 -0
  123. package/dist/version.d.ts +2 -0
  124. package/dist/version.d.ts.map +1 -0
  125. package/dist/version.js +3 -0
  126. package/dist/version.js.map +1 -0
  127. package/package.json +82 -4
package/dist/store.js ADDED
@@ -0,0 +1,135 @@
1
+ import { join } from "node:path";
2
+ import { CliError } from "@wirecat/cli-core";
3
+ import { paths } from "./config.js";
4
+ import { documentKnowledge, saveContributors } from "./knowledge.js";
5
+ export const openIndex = async (env) => {
6
+ const { ensureSqlite } = await import("@wirecat/cli-messaging/sqlite-runtime");
7
+ await ensureSqlite();
8
+ const { openStore } = await import("@wirecat/cli-messaging/store");
9
+ const store = await openStore({ path: env.DRIVE_STORE ?? join(paths(env).state, "drive.db"), env, command: "drive" });
10
+ return indexOver(store, env);
11
+ };
12
+ export const indexOver = (store, env) => {
13
+ const folder = async (principal, create) => {
14
+ const name = `google-drive:${principal}`;
15
+ const found = (await store.notes.folders()).find((item) => item.name === name);
16
+ return found ?? (create ? await store.notes.addFolder({ name, format: "markdown" }) : undefined);
17
+ };
18
+ const documents = new Map();
19
+ const cached = async (principal) => {
20
+ const known = documents.get(principal);
21
+ if (known)
22
+ return known;
23
+ const notes = new Map();
24
+ const selected = await folder(principal, false);
25
+ if (selected) {
26
+ for (let offset = 0;; offset += 500) {
27
+ const page = await store.notes.notes({ folderId: selected.id, source: "file", limit: 500, offset });
28
+ for (const note of page.items)
29
+ if (note.path)
30
+ notes.set(note.path, note);
31
+ if (!page.hasMore)
32
+ break;
33
+ if (offset >= 10000)
34
+ throw new CliError("provider_error", "local document listing exceeded its bound");
35
+ }
36
+ }
37
+ documents.set(principal, notes);
38
+ return notes;
39
+ };
40
+ const stale = async (ref) => {
41
+ for (const status of ["proposed", "confirmed"]) {
42
+ for (let batch = 0;; batch++) {
43
+ const memories = await store.memories.list({ subject: ref, status, limit: 500 });
44
+ for (const memory of memories)
45
+ await store.memories.markStale(memory.ref);
46
+ if (memories.length < 500)
47
+ break;
48
+ if (batch >= 20)
49
+ throw new CliError("provider_error", "memory invalidation exceeded its batch bound");
50
+ }
51
+ }
52
+ };
53
+ return {
54
+ knowledge: documentKnowledge(store, async (principal) => (await folder(principal, false))?.id),
55
+ save: async (principal, content, hash) => {
56
+ const selected = await folder(principal, true);
57
+ if (!selected)
58
+ throw new Error("folder registration failed");
59
+ const notes = await cached(principal);
60
+ const path = `${content.metadata.id}.md`;
61
+ const before = notes.get(path);
62
+ if (before && before.contentHash !== hash)
63
+ await stale(before.ref);
64
+ const { note } = await store.notes.saveFileNote({
65
+ folderId: selected.id,
66
+ path: `${content.metadata.id}.md`,
67
+ title: content.metadata.name,
68
+ text: content.text,
69
+ contentHash: hash,
70
+ frontMatter: {
71
+ source: "google-drive",
72
+ sourceUrl: content.metadata.url,
73
+ fileId: content.metadata.id,
74
+ owners: content.metadata.owners ?? [],
75
+ lastModifiedBy: content.metadata.lastModifiedBy ?? null,
76
+ modifiedAt: content.metadata.modifiedAt ?? null,
77
+ sourceVersion: content.metadata.version ?? null,
78
+ tabs: content.tabs.map(({ id, title }) => ({ id, title })),
79
+ },
80
+ });
81
+ await saveContributors(store, principal, content.metadata, note.id);
82
+ notes.set(path, note);
83
+ return note.ref;
84
+ },
85
+ remove: async (principal, id) => {
86
+ const selected = await folder(principal, false);
87
+ if (selected) {
88
+ const notes = await cached(principal);
89
+ const path = `${id}.md`;
90
+ const note = notes.get(path);
91
+ if (note)
92
+ await stale(note.ref);
93
+ await store.notes.deleteFileNotes(selected.id, [path]);
94
+ notes.delete(path);
95
+ }
96
+ },
97
+ search: async (principal, query, options) => {
98
+ const selected = await folder(principal, false);
99
+ if (!selected)
100
+ return {
101
+ query,
102
+ by: "words",
103
+ hits: [],
104
+ linked: [],
105
+ hasMore: false,
106
+ meaningSkipped: "this Google account has no imported sources",
107
+ };
108
+ const { searchNotes } = await import("@wirecat/cli-messaging/services");
109
+ const result = await searchNotes(store, query, {
110
+ ...options,
111
+ folderIds: selected ? [selected.id] : [],
112
+ env,
113
+ command: "tg",
114
+ });
115
+ return {
116
+ ...result,
117
+ hits: await Promise.all(result.hits.map(async (hit) => {
118
+ const note = await store.notes.note(hit.ref);
119
+ const metadata = note.frontMatter;
120
+ return {
121
+ ...hit,
122
+ sourceUrl: typeof metadata?.sourceUrl === "string" ? metadata.sourceUrl : null,
123
+ tabs: Array.isArray(metadata?.tabs) ? metadata.tabs : [],
124
+ };
125
+ })),
126
+ };
127
+ },
128
+ embed: async (max) => {
129
+ const { embedNotes } = await import("@wirecat/cli-messaging/services");
130
+ return embedNotes(store, { maxChunks: max, env, command: "tg" });
131
+ },
132
+ close: () => store.close(),
133
+ };
134
+ };
135
+ //# sourceMappingURL=store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.js","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"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"}
package/dist/sync.d.ts ADDED
@@ -0,0 +1,20 @@
1
+ import { type DocumentIndex, type FileMetadata, type GoogleSource } from "./model.js";
2
+ export declare const within: (file: FileMetadata, roots: string[], folders: Record<string, FileMetadata>, seen?: Set<string>) => boolean;
3
+ export interface SyncResult {
4
+ saved: number;
5
+ removed: number;
6
+ unchanged: number;
7
+ pending: number;
8
+ skipped: {
9
+ id: string;
10
+ reason: string;
11
+ }[];
12
+ errors: {
13
+ id: string;
14
+ code: string;
15
+ message: string;
16
+ }[];
17
+ coverage: string;
18
+ }
19
+ export declare const sync: (source: GoogleSource | undefined, index: DocumentIndex, env: NodeJS.ProcessEnv, name: string, max: number, signal?: AbortSignal, rescan?: boolean) => Promise<SyncResult>;
20
+ //# sourceMappingURL=sync.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.d.ts","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"AAKA,OAAO,EACL,KAAK,aAAa,EAClB,KAAK,YAAY,EAEjB,KAAK,YAAY,EAGlB,MAAM,YAAY,CAAA;AASnB,eAAO,MAAM,MAAM,SACX,YAAY,SACX,MAAM,EAAE,WACN,MAAM,CAAC,MAAM,EAAE,YAAY,CAAC,yBAEpC,OASF,CAAA;AAkID,MAAM,WAAW,UAAU;IACzB,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;IACf,SAAS,EAAE,MAAM,CAAA;IACjB,OAAO,EAAE,MAAM,CAAA;IACf,OAAO,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACzC,MAAM,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IACvD,QAAQ,EAAE,MAAM,CAAA;CACjB;AACD,eAAO,MAAM,IAAI,WACP,YAAY,GAAG,SAAS,SACzB,aAAa,OACf,MAAM,CAAC,UAAU,QAChB,MAAM,OACP,MAAM,WACF,WAAW,uBAEnB,OAAO,CAAC,UAAU,CAuGpB,CAAA"}
package/dist/sync.js ADDED
@@ -0,0 +1,278 @@
1
+ import { createHash } from "node:crypto";
2
+ import { CliError } from "@wirecat/cli-core";
3
+ import { activeProfile } from "./config.js";
4
+ import { googleError } from "./errors.js";
5
+ import { supported } from "./google.js";
6
+ import { FOLDER, } from "./model.js";
7
+ import { lockProfile } from "./profile-lock.js";
8
+ import { readState, removeSnapshot, saveSnapshot, saveState } from "./state.js";
9
+ const scopeHash = (roots) => createHash("sha256")
10
+ .update(JSON.stringify([...roots].sort()))
11
+ .digest("hex");
12
+ const hashText = (text) => createHash("sha256").update(text).digest("hex");
13
+ export const within = (file, roots, folders, seen = new Set()) => {
14
+ if (file.trashed)
15
+ return false;
16
+ if (roots.includes(file.id))
17
+ return true;
18
+ if (seen.has(file.id))
19
+ throw new CliError("invalid_response", "folder ancestry contains a cycle");
20
+ const next = new Set([...seen, file.id]);
21
+ return file.parents.some((id) => {
22
+ const folder = folders[id];
23
+ return folder ? within(folder, roots, folders, next) : roots.includes(id);
24
+ });
25
+ };
26
+ const plan = async (source, state, roots, abandoned = []) => {
27
+ const scope = scopeHash(roots);
28
+ if (!roots.length)
29
+ return {
30
+ scope,
31
+ cursor: state.cursor ?? "",
32
+ folders: {},
33
+ skipped: [],
34
+ jobs: [...new Set([...Object.keys(state.documents), ...abandoned])].map((id) => ({ id, kind: "remove" })),
35
+ };
36
+ if (!source)
37
+ throw new CliError("configuration_error", "selected folders require an authenticated Google source");
38
+ const initial = !state.cursor || scope !== state.scope;
39
+ const cursor = initial ? (roots.length ? await source.startToken() : (state.cursor ?? "")) : state.cursor;
40
+ const folders = initial ? {} : structuredClone(state.folders);
41
+ const files = new Map(Object.values(state.documents).map((doc) => [doc.metadata.id, doc.metadata]));
42
+ const changed = new Set();
43
+ for (const skipped of state.skipped)
44
+ if (skipped.file)
45
+ files.set(skipped.id, skipped.file);
46
+ const visited = new Set();
47
+ let discovered = 0;
48
+ const crawl = async (folder, ancestry = new Set()) => {
49
+ if (ancestry.has(folder.id))
50
+ throw new CliError("invalid_response", "folder traversal contains a cycle");
51
+ if (visited.has(folder.id))
52
+ return;
53
+ visited.add(folder.id);
54
+ folders[folder.id] = folder;
55
+ for (const file of await source.children(folder.id)) {
56
+ if (++discovered > 10000)
57
+ throw new CliError("provider_error", "folder scan exceeded 10000 entries; checkpoint preserved");
58
+ if (file.mime === FOLDER)
59
+ await crawl(file, new Set([...ancestry, folder.id]));
60
+ else {
61
+ files.set(file.id, file);
62
+ changed.add(file.id);
63
+ }
64
+ }
65
+ };
66
+ let finalCursor = cursor;
67
+ if (initial) {
68
+ files.clear();
69
+ for (const root of roots) {
70
+ if (visited.has(root))
71
+ continue;
72
+ const folder = await source.metadata(root);
73
+ if (folder.mime !== FOLDER || folder.trashed)
74
+ throw new CliError("validation_error", "configured root is not an accessible folder");
75
+ await crawl(folder);
76
+ }
77
+ }
78
+ else {
79
+ const page = await source.changes(cursor);
80
+ finalCursor = page.cursor;
81
+ const latest = new Map(page.items.map((change) => [change.id, change]));
82
+ const entering = [];
83
+ // Apply all ancestry changes before classifying document scope.
84
+ for (const change of latest.values()) {
85
+ if (change.removed || change.file?.trashed) {
86
+ files.delete(change.id);
87
+ if (folders[change.id])
88
+ folders[change.id] = { ...folders[change.id], trashed: true };
89
+ }
90
+ else if (change.file?.mime === FOLDER) {
91
+ folders[change.id] = change.file;
92
+ entering.push(change.file);
93
+ }
94
+ else if (change.file) {
95
+ files.set(change.id, change.file);
96
+ changed.add(change.id);
97
+ }
98
+ else if (state.documents[change.id] || folders[change.id])
99
+ throw new CliError("invalid_response", "known source changed without metadata; checkpoint preserved");
100
+ }
101
+ // Drive-level access changes may not emit an event for every descendant file.
102
+ for (const root of roots) {
103
+ const previous = folders[root];
104
+ try {
105
+ const current = await source.metadata(root);
106
+ if (current.id !== root || current.mime !== FOLDER)
107
+ throw new CliError("invalid_response", "selected folder metadata is inconsistent");
108
+ folders[root] = current;
109
+ if (previous?.trashed && !current.trashed)
110
+ entering.push(current);
111
+ }
112
+ catch (error) {
113
+ const safe = googleError(error);
114
+ if (safe.code !== "not_found" || !previous)
115
+ throw safe;
116
+ folders[root] = { ...previous, trashed: true };
117
+ }
118
+ }
119
+ for (const folder of entering)
120
+ if (!visited.has(folder.id) && within(folder, roots, folders))
121
+ await crawl(folder);
122
+ }
123
+ const jobs = [];
124
+ const skipped = [];
125
+ for (const root of roots)
126
+ if (folders[root]?.trashed)
127
+ skipped.push({ id: root, reason: "selected folder is unavailable" });
128
+ for (const [id, file] of files) {
129
+ if (!within(file, roots, folders))
130
+ continue;
131
+ const previousSkip = state.skipped.find((item) => item.id === id);
132
+ if (previousSkip && !changed.has(id) && !initial) {
133
+ skipped.push({ ...previousSkip, file });
134
+ continue;
135
+ }
136
+ if (!supported(file) || !file.canDownload) {
137
+ skipped.push({ id, reason: !file.canDownload ? "downloads restricted" : `unsupported type: ${file.mime}`, file });
138
+ continue;
139
+ }
140
+ if (changed.has(id)) {
141
+ const previous = state.documents[id]?.metadata;
142
+ if (!previous ||
143
+ previous.version !== file.version ||
144
+ previous.modifiedAt !== file.modifiedAt ||
145
+ previous.name !== file.name ||
146
+ previous.canDownload !== file.canDownload ||
147
+ JSON.stringify(previous.parents) !== JSON.stringify(file.parents) ||
148
+ initial)
149
+ jobs.push({ id, kind: "save", file });
150
+ }
151
+ }
152
+ for (const id of new Set([...Object.keys(state.documents), ...abandoned])) {
153
+ const file = files.get(id);
154
+ if (!file || !within(file, roots, folders) || !supported(file) || !file.canDownload)
155
+ jobs.push({ id, kind: "remove" });
156
+ }
157
+ // Only retain metadata for selected ancestry; the account-wide feed includes unrelated folders.
158
+ const scopedFolders = Object.fromEntries(Object.entries(folders).filter(([, file]) => within(file, roots, folders) || roots.includes(file.id)));
159
+ return { scope, cursor: finalCursor, folders: scopedFolders, jobs, skipped };
160
+ };
161
+ export const sync = async (source, index, env, name, max, signal, rescan = false) => {
162
+ const profile = activeProfile(env, name);
163
+ if (signal?.aborted)
164
+ throw new CliError("cancelled", "sync was cancelled");
165
+ const lock = await lockProfile(env, name);
166
+ const result = {
167
+ saved: 0,
168
+ removed: 0,
169
+ unchanged: 0,
170
+ pending: 0,
171
+ skipped: [],
172
+ errors: [],
173
+ coverage: "selected folders only; unsupported files are reported",
174
+ };
175
+ try {
176
+ if (profile.roots.length && (!source || (await source.identity()) !== profile.principal))
177
+ throw new CliError("authentication_error", "signed-in Google account does not match this profile");
178
+ const state = readState(env, name, profile.principal);
179
+ const currentScope = scopeHash(profile.roots);
180
+ const abandoned = state.pending && (state.pending.scope !== currentScope || rescan) ? state.pending.jobs.map((job) => job.id) : [];
181
+ if (state.pending?.scope !== currentScope || rescan)
182
+ delete state.pending;
183
+ if (rescan)
184
+ delete state.cursor;
185
+ if (!state.pending) {
186
+ state.pending = await plan(source, state, profile.roots, abandoned);
187
+ state.skipped = state.pending.skipped;
188
+ saveState(env, name, state);
189
+ }
190
+ const pending = state.pending;
191
+ if (!pending)
192
+ throw new CliError("invalid_response", "could not prepare a sync batch");
193
+ result.skipped = state.skipped.map(({ id, reason }) => ({ id, reason }));
194
+ const jobs = [...pending.jobs].slice(0, max);
195
+ for (const job of jobs) {
196
+ if (signal?.aborted)
197
+ throw new CliError("cancelled", "sync was cancelled; pending operations are retained");
198
+ lock.assertHeld();
199
+ try {
200
+ if (job.kind === "remove") {
201
+ await index.remove(profile.principal, job.id);
202
+ removeSnapshot(env, name, job.id);
203
+ delete state.documents[job.id];
204
+ result.removed++;
205
+ }
206
+ else if (job.file && (!supported(job.file) || !job.file.canDownload)) {
207
+ const skipped = {
208
+ id: job.id,
209
+ reason: !job.file.canDownload ? "downloads restricted" : `unsupported type: ${job.file.mime}`,
210
+ };
211
+ if (state.documents[job.id]) {
212
+ await index.remove(profile.principal, job.id);
213
+ removeSnapshot(env, name, job.id);
214
+ delete state.documents[job.id];
215
+ }
216
+ state.skipped.push(skipped);
217
+ result.skipped.push(skipped);
218
+ }
219
+ else {
220
+ if (!source)
221
+ throw new CliError("configuration_error", "a pending save requires Google sign-in");
222
+ const content = await source.content(job.id);
223
+ if (!within(content.metadata, profile.roots, pending.folders)) {
224
+ await index.remove(profile.principal, job.id);
225
+ removeSnapshot(env, name, job.id);
226
+ delete state.documents[job.id];
227
+ result.removed++;
228
+ }
229
+ else {
230
+ const hash = hashText(content.text);
231
+ const previous = state.documents[job.id];
232
+ const reference = await index.save(profile.principal, content, hash);
233
+ saveSnapshot(env, name, content);
234
+ state.documents[job.id] = { metadata: content.metadata, hash, reference, tabs: content.tabs.length };
235
+ if (previous?.hash === hash)
236
+ result.unchanged++;
237
+ else
238
+ result.saved++;
239
+ }
240
+ }
241
+ pending.jobs = pending.jobs.filter((item) => item !== job);
242
+ saveState(env, name, state);
243
+ }
244
+ catch (error) {
245
+ const safe = googleError(error);
246
+ if (safe.code === "cancelled")
247
+ throw safe;
248
+ if (job.kind === "save" && (safe.code === "not_found" || safe.code === "validation_error")) {
249
+ await index.remove(profile.principal, job.id);
250
+ removeSnapshot(env, name, job.id);
251
+ delete state.documents[job.id];
252
+ const skipped = { id: job.id, reason: safe.message, ...(job.file ? { file: job.file } : {}) };
253
+ state.skipped = state.skipped.filter((item) => item.id !== job.id);
254
+ state.skipped.push(skipped);
255
+ result.skipped.push({ id: skipped.id, reason: skipped.reason });
256
+ pending.jobs = pending.jobs.filter((item) => item !== job);
257
+ saveState(env, name, state);
258
+ continue;
259
+ }
260
+ result.errors.push({ id: job.id, code: safe.code, message: safe.message });
261
+ }
262
+ }
263
+ result.pending = pending.jobs.length;
264
+ if (!pending.jobs.length) {
265
+ state.cursor = pending.cursor;
266
+ state.scope = pending.scope;
267
+ state.folders = pending.folders;
268
+ delete state.pending;
269
+ state.lastSync = new Date().toISOString();
270
+ saveState(env, name, state);
271
+ }
272
+ return result;
273
+ }
274
+ finally {
275
+ await lock.release();
276
+ }
277
+ };
278
+ //# sourceMappingURL=sync.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sync.js","sourceRoot":"","sources":["../src/sync.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,26 @@
1
+ import { Credentials, type KeyringStore } from "@wirecat/cli-core";
2
+ import { OAuth2Client } from "google-auth-library";
3
+ import * as v from "valibot";
4
+ export declare const READ_SCOPE = "https://www.googleapis.com/auth/drive.readonly";
5
+ export declare const WRITE_SCOPE = "https://www.googleapis.com/auth/drive";
6
+ export declare const ACTIVITY_SCOPE = "https://www.googleapis.com/auth/drive.activity.readonly";
7
+ export declare const APPS_SCOPE = "https://www.googleapis.com/auth/drive.apps.readonly";
8
+ declare const Session: v.ObjectSchema<{
9
+ readonly principal: v.StringSchema<undefined>;
10
+ readonly clientId: v.StringSchema<undefined>;
11
+ readonly clientSecret: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
12
+ readonly tokens: v.ObjectSchema<{
13
+ readonly access_token: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
14
+ readonly refresh_token: v.SchemaWithPipe<readonly [v.StringSchema<undefined>, v.MinLengthAction<string, 1, undefined>]>;
15
+ readonly expiry_date: v.OptionalSchema<v.NullableSchema<v.NumberSchema<undefined>, undefined>, undefined>;
16
+ readonly scope: v.OptionalSchema<v.StringSchema<undefined>, undefined>;
17
+ readonly token_type: v.OptionalSchema<v.NullableSchema<v.StringSchema<undefined>, undefined>, undefined>;
18
+ }, undefined>;
19
+ }, undefined>;
20
+ export type Session = v.InferOutput<typeof Session>;
21
+ export declare const credentials: (env: NodeJS.ProcessEnv, storage: "keyring" | "file", keyring?: KeyringStore) => Credentials;
22
+ export declare const saveSession: (env: NodeJS.ProcessEnv, name: string, session: Session, storage: "keyring" | "file", keyring?: KeyringStore) => void;
23
+ export declare const authorizedClient: (env: NodeJS.ProcessEnv, name: string, keyring?: KeyringStore, signal?: AbortSignal) => OAuth2Client;
24
+ export declare const checkAuthorization: (client: OAuth2Client, required?: string) => Promise<void>;
25
+ export {};
26
+ //# sourceMappingURL=tokens.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.d.ts","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"AAAA,OAAO,EAAY,WAAW,EAAE,KAAK,YAAY,EAAsB,MAAM,mBAAmB,CAAA;AAChG,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAClD,OAAO,KAAK,CAAC,MAAM,SAAS,CAAA;AAI5B,eAAO,MAAM,UAAU,mDAAmD,CAAA;AAC1E,eAAO,MAAM,WAAW,0CAA0C,CAAA;AAClE,eAAO,MAAM,cAAc,4DAA4D,CAAA;AACvF,eAAO,MAAM,UAAU,wDAAwD,CAAA;AAC/E,QAAA,MAAM,OAAO;;;;;;;;;;;aAWX,CAAA;AACF,MAAM,MAAM,OAAO,GAAG,CAAC,CAAC,WAAW,CAAC,OAAO,OAAO,CAAC,CAAA;AACnD,eAAO,MAAM,WAAW,QAAS,MAAM,CAAC,UAAU,WAAW,SAAS,GAAG,MAAM,YAAY,YAAY,KAAG,WAQtG,CAAA;AACJ,eAAO,MAAM,WAAW,QACjB,MAAM,CAAC,UAAU,QAChB,MAAM,WACH,OAAO,WACP,SAAS,GAAG,MAAM,YACjB,YAAY,KACrB,IASF,CAAA;AACD,eAAO,MAAM,gBAAgB,QACtB,MAAM,CAAC,UAAU,QAChB,MAAM,YACF,YAAY,WACb,WAAW,KACnB,YA6BF,CAAA;AACD,eAAO,MAAM,kBAAkB,WAAkB,YAAY,wBAA0B,OAAO,CAAC,IAAI,CAalG,CAAA"}
package/dist/tokens.js ADDED
@@ -0,0 +1,83 @@
1
+ import { CliError, Credentials, pathsAreOverridden } from "@wirecat/cli-core";
2
+ import { OAuth2Client } from "google-auth-library";
3
+ import * as v from "valibot";
4
+ import { activeProfile, paths } from "./config.js";
5
+ import { googleError } from "./errors.js";
6
+ export const READ_SCOPE = "https://www.googleapis.com/auth/drive.readonly";
7
+ export const WRITE_SCOPE = "https://www.googleapis.com/auth/drive";
8
+ export const ACTIVITY_SCOPE = "https://www.googleapis.com/auth/drive.activity.readonly";
9
+ export const APPS_SCOPE = "https://www.googleapis.com/auth/drive.apps.readonly";
10
+ const Session = v.object({
11
+ principal: v.string(),
12
+ clientId: v.string(),
13
+ clientSecret: v.optional(v.string()),
14
+ tokens: v.object({
15
+ access_token: v.optional(v.nullable(v.string())),
16
+ refresh_token: v.pipe(v.string(), v.minLength(1)),
17
+ expiry_date: v.optional(v.nullable(v.number())),
18
+ scope: v.optional(v.string()),
19
+ token_type: v.optional(v.nullable(v.string())),
20
+ }),
21
+ });
22
+ export const credentials = (env, storage, keyring) => new Credentials({
23
+ configDir: paths(env).config,
24
+ service: "drive-cli",
25
+ storage,
26
+ env,
27
+ isolated: pathsAreOverridden({ appName: "drive-cli", prefix: "DRIVE", env }),
28
+ ...(keyring ? { keyring } : {}),
29
+ });
30
+ export const saveSession = (env, name, session, storage, keyring) => {
31
+ try {
32
+ credentials(env, storage, keyring).write(name, JSON.stringify(session));
33
+ }
34
+ catch {
35
+ throw new CliError("configuration_error", "could not save Google sign-in; use an available keyring or explicitly choose --credential-storage file");
36
+ }
37
+ };
38
+ export const authorizedClient = (env, name, keyring, signal) => {
39
+ const profile = activeProfile(env, name);
40
+ let parsed;
41
+ try {
42
+ const secret = credentials(env, profile.storage, keyring).read(name)?.secret;
43
+ if (!secret)
44
+ throw new Error("missing login");
45
+ parsed = v.safeParse(Session, JSON.parse(secret));
46
+ }
47
+ catch {
48
+ throw new CliError("authentication_error", "could not load Google sign-in — run drive session start again");
49
+ }
50
+ if (!parsed.success || parsed.output.principal !== profile.principal)
51
+ throw new CliError("authentication_error", "saved sign-in is invalid or belongs to another account");
52
+ const session = parsed.output;
53
+ const client = new OAuth2Client({
54
+ clientId: session.clientId,
55
+ clientSecret: session.clientSecret,
56
+ transporterOptions: { timeout: 30000, ...(signal ? { signal } : {}) },
57
+ });
58
+ client.setCredentials(session.tokens);
59
+ // Token refresh can rotate the refresh token; keep it with the same profile's application.
60
+ client.on("tokens", (tokens) => {
61
+ session.tokens = {
62
+ ...session.tokens,
63
+ ...tokens,
64
+ refresh_token: tokens.refresh_token ?? session.tokens.refresh_token,
65
+ };
66
+ saveSession(env, name, session, profile.storage, keyring);
67
+ });
68
+ return client;
69
+ };
70
+ export const checkAuthorization = async (client, required = READ_SCOPE) => {
71
+ try {
72
+ const { token } = await client.getAccessToken();
73
+ if (!token)
74
+ throw new CliError("authentication_error", "Google returned no access token");
75
+ const info = await client.getTokenInfo(token);
76
+ if (!info.scopes.includes(required) && !(required === READ_SCOPE && info.scopes.includes(WRITE_SCOPE)))
77
+ throw new CliError("permission_error", "sign-in lacks the required permission; run drive <profile> session start with --write, --activity or --apps when needed");
78
+ }
79
+ catch (error) {
80
+ throw googleError(error);
81
+ }
82
+ };
83
+ //# sourceMappingURL=tokens.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tokens.js","sourceRoot":"","sources":["../src/tokens.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const VERSION: string;
2
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,OAAO,QAEX,CAAA"}
@@ -0,0 +1,3 @@
1
+ import { readFileSync } from "node:fs";
2
+ export const VERSION = JSON.parse(readFileSync(new URL("../package.json", import.meta.url), "utf8")).version;
3
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../src/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA;AACtC,MAAM,CAAC,MAAM,OAAO,GAClB,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,GAAG,CAAC,iBAAiB,EAAE,OAAO,IAAI,CAAC,GAAG,CAAC,EAAE,MAAM,CAAC,CAC7E,CAAC,OAAO,CAAA"}