dsh-web-search-enhanced 0.2.1 → 0.2.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/README.md +8 -1
- package/lib/client.cjs +98 -72
- package/lib/client.cjs.map +1 -1
- package/lib/index.js +319 -64
- package/package.json +1 -1
package/lib/index.js
CHANGED
|
@@ -14680,7 +14680,8 @@ const SEARCH = {
|
|
|
14680
14680
|
tools: {
|
|
14681
14681
|
action: "web_search_enhanced",
|
|
14682
14682
|
list: "list_web_search_providers"
|
|
14683
|
-
}
|
|
14683
|
+
},
|
|
14684
|
+
command: "setup-search"
|
|
14684
14685
|
};
|
|
14685
14686
|
//#endregion
|
|
14686
14687
|
//#region ../core/src/shared/route.ts
|
|
@@ -14952,8 +14953,6 @@ async function runOnProvider(voice, access, connectionId, request, call, unhinte
|
|
|
14952
14953
|
/** The recipient `sendsTo` names for fetch `local`; the text says `fetches from this machine`. */
|
|
14953
14954
|
const THIS_MACHINE = "this machine";
|
|
14954
14955
|
const SESSION_MODEL = "the service behind the session model";
|
|
14955
|
-
/** Operator data in the listing is one line and bounded; labels and service names share the settings label bound. */
|
|
14956
|
-
const LABEL_MAX = 200;
|
|
14957
14956
|
const HOST_MAX = 253;
|
|
14958
14957
|
/** Why the session model cannot search, in English; the execution layer's error and the listing share it. */
|
|
14959
14958
|
const UNSUPPORTED_REASON_TEXT = {
|
|
@@ -15084,7 +15083,7 @@ function renderSearchListing(voice, value) {
|
|
|
15084
15083
|
}
|
|
15085
15084
|
function renderLines(voice, value, head, parts) {
|
|
15086
15085
|
const entries = value.providers.map((entry) => {
|
|
15087
|
-
const line = [statusText(entry)];
|
|
15086
|
+
const line = [statusText$1(entry)];
|
|
15088
15087
|
if (entry.id === value.sessionProvider) line.push("selected for this session");
|
|
15089
15088
|
if (entry.use !== void 0) line.push(entry.use);
|
|
15090
15089
|
line.push(...parts.marks(entry));
|
|
@@ -15100,7 +15099,7 @@ function renderLines(voice, value, head, parts) {
|
|
|
15100
15099
|
...tail
|
|
15101
15100
|
].join("\n");
|
|
15102
15101
|
}
|
|
15103
|
-
function statusText(entry) {
|
|
15102
|
+
function statusText$1(entry) {
|
|
15104
15103
|
switch (entry.status) {
|
|
15105
15104
|
case "ready": return "ready";
|
|
15106
15105
|
case "needs-key": return "needs an API key (ask the user)";
|
|
@@ -15118,7 +15117,7 @@ function listedBase(entry) {
|
|
|
15118
15117
|
const { use, recipient } = entry.facts;
|
|
15119
15118
|
return {
|
|
15120
15119
|
id: entry.id,
|
|
15121
|
-
name: oneLine(entry.name,
|
|
15120
|
+
name: oneLine(entry.name, 200),
|
|
15122
15121
|
...use === void 0 ? {} : { use },
|
|
15123
15122
|
sendsTo: recipientText(recipient)
|
|
15124
15123
|
};
|
|
@@ -15126,8 +15125,8 @@ function listedBase(entry) {
|
|
|
15126
15125
|
function recipientText(recipient) {
|
|
15127
15126
|
switch (recipient.kind) {
|
|
15128
15127
|
case "this-machine": return THIS_MACHINE;
|
|
15129
|
-
case "session-model": return recipient.provider === void 0 ? SESSION_MODEL : `${SESSION_MODEL} (${oneLine(recipient.provider,
|
|
15130
|
-
case "service": return recipient.host === void 0 ? oneLine(recipient.service,
|
|
15128
|
+
case "session-model": return recipient.provider === void 0 ? SESSION_MODEL : `${SESSION_MODEL} (${oneLine(recipient.provider, 200)})`;
|
|
15129
|
+
case "service": return recipient.host === void 0 ? oneLine(recipient.service, 200) : oneLine(recipient.host, HOST_MAX);
|
|
15131
15130
|
}
|
|
15132
15131
|
}
|
|
15133
15132
|
function readiness(entry) {
|
|
@@ -15214,8 +15213,8 @@ function nativeAuth(ctx, ref, secrets = /* @__PURE__ */ new Set()) {
|
|
|
15214
15213
|
};
|
|
15215
15214
|
}
|
|
15216
15215
|
/** Account readiness uses the next selected model, while request authentication uses its frozen route. */
|
|
15217
|
-
async function credentialReadiness(ctx,
|
|
15218
|
-
const account = options.endpoint !== void 0 &&
|
|
15216
|
+
async function credentialReadiness(ctx, model, options) {
|
|
15217
|
+
const account = options.endpoint !== void 0 && model?.provider === "deepseek-account" ? ctx.get("deepseekAccount") : void 0;
|
|
15219
15218
|
if (account !== void 0 && await account.resolveToken(options.endpoint) !== void 0) return {
|
|
15220
15219
|
access: "account",
|
|
15221
15220
|
status: "ready"
|
|
@@ -15311,10 +15310,32 @@ var Snapshots = class {
|
|
|
15311
15310
|
}
|
|
15312
15311
|
};
|
|
15313
15312
|
//#endregion
|
|
15313
|
+
//#region ../core/src/host/session-origin.ts
|
|
15314
|
+
function sessionOrigin(header) {
|
|
15315
|
+
const { parentSession: parent, isSeeded: seeded, origin } = header;
|
|
15316
|
+
if (origin === "subagent") return {
|
|
15317
|
+
kind: "subagent",
|
|
15318
|
+
parent,
|
|
15319
|
+
seeded
|
|
15320
|
+
};
|
|
15321
|
+
return parent === void 0 ? {
|
|
15322
|
+
kind: "top-level",
|
|
15323
|
+
seeded
|
|
15324
|
+
} : {
|
|
15325
|
+
kind: "fork",
|
|
15326
|
+
parent,
|
|
15327
|
+
seeded
|
|
15328
|
+
};
|
|
15329
|
+
}
|
|
15330
|
+
function parentOf(origin) {
|
|
15331
|
+
return origin.kind === "top-level" ? void 0 : origin.parent;
|
|
15332
|
+
}
|
|
15333
|
+
//#endregion
|
|
15314
15334
|
//#region ../core/src/host/provider-lists.ts
|
|
15315
15335
|
/** Live setup/created events do not make a new conversation a restored one. */
|
|
15316
15336
|
function isNewConversation(session) {
|
|
15317
|
-
|
|
15337
|
+
const origin = sessionOrigin(session.header);
|
|
15338
|
+
return parentOf(origin) === void 0 && !origin.seeded && session.firstLiveSeq === 0 && session.firstLifecycleSeq === 0;
|
|
15318
15339
|
}
|
|
15319
15340
|
/** Immutable conversation authorization, sharing the selection queue and storage lifetime. */
|
|
15320
15341
|
var ProviderLists = class {
|
|
@@ -15333,7 +15354,7 @@ var ProviderLists = class {
|
|
|
15333
15354
|
const table = (await this.storage.domain()).table("provider_lists");
|
|
15334
15355
|
const stored = table.get(agent.session.id);
|
|
15335
15356
|
if (stored !== void 0) return this.nonempty(stored);
|
|
15336
|
-
const parent = agent.session.header
|
|
15357
|
+
const parent = parentOf(sessionOrigin(agent.session.header));
|
|
15337
15358
|
let ids;
|
|
15338
15359
|
if (parent !== void 0) {
|
|
15339
15360
|
await this.storage.settled(parent);
|
|
@@ -15356,6 +15377,14 @@ function isSelectable(connection) {
|
|
|
15356
15377
|
}
|
|
15357
15378
|
//#endregion
|
|
15358
15379
|
//#region ../core/src/host/sessions.ts
|
|
15380
|
+
function liveSession(agent) {
|
|
15381
|
+
return {
|
|
15382
|
+
kind: "live",
|
|
15383
|
+
id: agent.session.id,
|
|
15384
|
+
header: agent.session.header,
|
|
15385
|
+
agent
|
|
15386
|
+
};
|
|
15387
|
+
}
|
|
15359
15388
|
var SelectionConflict = class extends Error {
|
|
15360
15389
|
constructor() {
|
|
15361
15390
|
super("the selection changed since it was read");
|
|
@@ -15376,20 +15405,20 @@ var Sessions = class {
|
|
|
15376
15405
|
this.restriction = restriction;
|
|
15377
15406
|
this.describe = describe;
|
|
15378
15407
|
}
|
|
15379
|
-
current(
|
|
15380
|
-
return this.exclusive(
|
|
15408
|
+
current(target) {
|
|
15409
|
+
return this.exclusive(target.id, async () => this.read(target, await this.table()));
|
|
15381
15410
|
}
|
|
15382
15411
|
/** Resolve visibility without creating records or materializing inherited/default options. */
|
|
15383
|
-
peek(
|
|
15384
|
-
return this.exclusive(
|
|
15412
|
+
peek(target) {
|
|
15413
|
+
return this.exclusive(target.id, async () => this.read(target, await this.table(), false));
|
|
15385
15414
|
}
|
|
15386
|
-
change(
|
|
15387
|
-
return this.exclusive(
|
|
15415
|
+
change(target, change, expectedRevision) {
|
|
15416
|
+
return this.exclusive(target.id, async () => {
|
|
15388
15417
|
const table = await this.table();
|
|
15389
|
-
await this.read(
|
|
15418
|
+
await this.read(target, table);
|
|
15390
15419
|
const { connectionId, ...options } = change;
|
|
15391
15420
|
const record = this.storage.optionsCodec.toRecord(options);
|
|
15392
|
-
const updated = await table.update(
|
|
15421
|
+
const updated = await table.update(target.id, (current) => {
|
|
15393
15422
|
if (current.revision !== expectedRevision) throw new SelectionConflict();
|
|
15394
15423
|
return {
|
|
15395
15424
|
...current,
|
|
@@ -15398,9 +15427,10 @@ var Sessions = class {
|
|
|
15398
15427
|
revision: current.revision + 1
|
|
15399
15428
|
};
|
|
15400
15429
|
});
|
|
15401
|
-
this.
|
|
15402
|
-
if (
|
|
15403
|
-
|
|
15430
|
+
const agent = this.ctx.get("agents")?.get(target.id);
|
|
15431
|
+
if (agent !== void 0) this.restriction.sync(agent, updated.connectionId);
|
|
15432
|
+
if (connectionId !== void 0 && sessionOrigin(target.header).kind !== "subagent") {
|
|
15433
|
+
const model = this.model(target);
|
|
15404
15434
|
if (model !== void 0) {
|
|
15405
15435
|
const memory = await this.pairings.set(model, updated.connectionId).then(() => ({ kind: "stored" }), (error) => ({
|
|
15406
15436
|
kind: "failed",
|
|
@@ -15415,29 +15445,33 @@ var Sessions = class {
|
|
|
15415
15445
|
};
|
|
15416
15446
|
});
|
|
15417
15447
|
}
|
|
15418
|
-
connections(
|
|
15419
|
-
return this.describe(this.settings(),
|
|
15448
|
+
connections(target) {
|
|
15449
|
+
return this.describe(this.settings(), this.model(target));
|
|
15420
15450
|
}
|
|
15421
15451
|
selectable(connectionId) {
|
|
15422
15452
|
return isSelectable(this.settings().connections.get(connectionId));
|
|
15423
15453
|
}
|
|
15454
|
+
model(target) {
|
|
15455
|
+
return target.kind === "live" ? nextModel(this.ctx, target.agent) : void 0;
|
|
15456
|
+
}
|
|
15424
15457
|
async table() {
|
|
15425
15458
|
return (await this.storage.domain()).table("selections");
|
|
15426
15459
|
}
|
|
15427
15460
|
exclusive(id, work) {
|
|
15428
15461
|
return this.storage.exclusive(id, work);
|
|
15429
15462
|
}
|
|
15430
|
-
async read(
|
|
15463
|
+
async read(target, table, persist = true) {
|
|
15431
15464
|
const settings = this.settings();
|
|
15432
15465
|
const codec = this.storage.optionsCodec;
|
|
15433
|
-
const id =
|
|
15466
|
+
const id = target.id;
|
|
15434
15467
|
let stored = table.get(id);
|
|
15435
|
-
const
|
|
15436
|
-
const
|
|
15468
|
+
const origin = sessionOrigin(target.header);
|
|
15469
|
+
const parentSession = parentOf(origin);
|
|
15470
|
+
const seeded = parentSession !== void 0 && origin.seeded;
|
|
15437
15471
|
let inherited = stored !== void 0 && seeded && (stored.inherited ?? table.get(parentSession) !== void 0);
|
|
15438
15472
|
if (stored === void 0 && seeded) {
|
|
15439
15473
|
const parentAgent = this.ctx.get("agents")?.get(parentSession);
|
|
15440
|
-
if (parentAgent !== void 0 && persist) await this.current(parentAgent);
|
|
15474
|
+
if (parentAgent !== void 0 && persist) await this.current(liveSession(parentAgent));
|
|
15441
15475
|
else await this.storage.settled(parentSession);
|
|
15442
15476
|
const parent = table.get(parentSession);
|
|
15443
15477
|
if (parent !== void 0) {
|
|
@@ -15461,7 +15495,7 @@ var Sessions = class {
|
|
|
15461
15495
|
source: next.revision > 0 ? "session" : "inherited"
|
|
15462
15496
|
};
|
|
15463
15497
|
}
|
|
15464
|
-
const fallback = await this.defaultFor(
|
|
15498
|
+
const fallback = await this.defaultFor(target, settings);
|
|
15465
15499
|
const options = stored === void 0 ? codec.initial(settings) : codec.fromRecord(stored, settings);
|
|
15466
15500
|
const next = {
|
|
15467
15501
|
...codec.toRecord(options),
|
|
@@ -15475,8 +15509,8 @@ var Sessions = class {
|
|
|
15475
15509
|
source: fallback.source
|
|
15476
15510
|
};
|
|
15477
15511
|
}
|
|
15478
|
-
async defaultFor(
|
|
15479
|
-
const model =
|
|
15512
|
+
async defaultFor(target, settings) {
|
|
15513
|
+
const model = this.model(target);
|
|
15480
15514
|
const paired = model === void 0 ? void 0 : await this.pairings.get(model);
|
|
15481
15515
|
if (paired === null) return {
|
|
15482
15516
|
connectionId: null,
|
|
@@ -15503,6 +15537,24 @@ function sameRecord(left, right) {
|
|
|
15503
15537
|
return left !== void 0 && JSON.stringify(left) === JSON.stringify(right);
|
|
15504
15538
|
}
|
|
15505
15539
|
//#endregion
|
|
15540
|
+
//#region ../core/src/host/selection-write.ts
|
|
15541
|
+
/** The shared eligibility check and revisioned write for commands and Remote set. */
|
|
15542
|
+
async function writeSelection(sessions, target, change, expectedRevision) {
|
|
15543
|
+
if (typeof change.connectionId === "string" && !sessions.selectable(change.connectionId)) return {
|
|
15544
|
+
kind: "unavailable",
|
|
15545
|
+
connectionId: change.connectionId
|
|
15546
|
+
};
|
|
15547
|
+
try {
|
|
15548
|
+
return {
|
|
15549
|
+
kind: "written",
|
|
15550
|
+
current: await sessions.change(target, change, expectedRevision)
|
|
15551
|
+
};
|
|
15552
|
+
} catch (error) {
|
|
15553
|
+
if (error instanceof SelectionConflict) return { kind: "conflict" };
|
|
15554
|
+
throw error;
|
|
15555
|
+
}
|
|
15556
|
+
}
|
|
15557
|
+
//#endregion
|
|
15506
15558
|
//#region ../core/src/host/remote.ts
|
|
15507
15559
|
var __runInitializers = function(thisArg, initializers, value) {
|
|
15508
15560
|
var useValue = arguments.length > 2;
|
|
@@ -15650,27 +15702,22 @@ function createConnectionsService(ctx, spec) {
|
|
|
15650
15702
|
async get(request) {
|
|
15651
15703
|
return boundary("get", async () => {
|
|
15652
15704
|
const { sessionId } = parse(selectionRequest, request);
|
|
15653
|
-
const
|
|
15654
|
-
return this.view(
|
|
15705
|
+
const target = await this.target(sessionId);
|
|
15706
|
+
return this.view(target, await spec.sessions.current(target));
|
|
15655
15707
|
});
|
|
15656
15708
|
}
|
|
15657
15709
|
async set(request) {
|
|
15658
15710
|
return boundary("set", async () => {
|
|
15659
15711
|
const { sessionId, connectionId, options, expectedRevision } = parse(spec.contract.selectionChange, request);
|
|
15660
|
-
const
|
|
15661
|
-
|
|
15662
|
-
|
|
15663
|
-
|
|
15664
|
-
|
|
15665
|
-
|
|
15666
|
-
|
|
15667
|
-
|
|
15668
|
-
|
|
15669
|
-
} catch (error) {
|
|
15670
|
-
if (error instanceof SelectionConflict) throw new RemoteError(spec.namespace + "/conflict", "the selection changed elsewhere; re-read it and retry", {});
|
|
15671
|
-
throw error;
|
|
15672
|
-
}
|
|
15673
|
-
return this.view(agent, current);
|
|
15712
|
+
const target = await this.target(sessionId);
|
|
15713
|
+
const change = {
|
|
15714
|
+
...options,
|
|
15715
|
+
...connectionId === void 0 ? {} : { connectionId }
|
|
15716
|
+
};
|
|
15717
|
+
const result = await writeSelection(spec.sessions, target, change, expectedRevision);
|
|
15718
|
+
if (result.kind === "unavailable") throw new RemoteError(spec.namespace + "/unavailable", "the connection is missing, disabled or unsupported", { connectionId: result.connectionId });
|
|
15719
|
+
if (result.kind === "conflict") throw new RemoteError(spec.namespace + "/conflict", "the selection changed elsewhere; re-read it and retry", {});
|
|
15720
|
+
return this.view(target, result.current);
|
|
15674
15721
|
});
|
|
15675
15722
|
}
|
|
15676
15723
|
async provider(request) {
|
|
@@ -15692,15 +15739,27 @@ function createConnectionsService(ctx, spec) {
|
|
|
15692
15739
|
return { pairings: await spec.pairings.list() };
|
|
15693
15740
|
});
|
|
15694
15741
|
}
|
|
15695
|
-
async
|
|
15696
|
-
const
|
|
15742
|
+
async target(sessionId) {
|
|
15743
|
+
const id = sessionId;
|
|
15744
|
+
const agent = this.ctx.agents.get(id);
|
|
15745
|
+
if (agent !== void 0) return liveSession(agent);
|
|
15746
|
+
const persistence = this.ctx.get("sessionPersistence");
|
|
15747
|
+
if (persistence !== void 0) {
|
|
15748
|
+
const stored = await persistence.stat(id);
|
|
15749
|
+
if (stored !== void 0 && sessionOrigin(stored.header).kind === "subagent") return {
|
|
15750
|
+
kind: "cold",
|
|
15751
|
+
id,
|
|
15752
|
+
header: stored.header
|
|
15753
|
+
};
|
|
15754
|
+
}
|
|
15755
|
+
const found = await this.ctx.sessionController.resolveAgent(id);
|
|
15697
15756
|
if ("error" in found) throw found.error;
|
|
15698
|
-
return found.agent;
|
|
15757
|
+
return liveSession(found.agent);
|
|
15699
15758
|
}
|
|
15700
|
-
async view(
|
|
15759
|
+
async view(target, current) {
|
|
15701
15760
|
return {
|
|
15702
15761
|
...current,
|
|
15703
|
-
connections: await spec.sessions.connections(
|
|
15762
|
+
connections: await spec.sessions.connections(target)
|
|
15704
15763
|
};
|
|
15705
15764
|
}
|
|
15706
15765
|
};
|
|
@@ -16014,7 +16073,7 @@ function explicitAccess(ctx, capability, runtime, errors, unavailable) {
|
|
|
16014
16073
|
const described = await errors.abortable(capability.describe({
|
|
16015
16074
|
...prepared.settings,
|
|
16016
16075
|
connections
|
|
16017
|
-
}, call.agent), call.signal);
|
|
16076
|
+
}, nextModel(ctx, call.agent)), call.signal);
|
|
16018
16077
|
errors.throwIfAborted(call.signal);
|
|
16019
16078
|
return new Map(described.map((view) => [view.id, view]));
|
|
16020
16079
|
} catch {
|
|
@@ -16211,6 +16270,188 @@ var SessionStorage = class {
|
|
|
16211
16270
|
}
|
|
16212
16271
|
};
|
|
16213
16272
|
//#endregion
|
|
16273
|
+
//#region ../core/src/host/command.ts
|
|
16274
|
+
var SelectionOperationError = class extends Error {};
|
|
16275
|
+
const SOURCES = {
|
|
16276
|
+
session: "chosen in this session",
|
|
16277
|
+
inherited: "copied from the parent session",
|
|
16278
|
+
model: "remembered for this model",
|
|
16279
|
+
default: "the default connection"
|
|
16280
|
+
};
|
|
16281
|
+
function registerCommand(ctx, capability, sessions) {
|
|
16282
|
+
const { command, providerId, rowId } = capability.identity;
|
|
16283
|
+
const noun = capability.tool === "web_search" ? "web search" : "web fetch";
|
|
16284
|
+
const capital = capability.tool === "web_search" ? "Web search" : "Web fetch";
|
|
16285
|
+
const options = capability.commandOptions;
|
|
16286
|
+
const hint = options === void 0 ? "[off | <connection id>]" : "[off | <connection id> | freshness auto|fresh|realtime]";
|
|
16287
|
+
const failure = "The " + noun + " selection could not be read or saved; retry, or check the Host logs.";
|
|
16288
|
+
const error = (text) => ({
|
|
16289
|
+
kind: "error",
|
|
16290
|
+
text
|
|
16291
|
+
});
|
|
16292
|
+
const selectionOperation = async (work) => {
|
|
16293
|
+
try {
|
|
16294
|
+
return await work();
|
|
16295
|
+
} catch (cause) {
|
|
16296
|
+
if (cause instanceof InvalidSettingsError) throw cause;
|
|
16297
|
+
ctx.logger.warn("%s command selection read or write failed: %s", rowId, cause);
|
|
16298
|
+
throw new SelectionOperationError("selection read or write failed");
|
|
16299
|
+
}
|
|
16300
|
+
};
|
|
16301
|
+
const route = () => routeFacts(ctx, capability.field, providerId);
|
|
16302
|
+
const routing = () => routingText(route(), capability.tool, providerId);
|
|
16303
|
+
const unavailable = (id) => error(id + " is missing or turned off in the settings. Run /" + command + " to list the connections.");
|
|
16304
|
+
const success = (text) => ({
|
|
16305
|
+
kind: "success",
|
|
16306
|
+
text: text + (route().kind === "this" ? "" : "\n" + routing())
|
|
16307
|
+
});
|
|
16308
|
+
const run = async (invocation) => {
|
|
16309
|
+
const raw = invocation.rawInput.trim();
|
|
16310
|
+
const args = raw === "" ? [] : raw.split(/\s+/u);
|
|
16311
|
+
const usage = () => error("Unknown argument \"" + oneLine(raw, 64) + "\". Usage: /" + command + " " + hint);
|
|
16312
|
+
const keyword = args.length === 0 ? "" : args[0].toLowerCase();
|
|
16313
|
+
const freshnessValue = args.length === 2 ? args[1].toLowerCase() : "";
|
|
16314
|
+
const freshness = options !== void 0 && args.length === 2 && keyword === "freshness";
|
|
16315
|
+
if (args.length > 0 && !freshness && !(args.length === 1 && (keyword === "off" || isConnectionId(args[0])))) return usage();
|
|
16316
|
+
if (freshness && !FRESHNESS.some((value) => value === freshnessValue)) return error("Unknown freshness \"" + oneLine(args[1], 64) + "\". Use auto, fresh or realtime.");
|
|
16317
|
+
const target = liveSession(invocation.agent);
|
|
16318
|
+
const settings = capability.settings();
|
|
16319
|
+
const current = await selectionOperation(() => sessions.current(target));
|
|
16320
|
+
if (args.length === 0) {
|
|
16321
|
+
const views = await sessions.connections(target);
|
|
16322
|
+
const id = current.selection.connectionId;
|
|
16323
|
+
const selected = id === null ? void 0 : views.find((view) => view.id === id);
|
|
16324
|
+
let summary = id === null ? "Off" : selected === void 0 || !sessions.selectable(id) ? id : oneLine(selected.label, 200) + " (" + id + ")";
|
|
16325
|
+
summary += " · " + SOURCES[current.source];
|
|
16326
|
+
if (id !== null && !sessions.selectable(id)) summary += " · missing or turned off in the settings; " + capability.tool + " fails until another connection is chosen";
|
|
16327
|
+
if (options !== void 0) summary += " · freshness: " + options.freshness(current.selection.options);
|
|
16328
|
+
const entries = [];
|
|
16329
|
+
for (const view of views) {
|
|
16330
|
+
const connection = settings.connections.get(view.id);
|
|
16331
|
+
if (!isSelectable(connection)) continue;
|
|
16332
|
+
const name = oneLine(view.label, 200);
|
|
16333
|
+
const parts = [statusText(view)];
|
|
16334
|
+
if (view.id === id) parts.push("current");
|
|
16335
|
+
if (view.freshness === true) parts.push("applies freshness");
|
|
16336
|
+
const recipient = recipientText(capability.enhanced.listing(connection, {
|
|
16337
|
+
agent: invocation.agent,
|
|
16338
|
+
signal: invocation.signal
|
|
16339
|
+
}).recipient);
|
|
16340
|
+
if (recipient === "this machine") parts.push("fetches from this machine");
|
|
16341
|
+
else if (recipient !== name) parts.push((capability.tool === "web_search" ? "queries" : "URLs") + " go to " + recipient);
|
|
16342
|
+
entries.push("- " + view.id + " — " + name + " · " + parts.join(" · "));
|
|
16343
|
+
}
|
|
16344
|
+
if (entries.length === 0) entries.push("- (none; turn connections on in the row settings)");
|
|
16345
|
+
const tail = "Turn off: /" + command + " off" + (options === void 0 ? "" : " · Freshness: /" + command + " freshness auto|fresh|realtime (connections marked \"applies freshness\")");
|
|
16346
|
+
return {
|
|
16347
|
+
kind: "success",
|
|
16348
|
+
text: [
|
|
16349
|
+
summary,
|
|
16350
|
+
routing(),
|
|
16351
|
+
"Connections (/" + command + " <id> chooses one):",
|
|
16352
|
+
...entries,
|
|
16353
|
+
tail
|
|
16354
|
+
].join("\n")
|
|
16355
|
+
};
|
|
16356
|
+
}
|
|
16357
|
+
let change;
|
|
16358
|
+
let message;
|
|
16359
|
+
if (freshness && options !== void 0) {
|
|
16360
|
+
const selected = (await sessions.connections(target)).find((view) => view.id === current.selection.connectionId);
|
|
16361
|
+
if (selected === void 0 || selected.freshness !== true || !sessions.selectable(selected.id)) return error("The current connection does not apply freshness. Choose one marked \"applies freshness\" first.");
|
|
16362
|
+
const value = FRESHNESS.find((mode) => mode === freshnessValue);
|
|
16363
|
+
change = options.changeFreshness(value);
|
|
16364
|
+
message = "Freshness is " + value + " from the next model request.";
|
|
16365
|
+
} else if (keyword === "off") {
|
|
16366
|
+
change = { connectionId: null };
|
|
16367
|
+
message = capital + " is off for this session from the next model request.";
|
|
16368
|
+
} else {
|
|
16369
|
+
const id = args[0];
|
|
16370
|
+
if (!sessions.selectable(id)) return unavailable(id);
|
|
16371
|
+
const selected = (await sessions.connections(target)).find((view) => view.id === id);
|
|
16372
|
+
change = { connectionId: id };
|
|
16373
|
+
message = "Now using " + oneLine(selected.label, 200) + " (" + id + ") for " + noun + " from the next model request.";
|
|
16374
|
+
}
|
|
16375
|
+
const result = await selectionOperation(() => writeSelection(sessions, target, change, current.selection.revision));
|
|
16376
|
+
if (result.kind === "unavailable") return unavailable(result.connectionId);
|
|
16377
|
+
if (result.kind === "conflict") return error("The selection changed while this command ran. Run /" + command + " to see it, then try again.");
|
|
16378
|
+
return success(message);
|
|
16379
|
+
};
|
|
16380
|
+
ctx.effect(() => ctx.commands.register({
|
|
16381
|
+
name: command,
|
|
16382
|
+
description: "Show or change this session's " + noun + " connection",
|
|
16383
|
+
input: { hint },
|
|
16384
|
+
async handler(invocation) {
|
|
16385
|
+
try {
|
|
16386
|
+
return await run(invocation);
|
|
16387
|
+
} catch (cause) {
|
|
16388
|
+
if (cause instanceof SelectionOperationError) return error(failure);
|
|
16389
|
+
ctx.logger.warn("%s command failed: %s", rowId, cause);
|
|
16390
|
+
if (cause instanceof InvalidSettingsError) return error("The " + noun + " settings are invalid; fix them in the Enhanced " + noun + " row settings.");
|
|
16391
|
+
throw new Error("The " + noun + " command failed; retry, or check the Host logs.");
|
|
16392
|
+
}
|
|
16393
|
+
}
|
|
16394
|
+
}));
|
|
16395
|
+
}
|
|
16396
|
+
function routingText(route, tool, providerId) {
|
|
16397
|
+
switch (route.kind) {
|
|
16398
|
+
case "this": return "Routing: " + tool + " goes to this plugin.";
|
|
16399
|
+
case "other": return "Routing: " + tool + " goes to " + oneLine(route.provider, 200) + ", so this selection has no effect until the web row routes it to " + providerId + ".";
|
|
16400
|
+
case "auto": return "Routing: the web row pins no " + tool + " provider, so this selection has no effect until it routes " + tool + " to " + providerId + ".";
|
|
16401
|
+
case "unknown": return "Routing: the web row could not be read, so this selection may have no effect.";
|
|
16402
|
+
}
|
|
16403
|
+
}
|
|
16404
|
+
function statusText(view) {
|
|
16405
|
+
switch (view.status) {
|
|
16406
|
+
case "ready": return "ready";
|
|
16407
|
+
case "needs-credential": return view.access === "account" ? "needs DeepSeek sign-in" : "needs an API key";
|
|
16408
|
+
case "unsupported": return "unavailable: " + UNSUPPORTED_REASON_TEXT[view.reason];
|
|
16409
|
+
case "disabled": return "missing or turned off in the settings";
|
|
16410
|
+
}
|
|
16411
|
+
}
|
|
16412
|
+
//#endregion
|
|
16413
|
+
//#region ../core/src/host/terminal.ts
|
|
16414
|
+
function registerTerminal(ctx, root, noun, settings, freshness) {
|
|
16415
|
+
ctx.effect(() => ctx.tuiCommandTrees.register({
|
|
16416
|
+
root,
|
|
16417
|
+
children(path) {
|
|
16418
|
+
if (path[0] !== root) return [];
|
|
16419
|
+
if (freshness && path.length === 2 && path[1] === "freshness") return [
|
|
16420
|
+
{
|
|
16421
|
+
name: "auto",
|
|
16422
|
+
description: "Auto"
|
|
16423
|
+
},
|
|
16424
|
+
{
|
|
16425
|
+
name: "fresh",
|
|
16426
|
+
description: "Within 24 hours"
|
|
16427
|
+
},
|
|
16428
|
+
{
|
|
16429
|
+
name: "realtime",
|
|
16430
|
+
description: "Live"
|
|
16431
|
+
}
|
|
16432
|
+
];
|
|
16433
|
+
if (path.length !== 1) return [];
|
|
16434
|
+
const nodes = [{
|
|
16435
|
+
name: "off",
|
|
16436
|
+
description: "Turn " + noun + " off for this session"
|
|
16437
|
+
}];
|
|
16438
|
+
try {
|
|
16439
|
+
for (const connection of settings().connections.values()) if (isSelectable(connection)) nodes.push({
|
|
16440
|
+
name: connection.id,
|
|
16441
|
+
description: oneLine(connection.label, 200)
|
|
16442
|
+
});
|
|
16443
|
+
} catch (error) {
|
|
16444
|
+
if (!(error instanceof InvalidSettingsError)) throw error;
|
|
16445
|
+
}
|
|
16446
|
+
if (freshness) nodes.push({
|
|
16447
|
+
name: "freshness",
|
|
16448
|
+
description: "Content freshness, for connections that apply it"
|
|
16449
|
+
});
|
|
16450
|
+
return nodes;
|
|
16451
|
+
}
|
|
16452
|
+
}));
|
|
16453
|
+
}
|
|
16454
|
+
//#endregion
|
|
16214
16455
|
//#region ../core/src/host/runtime.ts
|
|
16215
16456
|
/** Install the sole Seat, session lifecycle, route-guarded restrictions and Remote service. */
|
|
16216
16457
|
function installCapability(ctx, capability) {
|
|
@@ -16231,7 +16472,7 @@ function installCapability(ctx, capability) {
|
|
|
16231
16472
|
const restriction = new ToolRestriction(ctx, {
|
|
16232
16473
|
tool: capability.tool,
|
|
16233
16474
|
routed: () => routeFacts(ctx, capability.field, capability.identity.providerId).kind === "this",
|
|
16234
|
-
selection: async (agent) => (await sessions.peek(agent)).selection.connectionId,
|
|
16475
|
+
selection: async (agent) => (await sessions.peek(liveSession(agent))).selection.connectionId,
|
|
16235
16476
|
enhanced: {
|
|
16236
16477
|
rowId: capability.identity.rowId,
|
|
16237
16478
|
names: capability.enhanced.names,
|
|
@@ -16247,11 +16488,11 @@ function installCapability(ctx, capability) {
|
|
|
16247
16488
|
providers: (agent) => lists.read(agent)
|
|
16248
16489
|
}
|
|
16249
16490
|
});
|
|
16250
|
-
const sessions = new Sessions(ctx, () => capability.settings(), storage, pairings, restriction, (settings,
|
|
16491
|
+
const sessions = new Sessions(ctx, () => capability.settings(), storage, pairings, restriction, (settings, model) => capability.describe(settings, model));
|
|
16251
16492
|
const capture = async (agent, signal) => {
|
|
16252
16493
|
const operation = restriction.begin(agent);
|
|
16253
16494
|
try {
|
|
16254
|
-
const read = sessions.current(agent);
|
|
16495
|
+
const read = sessions.current(liveSession(agent));
|
|
16255
16496
|
const { selection } = signal === void 0 ? await read : await errors.abortable(read, signal);
|
|
16256
16497
|
if (!restriction.active) return {
|
|
16257
16498
|
kind: "failed",
|
|
@@ -16298,7 +16539,17 @@ function installCapability(ctx, capability) {
|
|
|
16298
16539
|
snapshots.forget(agent);
|
|
16299
16540
|
restriction.forget(agent);
|
|
16300
16541
|
});
|
|
16301
|
-
ctx.inject(["
|
|
16542
|
+
ctx.inject(["commands"], (scope) => {
|
|
16543
|
+
registerCommand(scope, capability, sessions);
|
|
16544
|
+
});
|
|
16545
|
+
ctx.inject(["tuiCommandTrees"], (scope) => {
|
|
16546
|
+
registerTerminal(scope, capability.identity.command, "web " + kind, () => capability.settings(), capability.commandOptions !== void 0);
|
|
16547
|
+
});
|
|
16548
|
+
ctx.inject([
|
|
16549
|
+
"sessionController",
|
|
16550
|
+
"typert",
|
|
16551
|
+
"agents"
|
|
16552
|
+
], (scope) => {
|
|
16302
16553
|
createConnectionsService(scope, {
|
|
16303
16554
|
namespace: capability.remoteNamespace,
|
|
16304
16555
|
contract: capability.contract,
|
|
@@ -17180,7 +17431,7 @@ const { withDeadline, readJson, requestJson, invalidResponse } = transport;
|
|
|
17180
17431
|
const mcp = createMcpClient(transport, searchErrors, {
|
|
17181
17432
|
clientInfo: {
|
|
17182
17433
|
name: SEARCH.packageName,
|
|
17183
|
-
version: "0.2.
|
|
17434
|
+
version: "0.2.2"
|
|
17184
17435
|
},
|
|
17185
17436
|
messages: {
|
|
17186
17437
|
toolFailed: (label, detail) => label + " could not complete the search; retry later or choose another search connection" + upstreamSuffix(label, detail),
|
|
@@ -18258,14 +18509,14 @@ function searchEnhanced(ctx) {
|
|
|
18258
18509
|
}
|
|
18259
18510
|
//#endregion
|
|
18260
18511
|
//#region src/host/connections.ts
|
|
18261
|
-
async function describeConnections(ctx, settings,
|
|
18512
|
+
async function describeConnections(ctx, settings, model) {
|
|
18262
18513
|
return Promise.all([...settings.connections.values()].map(async (connection) => {
|
|
18263
18514
|
const base = baseOf(connection);
|
|
18264
18515
|
if (connection.kind === "model") {
|
|
18265
18516
|
const target = connection.route.kind === "fixed" ? {
|
|
18266
18517
|
kind: "route",
|
|
18267
18518
|
route: fixedRoute(connection.route)
|
|
18268
|
-
} : sessionRoute(ctx,
|
|
18519
|
+
} : sessionRoute(ctx, model);
|
|
18269
18520
|
const access = target.kind === "route" ? target.route.auth.kind : "api-key";
|
|
18270
18521
|
if (connection.disabled) return {
|
|
18271
18522
|
...base,
|
|
@@ -18298,7 +18549,7 @@ async function describeConnections(ctx, settings, agent) {
|
|
|
18298
18549
|
const endpoint = connection.kind === "native" ? typeof connection.options.baseURL === "string" ? connection.options.baseURL : CATALOG[connection.native].endpoint : void 0;
|
|
18299
18550
|
return {
|
|
18300
18551
|
...base,
|
|
18301
|
-
...await credentialReadiness(ctx,
|
|
18552
|
+
...await credentialReadiness(ctx, model, {
|
|
18302
18553
|
endpoint,
|
|
18303
18554
|
credentialRef: connection.credentialRef
|
|
18304
18555
|
})
|
|
@@ -18343,7 +18594,11 @@ function searchCapability(ctx, settings) {
|
|
|
18343
18594
|
contract,
|
|
18344
18595
|
optionsCodec,
|
|
18345
18596
|
settings,
|
|
18346
|
-
|
|
18597
|
+
commandOptions: {
|
|
18598
|
+
freshness: (options) => options.freshness,
|
|
18599
|
+
changeFreshness: (freshness) => ({ freshness })
|
|
18600
|
+
},
|
|
18601
|
+
describe: (current, model) => describeConnections(ctx, current, model),
|
|
18347
18602
|
target: (connection, options, call) => {
|
|
18348
18603
|
switch (connection.kind) {
|
|
18349
18604
|
case "adapter": return {
|
package/package.json
CHANGED