ds-harness-remote 0.3.28 → 0.3.30

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/dist/index.js CHANGED
@@ -5636,7 +5636,9 @@ var SWITCHED_DOMAINS = [
5636
5636
  "agentPresets",
5637
5637
  "events",
5638
5638
  "goals",
5639
- "llm"
5639
+ "llm",
5640
+ "settings",
5641
+ "credentials"
5640
5642
  ];
5641
5643
  var ApiProxySwitch = class {
5642
5644
  remote;
@@ -13210,7 +13212,7 @@ function normalizeServerUrl(value) {
13210
13212
  }
13211
13213
 
13212
13214
  // src/version.ts
13213
- var PLUGIN_VERSION = "0.3.28";
13215
+ var PLUGIN_VERSION = "0.3.30";
13214
13216
 
13215
13217
  // src/server-api.ts
13216
13218
  var HostServerApi = class {
@@ -16072,6 +16074,59 @@ var commandExecuteSchema = external_exports.object({
16072
16074
  var commandListSchema = external_exports.object({
16073
16075
  agentId: external_exports.string().min(1).max(128)
16074
16076
  }).strict();
16077
+ var credentialRefSchema = external_exports.string().regex(/^[A-Za-z_][A-Za-z0-9_]*$/, "Invalid credential reference name").max(128);
16078
+ var CONFIG_PLANE_SETTINGS_BYTES = 64 * 1024;
16079
+ var CONFIG_PLANE_MAX_OPS = 64;
16080
+ var CONFIG_PLANE_MAX_PATH_SEGMENTS = 8;
16081
+ var CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES = 64;
16082
+ var CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES = 8 * 1024;
16083
+ var CONFIG_PLANE_MAX_BASE_URL_BYTES = 2048;
16084
+ var CONFIG_PLANE_MAX_NS_BYTES = 128;
16085
+ var settingsDescribeSchema = external_exports.object({}).strict();
16086
+ var settingsWriteBase = {
16087
+ ns: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES),
16088
+ expectedRevision: external_exports.number().int().nonnegative().optional()
16089
+ };
16090
+ var settingsUpdateSchema = external_exports.object({
16091
+ ...settingsWriteBase,
16092
+ patch: external_exports.record(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES), external_exports.unknown())
16093
+ }).strict();
16094
+ var settingsReplaceSchema = external_exports.object({
16095
+ ...settingsWriteBase,
16096
+ section: external_exports.record(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES), external_exports.unknown())
16097
+ }).strict();
16098
+ var settingsOpSchema = external_exports.union([
16099
+ external_exports.object({
16100
+ op: external_exports.literal("set"),
16101
+ path: external_exports.array(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES)).max(CONFIG_PLANE_MAX_PATH_SEGMENTS),
16102
+ value: external_exports.unknown()
16103
+ }).strict(),
16104
+ external_exports.object({
16105
+ op: external_exports.literal("unset"),
16106
+ path: external_exports.array(external_exports.string().min(1).max(CONFIG_PLANE_MAX_PATH_SEGMENT_BYTES)).max(CONFIG_PLANE_MAX_PATH_SEGMENTS)
16107
+ }).strict()
16108
+ ]);
16109
+ var settingsMutateSchema = external_exports.object({
16110
+ ...settingsWriteBase,
16111
+ ops: external_exports.array(settingsOpSchema).min(1).max(CONFIG_PLANE_MAX_OPS)
16112
+ }).strict();
16113
+ var credentialsDescribeSchema = external_exports.object({
16114
+ refs: external_exports.array(credentialRefSchema).max(CONFIG_PLANE_MAX_OPS)
16115
+ }).strict();
16116
+ var credentialsSetSchema = external_exports.object({
16117
+ ref: credentialRefSchema,
16118
+ value: external_exports.string().min(1).max(CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES)
16119
+ }).strict();
16120
+ var credentialsUnsetSchema = external_exports.object({
16121
+ ref: credentialRefSchema
16122
+ }).strict();
16123
+ var discoverModelsSchema = external_exports.object({
16124
+ settingsNs: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES),
16125
+ provider: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES).optional(),
16126
+ baseURL: external_exports.string().max(CONFIG_PLANE_MAX_BASE_URL_BYTES).optional(),
16127
+ api: external_exports.string().min(1).max(CONFIG_PLANE_MAX_NS_BYTES).optional(),
16128
+ apiKey: external_exports.string().min(1).max(CONFIG_PLANE_MAX_CREDENTIAL_VALUE_BYTES).optional()
16129
+ }).strict();
16075
16130
  var HARNESS_API_ALLOWLIST = [
16076
16131
  "session.list",
16077
16132
  "session.search",
@@ -16111,7 +16166,15 @@ var HARNESS_API_ALLOWLIST = [
16111
16166
  "commands.execute",
16112
16167
  "commands.list",
16113
16168
  "llm.providers",
16114
- "llm.models"
16169
+ "llm.models",
16170
+ "llm.discoverModels",
16171
+ "settings.describe",
16172
+ "settings.update",
16173
+ "settings.replace",
16174
+ "settings.mutate",
16175
+ "credentials.describe",
16176
+ "credentials.set",
16177
+ "credentials.unset"
16115
16178
  ];
16116
16179
  var NATIVE_CALL_TIMEOUT_MS = 3e4;
16117
16180
  var MAX_ACTIVE_API_TRANSFERS = 2;
@@ -16425,7 +16488,8 @@ function createMethodMap(api, typertGateway) {
16425
16488
  const domain = domainProperty(wireDomain);
16426
16489
  const implementation = domains[domain]?.[action];
16427
16490
  if (typeof implementation !== "function") continue;
16428
- methods.set(method, implementation.bind(domains[domain]));
16491
+ const scoped = CONFIG_PLANE_METHODS.includes(method) ? scopeConfigPlaneMethod(api, method, implementation) : void 0;
16492
+ methods.set(method, scoped ?? implementation.bind(domains[domain]));
16429
16493
  }
16430
16494
  return methods;
16431
16495
  }
