@divergeai/cli 0.1.29 → 0.1.30
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 +15 -2
- package/dist/diverge.mjs +138 -37
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -117,7 +117,8 @@ after `--` goes to dsh as given. Each launch, in order:
|
|
|
117
117
|
`$DIVERGE_HOME/harness/dsh/<version>`: about a minute and nearly 1 GB, and
|
|
118
118
|
Node 24.9 or later. A dsh you installed yourself is neither used nor touched.
|
|
119
119
|
A version no launch has used for a week is deleted.
|
|
120
|
-
4. brings
|
|
120
|
+
4. brings the launch organization's skills and the CLI's up to date (see
|
|
121
|
+
[Skills](#skills)) and names both roots in the overlay.
|
|
121
122
|
5. writes the overlay `$DSH_HOME/divergent-<surface>.yml`: the models the
|
|
122
123
|
gateway serves, each with the input, context window and output cap the
|
|
123
124
|
gateway lists for it; dsh's DeepSeek adapter, telemetry upload and vendor
|
|
@@ -178,7 +179,7 @@ a shell.
|
|
|
178
179
|
|
|
179
180
|
```bash
|
|
180
181
|
diverge skills list # what the platform serves you, per organization
|
|
181
|
-
diverge skills install # into ~/.claude/skills, ~/.codex/skills and $
|
|
182
|
+
diverge skills install # into ~/.claude/skills, ~/.codex/skills and $DIVERGE_HOME/skills/dsh
|
|
182
183
|
diverge skills refresh # the same, best effort and quiet: what sign-in and a session start run
|
|
183
184
|
diverge skills status # what each folder holds against the platform
|
|
184
185
|
```
|
|
@@ -213,6 +214,18 @@ shell with `diverge tools`, which costs nothing until a tool is called, and
|
|
|
213
214
|
the `diverge` skill shows it how, arguments piped through stdin and batches
|
|
214
215
|
included.
|
|
215
216
|
|
|
217
|
+
A dsh session is bound to one organization by the launch that starts it, so
|
|
218
|
+
dsh's skills do not sit side by side: the CLI writes them under its own root,
|
|
219
|
+
`$DIVERGE_HOME/skills/dsh/<organization id>/<folder>/SKILL.md`, and the CLI's
|
|
220
|
+
`diverge` and `drive-chrome` under `$DIVERGE_HOME/skills/dsh/cli/`. A `diverge
|
|
221
|
+
dsh` launch refreshes its organization's folder and names it and the CLI's as
|
|
222
|
+
`customSkillDirs` on dsh's skill provider, in the host row and in every
|
|
223
|
+
shipped agent preset that mounts one, so its catalog offers only the skills
|
|
224
|
+
its token can run. dsh's default roots stay on: your own `$DSH_HOME/skills`
|
|
225
|
+
and a project's `.agents/skills` still load. A CLI before 0.1.30 wrote every
|
|
226
|
+
organization's skills into `$DSH_HOME/skills`; the first install or launch
|
|
227
|
+
after it removes exactly the folders it recorded there, and nothing of yours.
|
|
228
|
+
|
|
216
229
|
dsh also gets the browser. The overlay mounts Chrome DevTools MCP, attached
|
|
217
230
|
to a Chrome the person starts in debug mode (`--remote-debugging-port=9222`,
|
|
218
231
|
on a profile of its own), and the CLI's `drive-chrome` skill says how to use
|
package/dist/diverge.mjs
CHANGED
|
@@ -7553,7 +7553,7 @@ function tokenSource(env, baseUrl) {
|
|
|
7553
7553
|
}
|
|
7554
7554
|
|
|
7555
7555
|
// src/version.ts
|
|
7556
|
-
var VERSION = true ? "0.1.
|
|
7556
|
+
var VERSION = true ? "0.1.30" : "dev";
|
|
7557
7557
|
var USER_AGENT = `diverge/${VERSION}`;
|
|
7558
7558
|
|
|
7559
7559
|
// src/http.ts
|
|
@@ -8601,9 +8601,18 @@ function dshPatchYaml(options) {
|
|
|
8601
8601
|
...dshShellRows(),
|
|
8602
8602
|
...dshBrowserRows(),
|
|
8603
8603
|
...options.hooks ? dshHookRows(options.hooks) : [],
|
|
8604
|
+
...options.skillDirs?.length ? dshSkillRows(options.skillDirs) : [],
|
|
8604
8605
|
""
|
|
8605
8606
|
].join("\n");
|
|
8606
8607
|
}
|
|
8608
|
+
function dshSkillRows(skillDirs) {
|
|
8609
|
+
return [
|
|
8610
|
+
"- id: skill-filesystem",
|
|
8611
|
+
" config:",
|
|
8612
|
+
" customSkillDirs:",
|
|
8613
|
+
...skillDirs.map((dir) => ` - ${JSON.stringify(dir)}`)
|
|
8614
|
+
];
|
|
8615
|
+
}
|
|
8607
8616
|
function repositoryHookConfig(cwd) {
|
|
8608
8617
|
for (let dir = path4.resolve(cwd); ; dir = path4.dirname(dir)) {
|
|
8609
8618
|
if (fs5.existsSync(path4.join(dir, ".git"))) {
|
|
@@ -8688,48 +8697,77 @@ function dshSavedModel(patchText, surface) {
|
|
|
8688
8697
|
return { model: String(config.model), ...config.reasoningEffort ? { reasoningEffort: String(config.reasoningEffort) } : {} };
|
|
8689
8698
|
}
|
|
8690
8699
|
var dshPresetsDir = (prefix) => path4.join(prefix, "node_modules", "@deepseek-ai", "dsh-web-app", "presets");
|
|
8691
|
-
function
|
|
8692
|
-
const
|
|
8693
|
-
|
|
8694
|
-
if (insert === -1) throw new Error("a shipped preset is not one inserted row");
|
|
8695
|
-
const row = lines.slice(insert + 1).map((line) => line.replace(/^ {4}/, ""));
|
|
8696
|
-
const start = row.findIndex((line) => /^\s+- id: ['"]?tool-web['"]?\s*$/.test(line));
|
|
8697
|
-
if (start === -1) return null;
|
|
8700
|
+
function editPresetPlugin(row, id, edit) {
|
|
8701
|
+
const start = row.findIndex((line) => new RegExp(`^\\s+- id: ['"]?${id}['"]?\\s*$`).test(line));
|
|
8702
|
+
if (start === -1) return false;
|
|
8698
8703
|
const indent = row[start].indexOf("-");
|
|
8699
8704
|
const body = " ".repeat(indent + 2);
|
|
8700
8705
|
let end = row.findIndex((line, index) => index > start && line.trim() !== "" && line.search(/\S/) <= indent);
|
|
8701
8706
|
if (end === -1) end = row.length;
|
|
8702
8707
|
const block = row.slice(start, end);
|
|
8703
|
-
|
|
8704
|
-
|
|
8705
|
-
|
|
8706
|
-
|
|
8707
|
-
|
|
8708
|
-
|
|
8709
|
-
|
|
8710
|
-
|
|
8711
|
-
|
|
8708
|
+
edit(block, body);
|
|
8709
|
+
row.splice(start, end - start, ...block);
|
|
8710
|
+
return true;
|
|
8711
|
+
}
|
|
8712
|
+
function dshPresetOverride(shipped, skillDirs = []) {
|
|
8713
|
+
const lines = shipped.split("\n");
|
|
8714
|
+
const insert = lines.indexOf("- insert:");
|
|
8715
|
+
if (insert === -1) throw new Error("a shipped preset is not one inserted row");
|
|
8716
|
+
const row = lines.slice(insert + 1).map((line) => line.replace(/^ {4}/, ""));
|
|
8717
|
+
const web = editPresetPlugin(row, "tool-web", (block, body) => {
|
|
8718
|
+
const search = block.findIndex((line) => line.startsWith(`${body} search:`));
|
|
8719
|
+
if (search !== -1) {
|
|
8720
|
+
block[search] = `${body} search: false`;
|
|
8721
|
+
} else {
|
|
8722
|
+
const config = block.indexOf(`${body}config:`);
|
|
8723
|
+
if (config !== -1) block.splice(config + 1, 0, `${body} search: false`);
|
|
8724
|
+
else block.splice(1, 0, `${body}config:`, `${body} search: false`);
|
|
8725
|
+
}
|
|
8726
|
+
});
|
|
8727
|
+
const skills = skillDirs.length > 0 && editPresetPlugin(row, "skill-filesystem", (block, body) => {
|
|
8728
|
+
const items = skillDirs.map((dir) => `${body} - ${JSON.stringify(dir)}`);
|
|
8729
|
+
const list = block.indexOf(`${body} customSkillDirs:`);
|
|
8730
|
+
if (list !== -1) {
|
|
8731
|
+
let last = list + 1;
|
|
8732
|
+
while (last < block.length && block[last].startsWith(`${body} `)) last += 1;
|
|
8733
|
+
block.splice(last, 0, ...items);
|
|
8734
|
+
} else {
|
|
8735
|
+
const config = block.indexOf(`${body}config:`);
|
|
8736
|
+
if (config !== -1) block.splice(config + 1, 0, `${body} customSkillDirs:`, ...items);
|
|
8737
|
+
else block.splice(1, 0, `${body}config:`, `${body} customSkillDirs:`, ...items);
|
|
8738
|
+
}
|
|
8739
|
+
});
|
|
8740
|
+
if (!web && !skills) return null;
|
|
8741
|
+
return row.join("\n").trimEnd() + "\n";
|
|
8712
8742
|
}
|
|
8713
|
-
function dshPresetOverrides(prefix) {
|
|
8743
|
+
function dshPresetOverrides(prefix, skillDirs = []) {
|
|
8714
8744
|
const dir = dshPresetsDir(prefix);
|
|
8715
|
-
return fs5.readdirSync(dir).filter((name) => name.endsWith(".patch.yml")).sort().flatMap((name) => dshPresetOverride(fs5.readFileSync(path4.join(dir, name), "utf8")) ?? []).join("");
|
|
8745
|
+
return fs5.readdirSync(dir).filter((name) => name.endsWith(".patch.yml")).sort().flatMap((name) => dshPresetOverride(fs5.readFileSync(path4.join(dir, name), "utf8"), skillDirs) ?? []).join("");
|
|
8716
8746
|
}
|
|
8717
8747
|
|
|
8718
8748
|
// src/skills/install.ts
|
|
8719
8749
|
var HARNESSES = ["claude", "codex", "dsh"];
|
|
8720
8750
|
var SKILLS_MANIFEST = ".diverge-skills.json";
|
|
8721
|
-
|
|
8751
|
+
var DSH_CLI_SKILLS = "cli";
|
|
8752
|
+
function harnessHome(harness, env) {
|
|
8722
8753
|
switch (harness) {
|
|
8723
8754
|
case "claude":
|
|
8724
|
-
return
|
|
8755
|
+
return env.CLAUDE_CONFIG_DIR?.trim() || path5.join(os3.homedir(), ".claude");
|
|
8725
8756
|
case "codex":
|
|
8726
|
-
return
|
|
8757
|
+
return env.CODEX_HOME?.trim() || path5.join(os3.homedir(), ".codex");
|
|
8727
8758
|
case "dsh":
|
|
8728
|
-
return
|
|
8759
|
+
return dshHome(env);
|
|
8729
8760
|
}
|
|
8730
8761
|
}
|
|
8762
|
+
function skillsRoot(harness, env = process.env) {
|
|
8763
|
+
return harness === "dsh" ? path5.join(configDir(env), "skills", "dsh") : path5.join(harnessHome(harness, env), "skills");
|
|
8764
|
+
}
|
|
8765
|
+
function dshSkillDirs(organizationId, env = process.env) {
|
|
8766
|
+
const root = skillsRoot("dsh", env);
|
|
8767
|
+
return [path5.join(root, organizationId), path5.join(root, DSH_CLI_SKILLS)];
|
|
8768
|
+
}
|
|
8731
8769
|
function presentHarnesses(env = process.env) {
|
|
8732
|
-
return HARNESSES.filter((harness) => fs6.existsSync(
|
|
8770
|
+
return HARNESSES.filter((harness) => fs6.existsSync(harnessHome(harness, env)));
|
|
8733
8771
|
}
|
|
8734
8772
|
function isRecord(value) {
|
|
8735
8773
|
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
@@ -8866,6 +8904,66 @@ function skillsStatus(root, set2) {
|
|
|
8866
8904
|
const retired = [...new Set(retirable(manifest, set2))].filter((folder) => !servedFolders.has(folder));
|
|
8867
8905
|
return { root, installedAt: manifest?.installedAt || null, current, behind, missing, retired, skipped };
|
|
8868
8906
|
}
|
|
8907
|
+
function isOrganizationFolder(id) {
|
|
8908
|
+
return id !== DSH_CLI_SKILLS && /^[A-Za-z0-9_-]{1,64}$/.test(id);
|
|
8909
|
+
}
|
|
8910
|
+
function targets(harness, root, set2) {
|
|
8911
|
+
if (harness !== "dsh") return [{ root, set: set2 }];
|
|
8912
|
+
return [
|
|
8913
|
+
...set2.organizations.filter((organization) => isOrganizationFolder(organization.id)).map((organization) => ({ root: path5.join(root, organization.id), set: { cli: [], organizations: [organization], complete: true } })),
|
|
8914
|
+
{ root: path5.join(root, DSH_CLI_SKILLS), set: { cli: set2.cli, organizations: [], complete: true } }
|
|
8915
|
+
];
|
|
8916
|
+
}
|
|
8917
|
+
function retiredOrganizations(root, set2) {
|
|
8918
|
+
if (!set2.complete || !fs6.existsSync(root)) return [];
|
|
8919
|
+
const listed = new Set(set2.organizations.map((organization) => organization.id));
|
|
8920
|
+
return fs6.readdirSync(root, { withFileTypes: true }).filter((entry) => entry.isDirectory() && isOrganizationFolder(entry.name) && !listed.has(entry.name) && readSkillsManifest(path5.join(root, entry.name))).map((entry) => path5.join(root, entry.name));
|
|
8921
|
+
}
|
|
8922
|
+
function legacyDshFolders(env) {
|
|
8923
|
+
const root = path5.join(dshHome(env), "skills");
|
|
8924
|
+
return { root, folders: [...heldFolders(readSkillsManifest(root)).keys()].filter(isSkillFolder) };
|
|
8925
|
+
}
|
|
8926
|
+
function installHarness(harness, root, set2, source, env = process.env, now = () => /* @__PURE__ */ new Date()) {
|
|
8927
|
+
const results = targets(harness, root, set2).map((target) => installSkills(target.root, target.set, source, now));
|
|
8928
|
+
const merged = {
|
|
8929
|
+
root,
|
|
8930
|
+
written: results.flatMap((result) => result.written),
|
|
8931
|
+
added: results.flatMap((result) => result.added),
|
|
8932
|
+
updated: results.flatMap((result) => result.updated),
|
|
8933
|
+
removed: results.flatMap((result) => result.removed),
|
|
8934
|
+
skipped: results.flatMap((result) => result.skipped),
|
|
8935
|
+
counts: results.flatMap((result) => result.counts)
|
|
8936
|
+
};
|
|
8937
|
+
if (harness !== "dsh") return merged;
|
|
8938
|
+
for (const folder of retiredOrganizations(root, set2)) {
|
|
8939
|
+
merged.removed.push(...heldFolders(readSkillsManifest(folder)).keys());
|
|
8940
|
+
fs6.rmSync(folder, { recursive: true, force: true });
|
|
8941
|
+
}
|
|
8942
|
+
if (root !== skillsRoot("dsh", env)) return merged;
|
|
8943
|
+
const legacy = legacyDshFolders(env);
|
|
8944
|
+
for (const folder of legacy.folders) fs6.rmSync(path5.join(legacy.root, folder), { recursive: true, force: true });
|
|
8945
|
+
fs6.rmSync(path5.join(legacy.root, SKILLS_MANIFEST), { force: true });
|
|
8946
|
+
merged.removed.push(...legacy.folders);
|
|
8947
|
+
return merged;
|
|
8948
|
+
}
|
|
8949
|
+
function harnessStatus(harness, root, set2, env = process.env) {
|
|
8950
|
+
const statuses = targets(harness, root, set2).map((target) => skillsStatus(target.root, target.set));
|
|
8951
|
+
const retired = statuses.flatMap((status2) => status2.retired);
|
|
8952
|
+
if (harness === "dsh") {
|
|
8953
|
+
for (const folder of retiredOrganizations(root, set2)) retired.push(...heldFolders(readSkillsManifest(folder)).keys());
|
|
8954
|
+
if (root === skillsRoot("dsh", env)) retired.push(...legacyDshFolders(env).folders);
|
|
8955
|
+
}
|
|
8956
|
+
const installed = statuses.map((status2) => status2.installedAt).filter((at) => at !== null).sort();
|
|
8957
|
+
return {
|
|
8958
|
+
root,
|
|
8959
|
+
installedAt: installed[0] ?? null,
|
|
8960
|
+
current: statuses.flatMap((status2) => status2.current),
|
|
8961
|
+
behind: statuses.flatMap((status2) => status2.behind),
|
|
8962
|
+
missing: statuses.flatMap((status2) => status2.missing),
|
|
8963
|
+
retired,
|
|
8964
|
+
skipped: statuses.flatMap((status2) => status2.skipped)
|
|
8965
|
+
};
|
|
8966
|
+
}
|
|
8869
8967
|
|
|
8870
8968
|
// src/skills/installable.ts
|
|
8871
8969
|
async function fetchInstallableSkills(baseUrl, accessToken) {
|
|
@@ -8913,9 +9011,11 @@ async function collectLoginSkills(deps, options = {}) {
|
|
|
8913
9011
|
var skillsUsage = `diverge skills <list|install|refresh|status> [--organization-id <id|name>] [--harness claude,codex,dsh] [--into <dir>]
|
|
8914
9012
|
|
|
8915
9013
|
list the skills the platform serves you: in every organization you can act in, the skills whose tools you can run
|
|
8916
|
-
install write them, and the CLI's own skills ("diverge"; "drive-chrome" for dsh), into each harness's
|
|
8917
|
-
|
|
8918
|
-
|
|
9014
|
+
install write them, and the CLI's own skills ("diverge"; "drive-chrome" for dsh), into each harness's skill folder:
|
|
9015
|
+
~/.claude/skills and ~/.codex/skills side by side under each organization's prefix; for dsh one folder
|
|
9016
|
+
per organization and one for the CLI's under ~/.diverge/skills/dsh, of which a diverge dsh launch names
|
|
9017
|
+
its organization's and the CLI's; retires what an organization stopped serving; reports what changed \u2014
|
|
9018
|
+
the full list is \`skills list\`
|
|
8919
9019
|
refresh the same, best effort: no login, no network or nothing changed prints nothing and never fails.
|
|
8920
9020
|
Runs at sign-in and at every session start, so the folders hold what the organizations serve now
|
|
8921
9021
|
status what each folder holds against what the platform serves now
|
|
@@ -8980,7 +9080,7 @@ function installReport(harness, result) {
|
|
|
8980
9080
|
return `${harness}: ${result.written.length} skills in ${result.root} (${holdings}${changes.length ? `; ${changes.join("; ")}` : "; unchanged"})`;
|
|
8981
9081
|
}
|
|
8982
9082
|
function installForHarness(io, harness, skills, apiUrl, into) {
|
|
8983
|
-
const result =
|
|
9083
|
+
const result = installHarness(harness, into ?? skillsRoot(harness, io.env), installSet(harness, skills), apiUrl, io.env);
|
|
8984
9084
|
io.stdout(installReport(harness, result));
|
|
8985
9085
|
return result;
|
|
8986
9086
|
}
|
|
@@ -8999,7 +9099,7 @@ async function refreshSkills(io, apiUrl, options = {}) {
|
|
|
8999
9099
|
}
|
|
9000
9100
|
const results = [];
|
|
9001
9101
|
for (const harness of harnesses) {
|
|
9002
|
-
const result =
|
|
9102
|
+
const result = installHarness(harness, skillsRoot(harness, io.env), installSet(harness, skills), apiUrl, io.env);
|
|
9003
9103
|
if (!options.quiet || result.added.length || result.updated.length || result.removed.length) io.stdout(installReport(harness, result));
|
|
9004
9104
|
results.push(result);
|
|
9005
9105
|
}
|
|
@@ -9037,7 +9137,7 @@ async function runSkills(args, io) {
|
|
|
9037
9137
|
const skills = await loginSkillSet(apiUrl, io.env, organizationId);
|
|
9038
9138
|
let behind = false;
|
|
9039
9139
|
for (const harness of harnessesOf(values.harness, io.env)) {
|
|
9040
|
-
const status2 =
|
|
9140
|
+
const status2 = harnessStatus(harness, values.into ?? skillsRoot(harness, io.env), installSet(harness, skills), io.env);
|
|
9041
9141
|
const parts = [`${status2.current.length} current`];
|
|
9042
9142
|
if (status2.behind.length) parts.push(`${status2.behind.length} behind (${few(status2.behind)})`);
|
|
9043
9143
|
if (status2.missing.length) parts.push(`${status2.missing.length} missing${status2.current.length || status2.behind.length ? ` (${few(status2.missing)})` : ""}`);
|
|
@@ -10327,7 +10427,7 @@ function savedModel(home, surface) {
|
|
|
10327
10427
|
throw new CliError(`${file}: ${error instanceof Error ? error.message : String(error)}`);
|
|
10328
10428
|
}
|
|
10329
10429
|
}
|
|
10330
|
-
async function overlayAndDefault(io, apiUrl, token, surface, requested, saved, launch, hooks) {
|
|
10430
|
+
async function overlayAndDefault(io, apiUrl, token, surface, requested, saved, launch, hooks, skillDirs) {
|
|
10331
10431
|
const served = (await listModels(apiUrl, token.access_token, surface)).map(servedModel);
|
|
10332
10432
|
const models = served.map((model) => model.id);
|
|
10333
10433
|
if (models.length === 0) throw new CliError(`the gateway serves no models on the ${surface} surface for this organization`);
|
|
@@ -10335,7 +10435,7 @@ async function overlayAndDefault(io, apiUrl, token, surface, requested, saved, l
|
|
|
10335
10435
|
const usable = !requested && saved && models.includes(saved.model) ? saved : null;
|
|
10336
10436
|
const defaultModel = dshDefaultModel(models, requested ?? usable?.model);
|
|
10337
10437
|
if (!requested && saved && !usable) io.stderr(`The model you last chose, ${saved.model}, is no longer served here; using ${defaultModel}.`);
|
|
10338
|
-
return { overlay: dshPatchYaml({ baseUrl: surfaceBaseUrl(apiUrl, surface), surface, models: served, defaultModel, reasoningEffort: usable?.reasoningEffort, launch, hooks }), defaultModel };
|
|
10438
|
+
return { overlay: dshPatchYaml({ baseUrl: surfaceBaseUrl(apiUrl, surface), surface, models: served, defaultModel, reasoningEffort: usable?.reasoningEffort, launch, hooks, skillDirs }), defaultModel };
|
|
10339
10439
|
}
|
|
10340
10440
|
async function runDshCommand(args, io) {
|
|
10341
10441
|
const terminator = args.indexOf("--");
|
|
@@ -10354,21 +10454,22 @@ async function runDshCommand(args, io) {
|
|
|
10354
10454
|
const token = await ensureInferenceLogin(io, apiUrl, values["organization-id"]);
|
|
10355
10455
|
const dsh = await ensureDsh(io);
|
|
10356
10456
|
const prefix = path18.join(dshInstallRoot(io.env), TESTED_DSH_VERSION);
|
|
10357
|
-
|
|
10457
|
+
const organizationId = tokenClaims(token.access_token).organizationId ?? values["organization-id"];
|
|
10458
|
+
if (!organizationId) throw new CliError("the gateway token names no organization; pass --organization-id");
|
|
10459
|
+
await skillsFor(io, apiUrl, "dsh", organizationId);
|
|
10460
|
+
const skillDirs = dshSkillDirs(organizationId, io.env);
|
|
10358
10461
|
const launch = { id: randomUUID(), client: `dsh/${TESTED_DSH_VERSION}` };
|
|
10359
10462
|
const home = dshHome(io.env);
|
|
10360
10463
|
const bridge = dshHookBridgeIn(prefix);
|
|
10361
10464
|
const configPath = bridge ? repositoryHookConfig(process.cwd()) : null;
|
|
10362
10465
|
const hooks = bridge && configPath ? { bridge, configPath } : null;
|
|
10363
|
-
const { overlay, defaultModel } = await overlayAndDefault(io, apiUrl, token, surface, values.model, savedModel(home, surface), launch, hooks);
|
|
10466
|
+
const { overlay, defaultModel } = await overlayAndDefault(io, apiUrl, token, surface, values.model, savedModel(home, surface), launch, hooks, skillDirs);
|
|
10364
10467
|
const overlayPath = path18.join(home, `divergent-${surface}.yml`);
|
|
10365
|
-
writeTextAtomic(overlayPath, `${overlay}${dshPresetOverrides(prefix)}`);
|
|
10468
|
+
writeTextAtomic(overlayPath, `${overlay}${dshPresetOverrides(prefix, skillDirs)}`);
|
|
10366
10469
|
io.stderr(`dsh ${TESTED_DSH_VERSION} on divergent-${surface} as you (organization ${tokenClaims(token.access_token).organizationId}), default model ${defaultModel}`);
|
|
10367
10470
|
if (hooks) io.stderr(`Running this repository's hooks (${hooks.configPath}).`);
|
|
10368
10471
|
if (passthrough.length === 0) io.stderr('Starting the web UI; open the URL dsh prints. For one task without the UI: diverge dsh -- "<task>"');
|
|
10369
10472
|
const source = tokenSource(io.env, apiUrl);
|
|
10370
|
-
const organizationId = tokenClaims(token.access_token).organizationId ?? values["organization-id"];
|
|
10371
|
-
if (!organizationId) throw new CliError("the gateway token names no organization; pass --organization-id");
|
|
10372
10473
|
io.stderr(`This session is organization ${organizationId}'s own record at the level its administrators set \u2014 off, metadata (tools, tokens, models; no content) or the whole conversation \u2014 named once its record opens. Yours to read: diverge tools call ${AGENT_SESSION_LIST_TOOL} (ADR 0121).`);
|
|
10373
10474
|
const tools = new ToolsClient({ apiUrl, organizationId, mode: "operator", clientId: clientId(io.env) }, io.env);
|
|
10374
10475
|
const publisher = new DshSessionPublisher({
|
package/package.json
CHANGED