@infersec/conduit 1.105.0 → 1.107.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -13,6 +13,7 @@ npx @infersec/conduit inference start --engine <type> --key <api-key> --source <
13
13
  | Command | Description |
14
14
  | ----------------------- | ------------------------------------------------------------------------------------------------------ |
15
15
  | `inference start` | Start the inference agent |
16
+ | `inference group start` | Start an inference agent for a source group (registers an ephemeral source) |
16
17
  | `tool connect <toolID>` | Connect a local tool (`local-filesystem`, `local-mysql`) to the API. Type is resolved from the server. |
17
18
 
18
19
  ### Flags
@@ -28,6 +29,16 @@ npx @infersec/conduit inference start --engine <type> --key <api-key> --source <
28
29
  | `--api-url` | No | `https://api.infersec.ai` | API base URL (matches `API_URL`). |
29
30
  | `--start-mode` | No | `auto` | Startup mode (matches `START_MODE`): `auto` starts engine, `idle` leaves conduit idle. |
30
31
 
32
+ #### `inference group start` flags
33
+
34
+ Same flags as `inference start`, except `--group` replaces `--source`:
35
+
36
+ | Flag | Required | Default | Notes |
37
+ | --------- | -------- | ------- | ------------------------------------- |
38
+ | `--group` | Yes | - | Source group ID (matches `GROUP_ID`). |
39
+
40
+ The agent registers an ephemeral source under the group (absorbing its model/engine settings), then runs the standard inference flow. Ephemeral sources are removed automatically after being offline for 1 hour.
41
+
31
42
  #### `tool connect` flags
32
43
 
33
44
  Common flags (all tool types):
@@ -67,6 +78,7 @@ Common flags (all tool types):
67
78
  | Required only | `npx @infersec/conduit inference start --engine vllm --key <api-key> --source <source-id>` |
68
79
  | Custom root/port | `npx @infersec/conduit inference start --engine vllm --key <api-key> --source <source-id> --root /data/infersec --port 9601` |
69
80
  | Custom engine/port | `npx @infersec/conduit inference start --engine vllm --key <api-key> --source <source-id> --port 9601 --engine-port 9701` |
81
+ | Source group | `npx @infersec/conduit inference group start --key <api-key> --group <group-id>` |
70
82
  | Connect FS tool | `npx @infersec/conduit tool connect <tool-id> --key <api-key> --path ./` |
71
83
  | Read-only FS tool | `npx @infersec/conduit tool connect <tool-id> --key <api-key> --path ./ --read-only` |
72
84
  | Connect MySQL tool | `MYSQL_URL=mysql://user:pass@host:3306/db npx @infersec/conduit tool connect <tool-id> --key <api-key>` |
