@infersec/conduit 1.104.0 → 1.106.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",
@@ -21494,11 +21626,15 @@ const ModelEndpointCallConfigSchema = object$1({
21494
21626
  });
21495
21627
  const ModelSourceCallConfigSchema = object$1({
21496
21628
  description: string$2().min(1),
21629
+ groupId: ULIDSchema.optional(),
21497
21630
  inputSchema: record(string$2(), unknown()).optional(),
21498
21631
  outputSchema: record(string$2(), unknown()).optional(),
21499
- sourceId: string$2().min(1),
21632
+ sourceId: ULIDSchema.optional(),
21500
21633
  systemPrompt: string$2().optional(),
21501
21634
  type: literal("model-source-call")
21635
+ })
21636
+ .refine(config => Boolean(config.sourceId) !== Boolean(config.groupId), {
21637
+ message: "Exactly one of sourceId or groupId must be set"
21502
21638
  });
21503
21639
  discriminatedUnion("type", [
21504
21640
  AccountManagementConfigSchema,
@@ -22333,6 +22469,22 @@ function buildConfigurationOverrides(options) {
22333
22469
  return configurationOverrides;
22334
22470
  }
22335
22471
 
22472
+ function buildGroupConfigurationOverrides(options) {
22473
+ const group = options.group ?? readEnvStringOptional("GROUP_ID", undefined);
22474
+ if (options.source && group) {
22475
+ throw new Error("Options --source and --group are mutually exclusive");
22476
+ }
22477
+ if (!group) {
22478
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
22479
+ }
22480
+ const overrides = buildConfigurationOverrides({
22481
+ ...options,
22482
+ source: undefined
22483
+ });
22484
+ overrides.groupID = group;
22485
+ return overrides;
22486
+ }
22487
+
22336
22488
  function commonjsRequire(path) {
22337
22489
  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
22490
  }
@@ -136620,6 +136772,81 @@ function createSignalShutdown$1({ connection, logger }) {
136620
136772
  };
136621
136773
  }
136622
136774
 
136775
+ async function resolveGroupRegistrationConfig({ apiKeyOverride, apiURLOverride }) {
136776
+ const apiKey = apiKeyOverride ?? readEnvString("API_KEY");
136777
+ const apiURL = apiURLOverride ?? readEnvStringOptional("API_URL", "https://api.infersec.ai");
136778
+ return { apiKey, apiURL };
136779
+ }
136780
+ async function registerGroupSource({ apiKeyOverride, apiURLOverride, groupID, logger }) {
136781
+ const log = logger ?? createLogger({ name: "infersec-conduit" });
136782
+ const { apiKey, apiURL } = await resolveGroupRegistrationConfig({
136783
+ apiKeyOverride,
136784
+ apiURLOverride
136785
+ });
136786
+ const fetchWithAPIKey = createFetchWithHeaders({
136787
+ fetchFn: async (input, init) => {
136788
+ try {
136789
+ return await fetchWithRetry(input, init, {
136790
+ maxAttempts: 4,
136791
+ timeoutMs: 10000
136792
+ });
136793
+ }
136794
+ catch (error) {
136795
+ log.warn("API request failed after retries", getNetworkErrorAttributes(error));
136796
+ throw error;
136797
+ }
136798
+ },
136799
+ headers: {
136800
+ "x-api-key": apiKey
136801
+ }
136802
+ });
136803
+ try {
136804
+ const result = (await fetchByReference({
136805
+ baseURL: apiURL,
136806
+ body: {},
136807
+ fetch: fetchWithAPIKey,
136808
+ method: "POST",
136809
+ parameters: {
136810
+ groupID
136811
+ },
136812
+ reference: API_SERVICE_CONDUIT_API_REFERENCE,
136813
+ route: "/conduit/api/v1/source-group/:groupID/register"
136814
+ }));
136815
+ log.info("Registered ephemeral source for group", {
136816
+ groupID,
136817
+ inferenceSourceID: result.sourceID
136818
+ });
136819
+ return result;
136820
+ }
136821
+ catch (error) {
136822
+ log.error("Source group registration failed", { error: asError(error), groupID });
136823
+ throw error;
136824
+ }
136825
+ }
136826
+
136827
+ async function startInferenceAgentForGroup({ configurationOverrides }) {
136828
+ setDefaultResultOrder("ipv4first");
136829
+ const logger = createLogger({
136830
+ name: "infersec-conduit"
136831
+ });
136832
+ const groupID = configurationOverrides?.groupID ?? readEnvStringOptional("GROUP_ID", undefined);
136833
+ if (!groupID) {
136834
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
136835
+ }
136836
+ const registration = await registerGroupSource({
136837
+ apiKeyOverride: configurationOverrides?.apiKey,
136838
+ apiURLOverride: configurationOverrides?.apiURL,
136839
+ groupID,
136840
+ logger
136841
+ });
136842
+ await startInferenceAgent({
136843
+ configurationOverrides: {
136844
+ ...configurationOverrides,
136845
+ inferenceSourceID: registration.sourceID
136846
+ }
136847
+ });
136848
+ }
136849
+
136623
136850
  function registerInferenceCommands({ program }) {
136624
136851
  const inference = program.command("inference").description("Manage inference agent");
136625
136852
  inference
@@ -136636,6 +136863,21 @@ function registerInferenceCommands({ program }) {
136636
136863
  const configurationOverrides = buildConfigurationOverrides(options);
136637
136864
  await startInferenceAgent({ configurationOverrides });
136638
136865
  });
136866
+ const group = inference.command("group").description("Manage source group agents");
136867
+ group
136868
+ .command("start")
136869
+ .description("Start an inference agent for a source group (registers an ephemeral source)")
136870
+ .option("--api-url <url>", "API base URL (or API_URL env)")
136871
+ .option("--engine-port <number>", "Engine port (or ENGINE_PORT env)")
136872
+ .option("--group <id>", "Source group ID (or GROUP_ID env)")
136873
+ .option("--key <value>", "API key (or API_KEY env)")
136874
+ .option("--port <number>", "Port to listen on (or PORT env)")
136875
+ .option("--root <path>", "Root directory (or ROOT_DIRECTORY env)")
136876
+ .option("--start-mode <mode>", "Startup mode: auto|idle (or START_MODE env)")
136877
+ .action(async (options) => {
136878
+ const configurationOverrides = buildGroupConfigurationOverrides(options);
136879
+ await startInferenceAgentForGroup({ configurationOverrides });
136880
+ });
136639
136881
  }