@@ -16437,6 +16501,167 @@ function domainProperty(wireDomain) {
16437
16501
  if (wireDomain === "goal") return "goals";
16438
16502
  return wireDomain;
16439
16503
  }
16504
+ var CONFIG_PLANE_METHODS = [
16505
+ "llm.discoverModels",
16506
+ "settings.describe",
16507
+ "settings.update",
16508
+ "settings.replace",
16509
+ "settings.mutate",
16510
+ "credentials.describe",
16511
+ "credentials.set",
16512
+ "credentials.unset"
16513
+ ];
16514
+ function scopeConfigPlaneMethod(api, method, native) {
16515
+ switch (method) {
16516
+ case "llm.discoverModels":
16517
+ return async (request, signal) => {
16518
+ const payload = parseConfigPlane(discoverModelsSchema, request.payload, "llm.discoverModels");
16519
+ if (payload.baseURL !== void 0) validateDiscoverBaseUrl(payload.baseURL);
16520
+ try {
16521
+ const response = await native({ rpcId: request.rpcId, payload }, signal);
16522
+ return sanitizeModelDiscoveryResponse(response, payload.settingsNs);
16523
+ } catch {
16524
+ return modelDiscoveryFailure(request.rpcId, payload.settingsNs);
16525
+ }
16526
+ };
16527
+ case "settings.describe":
16528
+ return async (request, signal) => {
16529
+ parseConfigPlane(settingsDescribeSchema, request.payload, "settings.describe");
16530
+ const response = await native({ rpcId: request.rpcId, payload: {} }, signal);
16531
+ return disableRemoteSettingsDocument(response);
16532
+ };
16533
+ case "settings.update":
16534
+ return async (request, signal) => {
16535
+ const payload = parseConfigPlane(settingsUpdateSchema, request.payload, "settings.update");
16536
+ await assertRegisteredSettingsNamespace(api, payload.ns);
16537
+ assertSerializedBytes(payload.patch, CONFIG_PLANE_SETTINGS_BYTES, "settings.update patch");
16538
+ return native({ rpcId: request.rpcId, payload }, signal);
16539
+ };
16540
+ case "settings.replace":
16541
+ return async (request, signal) => {
16542
+ const payload = parseConfigPlane(settingsReplaceSchema, request.payload, "settings.replace");
16543
+ await assertRegisteredSettingsNamespace(api, payload.ns);
16544
+ assertSerializedBytes(payload.section, CONFIG_PLANE_SETTINGS_BYTES, "settings.replace section");
16545
+ return native({ rpcId: request.rpcId, payload }, signal);
16546
+ };
16547
+ case "settings.mutate":
16548
+ return async (request, signal) => {
16549
+ const payload = parseConfigPlane(settingsMutateSchema, request.payload, "settings.mutate");
16550
+ await assertRegisteredSettingsNamespace(api, payload.ns);
16551
+ assertSerializedBytes(payload.ops, CONFIG_PLANE_SETTINGS_BYTES, "settings.mutate ops");
16552
+ return native({ rpcId: request.rpcId, payload }, signal);
16553
+ };
16554
+ case "credentials.describe":
16555
+ return async (request, signal) => {
16556
+ const payload = parseConfigPlane(credentialsDescribeSchema, request.payload, "credentials.describe");
16557
+ return native({ rpcId: request.rpcId, payload }, signal);
16558
+ };
16559
+ case "credentials.set":
16560
+ return async (request, signal) => {
16561
+ const payload = parseConfigPlane(credentialsSetSchema, request.payload, "credentials.set");
16562
+ return native({ rpcId: request.rpcId, payload }, signal);
16563
+ };
16564
+ case "credentials.unset":
16565
+ return async (request, signal) => {
16566
+ const payload = parseConfigPlane(credentialsUnsetSchema, request.payload, "credentials.unset");
16567
+ return native({ rpcId: request.rpcId, payload }, signal);
16568
+ };
16569
+ }
16570
+ }
16571
+ function parseConfigPlane(schema, payload, label) {
16572
+ try {
16573
+ return schema.parse(payload);
16574
+ } catch (error) {
16575
+ if (error instanceof external_exports.ZodError) {
16576
+ throw new RpcError("INVALID_MESSAGE", `The ${label} payload is invalid for the remote channel.`);
16577
+ }
16578
+ throw error;
16579
+ }
16580
+ }
16581
+ function validateDiscoverBaseUrl(value) {
16582
+ let url;
16583
+ try {
16584
+ url = new URL(value);
16585
+ } catch {
16586
+ throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL is invalid.");
16587
+ }
16588
+ const local = url.hostname === "localhost" || url.hostname === "127.0.0.1" || url.hostname === "::1";
16589
+ if (url.protocol !== "https:" && !(local && url.protocol === "http:")) {
16590
+ throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must use HTTPS (HTTP is allowed only for localhost).");
16591
+ }
16592
+ if (url.username !== "" || url.password !== "") {
16593
+ throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must not contain credentials.");
16594
+ }
16595
+ if (url.hash !== "") {
16596
+ throw new RpcError("INVALID_MESSAGE", "The model discovery baseURL must not contain a fragment.");
16597
+ }
16598
+ }
16599
+ function assertSerializedBytes(value, maxBytes, label) {
16600
+ const bytes = new TextEncoder().encode(JSON.stringify(value)).byteLength;
16601
+ if (bytes > maxBytes) {
16602
+ throw new RpcError("INVALID_MESSAGE", `The ${label} exceeds the ${maxBytes}-byte remote limit.`);
16603
+ }
16604
+ }
16605
+ function sanitizeModelDiscoveryResponse(response, settingsNs) {
16606
+ const result = response.result;
16607
+ if (typeof result === "object" && result !== null && "ok" in result && result.ok === true) return response;
16608
+ return modelDiscoveryFailure(response.rpcId, settingsNs);
16609
+ }
16610
+ function modelDiscoveryFailure(rpcId, settingsNs) {
16611
+ return {
16612
+ rpcId,
16613
+ result: {
16614
+ ok: false,
16615
+ error: {
16616
+ code: "model-discovery-failed",
16617
+ message: "Model discovery failed.",
16618
+ details: { settingsNs }
16619
+ }
16620
+ }
16621
+ };
16622
+ }
16623
+ function disableRemoteSettingsDocument(response) {
16624
+ const result = response.result;
16625
+ if (typeof result !== "object" || result === null || !("ok" in result) || result.ok !== true) return response;
16626
+ const value = result.value;
16627
+ if (typeof value !== "object" || value === null) return response;
16628
+ return { ...response, result: { ...result, value: { ...value, hasDocument: false } } };
16629
+ }
16630
+ var EMPTY_SETTINGS_NAMESPACES = /* @__PURE__ */ new Set();
16631
+ async function assertRegisteredSettingsNamespace(api, ns) {
16632
+ const allowed = await registeredSettingsNamespaces(api);
16633
+ if (!allowed.has(ns)) throw deniedSettingsNamespace(ns);
16634
+ }
16635
+ async function registeredSettingsNamespaces(api) {
16636
+ const settings = api.settings;
16637
+ const describe = settings?.describe;
16638
+ if (typeof describe !== "function") return EMPTY_SETTINGS_NAMESPACES;
16639
+ const response = await withTimeout(
16640
+ describe.call(settings, { rpcId: "bridge-settings-scope", payload: {} }, AbortSignal.timeout(NATIVE_CALL_TIMEOUT_MS)),
16641
+ NATIVE_CALL_TIMEOUT_MS,
16642
+ "The Host settings.describe call timed out."
16643
+ );
16644
+ const value = unwrapNativeValue(response, "settings.describe");
16645
+ const list = typeof value === "object" && value !== null ? value.namespaces : void 0;
16646
+ if (!Array.isArray(list)) return EMPTY_SETTINGS_NAMESPACES;
16647
+ const namespaces = /* @__PURE__ */ new Set();
16648
+ for (const item of list) {
16649
+ if (typeof item !== "object" || item === null) continue;
16650
+ const ns = item.ns;
16651
+ if (typeof ns === "string" && ns.length > 0) namespaces.add(ns);
16652
+ }
16653
+ return namespaces;
16654
+ }
16655
+ function unwrapNativeValue(response, method) {
16656
+ const result = response.result;
16657
+ if (typeof result !== "object" || result === null || !("ok" in result) || result.ok !== true || !("value" in result)) {
16658
+ throw new RpcError("INTERNAL_ERROR", `The Host ${method} call did not succeed.`);
16659
+ }
16660
+ return result.value;
16661
+ }
16662
+ function deniedSettingsNamespace(ns) {
16663
+ return new RpcError("METHOD_NOT_ALLOWED", `Harness settings namespace ${JSON.stringify(ns)} is not registered on the Host.`);
16664
+ }
16440
16665
  function deniedMethod(method) {
16441
16666
  return new RpcError("METHOD_NOT_ALLOWED", `Harness API method ${JSON.stringify(method)} is not available in remote mode.`);
16442
16667
  }