@@ -82,6 +94,7 @@ Credentials are best supplied via the `MYSQL_*` environment variables (or `MYSQL
82
94
  | `ENGINE` | Yes | - | Engine type (matches `--engine`). |
83
95
  | `ENGINE_PORT` | No | `9700` | Engine port (matches `--engine-port`). |
84
96
  | `API_KEY` | Yes | - | API key (matches `--key`). |
97
+ | `GROUP_ID` | No | - | Source group ID for `inference group start` (matches `--group`). |
85
98
  | `SOURCE` | Yes | - | Inference source ID (matches `--source`). |
86
99
  | `API_URL` | No | `https://api.infersec.ai` | API base URL (matches `--api-url`). |
87
100
  | `PORT` | No | `9600` | Port to listen on (matches `--port`). |
package/dist/cli.js CHANGED
@@ -20097,6 +20097,26 @@ const InferenceAgentConfigurationSchema = object$1({
20097
20097
  });
20098
20098
 
20099
20099
  const API_SERVICE_CONDUIT_API_REFERENCE = {
20100
+ "/conduit/api/v1/source-group/:groupID/register": {
20101
+ POST: {
20102
+ auth: {
20103
+ type: "api-key"
20104
+ },
20105
+ body: object$1({
20106
+ identifier: string$2().min(1).max(256).optional()
20107
+ }),
20108
+ parameters: {
20109
+ groupID: ULIDSchema
20110
+ },
20111
+ response: {
20112
+ schema: object$1({
20113
+ configuration: InferenceAgentConfigurationSchema,
20114
+ sourceID: ULIDSchema
20115
+ }),
20116
+ type: "rest"
20117
+ }
20118
+ }
20119
+ },
20100
20120
  "/conduit/api/v1/source/:sourceID/configuration": {
20101
20121
  GET: {
20102
20122
  auth: {
@@ -20993,6 +21013,8 @@ object$1({
20993
21013
  created: string$2(),
20994
21014
  engine: LLMEngineSchema.nullable(),
20995
21015
  engineId: ULIDSchema.nullable(),
21016
+ ephemeral: DBBooleanSchema.optional(),
21017
+ groupId: ULIDSchema.nullable().optional(),
20996
21018
  id: ULIDSchema,
20997
21019
  lastState: ConduitState.nullable(),
20998
21020
  lastStateTimestamp: string$2().nullable(),
@@ -21009,6 +21031,8 @@ object$1({
21009
21031
  engineConfig: unknown().nullable(),
21010
21032
  engineId: ULIDSchema.nullable(),
21011
21033
  engineName: string$2().nullable(),
21034
+ ephemeral: DBBooleanSchema.optional(),
21035
+ groupId: ULIDSchema.nullable().optional(),
21012
21036
  id: ULIDSchema,
21013
21037
  lastState: ConduitState.nullable(),
21014
21038
  lastStateTimestamp: string$2().nullable(),
@@ -21035,8 +21059,70 @@ object$1({
21035
21059
  object$1({
21036
21060
  id: ULIDSchema
21037
21061
  });
21062
+ object$1({
21063
+ contextLength: number$1().int().positive().max(1048576).optional(),
21064
+ engineId: ULIDSchema,
21065
+ modelID: ULIDSchema,
21066
+ name: ResourceNameSchema,
21067
+ quantizationLabel: string$2().min(1).max(128).optional()
21068
+ });
21069
+ object$1({
21070
+ results: array(object$1({
21071
+ contextLength: number$1().int().positive().nullable(),
21072
+ created: string$2(),
21073
+ engine: LLMEngineSchema.nullable(),
21074
+ engineId: ULIDSchema.nullable(),
21075
+ ephemeralSourceCount: number$1().int().nonnegative(),
21076
+ id: ULIDSchema,
21077
+ modelID: ULIDSchema.nullable(),
21078
+ modelName: string$2(),
21079
+ name: string$2(),
21080
+ onlineSourceCount: number$1().int().nonnegative(),
21081
+ updated: string$2()
21082
+ }))
21083
+ });
21084
+ object$1({
21085
+ contextLength: number$1().int().positive().nullable(),
21086
+ created: string$2(),
21087
+ engine: LLMEngineSchema.nullable(),
21088
+ engineConfig: unknown().nullable(),
21089
+ engineId: ULIDSchema.nullable(),
21090
+ engineName: string$2().nullable(),
21091
+ id: ULIDSchema,
21092
+ model: object$1({
21093
+ id: ULIDSchema,
21094
+ modelFormat: LLMModelFormatSchema,
21095
+ name: string$2(),
21096
+ provider: _enum$1(["storage", "huggingface"]),
21097
+ providerSlug: string$2(),
21098
+ taskType: LLMModelTaskTypeSchema
21099
+ })
21100
+ .nullable(),
21101
+ modelQuantizationLabel: string$2().nullable(),
21102
+ name: string$2(),
21103
+ sources: array(object$1({
21104
+ ephemeral: DBBooleanSchema,
21105
+ id: ULIDSchema,
21106
+ lastState: ConduitState.nullable(),
21107
+ lastStateTimestamp: string$2().nullable(),
21108
+ name: string$2(),
21109
+ online: DBBooleanSchema
21110
+ })),
21111
+ updated: string$2()
21112
+ });
21113
+ object$1({
21114
+ contextLength: number$1().int().positive().nullable().optional(),
21115
+ engineId: ULIDSchema.nullable().optional(),
21116
+ modelID: ULIDSchema.optional(),
21117
+ name: ResourceNameSchema.optional(),
21118
+ quantizationLabel: string$2().min(1).max(128).nullable().optional()
21119
+ });
21120
+ object$1({
21121
+ id: ULIDSchema
21122
+ });
21038
21123
  object$1({
21039
21124
  enabled: boolean$1().optional(),
21125
+ groupIDs: array(ULIDSchema).optional(),
21040
21126
  name: ResourceNameSchema,
21041
21127
  routingMethod: nativeEnum(RoutingMethod).optional(),
21042
21128
  sourceIDs: array(ULIDSchema)
@@ -21054,6 +21140,12 @@ object$1({
21054
21140
  object$1({
21055
21141
  created: string$2(),
21056
21142
  enabled: DBBooleanSchema,
21143
+ groups: array(object$1({
21144
+ id: ULIDSchema,
21145
+ name: string$2(),
21146
+ onlineSourceCount: number$1().int().nonnegative(),
21147
+ sourceCount: number$1().int().nonnegative()
21148
+ })),
21057
21149
  id: ULIDSchema,
21058
21150
  minimumEffectiveContextLength: number$1().int().positive().nullable(),
21059
21151
  name: string$2(),
@@ -21075,6 +21167,7 @@ object$1({
21075
21167
  });
21076
21168
  object$1({
21077
21169
  enabled: boolean$1().optional(),
21170
+ groupIDs: array(ULIDSchema).optional(),
21078
21171
  name: ResourceNameSchema.optional(),
21079
21172
  routingMethod: nativeEnum(RoutingMethod).optional(),
21080
21173
  sourceIDs: array(ULIDSchema).optional()
@@ -21150,6 +21243,20 @@ object$1({
21150
21243
  modelID: ULIDSchema.describe("Model identifier")
21151
21244
  }}
21152
21245
  },
21246
+ "/api/v1/source-groups/:groupID": {
21247
+ DELETE: {
21248
+ parameters: {
21249
+ groupID: ULIDSchema.describe("Source group identifier")
21250
+ }},
21251
+ GET: {
21252
+ parameters: {
21253
+ groupID: ULIDSchema.describe("Source group identifier")
21254
+ }},
21255
+ PATCH: {
21256
+ parameters: {
21257
+ groupID: ULIDSchema.describe("Source group identifier")
21258
+ }}
21259
+ },
21153
21260
  "/api/v1/sources/:sourceID": {
21154
21261
  DELETE: {
21155
21262
  parameters: {
@@ -21314,6 +21421,31 @@ const ACCOUNT_MANAGEMENT_OPERATION_METADATA = [
21314
21421
  name: "update_source"
21315
21422
  },
21316
21423
  { category: "delete", description: "Delete an inference source.", name: "delete_source" },
21424
+ {
21425
+ category: "read",
21426
+ description: "List inference source groups in the account.",
21427
+ name: "list_source_groups"
21428
+ },
21429
+ {
21430
+ category: "read",
21431
+ description: "Get full details for a single inference source group.",
21432
+ name: "get_source_group_details"
21433
+ },
21434
+ {
21435
+ category: "write",
21436
+ description: "Create a new inference source group.",
21437
+ name: "create_source_group"
21438
+ },
21439
+ {
21440
+ category: "write",
21441
+ description: "Update an inference source group's name, engine, model or context length.",
21442
+ name: "update_source_group"
21443
+ },
21444
+ {
21445
+ category: "delete",
21446
+ description: "Delete an inference source group and its ephemeral sources.",
21447
+ name: "delete_source_group"
21448
+ },
21317
21449
  { category: "read", description: "List models in the account.", name: "list_models" },
21318
21450
  {
21319
21451
  category: "read",
@@ -21488,17 +21620,23 @@ const ModelEndpointCallConfigSchema = object$1({
21488
21620
  description: string$2().min(1),
21489
21621
  endpointId: string$2().min(1),
21490
21622
  inputSchema: record(string$2(), unknown()).optional(),
21623
+ maxTokens: number$1().int().positive().optional(),
21491
21624
  outputSchema: record(string$2(), unknown()).optional(),
21492
21625
  systemPrompt: string$2().optional(),
21493
21626
  type: literal("model-endpoint-call")
21494
21627
  });
21495
21628
  const ModelSourceCallConfigSchema = object$1({
21496
21629
  description: string$2().min(1),
21630
+ groupId: ULIDSchema.optional(),
21497
21631
  inputSchema: record(string$2(), unknown()).optional(),
21632
+ maxTokens: number$1().int().positive().optional(),
21498
21633
  outputSchema: record(string$2(), unknown()).optional(),
21499
- sourceId: string$2().min(1),
21634
+ sourceId: ULIDSchema.optional(),
21500
21635
  systemPrompt: string$2().optional(),
21501
21636
  type: literal("model-source-call")
21637
+ })
21638
+ .refine(config => Boolean(config.sourceId) !== Boolean(config.groupId), {
21639
+ message: "Exactly one of sourceId or groupId must be set"
21502
21640
  });
21503
21641
  discriminatedUnion("type", [
21504
21642
  AccountManagementConfigSchema,
@@ -22333,6 +22471,22 @@ function buildConfigurationOverrides(options) {
22333
22471
  return configurationOverrides;
22334
22472
  }
22335
22473
 
22474
+ function buildGroupConfigurationOverrides(options) {
22475
+ const group = options.group ?? readEnvStringOptional("GROUP_ID", undefined);
22476
+ if (options.source && group) {
22477
+ throw new Error("Options --source and --group are mutually exclusive");
22478
+ }
22479
+ if (!group) {
22480
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
22481
+ }
22482
+ const overrides = buildConfigurationOverrides({
22483
+ ...options,
22484
+ source: undefined
22485
+ });
22486
+ overrides.groupID = group;
22487
+ return overrides;
22488
+ }
22489
+
22336
22490
  function commonjsRequire(path) {
22337
22491
  throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
22338
22492
  }
@@ -136620,6 +136774,81 @@ function createSignalShutdown$1({ connection, logger }) {
136620
136774
  };
136621
136775
  }
136622
136776
 
136777
+ async function resolveGroupRegistrationConfig({ apiKeyOverride, apiURLOverride }) {
136778
+ const apiKey = apiKeyOverride ?? readEnvString("API_KEY");
136779
+ const apiURL = apiURLOverride ?? readEnvStringOptional("API_URL", "https://api.infersec.ai");
136780
+ return { apiKey, apiURL };
136781
+ }
136782
+ async function registerGroupSource({ apiKeyOverride, apiURLOverride, groupID, logger }) {
136783
+ const log = logger ?? createLogger({ name: "infersec-conduit" });
136784
+ const { apiKey, apiURL } = await resolveGroupRegistrationConfig({
136785
+ apiKeyOverride,
136786
+ apiURLOverride
136787
+ });
136788
+ const fetchWithAPIKey = createFetchWithHeaders({
136789
+ fetchFn: async (input, init) => {
136790
+ try {
136791
+ return await fetchWithRetry(input, init, {
136792
+ maxAttempts: 4,
136793
+ timeoutMs: 10000
136794
+ });
136795
+ }
136796
+ catch (error) {
136797
+ log.warn("API request failed after retries", getNetworkErrorAttributes(error));
136798
+ throw error;
136799
+ }
136800
+ },
136801
+ headers: {
136802
+ "x-api-key": apiKey
136803
+ }
136804
+ });
136805
+ try {
136806
+ const result = (await fetchByReference({
136807
+ baseURL: apiURL,
136808
+ body: {},
136809
+ fetch: fetchWithAPIKey,
136810
+ method: "POST",
136811
+ parameters: {
136812
+ groupID
136813
+ },
136814
+ reference: API_SERVICE_CONDUIT_API_REFERENCE,
136815
+ route: "/conduit/api/v1/source-group/:groupID/register"
136816
+ }));
136817
+ log.info("Registered ephemeral source for group", {
136818
+ groupID,
136819
+ inferenceSourceID: result.sourceID
136820
+ });
136821
+ return result;
136822
+ }
136823
+ catch (error) {
136824
+ log.error("Source group registration failed", { error: asError(error), groupID });
136825
+ throw error;
136826
+ }
136827
+ }
136828
+
136829
+ async function startInferenceAgentForGroup({ configurationOverrides }) {
136830
+ setDefaultResultOrder("ipv4first");
136831
+ const logger = createLogger({
136832
+ name: "infersec-conduit"
136833
+ });
136834
+ const groupID = configurationOverrides?.groupID ?? readEnvStringOptional("GROUP_ID", undefined);
136835
+ if (!groupID) {
136836
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
136837
+ }
136838
+ const registration = await registerGroupSource({
136839
+ apiKeyOverride: configurationOverrides?.apiKey,
136840
+ apiURLOverride: configurationOverrides?.apiURL,
136841
+ groupID,
136842
+ logger
136843
+ });
136844
+ await startInferenceAgent({
136845
+ configurationOverrides: {
136846
+ ...configurationOverrides,
136847
+ inferenceSourceID: registration.sourceID
136848
+ }
136849
+ });
136850
+ }
136851
+
136623
136852
  function registerInferenceCommands({ program }) {
136624
136853
  const inference = program.command("inference").description("Manage inference agent");
136625
136854
  inference
@@ -136636,6 +136865,21 @@ function registerInferenceCommands({ program }) {
136636
136865
  const configurationOverrides = buildConfigurationOverrides(options);
136637
136866
  await startInferenceAgent({ configurationOverrides });
136638
136867
  });
136868
+ const group = inference.command("group").description("Manage source group agents");
136869
+ group
136870
+ .command("start")
136871
+ .description("Start an inference agent for a source group (registers an ephemeral source)")
136872
+ .option("--api-url <url>", "API base URL (or API_URL env)")
136873
+ .option("--engine-port <number>", "Engine port (or ENGINE_PORT env)")
136874
+ .option("--group <id>", "Source group ID (or GROUP_ID env)")
136875
+ .option("--key <value>", "API key (or API_KEY env)")
136876
+ .option("--port <number>", "Port to listen on (or PORT env)")
136877
+ .option("--root <path>", "Root directory (or ROOT_DIRECTORY env)")
136878
+ .option("--start-mode <mode>", "Startup mode: auto|idle (or START_MODE env)")
136879
+ .action(async (options) => {
136880
+ const configurationOverrides = buildGroupConfigurationOverrides(options);
136881
+ await startInferenceAgentForGroup({ configurationOverrides });
136882
+ });
136639
136883
  }
136640
136884
 
136641
136885
  const ROOT_DIRECTORY_DEFAULT = join(process.env.HOME ?? "/tmp", ".cache", "infersec", "iagent");
package/dist/cli.sea.cjs CHANGED
@@ -20112,6 +20112,26 @@ const InferenceAgentConfigurationSchema = object$1({
20112
20112
  });
20113
20113
 
20114
20114
  const API_SERVICE_CONDUIT_API_REFERENCE = {
20115
+ "/conduit/api/v1/source-group/:groupID/register": {
20116
+ POST: {
20117
+ auth: {
20118
+ type: "api-key"
20119
+ },
20120
+ body: object$1({
20121
+ identifier: string$2().min(1).max(256).optional()
20122
+ }),
20123
+ parameters: {
20124
+ groupID: ULIDSchema
20125
+ },
20126
+ response: {
20127
+ schema: object$1({
20128
+ configuration: InferenceAgentConfigurationSchema,
20129
+ sourceID: ULIDSchema
20130
+ }),
20131
+ type: "rest"
20132
+ }
20133
+ }
20134
+ },
20115
20135
  "/conduit/api/v1/source/:sourceID/configuration": {
20116
20136
  GET: {
20117
20137
  auth: {
@@ -21008,6 +21028,8 @@ object$1({
21008
21028
  created: string$2(),
21009
21029
  engine: LLMEngineSchema.nullable(),
21010
21030
  engineId: ULIDSchema.nullable(),
21031
+ ephemeral: DBBooleanSchema.optional(),
21032
+ groupId: ULIDSchema.nullable().optional(),
21011
21033
  id: ULIDSchema,
21012
21034
  lastState: ConduitState.nullable(),
21013
21035
  lastStateTimestamp: string$2().nullable(),
@@ -21024,6 +21046,8 @@ object$1({
21024
21046
  engineConfig: unknown().nullable(),
21025
21047
  engineId: ULIDSchema.nullable(),
21026
21048
  engineName: string$2().nullable(),
21049
+ ephemeral: DBBooleanSchema.optional(),
21050
+ groupId: ULIDSchema.nullable().optional(),
21027
21051
  id: ULIDSchema,
21028
21052
  lastState: ConduitState.nullable(),
21029
21053
  lastStateTimestamp: string$2().nullable(),
@@ -21050,8 +21074,70 @@ object$1({
21050
21074
  object$1({
21051
21075
  id: ULIDSchema
21052
21076
  });
21077
+ object$1({
21078
+ contextLength: number$1().int().positive().max(1048576).optional(),
21079
+ engineId: ULIDSchema,
21080
+ modelID: ULIDSchema,
21081
+ name: ResourceNameSchema,
21082
+ quantizationLabel: string$2().min(1).max(128).optional()
21083
+ });
21084
+ object$1({
21085
+ results: array(object$1({
21086
+ contextLength: number$1().int().positive().nullable(),
21087
+ created: string$2(),
21088
+ engine: LLMEngineSchema.nullable(),
21089
+ engineId: ULIDSchema.nullable(),
21090
+ ephemeralSourceCount: number$1().int().nonnegative(),
21091
+ id: ULIDSchema,
21092
+ modelID: ULIDSchema.nullable(),
21093
+ modelName: string$2(),
21094
+ name: string$2(),
21095
+ onlineSourceCount: number$1().int().nonnegative(),
21096
+ updated: string$2()
21097
+ }))
21098
+ });
21099
+ object$1({
21100
+ contextLength: number$1().int().positive().nullable(),
21101
+ created: string$2(),
21102
+ engine: LLMEngineSchema.nullable(),
21103
+ engineConfig: unknown().nullable(),
21104
+ engineId: ULIDSchema.nullable(),
21105
+ engineName: string$2().nullable(),
21106
+ id: ULIDSchema,
21107
+ model: object$1({
21108
+ id: ULIDSchema,
21109
+ modelFormat: LLMModelFormatSchema,
21110
+ name: string$2(),
21111
+ provider: _enum$1(["storage", "huggingface"]),
21112
+ providerSlug: string$2(),
21113
+ taskType: LLMModelTaskTypeSchema
21114
+ })
21115
+ .nullable(),
21116
+ modelQuantizationLabel: string$2().nullable(),
21117
+ name: string$2(),
21118
+ sources: array(object$1({
21119
+ ephemeral: DBBooleanSchema,
21120
+ id: ULIDSchema,
21121
+ lastState: ConduitState.nullable(),
21122
+ lastStateTimestamp: string$2().nullable(),
21123
+ name: string$2(),
21124
+ online: DBBooleanSchema
21125
+ })),
21126
+ updated: string$2()
21127
+ });
21128
+ object$1({
21129
+ contextLength: number$1().int().positive().nullable().optional(),
21130
+ engineId: ULIDSchema.nullable().optional(),
21131
+ modelID: ULIDSchema.optional(),
21132
+ name: ResourceNameSchema.optional(),
21133
+ quantizationLabel: string$2().min(1).max(128).nullable().optional()
21134
+ });
21135
+ object$1({
21136
+ id: ULIDSchema
21137
+ });
21053
21138
  object$1({
21054
21139
  enabled: boolean$1().optional(),
21140
+ groupIDs: array(ULIDSchema).optional(),
21055
21141
  name: ResourceNameSchema,
21056
21142
  routingMethod: nativeEnum(RoutingMethod).optional(),
21057
21143
  sourceIDs: array(ULIDSchema)
@@ -21069,6 +21155,12 @@ object$1({
21069
21155
  object$1({
21070
21156
  created: string$2(),
21071
21157
  enabled: DBBooleanSchema,
21158
+ groups: array(object$1({
21159
+ id: ULIDSchema,
21160
+ name: string$2(),
21161
+ onlineSourceCount: number$1().int().nonnegative(),
21162
+ sourceCount: number$1().int().nonnegative()
21163
+ })),
21072
21164
  id: ULIDSchema,
21073
21165
  minimumEffectiveContextLength: number$1().int().positive().nullable(),
21074
21166
  name: string$2(),
@@ -21090,6 +21182,7 @@ object$1({
21090
21182
  });
21091
21183
  object$1({
21092
21184
  enabled: boolean$1().optional(),
21185
+ groupIDs: array(ULIDSchema).optional(),
21093
21186
  name: ResourceNameSchema.optional(),
21094
21187
  routingMethod: nativeEnum(RoutingMethod).optional(),
21095
21188
  sourceIDs: array(ULIDSchema).optional()
@@ -21165,6 +21258,20 @@ object$1({
21165
21258
  modelID: ULIDSchema.describe("Model identifier")
21166
21259
  }}
21167
21260
  },
21261
+ "/api/v1/source-groups/:groupID": {
21262
+ DELETE: {
21263
+ parameters: {
21264
+ groupID: ULIDSchema.describe("Source group identifier")
21265
+ }},
21266
+ GET: {
21267
+ parameters: {
21268
+ groupID: ULIDSchema.describe("Source group identifier")
21269
+ }},
21270
+ PATCH: {
21271
+ parameters: {
21272
+ groupID: ULIDSchema.describe("Source group identifier")
21273
+ }}
21274
+ },
21168
21275
  "/api/v1/sources/:sourceID": {
21169
21276
  DELETE: {
21170
21277
  parameters: {
@@ -21329,6 +21436,31 @@ const ACCOUNT_MANAGEMENT_OPERATION_METADATA = [
21329
21436
  name: "update_source"
21330
21437
  },
21331
21438
  { category: "delete", description: "Delete an inference source.", name: "delete_source" },
21439
+ {
21440
+ category: "read",
21441
+ description: "List inference source groups in the account.",
21442
+ name: "list_source_groups"
21443
+ },
21444
+ {
21445
+ category: "read",
21446
+ description: "Get full details for a single inference source group.",
21447
+ name: "get_source_group_details"
21448
+ },
21449
+ {
21450
+ category: "write",
21451
+ description: "Create a new inference source group.",
21452
+ name: "create_source_group"
21453
+ },
21454
+ {
21455
+ category: "write",
21456
+ description: "Update an inference source group's name, engine, model or context length.",
21457
+ name: "update_source_group"
21458
+ },
21459
+ {
21460
+ category: "delete",
21461
+ description: "Delete an inference source group and its ephemeral sources.",
21462
+ name: "delete_source_group"
21463
+ },
21332
21464
  { category: "read", description: "List models in the account.", name: "list_models" },
21333
21465
  {
21334
21466
  category: "read",
@@ -21503,17 +21635,23 @@ const ModelEndpointCallConfigSchema = object$1({
21503
21635
  description: string$2().min(1),
21504
21636
  endpointId: string$2().min(1),
21505
21637
  inputSchema: record(string$2(), unknown()).optional(),
21638
+ maxTokens: number$1().int().positive().optional(),
21506
21639
  outputSchema: record(string$2(), unknown()).optional(),
21507
21640
  systemPrompt: string$2().optional(),
21508
21641
  type: literal("model-endpoint-call")
21509
21642
  });
21510
21643
  const ModelSourceCallConfigSchema = object$1({
21511
21644
  description: string$2().min(1),
21645
+ groupId: ULIDSchema.optional(),
21512
21646
  inputSchema: record(string$2(), unknown()).optional(),
21647
+ maxTokens: number$1().int().positive().optional(),
21513
21648
  outputSchema: record(string$2(), unknown()).optional(),
21514
- sourceId: string$2().min(1),
21649
+ sourceId: ULIDSchema.optional(),
21515
21650
  systemPrompt: string$2().optional(),
21516
21651
  type: literal("model-source-call")
21652
+ })
21653
+ .refine(config => Boolean(config.sourceId) !== Boolean(config.groupId), {
21654
+ message: "Exactly one of sourceId or groupId must be set"
21517
21655
  });
21518
21656
  discriminatedUnion("type", [
21519
21657
  AccountManagementConfigSchema,
@@ -22348,6 +22486,22 @@ function buildConfigurationOverrides(options) {
22348
22486
  return configurationOverrides;
22349
22487
  }
22350
22488
 
22489
+ function buildGroupConfigurationOverrides(options) {
22490
+ const group = options.group ?? readEnvStringOptional("GROUP_ID", undefined);
22491
+ if (options.source && group) {
22492
+ throw new Error("Options --source and --group are mutually exclusive");
22493
+ }
22494
+ if (!group) {
22495
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
22496
+ }
22497
+ const overrides = buildConfigurationOverrides({
22498
+ ...options,
22499
+ source: undefined
22500
+ });
22501
+ overrides.groupID = group;
22502
+ return overrides;
22503
+ }
22504
+
22351
22505
  function commonjsRequire(path) {
22352
22506
  throw new Error('Could not dynamically require "' + path + '". Please configure the dynamicRequireTargets or/and ignoreDynamicRequires option of @rollup/plugin-commonjs appropriately for this require call to work.');
22353
22507
  }
@@ -156850,6 +157004,81 @@ function createSignalShutdown$1({ connection, logger }) {
156850
157004
  };
156851
157005
  }
156852
157006
 
157007
+ async function resolveGroupRegistrationConfig({ apiKeyOverride, apiURLOverride }) {
157008
+ const apiKey = apiKeyOverride ?? readEnvString("API_KEY");
157009
+ const apiURL = apiURLOverride ?? readEnvStringOptional("API_URL", "https://api.infersec.ai");
157010
+ return { apiKey, apiURL };
157011
+ }
157012
+ async function registerGroupSource({ apiKeyOverride, apiURLOverride, groupID, logger }) {
157013
+ const log = logger ?? createLogger({ name: "infersec-conduit" });
157014
+ const { apiKey, apiURL } = await resolveGroupRegistrationConfig({
157015
+ apiKeyOverride,
157016
+ apiURLOverride
157017
+ });
157018
+ const fetchWithAPIKey = createFetchWithHeaders({
157019
+ fetchFn: async (input, init) => {
157020
+ try {
157021
+ return await fetchWithRetry(input, init, {
157022
+ maxAttempts: 4,
157023
+ timeoutMs: 10000
157024
+ });
157025
+ }
157026
+ catch (error) {
157027
+ log.warn("API request failed after retries", getNetworkErrorAttributes(error));
157028
+ throw error;
157029
+ }
157030
+ },
157031
+ headers: {
157032
+ "x-api-key": apiKey
157033
+ }
157034
+ });
157035
+ try {
157036
+ const result = (await fetchByReference({
157037
+ baseURL: apiURL,
157038
+ body: {},
157039
+ fetch: fetchWithAPIKey,
157040
+ method: "POST",
157041
+ parameters: {
157042
+ groupID
157043
+ },
157044
+ reference: API_SERVICE_CONDUIT_API_REFERENCE,
157045
+ route: "/conduit/api/v1/source-group/:groupID/register"
157046
+ }));
157047
+ log.info("Registered ephemeral source for group", {
157048
+ groupID,
157049
+ inferenceSourceID: result.sourceID
157050
+ });
157051
+ return result;
157052
+ }
157053
+ catch (error) {
157054
+ log.error("Source group registration failed", { error: asError(error), groupID });
157055
+ throw error;
157056
+ }
157057
+ }
157058
+
157059
+ async function startInferenceAgentForGroup({ configurationOverrides }) {
157060
+ require$$1$a.setDefaultResultOrder("ipv4first");
157061
+ const logger = createLogger({
157062
+ name: "infersec-conduit"
157063
+ });
157064
+ const groupID = configurationOverrides?.groupID ?? readEnvStringOptional("GROUP_ID", undefined);
157065
+ if (!groupID) {
157066
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
157067
+ }
157068
+ const registration = await registerGroupSource({
157069
+ apiKeyOverride: configurationOverrides?.apiKey,
157070
+ apiURLOverride: configurationOverrides?.apiURL,
157071
+ groupID,
157072
+ logger
157073
+ });
157074
+ await startInferenceAgent({
157075
+ configurationOverrides: {
157076
+ ...configurationOverrides,
157077
+ inferenceSourceID: registration.sourceID
157078
+ }
157079
+ });
157080
+ }
157081
+
156853
157082
  function registerInferenceCommands({ program }) {
156854
157083
  const inference = program.command("inference").description("Manage inference agent");
156855
157084
  inference
@@ -156866,6 +157095,21 @@ function registerInferenceCommands({ program }) {
156866
157095
  const configurationOverrides = buildConfigurationOverrides(options);
156867
157096
  await startInferenceAgent({ configurationOverrides });
156868
157097
  });
157098
+ const group = inference.command("group").description("Manage source group agents");
157099
+ group
157100
+ .command("start")
157101
+ .description("Start an inference agent for a source group (registers an ephemeral source)")
157102
+ .option("--api-url <url>", "API base URL (or API_URL env)")
157103
+ .option("--engine-port <number>", "Engine port (or ENGINE_PORT env)")
157104
+ .option("--group <id>", "Source group ID (or GROUP_ID env)")
157105
+ .option("--key <value>", "API key (or API_KEY env)")
157106
+ .option("--port <number>", "Port to listen on (or PORT env)")
157107
+ .option("--root <path>", "Root directory (or ROOT_DIRECTORY env)")
157108
+ .option("--start-mode <mode>", "Startup mode: auto|idle (or START_MODE env)")
157109
+ .action(async (options) => {
157110
+ const configurationOverrides = buildGroupConfigurationOverrides(options);
157111
+ await startInferenceAgentForGroup({ configurationOverrides });
157112
+ });
156869
157113
  }
156870
157114
 
156871
157115
  const ROOT_DIRECTORY_DEFAULT = path$1.join(process.env.HOME ?? "/tmp", ".cache", "infersec", "iagent");
@@ -0,0 +1,6 @@
1
+ import type { ConfigurationOverrides } from "../configuration.js";
2
+ import { type StartCommandOptions } from "./inferenceOptions.js";
3
+ export interface GroupStartCommandOptions extends StartCommandOptions {
4
+ group?: string;
5
+ }
6
+ export declare function buildGroupConfigurationOverrides(options: GroupStartCommandOptions): ConfigurationOverrides;
@@ -18,6 +18,7 @@ export interface ConfigurationOverrides {
18
18
  apiKey?: string;
19
19
  apiURL?: string;
20
20
  enginePort?: number;
21
+ groupID?: ULID;
21
22
  inferenceSourceID?: ULID;
22
23
  port?: number;
23
24
  rootDirectory?: string;
@@ -0,0 +1,12 @@
1
+ import { ULID } from "@infersec/definitions";
2
+ import { type Logger } from "@infersec/logger";
3
+ export interface RegisterGroupSourceResult {
4
+ configuration: unknown;
5
+ sourceID: ULID;
6
+ }
7
+ export declare function registerGroupSource({ apiKeyOverride, apiURLOverride, groupID, logger }: {
8
+ apiKeyOverride?: string;
9
+ apiURLOverride?: string;
10
+ groupID: ULID;
11
+ logger?: Logger;
12
+ }): Promise<RegisterGroupSourceResult>;
@@ -0,0 +1,4 @@
1
+ import type { ConfigurationOverrides } from "./configuration.js";
2
+ export declare function startInferenceAgentForGroup({ configurationOverrides }: {
3
+ configurationOverrides?: ConfigurationOverrides;
4
+ }): Promise<void>;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@infersec/conduit",
3
3
  "description": "End user conduit agent for connecting local LLMs to the cloud.",
4
- "version": "1.105.0",
4
+ "version": "1.107.0",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },