@inhuman.tools/harness-provider-sdk 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +7 -0
- package/dist/auth.d.ts +11 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +2 -0
- package/dist/auth.js.map +1 -0
- package/dist/blobs.d.ts +13 -0
- package/dist/blobs.d.ts.map +1 -0
- package/dist/blobs.js +16 -0
- package/dist/blobs.js.map +1 -0
- package/dist/capabilities.d.ts +105 -0
- package/dist/capabilities.d.ts.map +1 -0
- package/dist/capabilities.js +32 -0
- package/dist/capabilities.js.map +1 -0
- package/dist/descriptor.d.ts +20 -0
- package/dist/descriptor.d.ts.map +1 -0
- package/dist/descriptor.js +39 -0
- package/dist/descriptor.js.map +1 -0
- package/dist/driver.d.ts +5 -0
- package/dist/driver.d.ts.map +1 -0
- package/dist/driver.js +9 -0
- package/dist/driver.js.map +1 -0
- package/dist/identity.d.ts +10 -0
- package/dist/identity.d.ts.map +1 -0
- package/dist/identity.js +11 -0
- package/dist/identity.js.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +3 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/parse.js +9 -0
- package/dist/parse.js.map +1 -0
- package/dist/registration.d.ts +24 -0
- package/dist/registration.d.ts.map +1 -0
- package/dist/registration.js +70 -0
- package/dist/registration.js.map +1 -0
- package/dist/schemas/index.d.ts +2 -0
- package/dist/schemas/index.d.ts.map +1 -0
- package/dist/schemas/index.js +2 -0
- package/dist/schemas/index.js.map +1 -0
- package/dist/schemas/provider.d.ts +178 -0
- package/dist/schemas/provider.d.ts.map +1 -0
- package/dist/schemas/provider.js +100 -0
- package/dist/schemas/provider.js.map +1 -0
- package/dist/visuals.d.ts +12 -0
- package/dist/visuals.d.ts.map +1 -0
- package/dist/visuals.js +15 -0
- package/dist/visuals.js.map +1 -0
- package/package.json +49 -3
- package/src/auth.ts +11 -0
- package/src/blobs.ts +21 -0
- package/src/capabilities.ts +127 -0
- package/src/descriptor.ts +69 -0
- package/src/driver.ts +12 -0
- package/src/identity.ts +14 -0
- package/src/index.ts +33 -0
- package/src/parse.ts +9 -0
- package/src/registration.ts +108 -0
- package/src/schemas/index.ts +1 -0
- package/src/schemas/provider.ts +121 -0
- package/src/visuals.ts +20 -0
- package/README.md +0 -3
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named Zod shapes for provider descriptors, driver rows, and capability
|
|
3
|
+
* request envelopes. Sole definition home for this package.
|
|
4
|
+
*/
|
|
5
|
+
import { CompletionExpectation } from "@inhuman.tools/harness-model";
|
|
6
|
+
import { type DriverConnectionClass } from "@inhuman.tools/plexus-expectations/driver";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export declare const PROVIDER_SDK_CONTRACT: 1;
|
|
9
|
+
export declare const CAPABILITY_KINDS: readonly ["completion", "mcp", "web-search", "web-extract"];
|
|
10
|
+
export declare const capabilityKindSchema: z.ZodEnum<{
|
|
11
|
+
completion: "completion";
|
|
12
|
+
mcp: "mcp";
|
|
13
|
+
"web-search": "web-search";
|
|
14
|
+
"web-extract": "web-extract";
|
|
15
|
+
}>;
|
|
16
|
+
export declare const multiplicitySchema: z.ZodEnum<{
|
|
17
|
+
"add-by-default": "add-by-default";
|
|
18
|
+
"add-as-secondary": "add-as-secondary";
|
|
19
|
+
}>;
|
|
20
|
+
export declare const driverDefinitionSchema: z.ZodPreprocess<z.ZodObject<{
|
|
21
|
+
name: z.ZodString;
|
|
22
|
+
description: z.ZodString;
|
|
23
|
+
abilityClaim: z.ZodArray<z.ZodEnum<{
|
|
24
|
+
completion: "completion";
|
|
25
|
+
mcp: "mcp";
|
|
26
|
+
"web-search": "web-search";
|
|
27
|
+
"web-extract": "web-extract";
|
|
28
|
+
}>>;
|
|
29
|
+
multiplicity: z.ZodEnum<{
|
|
30
|
+
"add-by-default": "add-by-default";
|
|
31
|
+
"add-as-secondary": "add-as-secondary";
|
|
32
|
+
}>;
|
|
33
|
+
importPath: z.ZodOptional<z.ZodString>;
|
|
34
|
+
}, z.core.$strip>>;
|
|
35
|
+
export declare const providerDescriptorSchema: z.ZodObject<{
|
|
36
|
+
id: z.ZodString;
|
|
37
|
+
name: z.ZodString;
|
|
38
|
+
description: z.ZodOptional<z.ZodString>;
|
|
39
|
+
contract: z.ZodLiteral<1>;
|
|
40
|
+
drivers: z.ZodArray<z.ZodPreprocess<z.ZodObject<{
|
|
41
|
+
name: z.ZodString;
|
|
42
|
+
description: z.ZodString;
|
|
43
|
+
abilityClaim: z.ZodArray<z.ZodEnum<{
|
|
44
|
+
completion: "completion";
|
|
45
|
+
mcp: "mcp";
|
|
46
|
+
"web-search": "web-search";
|
|
47
|
+
"web-extract": "web-extract";
|
|
48
|
+
}>>;
|
|
49
|
+
multiplicity: z.ZodEnum<{
|
|
50
|
+
"add-by-default": "add-by-default";
|
|
51
|
+
"add-as-secondary": "add-as-secondary";
|
|
52
|
+
}>;
|
|
53
|
+
importPath: z.ZodOptional<z.ZodString>;
|
|
54
|
+
}, z.core.$strip>>>;
|
|
55
|
+
}, z.core.$strip>;
|
|
56
|
+
export declare const driverConnectionClassSchema: z.ZodCustom<DriverConnectionClass, DriverConnectionClass>;
|
|
57
|
+
export declare const registeredDriverInputSchema: z.ZodObject<{
|
|
58
|
+
name: z.ZodString;
|
|
59
|
+
description: z.ZodString;
|
|
60
|
+
abilityClaim: z.ZodArray<z.ZodEnum<{
|
|
61
|
+
completion: "completion";
|
|
62
|
+
mcp: "mcp";
|
|
63
|
+
"web-search": "web-search";
|
|
64
|
+
"web-extract": "web-extract";
|
|
65
|
+
}>>;
|
|
66
|
+
multiplicity: z.ZodEnum<{
|
|
67
|
+
"add-by-default": "add-by-default";
|
|
68
|
+
"add-as-secondary": "add-as-secondary";
|
|
69
|
+
}>;
|
|
70
|
+
importPath: z.ZodOptional<z.ZodString>;
|
|
71
|
+
connection: z.ZodCustom<DriverConnectionClass, DriverConnectionClass>;
|
|
72
|
+
}, z.core.$strip>;
|
|
73
|
+
export declare const providerRegistrationSchema: z.ZodObject<{
|
|
74
|
+
id: z.ZodString;
|
|
75
|
+
name: z.ZodString;
|
|
76
|
+
description: z.ZodOptional<z.ZodString>;
|
|
77
|
+
contract: z.ZodLiteral<1>;
|
|
78
|
+
drivers: z.ZodArray<z.ZodObject<{
|
|
79
|
+
name: z.ZodString;
|
|
80
|
+
description: z.ZodString;
|
|
81
|
+
abilityClaim: z.ZodArray<z.ZodEnum<{
|
|
82
|
+
completion: "completion";
|
|
83
|
+
mcp: "mcp";
|
|
84
|
+
"web-search": "web-search";
|
|
85
|
+
"web-extract": "web-extract";
|
|
86
|
+
}>>;
|
|
87
|
+
multiplicity: z.ZodEnum<{
|
|
88
|
+
"add-by-default": "add-by-default";
|
|
89
|
+
"add-as-secondary": "add-as-secondary";
|
|
90
|
+
}>;
|
|
91
|
+
importPath: z.ZodOptional<z.ZodString>;
|
|
92
|
+
connection: z.ZodCustom<DriverConnectionClass, DriverConnectionClass>;
|
|
93
|
+
}, z.core.$strip>>;
|
|
94
|
+
}, z.core.$strip>;
|
|
95
|
+
export declare const completeRequestSchema: z.ZodObject<{
|
|
96
|
+
connectionId: z.ZodString;
|
|
97
|
+
model: z.ZodString;
|
|
98
|
+
promptText: z.ZodOptional<z.ZodString>;
|
|
99
|
+
messages: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
100
|
+
responseSchemaJson: z.ZodOptional<z.ZodString>;
|
|
101
|
+
systemNote: z.ZodOptional<z.ZodString>;
|
|
102
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
103
|
+
round: z.ZodCustom<CompletionExpectation, CompletionExpectation>;
|
|
104
|
+
}, z.core.$strip>;
|
|
105
|
+
export declare const mcpCallRequestSchema: z.ZodObject<{
|
|
106
|
+
connectionId: z.ZodString;
|
|
107
|
+
serverToolName: z.ZodString;
|
|
108
|
+
args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
109
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
110
|
+
onDispatch: z.ZodOptional<z.ZodCustom<() => void, () => void>>;
|
|
111
|
+
}, z.core.$strip>;
|
|
112
|
+
export declare const webSearchRequestSchema: z.ZodObject<{
|
|
113
|
+
connectionId: z.ZodString;
|
|
114
|
+
query: z.ZodString;
|
|
115
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
116
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
117
|
+
}, z.core.$strip>;
|
|
118
|
+
export declare const webExtractRequestSchema: z.ZodObject<{
|
|
119
|
+
connectionId: z.ZodString;
|
|
120
|
+
url: z.ZodString;
|
|
121
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
122
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
123
|
+
}, z.core.$strip>;
|
|
124
|
+
export declare const capabilityRequestSchema: z.ZodDiscriminatedUnion<[z.ZodObject<{
|
|
125
|
+
kind: z.ZodLiteral<"completion">;
|
|
126
|
+
request: z.ZodObject<{
|
|
127
|
+
connectionId: z.ZodString;
|
|
128
|
+
model: z.ZodString;
|
|
129
|
+
promptText: z.ZodOptional<z.ZodString>;
|
|
130
|
+
messages: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
131
|
+
responseSchemaJson: z.ZodOptional<z.ZodString>;
|
|
132
|
+
systemNote: z.ZodOptional<z.ZodString>;
|
|
133
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
134
|
+
round: z.ZodCustom<CompletionExpectation, CompletionExpectation>;
|
|
135
|
+
}, z.core.$strip>;
|
|
136
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
137
|
+
kind: z.ZodLiteral<"mcp">;
|
|
138
|
+
request: z.ZodObject<{
|
|
139
|
+
connectionId: z.ZodString;
|
|
140
|
+
serverToolName: z.ZodString;
|
|
141
|
+
args: z.ZodDefault<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
142
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
143
|
+
onDispatch: z.ZodOptional<z.ZodCustom<() => void, () => void>>;
|
|
144
|
+
}, z.core.$strip>;
|
|
145
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
146
|
+
kind: z.ZodLiteral<"web-search">;
|
|
147
|
+
request: z.ZodObject<{
|
|
148
|
+
connectionId: z.ZodString;
|
|
149
|
+
query: z.ZodString;
|
|
150
|
+
limit: z.ZodOptional<z.ZodNumber>;
|
|
151
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
152
|
+
}, z.core.$strip>;
|
|
153
|
+
}, z.core.$strip>, z.ZodObject<{
|
|
154
|
+
kind: z.ZodLiteral<"web-extract">;
|
|
155
|
+
request: z.ZodObject<{
|
|
156
|
+
connectionId: z.ZodString;
|
|
157
|
+
url: z.ZodString;
|
|
158
|
+
charLimit: z.ZodOptional<z.ZodNumber>;
|
|
159
|
+
signal: z.ZodOptional<z.ZodCustom<AbortSignal, AbortSignal>>;
|
|
160
|
+
}, z.core.$strip>;
|
|
161
|
+
}, z.core.$strip>], "kind">;
|
|
162
|
+
export declare const AUTH_INTERACTION_KINDS: readonly ["none", "login", "refresh", "logout"];
|
|
163
|
+
export declare const authInteractionKindSchema: z.ZodEnum<{
|
|
164
|
+
none: "none";
|
|
165
|
+
login: "login";
|
|
166
|
+
refresh: "refresh";
|
|
167
|
+
logout: "logout";
|
|
168
|
+
}>;
|
|
169
|
+
export declare const authInteractionSchema: z.ZodObject<{
|
|
170
|
+
kind: z.ZodEnum<{
|
|
171
|
+
none: "none";
|
|
172
|
+
login: "login";
|
|
173
|
+
refresh: "refresh";
|
|
174
|
+
logout: "logout";
|
|
175
|
+
}>;
|
|
176
|
+
connectionId: z.ZodString;
|
|
177
|
+
}, z.core.$strip>;
|
|
178
|
+
//# sourceMappingURL=provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/schemas/provider.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAA2B,KAAK,qBAAqB,EAAE,MAAM,2CAA2C,CAAC;AAChH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,eAAO,MAAM,qBAAqB,EAAG,CAAU,CAAC;AAEhD,eAAO,MAAM,gBAAgB,6DAA8D,CAAC;AAE5F,eAAO,MAAM,oBAAoB;;;;;EAA2B,CAAC;AAE7D,eAAO,MAAM,kBAAkB;;;EAAiD,CAAC;AAoBjF,eAAO,MAAM,sBAAsB;;;;;;;;;;;;;;kBAAyD,CAAC;AAE7F,eAAO,MAAM,wBAAwB;;;;;;;;;;;;;;;;;;;;iBAQnC,CAAC;AAEH,eAAO,MAAM,2BAA2B,2DAEtC,CAAC;AAEH,eAAO,MAAM,2BAA2B;;;;;;;;;;;;;;;iBAEtC,CAAC;AAEH,eAAO,MAAM,0BAA0B;;;;;;;;;;;;;;;;;;;;;iBAErC,CAAC;AAUH,eAAO,MAAM,qBAAqB;;;;;;;;;iBAShC,CAAC;AAEH,eAAO,MAAM,oBAAoB;;;;;gDAMf,IAAI,QAAJ,IAAI;iBAIpB,CAAC;AAEH,eAAO,MAAM,sBAAsB;;;;;iBAKjC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;iBAKlC,CAAC;AAEH,eAAO,MAAM,uBAAuB;;;;;;;;;;;;;;;;;;;oDApBlB,IAAI,QAAJ,IAAI;;;;;;;;;;;;;;;;;;2BA4BpB,CAAC;AAEH,eAAO,MAAM,sBAAsB,iDAAkD,CAAC;AAEtF,eAAO,MAAM,yBAAyB;;;;;EAAiC,CAAC;AAExE,eAAO,MAAM,qBAAqB;;;;;;;;iBAGhC,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Named Zod shapes for provider descriptors, driver rows, and capability
|
|
3
|
+
* request envelopes. Sole definition home for this package.
|
|
4
|
+
*/
|
|
5
|
+
import { CompletionExpectation } from "@inhuman.tools/harness-model";
|
|
6
|
+
import { isDriverConnectionClass } from "@inhuman.tools/plexus-expectations/driver";
|
|
7
|
+
import { z } from "zod";
|
|
8
|
+
export const PROVIDER_SDK_CONTRACT = 1;
|
|
9
|
+
export const CAPABILITY_KINDS = ["completion", "mcp", "web-search", "web-extract"];
|
|
10
|
+
export const capabilityKindSchema = z.enum(CAPABILITY_KINDS);
|
|
11
|
+
export const multiplicitySchema = z.enum(["add-by-default", "add-as-secondary"]);
|
|
12
|
+
const nonempty = z.string().trim().min(1, "non-empty string required");
|
|
13
|
+
const driverDefinitionObject = z.object({
|
|
14
|
+
name: nonempty,
|
|
15
|
+
description: nonempty,
|
|
16
|
+
abilityClaim: z.array(capabilityKindSchema).min(1, "driver abilityClaim must name at least one kind"),
|
|
17
|
+
multiplicity: multiplicitySchema,
|
|
18
|
+
importPath: nonempty.optional(),
|
|
19
|
+
});
|
|
20
|
+
function liftAbilityClaim(value) {
|
|
21
|
+
if (value != null && typeof value === "object" && "can" in value && !("abilityClaim" in value)) {
|
|
22
|
+
const { can, ...rest } = value;
|
|
23
|
+
return { ...rest, abilityClaim: can };
|
|
24
|
+
}
|
|
25
|
+
return value;
|
|
26
|
+
}
|
|
27
|
+
export const driverDefinitionSchema = z.preprocess(liftAbilityClaim, driverDefinitionObject);
|
|
28
|
+
export const providerDescriptorSchema = z.object({
|
|
29
|
+
id: nonempty,
|
|
30
|
+
name: nonempty,
|
|
31
|
+
description: z.string().optional(),
|
|
32
|
+
contract: z.literal(PROVIDER_SDK_CONTRACT, {
|
|
33
|
+
error: `contract is incompatible (supported: ${PROVIDER_SDK_CONTRACT})`,
|
|
34
|
+
}),
|
|
35
|
+
drivers: z.array(driverDefinitionSchema).min(1, "provider must declare at least one driver"),
|
|
36
|
+
});
|
|
37
|
+
export const driverConnectionClassSchema = z.custom((value) => isDriverConnectionClass(value), {
|
|
38
|
+
message: "PEW driver connection class required",
|
|
39
|
+
});
|
|
40
|
+
export const registeredDriverInputSchema = driverDefinitionObject.extend({
|
|
41
|
+
connection: driverConnectionClassSchema,
|
|
42
|
+
});
|
|
43
|
+
export const providerRegistrationSchema = providerDescriptorSchema.extend({
|
|
44
|
+
drivers: z.array(registeredDriverInputSchema).min(1, "provider must declare at least one driver"),
|
|
45
|
+
});
|
|
46
|
+
const abortSignal = z.custom((value) => value instanceof AbortSignal, {
|
|
47
|
+
message: "AbortSignal required",
|
|
48
|
+
});
|
|
49
|
+
const completionRound = z.custom((value) => value instanceof CompletionExpectation, {
|
|
50
|
+
message: "completion round required",
|
|
51
|
+
});
|
|
52
|
+
export const completeRequestSchema = z.object({
|
|
53
|
+
connectionId: nonempty,
|
|
54
|
+
model: z.string(),
|
|
55
|
+
promptText: z.string().optional(),
|
|
56
|
+
messages: z.array(z.unknown()).optional(),
|
|
57
|
+
responseSchemaJson: z.string().optional(),
|
|
58
|
+
systemNote: z.string().optional(),
|
|
59
|
+
signal: abortSignal.optional(),
|
|
60
|
+
round: completionRound,
|
|
61
|
+
});
|
|
62
|
+
export const mcpCallRequestSchema = z.object({
|
|
63
|
+
connectionId: nonempty,
|
|
64
|
+
serverToolName: nonempty,
|
|
65
|
+
args: z.record(z.string(), z.unknown()).default({}),
|
|
66
|
+
signal: abortSignal.optional(),
|
|
67
|
+
onDispatch: z
|
|
68
|
+
.custom((value) => typeof value === "function", {
|
|
69
|
+
message: "JS function required",
|
|
70
|
+
})
|
|
71
|
+
.optional(),
|
|
72
|
+
});
|
|
73
|
+
export const webSearchRequestSchema = z.object({
|
|
74
|
+
connectionId: nonempty,
|
|
75
|
+
query: nonempty,
|
|
76
|
+
limit: z.number().optional(),
|
|
77
|
+
signal: abortSignal.optional(),
|
|
78
|
+
});
|
|
79
|
+
export const webExtractRequestSchema = z.object({
|
|
80
|
+
connectionId: nonempty,
|
|
81
|
+
url: nonempty,
|
|
82
|
+
charLimit: z.number().optional(),
|
|
83
|
+
signal: abortSignal.optional(),
|
|
84
|
+
});
|
|
85
|
+
export const capabilityRequestSchema = z.discriminatedUnion("kind", [
|
|
86
|
+
z.object({ kind: z.literal("completion"), request: completeRequestSchema }),
|
|
87
|
+
z.object({ kind: z.literal("mcp"), request: mcpCallRequestSchema }),
|
|
88
|
+
z.object({ kind: z.literal("web-search"), request: webSearchRequestSchema }),
|
|
89
|
+
z.object({
|
|
90
|
+
kind: z.literal("web-extract"),
|
|
91
|
+
request: webExtractRequestSchema,
|
|
92
|
+
}),
|
|
93
|
+
]);
|
|
94
|
+
export const AUTH_INTERACTION_KINDS = ["none", "login", "refresh", "logout"];
|
|
95
|
+
export const authInteractionKindSchema = z.enum(AUTH_INTERACTION_KINDS);
|
|
96
|
+
export const authInteractionSchema = z.object({
|
|
97
|
+
kind: authInteractionKindSchema,
|
|
98
|
+
connectionId: nonempty,
|
|
99
|
+
});
|
|
100
|
+
//# sourceMappingURL=provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/schemas/provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read seam for stored pictures. The session's picture store belongs to the
|
|
3
|
+
* daemon; a provider that projects a turn onto its wire reads bytes through
|
|
4
|
+
* here and never imports the store.
|
|
5
|
+
*/
|
|
6
|
+
/** Bytes of one stored picture, or null when the id is unknown or unreadable. */
|
|
7
|
+
export type VisualReader = (sessionId: string, id: string) => Uint8Array | null;
|
|
8
|
+
/** The host that owns the store binds it once at boot. `null` unbinds. */
|
|
9
|
+
export declare function bindVisualReader(read: VisualReader | null): void;
|
|
10
|
+
/** Null while nothing is bound, so a wire projection names the picture as omitted. */
|
|
11
|
+
export declare function readVisual(sessionId: string, id: string): Uint8Array | null;
|
|
12
|
+
//# sourceMappingURL=visuals.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visuals.d.ts","sourceRoot":"","sources":["../src/visuals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,iFAAiF;AACjF,MAAM,MAAM,YAAY,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,UAAU,GAAG,IAAI,CAAC;AAIhF,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,YAAY,GAAG,IAAI,GAAG,IAAI,CAEhE;AAED,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,GAAG,IAAI,CAE3E"}
|
package/dist/visuals.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read seam for stored pictures. The session's picture store belongs to the
|
|
3
|
+
* daemon; a provider that projects a turn onto its wire reads bytes through
|
|
4
|
+
* here and never imports the store.
|
|
5
|
+
*/
|
|
6
|
+
let reader = null;
|
|
7
|
+
/** The host that owns the store binds it once at boot. `null` unbinds. */
|
|
8
|
+
export function bindVisualReader(read) {
|
|
9
|
+
reader = read;
|
|
10
|
+
}
|
|
11
|
+
/** Null while nothing is bound, so a wire projection names the picture as omitted. */
|
|
12
|
+
export function readVisual(sessionId, id) {
|
|
13
|
+
return reader === null ? null : reader(sessionId, id);
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=visuals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visuals.js","sourceRoot":"","sources":["../src/visuals.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAKH,IAAI,MAAM,GAAwB,IAAI,CAAC;AAEvC,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,IAAyB;IACxD,MAAM,GAAG,IAAI,CAAC;AAChB,CAAC;AAED,sFAAsF;AACtF,MAAM,UAAU,UAAU,CAAC,SAAiB,EAAE,EAAU;IACtD,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;AACxD,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,52 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inhuman.tools/harness-provider-sdk",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.2.0",
|
|
4
|
+
"description": "Driver-provider registration and capability contracts on top of PEW. No vendors, no plugin manifests.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js",
|
|
12
|
+
"default": "./dist/index.js"
|
|
13
|
+
}
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src",
|
|
18
|
+
"!**/__tests__"
|
|
19
|
+
],
|
|
20
|
+
"dependencies": {
|
|
21
|
+
"zod": "^4.4.3",
|
|
22
|
+
"@inhuman.tools/harness-model": "^0.2.0",
|
|
23
|
+
"@inhuman.tools/plexus-expectations": "^0.2.0"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"@types/node": "^24.0.0",
|
|
27
|
+
"eslint": "9.39.2",
|
|
28
|
+
"typescript": "6.0.2",
|
|
29
|
+
"vitest": "4.1.0",
|
|
30
|
+
"@-internal-/eslint-configs": "0.0.0"
|
|
31
|
+
},
|
|
32
|
+
"license": "MIT",
|
|
33
|
+
"repository": {
|
|
34
|
+
"type": "git",
|
|
35
|
+
"url": "git+https://github.com/here-build/inhuman-harness.git",
|
|
36
|
+
"directory": "packages/harness-provider-sdk"
|
|
37
|
+
},
|
|
38
|
+
"browserslist": [
|
|
39
|
+
"node >= 22"
|
|
40
|
+
],
|
|
41
|
+
"author": "Merkle Bonsai",
|
|
42
|
+
"publishConfig": {
|
|
43
|
+
"access": "public"
|
|
44
|
+
},
|
|
45
|
+
"scripts": {
|
|
46
|
+
"build": "tsc -p tsconfig.build.json",
|
|
47
|
+
"lint": "eslint .",
|
|
48
|
+
"lint:fix": "eslint . --fix",
|
|
49
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
50
|
+
"test": "tsc -p tsconfig.json --noEmit && vitest run"
|
|
51
|
+
}
|
|
6
52
|
}
|
package/src/auth.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth interaction shapes. OAuth/OIDC/PKCE live in provider-auth; adopt
|
|
3
|
+
* helpers stay with the connection registry (D3).
|
|
4
|
+
*/
|
|
5
|
+
import { AUTH_INTERACTION_KINDS } from "./schemas/provider.js";
|
|
6
|
+
|
|
7
|
+
export type AuthInteractionKind = (typeof AUTH_INTERACTION_KINDS)[number];
|
|
8
|
+
export type AuthInteraction = {
|
|
9
|
+
readonly kind: AuthInteractionKind;
|
|
10
|
+
readonly connectionId: string;
|
|
11
|
+
};
|
package/src/blobs.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read seam for stored blobs. The kernel's blob bucket belongs to the daemon;
|
|
3
|
+
* code that needs a blob's bytes (a provider projecting a wire, a recall tool)
|
|
4
|
+
* reads them through here and never imports the store. Keys are content hashes,
|
|
5
|
+
* so there is no session or id to pass: a hash a document names is the whole address.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/** Bytes of one stored blob, or null when the hash is unknown or unreadable. */
|
|
9
|
+
export type BlobReader = (sha256: string) => Uint8Array | null;
|
|
10
|
+
|
|
11
|
+
let reader: BlobReader | null = null;
|
|
12
|
+
|
|
13
|
+
/** The host that owns the bucket binds it once at boot. `null` unbinds. */
|
|
14
|
+
export function bindBlobReader(read: BlobReader | null): void {
|
|
15
|
+
reader = read;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/** Null while nothing is bound, so a caller falls back to the head the document kept. */
|
|
19
|
+
export function readBlob(sha256: string): Uint8Array | null {
|
|
20
|
+
return reader === null ? null : reader(sha256);
|
|
21
|
+
}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Known capability kinds and request/result envelopes.
|
|
3
|
+
*
|
|
4
|
+
* `can` on a driver is these short names (product law). PEW/model kinds stay
|
|
5
|
+
* the existing Expectation classes — v1 does not invent third-party wire kinds.
|
|
6
|
+
*/
|
|
7
|
+
import type {
|
|
8
|
+
CompletionExpectation,
|
|
9
|
+
CompletionMessage,
|
|
10
|
+
CompletionResult,
|
|
11
|
+
McpToolResult,
|
|
12
|
+
WebExtractResult,
|
|
13
|
+
WebSearchResult,
|
|
14
|
+
} from "@inhuman.tools/harness-model";
|
|
15
|
+
|
|
16
|
+
import { parseWith } from "./parse.js";
|
|
17
|
+
import { CAPABILITY_KINDS, capabilityKindSchema, capabilityRequestSchema } from "./schemas/provider.js";
|
|
18
|
+
|
|
19
|
+
export type CapabilityKind = (typeof CAPABILITY_KINDS)[number];
|
|
20
|
+
|
|
21
|
+
/** Sync tags of the harness-model PEW kinds each `can` token claims. */
|
|
22
|
+
export const CAPABILITY_EXPECTATION = {
|
|
23
|
+
completion: "harness:expectation:completion",
|
|
24
|
+
mcp: "harness:expectation:mcp-tool",
|
|
25
|
+
"web-search": "harness:expectation:web-search",
|
|
26
|
+
"web-extract": "harness:expectation:web-extract",
|
|
27
|
+
} as const satisfies Record<CapabilityKind, string>;
|
|
28
|
+
|
|
29
|
+
export const CAPABILITY_METHOD = {
|
|
30
|
+
completion: "complete",
|
|
31
|
+
mcp: "callTool",
|
|
32
|
+
"web-search": "webSearch",
|
|
33
|
+
"web-extract": "webExtract",
|
|
34
|
+
} as const satisfies Record<CapabilityKind, string>;
|
|
35
|
+
|
|
36
|
+
export function isCapabilityKind(value: unknown): value is CapabilityKind {
|
|
37
|
+
return capabilityKindSchema.safeParse(value).success;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export function parseCapabilityKind(value: unknown): CapabilityKind {
|
|
41
|
+
return parseWith(capabilityKindSchema, value);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export function admitCapability(can: readonly string[], kind: CapabilityKind): boolean {
|
|
45
|
+
return can.includes(kind);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type CompleteFields = {
|
|
49
|
+
readonly model: string;
|
|
50
|
+
readonly promptText?: string;
|
|
51
|
+
readonly messages?: CompletionMessage[];
|
|
52
|
+
readonly responseSchemaJson?: string;
|
|
53
|
+
readonly systemNote?: string;
|
|
54
|
+
readonly signal?: AbortSignal;
|
|
55
|
+
/** Required. Homed on a session plexus. Mutated in place. */
|
|
56
|
+
readonly round: CompletionExpectation;
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export type CompleteRequest = CompleteFields & {
|
|
60
|
+
readonly connectionId: string;
|
|
61
|
+
};
|
|
62
|
+
export type ConnectionCompleteRequest = CompleteFields;
|
|
63
|
+
export type CompleteResult = CompletionResult;
|
|
64
|
+
|
|
65
|
+
export type McpCallRequest = {
|
|
66
|
+
readonly connectionId: string;
|
|
67
|
+
readonly serverToolName: string;
|
|
68
|
+
readonly args: Record<string, unknown>;
|
|
69
|
+
readonly signal?: AbortSignal;
|
|
70
|
+
readonly onDispatch?: () => void;
|
|
71
|
+
};
|
|
72
|
+
export type ConnectionMcpCallRequest = Omit<McpCallRequest, "connectionId">;
|
|
73
|
+
export type McpCallResult = McpToolResult;
|
|
74
|
+
|
|
75
|
+
export type WebSearchRequest = {
|
|
76
|
+
readonly connectionId: string;
|
|
77
|
+
readonly query: string;
|
|
78
|
+
readonly limit?: number;
|
|
79
|
+
readonly signal?: AbortSignal;
|
|
80
|
+
};
|
|
81
|
+
export type ConnectionWebSearchRequest = Omit<WebSearchRequest, "connectionId">;
|
|
82
|
+
export type WebSearchCapabilityResult = WebSearchResult;
|
|
83
|
+
|
|
84
|
+
export type WebExtractRequest = {
|
|
85
|
+
readonly connectionId: string;
|
|
86
|
+
readonly url: string;
|
|
87
|
+
readonly charLimit?: number;
|
|
88
|
+
readonly signal?: AbortSignal;
|
|
89
|
+
};
|
|
90
|
+
export type ConnectionWebExtractRequest = Omit<WebExtractRequest, "connectionId">;
|
|
91
|
+
export type WebExtractCapabilityResult = WebExtractResult;
|
|
92
|
+
|
|
93
|
+
export type CapabilityRequest =
|
|
94
|
+
| { readonly kind: "completion"; readonly request: CompleteRequest }
|
|
95
|
+
| { readonly kind: "mcp"; readonly request: McpCallRequest }
|
|
96
|
+
| { readonly kind: "web-search"; readonly request: WebSearchRequest }
|
|
97
|
+
| { readonly kind: "web-extract"; readonly request: WebExtractRequest };
|
|
98
|
+
|
|
99
|
+
export type CapabilityResult =
|
|
100
|
+
| { readonly kind: "completion"; readonly result: CompleteResult }
|
|
101
|
+
| { readonly kind: "mcp"; readonly result: McpCallResult }
|
|
102
|
+
| { readonly kind: "web-search"; readonly result: WebSearchCapabilityResult }
|
|
103
|
+
| {
|
|
104
|
+
readonly kind: "web-extract";
|
|
105
|
+
readonly result: WebExtractCapabilityResult;
|
|
106
|
+
};
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Duck-typed interned connection face. Generic admission uses this, not a
|
|
110
|
+
* vendor `instanceof`.
|
|
111
|
+
*/
|
|
112
|
+
export type CapabilityConnection = {
|
|
113
|
+
readonly connectionId: string;
|
|
114
|
+
complete?(req: ConnectionCompleteRequest): Promise<CompleteResult>;
|
|
115
|
+
callTool?(req: ConnectionMcpCallRequest): Promise<McpCallResult>;
|
|
116
|
+
webSearch?(req: ConnectionWebSearchRequest): Promise<WebSearchCapabilityResult>;
|
|
117
|
+
webExtract?(req: ConnectionWebExtractRequest): Promise<WebExtractCapabilityResult>;
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
export function parseCapabilityRequest(value: unknown): CapabilityRequest {
|
|
121
|
+
return parseWith(capabilityRequestSchema, value) as CapabilityRequest;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export function connectionSupports(connection: CapabilityConnection, kind: CapabilityKind): boolean {
|
|
125
|
+
const method = CAPABILITY_METHOD[kind];
|
|
126
|
+
return typeof connection[method] === "function";
|
|
127
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import type { DriverMultiplicity } from "@inhuman.tools/plexus-expectations";
|
|
2
|
+
|
|
3
|
+
import type { CapabilityKind } from "./capabilities.js";
|
|
4
|
+
import { providerBrand, type ProviderSdkContract } from "./identity.js";
|
|
5
|
+
import { parseWith } from "./parse.js";
|
|
6
|
+
import { PROVIDER_SDK_CONTRACT } from "./schemas/index.js";
|
|
7
|
+
import { providerDescriptorSchema } from "./schemas/provider.js";
|
|
8
|
+
|
|
9
|
+
export type DriverDefinition = {
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly description: string;
|
|
12
|
+
readonly abilityClaim: readonly CapabilityKind[];
|
|
13
|
+
readonly multiplicity: DriverMultiplicity;
|
|
14
|
+
readonly importPath: string;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type ProviderDescriptor = {
|
|
18
|
+
readonly [providerBrand.descriptor]: true;
|
|
19
|
+
readonly id: string;
|
|
20
|
+
readonly name: string;
|
|
21
|
+
readonly description: string;
|
|
22
|
+
readonly contract: ProviderSdkContract;
|
|
23
|
+
readonly drivers: readonly DriverDefinition[];
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
function freezeDriver(row: {
|
|
27
|
+
name: string;
|
|
28
|
+
description: string;
|
|
29
|
+
abilityClaim: CapabilityKind[];
|
|
30
|
+
multiplicity: DriverMultiplicity;
|
|
31
|
+
importPath?: string;
|
|
32
|
+
}): DriverDefinition {
|
|
33
|
+
return Object.freeze({
|
|
34
|
+
name: row.name,
|
|
35
|
+
description: row.description,
|
|
36
|
+
abilityClaim: Object.freeze([...row.abilityClaim]),
|
|
37
|
+
multiplicity: row.multiplicity,
|
|
38
|
+
importPath: row.importPath ?? row.name,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function rejectDuplicateDrivers(drivers: readonly { name: string }[], context: string): void {
|
|
43
|
+
const seen = new Set<string>();
|
|
44
|
+
for (const driver of drivers) {
|
|
45
|
+
if (seen.has(driver.name)) throw new Error(`${context}: driver "${driver.name}" collides`);
|
|
46
|
+
seen.add(driver.name);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function parseProviderDescriptor(value: unknown): ProviderDescriptor {
|
|
51
|
+
const parsed = parseWith(providerDescriptorSchema, value);
|
|
52
|
+
rejectDuplicateDrivers(parsed.drivers, "provider-sdk");
|
|
53
|
+
return Object.freeze({
|
|
54
|
+
[providerBrand.descriptor]: true as const,
|
|
55
|
+
id: parsed.id,
|
|
56
|
+
name: parsed.name,
|
|
57
|
+
description: parsed.description ?? "",
|
|
58
|
+
contract: PROVIDER_SDK_CONTRACT,
|
|
59
|
+
drivers: Object.freeze(parsed.drivers.map(freezeDriver)),
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
export function isProviderDescriptor(value: unknown): value is ProviderDescriptor {
|
|
64
|
+
return (
|
|
65
|
+
typeof value === "object" &&
|
|
66
|
+
value !== null &&
|
|
67
|
+
(value as { [k: symbol]: unknown })[providerBrand.descriptor] === true
|
|
68
|
+
);
|
|
69
|
+
}
|
package/src/driver.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { DriverSpec } from "@inhuman.tools/plexus-expectations";
|
|
2
|
+
|
|
3
|
+
import type { DriverDefinition } from "./descriptor.js";
|
|
4
|
+
|
|
5
|
+
/** Declarations fill DriverSpec inventory. Process facts stay untouched. */
|
|
6
|
+
export function applyDriverDefinition(spec: DriverSpec, driver: DriverDefinition): void {
|
|
7
|
+
spec.name = driver.name;
|
|
8
|
+
spec.description = driver.description;
|
|
9
|
+
spec.importPath = driver.importPath;
|
|
10
|
+
spec.abilityClaim = [...driver.abilityClaim];
|
|
11
|
+
spec.multiplicity = driver.multiplicity;
|
|
12
|
+
}
|
package/src/identity.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { PROVIDER_SDK_CONTRACT } from "./schemas/provider.js";
|
|
2
|
+
|
|
3
|
+
/** Process-local brands. Not plugin-sdk InhumanPlugin and not a PEW kind. */
|
|
4
|
+
export const providerBrand = {
|
|
5
|
+
descriptor: Symbol.for("@inhuman.tools/harness-provider-sdk:descriptor"),
|
|
6
|
+
registration: Symbol.for("@inhuman.tools/harness-provider-sdk:registration"),
|
|
7
|
+
driver: Symbol.for("@inhuman.tools/harness-provider-sdk:driver"),
|
|
8
|
+
} as const;
|
|
9
|
+
|
|
10
|
+
export type ProviderSdkContract = typeof PROVIDER_SDK_CONTRACT;
|
|
11
|
+
|
|
12
|
+
export function isCompatibleContract(contract: unknown): contract is ProviderSdkContract {
|
|
13
|
+
return contract === PROVIDER_SDK_CONTRACT;
|
|
14
|
+
}
|