@framers/agentos-ext-github 0.8.0 → 0.10.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 (71) hide show
  1. package/README.md +19 -13
  2. package/dist/documents/GitHubDocumentsConnector.d.ts +123 -26
  3. package/dist/documents/GitHubDocumentsConnector.d.ts.map +1 -1
  4. package/dist/documents/GitHubDocumentsConnector.js +229 -46
  5. package/dist/documents/GitHubDocumentsConnector.js.map +1 -1
  6. package/dist/documents/index.d.ts +3 -3
  7. package/dist/documents/index.d.ts.map +1 -1
  8. package/dist/documents/index.js +2 -2
  9. package/dist/documents/index.js.map +1 -1
  10. package/dist/documents/links.d.ts +28 -14
  11. package/dist/documents/links.d.ts.map +1 -1
  12. package/dist/documents/links.js +113 -39
  13. package/dist/documents/links.js.map +1 -1
  14. package/dist/documents/tree.d.ts +47 -13
  15. package/dist/documents/tree.d.ts.map +1 -1
  16. package/dist/documents/tree.js +98 -15
  17. package/dist/documents/tree.js.map +1 -1
  18. package/manifest.json +1 -1
  19. package/package.json +5 -4
  20. package/dist/__tests__/app.test.d.ts +0 -7
  21. package/dist/__tests__/app.test.d.ts.map +0 -1
  22. package/dist/__tests__/app.test.js +0 -1219
  23. package/dist/__tests__/app.test.js.map +0 -1
  24. package/dist/__tests__/documents.test.d.ts +0 -9
  25. package/dist/__tests__/documents.test.d.ts.map +0 -1
  26. package/dist/__tests__/documents.test.js +0 -644
  27. package/dist/__tests__/documents.test.js.map +0 -1
  28. package/dist/__tests__/entry.test.d.ts +0 -7
  29. package/dist/__tests__/entry.test.d.ts.map +0 -1
  30. package/dist/__tests__/entry.test.js +0 -34
  31. package/dist/__tests__/entry.test.js.map +0 -1
  32. package/dist/__tests__/events.test.d.ts +0 -8
  33. package/dist/__tests__/events.test.d.ts.map +0 -1
  34. package/dist/__tests__/events.test.js +0 -321
  35. package/dist/__tests__/events.test.js.map +0 -1
  36. package/dist/__tests__/fileAndBranchTools.test.d.ts +0 -6
  37. package/dist/__tests__/fileAndBranchTools.test.d.ts.map +0 -1
  38. package/dist/__tests__/fileAndBranchTools.test.js +0 -310
  39. package/dist/__tests__/fileAndBranchTools.test.js.map +0 -1
  40. package/dist/__tests__/indexer.test.d.ts +0 -6
  41. package/dist/__tests__/indexer.test.d.ts.map +0 -1
  42. package/dist/__tests__/indexer.test.js +0 -253
  43. package/dist/__tests__/indexer.test.js.map +0 -1
  44. package/dist/__tests__/issueTools.test.d.ts +0 -5
  45. package/dist/__tests__/issueTools.test.d.ts.map +0 -1
  46. package/dist/__tests__/issueTools.test.js +0 -183
  47. package/dist/__tests__/issueTools.test.js.map +0 -1
  48. package/dist/__tests__/links.test.d.ts +0 -8
  49. package/dist/__tests__/links.test.d.ts.map +0 -1
  50. package/dist/__tests__/links.test.js +0 -182
  51. package/dist/__tests__/links.test.js.map +0 -1
  52. package/dist/__tests__/prTools.test.d.ts +0 -5
  53. package/dist/__tests__/prTools.test.d.ts.map +0 -1
  54. package/dist/__tests__/prTools.test.js +0 -318
  55. package/dist/__tests__/prTools.test.js.map +0 -1
  56. package/dist/__tests__/refs.test.d.ts +0 -7
  57. package/dist/__tests__/refs.test.d.ts.map +0 -1
  58. package/dist/__tests__/refs.test.js +0 -420
  59. package/dist/__tests__/refs.test.js.map +0 -1
  60. package/dist/__tests__/releaseAndActionsTools.test.d.ts +0 -6
  61. package/dist/__tests__/releaseAndActionsTools.test.d.ts.map +0 -1
  62. package/dist/__tests__/releaseAndActionsTools.test.js +0 -315
  63. package/dist/__tests__/releaseAndActionsTools.test.js.map +0 -1
  64. package/dist/__tests__/repoTools.test.d.ts +0 -6
  65. package/dist/__tests__/repoTools.test.d.ts.map +0 -1
  66. package/dist/__tests__/repoTools.test.js +0 -308
  67. package/dist/__tests__/repoTools.test.js.map +0 -1
  68. package/dist/__tests__/service.test.d.ts +0 -6
  69. package/dist/__tests__/service.test.d.ts.map +0 -1
  70. package/dist/__tests__/service.test.js +0 -173
  71. package/dist/__tests__/service.test.js.map +0 -1
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * @fileoverview The GitHub addresses a person pastes, read without a request: a repository, a folder or a file on
3
3
  * github.com, and a file on raw.githubusercontent.com. Any other address on GitHub's hosts is refused, so no form of a