136640
136882
 
136641
136883
  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",
@@ -21509,11 +21641,15 @@ const ModelEndpointCallConfigSchema = object$1({
21509
21641
  });
21510
21642
  const ModelSourceCallConfigSchema = object$1({
21511
21643
  description: string$2().min(1),
21644
+ groupId: ULIDSchema.optional(),
21512
21645
  inputSchema: record(string$2(), unknown()).optional(),
21513
21646
  outputSchema: record(string$2(), unknown()).optional(),
21514
- sourceId: string$2().min(1),
21647
+ sourceId: ULIDSchema.optional(),
21515
21648
  systemPrompt: string$2().optional(),
21516
21649
  type: literal("model-source-call")
21650
+ })
21651
+ .refine(config => Boolean(config.sourceId) !== Boolean(config.groupId), {
21652
+ message: "Exactly one of sourceId or groupId must be set"
21517
21653
  });
21518
21654
  discriminatedUnion("type", [
21519
21655
  AccountManagementConfigSchema,
@@ -22348,6 +22484,22 @@ function buildConfigurationOverrides(options) {
22348
22484
  return configurationOverrides;
22349
22485
  }
22350
22486
 
22487
+ function buildGroupConfigurationOverrides(options) {
22488
+ const group = options.group ?? readEnvStringOptional("GROUP_ID", undefined);
22489
+ if (options.source && group) {
22490
+ throw new Error("Options --source and --group are mutually exclusive");
22491
+ }
22492
+ if (!group) {
22493
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
22494
+ }
22495
+ const overrides = buildConfigurationOverrides({
22496
+ ...options,
22497
+ source: undefined
22498
+ });
22499
+ overrides.groupID = group;
22500
+ return overrides;
22501
+ }
22502
+
22351
22503
  function commonjsRequire(path) {
22352
22504
  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
22505
  }
@@ -156850,6 +157002,81 @@ function createSignalShutdown$1({ connection, logger }) {
156850
157002
  };
156851
157003
  }
156852
157004
 
157005
+ async function resolveGroupRegistrationConfig({ apiKeyOverride, apiURLOverride }) {
157006
+ const apiKey = apiKeyOverride ?? readEnvString("API_KEY");
157007
+ const apiURL = apiURLOverride ?? readEnvStringOptional("API_URL", "https://api.infersec.ai");
157008
+ return { apiKey, apiURL };
157009
+ }
157010
+ async function registerGroupSource({ apiKeyOverride, apiURLOverride, groupID, logger }) {
157011
+ const log = logger ?? createLogger({ name: "infersec-conduit" });
157012
+ const { apiKey, apiURL } = await resolveGroupRegistrationConfig({
157013
+ apiKeyOverride,
157014
+ apiURLOverride
157015
+ });
157016
+ const fetchWithAPIKey = createFetchWithHeaders({
157017
+ fetchFn: async (input, init) => {
157018
+ try {
157019
+ return await fetchWithRetry(input, init, {
157020
+ maxAttempts: 4,
157021
+ timeoutMs: 10000
157022
+ });
157023
+ }
157024
+ catch (error) {
157025
+ log.warn("API request failed after retries", getNetworkErrorAttributes(error));
157026
+ throw error;
157027
+ }
157028
+ },
157029
+ headers: {
157030
+ "x-api-key": apiKey
157031
+ }
157032
+ });
157033
+ try {
157034
+ const result = (await fetchByReference({
157035
+ baseURL: apiURL,
157036
+ body: {},
157037
+ fetch: fetchWithAPIKey,
157038
+ method: "POST",
157039
+ parameters: {
157040
+ groupID
157041
+ },
157042
+ reference: API_SERVICE_CONDUIT_API_REFERENCE,
157043
+ route: "/conduit/api/v1/source-group/:groupID/register"
157044
+ }));
157045
+ log.info("Registered ephemeral source for group", {
157046
+ groupID,
157047
+ inferenceSourceID: result.sourceID
157048
+ });
157049
+ return result;
157050
+ }
157051
+ catch (error) {
157052
+ log.error("Source group registration failed", { error: asError(error), groupID });
157053
+ throw error;
157054
+ }
157055
+ }
157056
+
157057
+ async function startInferenceAgentForGroup({ configurationOverrides }) {
157058
+ require$$1$a.setDefaultResultOrder("ipv4first");
157059
+ const logger = createLogger({
157060
+ name: "infersec-conduit"
157061
+ });
157062
+ const groupID = configurationOverrides?.groupID ?? readEnvStringOptional("GROUP_ID", undefined);
157063
+ if (!groupID) {
157064
+ throw new Error("A source group ID is required (--group or GROUP_ID env)");
157065
+ }
157066
+ const registration = await registerGroupSource({
157067
+ apiKeyOverride: configurationOverrides?.apiKey,
157068
+ apiURLOverride: configurationOverrides?.apiURL,
157069
+ groupID,
157070
+ logger
157071
+ });
157072
+ await startInferenceAgent({
157073
+ configurationOverrides: {
157074
+ ...configurationOverrides,
157075
+ inferenceSourceID: registration.sourceID
157076
+ }
157077
+ });
157078
+ }
157079
+
156853
157080
  function registerInferenceCommands({ program }) {
156854
157081
  const inference = program.command("inference").description("Manage inference agent");
156855
157082
  inference
@@ -156866,6 +157093,21 @@ function registerInferenceCommands({ program }) {
156866
157093
  const configurationOverrides = buildConfigurationOverrides(options);
156867
157094
  await startInferenceAgent({ configurationOverrides });
156868
157095
  });
157096
+ const group = inference.command("group").description("Manage source group agents");
157097
+ group
157098
+ .command("start")
157099
+ .description("Start an inference agent for a source group (registers an ephemeral source)")
157100
+ .option("--api-url <url>", "API base URL (or API_URL env)")
157101
+ .option("--engine-port <number>", "Engine port (or ENGINE_PORT env)")
157102
+ .option("--group <id>", "Source group ID (or GROUP_ID env)")
157103
+ .option("--key <value>", "API key (or API_KEY env)")
157104
+ .option("--port <number>", "Port to listen on (or PORT env)")
157105
+ .option("--root <path>", "Root directory (or ROOT_DIRECTORY env)")
157106
+ .option("--start-mode <mode>", "Startup mode: auto|idle (or START_MODE env)")
157107
+ .action(async (options) => {
157108
+ const configurationOverrides = buildGroupConfigurationOverrides(options);
157109
+ await startInferenceAgentForGroup({ configurationOverrides });
157110
+ });
156869
157111
  }
156870
157112
 
156871
157113
  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.104.0",
4
+ "version": "1.106.0",
5
5
  "bin": {
6
6
  "infersec-conduit": "./dist/cli.js"
7
7
  },