@hasna/skills 0.5.11 → 0.6.1
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 +95 -53
- package/bin/index.js +17704 -30170
- package/bin/mcp.js +6856 -21003
- package/bin/migrate.js +108 -6
- package/bin/server.js +5827 -565
- package/bin/worker.js +489 -135
- package/dist/admin-contract.d.ts +13 -13
- package/dist/admin-contract.js +28 -47
- package/dist/cli/commands/agent-integration.d.ts +2 -0
- package/dist/cli/commands/context.d.ts +19 -0
- package/dist/cli/commands/install.d.ts +1 -0
- package/dist/cli/commands/profile-sync.d.ts +10 -0
- package/dist/cli/commands/profiles.d.ts +2 -0
- package/dist/cli/commands/runtime.d.ts +0 -3
- package/dist/cli/output.d.ts +2 -0
- package/dist/index.d.ts +5 -0
- package/dist/index.js +5406 -19111
- package/dist/lib/agent-integration.d.ts +74 -0
- package/dist/lib/cloud-executions.d.ts +39 -0
- package/dist/lib/managed-policy.d.ts +6 -0
- package/dist/lib/profile-admin.d.ts +4 -0
- package/dist/lib/profile-client.d.ts +19 -0
- package/dist/lib/read-access.d.ts +3 -23
- package/dist/lib/selected-document.d.ts +6 -0
- package/dist/lib/selected-run.d.ts +31 -0
- package/dist/lib/selection-cache.d.ts +40 -0
- package/dist/lib/selection-resolver.d.ts +75 -0
- package/dist/lib/skill-context.d.ts +43 -0
- package/dist/lib/skillinfo.d.ts +2 -0
- package/dist/sdk/execution/dispatchers/ecs.d.ts +8 -0
- package/dist/sdk/index.d.ts +2 -0
- package/dist/sdk/index.js +9911 -8305
- package/dist/server/app.d.ts +7 -1
- package/dist/server/artifact-storage.d.ts +7 -10
- package/dist/server/auth.d.ts +2 -0
- package/dist/server/config.d.ts +2 -0
- package/dist/server/profile-api.d.ts +3 -0
- package/dist/server/runtime-api.d.ts +31 -0
- package/dist/server/runtime-policy.d.ts +25 -0
- package/dist/server/runtime-store.d.ts +73 -0
- package/dist/server/runtime-worker.d.ts +19 -0
- package/dist/server/selection-store.d.ts +39 -0
- package/dist/server/sqlite-store.d.ts +2 -0
- package/dist/server/store.d.ts +3 -0
- package/dist/server/types.d.ts +3 -0
- package/dist/types/skill-selection.d.ts +41 -0
- package/migrations/postgres/0007_skill_profiles.sql +19 -0
- package/migrations/postgres/0008_skill_runtime.sql +14 -0
- package/migrations/sqlite/0007_skill_profiles.sql +19 -0
- package/migrations/sqlite/0008_skill_runtime.sql +14 -0
- package/package.json +1 -1
package/dist/server/app.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type GovernanceStore } from "../sdk/governance-store.js";
|
|
2
2
|
import { ArtifactStorage } from "./artifact-storage.js";
|
|
3
|
+
import { type RuntimeService } from "./runtime-api.js";
|
|
3
4
|
import { type SkillsServerConfig } from "./config.js";
|
|
4
5
|
import { type MemorySkillsStore } from "./store.js";
|
|
5
6
|
import { type SkillsProductStore } from "./types.js";
|
|
@@ -10,7 +11,12 @@ export interface SkillsServerOptions {
|
|
|
10
11
|
store?: SkillsProductStore;
|
|
11
12
|
/** Lifecycle ledger and ceiling reads for governance surfaces (cancellation). Defaults to the store's database. */
|
|
12
13
|
governanceStore?: GovernanceStore;
|
|
14
|
+
/** Inject a configured cloud runtime, or null to explicitly disable cloud execution. */
|
|
15
|
+
runtime?: RuntimeService | null;
|
|
13
16
|
}
|
|
17
|
+
export type SkillsFetchHandler = ((request: Request) => Promise<Response>) & {
|
|
18
|
+
close(): Promise<void>;
|
|
19
|
+
};
|
|
14
20
|
/**
|
|
15
21
|
* Refuse to serve traffic from storage that will not survive a restart.
|
|
16
22
|
*
|
|
@@ -28,7 +34,7 @@ export declare function assertDurableTarget(target: {
|
|
|
28
34
|
durable: boolean;
|
|
29
35
|
label: string;
|
|
30
36
|
}, config: Pick<SkillsServerConfig, "allowEphemeralStore">): void;
|
|
31
|
-
export declare function createSkillsFetchHandler(options?: SkillsServerOptions): Promise<
|
|
37
|
+
export declare function createSkillsFetchHandler(options?: SkillsServerOptions): Promise<SkillsFetchHandler>;
|
|
32
38
|
export declare function startSkillsServer(options?: SkillsServerOptions): Promise<Bun.Server<undefined>>;
|
|
33
39
|
/**
|
|
34
40
|
* Socket-level body ceiling, derived from the same setting the publish route enforces.
|
|
@@ -15,6 +15,8 @@ export interface S3ClientLike {
|
|
|
15
15
|
export interface ArtifactStorageOptions {
|
|
16
16
|
bucket?: string;
|
|
17
17
|
prefix?: string;
|
|
18
|
+
/** Separate expiring run outputs from durable bundle/version objects. Defaults to prefix for compatibility. */
|
|
19
|
+
runPrefix?: string;
|
|
18
20
|
region?: string;
|
|
19
21
|
/** Overrides the real S3 client (tests). Ignored when no bucket is configured. */
|
|
20
22
|
client?: S3ClientLike;
|
|
@@ -22,6 +24,7 @@ export interface ArtifactStorageOptions {
|
|
|
22
24
|
export declare class ArtifactStorage {
|
|
23
25
|
private bucket?;
|
|
24
26
|
private prefix;
|
|
27
|
+
private runPrefix;
|
|
25
28
|
private s3?;
|
|
26
29
|
constructor(options?: ArtifactStorageOptions);
|
|
27
30
|
get usesS3(): boolean;
|
|
@@ -114,16 +117,10 @@ export declare class ArtifactStorage {
|
|
|
114
117
|
* The content-addressed object under bundles/ stays the read path (dedupe); these keys
|
|
115
118
|
* are the durable, browsable history and are never deleted by orphan collection.
|
|
116
119
|
*
|
|
117
|
-
* RETENTION
|
|
118
|
-
*
|
|
119
|
-
*
|
|
120
|
-
*
|
|
121
|
-
* while `<prefix>/bundles/` (content-addressed, deduped across versions and slugs) is
|
|
122
|
-
* NEVER expired by lifecycle — only the reference-guarded delete path removes those,
|
|
123
|
-
* because one object can serve many versions. A busy org that pushes thousands of
|
|
124
|
-
* versions should pair the lifecycle rule with a documented cap on retained versions
|
|
125
|
-
* per slug (e.g. the newest K, pruned by a maintenance job that deletes the version row
|
|
126
|
-
* and its two objects together); row deletion alone would strand the objects.
|
|
120
|
+
* RETENTION: neither version history nor content-addressed bundles may share an
|
|
121
|
+
* expiring lifecycle prefix with run outputs. Configure runPrefix separately for
|
|
122
|
+
* ephemeral artifacts; retain this prefix until reference-aware maintenance removes
|
|
123
|
+
* the version rows and objects together. Existing persisted storage keys remain valid.
|
|
127
124
|
* Returns the placement recorded on the version row; in db mode nothing is written.
|
|
128
125
|
*/
|
|
129
126
|
putVersionObjects(orgId: string, slug: string, version: string, bytes: OwnedBytes, manifest: Record<string, unknown>, contentType?: string): Promise<{
|
package/dist/server/auth.d.ts
CHANGED
|
@@ -3,3 +3,5 @@ export declare function hashApiKey(token: string): string;
|
|
|
3
3
|
export declare function bearerToken(request: Request): string | null;
|
|
4
4
|
export declare function authenticateRequest(store: SkillsProductStore, request: Request): Promise<ApiPrincipal | null>;
|
|
5
5
|
export declare function publicPrincipal(partial?: Partial<ApiPrincipal>): ApiPrincipal;
|
|
6
|
+
/** Scope checks apply to the key, independently of its user's workspace role. */
|
|
7
|
+
export declare function permitsSkillsRoute(principal: ApiPrincipal, method: string, resource: string): boolean;
|
package/dist/server/config.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ export interface SkillsServerConfig {
|
|
|
7
7
|
seedBundledCorpus: boolean;
|
|
8
8
|
artifactBucket?: string;
|
|
9
9
|
artifactPrefix: string;
|
|
10
|
+
/** Optional expiring run-output namespace; immutable bundles retain artifactPrefix. */
|
|
11
|
+
runArtifactPrefix?: string;
|
|
10
12
|
inlineWorker: boolean;
|
|
11
13
|
/**
|
|
12
14
|
* HMAC key for signing served skill bundles. When set, the bundle endpoint adds
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
import type { ApiPrincipal, SkillsProductStore } from "./types.js";
|
|
2
|
+
import type { SkillsServerConfig } from "./config.js";
|
|
3
|
+
export declare function handleProfileApi(store: SkillsProductStore, principal: ApiPrincipal, request: Request, parts: string[], config: SkillsServerConfig): Promise<Response | null>;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ApiPrincipal, SkillsProductStore } from "./types.js";
|
|
2
|
+
import { ArtifactStorage } from "./artifact-storage.js";
|
|
3
|
+
import { RuntimeExecutionStore } from "./runtime-store.js";
|
|
4
|
+
import { EcsDispatcher, type EcsRunTaskClient } from "../sdk/execution/dispatchers/ecs.js";
|
|
5
|
+
import { type RuntimeConfig } from "./runtime-policy.js";
|
|
6
|
+
export interface RuntimeService {
|
|
7
|
+
config: RuntimeConfig;
|
|
8
|
+
signingKey: string;
|
|
9
|
+
store: RuntimeExecutionStore;
|
|
10
|
+
productStore: SkillsProductStore;
|
|
11
|
+
artifacts: ArtifactStorage;
|
|
12
|
+
dispatcher: EcsDispatcher;
|
|
13
|
+
close?: () => Promise<void>;
|
|
14
|
+
}
|
|
15
|
+
export declare function createRuntimeService(options: {
|
|
16
|
+
databaseUrl?: string;
|
|
17
|
+
productStore: SkillsProductStore;
|
|
18
|
+
artifacts?: ArtifactStorage;
|
|
19
|
+
env?: Record<string, string | undefined>;
|
|
20
|
+
executionStore?: RuntimeExecutionStore;
|
|
21
|
+
ecsClient?: EcsRunTaskClient;
|
|
22
|
+
}): Promise<RuntimeService | null>;
|
|
23
|
+
/** Called after normal bearer authentication. Dedicated paths avoid changing /runs. */
|
|
24
|
+
export declare function handleRuntimeApiRequest(request: Request, principal: ApiPrincipal, service: RuntimeService | null): Promise<Response | null>;
|
|
25
|
+
/** Worker-only route, before ordinary API-key auth. The token is bound to one
|
|
26
|
+
* run, attempt, generation and deadline; it cannot read the registry or another run. */
|
|
27
|
+
export declare function handleRuntimeWorkerRequest(request: Request, service: RuntimeService | null): Promise<Response | null>;
|
|
28
|
+
/** Replays persisted launch intents after an API restart and settles tasks that
|
|
29
|
+
* stop before they can send a completion. Lost launch observations remain
|
|
30
|
+
* unresolved: an empty eventual ECS listing must never cause a second launch. */
|
|
31
|
+
export declare function reconcileRuntimeJobs(service: RuntimeService): Promise<void>;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { EcsDispatcherConfig } from "../sdk/execution/dispatchers/ecs.js";
|
|
2
|
+
import type { FrozenAdmission, AttemptRecord } from "../sdk/execution/types.js";
|
|
3
|
+
export declare const RUNTIME_MAX_INPUT_BYTES = 100000;
|
|
4
|
+
export declare const RUNTIME_MAX_BUNDLE_BYTES = 1000000;
|
|
5
|
+
export declare const RUNTIME_MAX_ARTIFACT_BYTES = 2000000;
|
|
6
|
+
export declare const RUNTIME_MAX_LOG_BYTES = 32768;
|
|
7
|
+
export declare const RUNTIME_TIMEOUT_MS = 60000;
|
|
8
|
+
export interface RuntimeConfig extends EcsDispatcherConfig {
|
|
9
|
+
imageDigest: string;
|
|
10
|
+
apiOrigin: string;
|
|
11
|
+
/** Only independently reviewed exact bundles enter this first credential-free lane. */
|
|
12
|
+
reviewedBundles: {
|
|
13
|
+
slug: "pdf-generate";
|
|
14
|
+
version: string;
|
|
15
|
+
sha256: string;
|
|
16
|
+
}[];
|
|
17
|
+
}
|
|
18
|
+
export declare function readRuntimeConfig(env?: Record<string, string | undefined>): RuntimeConfig | null;
|
|
19
|
+
export declare function runtimeInput(value: unknown): {
|
|
20
|
+
content: string;
|
|
21
|
+
title?: string;
|
|
22
|
+
};
|
|
23
|
+
export declare function runtimeToken(key: string, admission: FrozenAdmission, attempt: AttemptRecord): string;
|
|
24
|
+
export declare function verifyRuntimeToken(token: string, key: string, admission: FrozenAdmission, attempt: AttemptRecord, now?: number): boolean;
|
|
25
|
+
export declare const hashBytes: (bytes: Uint8Array) => string;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import type { RunExecutionStore, CreateAttemptInput, ClaimAttemptInput, LaunchIntentResult } from "../sdk/execution/storage.js";
|
|
2
|
+
import type { FrozenAdmission, ExecutionRunRow, AttemptRecord, AttemptReceipt, RunTransitionRecord, ExecutionRunStatus, TerminalRunStatus, ClaimResult } from "../sdk/execution/types.js";
|
|
3
|
+
export interface RuntimeArtifact {
|
|
4
|
+
name: string;
|
|
5
|
+
contentType: string;
|
|
6
|
+
base64: string;
|
|
7
|
+
sha256: string;
|
|
8
|
+
byteSize: number;
|
|
9
|
+
}
|
|
10
|
+
export interface RuntimeResult {
|
|
11
|
+
exitCode: number;
|
|
12
|
+
stdout: string;
|
|
13
|
+
stderr: string;
|
|
14
|
+
artifacts: RuntimeArtifact[];
|
|
15
|
+
error?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface RuntimeJob {
|
|
18
|
+
execution: ExecutionRunRow;
|
|
19
|
+
attempts: AttemptRecord[];
|
|
20
|
+
receipts: AttemptReceipt[];
|
|
21
|
+
transitions: RunTransitionRecord[];
|
|
22
|
+
input?: {
|
|
23
|
+
content: string;
|
|
24
|
+
title?: string;
|
|
25
|
+
};
|
|
26
|
+
bundleBase64?: string;
|
|
27
|
+
result?: RuntimeResult;
|
|
28
|
+
}
|
|
29
|
+
/** Each mutation locks the complete execution aggregate. Cross-process claims,
|
|
30
|
+
* cancellation and receipts cannot interleave within one run. No process-local queue. */
|
|
31
|
+
export declare class RuntimeExecutionStore implements RunExecutionStore {
|
|
32
|
+
private sqlite?;
|
|
33
|
+
private postgres?;
|
|
34
|
+
readonly durable: boolean;
|
|
35
|
+
private constructor();
|
|
36
|
+
static open(databaseUrl?: string): Promise<RuntimeExecutionStore>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
job(runId: string): Promise<RuntimeJob | null>;
|
|
39
|
+
mutate<T>(id: string, fn: (job: RuntimeJob) => T): Promise<T | null>;
|
|
40
|
+
admit(admission: FrozenAdmission): Promise<ExecutionRunRow>;
|
|
41
|
+
activeJobs(limit?: number): Promise<RuntimeJob[]>;
|
|
42
|
+
getRun(id: string): Promise<ExecutionRunRow | null>;
|
|
43
|
+
getRunByKey(tenant: string, key: string): Promise<ExecutionRunRow | null>;
|
|
44
|
+
getRunByDigests(input: {
|
|
45
|
+
tenantId: string;
|
|
46
|
+
skillId: string;
|
|
47
|
+
skillVersion: string;
|
|
48
|
+
bundleDigest: string;
|
|
49
|
+
inputDigest: string;
|
|
50
|
+
}): Promise<ExecutionRunRow | null>;
|
|
51
|
+
listAttempts(id: string): Promise<AttemptRecord[]>;
|
|
52
|
+
createAttempt(input: CreateAttemptInput): Promise<AttemptRecord>;
|
|
53
|
+
claimAttempt(input: ClaimAttemptInput): Promise<ClaimResult>;
|
|
54
|
+
recordLaunchIntent(input: {
|
|
55
|
+
runId: string;
|
|
56
|
+
attemptId: string;
|
|
57
|
+
clientToken: string;
|
|
58
|
+
requestDigest: string;
|
|
59
|
+
startedBy: string;
|
|
60
|
+
}): Promise<LaunchIntentResult>;
|
|
61
|
+
recordLaunchState(input: {
|
|
62
|
+
runId: string;
|
|
63
|
+
attemptId: string;
|
|
64
|
+
launchState: AttemptRecord["launchState"];
|
|
65
|
+
taskId?: string | null;
|
|
66
|
+
}): Promise<AttemptRecord | null>;
|
|
67
|
+
recordTransition(t: RunTransitionRecord): Promise<void>;
|
|
68
|
+
markAttemptTerminal(id: string, attemptId: string): Promise<AttemptRecord | null>;
|
|
69
|
+
writeReceipt(receipt: AttemptReceipt): Promise<AttemptReceipt>;
|
|
70
|
+
getReceipt(id: string, attempt: string): Promise<AttemptReceipt | null>;
|
|
71
|
+
finalizeRun(id: string, status: TerminalRunStatus, receiptId: string): Promise<ExecutionRunRow | null>;
|
|
72
|
+
setRunStatus(id: string, status: ExecutionRunStatus): Promise<ExecutionRunRow | null>;
|
|
73
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env bun
|
|
2
|
+
import type { FrozenAdmission } from "../sdk/execution/types.js";
|
|
3
|
+
import type { RuntimeResult } from "./runtime-store.js";
|
|
4
|
+
export interface RuntimeWork {
|
|
5
|
+
admission: FrozenAdmission;
|
|
6
|
+
bundleBase64: string;
|
|
7
|
+
input: {
|
|
8
|
+
content: string;
|
|
9
|
+
title?: string;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface SupervisorOptions {
|
|
13
|
+
executable?: string;
|
|
14
|
+
dependenciesPath: string;
|
|
15
|
+
unprivileged?: boolean;
|
|
16
|
+
guardPath?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function executeRuntimeWork(work: RuntimeWork, options: SupervisorOptions): Promise<RuntimeResult>;
|
|
19
|
+
export declare function runRuntimeWorker(env?: Record<string, string | undefined>): Promise<void>;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import type { ApiPrincipal } from "./types.js";
|
|
3
|
+
import type { SkillProfile, SkillSelection, StationSkillState, StationSkillStateInput } from "../types/skill-selection.js";
|
|
4
|
+
export interface SkillSelectionStore {
|
|
5
|
+
getProfile(principal: ApiPrincipal, id: string): Promise<SkillProfile | null>;
|
|
6
|
+
/** null expected revision means create-only; null result means CAS conflict. */
|
|
7
|
+
saveProfile(principal: ApiPrincipal, id: string, selections: SkillSelection[], expected: string | null): Promise<SkillProfile | null>;
|
|
8
|
+
getStationState(principal: ApiPrincipal, id: string): Promise<StationSkillState | null>;
|
|
9
|
+
/** Refuses an obsolete profile revision atomically with storing the receipt. */
|
|
10
|
+
saveStationState(principal: ApiPrincipal, id: string, input: StationSkillStateInput): Promise<StationSkillState | null>;
|
|
11
|
+
}
|
|
12
|
+
type Row = Record<string, unknown>;
|
|
13
|
+
export declare class MemorySkillSelectionStore implements SkillSelectionStore {
|
|
14
|
+
private profiles;
|
|
15
|
+
private states;
|
|
16
|
+
private key;
|
|
17
|
+
getProfile(p: ApiPrincipal, id: string): Promise<SkillProfile | null>;
|
|
18
|
+
saveProfile(p: ApiPrincipal, id: string, selected: SkillSelection[], expected: string | null): Promise<SkillProfile | null>;
|
|
19
|
+
getStationState(p: ApiPrincipal, id: string): Promise<StationSkillState | null>;
|
|
20
|
+
saveStationState(p: ApiPrincipal, id: string, input: StationSkillStateInput): Promise<StationSkillState | null>;
|
|
21
|
+
}
|
|
22
|
+
export declare class SqliteSkillSelectionStore implements SkillSelectionStore {
|
|
23
|
+
private db;
|
|
24
|
+
constructor(db: Database);
|
|
25
|
+
getProfile(p: ApiPrincipal, id: string): Promise<SkillProfile | null>;
|
|
26
|
+
saveProfile(p: ApiPrincipal, id: string, selected: SkillSelection[], expected: string | null): Promise<SkillProfile | null>;
|
|
27
|
+
getStationState(p: ApiPrincipal, id: string): Promise<StationSkillState | null>;
|
|
28
|
+
saveStationState(p: ApiPrincipal, id: string, input: StationSkillStateInput): Promise<StationSkillState | null>;
|
|
29
|
+
}
|
|
30
|
+
type Sql = (strings: TemplateStringsArray, ...values: unknown[]) => Promise<Row[]>;
|
|
31
|
+
export declare class PostgresSkillSelectionStore implements SkillSelectionStore {
|
|
32
|
+
private sql;
|
|
33
|
+
constructor(sql: Sql);
|
|
34
|
+
getProfile(p: ApiPrincipal, id: string): Promise<SkillProfile | null>;
|
|
35
|
+
saveProfile(p: ApiPrincipal, id: string, selected: SkillSelection[], expected: string | null): Promise<SkillProfile | null>;
|
|
36
|
+
getStationState(p: ApiPrincipal, id: string): Promise<StationSkillState | null>;
|
|
37
|
+
saveStationState(p: ApiPrincipal, id: string, input: StationSkillStateInput): Promise<StationSkillState | null>;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
* requirement; changing Postgres behaviour is not this module's job.
|
|
14
14
|
*/
|
|
15
15
|
import { Database } from "bun:sqlite";
|
|
16
|
+
import { SqliteSkillSelectionStore } from "./selection-store.js";
|
|
16
17
|
import type { ApiPrincipal, ClaimRunInput, CreateRunInput, PublishSkillInput, RunTransitionPatch, ServerArtifact, ServerPin, ServerRunLog, ServerRunRecord, ServerSkillBundle, ServerSkillVersion, ServerSkillRecord, SkillsProductStore, StoreBackendInfo, UpdateSkillPatch } from "./types.js";
|
|
17
18
|
export interface SqliteStoreOptions {
|
|
18
19
|
/** Apply pending migrations on open. Default true - it is what makes zero-config work. */
|
|
@@ -30,6 +31,7 @@ export interface SqliteStoreOptions {
|
|
|
30
31
|
busyTimeoutMs?: number;
|
|
31
32
|
}
|
|
32
33
|
export declare class SqliteSkillsStore implements SkillsProductStore {
|
|
34
|
+
get selectionStore(): SqliteSkillSelectionStore;
|
|
33
35
|
readonly backend: StoreBackendInfo;
|
|
34
36
|
private db;
|
|
35
37
|
private closed;
|
package/dist/server/store.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { MemorySkillSelectionStore, PostgresSkillSelectionStore } from "./selection-store.js";
|
|
1
2
|
import type { ApiPrincipal, ClaimRunInput, CreateRunInput, PublishSkillInput, RunTransitionPatch, ServerArtifact, ServerPin, ServerRunLog, ServerRunRecord, ServerSkillBundle, ServerSkillRecord, ServerSkillVersion, SkillsProductStore, StoreBackendInfo, UpdateSkillPatch } from "./types.js";
|
|
2
3
|
import { type SqliteStoreOptions } from "./sqlite-store.js";
|
|
3
4
|
export declare function createArtifactId(): string;
|
|
@@ -23,6 +24,7 @@ export interface StoreOptions {
|
|
|
23
24
|
*/
|
|
24
25
|
export declare function createStore(options?: StoreOptions): Promise<SkillsProductStore>;
|
|
25
26
|
export declare class MemorySkillsStore implements SkillsProductStore {
|
|
27
|
+
readonly selectionStore: MemorySkillSelectionStore;
|
|
26
28
|
readonly backend: StoreBackendInfo;
|
|
27
29
|
private apiKeys;
|
|
28
30
|
private runs;
|
|
@@ -87,6 +89,7 @@ export declare class MemorySkillsStore implements SkillsProductStore {
|
|
|
87
89
|
private patchRun;
|
|
88
90
|
}
|
|
89
91
|
export declare class PostgresSkillsStore implements SkillsProductStore {
|
|
92
|
+
get selectionStore(): PostgresSkillSelectionStore;
|
|
90
93
|
readonly backend: StoreBackendInfo;
|
|
91
94
|
private sql;
|
|
92
95
|
constructor(databaseUrl: string);
|
package/dist/server/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { OwnedBytes } from "../lib/skill-bundle.js";
|
|
2
|
+
import type { SkillSelectionStore } from "./selection-store.js";
|
|
2
3
|
export declare const SERVER_RUN_STATUSES: readonly ["queued", "waiting_for_approval", "running", "succeeded", "failed", "cancel_requested", "cancelled", "retrying", "expired", "refunded"];
|
|
3
4
|
export type ServerRunStatus = (typeof SERVER_RUN_STATUSES)[number];
|
|
4
5
|
/**
|
|
@@ -297,6 +298,8 @@ export interface SkillsProductStore {
|
|
|
297
298
|
* actually being closed is our own default, which is now SQLite on disk.
|
|
298
299
|
*/
|
|
299
300
|
readonly backend?: StoreBackendInfo;
|
|
301
|
+
/** Optional for third-party stores; profile APIs fail closed when absent. */
|
|
302
|
+
readonly selectionStore?: SkillSelectionStore;
|
|
300
303
|
/** Release connections and file handles. Optional; not every backend holds any. */
|
|
301
304
|
close?(): Promise<void>;
|
|
302
305
|
/**
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/** Published selections are immutable references; credentials never define ownership. */
|
|
2
|
+
export interface SkillSelection {
|
|
3
|
+
slug: string;
|
|
4
|
+
version: string;
|
|
5
|
+
bundleDigest: string;
|
|
6
|
+
triggers?: {
|
|
7
|
+
keywords?: string[];
|
|
8
|
+
paths?: string[];
|
|
9
|
+
always?: boolean;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface SkillProfile {
|
|
13
|
+
id: string;
|
|
14
|
+
workspaceId: string;
|
|
15
|
+
revision: string;
|
|
16
|
+
selections: SkillSelection[];
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface ResolvedSkillSelection extends SkillSelection {
|
|
20
|
+
authority: string;
|
|
21
|
+
workspaceId: string;
|
|
22
|
+
profileRevision: string;
|
|
23
|
+
}
|
|
24
|
+
export interface ResolvedSkillProfile {
|
|
25
|
+
profileId: string;
|
|
26
|
+
workspaceId: string;
|
|
27
|
+
profileRevision: string;
|
|
28
|
+
authority: string;
|
|
29
|
+
selections: ResolvedSkillSelection[];
|
|
30
|
+
}
|
|
31
|
+
export interface StationSkillStateInput {
|
|
32
|
+
profileId: string;
|
|
33
|
+
profileRevision: string;
|
|
34
|
+
selections: SkillSelection[];
|
|
35
|
+
}
|
|
36
|
+
export interface StationSkillState extends StationSkillStateInput {
|
|
37
|
+
stationId: string;
|
|
38
|
+
workspaceId: string;
|
|
39
|
+
actorId: string;
|
|
40
|
+
appliedAt: string;
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Org predicates fence every read and mutation; there is no context-less worker writer.
|
|
2
|
+
CREATE TABLE IF NOT EXISTS skills_profiles (
|
|
3
|
+
org_id text NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
4
|
+
profile_id text NOT NULL,
|
|
5
|
+
revision text NOT NULL,
|
|
6
|
+
selections_json jsonb NOT NULL,
|
|
7
|
+
updated_at timestamptz NOT NULL,
|
|
8
|
+
PRIMARY KEY (org_id, profile_id)
|
|
9
|
+
);
|
|
10
|
+
CREATE TABLE IF NOT EXISTS skills_station_state (
|
|
11
|
+
org_id text NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
12
|
+
actor_id text NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
13
|
+
station_id text NOT NULL,
|
|
14
|
+
profile_id text NOT NULL,
|
|
15
|
+
profile_revision text NOT NULL,
|
|
16
|
+
selections_json jsonb NOT NULL,
|
|
17
|
+
applied_at timestamptz NOT NULL,
|
|
18
|
+
PRIMARY KEY (org_id, actor_id, station_id)
|
|
19
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS skills_runtime_jobs (
|
|
2
|
+
run_id TEXT PRIMARY KEY,
|
|
3
|
+
tenant_id TEXT NOT NULL,
|
|
4
|
+
idempotency_key TEXT NOT NULL,
|
|
5
|
+
skill_id TEXT NOT NULL,
|
|
6
|
+
skill_version TEXT NOT NULL,
|
|
7
|
+
bundle_digest TEXT NOT NULL,
|
|
8
|
+
input_digest TEXT NOT NULL,
|
|
9
|
+
status TEXT NOT NULL,
|
|
10
|
+
payload TEXT NOT NULL,
|
|
11
|
+
UNIQUE(tenant_id, idempotency_key)
|
|
12
|
+
);
|
|
13
|
+
CREATE INDEX IF NOT EXISTS skills_runtime_jobs_digests ON skills_runtime_jobs(tenant_id, skill_id, skill_version, bundle_digest, input_digest);
|
|
14
|
+
CREATE INDEX IF NOT EXISTS skills_runtime_jobs_active ON skills_runtime_jobs(tenant_id, status);
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
-- Desired selections belong to the workspace; receipts belong to stable actors/stations.
|
|
2
|
+
CREATE TABLE IF NOT EXISTS skills_profiles (
|
|
3
|
+
org_id text NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
4
|
+
profile_id text NOT NULL,
|
|
5
|
+
revision text NOT NULL,
|
|
6
|
+
selections_json text NOT NULL,
|
|
7
|
+
updated_at text NOT NULL,
|
|
8
|
+
PRIMARY KEY (org_id, profile_id)
|
|
9
|
+
);
|
|
10
|
+
CREATE TABLE IF NOT EXISTS skills_station_state (
|
|
11
|
+
org_id text NOT NULL REFERENCES organizations(id) ON DELETE CASCADE,
|
|
12
|
+
actor_id text NOT NULL REFERENCES users(id) ON DELETE CASCADE,
|
|
13
|
+
station_id text NOT NULL,
|
|
14
|
+
profile_id text NOT NULL,
|
|
15
|
+
profile_revision text NOT NULL,
|
|
16
|
+
selections_json text NOT NULL,
|
|
17
|
+
applied_at text NOT NULL,
|
|
18
|
+
PRIMARY KEY (org_id, actor_id, station_id)
|
|
19
|
+
);
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
CREATE TABLE IF NOT EXISTS skills_runtime_jobs (
|
|
2
|
+
run_id TEXT PRIMARY KEY,
|
|
3
|
+
tenant_id TEXT NOT NULL,
|
|
4
|
+
idempotency_key TEXT NOT NULL,
|
|
5
|
+
skill_id TEXT NOT NULL,
|
|
6
|
+
skill_version TEXT NOT NULL,
|
|
7
|
+
bundle_digest TEXT NOT NULL,
|
|
8
|
+
input_digest TEXT NOT NULL,
|
|
9
|
+
status TEXT NOT NULL,
|
|
10
|
+
payload TEXT NOT NULL,
|
|
11
|
+
UNIQUE(tenant_id, idempotency_key)
|
|
12
|
+
);
|
|
13
|
+
CREATE INDEX IF NOT EXISTS skills_runtime_jobs_digests ON skills_runtime_jobs(tenant_id, skill_id, skill_version, bundle_digest, input_digest);
|
|
14
|
+
CREATE INDEX IF NOT EXISTS skills_runtime_jobs_active ON skills_runtime_jobs(tenant_id, status);
|