4
- * GitHub address is read as another site's page; an address on any other host is not GitHub's.
4
+ * GitHub address is read as another site's page; an address on any other host is not GitHub's. A text is read as the
5
+ * URL standard reads an address, so every form a browser opens as a GitHub address is answered as one.
5
6
  * @module agentos-ext-github/documents/links
6
7
  */
7
8
  /** The hosts of GitHub's site, where a repository, a folder and a file are read. */
@@ -12,6 +13,13 @@ const RAW_HOST = 'raw.githubusercontent.com';
12
13
  const OTHER_HOSTS = new Set(['gist.github.com', 'api.github.com', 'codeload.github.com', 'uploads.github.com']);
13
14
  /** The domain under which GitHub serves its users' content: raw files, gists, release assets, avatars. */
14
15
  const CONTENT_DOMAIN = 'githubusercontent.com';
16
+ /**
17
+ * The domain of GitHub Enterprise Cloud with data residency: each enterprise on a subdomain of its own, its API on
18
+ * `api.<subdomain>.ghe.com`
19
+ * (https://docs.github.com/en/enterprise-cloud@latest/admin/data-residency/about-github-enterprise-cloud-with-data-residency).
20
+ * Its repositories are not read here.
21
+ */
22
+ const ENTERPRISE_DOMAIN = 'ghe.com';
15
23
  /** First path segments of github.com that name GitHub's own pages, never an account. */
