@framers/agentos-ext-account-sources 0.0.0-stage → 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.
- package/LICENSE +98 -0
- package/README.md +123 -2
- package/dist/cachePolicy.d.ts +39 -0
- package/dist/cachePolicy.d.ts.map +1 -0
- package/dist/cachePolicy.js +97 -0
- package/dist/cachePolicy.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -0
- package/dist/limiter.d.ts +6 -0
- package/dist/limiter.d.ts.map +1 -0
- package/dist/limiter.js +23 -0
- package/dist/limiter.js.map +1 -0
- package/dist/readCapped.d.ts +9 -0
- package/dist/readCapped.d.ts.map +1 -0
- package/dist/readCapped.js +52 -0
- package/dist/readCapped.js.map +1 -0
- package/dist/sourceRef.d.ts +11 -0
- package/dist/sourceRef.d.ts.map +1 -0
- package/dist/sourceRef.js +40 -0
- package/dist/sourceRef.js.map +1 -0
- package/dist/types.d.ts +74 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/manifest.json +33 -0
- package/package.json +69 -3
package/LICENSE
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
Apache License
|
|
2
|
+
Version 2.0, January 2004
|
|
3
|
+
http://www.apache.org/licenses/
|
|
4
|
+
|
|
5
|
+
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
6
|
+
|
|
7
|
+
1. Definitions.
|
|
8
|
+
|
|
9
|
+
"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
|
|
10
|
+
|
|
11
|
+
"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
|
|
12
|
+
|
|
13
|
+
"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
|
|
14
|
+
|
|
15
|
+
"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
|
|
16
|
+
|
|
17
|
+
"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
|
|
18
|
+
|
|
19
|
+
"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
|
|
20
|
+
|
|
21
|
+
"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
|
|
22
|
+
|
|
23
|
+
"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
|
|
24
|
+
|
|
25
|
+
"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
|
|
26
|
+
|
|
27
|
+
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
|
|
28
|
+
|
|
29
|
+
2. Grant of Copyright License.
|
|
30
|
+
|
|
31
|
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
|
|
32
|
+
|
|
33
|
+
3. Grant of Patent License.
|
|
34
|
+
|
|
35
|
+
Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
|
|
36
|
+
|
|
37
|
+
4. Redistribution.
|
|
38
|
+
|
|
39
|
+
You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
|
|
40
|
+
|
|
41
|
+
(a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
|
|
42
|
+
|
|
43
|
+
(b) You must cause any modified files to carry prominent notices stating that You changed the files; and
|
|
44
|
+
|
|
45
|
+
(c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
|
|
46
|
+
|
|
47
|
+
(d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
|
|
48
|
+
|
|
49
|
+
You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
|
|
50
|
+
|
|
51
|
+
5. Submission of Contributions.
|
|
52
|
+
|
|
53
|
+
Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
|
|
54
|
+
|
|
55
|
+
6. Trademarks.
|
|
56
|
+
|
|
57
|
+
This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
|
|
58
|
+
|
|
59
|
+
7. Disclaimer of Warranty.
|
|
60
|
+
|
|
61
|
+
Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
|
|
62
|
+
|
|
63
|
+
8. Limitation of Liability.
|
|
64
|
+
|
|
65
|
+
In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
|
|
66
|
+
|
|
67
|
+
9. Accepting Warranty or Additional Liability.
|
|
68
|
+
|
|
69
|
+
While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
|
|
70
|
+
|
|
71
|
+
END OF TERMS AND CONDITIONS
|
|
72
|
+
|
|
73
|
+
APPENDIX: How to apply the Apache License to your work.
|
|
74
|
+
|
|
75
|
+
To apply the Apache License to your work, attach the following
|
|
76
|
+
boilerplate notice, with the fields enclosed by brackets "[]"
|
|
77
|
+
replaced with your own identifying information. (Don't include
|
|
78
|
+
the brackets!) The text should be enclosed in the appropriate
|
|
79
|
+
comment syntax for the file format. We also recommend that a
|
|
80
|
+
file or class name and description of purpose be included on the
|
|
81
|
+
same "printed page" as the copyright notice for easier
|
|
82
|
+
identification within third-party archives.
|
|
83
|
+
|
|
84
|
+
Copyright (c) 2025 Framers
|
|
85
|
+
|
|
86
|
+
Licensed under the Apache License, Version 2.0 (the "License");
|
|
87
|
+
you may not use this file except in compliance with the License.
|
|
88
|
+
You may obtain a copy of the License at
|
|
89
|
+
|
|
90
|
+
http://www.apache.org/licenses/LICENSE-2.0
|
|
91
|
+
|
|
92
|
+
Unless required by applicable law or agreed to in writing, software
|
|
93
|
+
distributed under the License is distributed on an "AS IS" BASIS,
|
|
94
|
+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
95
|
+
See the License for the specific language governing permissions and
|
|
96
|
+
limitations under the License.
|
|
97
|
+
|
|
98
|
+
|
package/README.md
CHANGED
|
@@ -1,3 +1,124 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @framers/agentos-ext-account-sources
|
|
2
2
|
|
|
3
|
-
This
|
|
3
|
+
A person's own accounts as sources. This library defines `AccountSourceConnector` and the `SourceRef` every passage carries, with helpers for line ranges, links, bounded body reads, requests under the shared public-sources limiter and the cache lifetime of a read.
|
|
4
|
+
|
|
5
|
+
Install `@framers/agentos-ext-account-sources` with its peer `@framers/agentos` 0.10.40 or later. Node.js 20.19 or later is required. The runtime dependency is `@framers/agentos-ext-public-sources`.
|
|
6
|
+
|
|
7
|
+
## Connector
|
|
8
|
+
|
|
9
|
+
An `AccountSourceConnector` exposes its `kind` and four operations:
|
|
10
|
+
|
|
11
|
+
- `list(selection, signal?)` answers selected `SourceItem`s and `SourceGone` entries.
|
|
12
|
+
- `read(item, signal?)` answers a `SourceRead` or a `SourceGone` entry.
|
|
13
|
+
- `changesSince(cursor, selection, signal?)` answers changed items, gone items and the next cursor. A null cursor starts a listing.
|
|
14
|
+
- `revoke()` ends the access the connector holds where the account supports revocation.
|
|
15
|
+
|
|
16
|
+
A selection holds account item ids. A read carries text or bytes with a media type, the item and its attribution. A gone item names its id and the reason: `removed`, `no_access` or `not_owned`.
|
|
17
|
+
|
|
18
|
+
Connectors obtain their grants through AgentOS's auth module and store them through its sealed token store. This library holds no grants and performs no sealing.
|
|
19
|
+
|
|
20
|
+
## Attribution
|
|
21
|
+
|
|
22
|
+
`SourceRef` carries `kind`, `title`, `url`, `version` and `readAt` (ISO 8601), with optional `path` and `lines`. An absent address or version is null. The kind is open to later connectors. `isSourceRef(value)` checks the field types and that optional lines form an ordered pair of positive integers; it does not parse dates or authorize an address.
|
|
23
|
+
|
|
24
|
+
```ts
|
|
25
|
+
import { lineRange, sourceRefLink, type SourceRef } from '@framers/agentos-ext-account-sources';
|
|
26
|
+
|
|
27
|
+
const text = 'one\ntwo\nthree\nfour';
|
|
28
|
+
const ref: SourceRef = {
|
|
29
|
+
kind: 'github',
|
|
30
|
+
title: 'Guide',
|
|
31
|
+
url: 'https://github.com/example/example/blob/fake-commit/docs/guide.md',
|
|
32
|
+
version: 'fake-commit',
|
|
33
|
+
readAt: '2026-10-08T12:00:00Z',
|
|
34
|
+
path: 'docs/guide.md',
|
|
35
|
+
lines: lineRange(text, 4, 16),
|
|
36
|
+
};
|
|
37
|
+
const link = sourceRefLink(ref); // Ends in #L2-L4.
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
`lineRange(text, start, end)` takes valid UTF-16 offsets with an exclusive end and answers 1-based line numbers. CRLF counts as one break. An empty span belongs to the line at its start. `sourceRefLink` adds a GitHub line anchor, replacing an existing fragment; other addresses are unchanged and an absent address stays null.
|
|
41
|
+
|
|
42
|
+
## Reads and limits
|
|
43
|
+
|
|
44
|
+
`readCapped(response, maxBytes)` returns a `Uint8Array`. It cancels and throws `ReadCapExceeded` when the declared content length exceeds the cap, before reading, or when the streamed bytes pass it. It reads at most the first chunk past the cap. The error carries `maxBytes`; a response without a body answers an empty array. Pass a finite nonnegative byte cap.
|
|
45
|
+
|
|
46
|
+
`readThroughLimiter(limiter, call, signal?)` runs a response-producing call under `SourceLimiter`. A 429 or 503 blocks the limiter using `Retry-After`, cancels the response body and throws `LimiterRefused('blocked')`. Other responses are returned for the caller to inspect and consume. A blocked call is refused before it runs.
|
|
47
|
+
|
|
48
|
+
Share a limiter across callers to the same account source in a process and configure its limits for that source. `SourceLimiter`, `LimiterRefused` and `retryAfterMs` are re-exported unchanged from public-sources. The optional signal cancels admission and waiting; pass it to the fetch inside `call` as well to cancel the request. The limiter holds its slot until `call` and the status check finish; consuming a returned body is the caller's work.
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { readCapped, readThroughLimiter, SourceLimiter } from '@framers/agentos-ext-account-sources';
|
|
52
|
+
|
|
53
|
+
const limiter = new SourceLimiter({ concurrency: 3, spacingMs: 250 });
|
|
54
|
+
|
|
55
|
+
/** Reads a caller-supplied source address under a shared limiter and byte cap. */
|
|
56
|
+
async function readSource(url: string, signal?: AbortSignal): Promise<Uint8Array> {
|
|
57
|
+
/** Fetches with the caller's cancellation signal. */
|
|
58
|
+
const call = (): Promise<Response> => fetch(url, { signal });
|
|
59
|
+
const response = await readThroughLimiter(limiter, call, signal);
|
|
60
|
+
if (!response.ok) {
|
|
61
|
+
await response.body?.cancel();
|
|
62
|
+
throw new Error(`source returned ${response.status}`);
|
|
63
|
+
}
|
|
64
|
+
return readCapped(response, 2_000_000);
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Cache retention
|
|
69
|
+
|
|
70
|
+
```ts
|
|
71
|
+
import { decideSourceCache, type SourceCacheDecision, type SourceCachePermission } from '@framers/agentos-ext-account-sources';
|
|
72
|
+
|
|
73
|
+
/** Decides whether a response whose read began at `readStartedAt` may be stored, and until when. */
|
|
74
|
+
function cacheDecision(
|
|
75
|
+
response: Response,
|
|
76
|
+
permission: SourceCachePermission | null,
|
|
77
|
+
readStartedAt: number,
|
|
78
|
+
windowExpiresAt: number,
|
|
79
|
+
): SourceCacheDecision {
|
|
80
|
+
return decideSourceCache({
|
|
81
|
+
permission,
|
|
82
|
+
maximumCacheMs: 86_400_000,
|
|
83
|
+
readStartedAt,
|
|
84
|
+
receivedAt: Date.now(),
|
|
85
|
+
windowExpiresAt,
|
|
86
|
+
headers: {
|
|
87
|
+
cacheControl: response.headers.get('cache-control'),
|
|
88
|
+
date: response.headers.get('date'),
|
|
89
|
+
age: response.headers.get('age'),
|
|
90
|
+
expires: response.headers.get('expires'),
|
|
91
|
+
},
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
`decideSourceCache(input)` answers `{ kind: 'cache', expiresAt, evidenceId }` or `{ kind: 'skip', reason }`. Its input holds the permission record, the host's maximum lifetime, three times in epoch milliseconds and four response headers; it takes no response body, URL or token.
|
|
97
|
+
|
|
98
|
+
`permission` is the host's record of an approved retention policy: an opaque `evidenceId` and a `retentionMs`. The library applies the record; it does not establish that a provider allows caching. A missing record, a blank `evidenceId` or a `retentionMs` that is not a positive safe integer answers `not_permitted`, whatever the headers allow.
|
|
99
|
+
|
|
100
|
+
`expiresAt` is the earliest of:
|
|
101
|
+
|
|
102
|
+
- `readStartedAt` plus the smaller of `retentionMs` and `maximumCacheMs`, less the response's `Age`;
|
|
103
|
+
- `windowExpiresAt`, the end of the retained material's window (the earliest end when a read holds several items);
|
|
104
|
+
- the `max-age` and `s-maxage` lifetimes, counted from `receivedAt` and reduced by the corrected age of [RFC 9111, section 4.2.3](https://www.rfc-editor.org/rfc/rfc9111#section-4.2.3): the larger of the age the `Date` header implies and `Age` plus the time the read took;
|
|
105
|
+
- the `Expires` lifetime (its distance from `Date`, or from `readStartedAt` when `Date` is absent), counted and reduced the same way, and the `Expires` time itself.
|
|
106
|
+
|
|
107
|
+
A skip carries one of these reasons:
|
|
108
|
+
|
|
109
|
+
| Reason | When |
|
|
110
|
+
|---|---|
|
|
111
|
+
| `not_permitted` | No permission record, a blank `evidenceId`, or a `retentionMs` that is not a positive safe integer |
|
|
112
|
+
| `no_store` | `Cache-Control` holds `no-store` |
|
|
113
|
+
| `revalidation_required` | `Cache-Control` holds `no-cache`, with or without field names |
|
|
114
|
+
| `invalid_cache_header` | A malformed or repeated `Cache-Control` directive; a `max-age` or `s-maxage` without a whole number of seconds or past the safe-integer range; an `Age` that is not a whole number of seconds or is past the safe-integer range; a `Date` or `Expires` before 1970 or outside the IMF-fixdate form of [RFC 9110, section 5.6.7](https://www.rfc-editor.org/rfc/rfc9110#section-5.6.7), exactly as `Date.prototype.toUTCString()` writes it (`Tue, 14 Nov 2023 22:13:20 GMT`) |
|
|
115
|
+
| `invalid_bounds` | A clock value that is not a nonnegative safe integer, a `receivedAt` before `readStartedAt`, a `maximumCacheMs` that is not a positive safe integer, or a lifetime past the safe-integer range |
|
|
116
|
+
| `expired` | The lifetime ends at or before `receivedAt` |
|
|
117
|
+
|
|
118
|
+
Directive names match in any case and values may be quoted. Other directives, such as `private` and `immutable`, neither grant nor extend a lifetime. The obsolete HTTP date forms are refused rather than parsed.
|
|
119
|
+
|
|
120
|
+
A skip stores nothing: record its reason and keep no content. Store `expiresAt` with the content and check it on every read. Neither a later sync checkpoint nor a second call with the old response extends it; a new read takes a new decision.
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
Apache-2.0. This pack carries a copy of the repository's license.
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/** Host-verified permission; this module does not establish provider authorization. */
|
|
2
|
+
export interface SourceCachePermission {
|
|
3
|
+
readonly evidenceId: string;
|
|
4
|
+
readonly retentionMs: number;
|
|
5
|
+
}
|
|
6
|
+
/** Cache metadata only; no request URL, token or response content enters the policy. */
|
|
7
|
+
export interface SourceCacheHeaders {
|
|
8
|
+
readonly cacheControl: string | null;
|
|
9
|
+
readonly date: string | null;
|
|
10
|
+
readonly age: string | null;
|
|
11
|
+
readonly expires: string | null;
|
|
12
|
+
}
|
|
13
|
+
/** Clock and retention bounds for one obtained source response. */
|
|
14
|
+
export interface SourceCacheInput {
|
|
15
|
+
readonly permission: SourceCachePermission | null;
|
|
16
|
+
readonly maximumCacheMs: number;
|
|
17
|
+
readonly readStartedAt: number;
|
|
18
|
+
readonly receivedAt: number;
|
|
19
|
+
readonly windowExpiresAt: number;
|
|
20
|
+
readonly headers: SourceCacheHeaders;
|
|
21
|
+
}
|
|
22
|
+
/** Fixed reasons safe to aggregate without content-bearing provider messages. */
|
|
23
|
+
export type SourceCacheSkipReason = 'not_permitted' | 'no_store' | 'revalidation_required' | 'invalid_cache_header' | 'invalid_bounds' | 'expired';
|
|
24
|
+
/** A finite allowed lifetime, or an explicit refusal to persist any source content. */
|
|
25
|
+
export type SourceCacheDecision = {
|
|
26
|
+
readonly kind: 'cache';
|
|
27
|
+
readonly expiresAt: number;
|
|
28
|
+
readonly evidenceId: string;
|
|
29
|
+
} | {
|
|
30
|
+
readonly kind: 'skip';
|
|
31
|
+
readonly reason: SourceCacheSkipReason;
|
|
32
|
+
};
|
|
33
|
+
/**
|
|
34
|
+
* Applies explicit permission and conservative provider/cache/window limits.
|
|
35
|
+
* Returned expiry is never extended by a history checkpoint or by calling this
|
|
36
|
+
* function again with the old response. A new read needs its own permission check.
|
|
37
|
+
*/
|
|
38
|
+
export declare function decideSourceCache(input: SourceCacheInput): SourceCacheDecision;
|
|
39
|
+
//# sourceMappingURL=cachePolicy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cachePolicy.d.ts","sourceRoot":"","sources":["../src/cachePolicy.ts"],"names":[],"mappings":"AAAA,uFAAuF;AACvF,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;CAC9B;AAED,wFAAwF;AACxF,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAED,mEAAmE;AACnE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,CAAC,UAAU,EAAE,qBAAqB,GAAG,IAAI,CAAC;IAClD,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAC;CACtC;AAED,iFAAiF;AACjF,MAAM,MAAM,qBAAqB,GAC7B,eAAe,GAAG,UAAU,GAAG,uBAAuB,GACtD,sBAAsB,GAAG,gBAAgB,GAAG,SAAS,CAAC;AAE1D,uFAAuF;AACvF,MAAM,MAAM,mBAAmB,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAAE,GACnF;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,CAAC;AAiCtE;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,GAAG,mBAAmB,CAiD9E"}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
const integer = (value) => Number.isSafeInteger(value) && value >= 0;
|
|
2
|
+
const positive = (value) => integer(value) && value > 0;
|
|
3
|
+
const skip = (reason) => ({ kind: 'skip', reason });
|
|
4
|
+
/** Whole seconds written in digits only, as safe-integer milliseconds; anything else is null. */
|
|
5
|
+
function milliseconds(value) {
|
|
6
|
+
if (!/^\d+$/.test(value))
|
|
7
|
+
return null;
|
|
8
|
+
const converted = Number(value) * 1_000;
|
|
9
|
+
return integer(converted) ? converted : null;
|
|
10
|
+
}
|
|
11
|
+
/** An HTTP date accepted only in the exact form `toUTCString` writes, so a loose parse cannot invent a time. */
|
|
12
|
+
function date(value) {
|
|
13
|
+
if (value === null)
|
|
14
|
+
return null;
|
|
15
|
+
const parsed = Date.parse(value);
|
|
16
|
+
return integer(parsed) && new Date(parsed).toUTCString() === value ? parsed : null;
|
|
17
|
+
}
|
|
18
|
+
/** Cache-Control directives by lower-case name; a malformed or repeated directive answers null. */
|
|
19
|
+
function directives(value) {
|
|
20
|
+
const found = new Map();
|
|
21
|
+
if (value === null || value.trim() === '')
|
|
22
|
+
return found;
|
|
23
|
+
for (const part of value.split(',')) {
|
|
24
|
+
const match = /^([a-z][a-z0-9-]*)(?:\s*=\s*(?:"([^"]*)"|([^\s",]+)))?$/i.exec(part.trim());
|
|
25
|
+
const name = match?.[1]?.toLowerCase();
|
|
26
|
+
if (!match || !name || found.has(name))
|
|
27
|
+
return null;
|
|
28
|
+
found.set(name, match[2] ?? match[3] ?? null);
|
|
29
|
+
}
|
|
30
|
+
return found;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Applies explicit permission and conservative provider/cache/window limits.
|
|
34
|
+
* Returned expiry is never extended by a history checkpoint or by calling this
|
|
35
|
+
* function again with the old response. A new read needs its own permission check.
|
|
36
|
+
*/
|
|
37
|
+
export function decideSourceCache(input) {
|
|
38
|
+
const permission = input.permission;
|
|
39
|
+
if (!permission || typeof permission.evidenceId !== 'string'
|
|
40
|
+
|| permission.evidenceId.trim().length === 0 || !positive(permission.retentionMs)) {
|
|
41
|
+
return skip('not_permitted');
|
|
42
|
+
}
|
|
43
|
+
if (!positive(input.maximumCacheMs) || !integer(input.readStartedAt)
|
|
44
|
+
|| !integer(input.receivedAt) || !integer(input.windowExpiresAt)
|
|
45
|
+
|| input.receivedAt < input.readStartedAt)
|
|
46
|
+
return skip('invalid_bounds');
|
|
47
|
+
const policyEnd = input.readStartedAt + Math.min(permission.retentionMs, input.maximumCacheMs);
|
|
48
|
+
if (!integer(policyEnd))
|
|
49
|
+
return skip('invalid_bounds');
|
|
50
|
+
const rules = directives(input.headers.cacheControl);
|
|
51
|
+
if (rules === null)
|
|
52
|
+
return skip('invalid_cache_header');
|
|
53
|
+
if (rules.has('no-store'))
|
|
54
|
+
return skip('no_store');
|
|
55
|
+
if (rules.has('no-cache'))
|
|
56
|
+
return skip('revalidation_required');
|
|
57
|
+
const age = input.headers.age === null ? 0 : milliseconds(input.headers.age.trim());
|
|
58
|
+
const responseDate = date(input.headers.date);
|
|
59
|
+
const responseExpires = date(input.headers.expires);
|
|
60
|
+
if (age === null || (input.headers.date !== null && responseDate === null)
|
|
61
|
+
|| (input.headers.expires !== null && responseExpires === null)) {
|
|
62
|
+
return skip('invalid_cache_header');
|
|
63
|
+
}
|
|
64
|
+
const elapsed = input.receivedAt - input.readStartedAt;
|
|
65
|
+
const apparentAge = responseDate === null ? 0 : Math.max(0, input.receivedAt - responseDate);
|
|
66
|
+
const correctedAge = Math.max(apparentAge, age + elapsed);
|
|
67
|
+
if (!integer(correctedAge))
|
|
68
|
+
return skip('invalid_cache_header');
|
|
69
|
+
let expiresAt = Math.min(policyEnd - age, input.windowExpiresAt);
|
|
70
|
+
for (const name of ['max-age', 's-maxage']) {
|
|
71
|
+
if (!rules.has(name))
|
|
72
|
+
continue;
|
|
73
|
+
const value = rules.get(name);
|
|
74
|
+
if (value === null || value === undefined)
|
|
75
|
+
return skip('invalid_cache_header');
|
|
76
|
+
const freshFor = milliseconds(value);
|
|
77
|
+
if (freshFor === null)
|
|
78
|
+
return skip('invalid_cache_header');
|
|
79
|
+
const freshUntil = input.receivedAt + freshFor - correctedAge;
|
|
80
|
+
if (!Number.isSafeInteger(freshUntil))
|
|
81
|
+
return skip('invalid_cache_header');
|
|
82
|
+
expiresAt = Math.min(expiresAt, freshUntil);
|
|
83
|
+
}
|
|
84
|
+
if (responseExpires !== null) {
|
|
85
|
+
const freshFor = responseExpires - (responseDate ?? input.readStartedAt);
|
|
86
|
+
const freshUntil = input.receivedAt + freshFor - correctedAge;
|
|
87
|
+
if (!Number.isSafeInteger(freshUntil))
|
|
88
|
+
return skip('invalid_cache_header');
|
|
89
|
+
expiresAt = Math.min(expiresAt, freshUntil, responseExpires);
|
|
90
|
+
}
|
|
91
|
+
if (!Number.isSafeInteger(expiresAt))
|
|
92
|
+
return skip('invalid_bounds');
|
|
93
|
+
if (expiresAt <= input.receivedAt)
|
|
94
|
+
return skip('expired');
|
|
95
|
+
return { kind: 'cache', expiresAt, evidenceId: permission.evidenceId };
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=cachePolicy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cachePolicy.js","sourceRoot":"","sources":["../src/cachePolicy.ts"],"names":[],"mappings":"AAkCA,MAAM,OAAO,GAAG,CAAC,KAAa,EAAW,EAAE,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACtF,MAAM,QAAQ,GAAG,CAAC,KAAa,EAAW,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC,CAAC;AACzE,MAAM,IAAI,GAAG,CAAC,MAA6B,EAAuB,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;AAEhG,iGAAiG;AACjG,SAAS,YAAY,CAAC,KAAa;IACjC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACtC,MAAM,SAAS,GAAG,MAAM,CAAC,KAAK,CAAC,GAAG,KAAK,CAAC;IACxC,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC;AAED,gHAAgH;AAChH,SAAS,IAAI,CAAC,KAAoB;IAChC,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,OAAO,OAAO,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;AACrF,CAAC;AAED,mGAAmG;AACnG,SAAS,UAAU,CAAC,KAAoB;IACtC,MAAM,KAAK,GAAG,IAAI,GAAG,EAAyB,CAAC;IAC/C,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,KAAK,CAAC;IACxD,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC;QACpC,MAAM,KAAK,GAAG,0DAA0D,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;QAC3F,MAAM,IAAI,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,CAAC;QACvC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;QACpD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC;IAChD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAuB;IACvD,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,CAAC;IACpC,IAAI,CAAC,UAAU,IAAI,OAAO,UAAU,CAAC,UAAU,KAAK,QAAQ;WACvD,UAAU,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;QACpF,OAAO,IAAI,CAAC,eAAe,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,aAAa,CAAC;WAC/D,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC;WAC7D,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa;QAAE,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAE3E,MAAM,SAAS,GAAG,KAAK,CAAC,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,WAAW,EAAE,KAAK,CAAC,cAAc,CAAC,CAAC;IAC/F,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACvD,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC;IACrD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACxD,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC,UAAU,CAAC,CAAC;IACnD,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC;QAAE,OAAO,IAAI,CAAC,uBAAuB,CAAC,CAAC;IAEhE,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;IACpF,MAAM,YAAY,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,MAAM,eAAe,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACpD,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,KAAK,IAAI,IAAI,YAAY,KAAK,IAAI,CAAC;WACrE,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,KAAK,IAAI,IAAI,eAAe,KAAK,IAAI,CAAC,EAAE,CAAC;QAClE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,GAAG,KAAK,CAAC,aAAa,CAAC;IACvD,MAAM,WAAW,GAAG,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,UAAU,GAAG,YAAY,CAAC,CAAC;IAC7F,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,EAAE,GAAG,GAAG,OAAO,CAAC,CAAC;IAC1D,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;IAChE,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,GAAG,GAAG,EAAE,KAAK,CAAC,eAAe,CAAC,CAAC;IAEjE,KAAK,MAAM,IAAI,IAAI,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC9B,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC/E,MAAM,QAAQ,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;QACrC,IAAI,QAAQ,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3D,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3E,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,CAAC,CAAC;IAC9C,CAAC;IACD,IAAI,eAAe,KAAK,IAAI,EAAE,CAAC;QAC7B,MAAM,QAAQ,GAAG,eAAe,GAAG,CAAC,YAAY,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;QACzE,MAAM,UAAU,GAAG,KAAK,CAAC,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;QAC9D,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,UAAU,CAAC;YAAE,OAAO,IAAI,CAAC,sBAAsB,CAAC,CAAC;QAC3E,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,SAAS,EAAE,UAAU,EAAE,eAAe,CAAC,CAAC;IAC/D,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC,gBAAgB,CAAC,CAAC;IACpE,IAAI,SAAS,IAAI,KAAK,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC;IAC1D,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,CAAC,UAAU,EAAE,CAAC;AACzE,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The account connector and the attribution and item shapes it carries. */
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
/** Attribution guards, line ranges, and source links. */
|
|
4
|
+
export * from './sourceRef.js';
|
|
5
|
+
/** Response body reads under a byte cap and their refusal. */
|
|
6
|
+
export * from './readCapped.js';
|
|
7
|
+
/** The shared limiter and response-producing calls run under it. */
|
|
8
|
+
export * from './limiter.js';
|
|
9
|
+
/** Explicit retention permission and conservative source-cache expiry. */
|
|
10
|
+
export * from './cachePolicy.js';
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,cAAc,YAAY,CAAC;AAC3B,yDAAyD;AACzD,cAAc,gBAAgB,CAAC;AAC/B,8DAA8D;AAC9D,cAAc,iBAAiB,CAAC;AAChC,oEAAoE;AACpE,cAAc,cAAc,CAAC;AAC7B,0EAA0E;AAC1E,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** The account connector and the attribution and item shapes it carries. */
|
|
2
|
+
export * from './types.js';
|
|
3
|
+
/** Attribution guards, line ranges, and source links. */
|
|
4
|
+
export * from './sourceRef.js';
|
|
5
|
+
/** Response body reads under a byte cap and their refusal. */
|
|
6
|
+
export * from './readCapped.js';
|
|
7
|
+
/** The shared limiter and response-producing calls run under it. */
|
|
8
|
+
export * from './limiter.js';
|
|
9
|
+
/** Explicit retention permission and conservative source-cache expiry. */
|
|
10
|
+
export * from './cachePolicy.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,4EAA4E;AAC5E,cAAc,YAAY,CAAC;AAC3B,yDAAyD;AACzD,cAAc,gBAAgB,CAAC;AAC/B,8DAA8D;AAC9D,cAAc,iBAAiB,CAAC;AAChC,oEAAoE;AACpE,cAAc,cAAc,CAAC;AAC7B,0EAA0E;AAC1E,cAAc,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { SourceLimiter } from '@framers/agentos-ext-public-sources';
|
|
2
|
+
/** The shared per-process limiter, its refusal, and its Retry-After parser. */
|
|
3
|
+
export { SourceLimiter, LimiterRefused, retryAfterMs } from '@framers/agentos-ext-public-sources';
|
|
4
|
+
/** Runs a response-producing call under the limiter and blocks it on a 429 or 503 before throwing. */
|
|
5
|
+
export declare function readThroughLimiter(limiter: SourceLimiter, call: () => Promise<Response>, signal?: AbortSignal): Promise<Response>;
|
|
6
|
+
//# sourceMappingURL=limiter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.d.ts","sourceRoot":"","sources":["../src/limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,aAAa,EAAE,MAAM,qCAAqC,CAAC;AAEpF,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAElG,sGAAsG;AACtG,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,QAAQ,CAAC,CAgBvI"}
|
package/dist/limiter.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { LimiterRefused } from '@framers/agentos-ext-public-sources';
|
|
2
|
+
/** The shared per-process limiter, its refusal, and its Retry-After parser. */
|
|
3
|
+
export { SourceLimiter, LimiterRefused, retryAfterMs } from '@framers/agentos-ext-public-sources';
|
|
4
|
+
/** Runs a response-producing call under the limiter and blocks it on a 429 or 503 before throwing. */
|
|
5
|
+
export async function readThroughLimiter(limiter, call, signal) {
|
|
6
|
+
/** Checks the response while the call still holds the limiter's slot. */
|
|
7
|
+
const read = async () => {
|
|
8
|
+
const response = await call();
|
|
9
|
+
if (response.status === 429 || response.status === 503) {
|
|
10
|
+
limiter.block(response.headers.get('retry-after'));
|
|
11
|
+
try {
|
|
12
|
+
await response.body?.cancel();
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
// Cleanup failure must not replace the limiter refusal.
|
|
16
|
+
}
|
|
17
|
+
throw new LimiterRefused('blocked');
|
|
18
|
+
}
|
|
19
|
+
return response;
|
|
20
|
+
};
|
|
21
|
+
return limiter.run(read, signal);
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=limiter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limiter.js","sourceRoot":"","sources":["../src/limiter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAiB,MAAM,qCAAqC,CAAC;AAEpF,+EAA+E;AAC/E,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAC;AAElG,sGAAsG;AACtG,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,OAAsB,EAAE,IAA6B,EAAE,MAAoB;IAClH,yEAAyE;IACzE,MAAM,IAAI,GAAG,KAAK,IAAuB,EAAE;QACzC,MAAM,QAAQ,GAAG,MAAM,IAAI,EAAE,CAAC;QAC9B,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE,CAAC;YACvD,OAAO,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC;YACnD,IAAI,CAAC;gBACH,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,CAAC;YAChC,CAAC;YAAC,MAAM,CAAC;gBACP,wDAAwD;YAC1D,CAAC;YACD,MAAM,IAAI,cAAc,CAAC,SAAS,CAAC,CAAC;QACtC,CAAC;QACD,OAAO,QAAQ,CAAC;IAClB,CAAC,CAAC;IACF,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;AACnC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/** A body past its cap. */
|
|
2
|
+
export declare class ReadCapExceeded extends Error {
|
|
3
|
+
readonly maxBytes: number;
|
|
4
|
+
/** Records the byte cap the response exceeded. */
|
|
5
|
+
constructor(maxBytes: number);
|
|
6
|
+
}
|
|
7
|
+
/** A response's body read under a cap, refused at the header when it states more. */
|
|
8
|
+
export declare function readCapped(response: Response, maxBytes: number): Promise<Uint8Array>;
|
|
9
|
+
//# sourceMappingURL=readCapped.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readCapped.d.ts","sourceRoot":"","sources":["../src/readCapped.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,qBAAa,eAAgB,SAAQ,KAAK;IAE5B,QAAQ,CAAC,QAAQ,EAAE,MAAM;IADrC,kDAAkD;gBAC7B,QAAQ,EAAE,MAAM;CAItC;AAED,qFAAqF;AACrF,wBAAsB,UAAU,CAAC,QAAQ,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAmC1F"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/** A body past its cap. */
|
|
2
|
+
export class ReadCapExceeded extends Error {
|
|
3
|
+
maxBytes;
|
|
4
|
+
/** Records the byte cap the response exceeded. */
|
|
5
|
+
constructor(maxBytes) {
|
|
6
|
+
super(`the body passes ${maxBytes} bytes`);
|
|
7
|
+
this.maxBytes = maxBytes;
|
|
8
|
+
this.name = 'ReadCapExceeded';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
/** A response's body read under a cap, refused at the header when it states more. */
|
|
12
|
+
export async function readCapped(response, maxBytes) {
|
|
13
|
+
if (response.body === null)
|
|
14
|
+
return new Uint8Array(0);
|
|
15
|
+
const declared = Number(response.headers.get('content-length') ?? '0');
|
|
16
|
+
if (declared > maxBytes) {
|
|
17
|
+
try {
|
|
18
|
+
await response.body.cancel();
|
|
19
|
+
}
|
|
20
|
+
catch {
|
|
21
|
+
// Cleanup failure must not replace the cap error.
|
|
22
|
+
}
|
|
23
|
+
throw new ReadCapExceeded(maxBytes);
|
|
24
|
+
}
|
|
25
|
+
const reader = response.body.getReader();
|
|
26
|
+
const chunks = [];
|
|
27
|
+
let total = 0;
|
|
28
|
+
for (;;) {
|
|
29
|
+
const { done, value } = await reader.read();
|
|
30
|
+
if (done)
|
|
31
|
+
break;
|
|
32
|
+
total += value.byteLength;
|
|
33
|
+
if (total > maxBytes) {
|
|
34
|
+
try {
|
|
35
|
+
await reader.cancel();
|
|
36
|
+
}
|
|
37
|
+
catch {
|
|
38
|
+
// Cleanup failure must not replace the cap error.
|
|
39
|
+
}
|
|
40
|
+
throw new ReadCapExceeded(maxBytes);
|
|
41
|
+
}
|
|
42
|
+
chunks.push(value);
|
|
43
|
+
}
|
|
44
|
+
const out = new Uint8Array(total);
|
|
45
|
+
let at = 0;
|
|
46
|
+
for (const chunk of chunks) {
|
|
47
|
+
out.set(chunk, at);
|
|
48
|
+
at += chunk.byteLength;
|
|
49
|
+
}
|
|
50
|
+
return out;
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=readCapped.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"readCapped.js","sourceRoot":"","sources":["../src/readCapped.ts"],"names":[],"mappings":"AAAA,2BAA2B;AAC3B,MAAM,OAAO,eAAgB,SAAQ,KAAK;IAEnB;IADrB,kDAAkD;IAClD,YAAqB,QAAgB;QACnC,KAAK,CAAC,mBAAmB,QAAQ,QAAQ,CAAC,CAAC;QADxB,aAAQ,GAAR,QAAQ,CAAQ;QAEnC,IAAI,CAAC,IAAI,GAAG,iBAAiB,CAAC;IAChC,CAAC;CACF;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,QAAkB,EAAE,QAAgB;IACnE,IAAI,QAAQ,CAAC,IAAI,KAAK,IAAI;QAAE,OAAO,IAAI,UAAU,CAAC,CAAC,CAAC,CAAC;IACrD,MAAM,QAAQ,GAAG,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,IAAI,GAAG,CAAC,CAAC;IACvE,IAAI,QAAQ,GAAG,QAAQ,EAAE,CAAC;QACxB,IAAI,CAAC;YACH,MAAM,QAAQ,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;QAC/B,CAAC;QAAC,MAAM,CAAC;YACP,kDAAkD;QACpD,CAAC;QACD,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC;IACtC,CAAC;IACD,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;IACzC,MAAM,MAAM,GAAiB,EAAE,CAAC;IAChC,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,SAAS,CAAC;QACR,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QAC5C,IAAI,IAAI;YAAE,MAAM;QAChB,KAAK,IAAI,KAAK,CAAC,UAAU,CAAC;QAC1B,IAAI,KAAK,GAAG,QAAQ,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,MAAM,EAAE,CAAC;YACxB,CAAC;YAAC,MAAM,CAAC;gBACP,kDAAkD;YACpD,CAAC;YACD,MAAM,IAAI,eAAe,CAAC,QAAQ,CAAC,CAAC;QACtC,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACrB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAI,EAAE,GAAG,CAAC,CAAC;IACX,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,GAAG,CAAC,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACnB,EAAE,IAAI,KAAK,CAAC,UAAU,CAAC;IACzB,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { SourceRef } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* The 1-based first and last lines of a span at valid UTF-16 offsets, with an exclusive end.
|
|
4
|
+
* CRLF counts as one break; an empty span belongs to the line at its start.
|
|
5
|
+
*/
|
|
6
|
+
export declare function lineRange(text: string, start: number, end: number): [number, number];
|
|
7
|
+
/** A source's address, with a GitHub file's line anchor when it carries lines. */
|
|
8
|
+
export declare function sourceRefLink(ref: SourceRef): string | null;
|
|
9
|
+
/** Whether an unknown value carries a source's required fields and optional path and line range. */
|
|
10
|
+
export declare function isSourceRef(value: unknown): value is SourceRef;
|
|
11
|
+
//# sourceMappingURL=sourceRef.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sourceRef.d.ts","sourceRoot":"","sources":["../src/sourceRef.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C;;;GAGG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAIpF;AAED,kFAAkF;AAClF,wBAAgB,aAAa,CAAC,GAAG,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAK3D;AAED,oGAAoG;AACpG,wBAAgB,WAAW,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,SAAS,CAa9D"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The 1-based first and last lines of a span at valid UTF-16 offsets, with an exclusive end.
|
|
3
|
+
* CRLF counts as one break; an empty span belongs to the line at its start.
|
|
4
|
+
*/
|
|
5
|
+
export function lineRange(text, start, end) {
|
|
6
|
+
const first = 1 + (text.slice(0, start).match(/\n/gu)?.length ?? 0);
|
|
7
|
+
const last = 1 + (text.slice(0, Math.max(start, end - 1)).match(/\n/gu)?.length ?? 0);
|
|
8
|
+
return [first, last];
|
|
9
|
+
}
|
|
10
|
+
/** A source's address, with a GitHub file's line anchor when it carries lines. */
|
|
11
|
+
export function sourceRefLink(ref) {
|
|
12
|
+
if (ref.url === null || ref.kind !== 'github' || ref.lines === undefined)
|
|
13
|
+
return ref.url;
|
|
14
|
+
const [first, last] = ref.lines;
|
|
15
|
+
const url = ref.url.split('#')[0];
|
|
16
|
+
return `${url}#L${first}${first === last ? '' : `-L${last}`}`;
|
|
17
|
+
}
|
|
18
|
+
/** Whether an unknown value carries a source's required fields and optional path and line range. */
|
|
19
|
+
export function isSourceRef(value) {
|
|
20
|
+
if (value === null || typeof value !== 'object' || Array.isArray(value))
|
|
21
|
+
return false;
|
|
22
|
+
const ref = value;
|
|
23
|
+
if (typeof ref.kind !== 'string' || typeof ref.title !== 'string' || typeof ref.readAt !== 'string')
|
|
24
|
+
return false;
|
|
25
|
+
if (ref.url !== null && typeof ref.url !== 'string')
|
|
26
|
+
return false;
|
|
27
|
+
if (ref.version !== null && typeof ref.version !== 'string')
|
|
28
|
+
return false;
|
|
29
|
+
if (ref.path !== undefined && typeof ref.path !== 'string')
|
|
30
|
+
return false;
|
|
31
|
+
if (ref.lines !== undefined) {
|
|
32
|
+
if (!Array.isArray(ref.lines) || ref.lines.length !== 2)
|
|
33
|
+
return false;
|
|
34
|
+
const [first, last] = ref.lines;
|
|
35
|
+
if (typeof first !== 'number' || typeof last !== 'number' || !Number.isInteger(first) || !Number.isInteger(last) || first < 1 || last < first)
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=sourceRef.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sourceRef.js","sourceRoot":"","sources":["../src/sourceRef.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAa,EAAE,GAAW;IAChE,MAAM,KAAK,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;IACpE,MAAM,IAAI,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC,CAAC,CAAC;IACtF,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;AACvB,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,aAAa,CAAC,GAAc;IAC1C,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC,GAAG,CAAC;IACzF,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;IAChC,MAAM,GAAG,GAAG,GAAG,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAClC,OAAO,GAAG,GAAG,KAAK,KAAK,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,EAAE,CAAC;AAChE,CAAC;AAED,oGAAoG;AACpG,MAAM,UAAU,WAAW,CAAC,KAAc;IACxC,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,KAAK,CAAC;IACtF,MAAM,GAAG,GAAG,KAAgC,CAAC;IAC7C,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,KAAK,KAAK,QAAQ,IAAI,OAAO,GAAG,CAAC,MAAM,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClH,IAAI,GAAG,CAAC,GAAG,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,GAAG,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAClE,IAAI,GAAG,CAAC,OAAO,KAAK,IAAI,IAAI,OAAO,GAAG,CAAC,OAAO,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC1E,IAAI,GAAG,CAAC,IAAI,KAAK,SAAS,IAAI,OAAO,GAAG,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACzE,IAAI,GAAG,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,KAAK,CAAC;QACtE,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,GAAG,CAAC,KAAK,CAAC;QAChC,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,IAAI,IAAI,GAAG,KAAK;YAAE,OAAO,KAAK,CAAC;IAC9J,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview A person's own account as a source: what a connector lists, reads and reports as changed, and the
|
|
3
|
+
* attribution every passage of it carries.
|
|
4
|
+
* @module agentos-ext-account-sources/types
|
|
5
|
+
*/
|
|
6
|
+
/** Where a passage came from, as a page shows and links it. */
|
|
7
|
+
export interface SourceRef {
|
|
8
|
+
/** `upload`, `web`, `dropbox`, `google_drive`, `github`, or a later connector's kind. */
|
|
9
|
+
kind: string;
|
|
10
|
+
title: string;
|
|
11
|
+
/** The address a quote links to: a file at its commit, a Drive file, a web page. */
|
|
12
|
+
url: string | null;
|
|
13
|
+
/** The version read: a commit, a Drive file's version, a page's date. */
|
|
14
|
+
version: string | null;
|
|
15
|
+
/** When it was read, ISO 8601. */
|
|
16
|
+
readAt: string;
|
|
17
|
+
/** For a file in a repository: its path. */
|
|
18
|
+
path?: string;
|
|
19
|
+
/** For a passage: the first and last lines it spans, 1-based. */
|
|
20
|
+
lines?: [number, number];
|
|
21
|
+
}
|
|
22
|
+
/** One readable item of an account. */
|
|
23
|
+
export interface SourceItem {
|
|
24
|
+
/** The account's own id for it (a Drive file id; a repository id and a path). */
|
|
25
|
+
id: string;
|
|
26
|
+
title: string;
|
|
27
|
+
/** What reading it would cost, when known. */
|
|
28
|
+
size: number | null;
|
|
29
|
+
version: string | null;
|
|
30
|
+
}
|
|
31
|
+
/** What a connector is asked to list. */
|
|
32
|
+
export interface SourceSelection {
|
|
33
|
+
/** The account's ids the person chose (picked files, chosen repositories). */
|
|
34
|
+
ids: readonly string[];
|
|
35
|
+
}
|
|
36
|
+
/** One item read: its bytes or text, its type, its attribution. */
|
|
37
|
+
export interface SourceRead {
|
|
38
|
+
item: SourceItem;
|
|
39
|
+
/** Text when the account exported text; bytes for the caller's loaders otherwise. */
|
|
40
|
+
content: {
|
|
41
|
+
text: string;
|
|
42
|
+
} | {
|
|
43
|
+
bytes: Uint8Array;
|
|
44
|
+
mediaType: string;
|
|
45
|
+
};
|
|
46
|
+
ref: SourceRef;
|
|
47
|
+
}
|
|
48
|
+
/** An item that can no longer be read: removed, unshared, out of the grant. */
|
|
49
|
+
export interface SourceGone {
|
|
50
|
+
id: string;
|
|
51
|
+
reason: 'removed' | 'no_access' | 'not_owned';
|
|
52
|
+
}
|
|
53
|
+
/** What changed since a cursor. */
|
|
54
|
+
export interface SourceChanges {
|
|
55
|
+
changed: SourceItem[];
|
|
56
|
+
gone: SourceGone[];
|
|
57
|
+
cursor: string;
|
|
58
|
+
}
|
|
59
|
+
/** A connector to a person's account. */
|
|
60
|
+
export interface AccountSourceConnector {
|
|
61
|
+
readonly kind: string;
|
|
62
|
+
/** Lists the selected items and those that can no longer be read. */
|
|
63
|
+
list(selection: SourceSelection, signal?: AbortSignal): Promise<{
|
|
64
|
+
items: SourceItem[];
|
|
65
|
+
gone: SourceGone[];
|
|
66
|
+
}>;
|
|
67
|
+
/** Reads one item with its attribution or reports why it is gone. */
|
|
68
|
+
read(item: SourceItem, signal?: AbortSignal): Promise<SourceRead | SourceGone>;
|
|
69
|
+
/** Lists changes to the selection since a cursor and answers the next cursor. */
|
|
70
|
+
changesSince(cursor: string | null, selection: SourceSelection, signal?: AbortSignal): Promise<SourceChanges>;
|
|
71
|
+
/** Ends the access the connector holds, where the account has a way to. */
|
|
72
|
+
revoke(): Promise<void>;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,+DAA+D;AAC/D,MAAM,WAAW,SAAS;IACxB,yFAAyF;IACzF,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,oFAAoF;IACpF,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;IACnB,yEAAyE;IACzE,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,kCAAkC;IAClC,MAAM,EAAE,MAAM,CAAC;IACf,4CAA4C;IAC5C,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,KAAK,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1B;AAED,uCAAuC;AACvC,MAAM,WAAW,UAAU;IACzB,iFAAiF;IACjF,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,8CAA8C;IAC9C,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACxB;AAED,yCAAyC;AACzC,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,GAAG,EAAE,SAAS,MAAM,EAAE,CAAC;CACxB;AAED,mEAAmE;AACnE,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,UAAU,CAAC;IACjB,qFAAqF;IACrF,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,GAAG;QAAE,KAAK,EAAE,UAAU,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,GAAG,EAAE,SAAS,CAAC;CAChB;AAED,+EAA+E;AAC/E,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,SAAS,GAAG,WAAW,GAAG,WAAW,CAAC;CAC/C;AAED,mCAAmC;AACnC,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,UAAU,EAAE,CAAC;IACtB,IAAI,EAAE,UAAU,EAAE,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,yCAAyC;AACzC,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,qEAAqE;IACrE,IAAI,CAAC,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,UAAU,EAAE,CAAC;QAAC,IAAI,EAAE,UAAU,EAAE,CAAA;KAAE,CAAC,CAAC;IAC7G,qEAAqE;IACrE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,GAAG,UAAU,CAAC,CAAC;IAC/E,iFAAiF;IACjF,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9G,2EAA2E;IAC3E,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACzB"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG"}
|
package/manifest.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://agentos.sh/schemas/extension-manifest-v1.json",
|
|
3
|
+
"id": "com.framers.research.account-sources",
|
|
4
|
+
"name": "Account Sources",
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"description": "A person's own accounts as sources: connector interfaces, passage attribution, capped reads and a shared limiter",
|
|
7
|
+
"author": {
|
|
8
|
+
"name": "Frame",
|
|
9
|
+
"email": "team@frame.dev",
|
|
10
|
+
"url": "https://frame.dev"
|
|
11
|
+
},
|
|
12
|
+
"license": "Apache-2.0",
|
|
13
|
+
"keywords": [
|
|
14
|
+
"sources",
|
|
15
|
+
"connectors",
|
|
16
|
+
"attribution"
|
|
17
|
+
],
|
|
18
|
+
"agentosVersion": ">=0.10.40",
|
|
19
|
+
"categories": ["research"],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/framerslab/agentos-extensions"
|
|
23
|
+
},
|
|
24
|
+
"extensions": [
|
|
25
|
+
{
|
|
26
|
+
"kind": "library",
|
|
27
|
+
"id": "accountSources",
|
|
28
|
+
"displayName": "Account sources",
|
|
29
|
+
"description": "Connector interfaces and helpers for attributed passages from a person's accounts",
|
|
30
|
+
"entry": "./dist/index.js"
|
|
31
|
+
}
|
|
32
|
+
]
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,72 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@framers/agentos-ext-account-sources",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "A person's own accounts as sources: connector interfaces, passage attribution, capped reads and a shared limiter",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"type": "module",
|
|
8
|
+
"sideEffects": false,
|
|
9
|
+
"exports": {
|
|
10
|
+
".": {
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"types": "./dist/index.d.ts"
|
|
13
|
+
},
|
|
14
|
+
"./manifest.json": "./manifest.json",
|
|
15
|
+
"./package.json": "./package.json"
|
|
16
|
+
},
|
|
17
|
+
"keywords": [
|
|
18
|
+
"agentos",
|
|
19
|
+
"sources",
|
|
20
|
+
"connectors",
|
|
21
|
+
"attribution"
|
|
22
|
+
],
|
|
23
|
+
"author": {
|
|
24
|
+
"name": "Frame",
|
|
25
|
+
"email": "team@frame.dev",
|
|
26
|
+
"url": "https://frame.dev"
|
|
27
|
+
},
|
|
28
|
+
"license": "Apache-2.0",
|
|
29
|
+
"repository": {
|
|
30
|
+
"type": "git",
|
|
31
|
+
"url": "git+https://github.com/framerslab/agentos-extensions.git",
|
|
32
|
+
"directory": "registry/curated/research/account-sources"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"engines": {
|
|
38
|
+
"node": ">=20.19.0"
|
|
39
|
+
},
|
|
40
|
+
"peerDependencies": {
|
|
41
|
+
"@framers/agentos": ">=0.10.40"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"@framers/agentos-ext-public-sources": "^0.1.0"
|
|
45
|
+
},
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^20.12.12",
|
|
48
|
+
"@vitest/coverage-v8": "^3.2.7",
|
|
49
|
+
"rimraf": "^5.0.7",
|
|
50
|
+
"typedoc": "^0.28.20",
|
|
51
|
+
"typescript": "^5.4.5",
|
|
52
|
+
"vitest": "^3.2.7",
|
|
53
|
+
"@framers/agentos": "^0.13.89"
|
|
54
|
+
},
|
|
55
|
+
"homepage": "https://github.com/framerslab/agentos-extensions/tree/master/registry/curated/research/account-sources#readme",
|
|
56
|
+
"bugs": {
|
|
57
|
+
"url": "https://github.com/framerslab/agentos-extensions/issues"
|
|
58
|
+
},
|
|
59
|
+
"files": [
|
|
60
|
+
"dist",
|
|
61
|
+
"manifest.json"
|
|
62
|
+
],
|
|
63
|
+
"scripts": {
|
|
64
|
+
"build": "tsc",
|
|
65
|
+
"test": "vitest run --passWithNoTests",
|
|
66
|
+
"test:watch": "vitest",
|
|
67
|
+
"test:coverage": "vitest run --coverage",
|
|
68
|
+
"typecheck": "tsc --noEmit",
|
|
69
|
+
"docs": "typedoc --out docs src/index.ts",
|
|
70
|
+
"clean": "rimraf dist"
|
|
71
|
+
}
|
|
6
72
|
}
|