@openviking/openclaw-plugin 2026.6.2 → 2026.6.17-dev.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/INSTALL-AGENT.md +4 -4
- package/INSTALL-ZH.md +68 -8
- package/INSTALL.md +12 -8
- package/README.md +45 -35
- package/adapters/http-transport.ts +3 -0
- package/adapters/resource-packager.ts +141 -0
- package/auto-recall.ts +258 -27
- package/client.ts +201 -177
- package/commands/setup.ts +200 -33
- package/config/feature-gates.json +10 -0
- package/config.ts +428 -85
- package/context-engine.ts +71 -1402
- package/dist/adapters/http-transport.js +1 -0
- package/dist/adapters/resource-packager.js +114 -0
- package/dist/auto-recall.js +201 -25
- package/dist/client.js +125 -161
- package/dist/commands/setup.js +170 -32
- package/dist/config.js +285 -64
- package/dist/context-engine.js +62 -1173
- package/dist/index.js +209 -1489
- package/dist/memory-ranking.js +35 -12
- package/dist/plugin/command-registration.js +5 -0
- package/dist/plugin/openviking-archive-tools.js +210 -0
- package/dist/plugin/openviking-bypass-runtime.js +8 -0
- package/dist/plugin/openviking-client-runtime.js +28 -0
- package/dist/plugin/openviking-command-args.js +146 -0
- package/dist/plugin/openviking-command-definitions.js +206 -0
- package/dist/plugin/openviking-context-engine-ref.js +11 -0
- package/dist/plugin/openviking-context-engine-registration.js +23 -0
- package/dist/plugin/openviking-feature-gates.js +250 -0
- package/dist/plugin/openviking-import-runtime.js +50 -0
- package/dist/plugin/openviking-import-tools.js +86 -0
- package/dist/plugin/openviking-lifecycle-hooks.js +33 -0
- package/dist/plugin/openviking-memory-recall-tools.js +233 -0
- package/dist/plugin/openviking-memory-tools.js +199 -0
- package/dist/plugin/openviking-query-config-command.js +203 -0
- package/dist/plugin/openviking-query-runtime.js +367 -0
- package/dist/plugin/openviking-query-tools.js +91 -0
- package/dist/plugin/openviking-recall-trace-runtime.js +387 -0
- package/dist/plugin/openviking-recall-trace-tools.js +38 -0
- package/dist/plugin/openviking-runtime-state.js +26 -0
- package/dist/plugin/openviking-runtime-utils.js +62 -0
- package/dist/plugin/openviking-services.js +20 -0
- package/dist/plugin/openviking-session-routing-runtime.js +61 -0
- package/dist/plugin/openviking-tool-result-tools.js +268 -0
- package/dist/plugin/recall-trace-routes.js +77 -0
- package/dist/plugin/tool-registration.js +23 -0
- package/dist/process-manager.js +1 -1
- package/dist/query-config.js +336 -0
- package/dist/recall-trace.js +309 -0
- package/dist/registries/recall-resource-types.js +58 -0
- package/dist/routing/identity-routing.js +152 -0
- package/dist/routing/memory-uri.js +7 -0
- package/dist/services/context-lifecycle-service.js +847 -0
- package/dist/services/context-message-adapter.js +340 -0
- package/dist/session-transcript-repair.js +0 -1
- package/dist/text-utils.js +14 -31
- package/index.ts +271 -1873
- package/install-manifest.json +10 -1
- package/memory-ranking.ts +46 -10
- package/openclaw.plugin.json +198 -36
- package/package.json +14 -4
- package/plugin/command-registration.ts +34 -0
- package/plugin/openviking-archive-tools.ts +301 -0
- package/plugin/openviking-bypass-runtime.ts +26 -0
- package/plugin/openviking-client-runtime.ts +74 -0
- package/plugin/openviking-command-args.ts +187 -0
- package/plugin/openviking-command-definitions.ts +294 -0
- package/plugin/openviking-context-engine-ref.ts +16 -0
- package/plugin/openviking-context-engine-registration.ts +97 -0
- package/plugin/openviking-feature-gates.ts +335 -0
- package/plugin/openviking-import-runtime.ts +105 -0
- package/plugin/openviking-import-tools.ts +133 -0
- package/plugin/openviking-lifecycle-hooks.ts +65 -0
- package/plugin/openviking-memory-recall-tools.ts +368 -0
- package/plugin/openviking-memory-tools.ts +299 -0
- package/plugin/openviking-query-config-command.ts +230 -0
- package/plugin/openviking-query-formatters.ts +108 -0
- package/plugin/openviking-query-runtime.ts +476 -0
- package/plugin/openviking-query-tools.ts +161 -0
- package/plugin/openviking-recall-trace-runtime.ts +482 -0
- package/plugin/openviking-recall-trace-tools.ts +99 -0
- package/plugin/openviking-runtime-state.ts +52 -0
- package/plugin/openviking-runtime-utils.ts +67 -0
- package/plugin/openviking-services.ts +49 -0
- package/plugin/openviking-session-routing-runtime.ts +105 -0
- package/plugin/openviking-tool-result-tools.ts +397 -0
- package/plugin/recall-trace-routes.ts +133 -0
- package/plugin/tool-registration.ts +51 -0
- package/process-manager.ts +1 -1
- package/query-config.ts +400 -0
- package/recall-trace.ts +442 -0
- package/registries/openviking-tools.ts +84 -0
- package/registries/recall-resource-types.ts +74 -0
- package/routing/identity-routing.ts +210 -0
- package/routing/memory-uri.ts +8 -0
- package/services/context-lifecycle-service.ts +1209 -0
- package/services/context-message-adapter.ts +375 -0
- package/services/setup/config-writer.ts +125 -0
- package/services/setup/exit-utils.ts +5 -0
- package/services/setup/package-metadata.ts +56 -0
- package/services/setup/probe-service.ts +143 -0
- package/services/setup/setup-flow.ts +306 -0
- package/services/setup/version-compatibility.ts +41 -0
- package/session-transcript-repair.ts +0 -2
- package/skills/install-openviking-memory/SKILL.md +123 -50
- package/skills/openviking-context-database/SKILL.md +286 -0
- package/text-utils.ts +15 -34
package/commands/setup.ts
CHANGED
|
@@ -56,6 +56,32 @@ function readCompatRangeFromManifest(): { min: string; max: string } {
|
|
|
56
56
|
|
|
57
57
|
const PLUGIN_VERSION = readPluginVersion();
|
|
58
58
|
const { min: COMPATIBLE_SERVER_MIN, max: COMPATIBLE_SERVER_MAX } = readCompatRangeFromManifest();
|
|
59
|
+
const CONFIG_KEYS_TO_PRESERVE = [
|
|
60
|
+
"targetUri",
|
|
61
|
+
"timeoutMs",
|
|
62
|
+
"autoCapture",
|
|
63
|
+
"captureMode",
|
|
64
|
+
"captureMaxLength",
|
|
65
|
+
"autoRecall",
|
|
66
|
+
"recallResources",
|
|
67
|
+
"recallTargetTypes",
|
|
68
|
+
"recallLimit",
|
|
69
|
+
"recallScoreThreshold",
|
|
70
|
+
"recallMaxInjectedChars",
|
|
71
|
+
"recallMaxContentChars",
|
|
72
|
+
"recallPreferAbstract",
|
|
73
|
+
"recallTokenBudget",
|
|
74
|
+
"commitTokenThreshold",
|
|
75
|
+
"commitKeepRecentCount",
|
|
76
|
+
"bypassSessionPatterns",
|
|
77
|
+
"emitStandardDiagnostics",
|
|
78
|
+
"logFindRequests",
|
|
79
|
+
] as const;
|
|
80
|
+
|
|
81
|
+
type PeerRole = "none" | "assistant" | "person";
|
|
82
|
+
const DEFAULT_SETUP_PEER_ROLE: PeerRole = "assistant";
|
|
83
|
+
type RecallTargetType = "resource" | "user" | "agent";
|
|
84
|
+
const ALLOWED_RECALL_TARGET_TYPES = ["resource", "user", "agent"] as const;
|
|
59
85
|
|
|
60
86
|
type CommandProgram = {
|
|
61
87
|
command: (name: string) => CommandBuilder;
|
|
@@ -81,29 +107,129 @@ function maskKey(key: string): string {
|
|
|
81
107
|
return `${key.slice(0, 4)}...${key.slice(-4)}`;
|
|
82
108
|
}
|
|
83
109
|
|
|
84
|
-
function
|
|
110
|
+
function isValidPeerPrefixInput(value: string): boolean {
|
|
85
111
|
const trimmed = value.trim();
|
|
86
112
|
return !trimmed || /^[a-zA-Z0-9_-]+$/.test(trimmed);
|
|
87
113
|
}
|
|
88
114
|
|
|
89
|
-
|
|
115
|
+
function normalizePeerRole(value: unknown): PeerRole | undefined {
|
|
116
|
+
if (typeof value !== "string") return undefined;
|
|
117
|
+
const role = value.trim().toLowerCase();
|
|
118
|
+
if (role === "none" || role === "assistant" || role === "person") return role;
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function resolveExistingPeerRole(existing: Record<string, unknown> | null | undefined): PeerRole {
|
|
123
|
+
const explicit = normalizePeerRole(existing?.peer_role);
|
|
124
|
+
if (explicit) return explicit;
|
|
125
|
+
return DEFAULT_SETUP_PEER_ROLE;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function resolveExistingPeerPrefix(existing: Record<string, unknown> | null | undefined): string {
|
|
129
|
+
const value = existing?.peer_prefix;
|
|
130
|
+
if (typeof value !== "string" || !value.trim()) return "";
|
|
131
|
+
const trimmed = value.trim();
|
|
132
|
+
return trimmed === "default" ? "" : trimmed;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
function resolveSetupPeerRole(value: unknown): PeerRole {
|
|
136
|
+
if (value === undefined) return DEFAULT_SETUP_PEER_ROLE;
|
|
137
|
+
const role = normalizePeerRole(value);
|
|
138
|
+
if (role) return role;
|
|
139
|
+
throw new Error('peer_role must be "none", "assistant", or "person"');
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function normalizeSetupRecallTargetTypes(value: unknown): RecallTargetType[] | undefined {
|
|
143
|
+
if (value === undefined || value === null || value === "") {
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
const entries = Array.isArray(value)
|
|
147
|
+
? value
|
|
148
|
+
: typeof value === "string"
|
|
149
|
+
? value.split(/[,\n]/)
|
|
150
|
+
: [];
|
|
151
|
+
const seen = new Set<RecallTargetType>();
|
|
152
|
+
const normalized: RecallTargetType[] = [];
|
|
153
|
+
const unknown: string[] = [];
|
|
154
|
+
|
|
155
|
+
for (const raw of entries) {
|
|
156
|
+
if (typeof raw !== "string") {
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
const entry = raw.trim();
|
|
160
|
+
if (!entry) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if ((ALLOWED_RECALL_TARGET_TYPES as readonly string[]).includes(entry)) {
|
|
164
|
+
const typed = entry as RecallTargetType;
|
|
165
|
+
if (!seen.has(typed)) {
|
|
166
|
+
seen.add(typed);
|
|
167
|
+
normalized.push(typed);
|
|
168
|
+
}
|
|
169
|
+
} else {
|
|
170
|
+
unknown.push(entry);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (unknown.length > 0) {
|
|
175
|
+
throw new Error(`recall-target-types contains unknown resource types: ${unknown.join(", ")}`);
|
|
176
|
+
}
|
|
177
|
+
return normalized.length > 0 ? normalized : undefined;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function preserveCurrentConfig(existing: Record<string, unknown> | null | undefined) {
|
|
181
|
+
const config: Record<string, unknown> = {};
|
|
182
|
+
if (!existing) {
|
|
183
|
+
return config;
|
|
184
|
+
}
|
|
185
|
+
for (const key of CONFIG_KEYS_TO_PRESERVE) {
|
|
186
|
+
if (key in existing) {
|
|
187
|
+
config[key] = existing[key];
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return config;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
async function askPeerRole(
|
|
194
|
+
zh: boolean,
|
|
195
|
+
q: (prompt: string, def?: string) => Promise<string>,
|
|
196
|
+
defaultValue: PeerRole,
|
|
197
|
+
): Promise<PeerRole> {
|
|
198
|
+
while (true) {
|
|
199
|
+
const value = await q(
|
|
200
|
+
tr(zh, "Peer Role (none/assistant/person)", "Peer Role(none/assistant/person)"),
|
|
201
|
+
defaultValue,
|
|
202
|
+
);
|
|
203
|
+
const role = normalizePeerRole(value);
|
|
204
|
+
if (role) return role;
|
|
205
|
+
console.log(
|
|
206
|
+
` ✗ ${tr(
|
|
207
|
+
zh,
|
|
208
|
+
'Peer Role must be "none", "assistant", or "person".',
|
|
209
|
+
'Peer Role 必须是 "none"、"assistant" 或 "person"。',
|
|
210
|
+
)}`,
|
|
211
|
+
);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
async function askPeerPrefix(
|
|
90
216
|
zh: boolean,
|
|
91
217
|
q: (prompt: string, def?: string) => Promise<string>,
|
|
92
218
|
defaultValue: string,
|
|
93
219
|
): Promise<string> {
|
|
94
220
|
while (true) {
|
|
95
221
|
const value = (await q(
|
|
96
|
-
tr(zh, "
|
|
222
|
+
tr(zh, "Peer Prefix (optional)", "Peer Prefix(可选)"),
|
|
97
223
|
defaultValue,
|
|
98
224
|
)).trim();
|
|
99
|
-
if (
|
|
225
|
+
if (isValidPeerPrefixInput(value)) {
|
|
100
226
|
return value;
|
|
101
227
|
}
|
|
102
228
|
console.log(
|
|
103
229
|
` ✗ ${tr(
|
|
104
230
|
zh,
|
|
105
|
-
"
|
|
106
|
-
"
|
|
231
|
+
"Peer Prefix may only contain letters, digits, underscores, and hyphens, or be empty.",
|
|
232
|
+
"Peer Prefix 只能包含字母、数字、下划线和连字符,或留空。",
|
|
107
233
|
)}`,
|
|
108
234
|
);
|
|
109
235
|
}
|
|
@@ -366,9 +492,11 @@ type SetupResult = {
|
|
|
366
492
|
mode: string;
|
|
367
493
|
baseUrl: string;
|
|
368
494
|
apiKey?: string;
|
|
369
|
-
|
|
495
|
+
peer_role?: PeerRole;
|
|
496
|
+
peer_prefix?: string;
|
|
370
497
|
accountId?: string;
|
|
371
498
|
userId?: string;
|
|
499
|
+
recallTargetTypes?: string[];
|
|
372
500
|
};
|
|
373
501
|
health?: HealthResult;
|
|
374
502
|
keyProbe?: ApiKeyProbeResult;
|
|
@@ -388,7 +516,8 @@ type StatusResult = {
|
|
|
388
516
|
mode: string;
|
|
389
517
|
baseUrl: string;
|
|
390
518
|
hasApiKey: boolean;
|
|
391
|
-
|
|
519
|
+
peer_role: PeerRole;
|
|
520
|
+
peer_prefix?: string;
|
|
392
521
|
hasAccountId: boolean;
|
|
393
522
|
hasUserId: boolean;
|
|
394
523
|
};
|
|
@@ -449,21 +578,23 @@ export function registerSetupCli(api: any): void {
|
|
|
449
578
|
.option("--zh", "Chinese prompts")
|
|
450
579
|
.option("--base-url <url>", "OpenViking server URL (enables non-interactive mode)")
|
|
451
580
|
.option("--api-key <key>", "API key for authentication")
|
|
452
|
-
.option("--
|
|
581
|
+
.option("--peer-role <role>", "Peer ID role: none, assistant, or person")
|
|
582
|
+
.option("--peer-prefix <prefix>", "Prefix for assistant peer_id values")
|
|
453
583
|
.option("--account-id <id>", "Account ID (required for root API keys)")
|
|
454
584
|
.option("--user-id <id>", "User ID (required for root API keys)")
|
|
585
|
+
.option("--recall-target-types <types>", "Comma-separated recall target types: user, agent, resource")
|
|
455
586
|
.option("--allow-offline", "Allow config write even if server is unreachable")
|
|
456
587
|
.option("--force-slot", "Replace existing contextEngine slot even if owned by another plugin")
|
|
457
588
|
.option("--json", "Output result as JSON (machine-readable)")
|
|
458
589
|
.action(async (...args: unknown[]) => {
|
|
459
590
|
const options = (args[0] ?? {}) as Record<string, unknown>;
|
|
460
591
|
const {
|
|
461
|
-
reconfigure, zh: zhOpt, baseUrl, apiKey,
|
|
462
|
-
accountId, userId, allowOffline, forceSlot, json: jsonOpt,
|
|
592
|
+
reconfigure, zh: zhOpt, baseUrl, apiKey, peerRole, peerPrefix,
|
|
593
|
+
accountId, userId, recallTargetTypes, allowOffline, forceSlot, json: jsonOpt,
|
|
463
594
|
} = options as {
|
|
464
595
|
reconfigure?: boolean; zh?: boolean; baseUrl?: string;
|
|
465
|
-
apiKey?: string;
|
|
466
|
-
userId?: string; allowOffline?: boolean; forceSlot?: boolean;
|
|
596
|
+
apiKey?: string; peerRole?: string; peerPrefix?: string; accountId?: string;
|
|
597
|
+
userId?: string; recallTargetTypes?: string; allowOffline?: boolean; forceSlot?: boolean;
|
|
467
598
|
json?: boolean;
|
|
468
599
|
};
|
|
469
600
|
const zh = detectLangZh(options);
|
|
@@ -475,9 +606,11 @@ export function registerSetupCli(api: any): void {
|
|
|
475
606
|
const result = await setupNonInteractive(configPath, {
|
|
476
607
|
baseUrl: baseUrl!,
|
|
477
608
|
apiKey,
|
|
478
|
-
|
|
609
|
+
peerRole,
|
|
610
|
+
peerPrefix,
|
|
479
611
|
accountId,
|
|
480
612
|
userId,
|
|
613
|
+
recallTargetTypes: normalizeSetupRecallTargetTypes(recallTargetTypes),
|
|
481
614
|
allowOffline: !!allowOffline,
|
|
482
615
|
forceSlot: !!forceSlot,
|
|
483
616
|
});
|
|
@@ -533,7 +666,9 @@ export function registerSetupCli(api: any): void {
|
|
|
533
666
|
console.log(` mode: ${existing.mode}`);
|
|
534
667
|
console.log(` baseUrl: ${existing.baseUrl ?? DEFAULT_REMOTE_URL}`);
|
|
535
668
|
if (existing.apiKey) console.log(` apiKey: ${maskKey(String(existing.apiKey))}`);
|
|
536
|
-
|
|
669
|
+
console.log(` peer_role: ${resolveExistingPeerRole(existing)}`);
|
|
670
|
+
const existingPeerPrefix = resolveExistingPeerPrefix(existing);
|
|
671
|
+
if (existingPeerPrefix) console.log(` peer_prefix: ${existingPeerPrefix}`);
|
|
537
672
|
console.log("");
|
|
538
673
|
console.log(tr(
|
|
539
674
|
zh,
|
|
@@ -651,10 +786,25 @@ async function runRemoteCheck(
|
|
|
651
786
|
|
|
652
787
|
async function setupNonInteractive(
|
|
653
788
|
configPath: string,
|
|
654
|
-
params: {
|
|
789
|
+
params: {
|
|
790
|
+
baseUrl: string;
|
|
791
|
+
apiKey?: string;
|
|
792
|
+
peerRole?: string;
|
|
793
|
+
peerPrefix?: string;
|
|
794
|
+
accountId?: string;
|
|
795
|
+
userId?: string;
|
|
796
|
+
recallTargetTypes?: string[];
|
|
797
|
+
allowOffline?: boolean;
|
|
798
|
+
forceSlot?: boolean;
|
|
799
|
+
},
|
|
655
800
|
): Promise<SetupResult> {
|
|
656
801
|
try {
|
|
657
|
-
const { baseUrl, apiKey,
|
|
802
|
+
const { baseUrl, apiKey, peerPrefix, accountId, userId, recallTargetTypes, allowOffline, forceSlot } = params;
|
|
803
|
+
const resolvedPeerRole = resolveSetupPeerRole(params.peerRole);
|
|
804
|
+
const resolvedPeerPrefix = (peerPrefix ?? "").trim();
|
|
805
|
+
if (!isValidPeerPrefixInput(resolvedPeerPrefix)) {
|
|
806
|
+
throw new Error("peer_prefix may only contain letters, digits, underscores, and hyphens, or be empty");
|
|
807
|
+
}
|
|
658
808
|
|
|
659
809
|
// Phase 1: validate connectivity and key type BEFORE writing config
|
|
660
810
|
const health = await checkServiceHealth(baseUrl, apiKey);
|
|
@@ -694,9 +844,13 @@ async function setupNonInteractive(
|
|
|
694
844
|
// Phase 2: all checks passed (or --allow-offline), write config and activate slot
|
|
695
845
|
const pluginCfg: Record<string, unknown> = { mode: "remote", baseUrl };
|
|
696
846
|
if (apiKey) pluginCfg.apiKey = apiKey;
|
|
697
|
-
|
|
847
|
+
pluginCfg.peer_role = resolvedPeerRole;
|
|
848
|
+
if (resolvedPeerPrefix) pluginCfg.peer_prefix = resolvedPeerPrefix;
|
|
698
849
|
if (accountId) pluginCfg.accountId = accountId;
|
|
699
850
|
if (userId) pluginCfg.userId = userId;
|
|
851
|
+
if (recallTargetTypes && recallTargetTypes.length > 0) {
|
|
852
|
+
pluginCfg.recallTargetTypes = recallTargetTypes;
|
|
853
|
+
}
|
|
700
854
|
|
|
701
855
|
writeConfig(configPath, pluginCfg);
|
|
702
856
|
const slot = activateContextEngineSlot(configPath, !!forceSlot);
|
|
@@ -709,9 +863,11 @@ async function setupNonInteractive(
|
|
|
709
863
|
mode: "remote",
|
|
710
864
|
baseUrl,
|
|
711
865
|
...(apiKey ? { apiKey: maskKey(apiKey) } : {}),
|
|
712
|
-
|
|
866
|
+
peer_role: resolvedPeerRole,
|
|
867
|
+
...(resolvedPeerPrefix ? { peer_prefix: resolvedPeerPrefix } : {}),
|
|
713
868
|
...(accountId ? { accountId } : {}),
|
|
714
869
|
...(userId ? { userId } : {}),
|
|
870
|
+
...(recallTargetTypes && recallTargetTypes.length > 0 ? { recallTargetTypes } : {}),
|
|
715
871
|
},
|
|
716
872
|
health,
|
|
717
873
|
keyProbe,
|
|
@@ -727,9 +883,11 @@ async function setupNonInteractive(
|
|
|
727
883
|
mode: "remote",
|
|
728
884
|
baseUrl,
|
|
729
885
|
...(apiKey ? { apiKey: maskKey(apiKey) } : {}),
|
|
730
|
-
|
|
886
|
+
peer_role: resolvedPeerRole,
|
|
887
|
+
...(resolvedPeerPrefix ? { peer_prefix: resolvedPeerPrefix } : {}),
|
|
731
888
|
...(accountId ? { accountId } : {}),
|
|
732
889
|
...(userId ? { userId } : {}),
|
|
890
|
+
...(recallTargetTypes && recallTargetTypes.length > 0 ? { recallTargetTypes } : {}),
|
|
733
891
|
},
|
|
734
892
|
health,
|
|
735
893
|
keyProbe,
|
|
@@ -754,9 +912,11 @@ function printSetupResult(zh: boolean, result: SetupResult): void {
|
|
|
754
912
|
console.log(` mode: ${result.config.mode}`);
|
|
755
913
|
console.log(` baseUrl: ${result.config.baseUrl}`);
|
|
756
914
|
if (result.config.apiKey) console.log(` apiKey: ${result.config.apiKey}`);
|
|
757
|
-
|
|
915
|
+
console.log(` peer_role: ${result.config.peer_role ?? DEFAULT_SETUP_PEER_ROLE}`);
|
|
916
|
+
if (result.config.peer_prefix) console.log(` peer_prefix: ${result.config.peer_prefix}`);
|
|
758
917
|
if (result.config.accountId) console.log(` accountId: ${result.config.accountId}`);
|
|
759
918
|
if (result.config.userId) console.log(` userId: ${result.config.userId}`);
|
|
919
|
+
if (result.config.recallTargetTypes) console.log(` recallTargetTypes: ${result.config.recallTargetTypes.join(",")}`);
|
|
760
920
|
}
|
|
761
921
|
console.log("");
|
|
762
922
|
if (result.health?.ok) {
|
|
@@ -798,14 +958,15 @@ async function getStatus(configPath: string): Promise<StatusResult> {
|
|
|
798
958
|
const health = await checkServiceHealth(baseUrl, apiKey);
|
|
799
959
|
const keyProbe = health.ok ? await probeApiKeyType(baseUrl, apiKey) : undefined;
|
|
800
960
|
|
|
801
|
-
const
|
|
961
|
+
const peerPrefix = resolveExistingPeerPrefix(existing);
|
|
802
962
|
return {
|
|
803
963
|
configured: true,
|
|
804
964
|
config: {
|
|
805
965
|
mode: String(existing.mode ?? "remote"),
|
|
806
966
|
baseUrl,
|
|
807
967
|
hasApiKey: !!existing.apiKey,
|
|
808
|
-
|
|
968
|
+
peer_role: resolveExistingPeerRole(existing),
|
|
969
|
+
...(peerPrefix ? { peer_prefix: peerPrefix } : {}),
|
|
809
970
|
hasAccountId: !!existing.accountId,
|
|
810
971
|
hasUserId: !!existing.userId,
|
|
811
972
|
},
|
|
@@ -869,7 +1030,8 @@ function printStatus(zh: boolean, result: StatusResult): void {
|
|
|
869
1030
|
console.log(` mode: ${result.config.mode}`);
|
|
870
1031
|
console.log(` baseUrl: ${result.config.baseUrl}`);
|
|
871
1032
|
console.log(` apiKey: ${result.config.hasApiKey ? "set" : "not set"}`);
|
|
872
|
-
|
|
1033
|
+
console.log(` peer_role: ${result.config.peer_role}`);
|
|
1034
|
+
if (result.config.peer_prefix) console.log(` peer_prefix: ${result.config.peer_prefix}`);
|
|
873
1035
|
console.log(` accountId: ${result.config.hasAccountId ? "set" : "not set"}`);
|
|
874
1036
|
console.log(` userId: ${result.config.hasUserId ? "set" : "not set"}`);
|
|
875
1037
|
}
|
|
@@ -904,7 +1066,8 @@ async function setupRemote(
|
|
|
904
1066
|
? String(existing.baseUrl)
|
|
905
1067
|
: DEFAULT_REMOTE_URL;
|
|
906
1068
|
const defaultApiKey = existing?.apiKey ? String(existing.apiKey) : "";
|
|
907
|
-
const
|
|
1069
|
+
const defaultPeerRole = resolveExistingPeerRole(existing);
|
|
1070
|
+
const defaultPeerPrefix = resolveExistingPeerPrefix(existing);
|
|
908
1071
|
|
|
909
1072
|
const baseUrl = await q(tr(zh, "OpenViking server URL", "OpenViking 服务器地址"), defaultUrl);
|
|
910
1073
|
const apiKey = await q(tr(zh, "API Key (optional)", "API Key(可选)"), defaultApiKey);
|
|
@@ -927,7 +1090,10 @@ async function setupRemote(
|
|
|
927
1090
|
}
|
|
928
1091
|
}
|
|
929
1092
|
|
|
930
|
-
const
|
|
1093
|
+
const peerRole = await askPeerRole(zh, q, defaultPeerRole);
|
|
1094
|
+
const peerPrefix = peerRole === "assistant"
|
|
1095
|
+
? await askPeerPrefix(zh, q, defaultPeerPrefix)
|
|
1096
|
+
: "";
|
|
931
1097
|
|
|
932
1098
|
console.log("");
|
|
933
1099
|
|
|
@@ -948,20 +1114,19 @@ async function setupRemote(
|
|
|
948
1114
|
console.log("");
|
|
949
1115
|
|
|
950
1116
|
const pluginCfg: Record<string, unknown> = {
|
|
951
|
-
...(existing
|
|
1117
|
+
...preserveCurrentConfig(existing),
|
|
952
1118
|
mode: "remote",
|
|
953
1119
|
baseUrl,
|
|
954
1120
|
};
|
|
955
1121
|
if (apiKey) pluginCfg.apiKey = apiKey;
|
|
956
1122
|
else delete pluginCfg.apiKey;
|
|
957
|
-
|
|
958
|
-
|
|
1123
|
+
pluginCfg.peer_role = peerRole;
|
|
1124
|
+
if (peerPrefix) pluginCfg.peer_prefix = peerPrefix;
|
|
1125
|
+
else delete pluginCfg.peer_prefix;
|
|
959
1126
|
if (accountId) pluginCfg.accountId = accountId;
|
|
960
1127
|
else delete pluginCfg.accountId;
|
|
961
1128
|
if (userId) pluginCfg.userId = userId;
|
|
962
1129
|
else delete pluginCfg.userId;
|
|
963
|
-
delete pluginCfg.configPath;
|
|
964
|
-
delete pluginCfg.port;
|
|
965
1130
|
|
|
966
1131
|
writeConfig(configPath, pluginCfg);
|
|
967
1132
|
|
|
@@ -971,7 +1136,8 @@ async function setupRemote(
|
|
|
971
1136
|
console.log(` ${tr(zh, "mode:", "模式:")} remote`);
|
|
972
1137
|
console.log(` baseUrl: ${baseUrl}`);
|
|
973
1138
|
if (apiKey) console.log(` apiKey: ${maskKey(apiKey)}`);
|
|
974
|
-
|
|
1139
|
+
console.log(` peer_role: ${peerRole}`);
|
|
1140
|
+
if (peerPrefix) console.log(` peer_prefix: ${peerPrefix}`);
|
|
975
1141
|
if (accountId) console.log(` accountId: ${accountId}`);
|
|
976
1142
|
if (userId) console.log(` userId: ${userId}`);
|
|
977
1143
|
printSlotResult(zh, slotResult);
|
|
@@ -985,7 +1151,8 @@ async function setupRemote(
|
|
|
985
1151
|
|
|
986
1152
|
export const __test__ = {
|
|
987
1153
|
isLegacyLocalMode,
|
|
988
|
-
|
|
1154
|
+
isValidPeerPrefixInput,
|
|
1155
|
+
normalizeSetupRecallTargetTypes,
|
|
989
1156
|
activateContextEngineSlot,
|
|
990
1157
|
isContextEngineSlotActive,
|
|
991
1158
|
getStatus,
|