16
24
  const SITE_PAGES = new Set([
17
25
  'about', 'account', 'apps', 'codespaces', 'collections', 'contact', 'copilot', 'customer-stories', 'dashboard',
@@ -23,8 +31,19 @@ const SITE_PAGES = new Set([
23
31
  const OWNER = /^[A-Za-z0-9][A-Za-z0-9_-]{0,99}$/;
24
32
  /** A repository's name: letters, digits, dots, dashes and underscores. */
25
33
  const REPO = /^[A-Za-z0-9._-]{1,100}$/;
26
- /** An address with a scheme and an authority (`https://`, `http://`, `git://`, `ssh://`), whatever the scheme. */
27
- const SCHEME = /^[A-Za-z][A-Za-z0-9+.-]*:\/\//;
34
+ /**
35
+ * A scheme and the slashes before an address's host, as the URL standard reads them
36
+ * (https://url.spec.whatwg.org/#scheme-state), in any case: after `http`, `https`, `ws`, `wss` and `ftp`, special
37
+ * schemes, any run of `/` and `\`, none included (https://url.spec.whatwg.org/#special-authority-slashes-state); after
38
+ * `file`, two of them (https://url.spec.whatwg.org/#file-slash-state), and none when a third follows, since the host is
39
+ * then empty (https://url.spec.whatwg.org/#file-host-state) and the address names no host; after any other scheme
40
+ * (`git://`, `ssh://`), `//`.
41
+ */
42
+ const AUTHORITY = /^(?:(?:https?|wss?|ftp):[/\\]*|file:[/\\]{2}(?![/\\])|(?!file:)[a-z][a-z0-9+.-]*:\/\/)/i;
43
+ /** The characters the URL standard removes wherever they stand in an address: tab, line feed and carriage return. */
44
+ const TAB_OR_NEWLINE = /[\t\n\r]/g;
45
+ /** A white space character, as `String.prototype.trim` drops it. */
46
+ const WHITE_SPACE = /\s/;
28
47
  /** An opaque address, such as `mailto:` or `javascript:`, which names no host. */
29
48
  const OPAQUE = /^[A-Za-z][A-Za-z0-9+-]*:/;
30
49
  /**
@@ -34,6 +53,12 @@ const OPAQUE = /^[A-Za-z][A-Za-z0-9+-]*:/;
34
53
  * no path and stays opaque.
35
54
  */
36
55
  const CREDENTIALS = /^[^/?#\s@]*@[^/?#\s]*\//;
56
+ /**
57
+ * GitHub's namespaces of a branch's and a tag's full name, which its own Raw links write
58
+ * (`https://github.com/cli/cli/raw/refs/tags/v2.0.0/README.md` for a file at the tag `v2.0.0`): the one form that tells
59
+ * a tag from a branch of the same name.
60
+ */
61
+ const FULL_NAME = /^refs\/(?:heads|tags)\//;
37
62
  /** Git's address of a repository over SSH without a scheme: `git@github.com:<owner>/<repo>.git`. */
38
63
  const SCP = /^([A-Za-z0-9._-]+)@([^/:\s]+):(?!\/)(.*)$/;
39
64
  /** A refusal: the address is GitHub's, and names nothing read here. */
@@ -41,16 +66,38 @@ function refused() {
41
66
  return { kind: 'refused' };
42
67
  }
43
68
  /**
44
- * The address a text holds, read as its `https://` form: the scheme is dropped whatever it is, and a text without one
45
- * (`github.com/<owner>/<repo>`, `<user>:<password>@github.com/<owner>/<repo>`) is read as if it had it. Null for an
46
- * opaque address and for text that is no address.
69
+ * True for a character dropped around a pasted address: a C0 control or a space, as the URL standard drops them
70
+ * (https://url.spec.whatwg.org/#concept-basic-url-parser), or any other white space, as `String.prototype.trim` does.
71
+ */
72
+ function isAround(code) {
73
+ return code <= 0x20 || WHITE_SPACE.test(String.fromCharCode(code));
74
+ }
75
+ /**
76
+ * A pasted text as the URL standard reads an address: without the C0 controls, spaces and other white space around it,
77
+ * and without any tab or newline within it. Read by a loop at each end, so a text of many such characters costs one
78
+ * pass.
79
+ */
80
+ function cleaned(text) {
81
+ let start = 0;
82
+ let end = text.length;
83
+ while (start < end && isAround(text.charCodeAt(start)))
84
+ start += 1;
85
+ while (end > start && isAround(text.charCodeAt(end - 1)))
86
+ end -= 1;
87
+ return text.slice(start, end).replace(TAB_OR_NEWLINE, '');
88
+ }
89
+ /**
90
+ * The address a text holds, read as its `https://` form: the scheme and the slashes before the host are dropped
91
+ * whatever the scheme, and a text without one (`github.com/<owner>/<repo>`,
92
+ * `<user>:<password>@github.com/<owner>/<repo>`) is read as if it had it. Null for an opaque address (a scheme the URL
93
+ * standard does not treat as special, without `//`) and for text that is no address.
47
94
  */
48
95
  function addressOf(text) {
49
- const scheme = SCHEME.exec(text);
50
- if (scheme === null && OPAQUE.test(text) && !CREDENTIALS.test(text))
96
+ const authority = AUTHORITY.exec(text);
97
+ if (authority === null && OPAQUE.test(text) && !CREDENTIALS.test(text))
51
98
  return null;
52
99
  try {
53
- return new URL(`https://${scheme === null ? text : text.slice(scheme[0].length)}`);
100
+ return new URL(`https://${authority === null ? text : text.slice(authority[0].length)}`);
54
101
  }
55
102
  catch {
56
103
  // Text that is no address; the parser's message would quote it.
@@ -68,9 +115,16 @@ function hostOf(host) {
68
115
  end -= 1;
69
116
  return host.slice(0, end).toLowerCase();
70
117
  }
71
- /** True for a host of GitHub's: its site, its raw files, its other hosts and the hosts of its users' content. */
118
+ /** True for `domain` itself or a host under it. */
119
+ function isUnder(host, domain) {
120
+ return host === domain || host.endsWith(`.${domain}`);
121
+ }
122
+ /**
123
+ * True for a host of GitHub's: its site, its raw files, its other hosts, the hosts of its users' content, and the
124
+ * hosts of GitHub Enterprise Cloud with data residency.
125
+ */
72
126
  function isGitHubHost(host) {
73
- return SITE_HOSTS.has(host) || host === RAW_HOST || OTHER_HOSTS.has(host) || host === CONTENT_DOMAIN || host.endsWith(`.${CONTENT_DOMAIN}`);
127
+ return SITE_HOSTS.has(host) || host === RAW_HOST || OTHER_HOSTS.has(host) || isUnder(host, CONTENT_DOMAIN) || isUnder(host, ENTERPRISE_DOMAIN);
74
128
  }
75
129
  /**
76
130
  * An address's path as its segments, each decoded, without a trailing slash; null for a path with an empty segment
@@ -103,21 +157,29 @@ function hasControl(text) {
103
157
  return false;
104
158
  }
105
159
  /**
106
- * A folder's or a file's `<ref>/<path>` from the segments after `/tree/`, `/blob/` or `/raw/`, GitHub's own form of a
107
- * branch by its full name (`refs/heads/<branch>`) read as the branch. Null for none, for another kind of reference
108
- * (`refs/tags/`, `refs/pull/`), and for a text with an empty, `.` or `..` segment or a control character once decoded.
160
+ * A folder's or a file's `<ref>/<path>` from the segments after `/tree/`, `/blob/` or `/raw/`, a branch's or a tag's
161
+ * full name (`refs/heads/<branch>`, `refs/tags/<tag>`) kept whole. Null for none, for another kind of reference
162
+ * (`refs/pull/`, `refs/remotes/`) or a namespace with no name, and for a text with an empty, `.` or `..` segment or a
163
+ * control character once decoded.
109
164
  */
110
165
  function refAndPathOf(segments) {
111
- let parts = segments;
112
- if (parts[0] === 'refs') {
113
- if (parts[1] !== 'heads' || parts.length < 3)
114
- return null;
115
- parts = parts.slice(2);
116
- }
117
- const text = parts.join('/');
166
+ const text = segments.join('/');
118
167
  if (text === '' || hasControl(text))
119
168
  return null;
120
- return text.split('/').every((part) => part !== '' && part !== '.' && part !== '..') ? text : null;
169
+ const parts = text.split('/');
170
+ if (!parts.every((part) => part !== '' && part !== '.' && part !== '..'))
171
+ return null;
172
+ if (parts[0] === 'refs' && (parts.length < 3 || (parts[1] !== 'heads' && parts[1] !== 'tags')))
173
+ return null;
174
+ return text;
175
+ }
176
+ /**
177
+ * True for a ref and a path whose ref is followed by more of the text: a slash after the ref's name, the namespace of a
178
+ * full name aside. Where the ref ends is `resolveRef`'s to settle; a text without such a slash names a ref alone.
179
+ */
180
+ function namesMore(refAndPath) {
181
+ const name = FULL_NAME.test(refAndPath) ? refAndPath.slice(refAndPath.indexOf('/', 'refs/'.length) + 1) : refAndPath;
182
+ return name.includes('/');
121
183
  }
122
184
  /** The owner and the repository of an address's first two segments, `.git` dropped; null when either is not one. */
123
185
  function repositoryOf(segments) {
@@ -143,9 +205,10 @@ function siteLink(segments) {
143
205
  const refAndPath = refAndPathOf(segments.slice(3));
144
206
  if (refAndPath === null)
145
207
  return refused();
146
- const named = refAndPath.includes('/');
147
- // GitHub shows the folder for a blob address that names a ref alone, and answers none for a raw one.
148
- if (view === 'tree' || (view === 'blob' && !named))
208
+ const named = namesMore(refAndPath);
209
+ // GitHub redirects a blob address that names a ref alone by its short name to the folder, and answers 404 for one that
210
+ // names it by its full name and for a raw one.
211
+ if (view === 'tree' || (view === 'blob' && !named && !FULL_NAME.test(refAndPath)))
149
212
  return { kind: 'github_folder', ...repository, refAndPath };
150
213
  if (!named)
151
214
  return refused();
@@ -157,34 +220,45 @@ function rawLink(segments) {
157
220
  return refused();
158
221
  const repository = repositoryOf(segments);
159
222
  const refAndPath = refAndPathOf(segments.slice(2));
160
- if (repository === null || refAndPath === null || !refAndPath.includes('/'))
223
+ if (repository === null || refAndPath === null || !namesMore(refAndPath))
161
224
  return refused();
162
225
  return { kind: 'github_file', ...repository, refAndPath, raw: true };
163
226
  }
164
227
  /**
165
228
  * What a GitHub address names, read without a request. Null for an address whose host is not GitHub's, and for text
166
229
  * that is no address; `refused` for an address on GitHub's hosts that names no repository, folder or file read here: an
167
- * account, an issue, a pull request, a wiki, a release, a commit, a tag, a gist, the API, an archive, GitHub's own
168
- * pages, an address that carries credentials (with a scheme or without one: `<user>:<password>@github.com/...`), and
169
- * a host other than github.com, www.github.com and raw.githubusercontent.com. The scheme (or its absence), a port, the
170
- * dots that end a host, `.git`, a trailing slash, a query and a fragment are ignored, and so is the `git` user of an
171
- * SSH address (`git@github.com:<owner>/<repo>.git`).
230
+ * account, an issue, a pull request, a wiki, a release, a commit, a reference that is neither a branch nor a tag
231
+ * (`refs/pull/<n>/head`), a gist, the API, an archive, GitHub's own pages, an address that carries credentials (with a
232
+ * scheme or without one: `<user>:<password>@github.com/...`), a host of GitHub Enterprise Cloud with data residency
233
+ * (`<subdomain>.ghe.com`), and a host other than github.com, www.github.com and raw.githubusercontent.com. The scheme
234
+ * (or its absence), a port, the dots that end a host, `.git`, a trailing slash, a query and a fragment are ignored, and
235
+ * so is the `git` user of an SSH address (`git@github.com:<owner>/<repo>.git`).
236
+ *
237
+ * The text is read as the URL standard reads an address: the C0 controls and spaces around it, and any other white
238
+ * space there, are dropped, and every tab and newline in it; after `http`, `https`, `ws`, `wss` and `ftp` any run of
239
+ * `/` and `\` stands before the host, none included (`https:github.com/<owner>/<repo>`,
240
+ * `https:\\github.com\<owner>\<repo>`), as a browser opens such an address; after `file`, two of them; after any
241
+ * other scheme, `//`. A backslash in the path is a slash.
172
242
  *
173
243
  * A folder's and a file's ref and path are answered as one text, each segment decoded, since a branch name may hold a
174
- * slash; GitHub's form of a branch by its full name, `refs/heads/<branch>`, is read as the branch. A `/blob/` address
175
- * whose text has no slash names a ref alone and is a folder, as GitHub shows it (its `/blob/<ref>` redirects to
176
- * `/tree/<ref>`); one whose text has a slash is a file, which `resolveRef` may settle as a ref alone (an empty path).
244
+ * slash. A branch's or a tag's full name, `refs/heads/<branch>` or `refs/tags/<tag>`, the form GitHub's own Raw links
245
+ * write, stays whole in it, so `resolveRef` reads the name among the branches or the tags alone: the full name is the
246
+ * one form that tells a tag from a branch of the same name, or a branch from a longer tag beside it (the branch
247
+ * `release` and the tag `release/2.0`). A `/blob/` address whose text has no slash names a ref alone and is a folder,
248
+ * as GitHub shows it (its `/blob/<ref>` redirects to `/tree/<ref>`); one whose text has a slash is a file, which
249
+ * `resolveRef` may settle as a ref alone (an empty path). A full name with nothing after it under `/blob/` or `/raw/`
250
+ * names no file, as GitHub answers it 404, and is refused.
177
251
  *
178
- * @param text The address as pasted; spaces around it are dropped.
252
+ * @param text The address as pasted; the controls and spaces around it are dropped.
179
253
  * @throws TypeError when `text` is not a string.
180
254
  */
181
255
  export function parseGitHubLink(text) {
182
256
  if (typeof text !== 'string')
183
257
  throw new TypeError('a link is a string');
184
- const trimmed = text.trim();
185
- if (trimmed === '')
258
+ const pasted = cleaned(text);
259
+ if (pasted === '')
186
260
  return null;
187
- const scp = SCP.exec(trimmed);
261
+ const scp = SCP.exec(pasted);
188
262
  if (scp !== null) {
189
263
  const host = hostOf(scp[2]);
190
264
  if (!isGitHubHost(host))
@@ -195,7 +269,7 @@ export function parseGitHubLink(text) {
195
269
  const segments = address === null ? null : segmentsOf(address.pathname);
196
270
  return segments === null ? refused() : siteLink(segments);
197
271
  }
198
- const address = addressOf(trimmed);
272
+ const address = addressOf(pasted);
199
273
  if (address === null)
200
274
  return null;
201
275
  const host = hostOf(address.hostname);
@@ -1 +1 @@
1
- {"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/documents/links.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"links.js","sourceRoot":"","sources":["../../src/documents/links.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * @fileoverview A repository's tree at a commit, read within a request budget, and the filter that keeps its
3
3
  * documentation. GitHub cuts a recursive tree past 100,000 entries or 7 MB and marks it `truncated`; such a tree is
4
- * read again one subtree at a time, and a level GitHub cuts short even when asked for alone is refused whole.
4
+ * read again one subtree at a time, a folder's files by the folders on its path alone, and a level GitHub cuts short
5
+ * even when asked for alone is refused whole.
5
6
  * @module agentos-ext-github/documents/tree
6
7
  */
7
8
  /** One file of a tree: its path from the repository's root, its blob and its size in bytes. */
@@ -77,23 +78,40 @@ export declare class TreeTooLarge extends Error {
77
78
  */
78
79
  constructor(maxRequests: number, reason?: TreeTooLargeReason);
79
80
  }
80
- /** The budget of a tree read, the folders it never walks into, and its abort signal. */
81
+ /** The budget of a tree read, the folders it never walks into, the folder or the file it reads, and its abort signal. */
81
82
  export interface ReadTreeOptions {
82
83
  /** At most this many requests ({@link DEFAULT_MAX_TREE_REQUESTS} when absent). */
83
84
  maxRequests?: number;
84
85
  /** Folders, by name, whose files are left out and which a read by subtree never requests. */
85
86
  skipFolders?: readonly string[];
87
+ /**
88
+ * A folder of the tree, or a file, by its path with no leading or trailing slash: the files at it or under it are
89
+ * read, and no others. When GitHub truncates the recursive tree, the folders on the path are asked for one at a time
90
+ * and the folder it names is read as a whole tree is, so the read costs the path's depth and the folder's own
91
+ * subtree, whatever lies beside it. The whole tree when absent or `''`.
92
+ */
93
+ path?: string;
86
94
  signal?: AbortSignal;
87
95
  }
88
96
  /** A file's extension with its dot, in lower case, or `''` when its name has none. */
89
97
  export declare function extensionOf(path: string): string;
90
98
  /**
91
- * Every file of a repository's tree at a commit (symbolic links aside). The tree is asked for recursively; when GitHub
92
- * answers it truncated, its top level is read and each subtree is asked for the same way, so only the parts too large
93
- * for one answer cost a request per folder. Each request counts against `maxRequests`, and the read throws
94
- * {@link TreeTooLarge} (`budget`) rather than make one more. A level GitHub answers truncated without recursion as well
95
- * throws {@link TreeTooLarge} (`truncated`) at that answer, before any folder under it is asked for: the tree answer's
96
- * `truncated` field can be set on any answer, and a part of the tree would leave out files that then read as removed.
99
+ * Every file of a repository's tree at a commit (symbolic links aside), or of the folder or the file `options.path`
100
+ * names. The tree is asked for recursively; when GitHub answers it truncated, its top level is read and each subtree is
101
+ * asked for the same way, so only the parts too large for one answer cost a request per folder. Each request counts
102
+ * against `maxRequests`, and the read throws {@link TreeTooLarge} (`budget`) rather than make one more. A level GitHub
103
+ * answers truncated without recursion as well throws {@link TreeTooLarge} (`truncated`) at that answer, before any
104
+ * folder under it is asked for: the tree answer's `truncated` field can be set on any answer, and a part of the tree
105
+ * would leave out files that then read as removed.
106
+ *
107
+ * With a `path`, the files at it or under it are answered. A truncated tree is then read by the folders on the path
108
+ * alone, each asked for without recursion, down to the folder the path names, which is read as above, or to the file:
109
+ * a small folder of a large repository costs the path's depth and its own subtree, never a request for a folder beside
110
+ * it. A level that does not name the path's next folder or file answers no file, unless GitHub cut that level short,
111
+ * which throws {@link TreeTooLarge} (`truncated`), since the name may stand past the cut; a level cut short that names
112
+ * it is read on, since the folder's own subtree is whole. A path through a skipped folder (one of its segments before
113
+ * the last, which may name a file) holds no file kept, so it answers no file before any request, whatever the tree; a
114
+ * read whose signal is already aborted throws {@link GitHubNoAnswer} (`cancelled`) there, as a request would.
97
115
  *
98
116
  * Name the repository by its id. A full name reads whatever repository holds that name when the tree is asked for: a
99
117
  * renamed repository's old name can be taken again, and an account's old login claimed by another account, which ends
@@ -105,10 +123,19 @@ export declare function extensionOf(path: string): string;
105
123
  * @param repository The repository's id, read at `/repositories/<id>`, or its full name, `owner/name`.
106
124
  * @param commit The commit whose tree is read.
107
125
  * @param apiBase GitHub's REST API, or a stand-in's address in tests.
108
- * @param options The request budget, the folders skipped and an abort signal.
109
- * @throws TypeError before any request when `repository` is a number that is not a positive integer.
126
+ * @param options The request budget, the folders skipped, the folder or the file read and an abort signal.
127
+ * @throws TypeError before any request when `repository` is a number that is not a positive integer, or `options.path`
128
+ * has an empty, `.` or `..` segment or is not text.
110
129
  */
111
130
  export declare function readTree(fetchImpl: typeof fetch, token: string, repository: number | string, commit: string, apiBase?: string, options?: ReadTreeOptions): Promise<TreeBlob[]>;
131
+ /**
132
+ * The path of a folder or a file of a repository a caller names, checked: absent and `''` name the whole repository
133
+ * and answer `''`. A path with an empty, `.` or `..` segment (a leading or a trailing slash among them), and a value
134
+ * that is not text, throw a `TypeError` that quotes none of it.
135
+ */
136
+ export declare function pathOf(path: unknown): string;
137
+ /** The blobs at `path` or under it: a folder's files, or the one file it names; every blob for `''`. */
138
+ export declare function withinPath<T extends TreeBlob>(blobs: readonly T[], path: string): T[];
112
139
  /**
113
140
  * The filter that keeps a tree's documentation: the extensions kept, and with `includeCode` the code extensions beside
114
141
  * them; nothing under a skipped folder, nothing past the size cap, at most `maxFiles`, in path order. With code asked
@@ -140,6 +167,12 @@ export interface PlanTreeOptions extends TreeFilter {
140
167
  maxCodeBytes?: number;
141
168
  /** The extensions, with their dot, of the files skipped as images ({@link IMAGE_EXTENSIONS} when absent). */
142
169
  imageExtensions?: readonly string[];
170
+ /**
171
+ * A folder of the tree, or a file, by its path with no leading or trailing slash: only the files at it or under it
172
+ * are planned, and `maxFiles` counts them alone, as a listing keeps them under the same `path`. The whole tree when
173
+ * absent or `''`; a path with an empty, `.` or `..` segment, or one that is not text, is a `TypeError`.
174
+ */
175
+ path?: string;
143
176
  }
144
177
  /**
145
178
  * `pathFilter`'s sibling: every file of a tree, in path order, with its outcome under the same filter, so a caller can
@@ -149,11 +182,12 @@ export interface PlanTreeOptions extends TreeFilter {
149
182
  * (`count`, the documentation keeping its places first and the code taking the room left, as in `pathFilter`). A file
150
183
  * whose extension the filter's `extensions` names is documentation, an image's included; while code is asked for, one
151
184
  * of a code extension keeps `maxCodeBytes` as its bound, as a code file a tool wrote is left out whatever `extensions`
152
- * names. Each answer is a new object holding the file's `path`, `sha` and `size` and its `outcome`.
185
+ * names. Each answer is a new object holding the file's `path`, `sha` and `size` and its `outcome`. With a `path`, only
186
+ * the files of that folder, or the one file it names, are planned, and counted alone.
153
187
  *
154
188
  * @param blobs The files of a tree, as `readTree` answers them.
155
- * @param options The filter, the code bound and the image extensions.
156
- * @throws TypeError when `maxCodeBytes` is not a non-negative integer.
189
+ * @param options The filter, the code bound, the image extensions and the folder.
190
+ * @throws TypeError when `maxCodeBytes` is not a non-negative integer, or `path` is not a path.
157
191
  */
158
192
  export declare function planTree(blobs: readonly TreeBlob[], options?: PlanTreeOptions): PlannedBlob[];
159
193
  //# sourceMappingURL=tree.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/documents/tree.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../../src/documents/tree.ts"],"names":[],"mappings":"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"}
@@ -1,10 +1,11 @@
1
1
  /**
2
2
  * @fileoverview A repository's tree at a commit, read within a request budget, and the filter that keeps its
3
3
  * documentation. GitHub cuts a recursive tree past 100,000 entries or 7 MB and marks it `truncated`; such a tree is
4
- * read again one subtree at a time, and a level GitHub cuts short even when asked for alone is refused whole.
4
+ * read again one subtree at a time, a folder's files by the folders on its path alone, and a level GitHub cuts short
5
+ * even when asked for alone is refused whole.
5
6
  * @module agentos-ext-github/documents/tree
6
7
  */
7
- import { arrayOf, GITHUB_API_BASE, githubFetch, objectOf, repositoryPath, stringIn } from '../app/http.js';
8
+ import { arrayOf, GITHUB_API_BASE, githubFetch, GitHubNoAnswer, objectOf, repositoryPath, stringIn } from '../app/http.js';
8
9
  /** The documentation kept by default: Markdown, text, reStructuredText, HTML, PDF and Word files. */
9
10
  export const DOCUMENT_EXTENSIONS = ['.md', '.markdown', '.txt', '.rst', '.html', '.htm', '.pdf', '.docx'];
10
11
  /** The folders skipped by default: dependencies, build output and vendored code. */
@@ -89,12 +90,22 @@ function inSkippedFolder(path, skip) {
89
90
  return path.split('/').slice(0, -1).some((folder) => skip.has(folder));
90
91
  }
91
92
  /**
92
- * Every file of a repository's tree at a commit (symbolic links aside). The tree is asked for recursively; when GitHub
93
- * answers it truncated, its top level is read and each subtree is asked for the same way, so only the parts too large
94
- * for one answer cost a request per folder. Each request counts against `maxRequests`, and the read throws
95
- * {@link TreeTooLarge} (`budget`) rather than make one more. A level GitHub answers truncated without recursion as well
96
- * throws {@link TreeTooLarge} (`truncated`) at that answer, before any folder under it is asked for: the tree answer's
97
- * `truncated` field can be set on any answer, and a part of the tree would leave out files that then read as removed.
93
+ * Every file of a repository's tree at a commit (symbolic links aside), or of the folder or the file `options.path`
94
+ * names. The tree is asked for recursively; when GitHub answers it truncated, its top level is read and each subtree is
95
+ * asked for the same way, so only the parts too large for one answer cost a request per folder. Each request counts
96
+ * against `maxRequests`, and the read throws {@link TreeTooLarge} (`budget`) rather than make one more. A level GitHub
97
+ * answers truncated without recursion as well throws {@link TreeTooLarge} (`truncated`) at that answer, before any
98
+ * folder under it is asked for: the tree answer's `truncated` field can be set on any answer, and a part of the tree
99
+ * would leave out files that then read as removed.
100
+ *
101
+ * With a `path`, the files at it or under it are answered. A truncated tree is then read by the folders on the path
102
+ * alone, each asked for without recursion, down to the folder the path names, which is read as above, or to the file:
103
+ * a small folder of a large repository costs the path's depth and its own subtree, never a request for a folder beside
104
+ * it. A level that does not name the path's next folder or file answers no file, unless GitHub cut that level short,
105
+ * which throws {@link TreeTooLarge} (`truncated`), since the name may stand past the cut; a level cut short that names
106
+ * it is read on, since the folder's own subtree is whole. A path through a skipped folder (one of its segments before
107
+ * the last, which may name a file) holds no file kept, so it answers no file before any request, whatever the tree; a
108
+ * read whose signal is already aborted throws {@link GitHubNoAnswer} (`cancelled`) there, as a request would.
98
109
  *
99
110
  * Name the repository by its id. A full name reads whatever repository holds that name when the tree is asked for: a
100
111
  * renamed repository's old name can be taken again, and an account's old login claimed by another account, which ends
@@ -106,15 +117,23 @@ function inSkippedFolder(path, skip) {
106
117
  * @param repository The repository's id, read at `/repositories/<id>`, or its full name, `owner/name`.
107
118
  * @param commit The commit whose tree is read.
108
119
  * @param apiBase GitHub's REST API, or a stand-in's address in tests.
109
- * @param options The request budget, the folders skipped and an abort signal.
110
- * @throws TypeError before any request when `repository` is a number that is not a positive integer.
120
+ * @param options The request budget, the folders skipped, the folder or the file read and an abort signal.
121
+ * @throws TypeError before any request when `repository` is a number that is not a positive integer, or `options.path`
122
+ * has an empty, `.` or `..` segment or is not text.
111
123
  */
112
124
  export async function readTree(fetchImpl, token, repository, commit, apiBase = GITHUB_API_BASE, options = {}) {
113
125
  const address = `${apiBase}/${repositoryPath(repository)}`;
126
+ const target = pathOf(options.path);
114
127
  const maxRequests = options.maxRequests ?? DEFAULT_MAX_TREE_REQUESTS;
115
128
  const skip = new Set(options.skipFolders ?? []);
116
129
  const blobs = [];
117
130
  let requests = 0;
131
+ // A path through a skipped folder holds no file kept, so no level, whole or cut short, is asked for.
132
+ if (inSkippedFolder(target, skip)) {
133
+ if (options.signal?.aborted === true)
134
+ throw new GitHubNoAnswer('cancelled');
135
+ return blobs;
136
+ }
118
137
  const read = async (sha, recursive) => {
119
138
  if (requests >= maxRequests)
120
139
  throw new TreeTooLarge(maxRequests);
@@ -149,13 +168,73 @@ export async function readTree(fetchImpl, token, repository, commit, apiBase = G
149
168
  }
150
169
  }
151
170
  };
152
- await walk(commit, '');
171
+ /**
172
+ * The files at `target` or under it: the tree asked for recursively once, and, when GitHub cuts it short, each folder
173
+ * on the path asked for alone down to the folder the path names, which `walk` reads, or to the file.
174
+ */
175
+ const within = async () => {
176
+ const whole = await read(commit, true);
177
+ if (!whole.truncated) {
178
+ const folder = `${target}/`;
179
+ for (const entry of whole.entries)
180
+ if (entry.path === target || entry.path.startsWith(folder))
181
+ keep(entry, entry.path);
182
+ return;
183
+ }
184
+ const names = target.split('/');
185
+ let sha = commit;
186
+ let prefix = '';
187
+ for (const [index, name] of names.entries()) {
188
+ const level = await read(sha, false);
189
+ const entry = level.entries.find((candidate) => candidate.path === name);
190
+ // A level cut short may hold the name past its cut; one read whole holds every name it has.
191
+ if (entry === undefined) {
192
+ if (level.truncated)
193
+ throw new TreeTooLarge(maxRequests, 'truncated');
194
+ return;
195
+ }
196
+ if (entry.type !== 'tree') {
197
+ if (index === names.length - 1)
198
+ keep(entry, `${prefix}${name}`);
199
+ return;
200
+ }
201
+ if (skip.has(name))
202
+ return;
203
+ sha = entry.sha;
204
+ prefix = `${prefix}${name}/`;
205
+ }
206
+ await walk(sha, prefix);
207
+ };
208
+ if (target === '')
209
+ await walk(commit, '');
210
+ else
211
+ await within();
153
212
  return blobs;
154
213
  }
155
214
  /** Blobs in path order. */
156
215
  function byPath(a, b) {
157
216
  return a.path < b.path ? -1 : a.path > b.path ? 1 : 0;
158
217
  }
218
+ /**
219
+ * The path of a folder or a file of a repository a caller names, checked: absent and `''` name the whole repository
220
+ * and answer `''`. A path with an empty, `.` or `..` segment (a leading or a trailing slash among them), and a value
221
+ * that is not text, throw a `TypeError` that quotes none of it.
222
+ */
223
+ export function pathOf(path) {
224
+ if (path === undefined || path === '')
225
+ return '';
226
+ if (typeof path !== 'string' || path.split('/').some((segment) => segment === '' || segment === '.' || segment === '..')) {
227
+ throw new TypeError('a path is text with no empty, . or .. segment');
228
+ }
229
+ return path;
230
+ }
231
+ /** The blobs at `path` or under it: a folder's files, or the one file it names; every blob for `''`. */
232
+ export function withinPath(blobs, path) {
233
+ if (path === '')
234
+ return [...blobs];
235
+ const folder = `${path}/`;
236
+ return blobs.filter((blob) => blob.path === path || blob.path.startsWith(folder));
237
+ }
159
238
  /**
160
239
  * The filter that keeps a tree's documentation: the extensions kept, and with `includeCode` the code extensions beside
161
240
  * them; nothing under a skipped folder, nothing past the size cap, at most `maxFiles`, in path order. With code asked
@@ -187,16 +266,18 @@ export function pathFilter(filter = {}) {
187
266
  * (`count`, the documentation keeping its places first and the code taking the room left, as in `pathFilter`). A file
188
267
  * whose extension the filter's `extensions` names is documentation, an image's included; while code is asked for, one
189
268
  * of a code extension keeps `maxCodeBytes` as its bound, as a code file a tool wrote is left out whatever `extensions`
190
- * names. Each answer is a new object holding the file's `path`, `sha` and `size` and its `outcome`.
269
+ * names. Each answer is a new object holding the file's `path`, `sha` and `size` and its `outcome`. With a `path`, only
270
+ * the files of that folder, or the one file it names, are planned, and counted alone.
191
271
  *
192
272
  * @param blobs The files of a tree, as `readTree` answers them.
193
- * @param options The filter, the code bound and the image extensions.
194
- * @throws TypeError when `maxCodeBytes` is not a non-negative integer.
273
+ * @param options The filter, the code bound, the image extensions and the folder.
274
+ * @throws TypeError when `maxCodeBytes` is not a non-negative integer, or `path` is not a path.
195
275
  */
196
276
  export function planTree(blobs, options = {}) {
197
277
  if (options.maxCodeBytes !== undefined && !(Number.isSafeInteger(options.maxCodeBytes) && options.maxCodeBytes >= 0)) {
198
278
  throw new TypeError('maxCodeBytes is a number of bytes: a non-negative integer');
199
279
  }
280
+ const path = pathOf(options.path);
200
281
  const documents = new Set((options.extensions ?? DOCUMENT_EXTENSIONS).map((extension) => extension.toLowerCase()));
201
282
  const codeAsked = options.includeCode === true;
202
283
  const code = new Set(CODE_EXTENSIONS);
@@ -205,7 +286,9 @@ export function planTree(blobs, options = {}) {
205
286
  const maxFiles = options.maxFiles ?? DEFAULT_MAX_FILES;
206
287
  const maxFileBytes = options.maxFileBytes ?? DEFAULT_MAX_FILE_BYTES;
207
288
  const maxCodeBytes = Math.min(options.maxCodeBytes ?? maxFileBytes, maxFileBytes);
208
- const planned = [...blobs].sort(byPath).map((blob) => ({ path: blob.path, sha: blob.sha, size: blob.size, outcome: 'note' }));
289
+ const planned = withinPath(blobs, path)
290
+ .sort(byPath)
291
+ .map((blob) => ({ path: blob.path, sha: blob.sha, size: blob.size, outcome: 'note' }));
209
292
  const documentation = [];
210
293
  const sources = [];
211
294
  for (const blob of planned) {