@t2000/cli 9.0.0 → 9.1.0
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/dist/index.js
CHANGED
|
@@ -33689,6 +33689,475 @@ function registerModels(program3) {
|
|
|
33689
33689
|
});
|
|
33690
33690
|
}
|
|
33691
33691
|
|
|
33692
|
+
// src/commands/connect/index.ts
|
|
33693
|
+
import { readFileSync as readFileSync3, writeFileSync as writeFileSync3, mkdirSync as mkdirSync2, existsSync as existsSync3, appendFileSync } from "fs";
|
|
33694
|
+
import { dirname as dirname3, join as join5 } from "path";
|
|
33695
|
+
import { homedir as homedir4 } from "os";
|
|
33696
|
+
|
|
33697
|
+
// src/commands/connect/clients.ts
|
|
33698
|
+
import { join as join4 } from "path";
|
|
33699
|
+
import { homedir as homedir3 } from "os";
|
|
33700
|
+
var API_BASE = "https://api.t2000.ai/v1";
|
|
33701
|
+
var CHAT_COMPLETIONS_URL = `${API_BASE}/chat/completions`;
|
|
33702
|
+
var DEFAULT_MODEL = "t2000/auto";
|
|
33703
|
+
var OPEN_MODEL = "t2000/auto-open";
|
|
33704
|
+
var CONSOLE_KEYS_URL = "https://agents.t2000.ai/manage";
|
|
33705
|
+
var CONNECT_CLIENTS = [
|
|
33706
|
+
{
|
|
33707
|
+
slug: "t2code",
|
|
33708
|
+
name: "t2 code",
|
|
33709
|
+
aliases: ["code"],
|
|
33710
|
+
blurb: "the t2000 coding agent (npm i -g @t2000/code) \u2014 saves your key"
|
|
33711
|
+
},
|
|
33712
|
+
{
|
|
33713
|
+
slug: "claude-code",
|
|
33714
|
+
name: "Claude Code (via claude-code-router)",
|
|
33715
|
+
aliases: ["ccr", "claude"],
|
|
33716
|
+
blurb: "adds a t2000 provider to ~/.claude-code-router"
|
|
33717
|
+
},
|
|
33718
|
+
{
|
|
33719
|
+
slug: "continue",
|
|
33720
|
+
name: "Continue",
|
|
33721
|
+
aliases: [],
|
|
33722
|
+
blurb: "model entry for ~/.continue/config.yaml"
|
|
33723
|
+
},
|
|
33724
|
+
{
|
|
33725
|
+
slug: "aider",
|
|
33726
|
+
name: "Aider",
|
|
33727
|
+
aliases: [],
|
|
33728
|
+
blurb: "OpenAI-compatible base + model for ~/.aider.conf.yml"
|
|
33729
|
+
},
|
|
33730
|
+
{
|
|
33731
|
+
slug: "codex",
|
|
33732
|
+
name: "OpenAI Codex CLI",
|
|
33733
|
+
aliases: [],
|
|
33734
|
+
blurb: "t2000 provider profile in ~/.codex/config.toml"
|
|
33735
|
+
},
|
|
33736
|
+
{
|
|
33737
|
+
slug: "cline",
|
|
33738
|
+
name: "Cline",
|
|
33739
|
+
aliases: [],
|
|
33740
|
+
blurb: "settings walkthrough (GUI-managed config)"
|
|
33741
|
+
},
|
|
33742
|
+
{
|
|
33743
|
+
slug: "cursor",
|
|
33744
|
+
name: "Cursor",
|
|
33745
|
+
aliases: [],
|
|
33746
|
+
blurb: "settings walkthrough (GUI-managed config)"
|
|
33747
|
+
}
|
|
33748
|
+
];
|
|
33749
|
+
function resolveClientSlug(input) {
|
|
33750
|
+
const needle = input.toLowerCase();
|
|
33751
|
+
for (const c of CONNECT_CLIENTS) {
|
|
33752
|
+
if (c.slug === needle || c.aliases.includes(needle)) return c.slug;
|
|
33753
|
+
}
|
|
33754
|
+
return void 0;
|
|
33755
|
+
}
|
|
33756
|
+
function t2codeCredentialsPath(home = homedir3()) {
|
|
33757
|
+
return join4(home, ".config", "t2code", "credentials.json");
|
|
33758
|
+
}
|
|
33759
|
+
function withT2codeKey(existing, key) {
|
|
33760
|
+
return {
|
|
33761
|
+
...existing,
|
|
33762
|
+
default: {
|
|
33763
|
+
name: "t2000",
|
|
33764
|
+
email: "",
|
|
33765
|
+
...typeof existing.default === "object" && existing.default !== null ? existing.default : {},
|
|
33766
|
+
authToken: key
|
|
33767
|
+
}
|
|
33768
|
+
};
|
|
33769
|
+
}
|
|
33770
|
+
function t2codeHasKey(existing, key) {
|
|
33771
|
+
return existing.default?.authToken === key;
|
|
33772
|
+
}
|
|
33773
|
+
function ccrDir(home = homedir3()) {
|
|
33774
|
+
return join4(home, ".claude-code-router");
|
|
33775
|
+
}
|
|
33776
|
+
function ccrSqlitePath(home = homedir3()) {
|
|
33777
|
+
return join4(ccrDir(home), "config.sqlite");
|
|
33778
|
+
}
|
|
33779
|
+
function ccrConfigJsonPath(home = homedir3()) {
|
|
33780
|
+
return join4(ccrDir(home), "config.json");
|
|
33781
|
+
}
|
|
33782
|
+
function withCcrProvider(existing, key) {
|
|
33783
|
+
const provider = {
|
|
33784
|
+
name: "t2000",
|
|
33785
|
+
api_base_url: CHAT_COMPLETIONS_URL,
|
|
33786
|
+
api_key: key,
|
|
33787
|
+
models: [DEFAULT_MODEL, OPEN_MODEL]
|
|
33788
|
+
};
|
|
33789
|
+
const providers = Array.isArray(existing.Providers) ? [...existing.Providers] : [];
|
|
33790
|
+
const idx = providers.findIndex((p) => p?.name === "t2000");
|
|
33791
|
+
if (idx >= 0) providers[idx] = { ...providers[idx], ...provider };
|
|
33792
|
+
else providers.push(provider);
|
|
33793
|
+
const router = { ...existing.Router ?? {} };
|
|
33794
|
+
if (!router.default) router.default = `t2000,${DEFAULT_MODEL}`;
|
|
33795
|
+
return { ...existing, Providers: providers, Router: router };
|
|
33796
|
+
}
|
|
33797
|
+
function ccrHasProvider(existing) {
|
|
33798
|
+
return Array.isArray(existing.Providers) && existing.Providers.some((p) => p?.name === "t2000");
|
|
33799
|
+
}
|
|
33800
|
+
function continueConfigPath(home = homedir3()) {
|
|
33801
|
+
return join4(home, ".continue", "config.yaml");
|
|
33802
|
+
}
|
|
33803
|
+
function continueModelYaml(key) {
|
|
33804
|
+
return [
|
|
33805
|
+
` - name: t2000 auto`,
|
|
33806
|
+
` provider: openai`,
|
|
33807
|
+
` model: ${DEFAULT_MODEL}`,
|
|
33808
|
+
` apiBase: ${API_BASE}`,
|
|
33809
|
+
` apiKey: ${key}`,
|
|
33810
|
+
` roles:`,
|
|
33811
|
+
` - chat`,
|
|
33812
|
+
` - edit`,
|
|
33813
|
+
` - apply`
|
|
33814
|
+
].join("\n");
|
|
33815
|
+
}
|
|
33816
|
+
function continueFreshConfigYaml(key) {
|
|
33817
|
+
return [
|
|
33818
|
+
`name: t2000 Private Inference`,
|
|
33819
|
+
`version: 0.0.1`,
|
|
33820
|
+
`schema: v1`,
|
|
33821
|
+
``,
|
|
33822
|
+
`models:`,
|
|
33823
|
+
continueModelYaml(key),
|
|
33824
|
+
``
|
|
33825
|
+
].join("\n");
|
|
33826
|
+
}
|
|
33827
|
+
function aiderConfPath(home = homedir3()) {
|
|
33828
|
+
return join4(home, ".aider.conf.yml");
|
|
33829
|
+
}
|
|
33830
|
+
function aiderConfYaml(key) {
|
|
33831
|
+
return [
|
|
33832
|
+
`# t2000 Private Inference (written by \`t2 connect aider\`)`,
|
|
33833
|
+
`openai-api-base: ${API_BASE}`,
|
|
33834
|
+
`openai-api-key: ${key}`,
|
|
33835
|
+
`model: openai/${DEFAULT_MODEL}`,
|
|
33836
|
+
``
|
|
33837
|
+
].join("\n");
|
|
33838
|
+
}
|
|
33839
|
+
function codexConfigPath(home = homedir3()) {
|
|
33840
|
+
return join4(home, ".codex", "config.toml");
|
|
33841
|
+
}
|
|
33842
|
+
function codexTomlBlock() {
|
|
33843
|
+
return [
|
|
33844
|
+
``,
|
|
33845
|
+
`# t2000 Private Inference (written by \`t2 connect codex\`)`,
|
|
33846
|
+
`[model_providers.t2000]`,
|
|
33847
|
+
`name = "t2000"`,
|
|
33848
|
+
`base_url = "${API_BASE}"`,
|
|
33849
|
+
`env_key = "T2000_API_KEY"`,
|
|
33850
|
+
``,
|
|
33851
|
+
`[profiles.t2000]`,
|
|
33852
|
+
`model = "${DEFAULT_MODEL}"`,
|
|
33853
|
+
`model_provider = "t2000"`,
|
|
33854
|
+
``
|
|
33855
|
+
].join("\n");
|
|
33856
|
+
}
|
|
33857
|
+
function codexHasProvider(existingToml) {
|
|
33858
|
+
return existingToml.includes("[model_providers.t2000]");
|
|
33859
|
+
}
|
|
33860
|
+
|
|
33861
|
+
// src/commands/connect/index.ts
|
|
33862
|
+
function t2000ConfigPath() {
|
|
33863
|
+
return join5(homedir4(), ".t2000", "config.json");
|
|
33864
|
+
}
|
|
33865
|
+
function loadSavedKey() {
|
|
33866
|
+
try {
|
|
33867
|
+
const raw = JSON.parse(readFileSync3(t2000ConfigPath(), "utf-8"));
|
|
33868
|
+
const inference = raw.inference;
|
|
33869
|
+
if (typeof inference === "object" && inference !== null) {
|
|
33870
|
+
const key = inference.apiKey;
|
|
33871
|
+
if (typeof key === "string" && key.length > 0) return key;
|
|
33872
|
+
}
|
|
33873
|
+
} catch {
|
|
33874
|
+
}
|
|
33875
|
+
return void 0;
|
|
33876
|
+
}
|
|
33877
|
+
function saveKey2(key) {
|
|
33878
|
+
const path2 = t2000ConfigPath();
|
|
33879
|
+
let existing = {};
|
|
33880
|
+
try {
|
|
33881
|
+
existing = JSON.parse(readFileSync3(path2, "utf-8"));
|
|
33882
|
+
} catch {
|
|
33883
|
+
existing = {};
|
|
33884
|
+
}
|
|
33885
|
+
const merged = { ...existing, inference: { apiKey: key } };
|
|
33886
|
+
if (!existsSync3(dirname3(path2))) mkdirSync2(dirname3(path2), { recursive: true });
|
|
33887
|
+
writeFileSync3(path2, JSON.stringify(merged, null, 2) + "\n", { mode: 384 });
|
|
33888
|
+
}
|
|
33889
|
+
function resolveKey(flagKey) {
|
|
33890
|
+
if (flagKey && flagKey.trim().length > 0) return { key: flagKey.trim(), source: "--key" };
|
|
33891
|
+
const envKey = process.env.T2000_API_KEY;
|
|
33892
|
+
if (envKey && envKey.trim().length > 0) return { key: envKey.trim(), source: "T2000_API_KEY" };
|
|
33893
|
+
const saved = loadSavedKey();
|
|
33894
|
+
if (saved) return { key: saved, source: "~/.t2000/config.json" };
|
|
33895
|
+
return { source: "none" };
|
|
33896
|
+
}
|
|
33897
|
+
function readJson(path2) {
|
|
33898
|
+
try {
|
|
33899
|
+
return JSON.parse(readFileSync3(path2, "utf-8"));
|
|
33900
|
+
} catch {
|
|
33901
|
+
return {};
|
|
33902
|
+
}
|
|
33903
|
+
}
|
|
33904
|
+
function writeFileEnsuringDir(path2, contents, mode) {
|
|
33905
|
+
const dir = dirname3(path2);
|
|
33906
|
+
if (!existsSync3(dir)) mkdirSync2(dir, { recursive: true });
|
|
33907
|
+
writeFileSync3(path2, contents, mode !== void 0 ? { mode } : void 0);
|
|
33908
|
+
}
|
|
33909
|
+
function connectT2code(key, print2) {
|
|
33910
|
+
const path2 = t2codeCredentialsPath();
|
|
33911
|
+
const existing = readJson(path2);
|
|
33912
|
+
if (t2codeHasKey(existing, key)) {
|
|
33913
|
+
return { client: "t2code", action: "exists", path: path2, detail: "already connected with this key" };
|
|
33914
|
+
}
|
|
33915
|
+
if (print2) {
|
|
33916
|
+
return {
|
|
33917
|
+
client: "t2code",
|
|
33918
|
+
action: "snippet",
|
|
33919
|
+
path: path2,
|
|
33920
|
+
detail: "would write the key into t2 code credentials",
|
|
33921
|
+
text: `Would set default.authToken in ${path2}`
|
|
33922
|
+
};
|
|
33923
|
+
}
|
|
33924
|
+
writeFileEnsuringDir(path2, JSON.stringify(withT2codeKey(existing, key), null, 2), 384);
|
|
33925
|
+
return {
|
|
33926
|
+
client: "t2code",
|
|
33927
|
+
action: "written",
|
|
33928
|
+
path: path2,
|
|
33929
|
+
detail: "key saved \u2014 run `t2code` (or `npm i -g @t2000/code` first)"
|
|
33930
|
+
};
|
|
33931
|
+
}
|
|
33932
|
+
function connectClaudeCode(key, print2) {
|
|
33933
|
+
const sqlite = ccrSqlitePath();
|
|
33934
|
+
if (existsSync3(sqlite)) {
|
|
33935
|
+
return {
|
|
33936
|
+
client: "claude-code",
|
|
33937
|
+
action: "instructions",
|
|
33938
|
+
detail: "claude-code-router already manages config in SQLite \u2014 add the provider in its UI",
|
|
33939
|
+
text: [
|
|
33940
|
+
`claude-code-router found (SQLite config). Add the provider in the ccr UI:`,
|
|
33941
|
+
` Providers \u2192 Add Provider \u2192 Other / custom API endpoint`,
|
|
33942
|
+
` name: t2000`,
|
|
33943
|
+
` base URL: ${API_BASE}/chat/completions`,
|
|
33944
|
+
` protocol: OpenAI`,
|
|
33945
|
+
` API key: ${key}`,
|
|
33946
|
+
` models: ${DEFAULT_MODEL}`,
|
|
33947
|
+
` Then set the default route to t2000,${DEFAULT_MODEL}.`
|
|
33948
|
+
].join("\n")
|
|
33949
|
+
};
|
|
33950
|
+
}
|
|
33951
|
+
const path2 = ccrConfigJsonPath();
|
|
33952
|
+
const existing = readJson(path2);
|
|
33953
|
+
const already = ccrHasProvider(existing);
|
|
33954
|
+
if (print2) {
|
|
33955
|
+
return {
|
|
33956
|
+
client: "claude-code",
|
|
33957
|
+
action: "snippet",
|
|
33958
|
+
path: path2,
|
|
33959
|
+
detail: already ? "t2000 provider already present" : "would add the t2000 provider",
|
|
33960
|
+
text: JSON.stringify(withCcrProvider(existing, key), null, 2)
|
|
33961
|
+
};
|
|
33962
|
+
}
|
|
33963
|
+
writeFileEnsuringDir(path2, JSON.stringify(withCcrProvider(existing, key), null, 2) + "\n", 384);
|
|
33964
|
+
return {
|
|
33965
|
+
client: "claude-code",
|
|
33966
|
+
action: "written",
|
|
33967
|
+
path: path2,
|
|
33968
|
+
detail: already ? "t2000 provider refreshed \u2014 install ccr (npm i -g @musistudio/claude-code-router), then `ccr code`" : "t2000 provider added \u2014 install ccr (npm i -g @musistudio/claude-code-router), then `ccr code`"
|
|
33969
|
+
};
|
|
33970
|
+
}
|
|
33971
|
+
function connectContinue(key, print2) {
|
|
33972
|
+
const path2 = continueConfigPath();
|
|
33973
|
+
if (!existsSync3(path2) && !print2) {
|
|
33974
|
+
writeFileEnsuringDir(path2, continueFreshConfigYaml(key), 384);
|
|
33975
|
+
return { client: "continue", action: "written", path: path2, detail: "config.yaml created" };
|
|
33976
|
+
}
|
|
33977
|
+
return {
|
|
33978
|
+
client: "continue",
|
|
33979
|
+
action: "snippet",
|
|
33980
|
+
path: path2,
|
|
33981
|
+
detail: existsSync3(path2) ? "config.yaml exists \u2014 paste this model block under `models:`" : "would create config.yaml with this model block",
|
|
33982
|
+
text: continueModelYaml(key)
|
|
33983
|
+
};
|
|
33984
|
+
}
|
|
33985
|
+
function connectAider(key, print2) {
|
|
33986
|
+
const path2 = aiderConfPath();
|
|
33987
|
+
if (!existsSync3(path2) && !print2) {
|
|
33988
|
+
writeFileEnsuringDir(path2, aiderConfYaml(key), 384);
|
|
33989
|
+
return { client: "aider", action: "written", path: path2, detail: ".aider.conf.yml created" };
|
|
33990
|
+
}
|
|
33991
|
+
return {
|
|
33992
|
+
client: "aider",
|
|
33993
|
+
action: "snippet",
|
|
33994
|
+
path: path2,
|
|
33995
|
+
detail: existsSync3(path2) ? ".aider.conf.yml exists \u2014 add these lines (or use the flags below)" : "would create .aider.conf.yml",
|
|
33996
|
+
text: aiderConfYaml(key) + `
|
|
33997
|
+
# or without touching the file:
|
|
33998
|
+
# aider --openai-api-base ${API_BASE} --openai-api-key ${key} --model openai/${DEFAULT_MODEL}`
|
|
33999
|
+
};
|
|
34000
|
+
}
|
|
34001
|
+
function connectCodex(key, print2) {
|
|
34002
|
+
const path2 = codexConfigPath();
|
|
34003
|
+
const existing = existsSync3(path2) ? readFileSync3(path2, "utf-8") : "";
|
|
34004
|
+
if (codexHasProvider(existing)) {
|
|
34005
|
+
return {
|
|
34006
|
+
client: "codex",
|
|
34007
|
+
action: "exists",
|
|
34008
|
+
path: path2,
|
|
34009
|
+
detail: "t2000 provider already in config.toml \u2014 run `codex --profile t2000`"
|
|
34010
|
+
};
|
|
34011
|
+
}
|
|
34012
|
+
if (print2) {
|
|
34013
|
+
return {
|
|
34014
|
+
client: "codex",
|
|
34015
|
+
action: "snippet",
|
|
34016
|
+
path: path2,
|
|
34017
|
+
detail: "would append the t2000 provider + profile",
|
|
34018
|
+
text: codexTomlBlock()
|
|
34019
|
+
};
|
|
34020
|
+
}
|
|
34021
|
+
if (existsSync3(path2)) appendFileSync(path2, codexTomlBlock());
|
|
34022
|
+
else writeFileEnsuringDir(path2, codexTomlBlock().trimStart(), 384);
|
|
34023
|
+
return {
|
|
34024
|
+
client: "codex",
|
|
34025
|
+
action: "written",
|
|
34026
|
+
path: path2,
|
|
34027
|
+
detail: `provider + profile added \u2014 export T2000_API_KEY=${maskKey(key)} then \`codex --profile t2000\``
|
|
34028
|
+
};
|
|
34029
|
+
}
|
|
34030
|
+
function connectCline(key) {
|
|
34031
|
+
return {
|
|
34032
|
+
client: "cline",
|
|
34033
|
+
action: "instructions",
|
|
34034
|
+
detail: "Cline stores provider config in VS Code \u2014 set it in the extension settings",
|
|
34035
|
+
text: [
|
|
34036
|
+
`In Cline settings, choose the "OpenAI Compatible" API provider:`,
|
|
34037
|
+
` Base URL: ${API_BASE}`,
|
|
34038
|
+
` API key: ${key}`,
|
|
34039
|
+
` Model ID: ${DEFAULT_MODEL}`
|
|
34040
|
+
].join("\n")
|
|
34041
|
+
};
|
|
34042
|
+
}
|
|
34043
|
+
function connectCursor(key) {
|
|
34044
|
+
return {
|
|
34045
|
+
client: "cursor",
|
|
34046
|
+
action: "instructions",
|
|
34047
|
+
detail: "Cursor is configured in Settings \u2014 no file to write",
|
|
34048
|
+
text: [
|
|
34049
|
+
`Cursor \u2192 Settings \u2192 Models \u2192 API Keys:`,
|
|
34050
|
+
` 1. Paste the key into "OpenAI API Key": ${maskKey(key)}`,
|
|
34051
|
+
` 2. Expand "Override OpenAI Base URL" and set: ${API_BASE}`,
|
|
34052
|
+
` 3. Under Models, add \`${DEFAULT_MODEL}\`, then Verify.`,
|
|
34053
|
+
`Note: Cursor's agent features are tuned for its own models \u2014 use this`,
|
|
34054
|
+
`for private chat models; delegation runs through t2 code.`
|
|
34055
|
+
].join("\n")
|
|
34056
|
+
};
|
|
34057
|
+
}
|
|
34058
|
+
function maskKey(key) {
|
|
34059
|
+
return key.length > 8 ? `${key.slice(0, 5)}\u2026${key.slice(-3)}` : "sk-\u2026";
|
|
34060
|
+
}
|
|
34061
|
+
function runConnect(slug, key, print2) {
|
|
34062
|
+
switch (slug) {
|
|
34063
|
+
case "t2code":
|
|
34064
|
+
return connectT2code(key, print2);
|
|
34065
|
+
case "claude-code":
|
|
34066
|
+
return connectClaudeCode(key, print2);
|
|
34067
|
+
case "continue":
|
|
34068
|
+
return connectContinue(key, print2);
|
|
34069
|
+
case "aider":
|
|
34070
|
+
return connectAider(key, print2);
|
|
34071
|
+
case "codex":
|
|
34072
|
+
return connectCodex(key, print2);
|
|
34073
|
+
case "cline":
|
|
34074
|
+
return connectCline(key);
|
|
34075
|
+
case "cursor":
|
|
34076
|
+
return connectCursor(key);
|
|
34077
|
+
}
|
|
34078
|
+
}
|
|
34079
|
+
function registerConnect(program3) {
|
|
34080
|
+
program3.command("connect").description("Point a coding tool at Private Inference (api.t2000.ai/v1) with your key").argument("[client]", "client to connect: t2code | claude-code | continue | aider | codex | cline | cursor").option("--key <sk-key>", `Private Inference key (create one at ${CONSOLE_KEYS_URL})`).option("--print", "Show what would be written / the paste snippet, without writing").addHelpText(
|
|
34081
|
+
"after",
|
|
34082
|
+
`
|
|
34083
|
+
Examples:
|
|
34084
|
+
$ t2 connect List supported clients
|
|
34085
|
+
$ t2 connect t2code --key sk-... Save your key into t2 code
|
|
34086
|
+
$ t2 connect claude-code Add the t2000 provider to claude-code-router
|
|
34087
|
+
$ t2 connect aider --print Show the aider config without writing it
|
|
34088
|
+
|
|
34089
|
+
The key comes from the console: sign in at ${CONSOLE_KEYS_URL}
|
|
34090
|
+
(Google), create an API key, paste it once \u2014 it is saved to ~/.t2000/config.json
|
|
34091
|
+
and reused by later connects. All clients get model ${DEFAULT_MODEL} (the router;
|
|
34092
|
+
you pay the price of the model that actually served each request).`
|
|
34093
|
+
).action(async (clientArg, opts) => {
|
|
34094
|
+
try {
|
|
34095
|
+
if (!clientArg) {
|
|
34096
|
+
const { key: key2 } = resolveKey(opts.key);
|
|
34097
|
+
if (isJsonMode()) {
|
|
34098
|
+
printJson({
|
|
34099
|
+
clients: CONNECT_CLIENTS.map((c) => ({ slug: c.slug, name: c.name, blurb: c.blurb })),
|
|
34100
|
+
keySaved: !!key2
|
|
34101
|
+
});
|
|
34102
|
+
return;
|
|
34103
|
+
}
|
|
34104
|
+
printBlank();
|
|
34105
|
+
printLine(" Connect a coding tool to Private Inference:");
|
|
34106
|
+
printBlank();
|
|
34107
|
+
for (const c of CONNECT_CLIENTS) {
|
|
34108
|
+
printKeyValue(c.slug.padEnd(12), c.blurb);
|
|
34109
|
+
}
|
|
34110
|
+
printBlank();
|
|
34111
|
+
printInfo(`Usage: t2 connect <client> [--key sk-...]`);
|
|
34112
|
+
printInfo(
|
|
34113
|
+
key2 ? "A key is saved \u2014 connects will reuse it." : `No key yet \u2014 create one at ${CONSOLE_KEYS_URL}`
|
|
34114
|
+
);
|
|
34115
|
+
printBlank();
|
|
34116
|
+
return;
|
|
34117
|
+
}
|
|
34118
|
+
const slug = resolveClientSlug(clientArg);
|
|
34119
|
+
if (!slug) {
|
|
34120
|
+
printWarning(`Unknown client '${clientArg}'.`);
|
|
34121
|
+
printInfo(`Supported: ${CONNECT_CLIENTS.map((c) => c.slug).join(" \xB7 ")}`);
|
|
34122
|
+
process.exitCode = 1;
|
|
34123
|
+
return;
|
|
34124
|
+
}
|
|
34125
|
+
const { key, source } = resolveKey(opts.key);
|
|
34126
|
+
if (!key) {
|
|
34127
|
+
printBlank();
|
|
34128
|
+
printWarning("No API key found.");
|
|
34129
|
+
printInfo(`1. Sign in at ${CONSOLE_KEYS_URL} (Google) and create an API key`);
|
|
34130
|
+
printInfo(`2. Re-run: t2 connect ${slug} --key sk-...`);
|
|
34131
|
+
printBlank();
|
|
34132
|
+
process.exitCode = 1;
|
|
34133
|
+
return;
|
|
34134
|
+
}
|
|
34135
|
+
const result = runConnect(slug, key, !!opts.print);
|
|
34136
|
+
if (!opts.print && source !== "~/.t2000/config.json") saveKey2(key);
|
|
34137
|
+
if (isJsonMode()) {
|
|
34138
|
+
printJson({ ...result, keySource: source });
|
|
34139
|
+
return;
|
|
34140
|
+
}
|
|
34141
|
+
printBlank();
|
|
34142
|
+
if (result.action === "written") {
|
|
34143
|
+
printSuccess(`${slug}: ${result.detail}`);
|
|
34144
|
+
if (result.path) printKeyValue("wrote", result.path);
|
|
34145
|
+
} else if (result.action === "exists") {
|
|
34146
|
+
printInfo(`${slug}: ${result.detail}`);
|
|
34147
|
+
} else {
|
|
34148
|
+
printInfo(`${slug}: ${result.detail}`);
|
|
34149
|
+
}
|
|
34150
|
+
if (result.text) {
|
|
34151
|
+
printBlank();
|
|
34152
|
+
for (const line of result.text.split("\n")) printLine(` ${line}`);
|
|
34153
|
+
}
|
|
34154
|
+
printBlank();
|
|
34155
|
+
} catch (error) {
|
|
34156
|
+
handleError(error);
|
|
34157
|
+
}
|
|
34158
|
+
});
|
|
34159
|
+
}
|
|
34160
|
+
|
|
33692
34161
|
// src/commands/verify.ts
|
|
33693
34162
|
var import_picocolors10 = __toESM(require_picocolors(), 1);
|
|
33694
34163
|
function mark(check2) {
|
|
@@ -34121,7 +34590,7 @@ function registerMcpStart(parent) {
|
|
|
34121
34590
|
parent.command("start", { isDefault: true }).description("Start MCP server (stdio transport \u2014 for AI client integration)").option("--key <path>", "Custom wallet path (default ~/.t2000/wallet.key)").action(async (opts) => {
|
|
34122
34591
|
let mod3;
|
|
34123
34592
|
try {
|
|
34124
|
-
mod3 = await import("./dist-
|
|
34593
|
+
mod3 = await import("./dist-RTG3A7CI.js");
|
|
34125
34594
|
} catch {
|
|
34126
34595
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
34127
34596
|
process.exit(1);
|
|
@@ -34172,12 +34641,12 @@ function registerMcpInstall(parent) {
|
|
|
34172
34641
|
}
|
|
34173
34642
|
|
|
34174
34643
|
// src/commands/mcp/uninstall.ts
|
|
34175
|
-
import { existsSync as
|
|
34644
|
+
import { existsSync as existsSync4 } from "fs";
|
|
34176
34645
|
async function runUninstall() {
|
|
34177
34646
|
const platforms = getPlatformConfigs();
|
|
34178
34647
|
const results = [];
|
|
34179
34648
|
for (const platform of platforms) {
|
|
34180
|
-
if (!
|
|
34649
|
+
if (!existsSync4(platform.path)) {
|
|
34181
34650
|
results.push({ name: platform.name, slug: platform.slug, removed: false });
|
|
34182
34651
|
continue;
|
|
34183
34652
|
}
|
|
@@ -34233,12 +34702,12 @@ Subcommands:
|
|
|
34233
34702
|
|
|
34234
34703
|
// src/commands/skills/check.ts
|
|
34235
34704
|
import { readdir, readFile as readFile3 } from "fs/promises";
|
|
34236
|
-
import { join as
|
|
34705
|
+
import { join as join7 } from "path";
|
|
34237
34706
|
|
|
34238
34707
|
// src/commands/skills/lib.ts
|
|
34239
34708
|
import { stat } from "fs/promises";
|
|
34240
|
-
import { join as
|
|
34241
|
-
import { homedir as
|
|
34709
|
+
import { join as join6 } from "path";
|
|
34710
|
+
import { homedir as homedir5 } from "os";
|
|
34242
34711
|
var MANIFEST_URL = "https://t2000.ai/.well-known/agent-skills/index.json";
|
|
34243
34712
|
var SKILL_PREFIXES = ["t2000-", "mpp-"];
|
|
34244
34713
|
function isManagedSkillName(name) {
|
|
@@ -34246,21 +34715,21 @@ function isManagedSkillName(name) {
|
|
|
34246
34715
|
}
|
|
34247
34716
|
var SKILL_TARGETS = ["agents", "cursor", "claude-code"];
|
|
34248
34717
|
function resolveTargetDir(target, useGlobal, cwd = process.cwd()) {
|
|
34249
|
-
const root = useGlobal ?
|
|
34718
|
+
const root = useGlobal ? homedir5() : cwd;
|
|
34250
34719
|
switch (target) {
|
|
34251
34720
|
case "agents":
|
|
34252
|
-
return
|
|
34721
|
+
return join6(root, ".agents", "skills");
|
|
34253
34722
|
case "cursor":
|
|
34254
|
-
return
|
|
34723
|
+
return join6(root, ".cursor", "rules");
|
|
34255
34724
|
case "claude-code":
|
|
34256
|
-
return
|
|
34725
|
+
return join6(root, ".claude", "skills");
|
|
34257
34726
|
}
|
|
34258
34727
|
}
|
|
34259
34728
|
function filenameForTarget(slug, target) {
|
|
34260
34729
|
switch (target) {
|
|
34261
34730
|
case "agents":
|
|
34262
34731
|
case "claude-code":
|
|
34263
|
-
return
|
|
34732
|
+
return join6(slug, "SKILL.md");
|
|
34264
34733
|
case "cursor":
|
|
34265
34734
|
return `${slug}.mdc`;
|
|
34266
34735
|
}
|
|
@@ -34334,7 +34803,7 @@ async function checkTargetScope(manifest, servedCache, target, scope) {
|
|
|
34334
34803
|
const slugs = await installedSlugs(dir, target);
|
|
34335
34804
|
const rows = [];
|
|
34336
34805
|
for (const slug of slugs) {
|
|
34337
|
-
const path2 =
|
|
34806
|
+
const path2 = join7(dir, filenameForTarget(slug, target));
|
|
34338
34807
|
let installed;
|
|
34339
34808
|
try {
|
|
34340
34809
|
installed = await readFile3(path2, "utf-8");
|
|
@@ -34462,7 +34931,7 @@ function registerSkillsList(parent) {
|
|
|
34462
34931
|
|
|
34463
34932
|
// src/commands/skills/install.ts
|
|
34464
34933
|
import { writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
34465
|
-
import { join as
|
|
34934
|
+
import { join as join8 } from "path";
|
|
34466
34935
|
function registerSkillsInstall(parent) {
|
|
34467
34936
|
parent.command("install [slug]").description("Install all skills (or one named slug) into a local directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Install to ~/.<target>/ instead of <cwd>/.<target>/").action(async (slug, opts) => {
|
|
34468
34937
|
try {
|
|
@@ -34483,8 +34952,8 @@ function registerSkillsInstall(parent) {
|
|
|
34483
34952
|
const raw = await fetchSkill(s.url);
|
|
34484
34953
|
const transformed = transformForTarget(raw, target, s.description);
|
|
34485
34954
|
const relPath = filenameForTarget(s.name, target);
|
|
34486
|
-
const fullPath =
|
|
34487
|
-
await mkdir3(
|
|
34955
|
+
const fullPath = join8(targetDir, relPath);
|
|
34956
|
+
await mkdir3(join8(fullPath, ".."), { recursive: true });
|
|
34488
34957
|
await writeFile3(fullPath, transformed, "utf-8");
|
|
34489
34958
|
installed.push({ name: s.name, path: fullPath });
|
|
34490
34959
|
}
|
|
@@ -34513,7 +34982,7 @@ function registerSkillsInstall(parent) {
|
|
|
34513
34982
|
|
|
34514
34983
|
// src/commands/skills/uninstall.ts
|
|
34515
34984
|
import { readdir as readdir2, unlink, rmdir } from "fs/promises";
|
|
34516
|
-
import { join as
|
|
34985
|
+
import { join as join9 } from "path";
|
|
34517
34986
|
function registerSkillsUninstall(parent) {
|
|
34518
34987
|
parent.command("uninstall").description("Remove installed t2000 + MPP skills from the target directory").option("--target <name>", "Target client layout: agents (default), cursor, claude-code", "agents").option("--global", "Uninstall from ~/.<target>/ instead of <cwd>/.<target>/").action(async (opts) => {
|
|
34519
34988
|
try {
|
|
@@ -34531,7 +35000,7 @@ function registerSkillsUninstall(parent) {
|
|
|
34531
35000
|
const entries = await readdir2(targetDir);
|
|
34532
35001
|
const removed = [];
|
|
34533
35002
|
for (const entry of entries) {
|
|
34534
|
-
const full =
|
|
35003
|
+
const full = join9(targetDir, entry);
|
|
34535
35004
|
if (target === "cursor") {
|
|
34536
35005
|
const slug = entry.endsWith(".mdc") ? entry.slice(0, -".mdc".length) : entry;
|
|
34537
35006
|
if (entry.endsWith(".mdc") && isManagedSkillName(slug)) {
|
|
@@ -34540,7 +35009,7 @@ function registerSkillsUninstall(parent) {
|
|
|
34540
35009
|
}
|
|
34541
35010
|
} else {
|
|
34542
35011
|
if (isManagedSkillName(entry)) {
|
|
34543
|
-
const skillFile =
|
|
35012
|
+
const skillFile = join9(full, "SKILL.md");
|
|
34544
35013
|
try {
|
|
34545
35014
|
await unlink(skillFile);
|
|
34546
35015
|
} catch {
|
|
@@ -35156,6 +35625,7 @@ Examples:
|
|
|
35156
35625
|
$ t2 send 5 USDC alice.sui Send 5 USDC (gasless; asset required)
|
|
35157
35626
|
$ t2 swap 100 USDC SUI Swap 100 USDC for SUI via Cetus
|
|
35158
35627
|
$ t2 models List the Private Inference model catalog (chat lives in \`t2 code\`)
|
|
35628
|
+
$ t2 connect t2code --key sk-... Point a coding tool at Private Inference
|
|
35159
35629
|
$ t2 pay <url> --estimate Preview an x402 service's price + input schema (no payment)
|
|
35160
35630
|
$ t2 services search "image" Discover x402 services in the gateway catalog
|
|
35161
35631
|
$ t2 agents Look up the agent directory (agents.t2000.ai)
|
|
@@ -35172,6 +35642,7 @@ Examples:
|
|
|
35172
35642
|
registerSwap(program3);
|
|
35173
35643
|
registerPay(program3);
|
|
35174
35644
|
registerModels(program3);
|
|
35645
|
+
registerConnect(program3);
|
|
35175
35646
|
registerVerify(program3);
|
|
35176
35647
|
registerServices(program3);
|
|
35177
35648
|
registerLimit(program3);
|