gik-service-providers 0.1.0 → 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/README.md +40 -1
- package/dist/github-context-store.d.ts +26 -0
- package/dist/github-context-store.js +647 -0
- package/dist/github-context-store.js.map +1 -0
- package/package.json +23 -6
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ npm install gik-service-providers
|
|
|
7
7
|
```ts
|
|
8
8
|
import { createSchedulerServiceKind } from "gik-service-providers/scheduler";
|
|
9
9
|
import { createGmailServiceKind } from "gik-service-providers/gmail";
|
|
10
|
+
import { createGitHubContextStoreServiceKind } from "gik-service-providers/github-context-store";
|
|
10
11
|
```
|
|
11
12
|
|
|
12
13
|
There is deliberately **no package-root export or index barrel**. Applications
|
|
@@ -126,9 +127,47 @@ HTTP 408/5xx, or an unreadable success response produces
|
|
|
126
127
|
Investigate Sent mail and require fresh host authority before a new attempt;
|
|
127
128
|
Gmail does not provide a general idempotent-send guarantee.
|
|
128
129
|
|
|
130
|
+
## GitHub context store
|
|
131
|
+
|
|
132
|
+
Kind `github-context-store`, version `1`, implements the standard
|
|
133
|
+
`context-store.query/v1` and `context-store.ingest/v1` contracts:
|
|
134
|
+
|
|
135
|
+
```json
|
|
136
|
+
{
|
|
137
|
+
"endpoint": "https://api.github.com",
|
|
138
|
+
"repository": "owner/private-backing-store",
|
|
139
|
+
"ref": "refs/heads/context-v1",
|
|
140
|
+
"prefix": ".gik-state/context/v1",
|
|
141
|
+
"credentialRef": "github/context-store",
|
|
142
|
+
"maxRecordsPerScope": 1000,
|
|
143
|
+
"maxWriteAttempts": 3
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
The configured ref must already exist. The provider never creates repositories,
|
|
148
|
+
refs, credentials or authorization. The host resolves `credentialRef` to a
|
|
149
|
+
`GitHubContextStoreConnection` that adds authentication internally, and must
|
|
150
|
+
authorize every concrete `https://api.github.com` URL before the provider asks
|
|
151
|
+
for that connection. Query-only declarations require GitHub Contents read
|
|
152
|
+
permission; a declaration containing ingest requires Contents write permission.
|
|
153
|
+
|
|
154
|
+
Scopes and record identities are SHA-256 encoded into repository paths.
|
|
155
|
+
Ingestion creates immutable record blobs and a bounded recent-record index in
|
|
156
|
+
one Git commit, then advances the declared ref without force. Reusing an
|
|
157
|
+
identity with different content fails. A non-fast-forward ref race is rebuilt
|
|
158
|
+
from the new head up to `maxWriteAttempts`; exhaustion is explicit. Query reads
|
|
159
|
+
one ref revision and returns at most the requested standard limit. The Git
|
|
160
|
+
revision used or created is returned in `ServiceExecutionResult.detail`, while
|
|
161
|
+
the standard context-store output shape remains unchanged.
|
|
162
|
+
|
|
163
|
+
This provider stores only bounded, non-sensitive context. It is not a token
|
|
164
|
+
vault, GitHub event archive, durable-runtime journal, or substitute for host
|
|
165
|
+
authorization. Actions artifacts and Copilot Memory have different retention
|
|
166
|
+
and consistency semantics and are not silently used as fallbacks.
|
|
167
|
+
|
|
129
168
|
## Distribution and release
|
|
130
169
|
|
|
131
|
-
|
|
170
|
+
All subpaths are independently built and smoke-tested from the actual npm
|
|
132
171
|
tarball in a clean consumer, including TypeScript and the absent root export.
|
|
133
172
|
GitHub Actions performs all installation, build, typecheck and tests for this
|
|
134
173
|
repository. Publishing remains a protected maintainer-approved action; see the
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ServiceKindFactory } from 'gik-controlface/services';
|
|
2
|
+
|
|
3
|
+
interface GitHubContextStoreHttpRequest {
|
|
4
|
+
url: string;
|
|
5
|
+
method: "GET" | "POST" | "PATCH";
|
|
6
|
+
headers: Readonly<Record<string, string>>;
|
|
7
|
+
body?: string;
|
|
8
|
+
signal: AbortSignal;
|
|
9
|
+
}
|
|
10
|
+
/** The host owns authentication and adds it inside this connection. */
|
|
11
|
+
interface GitHubContextStoreConnection {
|
|
12
|
+
request(request: Readonly<GitHubContextStoreHttpRequest>): Promise<Response>;
|
|
13
|
+
}
|
|
14
|
+
declare class GitHubContextRecordConflictError extends Error {
|
|
15
|
+
readonly code = "github-context-record-conflict";
|
|
16
|
+
constructor(recordId: string);
|
|
17
|
+
}
|
|
18
|
+
declare class GitHubContextStoreRevisionConflictError extends Error {
|
|
19
|
+
readonly ref: string;
|
|
20
|
+
readonly attempts: number;
|
|
21
|
+
readonly code = "github-context-store-revision-conflict";
|
|
22
|
+
constructor(ref: string, attempts: number);
|
|
23
|
+
}
|
|
24
|
+
declare function createGitHubContextStoreServiceKind(): ServiceKindFactory;
|
|
25
|
+
|
|
26
|
+
export { GitHubContextRecordConflictError, type GitHubContextStoreConnection, type GitHubContextStoreHttpRequest, GitHubContextStoreRevisionConflictError, createGitHubContextStoreServiceKind };
|
|
@@ -0,0 +1,647 @@
|
|
|
1
|
+
// src/github-context-store.ts
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import { Buffer } from "buffer";
|
|
4
|
+
import {
|
|
5
|
+
CONTEXT_STORE_INGEST_CONTRACT,
|
|
6
|
+
CONTEXT_STORE_MAX_QUERY_LIMIT,
|
|
7
|
+
CONTEXT_STORE_QUERY_CONTRACT,
|
|
8
|
+
contextStoreIngestInputSchema,
|
|
9
|
+
contextStoreIngestOutputSchema,
|
|
10
|
+
contextStoreQueryInputSchema,
|
|
11
|
+
contextStoreQueryOutputSchema,
|
|
12
|
+
requireServiceDependency,
|
|
13
|
+
serviceConfig,
|
|
14
|
+
UnsatisfiedServiceDependencyError
|
|
15
|
+
} from "gik-controlface/services";
|
|
16
|
+
|
|
17
|
+
// src/values.ts
|
|
18
|
+
function object(value, label) {
|
|
19
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) throw new Error(`${label} must be an object`);
|
|
20
|
+
return value;
|
|
21
|
+
}
|
|
22
|
+
function text(value, label) {
|
|
23
|
+
if (typeof value !== "string" || !value.trim()) throw new Error(`${label} must be a nonempty string`);
|
|
24
|
+
return value;
|
|
25
|
+
}
|
|
26
|
+
function integer(value, label, minimum, maximum) {
|
|
27
|
+
if (typeof value !== "number" || !Number.isInteger(value) || value < minimum || value > maximum) {
|
|
28
|
+
throw new Error(`${label} must be an integer between ${minimum} and ${maximum}`);
|
|
29
|
+
}
|
|
30
|
+
return value;
|
|
31
|
+
}
|
|
32
|
+
function keys(value, allowed) {
|
|
33
|
+
const unexpected = Object.keys(value).filter((key) => !allowed.includes(key));
|
|
34
|
+
if (unexpected.length) throw new Error(`Unsupported input fields: ${unexpected.join(", ")}`);
|
|
35
|
+
}
|
|
36
|
+
function isJson(value) {
|
|
37
|
+
return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value) || Array.isArray(value) && value.every(isJson) || !!value && typeof value === "object" && Object.values(value).every(isJson);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// src/github-context-store.ts
|
|
41
|
+
var provider = { id: "github-context-store", version: "1" };
|
|
42
|
+
var recordMode = "100644";
|
|
43
|
+
var recordType = "blob";
|
|
44
|
+
var defaultMaxRecordsPerScope = 1e3;
|
|
45
|
+
var defaultMaxWriteAttempts = 3;
|
|
46
|
+
var GitHubContextRecordConflictError = class extends Error {
|
|
47
|
+
code = "github-context-record-conflict";
|
|
48
|
+
constructor(recordId) {
|
|
49
|
+
super(`GitHub context record '${recordId}' already exists with different content`);
|
|
50
|
+
this.name = "GitHubContextRecordConflictError";
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
var GitHubContextStoreRevisionConflictError = class extends Error {
|
|
54
|
+
constructor(ref, attempts) {
|
|
55
|
+
super(`GitHub context ref '${ref}' changed during ${attempts} write attempts`);
|
|
56
|
+
this.ref = ref;
|
|
57
|
+
this.attempts = attempts;
|
|
58
|
+
this.name = "GitHubContextStoreRevisionConflictError";
|
|
59
|
+
}
|
|
60
|
+
ref;
|
|
61
|
+
attempts;
|
|
62
|
+
code = "github-context-store-revision-conflict";
|
|
63
|
+
};
|
|
64
|
+
function isConnection(value) {
|
|
65
|
+
return !!value && typeof value === "object" && "request" in value && typeof value.request === "function";
|
|
66
|
+
}
|
|
67
|
+
function canonical(value) {
|
|
68
|
+
if (Array.isArray(value)) return value.map(canonical);
|
|
69
|
+
if (value && typeof value === "object") {
|
|
70
|
+
return Object.fromEntries(
|
|
71
|
+
Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => [key, canonical(entry)])
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
return value;
|
|
75
|
+
}
|
|
76
|
+
function serialize(value) {
|
|
77
|
+
if (!isJson(value)) throw new Error("GitHub context value must be JSON data");
|
|
78
|
+
return `${JSON.stringify(canonical(value))}
|
|
79
|
+
`;
|
|
80
|
+
}
|
|
81
|
+
function jsonValue(value, label) {
|
|
82
|
+
if (!isJson(value)) throw new Error(`${label} must be JSON data`);
|
|
83
|
+
return value;
|
|
84
|
+
}
|
|
85
|
+
function digest(value) {
|
|
86
|
+
return createHash("sha256").update(value).digest("hex");
|
|
87
|
+
}
|
|
88
|
+
function repositoryParts(repository) {
|
|
89
|
+
const parts = repository.split("/");
|
|
90
|
+
if (parts.length !== 2 || parts.some((part) => !/^[A-Za-z0-9_.-]+$/.test(part))) {
|
|
91
|
+
throw new Error("GitHub context repository must be an owner/name pair");
|
|
92
|
+
}
|
|
93
|
+
return [parts[0], parts[1]];
|
|
94
|
+
}
|
|
95
|
+
function normalizedRef(value) {
|
|
96
|
+
if (!value.startsWith("refs/heads/")) {
|
|
97
|
+
throw new Error("GitHub context ref must start with 'refs/heads/'");
|
|
98
|
+
}
|
|
99
|
+
const branch = value.slice("refs/heads/".length);
|
|
100
|
+
if (!branch || branch.startsWith("/") || branch.endsWith("/") || branch.includes("//") || branch.split("/").some((part) => !part || part === "." || part === ".." || !/^[A-Za-z0-9._-]+$/.test(part))) {
|
|
101
|
+
throw new Error("GitHub context ref contains an unsafe branch name");
|
|
102
|
+
}
|
|
103
|
+
return `heads/${branch}`;
|
|
104
|
+
}
|
|
105
|
+
function normalizedPrefix(value) {
|
|
106
|
+
if (value.startsWith("/") || value.endsWith("/") || value.includes("\\") || value.split("/").some((part) => !part || part === "." || part === "..")) {
|
|
107
|
+
throw new Error("GitHub context prefix must be a safe repository-relative path");
|
|
108
|
+
}
|
|
109
|
+
return value;
|
|
110
|
+
}
|
|
111
|
+
function config(declaration) {
|
|
112
|
+
const value = serviceConfig(declaration);
|
|
113
|
+
const endpoint2 = text(value.endpoint, "endpoint");
|
|
114
|
+
const ref = text(value.ref, "ref");
|
|
115
|
+
if (endpoint2 !== "https://api.github.com") {
|
|
116
|
+
throw new Error("GitHub context endpoint must be https://api.github.com");
|
|
117
|
+
}
|
|
118
|
+
normalizedRef(ref);
|
|
119
|
+
return {
|
|
120
|
+
endpoint: endpoint2,
|
|
121
|
+
repository: text(value.repository, "repository"),
|
|
122
|
+
ref,
|
|
123
|
+
prefix: normalizedPrefix(text(value.prefix, "prefix")),
|
|
124
|
+
credentialRef: text(value.credentialRef, "credentialRef"),
|
|
125
|
+
maxRecordsPerScope: integer(
|
|
126
|
+
value.maxRecordsPerScope ?? defaultMaxRecordsPerScope,
|
|
127
|
+
"maxRecordsPerScope",
|
|
128
|
+
1,
|
|
129
|
+
5e3
|
|
130
|
+
),
|
|
131
|
+
maxWriteAttempts: integer(
|
|
132
|
+
value.maxWriteAttempts ?? defaultMaxWriteAttempts,
|
|
133
|
+
"maxWriteAttempts",
|
|
134
|
+
1,
|
|
135
|
+
5
|
|
136
|
+
)
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
function credentialRequirement(declaration) {
|
|
140
|
+
const configured = config(declaration);
|
|
141
|
+
const writes = Object.values(declaration.operations).some(({ operation }) => operation === "ingest");
|
|
142
|
+
return {
|
|
143
|
+
id: "github-context-repository",
|
|
144
|
+
kind: "credential",
|
|
145
|
+
title: "GitHub context repository",
|
|
146
|
+
description: "Host-managed GitHub App connection for the declared context repository and ref",
|
|
147
|
+
ref: configured.credentialRef,
|
|
148
|
+
scheme: "github-app",
|
|
149
|
+
permissions: [writes ? "contents:write" : "contents:read"]
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
function validatedRecord(value) {
|
|
153
|
+
if (!isJson(value)) throw new Error("GitHub context record must be JSON data");
|
|
154
|
+
const record = object(value, "GitHub context record");
|
|
155
|
+
const id = text(record.id, "record id");
|
|
156
|
+
const kind = text(record.kind, "record kind");
|
|
157
|
+
const observedAt = text(record.observedAt, "record observedAt");
|
|
158
|
+
if (Number.isNaN(Date.parse(observedAt))) {
|
|
159
|
+
throw new Error("GitHub context record observedAt must be an ISO timestamp");
|
|
160
|
+
}
|
|
161
|
+
if (record.references !== void 0 && !Array.isArray(record.references)) {
|
|
162
|
+
throw new Error("GitHub context record references must be an array");
|
|
163
|
+
}
|
|
164
|
+
const result = { id, kind, observedAt };
|
|
165
|
+
for (const [key, entry] of Object.entries(record)) {
|
|
166
|
+
if (!isJson(entry)) throw new Error(`GitHub context record field '${key}' is not JSON data`);
|
|
167
|
+
result[key] = entry;
|
|
168
|
+
}
|
|
169
|
+
return result;
|
|
170
|
+
}
|
|
171
|
+
function jsonObject(value, label) {
|
|
172
|
+
const source = object(value, label);
|
|
173
|
+
const result = {};
|
|
174
|
+
for (const [key, entry] of Object.entries(source)) {
|
|
175
|
+
if (!isJson(entry)) throw new Error(`${label} field '${key}' is not JSON data`);
|
|
176
|
+
result[key] = entry;
|
|
177
|
+
}
|
|
178
|
+
return result;
|
|
179
|
+
}
|
|
180
|
+
function queryInput(value) {
|
|
181
|
+
const input = object(value, "GitHub context query");
|
|
182
|
+
keys(input, ["scope", "requestKey", "query", "limit"]);
|
|
183
|
+
return {
|
|
184
|
+
scope: text(input.scope, "scope"),
|
|
185
|
+
requestKey: text(input.requestKey, "requestKey"),
|
|
186
|
+
query: jsonObject(input.query, "query"),
|
|
187
|
+
limit: integer(input.limit, "limit", 1, CONTEXT_STORE_MAX_QUERY_LIMIT)
|
|
188
|
+
};
|
|
189
|
+
}
|
|
190
|
+
function ingestInput(value) {
|
|
191
|
+
const input = object(value, "GitHub context ingestion");
|
|
192
|
+
keys(input, ["scope", "records"]);
|
|
193
|
+
if (!Array.isArray(input.records)) throw new Error("GitHub context records must be an array");
|
|
194
|
+
const records = input.records.map(validatedRecord);
|
|
195
|
+
const identities = /* @__PURE__ */ new Map();
|
|
196
|
+
for (const record of records) {
|
|
197
|
+
const encoded = serialize(record);
|
|
198
|
+
const previous = identities.get(record.id);
|
|
199
|
+
if (previous !== void 0 && previous !== encoded) {
|
|
200
|
+
throw new GitHubContextRecordConflictError(record.id);
|
|
201
|
+
}
|
|
202
|
+
identities.set(record.id, encoded);
|
|
203
|
+
}
|
|
204
|
+
return { scope: text(input.scope, "scope"), records };
|
|
205
|
+
}
|
|
206
|
+
function apiPath(parts) {
|
|
207
|
+
return parts.map((part) => encodeURIComponent(part)).join("/");
|
|
208
|
+
}
|
|
209
|
+
function endpoint(configured, suffix) {
|
|
210
|
+
const [owner, repository] = repositoryParts(configured.repository);
|
|
211
|
+
return new URL(`/repos/${apiPath([owner, repository])}/${suffix}`, configured.endpoint);
|
|
212
|
+
}
|
|
213
|
+
function scopePaths(configured, scope) {
|
|
214
|
+
const root = `${configured.prefix}/scopes/${digest(scope)}`;
|
|
215
|
+
return {
|
|
216
|
+
metadata: `${root}/metadata.json`,
|
|
217
|
+
index: `${root}/recent.json`,
|
|
218
|
+
record: (id) => `${root}/records/${digest(id)}.json`
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
function jsonResponse(value, label) {
|
|
222
|
+
if (!isJson(value)) throw new Error(`${label} is not JSON data`);
|
|
223
|
+
return object(value, label);
|
|
224
|
+
}
|
|
225
|
+
function apiObject(value, label) {
|
|
226
|
+
const response = jsonResponse(value, label);
|
|
227
|
+
return { sha: text(response.sha, `${label} SHA`) };
|
|
228
|
+
}
|
|
229
|
+
function refResponse(value) {
|
|
230
|
+
const response = jsonResponse(value, "GitHub ref response");
|
|
231
|
+
const target = object(response.object, "GitHub ref object");
|
|
232
|
+
return { object: { sha: text(target.sha, "GitHub ref object SHA") } };
|
|
233
|
+
}
|
|
234
|
+
function commitResponse(value) {
|
|
235
|
+
const response = jsonResponse(value, "GitHub commit response");
|
|
236
|
+
const tree = object(response.tree, "GitHub commit tree");
|
|
237
|
+
return {
|
|
238
|
+
sha: text(response.sha, "GitHub commit SHA"),
|
|
239
|
+
tree: { sha: text(tree.sha, "GitHub commit tree SHA") }
|
|
240
|
+
};
|
|
241
|
+
}
|
|
242
|
+
function contentResponse(value) {
|
|
243
|
+
const response = jsonResponse(value, "GitHub content response");
|
|
244
|
+
if (response.type !== "file" || response.encoding !== "base64") {
|
|
245
|
+
throw new Error("GitHub content response is not a base64 file");
|
|
246
|
+
}
|
|
247
|
+
return {
|
|
248
|
+
type: "file",
|
|
249
|
+
encoding: "base64",
|
|
250
|
+
content: text(response.content, "GitHub content")
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
function scopeIndex(value, scope) {
|
|
254
|
+
const source = jsonResponse(value, "GitHub context scope index");
|
|
255
|
+
if (source.format !== "gik-github-context-recent/1" || source.scope !== scope || !Array.isArray(source.records)) {
|
|
256
|
+
throw new Error("GitHub context scope index is corrupt or belongs to another scope");
|
|
257
|
+
}
|
|
258
|
+
return {
|
|
259
|
+
format: "gik-github-context-recent/1",
|
|
260
|
+
scope,
|
|
261
|
+
records: source.records.map((entry) => {
|
|
262
|
+
const record = object(entry, "GitHub context scope index record");
|
|
263
|
+
return {
|
|
264
|
+
id: text(record.id, "indexed record id"),
|
|
265
|
+
observedAt: text(record.observedAt, "indexed record observedAt")
|
|
266
|
+
};
|
|
267
|
+
})
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
function createGitHubContextStoreServiceKind() {
|
|
271
|
+
return {
|
|
272
|
+
manifest: {
|
|
273
|
+
id: provider.id,
|
|
274
|
+
version: provider.version,
|
|
275
|
+
title: "GitHub-backed context store",
|
|
276
|
+
description: "Immutable bounded context records stored on a declared private GitHub ref",
|
|
277
|
+
configSchema: {
|
|
278
|
+
type: "object",
|
|
279
|
+
additionalProperties: false,
|
|
280
|
+
required: ["endpoint", "repository", "ref", "prefix", "credentialRef"],
|
|
281
|
+
properties: {
|
|
282
|
+
endpoint: { const: "https://api.github.com" },
|
|
283
|
+
repository: { type: "string", pattern: "^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$" },
|
|
284
|
+
ref: {
|
|
285
|
+
type: "string",
|
|
286
|
+
pattern: "^refs/heads/(?!\\.{1,2}(?:/|$))[A-Za-z0-9._-]+(?:/(?!\\.{1,2}(?:/|$))[A-Za-z0-9._-]+)*$"
|
|
287
|
+
},
|
|
288
|
+
prefix: { type: "string", minLength: 1 },
|
|
289
|
+
credentialRef: { type: "string", minLength: 1 },
|
|
290
|
+
maxRecordsPerScope: { type: "integer", minimum: 1, maximum: 5e3 },
|
|
291
|
+
maxWriteAttempts: { type: "integer", minimum: 1, maximum: 5 }
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
subjects: ["cell", "substrate-agent", "chat", "task"],
|
|
295
|
+
executionModes: ["immediate", "queued"],
|
|
296
|
+
supports: { discover: true, probe: true }
|
|
297
|
+
},
|
|
298
|
+
describeDependencies: (declaration) => [credentialRequirement(declaration)],
|
|
299
|
+
validate(declaration, context) {
|
|
300
|
+
try {
|
|
301
|
+
if (declaration.version !== "1") {
|
|
302
|
+
throw new Error("github-context-store supports version 1 only");
|
|
303
|
+
}
|
|
304
|
+
config(declaration);
|
|
305
|
+
if (!context.resolveCredential || !context.authorizeEndpoint) {
|
|
306
|
+
throw new Error(
|
|
307
|
+
"github-context-store requires host credential resolution and endpoint authorization"
|
|
308
|
+
);
|
|
309
|
+
}
|
|
310
|
+
if (!Object.keys(declaration.operations).length) {
|
|
311
|
+
throw new Error("github-context-store requires a declared operation");
|
|
312
|
+
}
|
|
313
|
+
for (const operation of Object.values(declaration.operations)) {
|
|
314
|
+
const contract = operation.operation === "query" ? CONTEXT_STORE_QUERY_CONTRACT : operation.operation === "ingest" ? CONTEXT_STORE_INGEST_CONTRACT : void 0;
|
|
315
|
+
if (!contract || operation.contract !== contract || operation.sense) {
|
|
316
|
+
throw new Error("Unsupported github-context-store operation or contract");
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return { ok: true };
|
|
320
|
+
} catch (error) {
|
|
321
|
+
return { ok: false, errors: [error instanceof Error ? error.message : String(error)] };
|
|
322
|
+
}
|
|
323
|
+
},
|
|
324
|
+
create(declaration, context) {
|
|
325
|
+
const configured = config(declaration);
|
|
326
|
+
const ref = normalizedRef(configured.ref);
|
|
327
|
+
const requirement = credentialRequirement(declaration);
|
|
328
|
+
const operations = [...new Set(
|
|
329
|
+
Object.values(declaration.operations).map(({ operation }) => operation)
|
|
330
|
+
)];
|
|
331
|
+
async function call(path, method, body, signal, allowedStatuses = []) {
|
|
332
|
+
requireServiceDependency(context, requirement, context.identity?.serviceId ?? provider.id);
|
|
333
|
+
const url = endpoint(configured, path);
|
|
334
|
+
if (!context.authorizeEndpoint || !await context.authorizeEndpoint(provider.id, url)) {
|
|
335
|
+
throw new Error("Host denied the declared GitHub context-store endpoint");
|
|
336
|
+
}
|
|
337
|
+
const connection = await context.resolveCredential?.(configured.credentialRef);
|
|
338
|
+
if (!isConnection(connection)) {
|
|
339
|
+
throw new UnsatisfiedServiceDependencyError(
|
|
340
|
+
"Host must supply a GitHub context-store connection",
|
|
341
|
+
requirement,
|
|
342
|
+
{
|
|
343
|
+
dependencyStatus: {
|
|
344
|
+
state: "missing",
|
|
345
|
+
message: "Configure the host-managed GitHub App connection"
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
const abort = AbortSignal.any([
|
|
351
|
+
...signal ? [signal] : [],
|
|
352
|
+
AbortSignal.timeout(3e4)
|
|
353
|
+
]);
|
|
354
|
+
abort.throwIfAborted();
|
|
355
|
+
requireServiceDependency(context, requirement, context.identity?.serviceId ?? provider.id);
|
|
356
|
+
const response = await connection.request({
|
|
357
|
+
url: url.href,
|
|
358
|
+
method,
|
|
359
|
+
headers: {
|
|
360
|
+
accept: "application/vnd.github+json",
|
|
361
|
+
"content-type": "application/json",
|
|
362
|
+
"x-github-api-version": "2026-03-10"
|
|
363
|
+
},
|
|
364
|
+
...body === void 0 ? {} : { body: JSON.stringify(body) },
|
|
365
|
+
signal: abort
|
|
366
|
+
});
|
|
367
|
+
if (response.status === 401) {
|
|
368
|
+
await context.clearCredential?.(configured.credentialRef);
|
|
369
|
+
throw new UnsatisfiedServiceDependencyError(
|
|
370
|
+
"GitHub context-store authorization expired",
|
|
371
|
+
requirement,
|
|
372
|
+
{
|
|
373
|
+
dependencyStatus: {
|
|
374
|
+
state: "authorization-required",
|
|
375
|
+
message: "Reconnect the GitHub App installation"
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
);
|
|
379
|
+
}
|
|
380
|
+
if (!response.ok && !allowedStatuses.includes(response.status)) {
|
|
381
|
+
throw new Error(
|
|
382
|
+
`GitHub context-store ${method} ${url.pathname} failed with HTTP ${response.status}`
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
if (response.status === 204 || allowedStatuses.includes(response.status)) {
|
|
386
|
+
return { response };
|
|
387
|
+
}
|
|
388
|
+
let value;
|
|
389
|
+
try {
|
|
390
|
+
value = await response.json();
|
|
391
|
+
} catch (error) {
|
|
392
|
+
throw new Error("GitHub context-store response is not valid JSON", { cause: error });
|
|
393
|
+
}
|
|
394
|
+
return { response, value };
|
|
395
|
+
}
|
|
396
|
+
async function head(signal) {
|
|
397
|
+
const reference = refResponse(
|
|
398
|
+
(await call(`git/ref/${apiPath(ref.split("/"))}`, "GET", void 0, signal)).value
|
|
399
|
+
);
|
|
400
|
+
const commit2 = commitResponse(
|
|
401
|
+
(await call(
|
|
402
|
+
`git/commits/${encodeURIComponent(reference.object.sha)}`,
|
|
403
|
+
"GET",
|
|
404
|
+
void 0,
|
|
405
|
+
signal
|
|
406
|
+
)).value
|
|
407
|
+
);
|
|
408
|
+
return commit2;
|
|
409
|
+
}
|
|
410
|
+
async function readPath(path, revision, signal) {
|
|
411
|
+
const url = `contents/${apiPath(path.split("/"))}?ref=${encodeURIComponent(revision)}`;
|
|
412
|
+
const result = await call(url, "GET", void 0, signal, [404]);
|
|
413
|
+
if (result.response.status === 404) return void 0;
|
|
414
|
+
const content = contentResponse(result.value);
|
|
415
|
+
try {
|
|
416
|
+
const value = JSON.parse(
|
|
417
|
+
Buffer.from(content.content.replace(/\s+/g, ""), "base64").toString("utf8")
|
|
418
|
+
);
|
|
419
|
+
if (!isJson(value)) throw new Error("Decoded value is not JSON data");
|
|
420
|
+
return value;
|
|
421
|
+
} catch (error) {
|
|
422
|
+
throw new Error(`GitHub context path '${path}' contains invalid JSON`, { cause: error });
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
async function createBlob(content, signal) {
|
|
426
|
+
const response = apiObject(
|
|
427
|
+
(await call("git/blobs", "POST", { content, encoding: "utf-8" }, signal)).value,
|
|
428
|
+
"GitHub blob response"
|
|
429
|
+
);
|
|
430
|
+
return response.sha;
|
|
431
|
+
}
|
|
432
|
+
async function commit(base, changes, message, signal) {
|
|
433
|
+
const treeEntries = await Promise.all(changes.map(async ({ path, content }) => ({
|
|
434
|
+
path,
|
|
435
|
+
mode: recordMode,
|
|
436
|
+
type: recordType,
|
|
437
|
+
sha: await createBlob(content, signal)
|
|
438
|
+
})));
|
|
439
|
+
const tree = apiObject(
|
|
440
|
+
(await call("git/trees", "POST", {
|
|
441
|
+
base_tree: base.tree.sha,
|
|
442
|
+
tree: treeEntries
|
|
443
|
+
}, signal)).value,
|
|
444
|
+
"GitHub tree response"
|
|
445
|
+
);
|
|
446
|
+
const created = apiObject(
|
|
447
|
+
(await call("git/commits", "POST", {
|
|
448
|
+
message,
|
|
449
|
+
tree: tree.sha,
|
|
450
|
+
parents: [base.sha]
|
|
451
|
+
}, signal)).value,
|
|
452
|
+
"GitHub commit response"
|
|
453
|
+
);
|
|
454
|
+
const revision = created.sha;
|
|
455
|
+
const update = await call(
|
|
456
|
+
`git/refs/${apiPath(ref.split("/"))}`,
|
|
457
|
+
"PATCH",
|
|
458
|
+
{ sha: revision, force: false },
|
|
459
|
+
signal,
|
|
460
|
+
[409, 422]
|
|
461
|
+
);
|
|
462
|
+
return update.response.ok ? revision : void 0;
|
|
463
|
+
}
|
|
464
|
+
async function query(input, signal) {
|
|
465
|
+
const current = await head(signal);
|
|
466
|
+
const paths = scopePaths(configured, input.scope);
|
|
467
|
+
const storedIndex = await readPath(paths.index, current.sha, signal);
|
|
468
|
+
if (storedIndex === void 0) {
|
|
469
|
+
return {
|
|
470
|
+
output: { scope: input.scope, requestKey: input.requestKey, records: [] },
|
|
471
|
+
revision: current.sha
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
const index = scopeIndex(storedIndex, input.scope);
|
|
475
|
+
const records = await Promise.all(index.records.slice(0, input.limit).map(async (entry) => {
|
|
476
|
+
const id = text(entry?.id, "indexed record id");
|
|
477
|
+
const value = await readPath(paths.record(id), current.sha, signal);
|
|
478
|
+
if (value === void 0) {
|
|
479
|
+
throw new Error(`GitHub context scope index references missing record '${id}'`);
|
|
480
|
+
}
|
|
481
|
+
const record = validatedRecord(value);
|
|
482
|
+
if (record.id !== id) {
|
|
483
|
+
throw new Error(`GitHub context record path identity mismatch for '${id}'`);
|
|
484
|
+
}
|
|
485
|
+
return record;
|
|
486
|
+
}));
|
|
487
|
+
return {
|
|
488
|
+
output: {
|
|
489
|
+
scope: input.scope,
|
|
490
|
+
requestKey: input.requestKey,
|
|
491
|
+
records
|
|
492
|
+
},
|
|
493
|
+
revision: current.sha
|
|
494
|
+
};
|
|
495
|
+
}
|
|
496
|
+
async function ingest(input, signal) {
|
|
497
|
+
const paths = scopePaths(configured, input.scope);
|
|
498
|
+
for (let attempt = 1; attempt <= configured.maxWriteAttempts; attempt += 1) {
|
|
499
|
+
const current = await head(signal);
|
|
500
|
+
const metadataValue = await readPath(paths.metadata, current.sha, signal);
|
|
501
|
+
if (metadataValue !== void 0) {
|
|
502
|
+
const metadata = object(metadataValue, "GitHub context scope metadata");
|
|
503
|
+
if (metadata.format !== "gik-github-context-scope/1" || metadata.scope !== input.scope) {
|
|
504
|
+
throw new Error("GitHub context scope metadata is corrupt or hash-collided");
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
const storedIndex = await readPath(paths.index, current.sha, signal);
|
|
508
|
+
let index = {
|
|
509
|
+
format: "gik-github-context-recent/1",
|
|
510
|
+
scope: input.scope,
|
|
511
|
+
records: []
|
|
512
|
+
};
|
|
513
|
+
if (storedIndex !== void 0) {
|
|
514
|
+
index = scopeIndex(storedIndex, input.scope);
|
|
515
|
+
}
|
|
516
|
+
const changes = [];
|
|
517
|
+
const entries = new Map(index.records.map((entry) => [entry.id, entry]));
|
|
518
|
+
const unique = /* @__PURE__ */ new Map();
|
|
519
|
+
for (const record of input.records) unique.set(record.id, record);
|
|
520
|
+
for (const record of unique.values()) {
|
|
521
|
+
const path = paths.record(record.id);
|
|
522
|
+
const encoded = serialize(record);
|
|
523
|
+
const existing = await readPath(path, current.sha, signal);
|
|
524
|
+
if (existing !== void 0) {
|
|
525
|
+
const stored = validatedRecord(existing);
|
|
526
|
+
if (stored.id !== record.id || serialize(stored) !== encoded) {
|
|
527
|
+
throw new GitHubContextRecordConflictError(record.id);
|
|
528
|
+
}
|
|
529
|
+
} else {
|
|
530
|
+
changes.push({ path, content: encoded });
|
|
531
|
+
}
|
|
532
|
+
entries.set(record.id, { id: record.id, observedAt: record.observedAt });
|
|
533
|
+
}
|
|
534
|
+
const nextRecords = [...entries.values()].sort((left, right) => right.observedAt.localeCompare(left.observedAt) || left.id.localeCompare(right.id)).slice(0, configured.maxRecordsPerScope);
|
|
535
|
+
const nextIndex = { ...index, records: nextRecords };
|
|
536
|
+
if (metadataValue === void 0) {
|
|
537
|
+
changes.push({
|
|
538
|
+
path: paths.metadata,
|
|
539
|
+
content: serialize({
|
|
540
|
+
format: "gik-github-context-scope/1",
|
|
541
|
+
scope: input.scope
|
|
542
|
+
})
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
if (storedIndex === void 0 || serialize(storedIndex) !== serialize(nextIndex)) {
|
|
546
|
+
changes.push({
|
|
547
|
+
path: paths.index,
|
|
548
|
+
content: serialize(nextIndex)
|
|
549
|
+
});
|
|
550
|
+
}
|
|
551
|
+
if (!changes.length) {
|
|
552
|
+
return {
|
|
553
|
+
output: {
|
|
554
|
+
scope: input.scope,
|
|
555
|
+
recordIds: input.records.map(({ id }) => id),
|
|
556
|
+
status: "stored"
|
|
557
|
+
},
|
|
558
|
+
revision: current.sha
|
|
559
|
+
};
|
|
560
|
+
}
|
|
561
|
+
const revision = await commit(
|
|
562
|
+
current,
|
|
563
|
+
changes,
|
|
564
|
+
`context: ingest ${input.records.length} record(s) for ${digest(input.scope).slice(0, 12)}`,
|
|
565
|
+
signal
|
|
566
|
+
);
|
|
567
|
+
if (revision) {
|
|
568
|
+
return {
|
|
569
|
+
output: {
|
|
570
|
+
scope: input.scope,
|
|
571
|
+
recordIds: input.records.map(({ id }) => id),
|
|
572
|
+
status: "stored"
|
|
573
|
+
},
|
|
574
|
+
revision
|
|
575
|
+
};
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
throw new GitHubContextStoreRevisionConflictError(
|
|
579
|
+
configured.ref,
|
|
580
|
+
configured.maxWriteAttempts
|
|
581
|
+
);
|
|
582
|
+
}
|
|
583
|
+
return {
|
|
584
|
+
provider,
|
|
585
|
+
discover: async () => ({
|
|
586
|
+
provider,
|
|
587
|
+
revision: "1",
|
|
588
|
+
discoveredAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
589
|
+
capabilities: operations.map((operation) => ({
|
|
590
|
+
id: operation === "query" ? CONTEXT_STORE_QUERY_CONTRACT : CONTEXT_STORE_INGEST_CONTRACT,
|
|
591
|
+
operation,
|
|
592
|
+
name: operation === "query" ? "Query GitHub context" : "Ingest GitHub context",
|
|
593
|
+
version: "1",
|
|
594
|
+
inputSchema: operation === "query" ? contextStoreQueryInputSchema : contextStoreIngestInputSchema,
|
|
595
|
+
outputSchema: operation === "query" ? contextStoreQueryOutputSchema : contextStoreIngestOutputSchema,
|
|
596
|
+
assurance: "declared-and-locally-validated"
|
|
597
|
+
}))
|
|
598
|
+
}),
|
|
599
|
+
async probe(adapterContext) {
|
|
600
|
+
const current = await head(adapterContext.signal);
|
|
601
|
+
return {
|
|
602
|
+
ok: true,
|
|
603
|
+
detail: {
|
|
604
|
+
repository: configured.repository,
|
|
605
|
+
ref: configured.ref,
|
|
606
|
+
revision: current.sha
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
},
|
|
610
|
+
async execute(request, adapterContext) {
|
|
611
|
+
if (!operations.includes(request.operation)) {
|
|
612
|
+
throw new Error("GitHub context-store operation is not declared");
|
|
613
|
+
}
|
|
614
|
+
if (request.operation === "query") {
|
|
615
|
+
const result = await query(queryInput(request.input), adapterContext.signal);
|
|
616
|
+
return {
|
|
617
|
+
output: jsonValue(result.output, "GitHub context query output"),
|
|
618
|
+
detail: {
|
|
619
|
+
repository: configured.repository,
|
|
620
|
+
ref: configured.ref,
|
|
621
|
+
revision: result.revision
|
|
622
|
+
}
|
|
623
|
+
};
|
|
624
|
+
}
|
|
625
|
+
if (request.operation === "ingest") {
|
|
626
|
+
const result = await ingest(ingestInput(request.input), adapterContext.signal);
|
|
627
|
+
return {
|
|
628
|
+
output: jsonValue(result.output, "GitHub context ingestion output"),
|
|
629
|
+
detail: {
|
|
630
|
+
repository: configured.repository,
|
|
631
|
+
ref: configured.ref,
|
|
632
|
+
revision: result.revision
|
|
633
|
+
}
|
|
634
|
+
};
|
|
635
|
+
}
|
|
636
|
+
throw new Error("Unsupported GitHub context-store operation");
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
}
|
|
642
|
+
export {
|
|
643
|
+
GitHubContextRecordConflictError,
|
|
644
|
+
GitHubContextStoreRevisionConflictError,
|
|
645
|
+
createGitHubContextStoreServiceKind
|
|
646
|
+
};
|
|
647
|
+
//# sourceMappingURL=github-context-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/github-context-store.ts","../src/values.ts"],"sourcesContent":["import { createHash } from \"node:crypto\";\nimport { Buffer } from \"node:buffer\";\n\nimport {\n CONTEXT_STORE_INGEST_CONTRACT,\n CONTEXT_STORE_MAX_QUERY_LIMIT,\n CONTEXT_STORE_QUERY_CONTRACT,\n contextStoreIngestInputSchema,\n contextStoreIngestOutputSchema,\n contextStoreQueryInputSchema,\n contextStoreQueryOutputSchema,\n requireServiceDependency,\n serviceConfig,\n UnsatisfiedServiceDependencyError,\n type ContextRecord,\n type ContextStoreIngestInput,\n type ContextStoreIngestOutput,\n type ContextStoreQueryInput,\n type ContextStoreQueryOutput,\n type ServiceDependencyRequirement,\n type ServiceKindContext,\n type ServiceKindFactory,\n type ServiceRequest,\n} from \"gik-controlface/services\";\nimport type { Json, NativeServiceDeclaration } from \"gik-kernel\";\nimport { integer, isJson, keys, object, text } from \"./values\";\n\nconst provider = { id: \"github-context-store\", version: \"1\" };\nconst recordMode = \"100644\";\nconst recordType = \"blob\";\nconst defaultMaxRecordsPerScope = 1000;\nconst defaultMaxWriteAttempts = 3;\n\nexport interface GitHubContextStoreHttpRequest {\n url: string;\n method: \"GET\" | \"POST\" | \"PATCH\";\n headers: Readonly<Record<string, string>>;\n body?: string;\n signal: AbortSignal;\n}\n\n/** The host owns authentication and adds it inside this connection. */\nexport interface GitHubContextStoreConnection {\n request(request: Readonly<GitHubContextStoreHttpRequest>): Promise<Response>;\n}\n\nexport class GitHubContextRecordConflictError extends Error {\n readonly code = \"github-context-record-conflict\";\n\n constructor(recordId: string) {\n super(`GitHub context record '${recordId}' already exists with different content`);\n this.name = \"GitHubContextRecordConflictError\";\n }\n}\n\nexport class GitHubContextStoreRevisionConflictError extends Error {\n readonly code = \"github-context-store-revision-conflict\";\n\n constructor(readonly ref: string, readonly attempts: number) {\n super(`GitHub context ref '${ref}' changed during ${attempts} write attempts`);\n this.name = \"GitHubContextStoreRevisionConflictError\";\n }\n}\n\ninterface GitHubContextStoreConfig {\n endpoint: string;\n repository: string;\n ref: string;\n prefix: string;\n credentialRef: string;\n maxRecordsPerScope: number;\n maxWriteAttempts: number;\n}\n\ninterface ScopeIndex {\n format: \"gik-github-context-recent/1\";\n scope: string;\n records: Array<{ id: string; observedAt: string }>;\n}\n\ninterface GitHubApiObject {\n sha: string;\n}\n\ninterface GitHubRefResponse {\n object: GitHubApiObject;\n}\n\ninterface GitHubCommitResponse extends GitHubApiObject {\n tree: GitHubApiObject;\n}\n\ninterface GitHubContentResponse {\n type: \"file\";\n encoding: \"base64\";\n content: string;\n}\n\nfunction isConnection(value: unknown): value is GitHubContextStoreConnection {\n return !!value && typeof value === \"object\"\n && \"request\" in value && typeof value.request === \"function\";\n}\n\nfunction canonical(value: Json): Json {\n if (Array.isArray(value)) return value.map(canonical);\n if (value && typeof value === \"object\") {\n return Object.fromEntries(\n Object.entries(value)\n .sort(([left], [right]) => left.localeCompare(right))\n .map(([key, entry]) => [key, canonical(entry)]),\n );\n }\n return value;\n}\n\nfunction serialize(value: unknown): string {\n if (!isJson(value)) throw new Error(\"GitHub context value must be JSON data\");\n return `${JSON.stringify(canonical(value))}\\n`;\n}\n\nfunction jsonValue(value: unknown, label: string): Json {\n if (!isJson(value)) throw new Error(`${label} must be JSON data`);\n return value;\n}\n\nfunction digest(value: string): string {\n return createHash(\"sha256\").update(value).digest(\"hex\");\n}\n\nfunction repositoryParts(repository: string): [string, string] {\n const parts = repository.split(\"/\");\n if (parts.length !== 2 || parts.some((part) => !/^[A-Za-z0-9_.-]+$/.test(part))) {\n throw new Error(\"GitHub context repository must be an owner/name pair\");\n }\n return [parts[0], parts[1]];\n}\n\nfunction normalizedRef(value: string): string {\n if (!value.startsWith(\"refs/heads/\")) {\n throw new Error(\"GitHub context ref must start with 'refs/heads/'\");\n }\n const branch = value.slice(\"refs/heads/\".length);\n if (!branch || branch.startsWith(\"/\") || branch.endsWith(\"/\")\n || branch.includes(\"//\") || branch.split(\"/\").some((part) =>\n !part || part === \".\" || part === \"..\" || !/^[A-Za-z0-9._-]+$/.test(part))) {\n throw new Error(\"GitHub context ref contains an unsafe branch name\");\n }\n return `heads/${branch}`;\n}\n\nfunction normalizedPrefix(value: string): string {\n if (value.startsWith(\"/\") || value.endsWith(\"/\") || value.includes(\"\\\\\")\n || value.split(\"/\").some((part) => !part || part === \".\" || part === \"..\")) {\n throw new Error(\"GitHub context prefix must be a safe repository-relative path\");\n }\n return value;\n}\n\nfunction config(declaration: NativeServiceDeclaration): GitHubContextStoreConfig {\n const value = serviceConfig(declaration);\n const endpoint = text(value.endpoint, \"endpoint\");\n const ref = text(value.ref, \"ref\");\n if (endpoint !== \"https://api.github.com\") {\n throw new Error(\"GitHub context endpoint must be https://api.github.com\");\n }\n normalizedRef(ref);\n return {\n endpoint,\n repository: text(value.repository, \"repository\"),\n ref,\n prefix: normalizedPrefix(text(value.prefix, \"prefix\")),\n credentialRef: text(value.credentialRef, \"credentialRef\"),\n maxRecordsPerScope: integer(\n value.maxRecordsPerScope ?? defaultMaxRecordsPerScope,\n \"maxRecordsPerScope\",\n 1,\n 5000,\n ),\n maxWriteAttempts: integer(\n value.maxWriteAttempts ?? defaultMaxWriteAttempts,\n \"maxWriteAttempts\",\n 1,\n 5,\n ),\n };\n}\n\nfunction credentialRequirement(declaration: NativeServiceDeclaration): ServiceDependencyRequirement {\n const configured = config(declaration);\n const writes = Object.values(declaration.operations)\n .some(({ operation }) => operation === \"ingest\");\n return {\n id: \"github-context-repository\",\n kind: \"credential\",\n title: \"GitHub context repository\",\n description: \"Host-managed GitHub App connection for the declared context repository and ref\",\n ref: configured.credentialRef,\n scheme: \"github-app\",\n permissions: [writes ? \"contents:write\" : \"contents:read\"],\n };\n}\n\nfunction validatedRecord(value: unknown): ContextRecord {\n if (!isJson(value)) throw new Error(\"GitHub context record must be JSON data\");\n const record = object(value, \"GitHub context record\");\n const id = text(record.id, \"record id\");\n const kind = text(record.kind, \"record kind\");\n const observedAt = text(record.observedAt, \"record observedAt\");\n if (Number.isNaN(Date.parse(observedAt))) {\n throw new Error(\"GitHub context record observedAt must be an ISO timestamp\");\n }\n if (record.references !== undefined && !Array.isArray(record.references)) {\n throw new Error(\"GitHub context record references must be an array\");\n }\n const result: ContextRecord = { id, kind, observedAt };\n for (const [key, entry] of Object.entries(record)) {\n if (!isJson(entry)) throw new Error(`GitHub context record field '${key}' is not JSON data`);\n result[key] = entry;\n }\n return result;\n}\n\nfunction jsonObject(value: unknown, label: string): Record<string, Json> {\n const source = object(value, label);\n const result: Record<string, Json> = {};\n for (const [key, entry] of Object.entries(source)) {\n if (!isJson(entry)) throw new Error(`${label} field '${key}' is not JSON data`);\n result[key] = entry;\n }\n return result;\n}\n\nfunction queryInput(value: unknown): ContextStoreQueryInput {\n const input = object(value, \"GitHub context query\");\n keys(input, [\"scope\", \"requestKey\", \"query\", \"limit\"]);\n return {\n scope: text(input.scope, \"scope\"),\n requestKey: text(input.requestKey, \"requestKey\"),\n query: jsonObject(input.query, \"query\"),\n limit: integer(input.limit, \"limit\", 1, CONTEXT_STORE_MAX_QUERY_LIMIT),\n };\n}\n\nfunction ingestInput(value: unknown): ContextStoreIngestInput {\n const input = object(value, \"GitHub context ingestion\");\n keys(input, [\"scope\", \"records\"]);\n if (!Array.isArray(input.records)) throw new Error(\"GitHub context records must be an array\");\n const records = input.records.map(validatedRecord);\n const identities = new Map<string, string>();\n for (const record of records) {\n const encoded = serialize(record);\n const previous = identities.get(record.id);\n if (previous !== undefined && previous !== encoded) {\n throw new GitHubContextRecordConflictError(record.id);\n }\n identities.set(record.id, encoded);\n }\n return { scope: text(input.scope, \"scope\"), records };\n}\n\nfunction apiPath(parts: string[]): string {\n return parts.map((part) => encodeURIComponent(part)).join(\"/\");\n}\n\nfunction endpoint(configured: GitHubContextStoreConfig, suffix: string): URL {\n const [owner, repository] = repositoryParts(configured.repository);\n return new URL(`/repos/${apiPath([owner, repository])}/${suffix}`, configured.endpoint);\n}\n\nfunction scopePaths(configured: GitHubContextStoreConfig, scope: string) {\n const root = `${configured.prefix}/scopes/${digest(scope)}`;\n return {\n metadata: `${root}/metadata.json`,\n index: `${root}/recent.json`,\n record: (id: string) => `${root}/records/${digest(id)}.json`,\n };\n}\n\nfunction jsonResponse(value: unknown, label: string): Record<string, unknown> {\n if (!isJson(value)) throw new Error(`${label} is not JSON data`);\n return object(value, label);\n}\n\nfunction apiObject(value: unknown, label: string): GitHubApiObject {\n const response = jsonResponse(value, label);\n return { sha: text(response.sha, `${label} SHA`) };\n}\n\nfunction refResponse(value: unknown): GitHubRefResponse {\n const response = jsonResponse(value, \"GitHub ref response\");\n const target = object(response.object, \"GitHub ref object\");\n return { object: { sha: text(target.sha, \"GitHub ref object SHA\") } };\n}\n\nfunction commitResponse(value: unknown): GitHubCommitResponse {\n const response = jsonResponse(value, \"GitHub commit response\");\n const tree = object(response.tree, \"GitHub commit tree\");\n return {\n sha: text(response.sha, \"GitHub commit SHA\"),\n tree: { sha: text(tree.sha, \"GitHub commit tree SHA\") },\n };\n}\n\nfunction contentResponse(value: unknown): GitHubContentResponse {\n const response = jsonResponse(value, \"GitHub content response\");\n if (response.type !== \"file\" || response.encoding !== \"base64\") {\n throw new Error(\"GitHub content response is not a base64 file\");\n }\n return {\n type: \"file\",\n encoding: \"base64\",\n content: text(response.content, \"GitHub content\"),\n };\n}\n\nfunction scopeIndex(value: unknown, scope: string): ScopeIndex {\n const source = jsonResponse(value, \"GitHub context scope index\");\n if (source.format !== \"gik-github-context-recent/1\"\n || source.scope !== scope || !Array.isArray(source.records)) {\n throw new Error(\"GitHub context scope index is corrupt or belongs to another scope\");\n }\n return {\n format: \"gik-github-context-recent/1\",\n scope,\n records: source.records.map((entry) => {\n const record = object(entry, \"GitHub context scope index record\");\n return {\n id: text(record.id, \"indexed record id\"),\n observedAt: text(record.observedAt, \"indexed record observedAt\"),\n };\n }),\n };\n}\n\nexport function createGitHubContextStoreServiceKind(): ServiceKindFactory {\n return {\n manifest: {\n id: provider.id,\n version: provider.version,\n title: \"GitHub-backed context store\",\n description: \"Immutable bounded context records stored on a declared private GitHub ref\",\n configSchema: {\n type: \"object\",\n additionalProperties: false,\n required: [\"endpoint\", \"repository\", \"ref\", \"prefix\", \"credentialRef\"],\n properties: {\n endpoint: { const: \"https://api.github.com\" },\n repository: { type: \"string\", pattern: \"^[A-Za-z0-9_.-]+/[A-Za-z0-9_.-]+$\" },\n ref: {\n type: \"string\",\n pattern:\n \"^refs/heads/(?!\\\\.{1,2}(?:/|$))[A-Za-z0-9._-]+(?:/(?!\\\\.{1,2}(?:/|$))[A-Za-z0-9._-]+)*$\",\n },\n prefix: { type: \"string\", minLength: 1 },\n credentialRef: { type: \"string\", minLength: 1 },\n maxRecordsPerScope: { type: \"integer\", minimum: 1, maximum: 5000 },\n maxWriteAttempts: { type: \"integer\", minimum: 1, maximum: 5 },\n },\n },\n subjects: [\"cell\", \"substrate-agent\", \"chat\", \"task\"],\n executionModes: [\"immediate\", \"queued\"],\n supports: { discover: true, probe: true },\n },\n describeDependencies: (declaration) => [credentialRequirement(declaration)],\n validate(declaration, context) {\n try {\n if (declaration.version !== \"1\") {\n throw new Error(\"github-context-store supports version 1 only\");\n }\n config(declaration);\n if (!context.resolveCredential || !context.authorizeEndpoint) {\n throw new Error(\n \"github-context-store requires host credential resolution and endpoint authorization\",\n );\n }\n if (!Object.keys(declaration.operations).length) {\n throw new Error(\"github-context-store requires a declared operation\");\n }\n for (const operation of Object.values(declaration.operations)) {\n const contract = operation.operation === \"query\"\n ? CONTEXT_STORE_QUERY_CONTRACT\n : operation.operation === \"ingest\"\n ? CONTEXT_STORE_INGEST_CONTRACT\n : undefined;\n if (!contract || operation.contract !== contract || operation.sense) {\n throw new Error(\"Unsupported github-context-store operation or contract\");\n }\n }\n return { ok: true };\n } catch (error) {\n return { ok: false, errors: [error instanceof Error ? error.message : String(error)] };\n }\n },\n create(declaration, context) {\n const configured = config(declaration);\n const ref = normalizedRef(configured.ref);\n const requirement = credentialRequirement(declaration);\n const operations = [...new Set(\n Object.values(declaration.operations).map(({ operation }) => operation),\n )];\n\n async function call(\n path: string,\n method: GitHubContextStoreHttpRequest[\"method\"],\n body?: Json,\n signal?: AbortSignal,\n allowedStatuses: readonly number[] = [],\n ): Promise<{ response: Response; value?: unknown }> {\n requireServiceDependency(context, requirement, context.identity?.serviceId ?? provider.id);\n const url = endpoint(configured, path);\n if (!context.authorizeEndpoint\n || !await context.authorizeEndpoint(provider.id, url)) {\n throw new Error(\"Host denied the declared GitHub context-store endpoint\");\n }\n const connection = await context.resolveCredential?.(configured.credentialRef);\n if (!isConnection(connection)) {\n throw new UnsatisfiedServiceDependencyError(\n \"Host must supply a GitHub context-store connection\",\n requirement,\n {\n dependencyStatus: {\n state: \"missing\",\n message: \"Configure the host-managed GitHub App connection\",\n },\n },\n );\n }\n const abort = AbortSignal.any([\n ...(signal ? [signal] : []),\n AbortSignal.timeout(30000),\n ]);\n abort.throwIfAborted();\n requireServiceDependency(context, requirement, context.identity?.serviceId ?? provider.id);\n const response = await connection.request({\n url: url.href,\n method,\n headers: {\n accept: \"application/vnd.github+json\",\n \"content-type\": \"application/json\",\n \"x-github-api-version\": \"2026-03-10\",\n },\n ...(body === undefined ? {} : { body: JSON.stringify(body) }),\n signal: abort,\n });\n if (response.status === 401) {\n await context.clearCredential?.(configured.credentialRef);\n throw new UnsatisfiedServiceDependencyError(\n \"GitHub context-store authorization expired\",\n requirement,\n {\n dependencyStatus: {\n state: \"authorization-required\",\n message: \"Reconnect the GitHub App installation\",\n },\n },\n );\n }\n if (!response.ok && !allowedStatuses.includes(response.status)) {\n throw new Error(\n `GitHub context-store ${method} ${url.pathname} failed with HTTP ${response.status}`,\n );\n }\n if (response.status === 204 || allowedStatuses.includes(response.status)) {\n return { response };\n }\n let value: unknown;\n try {\n value = await response.json();\n } catch (error) {\n throw new Error(\"GitHub context-store response is not valid JSON\", { cause: error });\n }\n return { response, value };\n }\n\n async function head(signal?: AbortSignal): Promise<GitHubCommitResponse> {\n const reference = refResponse(\n (await call(`git/ref/${apiPath(ref.split(\"/\"))}`, \"GET\", undefined, signal)).value,\n );\n const commit = commitResponse(\n (await call(\n `git/commits/${encodeURIComponent(reference.object.sha)}`,\n \"GET\",\n undefined,\n signal,\n )).value,\n );\n return commit;\n }\n\n async function readPath(\n path: string,\n revision: string,\n signal?: AbortSignal,\n ): Promise<Json | undefined> {\n const url = `contents/${apiPath(path.split(\"/\"))}?ref=${encodeURIComponent(revision)}`;\n const result = await call(url, \"GET\", undefined, signal, [404]);\n if (result.response.status === 404) return undefined;\n const content = contentResponse(result.value);\n try {\n const value: unknown = JSON.parse(\n Buffer.from(content.content.replace(/\\s+/g, \"\"), \"base64\").toString(\"utf8\"),\n );\n if (!isJson(value)) throw new Error(\"Decoded value is not JSON data\");\n return value;\n } catch (error) {\n throw new Error(`GitHub context path '${path}' contains invalid JSON`, { cause: error });\n }\n }\n\n async function createBlob(content: string, signal?: AbortSignal): Promise<string> {\n const response = apiObject(\n (await call(\"git/blobs\", \"POST\", { content, encoding: \"utf-8\" }, signal)).value,\n \"GitHub blob response\",\n );\n return response.sha;\n }\n\n async function commit(\n base: GitHubCommitResponse,\n changes: Array<{ path: string; content: string }>,\n message: string,\n signal?: AbortSignal,\n ): Promise<string | undefined> {\n const treeEntries = await Promise.all(changes.map(async ({ path, content }) => ({\n path,\n mode: recordMode,\n type: recordType,\n sha: await createBlob(content, signal),\n })));\n const tree = apiObject(\n (await call(\"git/trees\", \"POST\", {\n base_tree: base.tree.sha,\n tree: treeEntries,\n }, signal)).value,\n \"GitHub tree response\",\n );\n const created = apiObject(\n (await call(\"git/commits\", \"POST\", {\n message,\n tree: tree.sha,\n parents: [base.sha],\n }, signal)).value,\n \"GitHub commit response\",\n );\n const revision = created.sha;\n const update = await call(\n `git/refs/${apiPath(ref.split(\"/\"))}`,\n \"PATCH\",\n { sha: revision, force: false },\n signal,\n [409, 422],\n );\n return update.response.ok ? revision : undefined;\n }\n\n async function query(\n input: ContextStoreQueryInput,\n signal?: AbortSignal,\n ): Promise<{ output: ContextStoreQueryOutput; revision: string }> {\n const current = await head(signal);\n const paths = scopePaths(configured, input.scope);\n const storedIndex = await readPath(paths.index, current.sha, signal);\n if (storedIndex === undefined) {\n return {\n output: { scope: input.scope, requestKey: input.requestKey, records: [] },\n revision: current.sha,\n };\n }\n const index = scopeIndex(storedIndex, input.scope);\n const records = await Promise.all(index.records.slice(0, input.limit).map(async (entry) => {\n const id = text(entry?.id, \"indexed record id\");\n const value = await readPath(paths.record(id), current.sha, signal);\n if (value === undefined) {\n throw new Error(`GitHub context scope index references missing record '${id}'`);\n }\n const record = validatedRecord(value);\n if (record.id !== id) {\n throw new Error(`GitHub context record path identity mismatch for '${id}'`);\n }\n return record;\n }));\n return {\n output: {\n scope: input.scope,\n requestKey: input.requestKey,\n records,\n },\n revision: current.sha,\n };\n }\n\n async function ingest(\n input: ContextStoreIngestInput,\n signal?: AbortSignal,\n ): Promise<{ output: ContextStoreIngestOutput; revision: string }> {\n const paths = scopePaths(configured, input.scope);\n for (let attempt = 1; attempt <= configured.maxWriteAttempts; attempt += 1) {\n const current = await head(signal);\n const metadataValue = await readPath(paths.metadata, current.sha, signal);\n if (metadataValue !== undefined) {\n const metadata = object(metadataValue, \"GitHub context scope metadata\");\n if (metadata.format !== \"gik-github-context-scope/1\"\n || metadata.scope !== input.scope) {\n throw new Error(\"GitHub context scope metadata is corrupt or hash-collided\");\n }\n }\n const storedIndex = await readPath(paths.index, current.sha, signal);\n let index: ScopeIndex = {\n format: \"gik-github-context-recent/1\",\n scope: input.scope,\n records: [],\n };\n if (storedIndex !== undefined) {\n index = scopeIndex(storedIndex, input.scope);\n }\n\n const changes: Array<{ path: string; content: string }> = [];\n const entries = new Map(index.records.map((entry) => [entry.id, entry]));\n const unique = new Map<string, ContextRecord>();\n for (const record of input.records) unique.set(record.id, record);\n for (const record of unique.values()) {\n const path = paths.record(record.id);\n const encoded = serialize(record);\n const existing = await readPath(path, current.sha, signal);\n if (existing !== undefined) {\n const stored = validatedRecord(existing);\n if (stored.id !== record.id || serialize(stored) !== encoded) {\n throw new GitHubContextRecordConflictError(record.id);\n }\n } else {\n changes.push({ path, content: encoded });\n }\n entries.set(record.id, { id: record.id, observedAt: record.observedAt });\n }\n\n const nextRecords = [...entries.values()]\n .sort((left, right) =>\n right.observedAt.localeCompare(left.observedAt)\n || left.id.localeCompare(right.id))\n .slice(0, configured.maxRecordsPerScope);\n const nextIndex: ScopeIndex = { ...index, records: nextRecords };\n if (metadataValue === undefined) {\n changes.push({\n path: paths.metadata,\n content: serialize({\n format: \"gik-github-context-scope/1\",\n scope: input.scope,\n }),\n });\n }\n if (storedIndex === undefined\n || serialize(storedIndex) !== serialize(nextIndex)) {\n changes.push({\n path: paths.index,\n content: serialize(nextIndex),\n });\n }\n\n if (!changes.length) {\n return {\n output: {\n scope: input.scope,\n recordIds: input.records.map(({ id }) => id),\n status: \"stored\",\n },\n revision: current.sha,\n };\n }\n const revision = await commit(\n current,\n changes,\n `context: ingest ${input.records.length} record(s) for ${digest(input.scope).slice(0, 12)}`,\n signal,\n );\n if (revision) {\n return {\n output: {\n scope: input.scope,\n recordIds: input.records.map(({ id }) => id),\n status: \"stored\",\n },\n revision,\n };\n }\n }\n throw new GitHubContextStoreRevisionConflictError(\n configured.ref,\n configured.maxWriteAttempts,\n );\n }\n\n return {\n provider,\n discover: async () => ({\n provider,\n revision: \"1\",\n discoveredAt: new Date().toISOString(),\n capabilities: operations.map((operation) => ({\n id: operation === \"query\"\n ? CONTEXT_STORE_QUERY_CONTRACT\n : CONTEXT_STORE_INGEST_CONTRACT,\n operation,\n name: operation === \"query\"\n ? \"Query GitHub context\"\n : \"Ingest GitHub context\",\n version: \"1\",\n inputSchema: operation === \"query\"\n ? contextStoreQueryInputSchema\n : contextStoreIngestInputSchema,\n outputSchema: operation === \"query\"\n ? contextStoreQueryOutputSchema\n : contextStoreIngestOutputSchema,\n assurance: \"declared-and-locally-validated\",\n })),\n }),\n async probe(adapterContext) {\n const current = await head(adapterContext.signal);\n return {\n ok: true,\n detail: {\n repository: configured.repository,\n ref: configured.ref,\n revision: current.sha,\n },\n };\n },\n async execute(request: ServiceRequest, adapterContext) {\n if (!operations.includes(request.operation)) {\n throw new Error(\"GitHub context-store operation is not declared\");\n }\n if (request.operation === \"query\") {\n const result = await query(queryInput(request.input), adapterContext.signal);\n return {\n output: jsonValue(result.output, \"GitHub context query output\"),\n detail: {\n repository: configured.repository,\n ref: configured.ref,\n revision: result.revision,\n },\n };\n }\n if (request.operation === \"ingest\") {\n const result = await ingest(ingestInput(request.input), adapterContext.signal);\n return {\n output: jsonValue(result.output, \"GitHub context ingestion output\"),\n detail: {\n repository: configured.repository,\n ref: configured.ref,\n revision: result.revision,\n },\n };\n }\n throw new Error(\"Unsupported GitHub context-store operation\");\n },\n };\n },\n };\n}\n","import type { Json } from \"gik-kernel\";\n\nexport function object(value: unknown, label: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) throw new Error(`${label} must be an object`);\n return value as Record<string, unknown>;\n}\n\nexport function text(value: unknown, label: string): string {\n if (typeof value !== \"string\" || !value.trim()) throw new Error(`${label} must be a nonempty string`);\n return value;\n}\n\nexport function integer(value: unknown, label: string, minimum: number, maximum: number): number {\n if (typeof value !== \"number\" || !Number.isInteger(value) || value < minimum || value > maximum) {\n throw new Error(`${label} must be an integer between ${minimum} and ${maximum}`);\n }\n return value;\n}\n\nexport function keys(value: Record<string, unknown>, allowed: string[]): void {\n const unexpected = Object.keys(value).filter((key) => !allowed.includes(key));\n if (unexpected.length) throw new Error(`Unsupported input fields: ${unexpected.join(\", \")}`);\n}\n\nexport function isJson(value: unknown): value is Json {\n return value === null || typeof value === \"string\" || typeof value === \"boolean\"\n || typeof value === \"number\" && Number.isFinite(value)\n || Array.isArray(value) && value.every(isJson)\n || !!value && typeof value === \"object\" && Object.values(value).every(isJson);\n}\n"],"mappings":"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","names":["endpoint","commit"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gik-service-providers",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"description": "Individually imported host-managed
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Individually imported host-managed service providers for GIK.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
7
7
|
"author": "nsreehari",
|
|
@@ -11,10 +11,24 @@
|
|
|
11
11
|
"directory": "packages/service-providers"
|
|
12
12
|
},
|
|
13
13
|
"sideEffects": false,
|
|
14
|
-
"files": [
|
|
14
|
+
"files": [
|
|
15
|
+
"dist",
|
|
16
|
+
"README.md",
|
|
17
|
+
"examples"
|
|
18
|
+
],
|
|
15
19
|
"exports": {
|
|
16
|
-
"./scheduler": {
|
|
17
|
-
|
|
20
|
+
"./scheduler": {
|
|
21
|
+
"types": "./dist/scheduler.d.ts",
|
|
22
|
+
"import": "./dist/scheduler.js"
|
|
23
|
+
},
|
|
24
|
+
"./gmail": {
|
|
25
|
+
"types": "./dist/gmail.d.ts",
|
|
26
|
+
"import": "./dist/gmail.js"
|
|
27
|
+
},
|
|
28
|
+
"./github-context-store": {
|
|
29
|
+
"types": "./dist/github-context-store.d.ts",
|
|
30
|
+
"import": "./dist/github-context-store.js"
|
|
31
|
+
}
|
|
18
32
|
},
|
|
19
33
|
"dependencies": {
|
|
20
34
|
"croner": "^9.1.0",
|
|
@@ -26,5 +40,8 @@
|
|
|
26
40
|
"prepack": "npm run build",
|
|
27
41
|
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
28
42
|
},
|
|
29
|
-
"publishConfig": {
|
|
43
|
+
"publishConfig": {
|
|
44
|
+
"access": "public",
|
|
45
|
+
"registry": "https://registry.npmjs.org/"
|
|
46
|
+
}
|
|
30
47
|
}
|