@valon-technologies/gestalt 0.0.1-alpha.18 → 0.0.1-alpha.19
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 +34 -12
- package/package.json +5 -3
- package/src/agent-conversions.ts +201 -0
- package/src/agent-manager.ts +272 -83
- package/src/agent.ts +1023 -224
- package/src/api.ts +42 -0
- package/src/auth.ts +3 -3
- package/src/authorization.ts +1700 -51
- package/src/cache.ts +3 -3
- package/src/catalog.ts +22 -0
- package/src/http-subject.ts +9 -2
- package/src/index.ts +191 -17
- package/src/indexeddb.ts +3 -15
- package/src/internal/gen/v1/agent_pb.ts +137 -51
- package/src/internal/gen/v1/authorization_pb.ts +505 -27
- package/src/internal/gen/v1/plugin_pb.ts +67 -21
- package/src/internal/gen/v1/pluginruntime_pb.ts +95 -6
- package/src/internal/gen/v1/workflow_pb.ts +344 -62
- package/src/invoker.ts +6 -35
- package/src/plugin.ts +12 -12
- package/src/pluginruntime.ts +337 -49
- package/src/protocol/v1.ts +19 -0
- package/src/protocol-internal.ts +19 -0
- package/src/protocol.ts +183 -0
- package/src/provider-kind.ts +7 -3
- package/src/provider.ts +21 -13
- package/src/runtime-log-host.ts +80 -52
- package/src/runtime.ts +67 -0
- package/src/s3.ts +13 -28
- package/src/secrets.ts +3 -3
- package/src/workflow-manager.ts +350 -121
- package/src/workflow.ts +2598 -389
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { JsonObject } from "@bufbuild/protobuf";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
jsonObjectFromStruct,
|
|
5
|
+
structFromObject,
|
|
6
|
+
type JsonObjectInput,
|
|
7
|
+
} from "./protocol.ts";
|
|
8
|
+
|
|
9
|
+
export function optionalStruct(
|
|
10
|
+
value?: JsonObjectInput | undefined,
|
|
11
|
+
): JsonObject | undefined {
|
|
12
|
+
return value === undefined ? undefined : structFromObject(value);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function optionalObjectFromStruct(
|
|
16
|
+
value?: JsonObject | undefined,
|
|
17
|
+
): JsonObjectInput | undefined {
|
|
18
|
+
return value === undefined ? undefined : jsonObjectFromStruct(value);
|
|
19
|
+
}
|
package/src/protocol.ts
ADDED
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
import {
|
|
2
|
+
create,
|
|
3
|
+
fromJson,
|
|
4
|
+
toJson,
|
|
5
|
+
type JsonObject,
|
|
6
|
+
type JsonValue,
|
|
7
|
+
} from "@bufbuild/protobuf";
|
|
8
|
+
import {
|
|
9
|
+
StructSchema,
|
|
10
|
+
TimestampSchema,
|
|
11
|
+
ValueSchema,
|
|
12
|
+
type Struct,
|
|
13
|
+
type Timestamp,
|
|
14
|
+
type Value,
|
|
15
|
+
} from "@bufbuild/protobuf/wkt";
|
|
16
|
+
|
|
17
|
+
const MIN_TIMESTAMP_SECONDS = -62_135_596_800n;
|
|
18
|
+
const MAX_TIMESTAMP_SECONDS = 253_402_300_799n;
|
|
19
|
+
const MIN_TIMESTAMP_SECONDS_NUMBER = Number(MIN_TIMESTAMP_SECONDS);
|
|
20
|
+
const MAX_TIMESTAMP_SECONDS_NUMBER = Number(MAX_TIMESTAMP_SECONDS);
|
|
21
|
+
|
|
22
|
+
/** Primitive values accepted in protobuf JSON payloads. */
|
|
23
|
+
export type JsonPrimitiveInput = null | boolean | number | string;
|
|
24
|
+
/** Native value accepted by SDK-owned protocol helpers before runtime validation. */
|
|
25
|
+
export type JsonInput = JsonPrimitiveInput | readonly unknown[] | object;
|
|
26
|
+
/** Native object accepted by SDK-owned Struct helpers before runtime validation. */
|
|
27
|
+
export type JsonObjectInput = object;
|
|
28
|
+
/** Alias for google.protobuf.Struct at protocol boundaries. */
|
|
29
|
+
export type { Struct };
|
|
30
|
+
/** Alias for google.protobuf.Value at protocol boundaries. */
|
|
31
|
+
export type { Value };
|
|
32
|
+
/** Alias for google.protobuf.Timestamp at protocol boundaries. */
|
|
33
|
+
export type { Timestamp };
|
|
34
|
+
|
|
35
|
+
/** Schema for google.protobuf.Struct. */
|
|
36
|
+
export { StructSchema };
|
|
37
|
+
/** Schema for google.protobuf.Value. */
|
|
38
|
+
export { ValueSchema };
|
|
39
|
+
/** Schema for google.protobuf.Timestamp. */
|
|
40
|
+
export { TimestampSchema };
|
|
41
|
+
|
|
42
|
+
/** Returns a protobuf Struct-compatible JSON object for generated message fields. */
|
|
43
|
+
export function structFromObject(value: JsonObjectInput = {}): JsonObject {
|
|
44
|
+
return normalizeJsonObject(value, "struct", new WeakSet<object>());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/** Returns a protobuf Struct-compatible JSON object for generated message fields. */
|
|
48
|
+
export function structFromJsonObject(value: JsonObject = {}): JsonObject {
|
|
49
|
+
return structFromObject(value);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/** Converts a protobuf Struct-compatible field value back to a JSON object. */
|
|
53
|
+
export function jsonObjectFromStruct(value?: JsonObject | undefined): JsonObject {
|
|
54
|
+
return value === undefined ? {} : { ...value };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/** Converts a JSON-compatible native value into a protobuf Value message. */
|
|
58
|
+
export function valueFromJson(value: JsonInput): Value {
|
|
59
|
+
return fromJson(ValueSchema, jsonFromInput(value));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/** Converts a protobuf Value message into its JSON value. */
|
|
63
|
+
export function jsonFromValue(value?: Value | undefined): JsonValue {
|
|
64
|
+
if (value === undefined) {
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
return toJson(ValueSchema, value);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Converts a valid JavaScript Date into a protobuf Timestamp message. */
|
|
71
|
+
export function timestampFromDate(value: Date): Timestamp {
|
|
72
|
+
const millis = value.getTime();
|
|
73
|
+
if (Number.isNaN(millis)) {
|
|
74
|
+
throw new TypeError("timestampFromDate expects a valid Date");
|
|
75
|
+
}
|
|
76
|
+
const seconds = Math.floor(millis / 1000);
|
|
77
|
+
if (
|
|
78
|
+
seconds < MIN_TIMESTAMP_SECONDS_NUMBER ||
|
|
79
|
+
seconds > MAX_TIMESTAMP_SECONDS_NUMBER
|
|
80
|
+
) {
|
|
81
|
+
throw new RangeError("Date is outside the protobuf Timestamp range");
|
|
82
|
+
}
|
|
83
|
+
const nanos = Math.trunc((millis - (seconds * 1000)) * 1_000_000);
|
|
84
|
+
return create(TimestampSchema, {
|
|
85
|
+
seconds: BigInt(seconds),
|
|
86
|
+
nanos,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/** Converts a protobuf Timestamp message into a JavaScript Date. */
|
|
91
|
+
export function dateFromTimestamp(value: Timestamp): Date {
|
|
92
|
+
if (value.nanos < 0 || value.nanos >= 1_000_000_000) {
|
|
93
|
+
throw new RangeError("protobuf Timestamp nanos out of range");
|
|
94
|
+
}
|
|
95
|
+
if (
|
|
96
|
+
value.seconds < MIN_TIMESTAMP_SECONDS ||
|
|
97
|
+
value.seconds > MAX_TIMESTAMP_SECONDS
|
|
98
|
+
) {
|
|
99
|
+
throw new RangeError("protobuf Timestamp seconds out of range");
|
|
100
|
+
}
|
|
101
|
+
const millis =
|
|
102
|
+
(Number(value.seconds) * 1000) + Math.trunc(value.nanos / 1_000_000);
|
|
103
|
+
const date = new Date(millis);
|
|
104
|
+
if (Number.isNaN(date.getTime())) {
|
|
105
|
+
throw new RangeError("protobuf Timestamp seconds out of range");
|
|
106
|
+
}
|
|
107
|
+
return date;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/** Returns a protobuf-compatible JSON value from native SDK input. */
|
|
111
|
+
export function jsonFromInput(value: JsonInput): JsonValue {
|
|
112
|
+
return normalizeJsonValue(value, "value", new WeakSet<object>());
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function normalizeJsonObject(
|
|
116
|
+
value: unknown,
|
|
117
|
+
path: string,
|
|
118
|
+
seen: WeakSet<object>,
|
|
119
|
+
): JsonObject {
|
|
120
|
+
if (!isPlainObject(value)) {
|
|
121
|
+
throw new TypeError(`${path} must be a plain JSON object`);
|
|
122
|
+
}
|
|
123
|
+
if (seen.has(value)) {
|
|
124
|
+
throw new TypeError(`${path} contains a cycle`);
|
|
125
|
+
}
|
|
126
|
+
seen.add(value);
|
|
127
|
+
try {
|
|
128
|
+
const output: JsonObject = {};
|
|
129
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
130
|
+
if (typeof key !== "string") {
|
|
131
|
+
throw new TypeError(`${path} keys must be strings`);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
for (const [key, entry] of Object.entries(value)) {
|
|
135
|
+
output[key] = normalizeJsonValue(entry, `${path}.${key}`, seen);
|
|
136
|
+
}
|
|
137
|
+
return output;
|
|
138
|
+
} finally {
|
|
139
|
+
seen.delete(value);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function normalizeJsonValue(
|
|
144
|
+
value: unknown,
|
|
145
|
+
path: string,
|
|
146
|
+
seen: WeakSet<object>,
|
|
147
|
+
): JsonValue {
|
|
148
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") {
|
|
149
|
+
return value;
|
|
150
|
+
}
|
|
151
|
+
if (typeof value === "number") {
|
|
152
|
+
if (!Number.isFinite(value)) {
|
|
153
|
+
throw new TypeError(`${path} must be a finite number`);
|
|
154
|
+
}
|
|
155
|
+
return value;
|
|
156
|
+
}
|
|
157
|
+
if (typeof value === "undefined") {
|
|
158
|
+
throw new TypeError(`${path} must not be undefined`);
|
|
159
|
+
}
|
|
160
|
+
if (typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") {
|
|
161
|
+
throw new TypeError(`${path} must be JSON-compatible`);
|
|
162
|
+
}
|
|
163
|
+
if (Array.isArray(value)) {
|
|
164
|
+
if (seen.has(value)) {
|
|
165
|
+
throw new TypeError(`${path} contains a cycle`);
|
|
166
|
+
}
|
|
167
|
+
seen.add(value);
|
|
168
|
+
try {
|
|
169
|
+
return value.map((entry, index) => normalizeJsonValue(entry, `${path}[${index}]`, seen));
|
|
170
|
+
} finally {
|
|
171
|
+
seen.delete(value);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return normalizeJsonObject(value, path, seen);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isPlainObject(value: unknown): value is Record<string, unknown> {
|
|
178
|
+
if (value === null || typeof value !== "object") {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const prototype = Object.getPrototypeOf(value);
|
|
182
|
+
return prototype === Object.prototype || prototype === null;
|
|
183
|
+
}
|
package/src/provider-kind.ts
CHANGED
|
@@ -20,6 +20,12 @@ const PROVIDER_KIND_DEFINITIONS = {
|
|
|
20
20
|
defaultExportNames: ["authentication", "provider"],
|
|
21
21
|
label: "authentication provider",
|
|
22
22
|
},
|
|
23
|
+
authorization: {
|
|
24
|
+
tokens: ["authorization", "authz"],
|
|
25
|
+
formatToken: "authorization",
|
|
26
|
+
defaultExportNames: ["authorization", "provider"],
|
|
27
|
+
label: "authorization provider",
|
|
28
|
+
},
|
|
23
29
|
cache: {
|
|
24
30
|
tokens: ["cache"],
|
|
25
31
|
formatToken: "cache",
|
|
@@ -72,9 +78,7 @@ const EXTERNAL_PROVIDER_KIND_TOKEN_SET = new Set<string>(
|
|
|
72
78
|
|
|
73
79
|
const EXTERNAL_PROVIDER_KIND_MAP = new Map<string, ProviderKind>(
|
|
74
80
|
Object.entries(PROVIDER_KIND_DEFINITIONS).flatMap(([kind, definition]) =>
|
|
75
|
-
definition.tokens.map(
|
|
76
|
-
(token) => [token, kind as ProviderKind] as const,
|
|
77
|
-
),
|
|
81
|
+
definition.tokens.map((token) => [token, kind as ProviderKind] as const),
|
|
78
82
|
),
|
|
79
83
|
);
|
|
80
84
|
|
package/src/provider.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type { MaybePromise } from "./api.ts";
|
|
|
6
6
|
export type ProviderKind =
|
|
7
7
|
| "integration"
|
|
8
8
|
| "authentication"
|
|
9
|
+
| "authorization"
|
|
9
10
|
| "cache"
|
|
10
11
|
| "secrets"
|
|
11
12
|
| "s3"
|
|
@@ -55,9 +56,9 @@ export type StartHandler = () => MaybePromise<void>;
|
|
|
55
56
|
export type CloseHandler = () => MaybePromise<void>;
|
|
56
57
|
|
|
57
58
|
/**
|
|
58
|
-
* Shared
|
|
59
|
+
* Shared provider metadata and lifecycle hooks for authored providers.
|
|
59
60
|
*/
|
|
60
|
-
export interface
|
|
61
|
+
export interface ProviderBaseOptions {
|
|
61
62
|
name?: string;
|
|
62
63
|
displayName?: string;
|
|
63
64
|
description?: string;
|
|
@@ -72,7 +73,7 @@ export interface RuntimeProviderOptions {
|
|
|
72
73
|
/**
|
|
73
74
|
* Base class shared by all TypeScript SDK provider implementations.
|
|
74
75
|
*/
|
|
75
|
-
export abstract class
|
|
76
|
+
export abstract class ProviderBase {
|
|
76
77
|
abstract readonly kind: ProviderKind;
|
|
77
78
|
|
|
78
79
|
name: string;
|
|
@@ -86,7 +87,7 @@ export abstract class RuntimeProvider {
|
|
|
86
87
|
private readonly startHandler: StartHandler | undefined;
|
|
87
88
|
private readonly closeHandler: CloseHandler | undefined;
|
|
88
89
|
|
|
89
|
-
protected constructor(options:
|
|
90
|
+
protected constructor(options: ProviderBaseOptions) {
|
|
90
91
|
this.name = slugName(options.name ?? "");
|
|
91
92
|
this.displayName = options.displayName?.trim() ?? "";
|
|
92
93
|
this.description = options.description?.trim() ?? "";
|
|
@@ -106,7 +107,7 @@ export abstract class RuntimeProvider {
|
|
|
106
107
|
}
|
|
107
108
|
}
|
|
108
109
|
|
|
109
|
-
|
|
110
|
+
providerMetadata(): ProviderMetadata {
|
|
110
111
|
const metadata: ProviderMetadata = {
|
|
111
112
|
kind: this.kind,
|
|
112
113
|
};
|
|
@@ -125,7 +126,10 @@ export abstract class RuntimeProvider {
|
|
|
125
126
|
return metadata;
|
|
126
127
|
}
|
|
127
128
|
|
|
128
|
-
async configureProvider(
|
|
129
|
+
async configureProvider(
|
|
130
|
+
name: string,
|
|
131
|
+
config: Record<string, unknown>,
|
|
132
|
+
): Promise<void> {
|
|
129
133
|
await this.configureHandler?.(name, config);
|
|
130
134
|
}
|
|
131
135
|
|
|
@@ -157,28 +161,32 @@ export abstract class RuntimeProvider {
|
|
|
157
161
|
}
|
|
158
162
|
|
|
159
163
|
/**
|
|
160
|
-
*
|
|
164
|
+
* Type guard for values that implement the provider base contract.
|
|
161
165
|
*/
|
|
162
|
-
export function
|
|
166
|
+
export function isProviderBase(value: unknown): value is ProviderBase {
|
|
163
167
|
return (
|
|
164
|
-
value instanceof
|
|
168
|
+
value instanceof ProviderBase ||
|
|
165
169
|
(typeof value === "object" &&
|
|
166
170
|
value !== null &&
|
|
167
171
|
"kind" in value &&
|
|
168
172
|
"resolveName" in value &&
|
|
169
173
|
typeof (value as { resolveName?: unknown }).resolveName === "function" &&
|
|
170
174
|
"configureProvider" in value &&
|
|
171
|
-
typeof (value as { configureProvider?: unknown }).configureProvider ===
|
|
175
|
+
typeof (value as { configureProvider?: unknown }).configureProvider ===
|
|
176
|
+
"function" &&
|
|
172
177
|
"supportsHealthCheck" in value &&
|
|
173
|
-
typeof (value as { supportsHealthCheck?: unknown })
|
|
178
|
+
typeof (value as { supportsHealthCheck?: unknown })
|
|
179
|
+
.supportsHealthCheck === "function" &&
|
|
174
180
|
"healthCheck" in value &&
|
|
175
181
|
typeof (value as { healthCheck?: unknown }).healthCheck === "function" &&
|
|
176
182
|
"startProvider" in value &&
|
|
177
|
-
typeof (value as { startProvider?: unknown }).startProvider ===
|
|
183
|
+
typeof (value as { startProvider?: unknown }).startProvider ===
|
|
184
|
+
"function" &&
|
|
178
185
|
"warnings" in value &&
|
|
179
186
|
typeof (value as { warnings?: unknown }).warnings === "function" &&
|
|
180
187
|
"closeProvider" in value &&
|
|
181
|
-
typeof (value as { closeProvider?: unknown }).closeProvider ===
|
|
188
|
+
typeof (value as { closeProvider?: unknown }).closeProvider ===
|
|
189
|
+
"function")
|
|
182
190
|
);
|
|
183
191
|
}
|
|
184
192
|
|
package/src/runtime-log-host.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { connect } from "node:net";
|
|
2
2
|
import { Writable } from "node:stream";
|
|
3
3
|
|
|
4
|
-
import type { MessageInitShape } from "@bufbuild/protobuf";
|
|
5
4
|
import {
|
|
6
5
|
createClient,
|
|
7
6
|
type Client,
|
|
@@ -10,11 +9,10 @@ import {
|
|
|
10
9
|
import { createGrpcTransport } from "@connectrpc/connect-node";
|
|
11
10
|
|
|
12
11
|
import {
|
|
13
|
-
AppendPluginRuntimeLogsRequestSchema,
|
|
14
|
-
type AppendPluginRuntimeLogsResponse,
|
|
15
12
|
PluginRuntimeLogHost as PluginRuntimeLogHostService,
|
|
16
|
-
PluginRuntimeLogStream,
|
|
13
|
+
PluginRuntimeLogStream as ProtoPluginRuntimeLogStream,
|
|
17
14
|
} from "./internal/gen/v1/pluginruntime_pb.ts";
|
|
15
|
+
import { timestampFromDate } from "./protocol.ts";
|
|
18
16
|
|
|
19
17
|
/** Environment variable containing the runtime-log host-service target. */
|
|
20
18
|
export const ENV_RUNTIME_LOG_HOST_SOCKET = "GESTALT_RUNTIME_LOG_SOCKET";
|
|
@@ -28,16 +26,8 @@ const RUNTIME_LOG_RELAY_TOKEN_HEADER = "x-gestalt-host-service-relay-token";
|
|
|
28
26
|
|
|
29
27
|
/** Named runtime log streams accepted by the authored SDK. */
|
|
30
28
|
export type RuntimeLogStreamName = "stdout" | "stderr" | "runtime";
|
|
31
|
-
/** Runtime log stream input
|
|
32
|
-
export type RuntimeLogStreamInput =
|
|
33
|
-
| RuntimeLogStreamName
|
|
34
|
-
| PluginRuntimeLogStream;
|
|
35
|
-
/** Shape accepted by `RuntimeLogHost.appendLogs`. */
|
|
36
|
-
export type RuntimeLogAppendLogsInput = MessageInitShape<
|
|
37
|
-
typeof AppendPluginRuntimeLogsRequestSchema
|
|
38
|
-
>;
|
|
39
|
-
/** Response message returned after appending runtime logs. */
|
|
40
|
-
export type RuntimeLogAppendResponseMessage = AppendPluginRuntimeLogsResponse;
|
|
29
|
+
/** Runtime log stream input accepted by authored APIs. */
|
|
30
|
+
export type RuntimeLogStreamInput = RuntimeLogStreamName;
|
|
41
31
|
|
|
42
32
|
/** One runtime log entry to append through `RuntimeLogHost.append`. */
|
|
43
33
|
export interface RuntimeLogAppendInput {
|
|
@@ -53,6 +43,20 @@ export interface RuntimeLogAppendInput {
|
|
|
53
43
|
sourceSeq?: number | bigint;
|
|
54
44
|
}
|
|
55
45
|
|
|
46
|
+
/** Batch of runtime log entries to append through `RuntimeLogHost.appendLogs`. */
|
|
47
|
+
export interface RuntimeLogAppendLogsInput {
|
|
48
|
+
/** Runtime session id. Defaults to `GESTALT_RUNTIME_SESSION_ID`. */
|
|
49
|
+
sessionId?: string | undefined;
|
|
50
|
+
/** Log entries to append. */
|
|
51
|
+
logs: readonly RuntimeLogAppendInput[];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Response returned after appending runtime logs. */
|
|
55
|
+
export interface RuntimeLogAppendResponse {
|
|
56
|
+
/** Last source sequence accepted by the host. */
|
|
57
|
+
lastSeq: bigint;
|
|
58
|
+
}
|
|
59
|
+
|
|
56
60
|
/** Options for the `Writable` returned by `RuntimeLogHost.writer`. */
|
|
57
61
|
export interface RuntimeLogWriterOptions {
|
|
58
62
|
/** Runtime session id. Defaults to `GESTALT_RUNTIME_SESSION_ID`. */
|
|
@@ -66,8 +70,8 @@ export interface RuntimeLogWriterOptions {
|
|
|
66
70
|
/**
|
|
67
71
|
* Client for appending plugin-runtime logs to the host.
|
|
68
72
|
*
|
|
69
|
-
* Use `append` for a single entry, `appendLogs` for a
|
|
70
|
-
*
|
|
73
|
+
* Use `append` for a single entry, `appendLogs` for a native batch, or `writer`
|
|
74
|
+
* to bridge Node streams into the runtime log host.
|
|
71
75
|
*/
|
|
72
76
|
export class RuntimeLogHost {
|
|
73
77
|
private readonly client: Client<typeof PluginRuntimeLogHostService>;
|
|
@@ -102,31 +106,23 @@ export class RuntimeLogHost {
|
|
|
102
106
|
|
|
103
107
|
async appendLogs(
|
|
104
108
|
request: RuntimeLogAppendLogsInput,
|
|
105
|
-
): Promise<
|
|
106
|
-
|
|
109
|
+
): Promise<RuntimeLogAppendResponse> {
|
|
110
|
+
const sessionId = runtimeLogBatchSessionId(request);
|
|
111
|
+
return runtimeLogAppendResponseFromProto(
|
|
112
|
+
await this.client.appendLogs({
|
|
113
|
+
sessionId,
|
|
114
|
+
logs: request.logs.map((log) => this.runtimeLogEntryToProto(log)),
|
|
115
|
+
}),
|
|
116
|
+
);
|
|
107
117
|
}
|
|
108
118
|
|
|
109
119
|
/** Appends one runtime log entry. */
|
|
110
120
|
async append(
|
|
111
121
|
input: RuntimeLogAppendInput,
|
|
112
|
-
): Promise<
|
|
113
|
-
const sourceSeq =
|
|
114
|
-
input.sourceSeq === undefined
|
|
115
|
-
? (this.sourceSeq += 1n)
|
|
116
|
-
: BigInt(input.sourceSeq);
|
|
117
|
-
if (sourceSeq > this.sourceSeq) {
|
|
118
|
-
this.sourceSeq = sourceSeq;
|
|
119
|
-
}
|
|
122
|
+
): Promise<RuntimeLogAppendResponse> {
|
|
120
123
|
return await this.appendLogs({
|
|
121
|
-
sessionId:
|
|
122
|
-
logs: [
|
|
123
|
-
{
|
|
124
|
-
stream: runtimeLogStream(input.stream ?? "runtime"),
|
|
125
|
-
message: runtimeLogMessage(input.message),
|
|
126
|
-
observedAt: toProtoTimestamp(input.observedAt ?? new Date()),
|
|
127
|
-
sourceSeq,
|
|
128
|
-
},
|
|
129
|
-
],
|
|
124
|
+
sessionId: input.sessionId,
|
|
125
|
+
logs: [input],
|
|
130
126
|
});
|
|
131
127
|
}
|
|
132
128
|
|
|
@@ -171,6 +167,22 @@ export class RuntimeLogHost {
|
|
|
171
167
|
},
|
|
172
168
|
});
|
|
173
169
|
}
|
|
170
|
+
|
|
171
|
+
private runtimeLogEntryToProto(input: RuntimeLogAppendInput) {
|
|
172
|
+
const sourceSeq =
|
|
173
|
+
input.sourceSeq === undefined
|
|
174
|
+
? (this.sourceSeq += 1n)
|
|
175
|
+
: BigInt(input.sourceSeq);
|
|
176
|
+
if (sourceSeq > this.sourceSeq) {
|
|
177
|
+
this.sourceSeq = sourceSeq;
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
stream: runtimeLogStream(input.stream ?? "runtime"),
|
|
181
|
+
message: runtimeLogMessage(input.message),
|
|
182
|
+
observedAt: timestampFromDate(input.observedAt ?? new Date()),
|
|
183
|
+
sourceSeq,
|
|
184
|
+
};
|
|
185
|
+
}
|
|
174
186
|
}
|
|
175
187
|
|
|
176
188
|
function runtimeSessionId(sessionId?: string): string {
|
|
@@ -181,6 +193,27 @@ function runtimeSessionId(sessionId?: string): string {
|
|
|
181
193
|
return value;
|
|
182
194
|
}
|
|
183
195
|
|
|
196
|
+
function runtimeLogBatchSessionId(request: RuntimeLogAppendLogsInput): string {
|
|
197
|
+
const explicitSessionIds = new Set<string>();
|
|
198
|
+
addRuntimeLogSessionId(explicitSessionIds, request.sessionId);
|
|
199
|
+
for (const log of request.logs) {
|
|
200
|
+
addRuntimeLogSessionId(explicitSessionIds, log.sessionId);
|
|
201
|
+
}
|
|
202
|
+
if (explicitSessionIds.size > 1) {
|
|
203
|
+
throw new Error("runtime log host: appendLogs entries must use one session id");
|
|
204
|
+
}
|
|
205
|
+
return runtimeSessionId(
|
|
206
|
+
request.sessionId ?? request.logs.find((log) => log.sessionId)?.sessionId,
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function addRuntimeLogSessionId(values: Set<string>, sessionId?: string): void {
|
|
211
|
+
const value = sessionId?.trim();
|
|
212
|
+
if (value) {
|
|
213
|
+
values.add(value);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
|
|
184
217
|
function runtimeLogTransportOptions(rawTarget: string): {
|
|
185
218
|
baseUrl: string;
|
|
186
219
|
nodeOptions?: { path: string };
|
|
@@ -232,17 +265,22 @@ function runtimeLogRelayTokenInterceptor(token: string): Interceptor {
|
|
|
232
265
|
};
|
|
233
266
|
}
|
|
234
267
|
|
|
235
|
-
function
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
}
|
|
268
|
+
function runtimeLogAppendResponseFromProto(
|
|
269
|
+
response: { lastSeq: bigint },
|
|
270
|
+
): RuntimeLogAppendResponse {
|
|
271
|
+
return { lastSeq: response.lastSeq };
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function runtimeLogStream(
|
|
275
|
+
stream: RuntimeLogStreamInput,
|
|
276
|
+
): ProtoPluginRuntimeLogStream {
|
|
239
277
|
switch (stream.trim().toLowerCase()) {
|
|
240
278
|
case "stdout":
|
|
241
|
-
return
|
|
279
|
+
return ProtoPluginRuntimeLogStream.STDOUT;
|
|
242
280
|
case "stderr":
|
|
243
|
-
return
|
|
281
|
+
return ProtoPluginRuntimeLogStream.STDERR;
|
|
244
282
|
case "runtime":
|
|
245
|
-
return
|
|
283
|
+
return ProtoPluginRuntimeLogStream.RUNTIME;
|
|
246
284
|
default:
|
|
247
285
|
throw new Error(`unsupported runtime log stream ${JSON.stringify(stream)}`);
|
|
248
286
|
}
|
|
@@ -255,16 +293,6 @@ function runtimeLogMessage(message: string | Uint8Array): string {
|
|
|
255
293
|
return Buffer.from(message).toString("utf8");
|
|
256
294
|
}
|
|
257
295
|
|
|
258
|
-
function toProtoTimestamp(value: Date): { seconds: bigint; nanos: number } {
|
|
259
|
-
const millis = value.getTime();
|
|
260
|
-
const seconds = Math.floor(millis / 1000);
|
|
261
|
-
const nanos = Math.trunc((millis - (seconds * 1000)) * 1_000_000);
|
|
262
|
-
return {
|
|
263
|
-
seconds: BigInt(seconds),
|
|
264
|
-
nanos,
|
|
265
|
-
};
|
|
266
|
-
}
|
|
267
|
-
|
|
268
296
|
function toError(error: unknown): Error {
|
|
269
297
|
return error instanceof Error ? error : new Error(String(error));
|
|
270
298
|
}
|
package/src/runtime.ts
CHANGED
|
@@ -25,6 +25,7 @@ import {
|
|
|
25
25
|
type CompleteLoginRequest as AuthCompleteLoginRequest,
|
|
26
26
|
type ValidateExternalTokenRequest,
|
|
27
27
|
} from "./internal/gen/v1/authentication_pb.ts";
|
|
28
|
+
import { AuthorizationProvider as AuthorizationProviderService } from "./internal/gen/v1/authorization_pb.ts";
|
|
28
29
|
import {
|
|
29
30
|
Cache as CacheService,
|
|
30
31
|
CacheDeleteManyResponseSchema,
|
|
@@ -45,6 +46,7 @@ import {
|
|
|
45
46
|
CatalogSchema as ProtoCatalogSchema,
|
|
46
47
|
ConnectionMode as ProviderConnectionMode,
|
|
47
48
|
GetSessionCatalogResponseSchema,
|
|
49
|
+
OperationAnnotationsSchema as ProtoOperationAnnotationsSchema,
|
|
48
50
|
PostConnectResponseSchema,
|
|
49
51
|
ResolveHTTPSubjectResponseSchema,
|
|
50
52
|
OperationResultSchema,
|
|
@@ -84,9 +86,15 @@ import {
|
|
|
84
86
|
isAuthenticationProvider,
|
|
85
87
|
type AuthenticatedUser,
|
|
86
88
|
} from "./auth.ts";
|
|
89
|
+
import {
|
|
90
|
+
AuthorizationProvider,
|
|
91
|
+
createAuthorizationProviderService,
|
|
92
|
+
isAuthorizationProvider,
|
|
93
|
+
} from "./authorization.ts";
|
|
87
94
|
import { CacheProvider, isCacheProvider } from "./cache.ts";
|
|
88
95
|
import { SecretsProvider, isSecretsProvider } from "./secrets.ts";
|
|
89
96
|
import { catalogToYaml, type Catalog } from "./catalog.ts";
|
|
97
|
+
import { valueFromJson, type JsonInput } from "./protocol.ts";
|
|
90
98
|
import {
|
|
91
99
|
HTTPSubjectResolutionError,
|
|
92
100
|
type HTTPSubjectRequest,
|
|
@@ -145,6 +153,7 @@ export const CURRENT_PROTOCOL_VERSION = 3;
|
|
|
145
153
|
*/
|
|
146
154
|
export const USAGE = "usage: bun run runtime.ts ROOT PROVIDER_TARGET";
|
|
147
155
|
export { createAgentProviderService } from "./agent.ts";
|
|
156
|
+
export { createAuthorizationProviderService } from "./authorization.ts";
|
|
148
157
|
export { createPluginRuntimeProviderService } from "./pluginruntime.ts";
|
|
149
158
|
export { createWorkflowProviderService } from "./workflow.ts";
|
|
150
159
|
|
|
@@ -162,6 +171,7 @@ export type RuntimeArgs = {
|
|
|
162
171
|
export type LoadedProvider =
|
|
163
172
|
| PluginProvider
|
|
164
173
|
| AuthenticationProvider
|
|
174
|
+
| AuthorizationProvider
|
|
165
175
|
| CacheProvider
|
|
166
176
|
| SecretsProvider
|
|
167
177
|
| S3Provider
|
|
@@ -199,6 +209,18 @@ const PROVIDER_RUNTIME_ENTRIES: Partial<
|
|
|
199
209
|
);
|
|
200
210
|
},
|
|
201
211
|
},
|
|
212
|
+
authorization: {
|
|
213
|
+
isProvider: isAuthorizationProvider as (
|
|
214
|
+
value: unknown,
|
|
215
|
+
) => value is LoadedProvider,
|
|
216
|
+
protoKind: ProtoProviderKind.AUTHORIZATION,
|
|
217
|
+
registerService(router, provider) {
|
|
218
|
+
router.service(
|
|
219
|
+
AuthorizationProviderService,
|
|
220
|
+
createAuthorizationProviderService(provider as AuthorizationProvider),
|
|
221
|
+
);
|
|
222
|
+
},
|
|
223
|
+
},
|
|
202
224
|
cache: {
|
|
203
225
|
isProvider: isCacheProvider as (value: unknown) => value is LoadedProvider,
|
|
204
226
|
protoKind: ProtoProviderKind.CACHE,
|
|
@@ -596,6 +618,7 @@ export function createProviderService(
|
|
|
596
618
|
kind: subject.kind,
|
|
597
619
|
displayName: subject.displayName,
|
|
598
620
|
authSource: subject.authSource,
|
|
621
|
+
email: subject.email ?? "",
|
|
599
622
|
},
|
|
600
623
|
}
|
|
601
624
|
: {});
|
|
@@ -822,6 +845,9 @@ function providerRequest(
|
|
|
822
845
|
idempotencyKey = "",
|
|
823
846
|
): Request {
|
|
824
847
|
const subject = requestContext?.subject;
|
|
848
|
+
const agentSubject = requestContext?.agentSubject;
|
|
849
|
+
const externalIdentity = requestContext?.externalIdentity;
|
|
850
|
+
const agentExternalIdentity = requestContext?.agentExternalIdentity;
|
|
825
851
|
const credential = requestContext?.credential;
|
|
826
852
|
const access = requestContext?.access;
|
|
827
853
|
const host = requestContext?.host;
|
|
@@ -835,6 +861,22 @@ function providerRequest(
|
|
|
835
861
|
kind: subject?.kind ?? "",
|
|
836
862
|
displayName: subject?.displayName ?? "",
|
|
837
863
|
authSource: subject?.authSource ?? "",
|
|
864
|
+
email: subject?.email ?? "",
|
|
865
|
+
},
|
|
866
|
+
agentSubject: {
|
|
867
|
+
id: agentSubject?.id ?? "",
|
|
868
|
+
kind: agentSubject?.kind ?? "",
|
|
869
|
+
displayName: agentSubject?.displayName ?? "",
|
|
870
|
+
authSource: agentSubject?.authSource ?? "",
|
|
871
|
+
email: agentSubject?.email ?? "",
|
|
872
|
+
},
|
|
873
|
+
externalIdentity: {
|
|
874
|
+
type: externalIdentity?.type ?? "",
|
|
875
|
+
id: externalIdentity?.id ?? "",
|
|
876
|
+
},
|
|
877
|
+
agentExternalIdentity: {
|
|
878
|
+
type: agentExternalIdentity?.type ?? "",
|
|
879
|
+
id: agentExternalIdentity?.id ?? "",
|
|
838
880
|
},
|
|
839
881
|
credential: {
|
|
840
882
|
mode: credential?.mode ?? "",
|
|
@@ -982,8 +1024,20 @@ function catalogToProto(catalog: Catalog | Record<string, unknown>) {
|
|
|
982
1024
|
method: op.method,
|
|
983
1025
|
title: op.title ?? "",
|
|
984
1026
|
description: op.description ?? "",
|
|
1027
|
+
inputSchema: catalogSchemaToWire(op.inputSchema),
|
|
1028
|
+
outputSchema: catalogSchemaToWire(op.outputSchema),
|
|
1029
|
+
annotations: op.annotations
|
|
1030
|
+
? create(ProtoOperationAnnotationsSchema, {
|
|
1031
|
+
readOnlyHint: op.annotations.readOnlyHint,
|
|
1032
|
+
idempotentHint: op.annotations.idempotentHint,
|
|
1033
|
+
destructiveHint: op.annotations.destructiveHint,
|
|
1034
|
+
openWorldHint: op.annotations.openWorldHint,
|
|
1035
|
+
})
|
|
1036
|
+
: undefined,
|
|
1037
|
+
requiredScopes: op.requiredScopes ?? [],
|
|
985
1038
|
tags: op.tags ?? [],
|
|
986
1039
|
readOnly: op.readOnly ?? false,
|
|
1040
|
+
transport: op.transport ?? "",
|
|
987
1041
|
allowedRoles: op.allowedRoles ?? [],
|
|
988
1042
|
parameters: (op.parameters ?? []).map((p) =>
|
|
989
1043
|
create(ProtoCatalogParameterSchema, {
|
|
@@ -991,6 +1045,9 @@ function catalogToProto(catalog: Catalog | Record<string, unknown>) {
|
|
|
991
1045
|
type: p.type,
|
|
992
1046
|
description: p.description ?? "",
|
|
993
1047
|
required: p.required ?? false,
|
|
1048
|
+
default: p.default !== undefined
|
|
1049
|
+
? valueFromJson(p.default as JsonInput)
|
|
1050
|
+
: undefined,
|
|
994
1051
|
}),
|
|
995
1052
|
),
|
|
996
1053
|
});
|
|
@@ -1002,6 +1059,16 @@ function catalogToProto(catalog: Catalog | Record<string, unknown>) {
|
|
|
1002
1059
|
});
|
|
1003
1060
|
}
|
|
1004
1061
|
|
|
1062
|
+
function catalogSchemaToWire(schema: unknown): string {
|
|
1063
|
+
if (schema === undefined || schema === null) {
|
|
1064
|
+
return "";
|
|
1065
|
+
}
|
|
1066
|
+
if (typeof schema === "string") {
|
|
1067
|
+
return schema;
|
|
1068
|
+
}
|
|
1069
|
+
return JSON.stringify(schema);
|
|
1070
|
+
}
|
|
1071
|
+
|
|
1005
1072
|
function authenticatedUserToProto(user: AuthenticatedUser) {
|
|
1006
1073
|
return create(AuthenticatedUserSchema, {
|
|
1007
1074
|
subject: user.subject,
|