@onesi/genesis 0.0.1-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/README.md +29 -0
- package/dist/auto.d.ts +1010 -0
- package/dist/auto.js +125 -0
- package/dist/beacons.d.ts +145 -0
- package/dist/beacons.js +148 -0
- package/dist/blinds-owner-enrollment.d.ts +280 -0
- package/dist/blinds-owner-enrollment.js +169 -0
- package/dist/client.d.ts +52 -0
- package/dist/client.js +384 -0
- package/dist/context.d.ts +50 -0
- package/dist/context.js +153 -0
- package/dist/dials.d.ts +299 -0
- package/dist/dials.js +100 -0
- package/dist/errors.d.ts +35 -0
- package/dist/errors.js +66 -0
- package/dist/flares.d.ts +202 -0
- package/dist/flares.js +61 -0
- package/dist/fleets.d.ts +218 -0
- package/dist/fleets.js +189 -0
- package/dist/flocks.d.ts +439 -0
- package/dist/flocks.js +98 -0
- package/dist/foundry-billing.d.ts +97 -0
- package/dist/foundry-billing.js +107 -0
- package/dist/foundry.d.ts +424 -0
- package/dist/foundry.js +133 -0
- package/dist/garden.d.ts +754 -0
- package/dist/garden.js +76 -0
- package/dist/gateway.d.ts +365 -0
- package/dist/gateway.js +82 -0
- package/dist/gears.d.ts +226 -0
- package/dist/gears.js +42 -0
- package/dist/generated/operations.d.ts +4 -0
- package/dist/generated/operations.js +65134 -0
- package/dist/generated/schema.d.ts +87658 -0
- package/dist/generated/schema.js +1 -0
- package/dist/genesis.d.ts +9574 -0
- package/dist/genesis.js +271 -0
- package/dist/genesis.openapi.json +128522 -0
- package/dist/henry.d.ts +369 -0
- package/dist/henry.js +268 -0
- package/dist/hives-cells.d.ts +127 -0
- package/dist/hives-cells.js +151 -0
- package/dist/hives-environment.d.ts +37 -0
- package/dist/hives-environment.js +80 -0
- package/dist/hives-functions.d.ts +36 -0
- package/dist/hives-functions.js +185 -0
- package/dist/hives-marketplace.d.ts +128 -0
- package/dist/hives-marketplace.js +187 -0
- package/dist/hives-node.d.ts +9 -0
- package/dist/hives-node.js +155 -0
- package/dist/hives-operations.d.ts +451 -0
- package/dist/hives-operations.js +43 -0
- package/dist/hives-platform.d.ts +149 -0
- package/dist/hives-platform.js +183 -0
- package/dist/hives-queue-consumer.d.ts +56 -0
- package/dist/hives-queue-consumer.js +95 -0
- package/dist/hives-queue-funding.d.ts +28 -0
- package/dist/hives-queue-funding.js +81 -0
- package/dist/hives-queues.d.ts +137 -0
- package/dist/hives-queues.js +143 -0
- package/dist/hives-resources-transport.d.ts +23 -0
- package/dist/hives-resources-transport.js +204 -0
- package/dist/hives-response.d.ts +2 -0
- package/dist/hives-response.js +32 -0
- package/dist/hives-runtimes.d.ts +34 -0
- package/dist/hives-runtimes.js +32 -0
- package/dist/hives-sse.d.ts +24 -0
- package/dist/hives-sse.js +111 -0
- package/dist/hives-topics.d.ts +51 -0
- package/dist/hives-topics.js +79 -0
- package/dist/hives-upload.d.ts +9 -0
- package/dist/hives-upload.js +23 -0
- package/dist/hives-volumes.d.ts +64 -0
- package/dist/hives-volumes.js +117 -0
- package/dist/iam-directory.d.ts +8 -0
- package/dist/iam-directory.js +23 -0
- package/dist/iam.d.ts +391 -0
- package/dist/iam.js +92 -0
- package/dist/idempotency.d.ts +7 -0
- package/dist/idempotency.js +39 -0
- package/dist/index.d.ts +47 -0
- package/dist/index.js +37 -0
- package/dist/instances.d.ts +200 -0
- package/dist/instances.js +43 -0
- package/dist/lanes.d.ts +267 -0
- package/dist/lanes.js +41 -0
- package/dist/minds-agent.d.ts +88 -0
- package/dist/minds-agent.js +233 -0
- package/dist/minds-engine.d.ts +394 -0
- package/dist/minds-engine.js +555 -0
- package/dist/minds-owner.d.ts +110 -0
- package/dist/minds-owner.js +226 -0
- package/dist/minds.d.ts +377 -0
- package/dist/minds.js +228 -0
- package/dist/orgs.d.ts +405 -0
- package/dist/orgs.js +63 -0
- package/dist/relays-enrollment.d.ts +33 -0
- package/dist/relays-enrollment.js +115 -0
- package/dist/runner-grant.d.ts +10 -0
- package/dist/runner-grant.js +133 -0
- package/dist/runner.d.ts +72 -0
- package/dist/runner.js +117 -0
- package/dist/scopes.d.ts +310 -0
- package/dist/scopes.js +40 -0
- package/dist/taps.d.ts +118 -0
- package/dist/taps.js +45 -0
- package/dist/traces.d.ts +574 -0
- package/dist/traces.js +97 -0
- package/dist/types.d.ts +98 -0
- package/dist/types.js +1 -0
- package/dist/urls.d.ts +6 -0
- package/dist/urls.js +31 -0
- package/package.json +49 -1
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { GenesisError } from './errors.js';
|
|
2
|
+
export const RUNNER_SELF_GRANT_OPERATION = 'iam_runnerSelfExecutionGrant';
|
|
3
|
+
const requestKeys = ['schemaVersion', 'requestId', 'operationId', 'organizationId', 'projectId', 'platformId', 'workspaceId', 'fleetId', 'resourceEnvironment', 'expiresAtMs'];
|
|
4
|
+
const receiptKeys = ['id', 'principal_id', 'organization_id', 'project_id', 'platform_id', 'workspace_id', 'environmentId', 'role_ids', 'permissions', 'expires_at', 'created_at'];
|
|
5
|
+
const uuid = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
6
|
+
const match = (p, v) => typeof v === 'string' && p.exec(v)?.[0] === v;
|
|
7
|
+
const native = (v, prefix) => match(new RegExp('^' + prefix + '[A-Za-z0-9_]{1,32}$'), v);
|
|
8
|
+
const instant = (v) => typeof v === 'number' && Number.isSafeInteger(v) && v > 0;
|
|
9
|
+
function exact(v, keys) {
|
|
10
|
+
return !!v && typeof v === 'object' && !Array.isArray(v) && Object.keys(v).length === keys.length && keys.every(k => Object.hasOwn(v, k));
|
|
11
|
+
}
|
|
12
|
+
const invalid = () => new TypeError('Runner self-execution permission requires the exact ordinary-human Sandbox selection, operation, request correlation and finite expiry');
|
|
13
|
+
/** Copy only primitive data descriptors before any asynchronous credential call. */
|
|
14
|
+
export function snapshotRunnerSelfGrant(args, routing) {
|
|
15
|
+
if (routing !== 'gateway' || !exact(args, ['body']) || Reflect.ownKeys(args).length !== 1)
|
|
16
|
+
throw invalid();
|
|
17
|
+
const descriptor = Object.getOwnPropertyDescriptor(args, 'body');
|
|
18
|
+
if (!descriptor || !('value' in descriptor))
|
|
19
|
+
throw invalid();
|
|
20
|
+
const body = descriptor.value;
|
|
21
|
+
if (!exact(body, requestKeys) || ![Object.prototype, null].includes(Object.getPrototypeOf(body)) || Reflect.ownKeys(body).length !== requestKeys.length)
|
|
22
|
+
throw invalid();
|
|
23
|
+
const copy = {};
|
|
24
|
+
for (const key of requestKeys) {
|
|
25
|
+
const d = Object.getOwnPropertyDescriptor(body, key);
|
|
26
|
+
if (!d || !('value' in d) || !d.enumerable || (d.value !== null && !['string', 'number'].includes(typeof d.value)))
|
|
27
|
+
throw invalid();
|
|
28
|
+
copy[key] = d.value;
|
|
29
|
+
}
|
|
30
|
+
const now = Date.now();
|
|
31
|
+
if (copy.schemaVersion !== 1 || !match(uuid, copy.requestId) || !match(uuid, copy.operationId)
|
|
32
|
+
|| !native(copy.organizationId, 'o_') || !native(copy.projectId, 'pr_') || !native(copy.workspaceId, 'w_')
|
|
33
|
+
|| copy.platformId !== 'pf_console' || copy.fleetId !== null || copy.resourceEnvironment !== 'sandbox'
|
|
34
|
+
|| !instant(copy.expiresAtMs) || copy.expiresAtMs <= now || copy.expiresAtMs > now + 1_800_000)
|
|
35
|
+
throw invalid();
|
|
36
|
+
return Object.freeze(copy);
|
|
37
|
+
}
|
|
38
|
+
function closedJson(raw) {
|
|
39
|
+
const value = JSON.parse(raw);
|
|
40
|
+
const stack = [];
|
|
41
|
+
for (const token of raw.match(/"(?:\\.|[^"\\])*"|[{}\[\],:]|true|false|null|-?\d+(?:\.\d+)?(?:[eE][+-]?\d+)?/g) ?? []) {
|
|
42
|
+
const frame = stack.at(-1);
|
|
43
|
+
if (token === '{' || token === '[')
|
|
44
|
+
stack.push({ object: token === '{', key: token === '{', keys: new Set() });
|
|
45
|
+
else if (token === '}' || token === ']')
|
|
46
|
+
stack.pop();
|
|
47
|
+
else if (token === ',' && frame?.object)
|
|
48
|
+
frame.key = true;
|
|
49
|
+
else if (token === ':' && frame?.object)
|
|
50
|
+
frame.key = false;
|
|
51
|
+
else if (token.startsWith('"') && frame?.object && frame.key) {
|
|
52
|
+
const key = JSON.parse(token);
|
|
53
|
+
if (frame.keys.has(key))
|
|
54
|
+
throw invalid();
|
|
55
|
+
frame.keys.add(key);
|
|
56
|
+
}
|
|
57
|
+
else if (/^-?\d/.test(token) && !/^-?(?:0|[1-9]\d*)$/.test(token))
|
|
58
|
+
throw invalid();
|
|
59
|
+
}
|
|
60
|
+
return value;
|
|
61
|
+
}
|
|
62
|
+
const errorRows = [
|
|
63
|
+
[400, 'INVALID_ARGUMENT', 'invalid Runner self-execution grant request', 'invalid_runner_self_execution_grant_request'],
|
|
64
|
+
[400, 'INVALID_ARGUMENT', 'Runner self-execution grant expiry is out of bounds', 'runner_self_execution_grant_expiry_out_of_bounds'],
|
|
65
|
+
[401, 'UNAUTHENTICATED', 'Runner self-execution authority inactive', 'runner_self_execution_grant_inactive'],
|
|
66
|
+
[403, 'PERMISSION_DENIED', 'Runner self-execution authority denied', 'runner_self_execution_grant_denied'],
|
|
67
|
+
[409, 'CONFLICT', 'Runner self-execution grant operation conflict', 'runner_self_execution_grant_conflict'],
|
|
68
|
+
[409, 'CONFLICT', 'Runner self-execution grant replay is stale', 'runner_self_execution_grant_replay_stale'],
|
|
69
|
+
[503, 'PROVIDER_UNAVAILABLE', 'Runner self-execution grant unavailable', 'runner_self_execution_grant_unavailable'],
|
|
70
|
+
];
|
|
71
|
+
function uncertain(status, message) {
|
|
72
|
+
return new GenesisError({ status, type: 'runner_grant_uncertain', operationId: RUNNER_SELF_GRANT_OPERATION, message });
|
|
73
|
+
}
|
|
74
|
+
export function runnerGrantTransportError() {
|
|
75
|
+
return uncertain(0, 'Runner permission response was lost. Retry the same operation, scope and expiry with fresh request correlation.');
|
|
76
|
+
}
|
|
77
|
+
/** A bounded closed response; no arbitrary upstream body reaches CLI or MCP. */
|
|
78
|
+
export async function runnerGrantResponse(res, input) {
|
|
79
|
+
let value;
|
|
80
|
+
try {
|
|
81
|
+
if (res.redirected || res.headers.get('content-type')?.split(';')[0].trim().toLowerCase() !== 'application/json')
|
|
82
|
+
throw invalid();
|
|
83
|
+
const reader = res.body?.getReader();
|
|
84
|
+
const chunks = [];
|
|
85
|
+
let size = 0;
|
|
86
|
+
if (reader) {
|
|
87
|
+
try {
|
|
88
|
+
while (true) {
|
|
89
|
+
const next = await reader.read();
|
|
90
|
+
if (next.done)
|
|
91
|
+
break;
|
|
92
|
+
size += next.value.byteLength;
|
|
93
|
+
if (size > 8192) {
|
|
94
|
+
await reader.cancel();
|
|
95
|
+
throw invalid();
|
|
96
|
+
}
|
|
97
|
+
chunks.push(next.value);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
finally {
|
|
101
|
+
reader.releaseLock();
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
const bytes = new Uint8Array(size);
|
|
105
|
+
let offset = 0;
|
|
106
|
+
for (const chunk of chunks) {
|
|
107
|
+
bytes.set(chunk, offset);
|
|
108
|
+
offset += chunk.byteLength;
|
|
109
|
+
}
|
|
110
|
+
value = closedJson(new TextDecoder('utf-8', { fatal: true }).decode(bytes));
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
throw uncertain(res.status, 'Runner permission could not be confirmed. Retry the same operation, scope and expiry with fresh request correlation.');
|
|
114
|
+
}
|
|
115
|
+
if (res.status !== 200) {
|
|
116
|
+
if (exact(value, ['code', 'message', 'details']) && exact(value.details, ['schemaVersion', 'reason']) && value.details.schemaVersion === 1) {
|
|
117
|
+
const details = value.details;
|
|
118
|
+
const row = errorRows.find(r => r[0] === res.status && r[1] === value.code && r[2] === value.message && r[3] === details.reason);
|
|
119
|
+
if (row)
|
|
120
|
+
throw new GenesisError({ status: res.status, type: 'runner_grant_denied', code: row[1], operationId: RUNNER_SELF_GRANT_OPERATION, message: row[2], body: value });
|
|
121
|
+
}
|
|
122
|
+
throw uncertain(res.status, 'Runner permission is unavailable or unconfirmed. Retry the same operation, scope and expiry with fresh request correlation.');
|
|
123
|
+
}
|
|
124
|
+
if (!exact(value, receiptKeys) || !match(/^g_[0-7][0123456789ABCDEFGHJKMNPQRSTVWXYZ]{25}$/, value.id)
|
|
125
|
+
|| !native(value.principal_id, 'h_') || value.organization_id !== input.organizationId || value.project_id !== input.projectId
|
|
126
|
+
|| value.platform_id !== input.platformId || value.workspace_id !== input.workspaceId || value.environmentId !== input.resourceEnvironment
|
|
127
|
+
|| !Array.isArray(value.role_ids) || value.role_ids.length !== 0 || !Array.isArray(value.permissions)
|
|
128
|
+
|| value.permissions.length !== 1 || value.permissions[0] !== 'runner.tasks.execute'
|
|
129
|
+
|| value.expires_at !== input.expiresAtMs || input.expiresAtMs <= Date.now() || !instant(value.created_at) || value.created_at >= input.expiresAtMs) {
|
|
130
|
+
throw uncertain(502, 'Runner returned an unqualified permission receipt. Retry the same operation, scope and expiry to reconcile it.');
|
|
131
|
+
}
|
|
132
|
+
return Response.json(value, { status: 200, headers: { 'Cache-Control': 'no-store', 'X-Content-Type-Options': 'nosniff' } });
|
|
133
|
+
}
|
package/dist/runner.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import type { GenesisClient } from './client.js';
|
|
2
|
+
import type { components } from './generated/schema.js';
|
|
3
|
+
import { type RunnerSelfExecutionGrantInput } from './runner-grant.js';
|
|
4
|
+
type Schemas = components['schemas'];
|
|
5
|
+
export type RunnerStartInput = Schemas['Runner.StartInput'];
|
|
6
|
+
export type RunnerSnapshot = Schemas['Runner.Snapshot'];
|
|
7
|
+
export type RunnerCatalog = Schemas['Runner.Catalog'];
|
|
8
|
+
export type RunnerEvent = Schemas['Runner.Event'];
|
|
9
|
+
export type RunnerProviderResult = Schemas['Runner.ProviderResult'];
|
|
10
|
+
export type RunnerRequestOptions = {
|
|
11
|
+
signal?: AbortSignal;
|
|
12
|
+
};
|
|
13
|
+
/** Runner routes use the Genesis client's credential; the backend owns org/subject scoping. */
|
|
14
|
+
export declare function runnerModule(client: GenesisClient): Readonly<{
|
|
15
|
+
permission: Readonly<{
|
|
16
|
+
grant: (input: RunnerSelfExecutionGrantInput, opts?: RunnerRequestOptions) => Promise<{
|
|
17
|
+
id: string;
|
|
18
|
+
principal_id: string;
|
|
19
|
+
organization_id: string;
|
|
20
|
+
project_id: string;
|
|
21
|
+
platform_id: "pf_console";
|
|
22
|
+
workspace_id: string;
|
|
23
|
+
environmentId: "sandbox";
|
|
24
|
+
role_ids: unknown[];
|
|
25
|
+
permissions: "runner.tasks.execute"[];
|
|
26
|
+
expires_at: number;
|
|
27
|
+
created_at: number;
|
|
28
|
+
}>;
|
|
29
|
+
}>;
|
|
30
|
+
catalog: (opts?: RunnerRequestOptions) => Promise<{
|
|
31
|
+
workspaces: {
|
|
32
|
+
key: components["schemas"]["Runner.SafeOpaqueRef"];
|
|
33
|
+
label: string;
|
|
34
|
+
}[];
|
|
35
|
+
routes: {
|
|
36
|
+
routeId: components["schemas"]["Runner.SafeOpaqueRef"];
|
|
37
|
+
kind: "external-harness" | "internal-model";
|
|
38
|
+
name: string;
|
|
39
|
+
via: string;
|
|
40
|
+
state: "synthetic" | "bound" | "unbound";
|
|
41
|
+
default: boolean;
|
|
42
|
+
}[];
|
|
43
|
+
}>;
|
|
44
|
+
jobs: Readonly<{
|
|
45
|
+
list: (opts?: RunnerRequestOptions) => Promise<{
|
|
46
|
+
jobs: components["schemas"]["Runner.Snapshot"][];
|
|
47
|
+
}>;
|
|
48
|
+
start: (input: RunnerStartInput, opts?: RunnerRequestOptions) => Promise<{
|
|
49
|
+
jobId: components["schemas"]["Runner.SafeOpaqueRef"];
|
|
50
|
+
snapshot: components["schemas"]["Runner.Snapshot"];
|
|
51
|
+
}>;
|
|
52
|
+
get: (jobId: string, opts?: RunnerRequestOptions) => Promise<{
|
|
53
|
+
snapshot: components["schemas"]["Runner.Snapshot"];
|
|
54
|
+
}>;
|
|
55
|
+
events: (jobId: string, afterSeq?: number, opts?: RunnerRequestOptions) => Promise<{
|
|
56
|
+
events: components["schemas"]["Runner.Event"][];
|
|
57
|
+
nextAfterSeq: number;
|
|
58
|
+
hasMore: boolean;
|
|
59
|
+
}>;
|
|
60
|
+
result: (jobId: string, opts?: RunnerRequestOptions) => Promise<{
|
|
61
|
+
result: components["schemas"]["Runner.ProviderResult"];
|
|
62
|
+
}>;
|
|
63
|
+
cancel: (jobId: string, opts?: RunnerRequestOptions) => Promise<{
|
|
64
|
+
snapshot: components["schemas"]["Runner.Snapshot"];
|
|
65
|
+
}>;
|
|
66
|
+
delete: (jobId: string, opts?: RunnerRequestOptions) => Promise<{
|
|
67
|
+
jobId: components["schemas"]["Runner.SafeOpaqueRef"];
|
|
68
|
+
deleted: true;
|
|
69
|
+
}>;
|
|
70
|
+
}>;
|
|
71
|
+
}>;
|
|
72
|
+
export {};
|
package/dist/runner.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
import { RUNNER_SELF_GRANT_OPERATION } from './runner-grant.js';
|
|
2
|
+
const requestOptions = (options) => ({ signal: options.signal });
|
|
3
|
+
const opaqueId = (v) => typeof v === 'string' && /^[A-Za-z0-9][A-Za-z0-9._:-]{0,127}$/.test(v);
|
|
4
|
+
const pathLike = (v) => /^[A-Za-z]:/.test(v) || v.includes('..');
|
|
5
|
+
const invalid = () => new TypeError('Runner input must match the bounded runner/task-client/v0 contract');
|
|
6
|
+
function checkedJobId(value) {
|
|
7
|
+
if (!opaqueId(value) || pathLike(value)
|
|
8
|
+
|| /^(?:https?|ftp|file|data|javascript|bearer|basic):|^(?:sk[-_]|pk[-_]|gh[pousr]_|github_pat_|xox[baprs]-|eyJ)/i.test(value)) {
|
|
9
|
+
throw invalid();
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
function closed(value, required, optional = []) {
|
|
14
|
+
return value !== null && typeof value === 'object' && !Array.isArray(value)
|
|
15
|
+
&& required.every((key) => Object.hasOwn(value, key))
|
|
16
|
+
&& Object.keys(value).every((key) => required.includes(key) || optional.includes(key));
|
|
17
|
+
}
|
|
18
|
+
// Match the core's input bounds and copy once so a caller cannot mutate a validated request
|
|
19
|
+
// while the asynchronous credential provider runs. Identity is never an input property.
|
|
20
|
+
function copyBoundedInput(value) {
|
|
21
|
+
let nodes = 0;
|
|
22
|
+
let chars = 0;
|
|
23
|
+
const ancestors = new Set();
|
|
24
|
+
const countText = (text) => {
|
|
25
|
+
chars += text.length;
|
|
26
|
+
if (text.length > 32768 || chars > 65536)
|
|
27
|
+
throw invalid();
|
|
28
|
+
return text;
|
|
29
|
+
};
|
|
30
|
+
const walk = (v, depth) => {
|
|
31
|
+
if (++nodes > 256)
|
|
32
|
+
throw invalid();
|
|
33
|
+
if (v === null || typeof v === 'boolean')
|
|
34
|
+
return v;
|
|
35
|
+
if (typeof v === 'string')
|
|
36
|
+
return countText(v);
|
|
37
|
+
if (typeof v === 'number' && Number.isFinite(v))
|
|
38
|
+
return v;
|
|
39
|
+
if (typeof v !== 'object' || depth >= 6 || ancestors.has(v))
|
|
40
|
+
throw invalid();
|
|
41
|
+
ancestors.add(v);
|
|
42
|
+
try {
|
|
43
|
+
if (Array.isArray(v)) {
|
|
44
|
+
if (Object.getPrototypeOf(v) !== Array.prototype || v.length > 64 || Reflect.ownKeys(v).length !== v.length + 1)
|
|
45
|
+
throw invalid();
|
|
46
|
+
return Array.from({ length: v.length }, (_, index) => {
|
|
47
|
+
const d = Object.getOwnPropertyDescriptor(v, String(index));
|
|
48
|
+
if (!d || !('value' in d) || !d.enumerable)
|
|
49
|
+
throw invalid();
|
|
50
|
+
return walk(d.value, depth + 1);
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
const prototype = Object.getPrototypeOf(v);
|
|
54
|
+
if (prototype !== null && prototype !== Object.prototype)
|
|
55
|
+
throw invalid();
|
|
56
|
+
const keys = Reflect.ownKeys(v);
|
|
57
|
+
if (keys.length > 32)
|
|
58
|
+
throw invalid();
|
|
59
|
+
const out = Object.create(null);
|
|
60
|
+
for (const key of keys) {
|
|
61
|
+
if (typeof key !== 'string')
|
|
62
|
+
throw invalid();
|
|
63
|
+
countText(key);
|
|
64
|
+
const d = Object.getOwnPropertyDescriptor(v, key);
|
|
65
|
+
if (!('value' in d) || !d.enumerable)
|
|
66
|
+
throw invalid();
|
|
67
|
+
out[key] = walk(d.value, depth + 1);
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
finally {
|
|
72
|
+
ancestors.delete(v);
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
return walk(value, 0);
|
|
76
|
+
}
|
|
77
|
+
function checkedStartInput(input) {
|
|
78
|
+
const v = copyBoundedInput(input);
|
|
79
|
+
if (!closed(v, ['task', 'workspaceRef', 'executionRef', 'limits', 'idempotencyKey'])
|
|
80
|
+
|| !closed(v.task, ['id', 'text'], ['meta']) || !opaqueId(v.task.id)
|
|
81
|
+
|| typeof v.task.text !== 'string' || !v.task.text.trim()
|
|
82
|
+
|| (Object.hasOwn(v.task, 'meta') && (v.task.meta === null || typeof v.task.meta !== 'object' || Array.isArray(v.task.meta)))
|
|
83
|
+
|| !opaqueId(v.workspaceRef) || pathLike(v.workspaceRef)
|
|
84
|
+
|| !closed(v.executionRef, ['kind', 'routeId'])
|
|
85
|
+
|| !['external-harness', 'internal-model'].includes(v.executionRef.kind) || !opaqueId(v.executionRef.routeId)
|
|
86
|
+
|| !closed(v.limits, ['maxDurationMs', 'maxOutputBytes'], ['maxEvents']) || !opaqueId(v.idempotencyKey))
|
|
87
|
+
throw invalid();
|
|
88
|
+
const limit = (n, maximum) => Number.isInteger(n) && n > 0 && n <= maximum;
|
|
89
|
+
if (!limit(v.limits.maxDurationMs, 86400000) || !limit(v.limits.maxOutputBytes, 67108864)
|
|
90
|
+
|| (Object.hasOwn(v.limits, 'maxEvents') && !limit(v.limits.maxEvents, 1000)))
|
|
91
|
+
throw invalid();
|
|
92
|
+
if (new TextEncoder().encode(JSON.stringify(v)).byteLength > 65536)
|
|
93
|
+
throw invalid();
|
|
94
|
+
return v;
|
|
95
|
+
}
|
|
96
|
+
/** Runner routes use the Genesis client's credential; the backend owns org/subject scoping. */
|
|
97
|
+
export function runnerModule(client) {
|
|
98
|
+
return Object.freeze({
|
|
99
|
+
permission: Object.freeze({
|
|
100
|
+
grant: (input, opts = {}) => client.request(RUNNER_SELF_GRANT_OPERATION, { body: input }, requestOptions(opts)),
|
|
101
|
+
}),
|
|
102
|
+
catalog: (opts = {}) => client.request('runner_getCatalog', undefined, requestOptions(opts)),
|
|
103
|
+
jobs: Object.freeze({
|
|
104
|
+
list: (opts = {}) => client.request('runner_listJobs', undefined, requestOptions(opts)),
|
|
105
|
+
start: (input, opts = {}) => client.request('runner_startJob', { body: checkedStartInput(input) }, requestOptions(opts)),
|
|
106
|
+
get: (jobId, opts = {}) => client.request('runner_getJob', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
107
|
+
events: (jobId, afterSeq = 0, opts = {}) => {
|
|
108
|
+
if (!Number.isSafeInteger(afterSeq) || afterSeq < 0)
|
|
109
|
+
throw invalid();
|
|
110
|
+
return client.request('runner_getJobEvents', { jobId: checkedJobId(jobId), afterSeq }, requestOptions(opts));
|
|
111
|
+
},
|
|
112
|
+
result: (jobId, opts = {}) => client.request('runner_getJobResult', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
113
|
+
cancel: (jobId, opts = {}) => client.request('runner_cancelJob', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
114
|
+
delete: (jobId, opts = {}) => client.request('runner_deleteJob', { jobId: checkedJobId(jobId) }, requestOptions(opts)),
|
|
115
|
+
}),
|
|
116
|
+
});
|
|
117
|
+
}
|
package/dist/scopes.d.ts
ADDED
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
import type { GenesisClient } from './client.js';
|
|
2
|
+
import type { OperationInput as In } from './types.js';
|
|
3
|
+
/** Scopes (work graph): projects, tasks, dependencies, assignments to agents or people, comments and activity.
|
|
4
|
+
* Scopes never runs agents; the assignee's runtime (Henry, Fleets or Flocks) does. Updates, archives and assignee
|
|
5
|
+
* changes take the `version` you read (sent as If-Match); a stale one is a 409. Archiving needs scopes:admin. */
|
|
6
|
+
export declare function scopesModule(client: GenesisClient): {
|
|
7
|
+
whoami: () => Promise<{
|
|
8
|
+
org: string;
|
|
9
|
+
principal: string;
|
|
10
|
+
kind: "api_key" | "m2m_token" | "bridge_session";
|
|
11
|
+
scopes: string[];
|
|
12
|
+
}>;
|
|
13
|
+
workload: (projectId?: string) => Promise<{
|
|
14
|
+
data: import("./index.js").components["schemas"]["Scopes.Workload"][];
|
|
15
|
+
}>;
|
|
16
|
+
projects: {
|
|
17
|
+
list: (filter?: In<"scopes_listProjects">) => Promise<{
|
|
18
|
+
data: import("./index.js").components["schemas"]["Scopes.Project"][];
|
|
19
|
+
}>;
|
|
20
|
+
get: (project: string) => Promise<{
|
|
21
|
+
id: string;
|
|
22
|
+
key: string;
|
|
23
|
+
name: string;
|
|
24
|
+
description: string | null;
|
|
25
|
+
status: import("./index.js").components["schemas"]["Scopes.ProjectStatus"];
|
|
26
|
+
auto_org_id: string | null;
|
|
27
|
+
lead: string | null;
|
|
28
|
+
target_on: string | null;
|
|
29
|
+
task_count: number;
|
|
30
|
+
open_count: number;
|
|
31
|
+
archived_at: string | null;
|
|
32
|
+
version: number;
|
|
33
|
+
created_at: string;
|
|
34
|
+
updated_at: string;
|
|
35
|
+
}>;
|
|
36
|
+
create: (body: In<"scopes_createProject">["body"]) => Promise<{
|
|
37
|
+
id: string;
|
|
38
|
+
key: string;
|
|
39
|
+
name: string;
|
|
40
|
+
description: string | null;
|
|
41
|
+
status: import("./index.js").components["schemas"]["Scopes.ProjectStatus"];
|
|
42
|
+
auto_org_id: string | null;
|
|
43
|
+
lead: string | null;
|
|
44
|
+
target_on: string | null;
|
|
45
|
+
task_count: number;
|
|
46
|
+
open_count: number;
|
|
47
|
+
archived_at: string | null;
|
|
48
|
+
version: number;
|
|
49
|
+
created_at: string;
|
|
50
|
+
updated_at: string;
|
|
51
|
+
}>;
|
|
52
|
+
update: (project: string, version: number | string, body: In<"scopes_updateProject">["body"]) => Promise<{
|
|
53
|
+
id: string;
|
|
54
|
+
key: string;
|
|
55
|
+
name: string;
|
|
56
|
+
description: string | null;
|
|
57
|
+
status: import("./index.js").components["schemas"]["Scopes.ProjectStatus"];
|
|
58
|
+
auto_org_id: string | null;
|
|
59
|
+
lead: string | null;
|
|
60
|
+
target_on: string | null;
|
|
61
|
+
task_count: number;
|
|
62
|
+
open_count: number;
|
|
63
|
+
archived_at: string | null;
|
|
64
|
+
version: number;
|
|
65
|
+
created_at: string;
|
|
66
|
+
updated_at: string;
|
|
67
|
+
}>;
|
|
68
|
+
archive: (project: string, version: number | string) => Promise<{
|
|
69
|
+
id: string;
|
|
70
|
+
key: string;
|
|
71
|
+
name: string;
|
|
72
|
+
description: string | null;
|
|
73
|
+
status: import("./index.js").components["schemas"]["Scopes.ProjectStatus"];
|
|
74
|
+
auto_org_id: string | null;
|
|
75
|
+
lead: string | null;
|
|
76
|
+
target_on: string | null;
|
|
77
|
+
task_count: number;
|
|
78
|
+
open_count: number;
|
|
79
|
+
archived_at: string | null;
|
|
80
|
+
version: number;
|
|
81
|
+
created_at: string;
|
|
82
|
+
updated_at: string;
|
|
83
|
+
}>;
|
|
84
|
+
graph: (project: string) => Promise<{
|
|
85
|
+
project: import("./index.js").components["schemas"]["Scopes.Project"];
|
|
86
|
+
tasks: import("./index.js").components["schemas"]["Scopes.Task"][];
|
|
87
|
+
edges: {
|
|
88
|
+
from: string;
|
|
89
|
+
to: string;
|
|
90
|
+
kind: import("./index.js").components["schemas"]["Scopes.DependencyKind"];
|
|
91
|
+
}[];
|
|
92
|
+
order: string[];
|
|
93
|
+
critical_path: string[];
|
|
94
|
+
}>;
|
|
95
|
+
ready: (project: string, unassigned?: boolean) => Promise<{
|
|
96
|
+
data: import("./index.js").components["schemas"]["Scopes.Task"][];
|
|
97
|
+
}>;
|
|
98
|
+
tasks: (project: string, filter?: Omit<In<"scopes_listProjectTasks">, "project">) => Promise<{
|
|
99
|
+
data: import("./index.js").components["schemas"]["Scopes.Task"][];
|
|
100
|
+
next_after: number | null;
|
|
101
|
+
}>;
|
|
102
|
+
createTask: (project: string, body: In<"scopes_createTask">["body"]) => Promise<{
|
|
103
|
+
id: string;
|
|
104
|
+
project_id: string;
|
|
105
|
+
number: number;
|
|
106
|
+
identifier: string;
|
|
107
|
+
title: string;
|
|
108
|
+
description: string | null;
|
|
109
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
110
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
111
|
+
estimate: number | null;
|
|
112
|
+
labels: string[];
|
|
113
|
+
parent_id: string | null;
|
|
114
|
+
due_on: string | null;
|
|
115
|
+
start_on: string | null;
|
|
116
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
117
|
+
assigned_at: string | null;
|
|
118
|
+
started_at: string | null;
|
|
119
|
+
completed_at: string | null;
|
|
120
|
+
canceled_at: string | null;
|
|
121
|
+
blocked: boolean;
|
|
122
|
+
archived_at: string | null;
|
|
123
|
+
version: number;
|
|
124
|
+
created_at: string;
|
|
125
|
+
updated_at: string;
|
|
126
|
+
}>;
|
|
127
|
+
activity: (project: string, p?: {
|
|
128
|
+
after?: number;
|
|
129
|
+
limit?: number;
|
|
130
|
+
}) => Promise<{
|
|
131
|
+
data: import("./index.js").components["schemas"]["Scopes.Event"][];
|
|
132
|
+
next_after: number | null;
|
|
133
|
+
}>;
|
|
134
|
+
};
|
|
135
|
+
tasks: {
|
|
136
|
+
list: (filter?: In<"scopes_listTasks">) => Promise<{
|
|
137
|
+
data: import("./index.js").components["schemas"]["Scopes.Task"][];
|
|
138
|
+
next_after: number | null;
|
|
139
|
+
}>;
|
|
140
|
+
get: (task: string) => Promise<{
|
|
141
|
+
id: string;
|
|
142
|
+
project_id: string;
|
|
143
|
+
number: number;
|
|
144
|
+
identifier: string;
|
|
145
|
+
title: string;
|
|
146
|
+
description: string | null;
|
|
147
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
148
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
149
|
+
estimate: number | null;
|
|
150
|
+
labels: string[];
|
|
151
|
+
parent_id: string | null;
|
|
152
|
+
due_on: string | null;
|
|
153
|
+
start_on: string | null;
|
|
154
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
155
|
+
assigned_at: string | null;
|
|
156
|
+
started_at: string | null;
|
|
157
|
+
completed_at: string | null;
|
|
158
|
+
canceled_at: string | null;
|
|
159
|
+
blocked: boolean;
|
|
160
|
+
archived_at: string | null;
|
|
161
|
+
version: number;
|
|
162
|
+
created_at: string;
|
|
163
|
+
updated_at: string;
|
|
164
|
+
}>;
|
|
165
|
+
update: (task: string, version: number | string, body: In<"scopes_updateTask">["body"]) => Promise<{
|
|
166
|
+
id: string;
|
|
167
|
+
project_id: string;
|
|
168
|
+
number: number;
|
|
169
|
+
identifier: string;
|
|
170
|
+
title: string;
|
|
171
|
+
description: string | null;
|
|
172
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
173
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
174
|
+
estimate: number | null;
|
|
175
|
+
labels: string[];
|
|
176
|
+
parent_id: string | null;
|
|
177
|
+
due_on: string | null;
|
|
178
|
+
start_on: string | null;
|
|
179
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
180
|
+
assigned_at: string | null;
|
|
181
|
+
started_at: string | null;
|
|
182
|
+
completed_at: string | null;
|
|
183
|
+
canceled_at: string | null;
|
|
184
|
+
blocked: boolean;
|
|
185
|
+
archived_at: string | null;
|
|
186
|
+
version: number;
|
|
187
|
+
created_at: string;
|
|
188
|
+
updated_at: string;
|
|
189
|
+
}>;
|
|
190
|
+
archive: (task: string, version: number | string) => Promise<{
|
|
191
|
+
id: string;
|
|
192
|
+
project_id: string;
|
|
193
|
+
number: number;
|
|
194
|
+
identifier: string;
|
|
195
|
+
title: string;
|
|
196
|
+
description: string | null;
|
|
197
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
198
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
199
|
+
estimate: number | null;
|
|
200
|
+
labels: string[];
|
|
201
|
+
parent_id: string | null;
|
|
202
|
+
due_on: string | null;
|
|
203
|
+
start_on: string | null;
|
|
204
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
205
|
+
assigned_at: string | null;
|
|
206
|
+
started_at: string | null;
|
|
207
|
+
completed_at: string | null;
|
|
208
|
+
canceled_at: string | null;
|
|
209
|
+
blocked: boolean;
|
|
210
|
+
archived_at: string | null;
|
|
211
|
+
version: number;
|
|
212
|
+
created_at: string;
|
|
213
|
+
updated_at: string;
|
|
214
|
+
}>;
|
|
215
|
+
assign: (task: string, version: number | string, body: In<"scopes_assignTask">["body"]) => Promise<{
|
|
216
|
+
id: string;
|
|
217
|
+
project_id: string;
|
|
218
|
+
number: number;
|
|
219
|
+
identifier: string;
|
|
220
|
+
title: string;
|
|
221
|
+
description: string | null;
|
|
222
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
223
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
224
|
+
estimate: number | null;
|
|
225
|
+
labels: string[];
|
|
226
|
+
parent_id: string | null;
|
|
227
|
+
due_on: string | null;
|
|
228
|
+
start_on: string | null;
|
|
229
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
230
|
+
assigned_at: string | null;
|
|
231
|
+
started_at: string | null;
|
|
232
|
+
completed_at: string | null;
|
|
233
|
+
canceled_at: string | null;
|
|
234
|
+
blocked: boolean;
|
|
235
|
+
archived_at: string | null;
|
|
236
|
+
version: number;
|
|
237
|
+
created_at: string;
|
|
238
|
+
updated_at: string;
|
|
239
|
+
}>;
|
|
240
|
+
unassign: (task: string, version: number | string) => Promise<{
|
|
241
|
+
id: string;
|
|
242
|
+
project_id: string;
|
|
243
|
+
number: number;
|
|
244
|
+
identifier: string;
|
|
245
|
+
title: string;
|
|
246
|
+
description: string | null;
|
|
247
|
+
status: import("./index.js").components["schemas"]["Scopes.TaskStatus"];
|
|
248
|
+
priority: import("./index.js").components["schemas"]["Scopes.Priority"];
|
|
249
|
+
estimate: number | null;
|
|
250
|
+
labels: string[];
|
|
251
|
+
parent_id: string | null;
|
|
252
|
+
due_on: string | null;
|
|
253
|
+
start_on: string | null;
|
|
254
|
+
assignee: import("./index.js").components["schemas"]["Scopes.Assignee"] | null;
|
|
255
|
+
assigned_at: string | null;
|
|
256
|
+
started_at: string | null;
|
|
257
|
+
completed_at: string | null;
|
|
258
|
+
canceled_at: string | null;
|
|
259
|
+
blocked: boolean;
|
|
260
|
+
archived_at: string | null;
|
|
261
|
+
version: number;
|
|
262
|
+
created_at: string;
|
|
263
|
+
updated_at: string;
|
|
264
|
+
}>;
|
|
265
|
+
assignments: (task: string) => Promise<{
|
|
266
|
+
data: import("./index.js").components["schemas"]["Scopes.Assignment"][];
|
|
267
|
+
}>;
|
|
268
|
+
dependencies: (task: string) => Promise<{
|
|
269
|
+
blocked_by: import("./index.js").components["schemas"]["Scopes.Dependency"][];
|
|
270
|
+
blocks: import("./index.js").components["schemas"]["Scopes.Dependency"][];
|
|
271
|
+
related: import("./index.js").components["schemas"]["Scopes.Dependency"][];
|
|
272
|
+
}>;
|
|
273
|
+
addDependency: (task: string, body: In<"scopes_addDependency">["body"]) => Promise<{
|
|
274
|
+
id: string;
|
|
275
|
+
task_id: string;
|
|
276
|
+
depends_on_id: string;
|
|
277
|
+
kind: import("./index.js").components["schemas"]["Scopes.DependencyKind"];
|
|
278
|
+
created_at: string;
|
|
279
|
+
created_by: string;
|
|
280
|
+
}>;
|
|
281
|
+
comments: (task: string) => Promise<{
|
|
282
|
+
data: import("./index.js").components["schemas"]["Scopes.Comment"][];
|
|
283
|
+
}>;
|
|
284
|
+
addComment: (task: string, body: In<"scopes_addComment">["body"]) => Promise<{
|
|
285
|
+
id: string;
|
|
286
|
+
task_id: string;
|
|
287
|
+
body: string;
|
|
288
|
+
author: string;
|
|
289
|
+
author_kind: string;
|
|
290
|
+
created_at: string;
|
|
291
|
+
}>;
|
|
292
|
+
activity: (task: string, p?: {
|
|
293
|
+
after?: number;
|
|
294
|
+
limit?: number;
|
|
295
|
+
}) => Promise<{
|
|
296
|
+
data: import("./index.js").components["schemas"]["Scopes.Event"][];
|
|
297
|
+
next_after: number | null;
|
|
298
|
+
}>;
|
|
299
|
+
};
|
|
300
|
+
dependencies: {
|
|
301
|
+
remove: (dependency: string) => Promise<{
|
|
302
|
+
id: string;
|
|
303
|
+
task_id: string;
|
|
304
|
+
depends_on_id: string;
|
|
305
|
+
kind: import("./index.js").components["schemas"]["Scopes.DependencyKind"];
|
|
306
|
+
created_at: string;
|
|
307
|
+
created_by: string;
|
|
308
|
+
}>;
|
|
309
|
+
};
|
|
310
|
+
};
|