feat(runtime): workspace_root 제거와 tool 호환을 반영한다
Node store/workspace 위치를 Edge가 내려주는 runtime payload에서 분리한다. Chat Completions tool 요청은 내부 실행에서 tool_choice=none으로 낮춰 downstream 자동 tool 호출 요구로 실패하지 않게 맞춘다.
This commit is contained in:
parent
94ac2e6e57
commit
912e900244
39 changed files with 1187 additions and 509 deletions
|
|
@ -39,7 +39,7 @@ tracked config에는 public 예시와 기본 구조만 두고, 실제 endpoint/c
|
|||
## refresh 분류 기준
|
||||
|
||||
- live apply 가능: provider capacity, provider max queue, provider queue timeout, `models[]` display/provider mapping, node runtime concurrency.
|
||||
- restart required: Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, node workspace root, provider type/category/adapter/models/health/lifecycle capability.
|
||||
- restart required: Edge identity/listen/bootstrap/logging/metrics/console/control-plane/openai/a2a listener config, node 추가/삭제, node token/alias/agent kind, adapter 설정, provider type/category/adapter/models/health/lifecycle capability.
|
||||
- rejected: candidate config load/validate 실패, invalid refresh mode, apply failure.
|
||||
|
||||
## 금지 사항
|
||||
|
|
|
|||
|
|
@ -47,7 +47,7 @@ Edge는 Node 연결을 수락하고, Node는 연결 직후 등록 요청을 보
|
|||
- `NodeCommandRequest.type`: 실행이 아닌 조회/제어성 명령이다. adapter execution 요청과 섞지 않는다.
|
||||
- `NodeConfigPayload.adapters`: Edge가 Node에 내려주는 adapter instance 설정이다.
|
||||
- `AdapterConfig.name`: node 내부 stable adapter instance identity다. 비어 있으면 legacy single-instance type 이름과 동등하다.
|
||||
- `NodeRuntimeConfig.workspace_root`: node runtime/store/workspace 기준 경로다. OS별 경로를 섞어 쓰지 않는다.
|
||||
- `NodeRuntimeConfig.concurrency`: node-wide 실행 동시성 제한이다. Node store 위치나 CLI 실행 작업 디렉터리는 이 runtime payload에 싣지 않는다.
|
||||
|
||||
## 금지 사항
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
- `apps/edge/internal/openai/chat_handler.go`
|
||||
- `apps/edge/internal/openai/responses_handler.go`
|
||||
- `apps/edge/internal/openai/types.go`
|
||||
- `apps/node/internal/adapters/openai_compat/openai_compat.go`
|
||||
- `packages/go/config/config.go`
|
||||
- `configs/edge.yaml`
|
||||
- human docs: `docs/openai-compatible-api-contract.md`
|
||||
|
|
@ -160,6 +161,13 @@ Workspace-bound route는 workspace가 없거나 상대 경로이면 OpenAI-compa
|
|||
- `stop`
|
||||
- `response_format`
|
||||
- `tools`
|
||||
- `tool_choice`
|
||||
- `parallel_tool_calls`
|
||||
- `stream_options`
|
||||
|
||||
`tools`가 있는 Chat Completions 요청에서 현재 Edge는 OpenAI tool call 생성을 보장하지 않는다.
|
||||
호환성을 위해 `tool_choice`가 생략되었거나 `auto`/강제 tool 선택 형태로 들어오면 내부 실행 입력에서는 `tool_choice: "none"`으로 낮춰 백엔드의 auto tool-calling 요구 조건에 의해 요청 전체가 실패하지 않게 한다.
|
||||
`parallel_tool_calls`와 `stream_options`는 클라이언트 호환성을 위해 수신하지만 현재 Edge 실행 의미에는 반영하지 않는다.
|
||||
|
||||
금지:
|
||||
|
||||
|
|
|
|||
|
|
@ -605,6 +605,7 @@ class EdgeNodeSnapshot extends $pb.GeneratedMessage {
|
|||
$core.String? label,
|
||||
$core.bool? connected,
|
||||
$0.NodeConfigPayload? config,
|
||||
$core.Iterable<$0.ProviderSnapshot>? providerSnapshots,
|
||||
}) {
|
||||
final result = create();
|
||||
if (nodeId != null) result.nodeId = nodeId;
|
||||
|
|
@ -612,6 +613,8 @@ class EdgeNodeSnapshot extends $pb.GeneratedMessage {
|
|||
if (label != null) result.label = label;
|
||||
if (connected != null) result.connected = connected;
|
||||
if (config != null) result.config = config;
|
||||
if (providerSnapshots != null)
|
||||
result.providerSnapshots.addAll(providerSnapshots);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -634,6 +637,8 @@ class EdgeNodeSnapshot extends $pb.GeneratedMessage {
|
|||
..aOB(4, _omitFieldNames ? '' : 'connected')
|
||||
..aOM<$0.NodeConfigPayload>(5, _omitFieldNames ? '' : 'config',
|
||||
subBuilder: $0.NodeConfigPayload.create)
|
||||
..pPM<$0.ProviderSnapshot>(6, _omitFieldNames ? '' : 'providerSnapshots',
|
||||
subBuilder: $0.ProviderSnapshot.create)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -701,6 +706,9 @@ class EdgeNodeSnapshot extends $pb.GeneratedMessage {
|
|||
void clearConfig() => $_clearField(5);
|
||||
@$pb.TagNumber(5)
|
||||
$0.NodeConfigPayload ensureConfig() => $_ensure(4);
|
||||
|
||||
@$pb.TagNumber(6)
|
||||
$pb.PbList<$0.ProviderSnapshot> get providerSnapshots => $_getList(5);
|
||||
}
|
||||
|
||||
/// EdgeStatusResponse returns the Edge-owned node snapshot list in reply to an
|
||||
|
|
|
|||
|
|
@ -205,6 +205,14 @@ const EdgeNodeSnapshot$json = {
|
|||
'6': '.iop.NodeConfigPayload',
|
||||
'10': 'config'
|
||||
},
|
||||
{
|
||||
'1': 'provider_snapshots',
|
||||
'3': 6,
|
||||
'4': 3,
|
||||
'5': 11,
|
||||
'6': '.iop.ProviderSnapshot',
|
||||
'10': 'providerSnapshots'
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
|
|
@ -212,7 +220,9 @@ const EdgeNodeSnapshot$json = {
|
|||
final $typed_data.Uint8List edgeNodeSnapshotDescriptor = $convert.base64Decode(
|
||||
'ChBFZGdlTm9kZVNuYXBzaG90EhcKB25vZGVfaWQYASABKAlSBm5vZGVJZBIUCgVhbGlhcxgCIA'
|
||||
'EoCVIFYWxpYXMSFAoFbGFiZWwYAyABKAlSBWxhYmVsEhwKCWNvbm5lY3RlZBgEIAEoCFIJY29u'
|
||||
'bmVjdGVkEi4KBmNvbmZpZxgFIAEoCzIWLmlvcC5Ob2RlQ29uZmlnUGF5bG9hZFIGY29uZmln');
|
||||
'bmVjdGVkEi4KBmNvbmZpZxgFIAEoCzIWLmlvcC5Ob2RlQ29uZmlnUGF5bG9hZFIGY29uZmlnEk'
|
||||
'QKEnByb3ZpZGVyX3NuYXBzaG90cxgGIAMoCzIVLmlvcC5Qcm92aWRlclNuYXBzaG90UhFwcm92'
|
||||
'aWRlclNuYXBzaG90cw==');
|
||||
|
||||
@$core.Deprecated('Use edgeStatusResponseDescriptor instead')
|
||||
const EdgeStatusResponse$json = {
|
||||
|
|
|
|||
|
|
@ -883,6 +883,7 @@ class NodeCommandResponse extends $pb.GeneratedMessage {
|
|||
AgentUsageStatus? usageStatus,
|
||||
$core.String? error,
|
||||
$core.Iterable<$core.MapEntry<$core.String, $core.String>>? result,
|
||||
$core.Iterable<ProviderSnapshot>? providerSnapshots,
|
||||
}) {
|
||||
final result$ = create();
|
||||
if (requestId != null) result$.requestId = requestId;
|
||||
|
|
@ -893,6 +894,8 @@ class NodeCommandResponse extends $pb.GeneratedMessage {
|
|||
if (usageStatus != null) result$.usageStatus = usageStatus;
|
||||
if (error != null) result$.error = error;
|
||||
if (result != null) result$.result.addEntries(result);
|
||||
if (providerSnapshots != null)
|
||||
result$.providerSnapshots.addAll(providerSnapshots);
|
||||
return result$;
|
||||
}
|
||||
|
||||
|
|
@ -923,6 +926,8 @@ class NodeCommandResponse extends $pb.GeneratedMessage {
|
|||
keyFieldType: $pb.PbFieldType.OS,
|
||||
valueFieldType: $pb.PbFieldType.OS,
|
||||
packageName: const $pb.PackageName('iop'))
|
||||
..pPM<ProviderSnapshot>(9, _omitFieldNames ? '' : 'providerSnapshots',
|
||||
subBuilder: ProviderSnapshot.create)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -1014,6 +1019,194 @@ class NodeCommandResponse extends $pb.GeneratedMessage {
|
|||
/// dedicated typed payload.
|
||||
@$pb.TagNumber(8)
|
||||
$pb.PbMap<$core.String, $core.String> get result => $_getMap(7);
|
||||
|
||||
@$pb.TagNumber(9)
|
||||
$pb.PbList<ProviderSnapshot> get providerSnapshots => $_getList(8);
|
||||
}
|
||||
|
||||
class ProviderSnapshot extends $pb.GeneratedMessage {
|
||||
factory ProviderSnapshot({
|
||||
$core.String? adapter,
|
||||
$core.String? status,
|
||||
$core.int? capacity,
|
||||
$core.int? inFlight,
|
||||
$core.int? queued,
|
||||
$core.String? id,
|
||||
$core.String? type,
|
||||
$core.String? category,
|
||||
$core.Iterable<$core.String>? servedModels,
|
||||
$core.String? health,
|
||||
$core.double? loadRatio,
|
||||
$core.Iterable<$core.String>? lifecycleCapabilities,
|
||||
}) {
|
||||
final result = create();
|
||||
if (adapter != null) result.adapter = adapter;
|
||||
if (status != null) result.status = status;
|
||||
if (capacity != null) result.capacity = capacity;
|
||||
if (inFlight != null) result.inFlight = inFlight;
|
||||
if (queued != null) result.queued = queued;
|
||||
if (id != null) result.id = id;
|
||||
if (type != null) result.type = type;
|
||||
if (category != null) result.category = category;
|
||||
if (servedModels != null) result.servedModels.addAll(servedModels);
|
||||
if (health != null) result.health = health;
|
||||
if (loadRatio != null) result.loadRatio = loadRatio;
|
||||
if (lifecycleCapabilities != null)
|
||||
result.lifecycleCapabilities.addAll(lifecycleCapabilities);
|
||||
return result;
|
||||
}
|
||||
|
||||
ProviderSnapshot._();
|
||||
|
||||
factory ProviderSnapshot.fromBuffer($core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory ProviderSnapshot.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'ProviderSnapshot',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'adapter')
|
||||
..aOS(2, _omitFieldNames ? '' : 'status')
|
||||
..aI(3, _omitFieldNames ? '' : 'capacity')
|
||||
..aI(4, _omitFieldNames ? '' : 'inFlight')
|
||||
..aI(5, _omitFieldNames ? '' : 'queued')
|
||||
..aOS(6, _omitFieldNames ? '' : 'id')
|
||||
..aOS(7, _omitFieldNames ? '' : 'type')
|
||||
..aOS(8, _omitFieldNames ? '' : 'category')
|
||||
..pPS(9, _omitFieldNames ? '' : 'servedModels')
|
||||
..aOS(10, _omitFieldNames ? '' : 'health')
|
||||
..aD(11, _omitFieldNames ? '' : 'loadRatio', fieldType: $pb.PbFieldType.OF)
|
||||
..pPS(12, _omitFieldNames ? '' : 'lifecycleCapabilities')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
ProviderSnapshot clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
ProviderSnapshot copyWith(void Function(ProviderSnapshot) updates) =>
|
||||
super.copyWith((message) => updates(message as ProviderSnapshot))
|
||||
as ProviderSnapshot;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ProviderSnapshot create() => ProviderSnapshot._();
|
||||
@$core.override
|
||||
ProviderSnapshot createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ProviderSnapshot getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<ProviderSnapshot>(create);
|
||||
static ProviderSnapshot? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get adapter => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set adapter($core.String value) => $_setString(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasAdapter() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearAdapter() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get status => $_getSZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set status($core.String value) => $_setString(1, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasStatus() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearStatus() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get capacity => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set capacity($core.int value) => $_setSignedInt32(2, value);
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasCapacity() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearCapacity() => $_clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get inFlight => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set inFlight($core.int value) => $_setSignedInt32(3, value);
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasInFlight() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearInFlight() => $_clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.int get queued => $_getIZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set queued($core.int value) => $_setSignedInt32(4, value);
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasQueued() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearQueued() => $_clearField(5);
|
||||
|
||||
/// Provider catalog fields (MVP).
|
||||
/// id uniquely identifies this provider within its node.
|
||||
@$pb.TagNumber(6)
|
||||
$core.String get id => $_getSZ(5);
|
||||
@$pb.TagNumber(6)
|
||||
set id($core.String value) => $_setString(5, value);
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool hasId() => $_has(5);
|
||||
@$pb.TagNumber(6)
|
||||
void clearId() => $_clearField(6);
|
||||
|
||||
/// type is the runtime type (e.g. "ollama", "vllm", "lemonade", "sglang", "openai_api", "cli").
|
||||
@$pb.TagNumber(7)
|
||||
$core.String get type => $_getSZ(6);
|
||||
@$pb.TagNumber(7)
|
||||
set type($core.String value) => $_setString(6, value);
|
||||
@$pb.TagNumber(7)
|
||||
$core.bool hasType() => $_has(6);
|
||||
@$pb.TagNumber(7)
|
||||
void clearType() => $_clearField(7);
|
||||
|
||||
/// category classifies the provider; MVP values: api, cli, local_inference.
|
||||
@$pb.TagNumber(8)
|
||||
$core.String get category => $_getSZ(7);
|
||||
@$pb.TagNumber(8)
|
||||
set category($core.String value) => $_setString(7, value);
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool hasCategory() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearCategory() => $_clearField(8);
|
||||
|
||||
/// served_models lists the model names this provider can actually serve.
|
||||
@$pb.TagNumber(9)
|
||||
$pb.PbList<$core.String> get servedModels => $_getList(8);
|
||||
|
||||
/// health is the observed provider health state (e.g. "healthy", "degraded", "unhealthy").
|
||||
@$pb.TagNumber(10)
|
||||
$core.String get health => $_getSZ(9);
|
||||
@$pb.TagNumber(10)
|
||||
set health($core.String value) => $_setString(9, value);
|
||||
@$pb.TagNumber(10)
|
||||
$core.bool hasHealth() => $_has(9);
|
||||
@$pb.TagNumber(10)
|
||||
void clearHealth() => $_clearField(10);
|
||||
|
||||
/// load_ratio is the computed in_flight / capacity value. When capacity is 0
|
||||
/// or unknown the provider is treated as unavailable for selection.
|
||||
@$pb.TagNumber(11)
|
||||
$core.double get loadRatio => $_getN(10);
|
||||
@$pb.TagNumber(11)
|
||||
set loadRatio($core.double value) => $_setFloat(10, value);
|
||||
@$pb.TagNumber(11)
|
||||
$core.bool hasLoadRatio() => $_has(10);
|
||||
@$pb.TagNumber(11)
|
||||
void clearLoadRatio() => $_clearField(11);
|
||||
|
||||
/// lifecycle_capabilities lists coarse lifecycle capability flags (e.g.
|
||||
/// "list_models", "load_model", "unload_model", "pull_model", "delete_model").
|
||||
@$pb.TagNumber(12)
|
||||
$pb.PbList<$core.String> get lifecycleCapabilities => $_getList(11);
|
||||
}
|
||||
|
||||
class AgentUsageStatus extends $pb.GeneratedMessage {
|
||||
|
|
@ -1420,9 +1613,12 @@ class NodeConfigPayload extends $pb.GeneratedMessage {
|
|||
NodeRuntimeConfig ensureRuntime() => $_ensure(1);
|
||||
}
|
||||
|
||||
enum AdapterConfig_Config { cli, ollama, vllm, mock, notSet }
|
||||
enum AdapterConfig_Config { cli, ollama, vllm, mock, openaiCompat, notSet }
|
||||
|
||||
/// AdapterConfig describes one adapter to enable on the node.
|
||||
/// name is the stable instance identity within a node; for single-instance
|
||||
/// adapters it may be empty (equivalent to the type name). When a node carries
|
||||
/// multiple instances of the same adapter type each must have a unique name.
|
||||
class AdapterConfig extends $pb.GeneratedMessage {
|
||||
factory AdapterConfig({
|
||||
$core.String? type,
|
||||
|
|
@ -1432,6 +1628,9 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
OllamaAdapterConfig? ollama,
|
||||
VllmAdapterConfig? vllm,
|
||||
MockAdapterConfig? mock,
|
||||
$core.String? name,
|
||||
$core.String? target,
|
||||
OpenAICompatAdapterConfig? openaiCompat,
|
||||
}) {
|
||||
final result = create();
|
||||
if (type != null) result.type = type;
|
||||
|
|
@ -1441,6 +1640,9 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
if (ollama != null) result.ollama = ollama;
|
||||
if (vllm != null) result.vllm = vllm;
|
||||
if (mock != null) result.mock = mock;
|
||||
if (name != null) result.name = name;
|
||||
if (target != null) result.target = target;
|
||||
if (openaiCompat != null) result.openaiCompat = openaiCompat;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1459,13 +1661,14 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
5: AdapterConfig_Config.ollama,
|
||||
6: AdapterConfig_Config.vllm,
|
||||
7: AdapterConfig_Config.mock,
|
||||
10: AdapterConfig_Config.openaiCompat,
|
||||
0: AdapterConfig_Config.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'AdapterConfig',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..oo(0, [4, 5, 6, 7])
|
||||
..oo(0, [4, 5, 6, 7, 10])
|
||||
..aOS(1, _omitFieldNames ? '' : 'type')
|
||||
..aOB(2, _omitFieldNames ? '' : 'enabled')
|
||||
..aOM<$0.Struct>(3, _omitFieldNames ? '' : 'settings',
|
||||
|
|
@ -1478,6 +1681,10 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
subBuilder: VllmAdapterConfig.create)
|
||||
..aOM<MockAdapterConfig>(7, _omitFieldNames ? '' : 'mock',
|
||||
subBuilder: MockAdapterConfig.create)
|
||||
..aOS(8, _omitFieldNames ? '' : 'name')
|
||||
..aOS(9, _omitFieldNames ? '' : 'target')
|
||||
..aOM<OpenAICompatAdapterConfig>(10, _omitFieldNames ? '' : 'openaiCompat',
|
||||
subBuilder: OpenAICompatAdapterConfig.create)
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -1503,12 +1710,14 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
@$pb.TagNumber(5)
|
||||
@$pb.TagNumber(6)
|
||||
@$pb.TagNumber(7)
|
||||
@$pb.TagNumber(10)
|
||||
AdapterConfig_Config whichConfig() =>
|
||||
_AdapterConfig_ConfigByTag[$_whichOneof(0)]!;
|
||||
@$pb.TagNumber(4)
|
||||
@$pb.TagNumber(5)
|
||||
@$pb.TagNumber(6)
|
||||
@$pb.TagNumber(7)
|
||||
@$pb.TagNumber(10)
|
||||
void clearConfig() => $_clearField($_whichOneof(0));
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
|
|
@ -1583,6 +1792,35 @@ class AdapterConfig extends $pb.GeneratedMessage {
|
|||
void clearMock() => $_clearField(7);
|
||||
@$pb.TagNumber(7)
|
||||
MockAdapterConfig ensureMock() => $_ensure(6);
|
||||
|
||||
@$pb.TagNumber(8)
|
||||
$core.String get name => $_getSZ(7);
|
||||
@$pb.TagNumber(8)
|
||||
set name($core.String value) => $_setString(7, value);
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool hasName() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearName() => $_clearField(8);
|
||||
|
||||
@$pb.TagNumber(9)
|
||||
$core.String get target => $_getSZ(8);
|
||||
@$pb.TagNumber(9)
|
||||
set target($core.String value) => $_setString(8, value);
|
||||
@$pb.TagNumber(9)
|
||||
$core.bool hasTarget() => $_has(8);
|
||||
@$pb.TagNumber(9)
|
||||
void clearTarget() => $_clearField(9);
|
||||
|
||||
@$pb.TagNumber(10)
|
||||
OpenAICompatAdapterConfig get openaiCompat => $_getN(9);
|
||||
@$pb.TagNumber(10)
|
||||
set openaiCompat(OpenAICompatAdapterConfig value) => $_setField(10, value);
|
||||
@$pb.TagNumber(10)
|
||||
$core.bool hasOpenaiCompat() => $_has(9);
|
||||
@$pb.TagNumber(10)
|
||||
void clearOpenaiCompat() => $_clearField(10);
|
||||
@$pb.TagNumber(10)
|
||||
OpenAICompatAdapterConfig ensureOpenaiCompat() => $_ensure(9);
|
||||
}
|
||||
|
||||
class MockAdapterConfig extends $pb.GeneratedMessage {
|
||||
|
|
@ -1908,10 +2146,18 @@ class OllamaAdapterConfig extends $pb.GeneratedMessage {
|
|||
factory OllamaAdapterConfig({
|
||||
$core.String? baseUrl,
|
||||
$core.int? contextSize,
|
||||
$core.int? capacity,
|
||||
$core.int? maxQueue,
|
||||
$core.int? queueTimeoutMs,
|
||||
$core.int? requestTimeoutMs,
|
||||
}) {
|
||||
final result = create();
|
||||
if (baseUrl != null) result.baseUrl = baseUrl;
|
||||
if (contextSize != null) result.contextSize = contextSize;
|
||||
if (capacity != null) result.capacity = capacity;
|
||||
if (maxQueue != null) result.maxQueue = maxQueue;
|
||||
if (queueTimeoutMs != null) result.queueTimeoutMs = queueTimeoutMs;
|
||||
if (requestTimeoutMs != null) result.requestTimeoutMs = requestTimeoutMs;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1930,6 +2176,10 @@ class OllamaAdapterConfig extends $pb.GeneratedMessage {
|
|||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'baseUrl')
|
||||
..aI(2, _omitFieldNames ? '' : 'contextSize')
|
||||
..aI(3, _omitFieldNames ? '' : 'capacity')
|
||||
..aI(4, _omitFieldNames ? '' : 'maxQueue')
|
||||
..aI(5, _omitFieldNames ? '' : 'queueTimeoutMs')
|
||||
..aI(6, _omitFieldNames ? '' : 'requestTimeoutMs')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -1968,14 +2218,58 @@ class OllamaAdapterConfig extends $pb.GeneratedMessage {
|
|||
$core.bool hasContextSize() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearContextSize() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get capacity => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set capacity($core.int value) => $_setSignedInt32(2, value);
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasCapacity() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearCapacity() => $_clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get maxQueue => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set maxQueue($core.int value) => $_setSignedInt32(3, value);
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasMaxQueue() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearMaxQueue() => $_clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.int get queueTimeoutMs => $_getIZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set queueTimeoutMs($core.int value) => $_setSignedInt32(4, value);
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasQueueTimeoutMs() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearQueueTimeoutMs() => $_clearField(5);
|
||||
|
||||
@$pb.TagNumber(6)
|
||||
$core.int get requestTimeoutMs => $_getIZ(5);
|
||||
@$pb.TagNumber(6)
|
||||
set requestTimeoutMs($core.int value) => $_setSignedInt32(5, value);
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool hasRequestTimeoutMs() => $_has(5);
|
||||
@$pb.TagNumber(6)
|
||||
void clearRequestTimeoutMs() => $_clearField(6);
|
||||
}
|
||||
|
||||
class VllmAdapterConfig extends $pb.GeneratedMessage {
|
||||
factory VllmAdapterConfig({
|
||||
$core.String? endpoint,
|
||||
$core.int? capacity,
|
||||
$core.int? maxQueue,
|
||||
$core.int? queueTimeoutMs,
|
||||
$core.int? requestTimeoutMs,
|
||||
}) {
|
||||
final result = create();
|
||||
if (endpoint != null) result.endpoint = endpoint;
|
||||
if (capacity != null) result.capacity = capacity;
|
||||
if (maxQueue != null) result.maxQueue = maxQueue;
|
||||
if (queueTimeoutMs != null) result.queueTimeoutMs = queueTimeoutMs;
|
||||
if (requestTimeoutMs != null) result.requestTimeoutMs = requestTimeoutMs;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -1993,6 +2287,10 @@ class VllmAdapterConfig extends $pb.GeneratedMessage {
|
|||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'endpoint')
|
||||
..aI(2, _omitFieldNames ? '' : 'capacity')
|
||||
..aI(3, _omitFieldNames ? '' : 'maxQueue')
|
||||
..aI(4, _omitFieldNames ? '' : 'queueTimeoutMs')
|
||||
..aI(5, _omitFieldNames ? '' : 'requestTimeoutMs')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -2022,17 +2320,176 @@ class VllmAdapterConfig extends $pb.GeneratedMessage {
|
|||
$core.bool hasEndpoint() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearEndpoint() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get capacity => $_getIZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set capacity($core.int value) => $_setSignedInt32(1, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasCapacity() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearCapacity() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.int get maxQueue => $_getIZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set maxQueue($core.int value) => $_setSignedInt32(2, value);
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasMaxQueue() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearMaxQueue() => $_clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get queueTimeoutMs => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set queueTimeoutMs($core.int value) => $_setSignedInt32(3, value);
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasQueueTimeoutMs() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearQueueTimeoutMs() => $_clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.int get requestTimeoutMs => $_getIZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set requestTimeoutMs($core.int value) => $_setSignedInt32(4, value);
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasRequestTimeoutMs() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearRequestTimeoutMs() => $_clearField(5);
|
||||
}
|
||||
|
||||
class OpenAICompatAdapterConfig extends $pb.GeneratedMessage {
|
||||
factory OpenAICompatAdapterConfig({
|
||||
$core.String? provider,
|
||||
$core.String? endpoint,
|
||||
$core.Iterable<$core.MapEntry<$core.String, $core.String>>? headers,
|
||||
$core.int? capacity,
|
||||
$core.int? maxQueue,
|
||||
$core.int? queueTimeoutMs,
|
||||
$core.int? requestTimeoutMs,
|
||||
}) {
|
||||
final result = create();
|
||||
if (provider != null) result.provider = provider;
|
||||
if (endpoint != null) result.endpoint = endpoint;
|
||||
if (headers != null) result.headers.addEntries(headers);
|
||||
if (capacity != null) result.capacity = capacity;
|
||||
if (maxQueue != null) result.maxQueue = maxQueue;
|
||||
if (queueTimeoutMs != null) result.queueTimeoutMs = queueTimeoutMs;
|
||||
if (requestTimeoutMs != null) result.requestTimeoutMs = requestTimeoutMs;
|
||||
return result;
|
||||
}
|
||||
|
||||
OpenAICompatAdapterConfig._();
|
||||
|
||||
factory OpenAICompatAdapterConfig.fromBuffer($core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory OpenAICompatAdapterConfig.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'OpenAICompatAdapterConfig',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'provider')
|
||||
..aOS(2, _omitFieldNames ? '' : 'endpoint')
|
||||
..m<$core.String, $core.String>(3, _omitFieldNames ? '' : 'headers',
|
||||
entryClassName: 'OpenAICompatAdapterConfig.HeadersEntry',
|
||||
keyFieldType: $pb.PbFieldType.OS,
|
||||
valueFieldType: $pb.PbFieldType.OS,
|
||||
packageName: const $pb.PackageName('iop'))
|
||||
..aI(4, _omitFieldNames ? '' : 'capacity')
|
||||
..aI(5, _omitFieldNames ? '' : 'maxQueue')
|
||||
..aI(6, _omitFieldNames ? '' : 'queueTimeoutMs')
|
||||
..aI(7, _omitFieldNames ? '' : 'requestTimeoutMs')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
OpenAICompatAdapterConfig clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
OpenAICompatAdapterConfig copyWith(
|
||||
void Function(OpenAICompatAdapterConfig) updates) =>
|
||||
super.copyWith((message) => updates(message as OpenAICompatAdapterConfig))
|
||||
as OpenAICompatAdapterConfig;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static OpenAICompatAdapterConfig create() => OpenAICompatAdapterConfig._();
|
||||
@$core.override
|
||||
OpenAICompatAdapterConfig createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static OpenAICompatAdapterConfig getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<OpenAICompatAdapterConfig>(create);
|
||||
static OpenAICompatAdapterConfig? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get provider => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set provider($core.String value) => $_setString(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasProvider() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearProvider() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get endpoint => $_getSZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set endpoint($core.String value) => $_setString(1, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasEndpoint() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearEndpoint() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$pb.PbMap<$core.String, $core.String> get headers => $_getMap(2);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.int get capacity => $_getIZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set capacity($core.int value) => $_setSignedInt32(3, value);
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasCapacity() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearCapacity() => $_clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.int get maxQueue => $_getIZ(4);
|
||||
@$pb.TagNumber(5)
|
||||
set maxQueue($core.int value) => $_setSignedInt32(4, value);
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasMaxQueue() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearMaxQueue() => $_clearField(5);
|
||||
|
||||
@$pb.TagNumber(6)
|
||||
$core.int get queueTimeoutMs => $_getIZ(5);
|
||||
@$pb.TagNumber(6)
|
||||
set queueTimeoutMs($core.int value) => $_setSignedInt32(5, value);
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool hasQueueTimeoutMs() => $_has(5);
|
||||
@$pb.TagNumber(6)
|
||||
void clearQueueTimeoutMs() => $_clearField(6);
|
||||
|
||||
@$pb.TagNumber(7)
|
||||
$core.int get requestTimeoutMs => $_getIZ(6);
|
||||
@$pb.TagNumber(7)
|
||||
set requestTimeoutMs($core.int value) => $_setSignedInt32(6, value);
|
||||
@$pb.TagNumber(7)
|
||||
$core.bool hasRequestTimeoutMs() => $_has(6);
|
||||
@$pb.TagNumber(7)
|
||||
void clearRequestTimeoutMs() => $_clearField(7);
|
||||
}
|
||||
|
||||
/// NodeRuntimeConfig is the runtime tuning pushed to the node.
|
||||
class NodeRuntimeConfig extends $pb.GeneratedMessage {
|
||||
factory NodeRuntimeConfig({
|
||||
$core.int? concurrency,
|
||||
$core.String? workspaceRoot,
|
||||
}) {
|
||||
final result = create();
|
||||
if (concurrency != null) result.concurrency = concurrency;
|
||||
if (workspaceRoot != null) result.workspaceRoot = workspaceRoot;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2050,7 +2507,6 @@ class NodeRuntimeConfig extends $pb.GeneratedMessage {
|
|||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aI(1, _omitFieldNames ? '' : 'concurrency')
|
||||
..aOS(2, _omitFieldNames ? '' : 'workspaceRoot')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
|
|
@ -2080,15 +2536,171 @@ class NodeRuntimeConfig extends $pb.GeneratedMessage {
|
|||
$core.bool hasConcurrency() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearConcurrency() => $_clearField(1);
|
||||
}
|
||||
|
||||
/// NodeConfigRefreshRequest is sent by edge to a connected node to push a new config payload.
|
||||
class NodeConfigRefreshRequest extends $pb.GeneratedMessage {
|
||||
factory NodeConfigRefreshRequest({
|
||||
$core.String? requestId,
|
||||
NodeConfigPayload? config,
|
||||
$core.Iterable<$core.String>? changedPaths,
|
||||
}) {
|
||||
final result = create();
|
||||
if (requestId != null) result.requestId = requestId;
|
||||
if (config != null) result.config = config;
|
||||
if (changedPaths != null) result.changedPaths.addAll(changedPaths);
|
||||
return result;
|
||||
}
|
||||
|
||||
NodeConfigRefreshRequest._();
|
||||
|
||||
factory NodeConfigRefreshRequest.fromBuffer($core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory NodeConfigRefreshRequest.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'NodeConfigRefreshRequest',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'requestId')
|
||||
..aOM<NodeConfigPayload>(2, _omitFieldNames ? '' : 'config',
|
||||
subBuilder: NodeConfigPayload.create)
|
||||
..pPS(3, _omitFieldNames ? '' : 'changedPaths')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
NodeConfigRefreshRequest clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
NodeConfigRefreshRequest copyWith(
|
||||
void Function(NodeConfigRefreshRequest) updates) =>
|
||||
super.copyWith((message) => updates(message as NodeConfigRefreshRequest))
|
||||
as NodeConfigRefreshRequest;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static NodeConfigRefreshRequest create() => NodeConfigRefreshRequest._();
|
||||
@$core.override
|
||||
NodeConfigRefreshRequest createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static NodeConfigRefreshRequest getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<NodeConfigRefreshRequest>(create);
|
||||
static NodeConfigRefreshRequest? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get requestId => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set requestId($core.String value) => $_setString(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasRequestId() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearRequestId() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get workspaceRoot => $_getSZ(1);
|
||||
NodeConfigPayload get config => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set workspaceRoot($core.String value) => $_setString(1, value);
|
||||
set config(NodeConfigPayload value) => $_setField(2, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasWorkspaceRoot() => $_has(1);
|
||||
$core.bool hasConfig() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearWorkspaceRoot() => $_clearField(2);
|
||||
void clearConfig() => $_clearField(2);
|
||||
@$pb.TagNumber(2)
|
||||
NodeConfigPayload ensureConfig() => $_ensure(1);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$pb.PbList<$core.String> get changedPaths => $_getList(2);
|
||||
}
|
||||
|
||||
/// NodeConfigRefreshResponse is returned by the node to acknowledge or report failure.
|
||||
class NodeConfigRefreshResponse extends $pb.GeneratedMessage {
|
||||
factory NodeConfigRefreshResponse({
|
||||
$core.String? requestId,
|
||||
NodeConfigRefreshStatus? status,
|
||||
$core.Iterable<$core.String>? restartRequiredPaths,
|
||||
$core.String? error,
|
||||
}) {
|
||||
final result = create();
|
||||
if (requestId != null) result.requestId = requestId;
|
||||
if (status != null) result.status = status;
|
||||
if (restartRequiredPaths != null)
|
||||
result.restartRequiredPaths.addAll(restartRequiredPaths);
|
||||
if (error != null) result.error = error;
|
||||
return result;
|
||||
}
|
||||
|
||||
NodeConfigRefreshResponse._();
|
||||
|
||||
factory NodeConfigRefreshResponse.fromBuffer($core.List<$core.int> data,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromBuffer(data, registry);
|
||||
factory NodeConfigRefreshResponse.fromJson($core.String json,
|
||||
[$pb.ExtensionRegistry registry = $pb.ExtensionRegistry.EMPTY]) =>
|
||||
create()..mergeFromJson(json, registry);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(
|
||||
_omitMessageNames ? '' : 'NodeConfigRefreshResponse',
|
||||
package: const $pb.PackageName(_omitMessageNames ? '' : 'iop'),
|
||||
createEmptyInstance: create)
|
||||
..aOS(1, _omitFieldNames ? '' : 'requestId')
|
||||
..aE<NodeConfigRefreshStatus>(2, _omitFieldNames ? '' : 'status',
|
||||
enumValues: NodeConfigRefreshStatus.values)
|
||||
..pPS(3, _omitFieldNames ? '' : 'restartRequiredPaths')
|
||||
..aOS(4, _omitFieldNames ? '' : 'error')
|
||||
..hasRequiredFields = false;
|
||||
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
NodeConfigRefreshResponse clone() => deepCopy();
|
||||
@$core.Deprecated('See https://github.com/google/protobuf.dart/issues/998.')
|
||||
NodeConfigRefreshResponse copyWith(
|
||||
void Function(NodeConfigRefreshResponse) updates) =>
|
||||
super.copyWith((message) => updates(message as NodeConfigRefreshResponse))
|
||||
as NodeConfigRefreshResponse;
|
||||
|
||||
@$core.override
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static NodeConfigRefreshResponse create() => NodeConfigRefreshResponse._();
|
||||
@$core.override
|
||||
NodeConfigRefreshResponse createEmptyInstance() => create();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static NodeConfigRefreshResponse getDefault() => _defaultInstance ??=
|
||||
$pb.GeneratedMessage.$_defaultFor<NodeConfigRefreshResponse>(create);
|
||||
static NodeConfigRefreshResponse? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get requestId => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set requestId($core.String value) => $_setString(0, value);
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasRequestId() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearRequestId() => $_clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
NodeConfigRefreshStatus get status => $_getN(1);
|
||||
@$pb.TagNumber(2)
|
||||
set status(NodeConfigRefreshStatus value) => $_setField(2, value);
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasStatus() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearStatus() => $_clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$pb.PbList<$core.String> get restartRequiredPaths => $_getList(2);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
$core.String get error => $_getSZ(3);
|
||||
@$pb.TagNumber(4)
|
||||
set error($core.String value) => $_setString(3, value);
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasError() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearError() => $_clearField(4);
|
||||
}
|
||||
|
||||
const $core.bool _omitFieldNames =
|
||||
|
|
|
|||
|
|
@ -96,5 +96,39 @@ class NodeCommandType extends $pb.ProtobufEnum {
|
|||
const NodeCommandType._(super.value, super.name);
|
||||
}
|
||||
|
||||
class NodeConfigRefreshStatus extends $pb.ProtobufEnum {
|
||||
static const NodeConfigRefreshStatus NODE_CONFIG_REFRESH_STATUS_UNSPECIFIED =
|
||||
NodeConfigRefreshStatus._(
|
||||
0, _omitEnumNames ? '' : 'NODE_CONFIG_REFRESH_STATUS_UNSPECIFIED');
|
||||
static const NodeConfigRefreshStatus NODE_CONFIG_REFRESH_STATUS_APPLIED =
|
||||
NodeConfigRefreshStatus._(
|
||||
1, _omitEnumNames ? '' : 'NODE_CONFIG_REFRESH_STATUS_APPLIED');
|
||||
static const NodeConfigRefreshStatus
|
||||
NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED = NodeConfigRefreshStatus._(2,
|
||||
_omitEnumNames ? '' : 'NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED');
|
||||
static const NodeConfigRefreshStatus NODE_CONFIG_REFRESH_STATUS_FAILED =
|
||||
NodeConfigRefreshStatus._(
|
||||
3, _omitEnumNames ? '' : 'NODE_CONFIG_REFRESH_STATUS_FAILED');
|
||||
static const NodeConfigRefreshStatus NODE_CONFIG_REFRESH_STATUS_SKIPPED =
|
||||
NodeConfigRefreshStatus._(
|
||||
4, _omitEnumNames ? '' : 'NODE_CONFIG_REFRESH_STATUS_SKIPPED');
|
||||
|
||||
static const $core.List<NodeConfigRefreshStatus> values =
|
||||
<NodeConfigRefreshStatus>[
|
||||
NODE_CONFIG_REFRESH_STATUS_UNSPECIFIED,
|
||||
NODE_CONFIG_REFRESH_STATUS_APPLIED,
|
||||
NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED,
|
||||
NODE_CONFIG_REFRESH_STATUS_FAILED,
|
||||
NODE_CONFIG_REFRESH_STATUS_SKIPPED,
|
||||
];
|
||||
|
||||
static final $core.List<NodeConfigRefreshStatus?> _byValue =
|
||||
$pb.ProtobufEnum.$_initByValueList(values, 4);
|
||||
static NodeConfigRefreshStatus? valueOf($core.int value) =>
|
||||
value < 0 || value >= _byValue.length ? null : _byValue[value];
|
||||
|
||||
const NodeConfigRefreshStatus._(super.value, super.name);
|
||||
}
|
||||
|
||||
const $core.bool _omitEnumNames =
|
||||
$core.bool.fromEnvironment('protobuf.omit_enum_names');
|
||||
|
|
|
|||
|
|
@ -68,6 +68,26 @@ final $typed_data.Uint8List nodeCommandTypeDescriptor = $convert.base64Decode(
|
|||
'RFX0NPTU1BTkRfVFlQRV9UUkFOU1BPUlRfU1RBVFVTEAQSIAocTk9ERV9DT01NQU5EX1RZUEVf'
|
||||
'T0xMQU1BX0FQSRAF');
|
||||
|
||||
@$core.Deprecated('Use nodeConfigRefreshStatusDescriptor instead')
|
||||
const NodeConfigRefreshStatus$json = {
|
||||
'1': 'NodeConfigRefreshStatus',
|
||||
'2': [
|
||||
{'1': 'NODE_CONFIG_REFRESH_STATUS_UNSPECIFIED', '2': 0},
|
||||
{'1': 'NODE_CONFIG_REFRESH_STATUS_APPLIED', '2': 1},
|
||||
{'1': 'NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED', '2': 2},
|
||||
{'1': 'NODE_CONFIG_REFRESH_STATUS_FAILED', '2': 3},
|
||||
{'1': 'NODE_CONFIG_REFRESH_STATUS_SKIPPED', '2': 4},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `NodeConfigRefreshStatus`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List nodeConfigRefreshStatusDescriptor = $convert.base64Decode(
|
||||
'ChdOb2RlQ29uZmlnUmVmcmVzaFN0YXR1cxIqCiZOT0RFX0NPTkZJR19SRUZSRVNIX1NUQVRVU1'
|
||||
'9VTlNQRUNJRklFRBAAEiYKIk5PREVfQ09ORklHX1JFRlJFU0hfU1RBVFVTX0FQUExJRUQQARIv'
|
||||
'CitOT0RFX0NPTkZJR19SRUZSRVNIX1NUQVRVU19SRVNUQVJUX1JFUVVJUkVEEAISJQohTk9ERV'
|
||||
'9DT05GSUdfUkVGUkVTSF9TVEFUVVNfRkFJTEVEEAMSJgoiTk9ERV9DT05GSUdfUkVGUkVTSF9T'
|
||||
'VEFUVVNfU0tJUFBFRBAE');
|
||||
|
||||
@$core.Deprecated('Use runRequestDescriptor instead')
|
||||
const RunRequest$json = {
|
||||
'1': 'RunRequest',
|
||||
|
|
@ -360,6 +380,14 @@ const NodeCommandResponse$json = {
|
|||
'6': '.iop.NodeCommandResponse.ResultEntry',
|
||||
'10': 'result'
|
||||
},
|
||||
{
|
||||
'1': 'provider_snapshots',
|
||||
'3': 9,
|
||||
'4': 3,
|
||||
'5': 11,
|
||||
'6': '.iop.ProviderSnapshot',
|
||||
'10': 'providerSnapshots'
|
||||
},
|
||||
],
|
||||
'3': [NodeCommandResponse_ResultEntry$json],
|
||||
};
|
||||
|
|
@ -381,8 +409,45 @@ final $typed_data.Uint8List nodeCommandResponseDescriptor = $convert.base64Decod
|
|||
'UgdhZGFwdGVyEhYKBnRhcmdldBgEIAEoCVIGdGFyZ2V0Eh0KCnNlc3Npb25faWQYBSABKAlSCX'
|
||||
'Nlc3Npb25JZBI4Cgx1c2FnZV9zdGF0dXMYBiABKAsyFS5pb3AuQWdlbnRVc2FnZVN0YXR1c1IL'
|
||||
'dXNhZ2VTdGF0dXMSFAoFZXJyb3IYByABKAlSBWVycm9yEjwKBnJlc3VsdBgIIAMoCzIkLmlvcC'
|
||||
'5Ob2RlQ29tbWFuZFJlc3BvbnNlLlJlc3VsdEVudHJ5UgZyZXN1bHQaOQoLUmVzdWx0RW50cnkS'
|
||||
'EAoDa2V5GAEgASgJUgNrZXkSFAoFdmFsdWUYAiABKAlSBXZhbHVlOgI4AQ==');
|
||||
'5Ob2RlQ29tbWFuZFJlc3BvbnNlLlJlc3VsdEVudHJ5UgZyZXN1bHQSRAoScHJvdmlkZXJfc25h'
|
||||
'cHNob3RzGAkgAygLMhUuaW9wLlByb3ZpZGVyU25hcHNob3RSEXByb3ZpZGVyU25hcHNob3RzGj'
|
||||
'kKC1Jlc3VsdEVudHJ5EhAKA2tleRgBIAEoCVIDa2V5EhQKBXZhbHVlGAIgASgJUgV2YWx1ZToC'
|
||||
'OAE=');
|
||||
|
||||
@$core.Deprecated('Use providerSnapshotDescriptor instead')
|
||||
const ProviderSnapshot$json = {
|
||||
'1': 'ProviderSnapshot',
|
||||
'2': [
|
||||
{'1': 'adapter', '3': 1, '4': 1, '5': 9, '10': 'adapter'},
|
||||
{'1': 'status', '3': 2, '4': 1, '5': 9, '10': 'status'},
|
||||
{'1': 'capacity', '3': 3, '4': 1, '5': 5, '10': 'capacity'},
|
||||
{'1': 'in_flight', '3': 4, '4': 1, '5': 5, '10': 'inFlight'},
|
||||
{'1': 'queued', '3': 5, '4': 1, '5': 5, '10': 'queued'},
|
||||
{'1': 'id', '3': 6, '4': 1, '5': 9, '10': 'id'},
|
||||
{'1': 'type', '3': 7, '4': 1, '5': 9, '10': 'type'},
|
||||
{'1': 'category', '3': 8, '4': 1, '5': 9, '10': 'category'},
|
||||
{'1': 'served_models', '3': 9, '4': 3, '5': 9, '10': 'servedModels'},
|
||||
{'1': 'health', '3': 10, '4': 1, '5': 9, '10': 'health'},
|
||||
{'1': 'load_ratio', '3': 11, '4': 1, '5': 2, '10': 'loadRatio'},
|
||||
{
|
||||
'1': 'lifecycle_capabilities',
|
||||
'3': 12,
|
||||
'4': 3,
|
||||
'5': 9,
|
||||
'10': 'lifecycleCapabilities'
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `ProviderSnapshot`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List providerSnapshotDescriptor = $convert.base64Decode(
|
||||
'ChBQcm92aWRlclNuYXBzaG90EhgKB2FkYXB0ZXIYASABKAlSB2FkYXB0ZXISFgoGc3RhdHVzGA'
|
||||
'IgASgJUgZzdGF0dXMSGgoIY2FwYWNpdHkYAyABKAVSCGNhcGFjaXR5EhsKCWluX2ZsaWdodBgE'
|
||||
'IAEoBVIIaW5GbGlnaHQSFgoGcXVldWVkGAUgASgFUgZxdWV1ZWQSDgoCaWQYBiABKAlSAmlkEh'
|
||||
'IKBHR5cGUYByABKAlSBHR5cGUSGgoIY2F0ZWdvcnkYCCABKAlSCGNhdGVnb3J5EiMKDXNlcnZl'
|
||||
'ZF9tb2RlbHMYCSADKAlSDHNlcnZlZE1vZGVscxIWCgZoZWFsdGgYCiABKAlSBmhlYWx0aBIdCg'
|
||||
'psb2FkX3JhdGlvGAsgASgCUglsb2FkUmF0aW8SNQoWbGlmZWN5Y2xlX2NhcGFiaWxpdGllcxgM'
|
||||
'IAMoCVIVbGlmZWN5Y2xlQ2FwYWJpbGl0aWVz');
|
||||
|
||||
@$core.Deprecated('Use agentUsageStatusDescriptor instead')
|
||||
const AgentUsageStatus$json = {
|
||||
|
|
@ -553,6 +618,17 @@ const AdapterConfig$json = {
|
|||
'9': 0,
|
||||
'10': 'mock'
|
||||
},
|
||||
{
|
||||
'1': 'openai_compat',
|
||||
'3': 10,
|
||||
'4': 1,
|
||||
'5': 11,
|
||||
'6': '.iop.OpenAICompatAdapterConfig',
|
||||
'9': 0,
|
||||
'10': 'openaiCompat'
|
||||
},
|
||||
{'1': 'name', '3': 8, '4': 1, '5': 9, '10': 'name'},
|
||||
{'1': 'target', '3': 9, '4': 1, '5': 9, '10': 'target'},
|
||||
],
|
||||
'8': [
|
||||
{'1': 'config'},
|
||||
|
|
@ -566,7 +642,9 @@ final $typed_data.Uint8List adapterConfigDescriptor = $convert.base64Decode(
|
|||
'bmdzEikKA2NsaRgEIAEoCzIVLmlvcC5DTElBZGFwdGVyQ29uZmlnSABSA2NsaRIyCgZvbGxhbW'
|
||||
'EYBSABKAsyGC5pb3AuT2xsYW1hQWRhcHRlckNvbmZpZ0gAUgZvbGxhbWESLAoEdmxsbRgGIAEo'
|
||||
'CzIWLmlvcC5WbGxtQWRhcHRlckNvbmZpZ0gAUgR2bGxtEiwKBG1vY2sYByABKAsyFi5pb3AuTW'
|
||||
'9ja0FkYXB0ZXJDb25maWdIAFIEbW9ja0IICgZjb25maWc=');
|
||||
'9ja0FkYXB0ZXJDb25maWdIAFIEbW9jaxJFCg1vcGVuYWlfY29tcGF0GAogASgLMh4uaW9wLk9w'
|
||||
'ZW5BSUNvbXBhdEFkYXB0ZXJDb25maWdIAFIMb3BlbmFpQ29tcGF0EhIKBG5hbWUYCCABKAlSBG'
|
||||
'5hbWUSFgoGdGFyZ2V0GAkgASgJUgZ0YXJnZXRCCAoGY29uZmln');
|
||||
|
||||
@$core.Deprecated('Use mockAdapterConfigDescriptor instead')
|
||||
const MockAdapterConfig$json = {
|
||||
|
|
@ -685,36 +763,166 @@ const OllamaAdapterConfig$json = {
|
|||
'2': [
|
||||
{'1': 'base_url', '3': 1, '4': 1, '5': 9, '10': 'baseUrl'},
|
||||
{'1': 'context_size', '3': 2, '4': 1, '5': 5, '10': 'contextSize'},
|
||||
{'1': 'capacity', '3': 3, '4': 1, '5': 5, '10': 'capacity'},
|
||||
{'1': 'max_queue', '3': 4, '4': 1, '5': 5, '10': 'maxQueue'},
|
||||
{'1': 'queue_timeout_ms', '3': 5, '4': 1, '5': 5, '10': 'queueTimeoutMs'},
|
||||
{
|
||||
'1': 'request_timeout_ms',
|
||||
'3': 6,
|
||||
'4': 1,
|
||||
'5': 5,
|
||||
'10': 'requestTimeoutMs'
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `OllamaAdapterConfig`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List ollamaAdapterConfigDescriptor = $convert.base64Decode(
|
||||
'ChNPbGxhbWFBZGFwdGVyQ29uZmlnEhkKCGJhc2VfdXJsGAEgASgJUgdiYXNlVXJsEiEKDGNvbn'
|
||||
'RleHRfc2l6ZRgCIAEoBVILY29udGV4dFNpemU=');
|
||||
'RleHRfc2l6ZRgCIAEoBVILY29udGV4dFNpemUSGgoIY2FwYWNpdHkYAyABKAVSCGNhcGFjaXR5'
|
||||
'EhsKCW1heF9xdWV1ZRgEIAEoBVIIbWF4UXVldWUSKAoQcXVldWVfdGltZW91dF9tcxgFIAEoBV'
|
||||
'IOcXVldWVUaW1lb3V0TXMSLAoScmVxdWVzdF90aW1lb3V0X21zGAYgASgFUhByZXF1ZXN0VGlt'
|
||||
'ZW91dE1z');
|
||||
|
||||
@$core.Deprecated('Use vllmAdapterConfigDescriptor instead')
|
||||
const VllmAdapterConfig$json = {
|
||||
'1': 'VllmAdapterConfig',
|
||||
'2': [
|
||||
{'1': 'endpoint', '3': 1, '4': 1, '5': 9, '10': 'endpoint'},
|
||||
{'1': 'capacity', '3': 2, '4': 1, '5': 5, '10': 'capacity'},
|
||||
{'1': 'max_queue', '3': 3, '4': 1, '5': 5, '10': 'maxQueue'},
|
||||
{'1': 'queue_timeout_ms', '3': 4, '4': 1, '5': 5, '10': 'queueTimeoutMs'},
|
||||
{
|
||||
'1': 'request_timeout_ms',
|
||||
'3': 5,
|
||||
'4': 1,
|
||||
'5': 5,
|
||||
'10': 'requestTimeoutMs'
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `VllmAdapterConfig`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List vllmAdapterConfigDescriptor = $convert.base64Decode(
|
||||
'ChFWbGxtQWRhcHRlckNvbmZpZxIaCghlbmRwb2ludBgBIAEoCVIIZW5kcG9pbnQ=');
|
||||
'ChFWbGxtQWRhcHRlckNvbmZpZxIaCghlbmRwb2ludBgBIAEoCVIIZW5kcG9pbnQSGgoIY2FwYW'
|
||||
'NpdHkYAiABKAVSCGNhcGFjaXR5EhsKCW1heF9xdWV1ZRgDIAEoBVIIbWF4UXVldWUSKAoQcXVl'
|
||||
'dWVfdGltZW91dF9tcxgEIAEoBVIOcXVldWVUaW1lb3V0TXMSLAoScmVxdWVzdF90aW1lb3V0X2'
|
||||
'1zGAUgASgFUhByZXF1ZXN0VGltZW91dE1z');
|
||||
|
||||
@$core.Deprecated('Use openAICompatAdapterConfigDescriptor instead')
|
||||
const OpenAICompatAdapterConfig$json = {
|
||||
'1': 'OpenAICompatAdapterConfig',
|
||||
'2': [
|
||||
{'1': 'provider', '3': 1, '4': 1, '5': 9, '10': 'provider'},
|
||||
{'1': 'endpoint', '3': 2, '4': 1, '5': 9, '10': 'endpoint'},
|
||||
{
|
||||
'1': 'headers',
|
||||
'3': 3,
|
||||
'4': 3,
|
||||
'5': 11,
|
||||
'6': '.iop.OpenAICompatAdapterConfig.HeadersEntry',
|
||||
'10': 'headers'
|
||||
},
|
||||
{'1': 'capacity', '3': 4, '4': 1, '5': 5, '10': 'capacity'},
|
||||
{'1': 'max_queue', '3': 5, '4': 1, '5': 5, '10': 'maxQueue'},
|
||||
{'1': 'queue_timeout_ms', '3': 6, '4': 1, '5': 5, '10': 'queueTimeoutMs'},
|
||||
{
|
||||
'1': 'request_timeout_ms',
|
||||
'3': 7,
|
||||
'4': 1,
|
||||
'5': 5,
|
||||
'10': 'requestTimeoutMs'
|
||||
},
|
||||
],
|
||||
'3': [OpenAICompatAdapterConfig_HeadersEntry$json],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use openAICompatAdapterConfigDescriptor instead')
|
||||
const OpenAICompatAdapterConfig_HeadersEntry$json = {
|
||||
'1': 'HeadersEntry',
|
||||
'2': [
|
||||
{'1': 'key', '3': 1, '4': 1, '5': 9, '10': 'key'},
|
||||
{'1': 'value', '3': 2, '4': 1, '5': 9, '10': 'value'},
|
||||
],
|
||||
'7': {'7': true},
|
||||
};
|
||||
|
||||
/// Descriptor for `OpenAICompatAdapterConfig`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List openAICompatAdapterConfigDescriptor = $convert.base64Decode(
|
||||
'ChlPcGVuQUlDb21wYXRBZGFwdGVyQ29uZmlnEhoKCHByb3ZpZGVyGAEgASgJUghwcm92aWRlch'
|
||||
'IaCghlbmRwb2ludBgCIAEoCVIIZW5kcG9pbnQSRQoHaGVhZGVycxgDIAMoCzIrLmlvcC5PcGVu'
|
||||
'QUlDb21wYXRBZGFwdGVyQ29uZmlnLkhlYWRlcnNFbnRyeVIHaGVhZGVycxIaCghjYXBhY2l0eR'
|
||||
'gEIAEoBVIIY2FwYWNpdHkSGwoJbWF4X3F1ZXVlGAUgASgFUghtYXhRdWV1ZRIoChBxdWV1ZV90'
|
||||
'aW1lb3V0X21zGAYgASgFUg5xdWV1ZVRpbWVvdXRNcxIsChJyZXF1ZXN0X3RpbWVvdXRfbXMYBy'
|
||||
'ABKAVSEHJlcXVlc3RUaW1lb3V0TXMaOgoMSGVhZGVyc0VudHJ5EhAKA2tleRgBIAEoCVIDa2V5'
|
||||
'EhQKBXZhbHVlGAIgASgJUgV2YWx1ZToCOAE=');
|
||||
|
||||
@$core.Deprecated('Use nodeRuntimeConfigDescriptor instead')
|
||||
const NodeRuntimeConfig$json = {
|
||||
'1': 'NodeRuntimeConfig',
|
||||
'2': [
|
||||
{'1': 'concurrency', '3': 1, '4': 1, '5': 5, '10': 'concurrency'},
|
||||
{'1': 'workspace_root', '3': 2, '4': 1, '5': 9, '10': 'workspaceRoot'},
|
||||
],
|
||||
'9': [
|
||||
{'1': 2, '2': 3},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `NodeRuntimeConfig`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List nodeRuntimeConfigDescriptor = $convert.base64Decode(
|
||||
'ChFOb2RlUnVudGltZUNvbmZpZxIgCgtjb25jdXJyZW5jeRgBIAEoBVILY29uY3VycmVuY3kSJQ'
|
||||
'oOd29ya3NwYWNlX3Jvb3QYAiABKAlSDXdvcmtzcGFjZVJvb3Q=');
|
||||
'ChFOb2RlUnVudGltZUNvbmZpZxIgCgtjb25jdXJyZW5jeRgBIAEoBVILY29uY3VycmVuY3lKBA'
|
||||
'gCEAM=');
|
||||
|
||||
@$core.Deprecated('Use nodeConfigRefreshRequestDescriptor instead')
|
||||
const NodeConfigRefreshRequest$json = {
|
||||
'1': 'NodeConfigRefreshRequest',
|
||||
'2': [
|
||||
{'1': 'request_id', '3': 1, '4': 1, '5': 9, '10': 'requestId'},
|
||||
{
|
||||
'1': 'config',
|
||||
'3': 2,
|
||||
'4': 1,
|
||||
'5': 11,
|
||||
'6': '.iop.NodeConfigPayload',
|
||||
'10': 'config'
|
||||
},
|
||||
{'1': 'changed_paths', '3': 3, '4': 3, '5': 9, '10': 'changedPaths'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `NodeConfigRefreshRequest`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List nodeConfigRefreshRequestDescriptor = $convert.base64Decode(
|
||||
'ChhOb2RlQ29uZmlnUmVmcmVzaFJlcXVlc3QSHQoKcmVxdWVzdF9pZBgBIAEoCVIJcmVxdWVzdE'
|
||||
'lkEi4KBmNvbmZpZxgCIAEoCzIWLmlvcC5Ob2RlQ29uZmlnUGF5bG9hZFIGY29uZmlnEiMKDWNo'
|
||||
'YW5nZWRfcGF0aHMYAyADKAlSDGNoYW5nZWRQYXRocw==');
|
||||
|
||||
@$core.Deprecated('Use nodeConfigRefreshResponseDescriptor instead')
|
||||
const NodeConfigRefreshResponse$json = {
|
||||
'1': 'NodeConfigRefreshResponse',
|
||||
'2': [
|
||||
{'1': 'request_id', '3': 1, '4': 1, '5': 9, '10': 'requestId'},
|
||||
{
|
||||
'1': 'status',
|
||||
'3': 2,
|
||||
'4': 1,
|
||||
'5': 14,
|
||||
'6': '.iop.NodeConfigRefreshStatus',
|
||||
'10': 'status'
|
||||
},
|
||||
{
|
||||
'1': 'restart_required_paths',
|
||||
'3': 3,
|
||||
'4': 3,
|
||||
'5': 9,
|
||||
'10': 'restartRequiredPaths'
|
||||
},
|
||||
{'1': 'error', '3': 4, '4': 1, '5': 9, '10': 'error'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `NodeConfigRefreshResponse`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List nodeConfigRefreshResponseDescriptor = $convert.base64Decode(
|
||||
'ChlOb2RlQ29uZmlnUmVmcmVzaFJlc3BvbnNlEh0KCnJlcXVlc3RfaWQYASABKAlSCXJlcXVlc3'
|
||||
'RJZBI0CgZzdGF0dXMYAiABKA4yHC5pb3AuTm9kZUNvbmZpZ1JlZnJlc2hTdGF0dXNSBnN0YXR1'
|
||||
'cxI0ChZyZXN0YXJ0X3JlcXVpcmVkX3BhdGhzGAMgAygJUhRyZXN0YXJ0UmVxdWlyZWRQYXRocx'
|
||||
'IUCgVlcnJvchgEIAEoCVIFZXJyb3I=');
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ iop-edge --config edge.yaml config refresh --mode apply --addr 127.0.0.1:19093
|
|||
|
||||
refresh admin API는 operator-local 표면이다. 별도 접근 제어 계층 없이 public interface에 열지 않는다.
|
||||
|
||||
provider capacity, provider mapping, model catalog, Node provider 설정, Node runtime concurrency처럼 runtime mutable로 분류된 변경은 refresh apply 결과가 `applied`로 반환되고 연결된 Node에 새 config payload가 전달된다. listener address, Edge identity, bootstrap artifact dir, Node workspace root처럼 live apply가 위험한 변경은 `restart_required`로 보고되며 조용히 적용하지 않는다. invalid YAML이나 검증 실패는 `rejected`로 끝나고 기존 routing/runtime 상태를 유지한다.
|
||||
provider capacity, provider mapping, model catalog, Node provider 설정, Node runtime concurrency처럼 runtime mutable로 분류된 변경은 refresh apply 결과가 `applied`로 반환되고 연결된 Node에 새 config payload가 전달된다. listener address, Edge identity, bootstrap artifact dir처럼 live apply가 위험한 변경은 `restart_required`로 보고되며 조용히 적용하지 않는다. invalid YAML이나 검증 실패는 `rejected`로 끝나고 기존 routing/runtime 상태를 유지한다.
|
||||
|
||||
Node는 최초 연결 성공 이후 Edge transport가 끊기면 기본 `10s` 간격으로 최대 `10`회 재접속을 시도한다. Edge process 재시작이나 일시 단절이 retry window 안에서 회복되면 사용자가 bootstrap 명령을 다시 실행하지 않아도 Node가 재등록된다. retry 한계를 넘으면 Node는 session/runtime을 정리하고 종료 경로를 탄다.
|
||||
|
||||
|
|
|
|||
|
|
@ -876,7 +876,6 @@ nodes:
|
|||
queue_timeout_ms: 5000
|
||||
runtime:
|
||||
concurrency: 7
|
||||
workspace_root: "/tmp/iop-refresh-ws"
|
||||
providers:
|
||||
- id: "prov-r"
|
||||
type: "ollama"
|
||||
|
|
@ -1021,13 +1020,10 @@ nodes:
|
|||
if payload == nil {
|
||||
t.Fatal("expected non-nil NodeConfigPayload in refresh request")
|
||||
}
|
||||
// Runtime tuning is pushed verbatim from the node record.
|
||||
// Runtime tuning is pushed from the node record.
|
||||
if got := payload.GetRuntime().GetConcurrency(); got != 7 {
|
||||
t.Errorf("runtime concurrency: got %d, want 7", got)
|
||||
}
|
||||
if got := payload.GetRuntime().GetWorkspaceRoot(); got != "/tmp/iop-refresh-ws" {
|
||||
t.Errorf("runtime workspace_root: got %q, want %q", got, "/tmp/iop-refresh-ws")
|
||||
}
|
||||
// The configured openai_compat adapter instance must be present with its
|
||||
// typed fields (provider/endpoint/capacity) intact, and the CLI adapter too.
|
||||
var oai *iop.OpenAICompatAdapterConfig
|
||||
|
|
@ -1644,16 +1640,14 @@ func TestRefreshRejectedPreservesProviderDispatch(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestRefreshConfigNodeRuntimeConcurrencyAppliedAndWorkspaceRestartRequired
|
||||
// verifies the S15 boundary at the running-edge level: a node runtime.concurrency
|
||||
// change is applied live and pushed to the connected node (node result reported),
|
||||
// while a runtime.workspace_root change is classified restart_required and is NOT
|
||||
// pushed to nodes (no node results) nor committed to the runtime snapshot.
|
||||
func TestRefreshConfigNodeRuntimeConcurrencyAppliedAndWorkspaceRestartRequired(t *testing.T) {
|
||||
// TestRefreshConfigNodeRuntimeConcurrencyApplied verifies the S15 boundary at
|
||||
// the running-edge level: a node runtime.concurrency change is applied live
|
||||
// and pushed to the connected node.
|
||||
func TestRefreshConfigNodeRuntimeConcurrencyApplied(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
serverAddr := freeTCPAddr(t)
|
||||
|
||||
writeCfg := func(name string, concurrency int, workspaceRoot string) string {
|
||||
writeCfg := func(name string, concurrency int) string {
|
||||
path := filepath.Join(dir, name)
|
||||
yaml := fmt.Sprintf(`
|
||||
server:
|
||||
|
|
@ -1681,17 +1675,15 @@ nodes:
|
|||
enabled: true
|
||||
runtime:
|
||||
concurrency: %d
|
||||
workspace_root: %q
|
||||
`, serverAddr, concurrency, workspaceRoot)
|
||||
`, serverAddr, concurrency)
|
||||
if err := os.WriteFile(path, []byte(yaml), 0o600); err != nil {
|
||||
t.Fatalf("write %s: %v", name, err)
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
basePath := writeCfg("base.yaml", 2, "/var/lib/iop/ws-a")
|
||||
concurrencyPath := writeCfg("concurrency.yaml", 4, "/var/lib/iop/ws-a")
|
||||
workspacePath := writeCfg("workspace.yaml", 2, "/var/lib/iop/ws-b")
|
||||
basePath := writeCfg("base.yaml", 2)
|
||||
concurrencyPath := writeCfg("concurrency.yaml", 4)
|
||||
|
||||
rt, err := NewRuntime(loadServeNormalizedConfig(t, basePath))
|
||||
if err != nil {
|
||||
|
|
@ -1767,27 +1759,6 @@ nodes:
|
|||
t.Fatal("fake node not registered in edge registry")
|
||||
}
|
||||
|
||||
// workspace_root change → restart_required, NOT pushed, snapshot unchanged.
|
||||
wsResult, err := rt.RefreshConfig(context.Background(), configrefresh.Request{
|
||||
Mode: configrefresh.ModeApply,
|
||||
ConfigPath: workspacePath,
|
||||
RequestID: "rt-ws",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("RefreshConfig workspace: %v", err)
|
||||
}
|
||||
if wsResult.Status != configrefresh.StatusRestartRequired {
|
||||
t.Fatalf("expected workspace change status=restart_required, got %q", wsResult.Status)
|
||||
}
|
||||
if len(wsResult.NodeResults) != 0 {
|
||||
t.Errorf("workspace restart_required must not push to nodes, got node_results=%+v", wsResult.NodeResults)
|
||||
}
|
||||
capturedMu.Lock()
|
||||
if capturedConcurrency != -1 {
|
||||
t.Errorf("node must not receive a push for a restart_required workspace change, captured concurrency=%d", capturedConcurrency)
|
||||
}
|
||||
capturedMu.Unlock()
|
||||
|
||||
// concurrency change → applied, pushed to node, node result reported.
|
||||
concResult, err := rt.RefreshConfig(context.Background(), configrefresh.Request{
|
||||
Mode: configrefresh.ModeApply,
|
||||
|
|
|
|||
|
|
@ -217,11 +217,8 @@ func Classify(current, candidate *config.EdgeConfig) Result {
|
|||
appendIfChanged(&changes, fmt.Sprintf("nodes[%q].token", key), StatusRestartRequired, cur.Token, next.Token)
|
||||
appendIfChanged(&changes, fmt.Sprintf("nodes[%q].agent_kind", key), StatusRestartRequired, cur.AgentKind, next.AgentKind)
|
||||
appendDeepIfChanged(&changes, fmt.Sprintf("nodes[%q].adapters", key), StatusRestartRequired, cur.Adapters, next.Adapters)
|
||||
// Runtime tuning is classified per field: node-wide concurrency is applied
|
||||
// live, while workspace_root requires a node restart because the store DB
|
||||
// path is fixed at bootstrap.
|
||||
// Node-wide concurrency is live-applyable.
|
||||
appendIfChanged(&changes, fmt.Sprintf("nodes[%q].runtime.concurrency", key), StatusApplied, cur.Runtime.Concurrency, next.Runtime.Concurrency)
|
||||
appendIfChanged(&changes, fmt.Sprintf("nodes[%q].runtime.workspace_root", key), StatusRestartRequired, cur.Runtime.WorkspaceRoot, next.Runtime.WorkspaceRoot)
|
||||
}
|
||||
for key := range candidateNodes {
|
||||
if _, exists := currentNodes[key]; !exists {
|
||||
|
|
|
|||
|
|
@ -711,10 +711,9 @@ nodes:
|
|||
}
|
||||
}
|
||||
|
||||
// TestClassifyNodeRuntimeConcurrencyAppliedWorkspaceRestartRequired verifies
|
||||
// S15: node runtime tuning is classified per field. concurrency is applied live
|
||||
// while workspace_root requires a node restart.
|
||||
func TestClassifyNodeRuntimeConcurrencyAppliedWorkspaceRestartRequired(t *testing.T) {
|
||||
// TestClassifyNodeRuntimeConcurrencyApplied verifies S15: node runtime
|
||||
// concurrency is applied live.
|
||||
func TestClassifyNodeRuntimeConcurrencyApplied(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
|
||||
currentYAML := `
|
||||
|
|
@ -729,7 +728,6 @@ nodes:
|
|||
enabled: true
|
||||
runtime:
|
||||
concurrency: 2
|
||||
workspace_root: "/var/lib/iop/ws-a"
|
||||
`
|
||||
currentPath := writeYAML(t, dir, "current.yaml", currentYAML)
|
||||
|
||||
|
|
@ -745,7 +743,6 @@ nodes:
|
|||
enabled: true
|
||||
runtime:
|
||||
concurrency: 4
|
||||
workspace_root: "/var/lib/iop/ws-a"
|
||||
`
|
||||
concurrencyOnlyPath := writeYAML(t, dir, "concurrency.yaml", concurrencyOnlyYAML)
|
||||
|
||||
|
|
@ -780,52 +777,4 @@ nodes:
|
|||
t.Errorf("concurrency change path not found in: %+v", result.Changes)
|
||||
}
|
||||
|
||||
// workspace_root change → restart_required.
|
||||
workspaceYAML := `
|
||||
server:
|
||||
listen: "0.0.0.0:9090"
|
||||
nodes:
|
||||
- id: "node-1"
|
||||
alias: "n1"
|
||||
token: "tok-1"
|
||||
adapters:
|
||||
cli:
|
||||
enabled: true
|
||||
runtime:
|
||||
concurrency: 2
|
||||
workspace_root: "/var/lib/iop/ws-b"
|
||||
`
|
||||
workspacePath := writeYAML(t, dir, "workspace.yaml", workspaceYAML)
|
||||
wsResult, _, err := configrefresh.Evaluate(ctx, current, configrefresh.Request{
|
||||
Mode: configrefresh.ModeDryRun,
|
||||
ConfigPath: workspacePath,
|
||||
RequestID: "test-s15-ws",
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("Evaluate workspace: %v", err)
|
||||
}
|
||||
if wsResult.Status != configrefresh.StatusRestartRequired {
|
||||
t.Fatalf("expected workspace_root change status=restart_required, got %q", wsResult.Status)
|
||||
}
|
||||
foundWS := false
|
||||
for _, c := range wsResult.Changes {
|
||||
if c.Path == `nodes["node-1"].runtime.workspace_root` {
|
||||
foundWS = true
|
||||
if c.Class != configrefresh.StatusRestartRequired {
|
||||
t.Errorf("expected workspace_root class=restart_required, got %q", c.Class)
|
||||
}
|
||||
}
|
||||
}
|
||||
if !foundWS {
|
||||
t.Errorf("workspace_root change path not found in: %+v", wsResult.Changes)
|
||||
}
|
||||
foundRestartPath := false
|
||||
for _, p := range wsResult.RestartRequiredPaths {
|
||||
if p == `nodes["node-1"].runtime.workspace_root` {
|
||||
foundRestartPath = true
|
||||
}
|
||||
}
|
||||
if !foundRestartPath {
|
||||
t.Errorf("workspace_root not in RestartRequiredPaths: %v", wsResult.RestartRequiredPaths)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -758,8 +758,7 @@ func TestConnectorBuildStatusResponseNonLeak(t *testing.T) {
|
|||
Label: "node0",
|
||||
Config: &iop.NodeConfigPayload{
|
||||
Runtime: &iop.NodeRuntimeConfig{
|
||||
Concurrency: 5,
|
||||
WorkspaceRoot: "/sensitive/workspace",
|
||||
Concurrency: 5,
|
||||
},
|
||||
Adapters: []*iop.AdapterConfig{
|
||||
{
|
||||
|
|
|
|||
|
|
@ -353,6 +353,7 @@ YAML
|
|||
|
||||
echo "[iop-bootstrap] config=$CONFIG_FILE"
|
||||
echo "[iop-bootstrap] starting node against $EDGE_ADDR"
|
||||
cd "$INSTALL_DIR"
|
||||
exec "$BIN_FILE" serve --config "$CONFIG_FILE"
|
||||
`
|
||||
}
|
||||
|
|
@ -409,7 +410,7 @@ metrics:
|
|||
port: 19104
|
||||
"@ | Set-Content -Encoding UTF8 -Path $ConfigFile
|
||||
|
||||
$Process = Start-Process -FilePath $BinFile -ArgumentList @('serve', '--config', $ConfigFile) -RedirectStandardOutput $StdoutLog -RedirectStandardError $StderrLog -WindowStyle Hidden -PassThru
|
||||
$Process = Start-Process -FilePath $BinFile -ArgumentList @('serve', '--config', $ConfigFile) -WorkingDirectory $InstallDir -RedirectStandardOutput $StdoutLog -RedirectStandardError $StderrLog -WindowStyle Hidden -PassThru
|
||||
"[iop-bootstrap] version=$Version target=$Target pid=$($Process.Id)"
|
||||
"[iop-bootstrap] config=$ConfigFile log=$LogFile"
|
||||
} finally {
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ var (
|
|||
regOllamaBaseURL string
|
||||
regOllamaContextSize int
|
||||
regRuntimeConcurrency int
|
||||
regWorkspaceRoot string
|
||||
regTarget string
|
||||
regArtifactBaseURL string
|
||||
)
|
||||
|
|
@ -167,9 +166,6 @@ directly in the default flow.`,
|
|||
if cmd.Flags().Changed("runtime-concurrency") {
|
||||
nodeDef.Runtime.Concurrency = regRuntimeConcurrency
|
||||
}
|
||||
if cmd.Flags().Changed("workspace-root") {
|
||||
nodeDef.Runtime.WorkspaceRoot = regWorkspaceRoot
|
||||
}
|
||||
|
||||
if nodeDef.Token == "" {
|
||||
nodeDef.Token = tokenGenerator()
|
||||
|
|
@ -212,11 +208,6 @@ directly in the default flow.`,
|
|||
concurrency = regRuntimeConcurrency
|
||||
}
|
||||
|
||||
workspaceRoot := ""
|
||||
if cmd.Flags().Changed("workspace-root") {
|
||||
workspaceRoot = regWorkspaceRoot
|
||||
}
|
||||
|
||||
newDef := config.NodeDefinition{
|
||||
ID: nodeID,
|
||||
Alias: alias,
|
||||
|
|
@ -226,8 +217,7 @@ directly in the default flow.`,
|
|||
CLI: cli,
|
||||
},
|
||||
Runtime: config.RuntimeConf{
|
||||
Concurrency: concurrency,
|
||||
WorkspaceRoot: workspaceRoot,
|
||||
Concurrency: concurrency,
|
||||
},
|
||||
}
|
||||
cfg.Nodes = append(cfg.Nodes, newDef)
|
||||
|
|
@ -275,7 +265,6 @@ directly in the default flow.`,
|
|||
c.Flags().StringVar(®OllamaBaseURL, "ollama-base-url", "", "ollama base URL")
|
||||
c.Flags().IntVar(®OllamaContextSize, "ollama-context-size", 2048, "ollama context size")
|
||||
c.Flags().IntVar(®RuntimeConcurrency, "runtime-concurrency", 1, "runtime concurrency limit")
|
||||
c.Flags().StringVar(®WorkspaceRoot, "workspace-root", "", "workspace root path")
|
||||
c.Flags().StringVar(®Target, "target", "", "bootstrap target platform (e.g. darwin-arm64, linux-amd64)")
|
||||
c.Flags().StringVar(®ArtifactBaseURL, "artifact-base-url", "", "artifact base URL for bootstrap download")
|
||||
|
||||
|
|
|
|||
|
|
@ -17,8 +17,7 @@ import (
|
|||
func BuildConfigPayload(rec *NodeRecord) (*iop.NodeConfigPayload, error) {
|
||||
payload := &iop.NodeConfigPayload{
|
||||
Runtime: &iop.NodeRuntimeConfig{
|
||||
Concurrency: int32(rec.Runtime.Concurrency),
|
||||
WorkspaceRoot: rec.Runtime.WorkspaceRoot,
|
||||
Concurrency: int32(rec.Runtime.Concurrency),
|
||||
},
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,8 +31,7 @@ func TestBuildConfigPayload_OllamaEnabled(t *testing.T) {
|
|||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{
|
||||
Concurrency: 4,
|
||||
WorkspaceRoot: "/tmp/ws",
|
||||
Concurrency: 4,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -111,9 +110,7 @@ func TestBuildConfigPayload_CLIProfiles(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{
|
||||
WorkspaceRoot: "/tmp/ws",
|
||||
},
|
||||
Runtime: config.RuntimeConf{},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -172,7 +169,6 @@ func TestBuildConfigPayload_CLIProfileOpencodeSSEMode(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -236,9 +232,7 @@ func TestBuildConfigPayload_MockAlwaysPresent(t *testing.T) {
|
|||
Vllm: config.VllmConf{Enabled: false},
|
||||
CLI: config.CLIConf{Enabled: false},
|
||||
},
|
||||
Runtime: config.RuntimeConf{
|
||||
WorkspaceRoot: "/tmp/ws",
|
||||
},
|
||||
Runtime: config.RuntimeConf{},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -267,7 +261,6 @@ func TestBuildConfigPayload_MultiOllamaInstances(t *testing.T) {
|
|||
{Name: "dgx", Enabled: true, BaseURL: "http://192.168.0.91:11434", ContextSize: 262144, Capacity: 6, MaxQueue: 12, QueueTimeoutMS: 2000, RequestTimeoutMS: 60000},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -314,7 +307,6 @@ func TestBuildConfigPayload_MultiVllmInstances(t *testing.T) {
|
|||
{Name: "h100", Enabled: true, Endpoint: "http://10.0.0.6:8000", Capacity: 8, MaxQueue: 16, QueueTimeoutMS: 2500, RequestTimeoutMS: 90000},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -364,7 +356,6 @@ func TestBuildConfigPayload_LegacyOllamaViaInstances(t *testing.T) {
|
|||
{Name: "ollama", Enabled: true, BaseURL: "http://localhost:11434", ContextSize: 4096, Capacity: 5, MaxQueue: 9, QueueTimeoutMS: 1700, RequestTimeoutMS: 55000},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -453,7 +444,6 @@ func TestBuildConfigPayload_OpenAICompatInstances(t *testing.T) {
|
|||
{Name: "openai-api", Enabled: true, Provider: "openai", Endpoint: "https://api.openai.com/v1", Headers: map[string]string{"authorization": "Bearer sk-test"}, Capacity: 8, MaxQueue: 20, QueueTimeoutMS: 2500, RequestTimeoutMS: 60000},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
@ -547,7 +537,6 @@ func TestBuildConfigPayload_VLLMOpenAICompatInstance(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
Runtime: config.RuntimeConf{WorkspaceRoot: "/tmp/ws"},
|
||||
}
|
||||
|
||||
payload, err := edgenode.BuildConfigPayload(rec)
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ func decodeChatCompletionRequest(dec *json.Decoder, req *chatCompletionRequest)
|
|||
}
|
||||
for key := range raw {
|
||||
switch key {
|
||||
case "model", "messages", "stream", "metadata", "max_tokens", "max_completion_tokens", "temperature", "top_p", "presence_penalty", "frequency_penalty", "seed", "stop", "response_format", "tools":
|
||||
case "model", "messages", "stream", "metadata", "max_tokens", "max_completion_tokens", "temperature", "top_p", "presence_penalty", "frequency_penalty", "seed", "stop", "response_format", "tools", "tool_choice", "parallel_tool_calls", "stream_options":
|
||||
default:
|
||||
return fmt.Errorf("%s is not supported for /v1/chat/completions", key)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,6 +226,41 @@ func TestChatCompletionsPassesStandardOptions(t *testing.T) {
|
|||
if tools, ok := fake.req.Input["tools"].([]any); !ok || len(tools) != 1 {
|
||||
t.Fatalf("tools not passed: %+v", fake.req.Input["tools"])
|
||||
}
|
||||
if fake.req.Input["tool_choice"] != "none" {
|
||||
t.Fatalf("tool_choice not downgraded: %+v", fake.req.Input["tool_choice"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatCompletionsDowngradesToolChoiceAutoToNone(t *testing.T) {
|
||||
fake := &fakeRunService{events: make(chan *iop.RunEvent, 2)}
|
||||
fake.events <- &iop.RunEvent{Type: "delta", Delta: "ok"}
|
||||
fake.events <- &iop.RunEvent{Type: "complete"}
|
||||
|
||||
srv := NewServer(config.EdgeOpenAIConf{Adapter: "openai_compat"}, fake, nil)
|
||||
req := httptest.NewRequest(http.MethodPost, "/v1/chat/completions", strings.NewReader(`{
|
||||
"model":"qwen3.6:35b",
|
||||
"messages":[{"role":"user","content":"hi"}],
|
||||
"tools":[{"type":"function","function":{"name":"lookup"}}],
|
||||
"tool_choice":"auto",
|
||||
"parallel_tool_calls":true,
|
||||
"stream_options":{"include_usage":true}
|
||||
}`))
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
srv.handleChatCompletions(w, req)
|
||||
|
||||
if w.Code != http.StatusOK {
|
||||
t.Fatalf("status: got %d body=%s", w.Code, w.Body.String())
|
||||
}
|
||||
if fake.req.Input["tool_choice"] != "none" {
|
||||
t.Fatalf("tool_choice: got %+v, want none", fake.req.Input["tool_choice"])
|
||||
}
|
||||
if _, ok := fake.req.Input["parallel_tool_calls"]; ok {
|
||||
t.Fatalf("parallel_tool_calls must not be forwarded: %+v", fake.req.Input)
|
||||
}
|
||||
if _, ok := fake.req.Input["stream_options"]; ok {
|
||||
t.Fatalf("stream_options must not be forwarded: %+v", fake.req.Input)
|
||||
}
|
||||
}
|
||||
|
||||
func TestChatCompletionsMapsMaxCompletionTokens(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -20,6 +20,9 @@ type chatCompletionRequest struct {
|
|||
Stop any `json:"stop,omitempty"`
|
||||
ResponseFormat any `json:"response_format,omitempty"`
|
||||
Tools []any `json:"tools,omitempty"`
|
||||
ToolChoice any `json:"tool_choice,omitempty"`
|
||||
ParallelToolCalls *bool `json:"parallel_tool_calls,omitempty"`
|
||||
StreamOptions any `json:"stream_options,omitempty"`
|
||||
}
|
||||
|
||||
type chatMessage struct {
|
||||
|
|
@ -82,10 +85,17 @@ func (req chatCompletionRequest) runInput(prompt string, messages []chatMessage,
|
|||
}
|
||||
if len(req.Tools) > 0 {
|
||||
input["tools"] = req.Tools
|
||||
input["tool_choice"] = normalizeToolChoice(req.ToolChoice)
|
||||
}
|
||||
return input
|
||||
}
|
||||
|
||||
func normalizeToolChoice(any) string {
|
||||
// IOP does not yet emit OpenAI tool_calls, so prevent downstream auto
|
||||
// tool selection from turning an otherwise valid chat request into a 400.
|
||||
return "none"
|
||||
}
|
||||
|
||||
func setOptionInt(options map[string]any, key string, val *int) {
|
||||
if val != nil {
|
||||
options[key] = *val
|
||||
|
|
|
|||
|
|
@ -332,8 +332,7 @@ func TestListNodeSnapshotsWithConfig(t *testing.T) {
|
|||
Alias: "alpha",
|
||||
Token: "tok-1",
|
||||
Runtime: config.RuntimeConf{
|
||||
Concurrency: 3,
|
||||
WorkspaceRoot: "/workspace",
|
||||
Concurrency: 3,
|
||||
},
|
||||
Adapters: config.AdaptersConf{
|
||||
OllamaInstances: []config.OllamaInstanceConf{
|
||||
|
|
|
|||
|
|
@ -273,7 +273,7 @@ func TestEdgeServerIntegration(t *testing.T) {
|
|||
Adapters: config.AdaptersConf{
|
||||
Ollama: config.OllamaConf{Enabled: true, BaseURL: "http://localhost:11434"},
|
||||
},
|
||||
Runtime: config.RuntimeConf{Concurrency: 2, WorkspaceRoot: "/tmp/iop/test"},
|
||||
Runtime: config.RuntimeConf{Concurrency: 2},
|
||||
},
|
||||
})
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -22,11 +22,10 @@ type ConfigSet struct {
|
|||
Runtime RuntimeConfig
|
||||
}
|
||||
|
||||
// RuntimeConfig captures the node-wide runtime tuning carried alongside the
|
||||
// adapter set so config refresh can detect concurrency and workspace changes.
|
||||
// RuntimeConfig captures node-wide runtime tuning carried alongside the adapter
|
||||
// set so config refresh can detect concurrency changes.
|
||||
type RuntimeConfig struct {
|
||||
Concurrency int
|
||||
WorkspaceRoot string
|
||||
Concurrency int
|
||||
}
|
||||
|
||||
type ConfigItem struct {
|
||||
|
|
@ -143,8 +142,7 @@ func BuildConfigSet(payload *iop.NodeConfigPayload, logger *zap.Logger) (*Config
|
|||
Registry: reg,
|
||||
Items: items,
|
||||
Runtime: RuntimeConfig{
|
||||
Concurrency: int(payload.GetRuntime().GetConcurrency()),
|
||||
WorkspaceRoot: payload.GetRuntime().GetWorkspaceRoot(),
|
||||
Concurrency: int(payload.GetRuntime().GetConcurrency()),
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -316,7 +316,7 @@ func buildRequestBody(model string, messages []chatMessage, input map[string]any
|
|||
}
|
||||
}
|
||||
// Pass through optional OpenAI-compatible fields when present in the input.
|
||||
for _, key := range []string{"tools", "format", "think", "keep_alive"} {
|
||||
for _, key := range []string{"tools", "tool_choice", "format", "think", "keep_alive"} {
|
||||
if v, ok := input[key]; ok {
|
||||
body[key] = v
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,39 @@ func TestOpenAICompatExecutePassesOptionsAsTopLevelFields(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatExecutePassesToolsAndToolChoice(t *testing.T) {
|
||||
var body map[string]any
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if err := json.NewDecoder(r.Body).Decode(&body); err != nil {
|
||||
t.Fatalf("decode: %v", err)
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
_, _ = fmt.Fprintf(w, "data: %s\n\n", `{"choices":[{"delta":{"content":"ok"}}]}`)
|
||||
_, _ = fmt.Fprintf(w, "data: [DONE]\n\n")
|
||||
}))
|
||||
defer server.Close()
|
||||
|
||||
adapter := New(config.OpenAICompatConf{Endpoint: server.URL}, zap.NewNop())
|
||||
sink := &fakeSink{}
|
||||
if err := adapter.Execute(context.Background(), runtime.ExecutionSpec{
|
||||
RunID: "run-t",
|
||||
Target: "qwen3.6:35b",
|
||||
Input: map[string]any{
|
||||
"prompt": "hi",
|
||||
"tools": []any{map[string]any{"type": "function"}},
|
||||
"tool_choice": "none",
|
||||
},
|
||||
}, sink); err != nil {
|
||||
t.Fatalf("Execute failed: %v", err)
|
||||
}
|
||||
if tools, ok := body["tools"].([]any); !ok || len(tools) != 1 {
|
||||
t.Fatalf("tools not passed: %+v", body["tools"])
|
||||
}
|
||||
if body["tool_choice"] != "none" {
|
||||
t.Fatalf("tool_choice not passed: %+v", body["tool_choice"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestOpenAICompatExecuteRejectsEmptyEndpointOrModel(t *testing.T) {
|
||||
t.Run("empty_endpoint", func(t *testing.T) {
|
||||
adapter := New(config.OpenAICompatConf{}, zap.NewNop())
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
|
@ -83,7 +82,7 @@ func connectRuntime(ctx context.Context, cfg *config.NodeConfig, logger *zap.Log
|
|||
}
|
||||
owner.reg = set.Registry
|
||||
|
||||
dsn, err := storeDSN(result.Config.GetRuntime().GetWorkspaceRoot())
|
||||
dsn, err := storeDSN()
|
||||
if err != nil {
|
||||
owner.close()
|
||||
return nil, err
|
||||
|
|
@ -278,14 +277,8 @@ func Module(cfg *config.NodeConfig, opts ...Option) fx.Option {
|
|||
)
|
||||
}
|
||||
|
||||
func storeDSN(workspaceRoot string) (string, error) {
|
||||
if workspaceRoot == "" {
|
||||
return "file:iop.db?cache=shared&mode=rwc", nil
|
||||
}
|
||||
if err := os.MkdirAll(workspaceRoot, 0o755); err != nil {
|
||||
return "", fmt.Errorf("bootstrap: workspace: %w", err)
|
||||
}
|
||||
return "file:" + filepath.Join(workspaceRoot, "iop.db") + "?cache=shared&mode=rwc", nil
|
||||
func storeDSN() (string, error) {
|
||||
return "file:iop.db?cache=shared&mode=rwc", nil
|
||||
}
|
||||
|
||||
func printEdgeEvent(out io.Writer, event *iop.EdgeNodeEvent) {
|
||||
|
|
|
|||
|
|
@ -6,7 +6,6 @@ import (
|
|||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"runtime"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
|
|
@ -16,7 +15,6 @@ import (
|
|||
"go.uber.org/fx"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/protobuf/proto"
|
||||
"google.golang.org/protobuf/types/known/structpb"
|
||||
|
||||
"iop/apps/node/internal/bootstrap"
|
||||
"iop/apps/node/internal/transport"
|
||||
|
|
@ -46,111 +44,26 @@ func freeAddrForBootstrap(t *testing.T) (host string, port int, addr string) {
|
|||
return h, port, addr
|
||||
}
|
||||
|
||||
// TestModuleDoesNotStartAdaptersBeforeStoreReady verifies that reg.Start is
|
||||
// invoked only after the store is initialised. If storeDSN fails (workspace_root
|
||||
// is an existing file, not a directory), the CLI persistent process must not
|
||||
// have been started — the marker file must not exist.
|
||||
func TestModuleDoesNotStartAdaptersBeforeStoreReady(t *testing.T) {
|
||||
if runtime.GOOS == "windows" {
|
||||
t.Skip("Unix shell required")
|
||||
}
|
||||
|
||||
// A regular file used as workspace root → os.MkdirAll fails.
|
||||
wsFile, err := os.CreateTemp("", "iop-ws-*")
|
||||
func useTempCwd(t *testing.T) {
|
||||
t.Helper()
|
||||
previous, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatalf("create temp file: %v", err)
|
||||
t.Fatalf("get cwd: %v", err)
|
||||
}
|
||||
wsFile.Close()
|
||||
t.Cleanup(func() { os.Remove(wsFile.Name()) })
|
||||
|
||||
markerPath := wsFile.Name() + ".marker"
|
||||
t.Cleanup(func() { os.Remove(markerPath) })
|
||||
|
||||
settings, err := structpb.NewStruct(map[string]any{
|
||||
"profiles": map[string]any{
|
||||
"marker-profile": map[string]any{
|
||||
"command": "sh",
|
||||
"args": []any{"-c", fmt.Sprintf(`touch "%s"; sleep 30`, markerPath)},
|
||||
"env": []any{},
|
||||
"persistent": true,
|
||||
"terminal": false,
|
||||
"startup_idle_timeout_ms": float64(50),
|
||||
},
|
||||
},
|
||||
if err := os.Chdir(t.TempDir()); err != nil {
|
||||
t.Fatalf("chdir temp: %v", err)
|
||||
}
|
||||
t.Cleanup(func() {
|
||||
if err := os.Chdir(previous); err != nil {
|
||||
t.Fatalf("restore cwd: %v", err)
|
||||
}
|
||||
})
|
||||
if err != nil {
|
||||
t.Fatalf("build settings: %v", err)
|
||||
}
|
||||
|
||||
host, port, addr := freeAddrForBootstrap(t)
|
||||
|
||||
serverCtx, serverCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
t.Cleanup(serverCancel)
|
||||
|
||||
server := toki.NewTcpServer(host, port, func(conn net.Conn) *toki.TcpClient {
|
||||
client := toki.NewTcpClient(conn, 30, 10, bootstrapEdgeParserMap())
|
||||
toki.AddRequestListenerTyped[*iop.RegisterRequest, *iop.RegisterResponse](
|
||||
&client.Communicator,
|
||||
func(_ *iop.RegisterRequest) (*iop.RegisterResponse, error) {
|
||||
return &iop.RegisterResponse{
|
||||
Accepted: true,
|
||||
NodeId: "bootstrap-test-node",
|
||||
Alias: "test",
|
||||
Config: &iop.NodeConfigPayload{
|
||||
Runtime: &iop.NodeRuntimeConfig{
|
||||
WorkspaceRoot: wsFile.Name(), // file, not dir → storeDSN fails
|
||||
},
|
||||
Adapters: []*iop.AdapterConfig{
|
||||
{
|
||||
Type: "cli",
|
||||
Enabled: true,
|
||||
Settings: settings,
|
||||
},
|
||||
},
|
||||
},
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
return client
|
||||
})
|
||||
if err := server.Start(serverCtx); err != nil {
|
||||
t.Fatalf("start mock edge server: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { server.Stop() })
|
||||
|
||||
cfg := &config.NodeConfig{
|
||||
Transport: config.TransportConf{
|
||||
EdgeAddr: addr,
|
||||
Token: "test-token",
|
||||
},
|
||||
Logging: config.LoggingConf{Level: "error"},
|
||||
}
|
||||
|
||||
app := fx.New(
|
||||
bootstrap.Module(cfg),
|
||||
fx.NopLogger,
|
||||
)
|
||||
|
||||
startCtx, startCancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer startCancel()
|
||||
|
||||
startErr := app.Start(startCtx)
|
||||
if startErr == nil {
|
||||
_ = app.Stop(context.Background())
|
||||
t.Fatal("expected bootstrap to fail when workspace root is an existing file")
|
||||
}
|
||||
|
||||
// Allow a brief moment in case a process was spawned despite the fix.
|
||||
time.Sleep(150 * time.Millisecond)
|
||||
|
||||
if _, statErr := os.Stat(markerPath); statErr == nil {
|
||||
t.Fatal("marker file was created — adapter was started before store was ready")
|
||||
}
|
||||
}
|
||||
|
||||
// TestReconnectSupervisorReestablishesSession verifies that after the edge-side
|
||||
// client closes the connection, the supervisor reconnects and re-registers.
|
||||
func TestReconnectSupervisorReestablishesSession(t *testing.T) {
|
||||
useTempCwd(t)
|
||||
host, port, addr := freeAddrForBootstrap(t)
|
||||
|
||||
serverCtx, serverCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
|
@ -169,7 +82,7 @@ func TestReconnectSupervisorReestablishesSession(t *testing.T) {
|
|||
return &iop.RegisterResponse{
|
||||
Accepted: true,
|
||||
NodeId: "reconnect-test-node",
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1, WorkspaceRoot: t.TempDir()}},
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1}},
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
|
@ -223,6 +136,7 @@ func TestReconnectSupervisorReestablishesSession(t *testing.T) {
|
|||
// TestReconnectSupervisorExhaustsRetries verifies that when all reconnect
|
||||
// attempts fail, the node cleans up resources and calls Shutdown(ExitCode(1)).
|
||||
func TestReconnectSupervisorExhaustsRetries(t *testing.T) {
|
||||
useTempCwd(t)
|
||||
host, port, addr := freeAddrForBootstrap(t)
|
||||
|
||||
serverCtx, serverCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
|
@ -237,7 +151,7 @@ func TestReconnectSupervisorExhaustsRetries(t *testing.T) {
|
|||
return &iop.RegisterResponse{
|
||||
Accepted: true,
|
||||
NodeId: "exhaust-test-node",
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1, WorkspaceRoot: t.TempDir()}},
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1}},
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
|
@ -306,6 +220,7 @@ func TestReconnectSupervisorExhaustsRetries(t *testing.T) {
|
|||
// respects MaxAttempts=10 and that the fake sleeper receives IntervalSec=10s
|
||||
// before each reconnect attempt (SDD reconnect_waiting state).
|
||||
func TestReconnectSupervisorPolicyTimingAndLimit(t *testing.T) {
|
||||
useTempCwd(t)
|
||||
host, port, addr := freeAddrForBootstrap(t)
|
||||
|
||||
serverCtx, serverCancel := context.WithTimeout(context.Background(), 10*time.Second)
|
||||
|
|
@ -320,7 +235,7 @@ func TestReconnectSupervisorPolicyTimingAndLimit(t *testing.T) {
|
|||
return &iop.RegisterResponse{
|
||||
Accepted: true,
|
||||
NodeId: "policy-test-node",
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1, WorkspaceRoot: t.TempDir()}},
|
||||
Config: &iop.NodeConfigPayload{Runtime: &iop.NodeRuntimeConfig{Concurrency: 1}},
|
||||
}, nil
|
||||
},
|
||||
)
|
||||
|
|
|
|||
|
|
@ -334,30 +334,12 @@ func (n *Node) OnConfigRefresh(ctx context.Context, _ *transport.Session, req *i
|
|||
n.configSetMu.Lock()
|
||||
defer n.configSetMu.Unlock()
|
||||
|
||||
// Runtime tuning. workspace_root cannot be applied live because the store DB
|
||||
// path is fixed at bootstrap, so a change is reported as restart_required
|
||||
// without touching the running store. Concurrency is applied live but
|
||||
// deferred until after adapter registry start/swap succeeds so that a
|
||||
// failed refresh preserves the previous admission state.
|
||||
// Runtime tuning. Concurrency is applied live but deferred until after
|
||||
// adapter registry start/swap succeeds so that a failed refresh preserves
|
||||
// the previous admission state.
|
||||
var nextConcurrency int
|
||||
var hasRuntimeConcurrencyChange bool
|
||||
if rc := req.GetConfig().GetRuntime(); rc != nil {
|
||||
currentWorkspaceRoot := ""
|
||||
if n.currentConfigSet != nil {
|
||||
currentWorkspaceRoot = n.currentConfigSet.Runtime.WorkspaceRoot
|
||||
}
|
||||
if rc.GetWorkspaceRoot() != currentWorkspaceRoot {
|
||||
n.logger.Info("config refresh: workspace_root change requires restart",
|
||||
zap.String("current", currentWorkspaceRoot),
|
||||
zap.String("next", rc.GetWorkspaceRoot()),
|
||||
)
|
||||
return &iop.NodeConfigRefreshResponse{
|
||||
RequestId: req.GetRequestId(),
|
||||
Status: iop.NodeConfigRefreshStatus_NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED,
|
||||
RestartRequiredPaths: []string{"runtime.workspace_root"},
|
||||
}, nil
|
||||
}
|
||||
|
||||
// Pre-compute the concurrency change without mutating the gate yet.
|
||||
nextConcurrency = int(rc.GetConcurrency())
|
||||
hasRuntimeConcurrencyChange = nextConcurrency != n.globalGate.currentCapacity()
|
||||
|
|
@ -367,8 +349,6 @@ func (n *Node) OnConfigRefresh(ctx context.Context, _ *transport.Session, req *i
|
|||
|
||||
if len(diff.Added) == 0 && len(diff.Updated) == 0 && len(diff.Removed) == 0 {
|
||||
n.logger.Info("config refresh: no adapter changes detected")
|
||||
// Persist the latest runtime snapshot even when adapters are unchanged so
|
||||
// subsequent refreshes diff workspace_root against the applied value.
|
||||
if n.currentConfigSet != nil {
|
||||
n.currentConfigSet.Runtime = nextSet.Runtime
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2863,44 +2863,3 @@ func (a *blockingAdapterWithStart) Start(_ context.Context) error {
|
|||
func (a *blockingAdapterWithStart) Stop(_ context.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func TestConfigRefreshWorkspaceRootReportsRestartRequired(t *testing.T) {
|
||||
initialPayload := &iop.NodeConfigPayload{
|
||||
Runtime: &iop.NodeRuntimeConfig{Concurrency: 1, WorkspaceRoot: "/tmp/ws-a"},
|
||||
}
|
||||
set, err := adapters.BuildConfigSet(initialPayload, zap.NewNop())
|
||||
if err != nil {
|
||||
t.Fatalf("BuildConfigSet: %v", err)
|
||||
}
|
||||
|
||||
rtr := router.New(set.Registry, zap.NewNop())
|
||||
st, err := store.New(":memory:", zap.NewNop())
|
||||
if err != nil {
|
||||
t.Fatalf("store: %v", err)
|
||||
}
|
||||
t.Cleanup(func() { _ = st.Close() })
|
||||
|
||||
n := node.New("test-node", rtr, st, 1, io.Discard, zap.NewNop(), set)
|
||||
|
||||
resp, refreshErr := n.OnConfigRefresh(context.Background(), nil, &iop.NodeConfigRefreshRequest{
|
||||
RequestId: "refresh-ws",
|
||||
Config: &iop.NodeConfigPayload{
|
||||
Runtime: &iop.NodeRuntimeConfig{Concurrency: 1, WorkspaceRoot: "/tmp/ws-b"},
|
||||
},
|
||||
})
|
||||
if refreshErr != nil {
|
||||
t.Fatalf("OnConfigRefresh failed: %v", refreshErr)
|
||||
}
|
||||
if resp.Status != iop.NodeConfigRefreshStatus_NODE_CONFIG_REFRESH_STATUS_RESTART_REQUIRED {
|
||||
t.Fatalf("expected RESTART_REQUIRED, got %v", resp.Status)
|
||||
}
|
||||
foundWS := false
|
||||
for _, p := range resp.GetRestartRequiredPaths() {
|
||||
if p == "runtime.workspace_root" {
|
||||
foundWS = true
|
||||
}
|
||||
}
|
||||
if !foundWS {
|
||||
t.Fatalf("expected runtime.workspace_root in restart_required paths, got %v", resp.GetRestartRequiredPaths())
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -251,7 +251,6 @@ nodes:
|
|||
mode: "codex-exec"
|
||||
runtime:
|
||||
concurrency: 1
|
||||
workspace_root: ""
|
||||
|
||||
# Multi-adapter example: two Ollama instances + CLI profiles on one node.
|
||||
# Each ollama_instances entry requires a unique "name" within the node.
|
||||
|
|
@ -305,4 +304,3 @@ nodes:
|
|||
# request_timeout_ms: 300000
|
||||
# runtime:
|
||||
# concurrency: 4
|
||||
# workspace_root: "/workspace"
|
||||
|
|
|
|||
|
|
@ -328,8 +328,7 @@ type TLSConf struct {
|
|||
}
|
||||
|
||||
type RuntimeConf struct {
|
||||
Concurrency int `mapstructure:"concurrency" yaml:"concurrency"`
|
||||
WorkspaceRoot string `mapstructure:"workspace_root" yaml:"workspace_root"`
|
||||
Concurrency int `mapstructure:"concurrency" yaml:"concurrency"`
|
||||
}
|
||||
|
||||
type SQLiteConf struct {
|
||||
|
|
|
|||
|
|
@ -2110,7 +2110,6 @@ func (x *OpenAICompatAdapterConfig) GetRequestTimeoutMs() int32 {
|
|||
type NodeRuntimeConfig struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
Concurrency int32 `protobuf:"varint,1,opt,name=concurrency,proto3" json:"concurrency,omitempty"`
|
||||
WorkspaceRoot string `protobuf:"bytes,2,opt,name=workspace_root,json=workspaceRoot,proto3" json:"workspace_root,omitempty"`
|
||||
unknownFields protoimpl.UnknownFields
|
||||
sizeCache protoimpl.SizeCache
|
||||
}
|
||||
|
|
@ -2152,13 +2151,6 @@ func (x *NodeRuntimeConfig) GetConcurrency() int32 {
|
|||
return 0
|
||||
}
|
||||
|
||||
func (x *NodeRuntimeConfig) GetWorkspaceRoot() string {
|
||||
if x != nil {
|
||||
return x.WorkspaceRoot
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// NodeConfigRefreshRequest is sent by edge to a connected node to push a new config payload.
|
||||
type NodeConfigRefreshRequest struct {
|
||||
state protoimpl.MessageState `protogen:"open.v1"`
|
||||
|
|
@ -2492,10 +2484,9 @@ const file_proto_iop_runtime_proto_rawDesc = "" +
|
|||
"\x12request_timeout_ms\x18\a \x01(\x05R\x10requestTimeoutMs\x1a:\n" +
|
||||
"\fHeadersEntry\x12\x10\n" +
|
||||
"\x03key\x18\x01 \x01(\tR\x03key\x12\x14\n" +
|
||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\"\\\n" +
|
||||
"\x05value\x18\x02 \x01(\tR\x05value:\x028\x01\";\n" +
|
||||
"\x11NodeRuntimeConfig\x12 \n" +
|
||||
"\vconcurrency\x18\x01 \x01(\x05R\vconcurrency\x12%\n" +
|
||||
"\x0eworkspace_root\x18\x02 \x01(\tR\rworkspaceRoot\"\x8e\x01\n" +
|
||||
"\vconcurrency\x18\x01 \x01(\x05R\vconcurrencyJ\x04\b\x02\x10\x03\"\x8e\x01\n" +
|
||||
"\x18NodeConfigRefreshRequest\x12\x1d\n" +
|
||||
"\n" +
|
||||
"request_id\x18\x01 \x01(\tR\trequestId\x12.\n" +
|
||||
|
|
|
|||
|
|
@ -251,7 +251,7 @@ message OpenAICompatAdapterConfig {
|
|||
// NodeRuntimeConfig is the runtime tuning pushed to the node.
|
||||
message NodeRuntimeConfig {
|
||||
int32 concurrency = 1;
|
||||
string workspace_root = 2;
|
||||
reserved 2;
|
||||
}
|
||||
|
||||
enum NodeConfigRefreshStatus {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@ set -euo pipefail
|
|||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
REPO_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
CONFIG_FILE="${IOP_NODE_CONFIG:-$REPO_ROOT/configs/node.yaml}"
|
||||
CONFIG_DIR="$(cd "$(dirname "$CONFIG_FILE")" && pwd)"
|
||||
|
||||
cd "$REPO_ROOT"
|
||||
echo "[node] config=$CONFIG_FILE"
|
||||
|
|
@ -33,4 +34,11 @@ while ! timeout 1 bash -c 'cat < /dev/null > /dev/tcp/"$1"/"$2"' _ "$EDGE_HOST"
|
|||
done
|
||||
echo "[node] edge is reachable"
|
||||
|
||||
exec go run ./apps/node/cmd/node serve --config "$CONFIG_FILE"
|
||||
NODE_BIN="${IOP_NODE_BIN:-$REPO_ROOT/build/dev/iop-node}"
|
||||
if [[ -z "${IOP_NODE_BIN:-}" ]]; then
|
||||
mkdir -p "$(dirname "$NODE_BIN")"
|
||||
(cd "$REPO_ROOT" && go build -o "$NODE_BIN" ./apps/node/cmd/node)
|
||||
fi
|
||||
|
||||
cd "$CONFIG_DIR"
|
||||
exec "$NODE_BIN" serve --config "$CONFIG_FILE"
|
||||
|
|
|
|||
|
|
@ -78,8 +78,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/node_workspace"
|
||||
adapters:
|
||||
cli:
|
||||
enabled: true
|
||||
|
|
|
|||
|
|
@ -84,61 +84,61 @@ else
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type chatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Stream bool `json:"stream"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
Model string `json:"model"`
|
||||
Stream bool `json:"stream"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 3 {
|
||||
log.Fatal("usage: fake_lemonade <listen-addr> <model>")
|
||||
}
|
||||
model := os.Args[2]
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/v1/models", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"object":"list","data":[{"id":"` + model + `"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/v1/chat/completions", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != model {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !req.Stream {
|
||||
http.Error(w, "expected stream=true from openai_compat adapter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
flush := func() {
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"reasoning_content":"thinking..."}}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"IOP_OPENAI_"}}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"LEMONADE_OK"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: [DONE]\n\n"))
|
||||
flush()
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
if len(os.Args) < 3 {
|
||||
log.Fatal("usage: fake_lemonade <listen-addr> <model>")
|
||||
}
|
||||
model := os.Args[2]
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/v1/models", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"object":"list","data":[{"id":"` + model + `"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/v1/chat/completions", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != model {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !req.Stream {
|
||||
http.Error(w, "expected stream=true from openai_compat adapter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
flush := func() {
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"reasoning_content":"thinking..."}}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"IOP_OPENAI_"}}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"LEMONADE_OK"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: [DONE]\n\n"))
|
||||
flush()
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -198,8 +198,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/workspace"
|
||||
adapters:
|
||||
$(cat "$ADAPTER_BLOCK")
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -35,59 +35,59 @@ cat > "$FAKE_OLLAMA" <<'EOF'
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type chatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
Options struct {
|
||||
NumCtx int `json:"num_ctx"`
|
||||
} `json:"options"`
|
||||
Model string `json:"model"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
Options struct {
|
||||
NumCtx int `json:"num_ctx"`
|
||||
} `json:"options"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatal("missing listen addr")
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/tags", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"models":[{"name":"fake-ollama-model"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/api/chat", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != "fake-ollama-model" {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Options.NumCtx != 262144 {
|
||||
http.Error(w, "unexpected num_ctx", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/x-ndjson")
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","thinking":"thinking..."},"done":false}` + "\n"))
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","content":"IOP_OPENAI_"},"done":false}` + "\n"))
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","content":"OLLAMA_OK"},"done":false}` + "\n"))
|
||||
_, _ = w.Write([]byte(`{"done":true,"prompt_eval_count":5,"eval_count":2}` + "\n"))
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
if len(os.Args) < 2 {
|
||||
log.Fatal("missing listen addr")
|
||||
}
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/api/tags", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"models":[{"name":"fake-ollama-model"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/api/chat", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != "fake-ollama-model" {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Options.NumCtx != 262144 {
|
||||
http.Error(w, "unexpected num_ctx", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "application/x-ndjson")
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","thinking":"thinking..."},"done":false}` + "\n"))
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","content":"IOP_OPENAI_"},"done":false}` + "\n"))
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
_, _ = w.Write([]byte(`{"message":{"role":"assistant","content":"OLLAMA_OK"},"done":false}` + "\n"))
|
||||
_, _ = w.Write([]byte(`{"done":true,"prompt_eval_count":5,"eval_count":2}` + "\n"))
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -142,8 +142,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/workspace"
|
||||
adapters:
|
||||
ollama:
|
||||
enabled: true
|
||||
|
|
|
|||
|
|
@ -88,59 +88,59 @@ else
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/http"
|
||||
"os"
|
||||
)
|
||||
|
||||
type chatRequest struct {
|
||||
Model string `json:"model"`
|
||||
Stream bool `json:"stream"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
Model string `json:"model"`
|
||||
Stream bool `json:"stream"`
|
||||
Messages []struct {
|
||||
Role string `json:"role"`
|
||||
Content string `json:"content"`
|
||||
} `json:"messages"`
|
||||
}
|
||||
|
||||
func main() {
|
||||
if len(os.Args) < 3 {
|
||||
log.Fatal("usage: fake_vllm <listen-addr> <served-model>")
|
||||
}
|
||||
servedModel := os.Args[2]
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/v1/models", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"object":"list","data":[{"id":"` + servedModel + `"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/v1/chat/completions", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != servedModel {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !req.Stream {
|
||||
http.Error(w, "expected stream=true from openai_compat adapter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
flush := func() {
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"IOP_OPENAI_"},"finish_reason":null}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"VLLM_OK"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: [DONE]\n\n"))
|
||||
flush()
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
if len(os.Args) < 3 {
|
||||
log.Fatal("usage: fake_vllm <listen-addr> <served-model>")
|
||||
}
|
||||
servedModel := os.Args[2]
|
||||
mux := http.NewServeMux()
|
||||
mux.HandleFunc("/v1/models", func(w http.ResponseWriter, _ *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
_, _ = w.Write([]byte(`{"object":"list","data":[{"id":"` + servedModel + `"}]}`))
|
||||
})
|
||||
mux.HandleFunc("/v1/chat/completions", func(w http.ResponseWriter, r *http.Request) {
|
||||
var req chatRequest
|
||||
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
|
||||
http.Error(w, err.Error(), http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if req.Model != servedModel {
|
||||
http.Error(w, "unexpected model: "+req.Model, http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
if !req.Stream {
|
||||
http.Error(w, "expected stream=true from openai_compat adapter", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/event-stream")
|
||||
flush := func() {
|
||||
if f, ok := w.(http.Flusher); ok {
|
||||
f.Flush()
|
||||
}
|
||||
}
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"IOP_OPENAI_"},"finish_reason":null}]}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: " + `{"choices":[{"delta":{"content":"VLLM_OK"},"finish_reason":"stop"}],"usage":{"prompt_tokens":5,"completion_tokens":2}}` + "\n\n"))
|
||||
flush()
|
||||
_, _ = w.Write([]byte("data: [DONE]\n\n"))
|
||||
flush()
|
||||
})
|
||||
log.Fatal(http.ListenAndServe(os.Args[1], mux))
|
||||
}
|
||||
EOF
|
||||
|
||||
|
|
@ -196,8 +196,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/workspace"
|
||||
adapters:
|
||||
$(cat "$ADAPTER_BLOCK")
|
||||
EOF
|
||||
|
|
|
|||
|
|
@ -140,8 +140,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/workspace"
|
||||
adapters:
|
||||
mock:
|
||||
enabled: true
|
||||
|
|
@ -211,8 +209,6 @@ nodes:
|
|||
- id: test-node
|
||||
alias: test-node
|
||||
token: test-token
|
||||
runtime:
|
||||
workspace_root: "$TMP_DIR/workspace"
|
||||
adapters:
|
||||
cli:
|
||||
enabled: true
|
||||
|
|
@ -685,8 +681,6 @@ elif [ "$IS_PERSISTENT" -eq 1 ]; then
|
|||
check_grep "mode=persistent target=${TARGET} session=session2" "$EDGE_OUT" "/sessions entry for session2 not found"
|
||||
fi
|
||||
|
||||
check_no_grep 'file:iop.db?cache=shared&mode=rwc' "$NODE_OUT" "node store used repo-root fallback dsn"
|
||||
|
||||
if [ "$IS_PERSISTENT" -eq 1 ]; then
|
||||
check_grep "terminated session" "$EDGE_OUT" "/terminate-session success not found"
|
||||
fi
|
||||
|
|
|
|||
Loading…
Reference in a new issue