@ycodium-ai/agent-dsh 0.2.2690 → 0.2.2694
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 +7 -0
- package/dist/index.js +209 -29
- package/locales/en.json +5 -0
- package/locales/zh-CN.json +5 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -22,6 +22,13 @@ Facts:
|
|
|
22
22
|
disk format is unchanged.
|
|
23
23
|
- Credentials come from the environment (`DEEPSEEK_API_KEY`); there is no login
|
|
24
24
|
command and no device-code flow, so `ExecutorInstance.signIn` is not implemented.
|
|
25
|
+
- Usage (ADR-0034): DSH runs on a DeepSeek API key, so the quota is the account's remaining
|
|
26
|
+
balance, not windows. `ExecutorInstance.usage.readQuota` calls `GET https://api.deepseek.com/user/balance`
|
|
27
|
+
(through `host.fetch`) and maps each `balance_infos` entry to a money balance in the currency the reply
|
|
28
|
+
names. The key is found the way DSH finds it: instance environment table / process environment, then
|
|
29
|
+
`$DSH_HOME/.credentials.yaml` `refs.DEEPSEEK_API_KEY`, then `$DSH_HOME/.env`. A `DEEPSEEK_BASE_URL` that is
|
|
30
|
+
not `api.deepseek.com` reports `customEndpoint` and sends nothing. No `readTokenUsage`: DSH's ACP reply
|
|
31
|
+
carries no usage and its session log (`session.v4.jsonl.zstd`) has no per-event timestamps.
|
|
25
32
|
- Manifest permission is `{ kind: "executor" }`.
|
|
26
33
|
- Session model switching is `unsupported` on the card: the plugin does not switch
|
|
27
34
|
models inside a running session.
|
package/dist/index.js
CHANGED
|
@@ -24903,6 +24903,13 @@ function parseSessionModeState(sessionResponse) {
|
|
|
24903
24903
|
availableModes
|
|
24904
24904
|
};
|
|
24905
24905
|
}
|
|
24906
|
+
function acpCommandsToSlashCommands(commands) {
|
|
24907
|
+
return commands.map((command) => ({
|
|
24908
|
+
name: command.name,
|
|
24909
|
+
...command.description === void 0 ? {} : { description: command.description },
|
|
24910
|
+
...command.inputHint === void 0 ? {} : { input: { hint: command.inputHint } }
|
|
24911
|
+
}));
|
|
24912
|
+
}
|
|
24906
24913
|
function parseAvailableCommandsUpdate(params) {
|
|
24907
24914
|
const update = params.update;
|
|
24908
24915
|
if (update["sessionUpdate"] !== "available_commands_update") {
|
|
@@ -25354,24 +25361,7 @@ function filterMcpServersByAgentCapabilities(mcpServers, agentCapabilities) {
|
|
|
25354
25361
|
});
|
|
25355
25362
|
}
|
|
25356
25363
|
|
|
25357
|
-
// ../../packages/ycodium-acp-executor/src/
|
|
25358
|
-
var defaultVendorHooks = {
|
|
25359
|
-
completedStopReason: (response) => response.stopReason
|
|
25360
|
-
};
|
|
25361
|
-
|
|
25362
|
-
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
25363
|
-
var DEFAULT_CANCEL_GRACE_MS = 5e3;
|
|
25364
|
-
var userInputAnswerOptionId = (question, answers) => {
|
|
25365
|
-
const answer = answers[question.id];
|
|
25366
|
-
const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
|
|
25367
|
-
return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
|
|
25368
|
-
};
|
|
25369
|
-
function defaultNowIso() {
|
|
25370
|
-
return (/* @__PURE__ */ new Date()).toISOString();
|
|
25371
|
-
}
|
|
25372
|
-
function defaultRandomId() {
|
|
25373
|
-
return NodeCrypto.randomUUID();
|
|
25374
|
-
}
|
|
25364
|
+
// ../../packages/ycodium-acp-executor/src/model-selection.ts
|
|
25375
25365
|
function normalizeModelId(value) {
|
|
25376
25366
|
return value?.trim() || void 0;
|
|
25377
25367
|
}
|
|
@@ -25390,6 +25380,25 @@ function modelSelectionStateFromSetup(setup) {
|
|
|
25390
25380
|
advertisedModelValues: strategy === "config-option" ? modelConfigOption === void 0 ? [] : collectSessionConfigOptionValues(modelConfigOption) : collectSessionModelIds(sessionModels)
|
|
25391
25381
|
};
|
|
25392
25382
|
}
|
|
25383
|
+
|
|
25384
|
+
// ../../packages/ycodium-acp-executor/src/vendor-hooks.ts
|
|
25385
|
+
var defaultVendorHooks = {
|
|
25386
|
+
completedStopReason: (response) => response.stopReason
|
|
25387
|
+
};
|
|
25388
|
+
|
|
25389
|
+
// ../../packages/ycodium-acp-executor/src/executor.ts
|
|
25390
|
+
var DEFAULT_CANCEL_GRACE_MS = 5e3;
|
|
25391
|
+
var userInputAnswerOptionId = (question, answers) => {
|
|
25392
|
+
const answer = answers[question.id];
|
|
25393
|
+
const selected = typeof answer === "string" ? answer : Array.isArray(answer) && answer.length === 1 && typeof answer[0] === "string" ? answer[0] : void 0;
|
|
25394
|
+
return selected !== void 0 && question.options.some((option) => option.id === selected) ? selected : void 0;
|
|
25395
|
+
};
|
|
25396
|
+
function defaultNowIso() {
|
|
25397
|
+
return (/* @__PURE__ */ new Date()).toISOString();
|
|
25398
|
+
}
|
|
25399
|
+
function defaultRandomId() {
|
|
25400
|
+
return NodeCrypto.randomUUID();
|
|
25401
|
+
}
|
|
25393
25402
|
function createAcpExecutor(options) {
|
|
25394
25403
|
const hooks = { ...defaultVendorHooks, ...options.hooks };
|
|
25395
25404
|
const cancelGraceMs = options.cancelGraceMs ?? DEFAULT_CANCEL_GRACE_MS;
|
|
@@ -25599,6 +25608,7 @@ function createAcpExecutor(options) {
|
|
|
25599
25608
|
const commands = parseAvailableCommandsUpdate(params);
|
|
25600
25609
|
if (commands !== void 0) {
|
|
25601
25610
|
availableCommands = commands;
|
|
25611
|
+
options.onAvailableCommands?.(commands);
|
|
25602
25612
|
}
|
|
25603
25613
|
if (sessionLoadInFlight) {
|
|
25604
25614
|
droppedReplayUpdates += parsed.events.filter((event) => event._tag !== "ModeChanged").length;
|
|
@@ -26760,6 +26770,164 @@ async function probeCliVersion(input2) {
|
|
|
26760
26770
|
}
|
|
26761
26771
|
}
|
|
26762
26772
|
|
|
26773
|
+
// src/dshBalance.ts
|
|
26774
|
+
import * as NodeCrypto2 from "node:crypto";
|
|
26775
|
+
import * as NodeFS from "node:fs";
|
|
26776
|
+
import * as NodeOS from "node:os";
|
|
26777
|
+
import * as NodePath from "node:path";
|
|
26778
|
+
import {
|
|
26779
|
+
parseRetryAfterMs
|
|
26780
|
+
} from "@ycodium-ai/plugin-api/usage";
|
|
26781
|
+
var BALANCE_URL = "https://api.deepseek.com/user/balance";
|
|
26782
|
+
var OFFICIAL_HOSTS = /* @__PURE__ */ new Set(["api.deepseek.com"]);
|
|
26783
|
+
var API_KEY_NAME = "DEEPSEEK_API_KEY";
|
|
26784
|
+
var BASE_URL_NAME = "DEEPSEEK_BASE_URL";
|
|
26785
|
+
var TIMEOUT_MS = 1e4;
|
|
26786
|
+
var asObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) ? value : null;
|
|
26787
|
+
var parseJson = (raw) => {
|
|
26788
|
+
try {
|
|
26789
|
+
return JSON.parse(raw);
|
|
26790
|
+
} catch {
|
|
26791
|
+
return null;
|
|
26792
|
+
}
|
|
26793
|
+
};
|
|
26794
|
+
var readFile = (path) => {
|
|
26795
|
+
try {
|
|
26796
|
+
return NodeFS.readFileSync(path, "utf8");
|
|
26797
|
+
} catch {
|
|
26798
|
+
return null;
|
|
26799
|
+
}
|
|
26800
|
+
};
|
|
26801
|
+
var unquote = (raw) => {
|
|
26802
|
+
const trimmed = raw.trim();
|
|
26803
|
+
const quoted = /^(["'])(.*)\1/.exec(trimmed);
|
|
26804
|
+
if (quoted?.[2] !== void 0) return quoted[2];
|
|
26805
|
+
return (trimmed.split(/\s+#/)[0] ?? "").trim();
|
|
26806
|
+
};
|
|
26807
|
+
var readCredentialsYamlRef = (yaml, name) => {
|
|
26808
|
+
let inRefs = false;
|
|
26809
|
+
for (const line of yaml.split(/\r?\n/)) {
|
|
26810
|
+
if (line.trim().length === 0 || line.trimStart().startsWith("#")) continue;
|
|
26811
|
+
if (!/^\s/.test(line)) {
|
|
26812
|
+
inRefs = /^refs\s*:\s*(?:#.*)?$/.test(line);
|
|
26813
|
+
continue;
|
|
26814
|
+
}
|
|
26815
|
+
if (!inRefs) continue;
|
|
26816
|
+
const match = /^\s+([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/.exec(line);
|
|
26817
|
+
if (match?.[1] === name) {
|
|
26818
|
+
const value = unquote(match[2] ?? "");
|
|
26819
|
+
return value.length > 0 ? value : null;
|
|
26820
|
+
}
|
|
26821
|
+
}
|
|
26822
|
+
return null;
|
|
26823
|
+
};
|
|
26824
|
+
var readDotenvValue = (dotenv, name) => {
|
|
26825
|
+
for (const line of dotenv.split(/\r?\n/)) {
|
|
26826
|
+
const match = /^\s*(?:export\s+)?([A-Za-z_][A-Za-z0-9_]*)\s*=\s*(.*)$/.exec(line);
|
|
26827
|
+
if (match?.[1] !== name) continue;
|
|
26828
|
+
const value = unquote(match[2] ?? "");
|
|
26829
|
+
return value.length > 0 ? value : null;
|
|
26830
|
+
}
|
|
26831
|
+
return null;
|
|
26832
|
+
};
|
|
26833
|
+
var nonEmpty = (value) => {
|
|
26834
|
+
const trimmed = value?.trim() ?? "";
|
|
26835
|
+
return trimmed.length > 0 ? trimmed : null;
|
|
26836
|
+
};
|
|
26837
|
+
var asMoney = (value) => {
|
|
26838
|
+
const parsed = typeof value === "number" ? value : typeof value === "string" ? Number(value) : NaN;
|
|
26839
|
+
return Number.isFinite(parsed) ? parsed : null;
|
|
26840
|
+
};
|
|
26841
|
+
var dshBalances = (body) => {
|
|
26842
|
+
const infos = asObject(body)?.["balance_infos"];
|
|
26843
|
+
if (!Array.isArray(infos)) return [];
|
|
26844
|
+
const balances = [];
|
|
26845
|
+
for (const entry of infos) {
|
|
26846
|
+
const info = asObject(entry);
|
|
26847
|
+
const currency = typeof info?.["currency"] === "string" ? info["currency"].trim() : "";
|
|
26848
|
+
const total = asMoney(info?.["total_balance"]);
|
|
26849
|
+
if (info === null || !/^[A-Z]{3}$/.test(currency) || total === null) continue;
|
|
26850
|
+
balances.push({
|
|
26851
|
+
id: `balance-${currency}`,
|
|
26852
|
+
label: { key: "usage.balance.account" },
|
|
26853
|
+
remaining: total,
|
|
26854
|
+
used: null,
|
|
26855
|
+
limit: null,
|
|
26856
|
+
unit: { kind: "money", currency },
|
|
26857
|
+
resetsAt: null
|
|
26858
|
+
});
|
|
26859
|
+
}
|
|
26860
|
+
return balances;
|
|
26861
|
+
};
|
|
26862
|
+
var createDshUsage = (input2) => {
|
|
26863
|
+
const now = input2.now ?? Date.now;
|
|
26864
|
+
const processEnv = input2.processEnv ?? process.env;
|
|
26865
|
+
const envValue = (name) => nonEmpty(input2.environment[name]) ?? nonEmpty(processEnv[name]);
|
|
26866
|
+
const dshHome = () => nonEmpty(input2.environment[input2.homeEnvVar]) ?? nonEmpty(input2.homePath) ?? nonEmpty(processEnv[input2.homeEnvVar]) ?? NodePath.join(NodeOS.homedir(), ".dsh");
|
|
26867
|
+
const resolveKey = () => {
|
|
26868
|
+
const fromEnvironment = envValue(API_KEY_NAME);
|
|
26869
|
+
if (fromEnvironment !== null) return fromEnvironment;
|
|
26870
|
+
const home = dshHome();
|
|
26871
|
+
const yaml = readFile(NodePath.join(home, ".credentials.yaml"));
|
|
26872
|
+
const fromYaml = yaml === null ? null : readCredentialsYamlRef(yaml, API_KEY_NAME);
|
|
26873
|
+
if (fromYaml !== null) return fromYaml;
|
|
26874
|
+
const dotenv = readFile(NodePath.join(home, ".env"));
|
|
26875
|
+
return dotenv === null ? null : readDotenvValue(dotenv, API_KEY_NAME);
|
|
26876
|
+
};
|
|
26877
|
+
const readQuota = async (request) => {
|
|
26878
|
+
const baseUrl = envValue(BASE_URL_NAME);
|
|
26879
|
+
if (baseUrl !== null) {
|
|
26880
|
+
const host = URL.parse(baseUrl)?.hostname.toLowerCase();
|
|
26881
|
+
if (host === void 0 || !OFFICIAL_HOSTS.has(host)) {
|
|
26882
|
+
return { status: "unavailable", reason: "customEndpoint" };
|
|
26883
|
+
}
|
|
26884
|
+
}
|
|
26885
|
+
const key = resolveKey();
|
|
26886
|
+
if (key === null) return { status: "unavailable", reason: "missingCredentials" };
|
|
26887
|
+
let response;
|
|
26888
|
+
try {
|
|
26889
|
+
response = await input2.fetch(BALANCE_URL, {
|
|
26890
|
+
headers: { Authorization: `Bearer ${key}`, Accept: "application/json" },
|
|
26891
|
+
signal: AbortSignal.any([
|
|
26892
|
+
...request.signal === void 0 ? [] : [request.signal],
|
|
26893
|
+
AbortSignal.timeout(TIMEOUT_MS)
|
|
26894
|
+
])
|
|
26895
|
+
});
|
|
26896
|
+
} catch {
|
|
26897
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
26898
|
+
}
|
|
26899
|
+
if (response.status === 401 || response.status === 403) {
|
|
26900
|
+
return { status: "unavailable", reason: "authRejected" };
|
|
26901
|
+
}
|
|
26902
|
+
if (response.status === 429) {
|
|
26903
|
+
const retryAfterMs = parseRetryAfterMs(response.headers.get("retry-after"), now());
|
|
26904
|
+
return {
|
|
26905
|
+
status: "unavailable",
|
|
26906
|
+
reason: "rateLimited",
|
|
26907
|
+
...retryAfterMs === null ? {} : { retryAfterMs }
|
|
26908
|
+
};
|
|
26909
|
+
}
|
|
26910
|
+
if (!response.ok) return { status: "unavailable", reason: "unreachable" };
|
|
26911
|
+
let body;
|
|
26912
|
+
try {
|
|
26913
|
+
body = parseJson(await response.text());
|
|
26914
|
+
} catch {
|
|
26915
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
26916
|
+
}
|
|
26917
|
+
if (asObject(body) === null || !Array.isArray(asObject(body)?.["balance_infos"])) {
|
|
26918
|
+
return { status: "unavailable", reason: "unreachable" };
|
|
26919
|
+
}
|
|
26920
|
+
return {
|
|
26921
|
+
status: "available",
|
|
26922
|
+
windows: [],
|
|
26923
|
+
balances: dshBalances(body),
|
|
26924
|
+
// 同一把 key 的两个实例是同一个账户:用 key 的指纹合成一行(指纹不可逆,不含 key 本身)。
|
|
26925
|
+
accountKey: `deepseek:${NodeCrypto2.createHash("sha256").update(key).digest("hex").slice(0, 12)}`
|
|
26926
|
+
};
|
|
26927
|
+
};
|
|
26928
|
+
return { readQuota };
|
|
26929
|
+
};
|
|
26930
|
+
|
|
26763
26931
|
// src/config.ts
|
|
26764
26932
|
var DSH_DEFAULT_LAUNCH_ARGS = "--profile acp";
|
|
26765
26933
|
function isRecord6(value) {
|
|
@@ -26857,9 +27025,9 @@ function tokenizeLaunchArgs(value) {
|
|
|
26857
27025
|
}
|
|
26858
27026
|
|
|
26859
27027
|
// src/probeModels.ts
|
|
26860
|
-
import * as
|
|
26861
|
-
import * as
|
|
26862
|
-
import * as
|
|
27028
|
+
import * as NodeFS2 from "node:fs";
|
|
27029
|
+
import * as NodeOS3 from "node:os";
|
|
27030
|
+
import * as NodePath3 from "node:path";
|
|
26863
27031
|
import {
|
|
26864
27032
|
describeExecutorSpawnFailure,
|
|
26865
27033
|
ExecutorSpawnRefusedError
|
|
@@ -26867,8 +27035,8 @@ import {
|
|
|
26867
27035
|
import { nodeStreamsFromHandle } from "@ycodium-ai/plugin-api/process-stdin";
|
|
26868
27036
|
|
|
26869
27037
|
// src/spawnEnv.ts
|
|
26870
|
-
import * as
|
|
26871
|
-
import * as
|
|
27038
|
+
import * as NodeOS2 from "node:os";
|
|
27039
|
+
import * as NodePath2 from "node:path";
|
|
26872
27040
|
import { mergeLaunchEnv } from "@ycodium-ai/plugin-api/executor";
|
|
26873
27041
|
|
|
26874
27042
|
// src/permission.ts
|
|
@@ -26911,20 +27079,20 @@ function dshPermissionEnv(nativeModeId) {
|
|
|
26911
27079
|
|
|
26912
27080
|
// src/spawnEnv.ts
|
|
26913
27081
|
function expandHomePath(value) {
|
|
26914
|
-
if (value === "~") return
|
|
27082
|
+
if (value === "~") return NodeOS2.homedir();
|
|
26915
27083
|
if (value.startsWith("~/") || value.startsWith("~\\")) {
|
|
26916
|
-
return
|
|
27084
|
+
return NodePath2.join(NodeOS2.homedir(), value.slice(2));
|
|
26917
27085
|
}
|
|
26918
27086
|
return value;
|
|
26919
27087
|
}
|
|
26920
27088
|
function resolveHomePath(value) {
|
|
26921
27089
|
const trimmed = value.trim();
|
|
26922
27090
|
if (trimmed.length === 0) return "";
|
|
26923
|
-
return
|
|
27091
|
+
return NodePath2.resolve(expandHomePath(trimmed));
|
|
26924
27092
|
}
|
|
26925
27093
|
function dshContinuationKey(homePath) {
|
|
26926
27094
|
const resolved = resolveHomePath(homePath);
|
|
26927
|
-
return `dsh:home:${resolved.length > 0 ? resolved :
|
|
27095
|
+
return `dsh:home:${resolved.length > 0 ? resolved : NodePath2.join(NodeOS2.homedir(), ".dsh")}`;
|
|
26928
27096
|
}
|
|
26929
27097
|
function buildSpawnEnv(recipe, resolvedHomePath, nativeModeId) {
|
|
26930
27098
|
const homeEnvVar = recipe.homeEnvVar.trim() || DSH_CARD.homeEnvVar;
|
|
@@ -26942,7 +27110,7 @@ function buildSpawnEnv(recipe, resolvedHomePath, nativeModeId) {
|
|
|
26942
27110
|
var PROBE_REQUEST_TIMEOUT_MS = 15e3;
|
|
26943
27111
|
function dshProbeSessionCwd(instanceId) {
|
|
26944
27112
|
const safe = instanceId.trim().replace(/[^A-Za-z0-9._-]/g, "-") || "instance";
|
|
26945
|
-
return
|
|
27113
|
+
return NodePath3.join(NodeOS3.tmpdir(), `ycodium-dsh-probe-${safe}`);
|
|
26946
27114
|
}
|
|
26947
27115
|
function isRecord7(value) {
|
|
26948
27116
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -27004,7 +27172,7 @@ async function probeDshModels(input2) {
|
|
|
27004
27172
|
const { recipe, host } = input2;
|
|
27005
27173
|
const probeCwd = dshProbeSessionCwd(host.instanceId);
|
|
27006
27174
|
try {
|
|
27007
|
-
|
|
27175
|
+
NodeFS2.mkdirSync(probeCwd, { recursive: true });
|
|
27008
27176
|
} catch (error62) {
|
|
27009
27177
|
return { kind: "failed", detail: failureDetail(error62) };
|
|
27010
27178
|
}
|
|
@@ -27191,6 +27359,11 @@ var createDshInstance = (config2, host) => {
|
|
|
27191
27359
|
providerInstanceId: host.instanceId,
|
|
27192
27360
|
clientInfo: DSH_CLIENT_INFO,
|
|
27193
27361
|
log: host.log,
|
|
27362
|
+
// agent 自己宣告的斜杠命令按会话报给宿主,输入区的 / 菜单才有它们。
|
|
27363
|
+
onAvailableCommands: (commands) => host.reportSessionInventory?.({
|
|
27364
|
+
threadId: input2.threadId,
|
|
27365
|
+
slashCommands: acpCommandsToSlashCommands(commands)
|
|
27366
|
+
}),
|
|
27194
27367
|
// 该 agent 不实现 session/load,只实现 session/resume——续接重新激活
|
|
27195
27368
|
// 持久会话而不重放记录,发 load 会卡在永远不结算的重放门上。
|
|
27196
27369
|
resumeMethod: "session/resume",
|
|
@@ -27323,6 +27496,13 @@ var createDshInstance = (config2, host) => {
|
|
|
27323
27496
|
return { threadId, turns: booked.turns };
|
|
27324
27497
|
},
|
|
27325
27498
|
events,
|
|
27499
|
+
// 额度是 DeepSeek 账户的剩余金额(API key,没有订阅窗口);token 暂无来源,见 dshBalance.ts 与 README。
|
|
27500
|
+
usage: createDshUsage({
|
|
27501
|
+
environment: recipe.environment,
|
|
27502
|
+
homePath: resolveHomePath(recipe.homePath),
|
|
27503
|
+
homeEnvVar: recipe.homeEnvVar.trim() || DSH_CARD.homeEnvVar,
|
|
27504
|
+
fetch: host.fetch
|
|
27505
|
+
}),
|
|
27326
27506
|
continuationKey: dshContinuationKey(recipe.homePath),
|
|
27327
27507
|
dispose: async () => {
|
|
27328
27508
|
if (disposed) return;
|
package/locales/en.json
CHANGED
|
@@ -10,5 +10,10 @@
|
|
|
10
10
|
"description": "Sessions live here, so providers sharing this directory can pick up each other's threads and providers with different directories cannot. Leave empty to use the CLI's default (~/.dsh).",
|
|
11
11
|
"placeholder": "e.g. ~/.dsh-work"
|
|
12
12
|
}
|
|
13
|
+
},
|
|
14
|
+
"usage": {
|
|
15
|
+
"balance": {
|
|
16
|
+
"account": "Account balance"
|
|
17
|
+
}
|
|
13
18
|
}
|
|
14
19
|
}
|
package/locales/zh-CN.json
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ycodium-ai/agent-dsh",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.2694",
|
|
4
4
|
"description": "DeepSeek Harness executor: dsh CLI over Agent Client Protocol stdio.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ycodium",
|
|
@@ -21,9 +21,9 @@
|
|
|
21
21
|
"@types/node": "24.12.4",
|
|
22
22
|
"esbuild": "0.28.1",
|
|
23
23
|
"vite-plus": "0.2.2",
|
|
24
|
-
"ycodium-
|
|
24
|
+
"@ycodium-ai/plugin-api": "0.2.2694",
|
|
25
25
|
"ycodium-executor-testing": "0.0.0",
|
|
26
|
-
"
|
|
26
|
+
"ycodium-acp-executor": "0.2.2694"
|
|
27
27
|
},
|
|
28
28
|
"ycodium": {
|
|
29
29
|
"plugin": "./dist/index.js",
|