@t2000/cli 8.2.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
|
@@ -33657,72 +33657,9 @@ function describeSchemaFields(schema) {
|
|
|
33657
33657
|
});
|
|
33658
33658
|
}
|
|
33659
33659
|
|
|
33660
|
-
// src/commands/
|
|
33660
|
+
// src/commands/models.ts
|
|
33661
33661
|
var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
33662
|
-
function
|
|
33663
|
-
if (receiptId) {
|
|
33664
|
-
printLine(import_picocolors9.default.dim(`\u{1F512} confidential \xB7 attested \xB7 receipt ${receiptId}`));
|
|
33665
|
-
}
|
|
33666
|
-
}
|
|
33667
|
-
var DEFAULT_MODEL = "openai/gpt-oss-120b";
|
|
33668
|
-
function numOrUndef(v) {
|
|
33669
|
-
if (v === void 0) {
|
|
33670
|
-
return;
|
|
33671
|
-
}
|
|
33672
|
-
const n = Number(v);
|
|
33673
|
-
return Number.isFinite(n) ? n : void 0;
|
|
33674
|
-
}
|
|
33675
|
-
function registerChat(program3) {
|
|
33676
|
-
program3.command("chat").argument("<message...>", "Your prompt").description(
|
|
33677
|
-
"Chat with a model on t2000 Private Inference (OpenAI-compatible, ZDR; a phala/* tier is GPU-TEE confidential). Needs an API key \u2014 generate one at agents.t2000.ai/manage, then pass --api-key or set T2000_API_KEY."
|
|
33678
|
-
).option("--model <id>", `Model id (default ${DEFAULT_MODEL}; see \`t2 models\`)`, DEFAULT_MODEL).option("--system <text>", "System prompt").option("--max-tokens <n>", "Max output tokens").option("--temperature <t>", "Sampling temperature (0\u20132)").option("--no-stream", "Wait for the full response instead of streaming").option("--api-key <key>", "Private Inference key (or set T2000_API_KEY)").option("--api <url>", "API base URL (default https://api.t2000.ai/v1)").action(
|
|
33679
|
-
async (messageParts, opts) => {
|
|
33680
|
-
try {
|
|
33681
|
-
const messages = [];
|
|
33682
|
-
if (opts.system) {
|
|
33683
|
-
messages.push({ role: "system", content: opts.system });
|
|
33684
|
-
}
|
|
33685
|
-
messages.push({ role: "user", content: messageParts.join(" ") });
|
|
33686
|
-
const params = {
|
|
33687
|
-
model: opts.model,
|
|
33688
|
-
messages,
|
|
33689
|
-
apiKey: opts.apiKey,
|
|
33690
|
-
apiBase: opts.api,
|
|
33691
|
-
maxTokens: numOrUndef(opts.maxTokens),
|
|
33692
|
-
temperature: numOrUndef(opts.temperature)
|
|
33693
|
-
};
|
|
33694
|
-
if (isJsonMode() || opts.stream === false) {
|
|
33695
|
-
const res = await chatCompletion(params);
|
|
33696
|
-
if (isJsonMode()) {
|
|
33697
|
-
printJson({
|
|
33698
|
-
model: res.model,
|
|
33699
|
-
content: res.content,
|
|
33700
|
-
usage: res.usage,
|
|
33701
|
-
receiptId: res.receiptId
|
|
33702
|
-
});
|
|
33703
|
-
return;
|
|
33704
|
-
}
|
|
33705
|
-
printBlank();
|
|
33706
|
-
printLine(res.content);
|
|
33707
|
-
receiptLine(res.receiptId);
|
|
33708
|
-
printBlank();
|
|
33709
|
-
return;
|
|
33710
|
-
}
|
|
33711
|
-
const gen = chatCompletionStream(params);
|
|
33712
|
-
let any = false;
|
|
33713
|
-
let next = await gen.next();
|
|
33714
|
-
while (!next.done) {
|
|
33715
|
-
process.stdout.write(next.value);
|
|
33716
|
-
any = true;
|
|
33717
|
-
next = await gen.next();
|
|
33718
|
-
}
|
|
33719
|
-
process.stdout.write(any ? "\n" : "");
|
|
33720
|
-
receiptLine(next.value?.receiptId);
|
|
33721
|
-
} catch (error) {
|
|
33722
|
-
handleError(error);
|
|
33723
|
-
}
|
|
33724
|
-
}
|
|
33725
|
-
);
|
|
33662
|
+
function registerModels(program3) {
|
|
33726
33663
|
program3.command("models").description("List the t2000 Private Inference model catalog (id \xB7 privacy tier \xB7 per-1M pricing).").option("--api-key <key>", "Private Inference key (or set T2000_API_KEY)").option("--api <url>", "API base URL (default https://api.t2000.ai/v1)").action(async (opts) => {
|
|
33727
33664
|
try {
|
|
33728
33665
|
const models = await listModels({ apiKey: opts.apiKey, apiBase: opts.api });
|
|
@@ -33743,6 +33680,482 @@ function registerChat(program3) {
|
|
|
33743
33680
|
handleError(error);
|
|
33744
33681
|
}
|
|
33745
33682
|
});
|
|
33683
|
+
program3.command("chat", { hidden: true }).allowUnknownOption(true).argument("[message...]").action(() => {
|
|
33684
|
+
printLine("`t2 chat` moved into t2 code \u2014 the coding agent on the same rail.");
|
|
33685
|
+
printLine(" npm install -g @t2000/code");
|
|
33686
|
+
printLine(' t2code "your prompt" # interactive');
|
|
33687
|
+
printLine(' t2code exec "your task" # one-shot, headless');
|
|
33688
|
+
process.exitCode = 1;
|
|
33689
|
+
});
|
|
33690
|
+
}
|
|
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
|
+
});
|
|
33746
34159
|
}
|
|
33747
34160
|
|
|
33748
34161
|
// src/commands/verify.ts
|
|
@@ -34177,7 +34590,7 @@ function registerMcpStart(parent) {
|
|
|
34177
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) => {
|
|
34178
34591
|
let mod3;
|
|
34179
34592
|
try {
|
|
34180
|
-
mod3 = await import("./dist-
|
|
34593
|
+
mod3 = await import("./dist-RTG3A7CI.js");
|
|
34181
34594
|
} catch {
|
|
34182
34595
|
console.error("MCP server not installed. Run:\n npm install -g @t2000/mcp");
|
|
34183
34596
|
process.exit(1);
|
|
@@ -34228,12 +34641,12 @@ function registerMcpInstall(parent) {
|
|
|
34228
34641
|
}
|
|
34229
34642
|
|
|
34230
34643
|
// src/commands/mcp/uninstall.ts
|
|
34231
|
-
import { existsSync as
|
|
34644
|
+
import { existsSync as existsSync4 } from "fs";
|
|
34232
34645
|
async function runUninstall() {
|
|
34233
34646
|
const platforms = getPlatformConfigs();
|
|
34234
34647
|
const results = [];
|
|
34235
34648
|
for (const platform of platforms) {
|
|
34236
|
-
if (!
|
|
34649
|
+
if (!existsSync4(platform.path)) {
|
|
34237
34650
|
results.push({ name: platform.name, slug: platform.slug, removed: false });
|
|
34238
34651
|
continue;
|
|
34239
34652
|
}
|
|
@@ -34289,12 +34702,12 @@ Subcommands:
|
|
|
34289
34702
|
|
|
34290
34703
|
// src/commands/skills/check.ts
|
|
34291
34704
|
import { readdir, readFile as readFile3 } from "fs/promises";
|
|
34292
|
-
import { join as
|
|
34705
|
+
import { join as join7 } from "path";
|
|
34293
34706
|
|
|
34294
34707
|
// src/commands/skills/lib.ts
|
|
34295
34708
|
import { stat } from "fs/promises";
|
|
34296
|
-
import { join as
|
|
34297
|
-
import { homedir as
|
|
34709
|
+
import { join as join6 } from "path";
|
|
34710
|
+
import { homedir as homedir5 } from "os";
|
|
34298
34711
|
var MANIFEST_URL = "https://t2000.ai/.well-known/agent-skills/index.json";
|
|
34299
34712
|
var SKILL_PREFIXES = ["t2000-", "mpp-"];
|
|
34300
34713
|
function isManagedSkillName(name) {
|
|
@@ -34302,21 +34715,21 @@ function isManagedSkillName(name) {
|
|
|
34302
34715
|
}
|
|
34303
34716
|
var SKILL_TARGETS = ["agents", "cursor", "claude-code"];
|
|
34304
34717
|
function resolveTargetDir(target, useGlobal, cwd = process.cwd()) {
|
|
34305
|
-
const root = useGlobal ?
|
|
34718
|
+
const root = useGlobal ? homedir5() : cwd;
|
|
34306
34719
|
switch (target) {
|
|
34307
34720
|
case "agents":
|
|
34308
|
-
return
|
|
34721
|
+
return join6(root, ".agents", "skills");
|
|
34309
34722
|
case "cursor":
|
|
34310
|
-
return
|
|
34723
|
+
return join6(root, ".cursor", "rules");
|
|
34311
34724
|
case "claude-code":
|
|
34312
|
-
return
|
|
34725
|
+
return join6(root, ".claude", "skills");
|
|
34313
34726
|
}
|
|
34314
34727
|
}
|
|
34315
34728
|
function filenameForTarget(slug, target) {
|
|
34316
34729
|
switch (target) {
|
|
34317
34730
|
case "agents":
|
|
34318
34731
|
case "claude-code":
|
|
34319
|
-
return
|
|
34732
|
+
return join6(slug, "SKILL.md");
|
|
34320
34733
|
case "cursor":
|
|
34321
34734
|
return `${slug}.mdc`;
|
|
34322
34735
|
}
|
|
@@ -34390,7 +34803,7 @@ async function checkTargetScope(manifest, servedCache, target, scope) {
|
|
|
34390
34803
|
const slugs = await installedSlugs(dir, target);
|
|
34391
34804
|
const rows = [];
|
|
34392
34805
|
for (const slug of slugs) {
|
|
34393
|
-
const path2 =
|
|
34806
|
+
const path2 = join7(dir, filenameForTarget(slug, target));
|
|
34394
34807
|
let installed;
|
|
34395
34808
|
try {
|
|
34396
34809
|
installed = await readFile3(path2, "utf-8");
|
|
@@ -34518,7 +34931,7 @@ function registerSkillsList(parent) {
|
|
|
34518
34931
|
|
|
34519
34932
|
// src/commands/skills/install.ts
|
|
34520
34933
|
import { writeFile as writeFile3, mkdir as mkdir3 } from "fs/promises";
|
|
34521
|
-
import { join as
|
|
34934
|
+
import { join as join8 } from "path";
|
|
34522
34935
|
function registerSkillsInstall(parent) {
|
|
34523
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) => {
|
|
34524
34937
|
try {
|
|
@@ -34539,8 +34952,8 @@ function registerSkillsInstall(parent) {
|
|
|
34539
34952
|
const raw = await fetchSkill(s.url);
|
|
34540
34953
|
const transformed = transformForTarget(raw, target, s.description);
|
|
34541
34954
|
const relPath = filenameForTarget(s.name, target);
|
|
34542
|
-
const fullPath =
|
|
34543
|
-
await mkdir3(
|
|
34955
|
+
const fullPath = join8(targetDir, relPath);
|
|
34956
|
+
await mkdir3(join8(fullPath, ".."), { recursive: true });
|
|
34544
34957
|
await writeFile3(fullPath, transformed, "utf-8");
|
|
34545
34958
|
installed.push({ name: s.name, path: fullPath });
|
|
34546
34959
|
}
|
|
@@ -34569,7 +34982,7 @@ function registerSkillsInstall(parent) {
|
|
|
34569
34982
|
|
|
34570
34983
|
// src/commands/skills/uninstall.ts
|
|
34571
34984
|
import { readdir as readdir2, unlink, rmdir } from "fs/promises";
|
|
34572
|
-
import { join as
|
|
34985
|
+
import { join as join9 } from "path";
|
|
34573
34986
|
function registerSkillsUninstall(parent) {
|
|
34574
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) => {
|
|
34575
34988
|
try {
|
|
@@ -34587,7 +35000,7 @@ function registerSkillsUninstall(parent) {
|
|
|
34587
35000
|
const entries = await readdir2(targetDir);
|
|
34588
35001
|
const removed = [];
|
|
34589
35002
|
for (const entry of entries) {
|
|
34590
|
-
const full =
|
|
35003
|
+
const full = join9(targetDir, entry);
|
|
34591
35004
|
if (target === "cursor") {
|
|
34592
35005
|
const slug = entry.endsWith(".mdc") ? entry.slice(0, -".mdc".length) : entry;
|
|
34593
35006
|
if (entry.endsWith(".mdc") && isManagedSkillName(slug)) {
|
|
@@ -34596,7 +35009,7 @@ function registerSkillsUninstall(parent) {
|
|
|
34596
35009
|
}
|
|
34597
35010
|
} else {
|
|
34598
35011
|
if (isManagedSkillName(entry)) {
|
|
34599
|
-
const skillFile =
|
|
35012
|
+
const skillFile = join9(full, "SKILL.md");
|
|
34600
35013
|
try {
|
|
34601
35014
|
await unlink(skillFile);
|
|
34602
35015
|
} catch {
|
|
@@ -35211,8 +35624,8 @@ Examples:
|
|
|
35211
35624
|
$ t2 balance Show USDC / USDsui / SUI holdings
|
|
35212
35625
|
$ t2 send 5 USDC alice.sui Send 5 USDC (gasless; asset required)
|
|
35213
35626
|
$ t2 swap 100 USDC SUI Swap 100 USDC for SUI via Cetus
|
|
35214
|
-
$ t2
|
|
35215
|
-
$ t2
|
|
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
|
|
35216
35629
|
$ t2 pay <url> --estimate Preview an x402 service's price + input schema (no payment)
|
|
35217
35630
|
$ t2 services search "image" Discover x402 services in the gateway catalog
|
|
35218
35631
|
$ t2 agents Look up the agent directory (agents.t2000.ai)
|
|
@@ -35228,7 +35641,8 @@ Examples:
|
|
|
35228
35641
|
registerSend(program3);
|
|
35229
35642
|
registerSwap(program3);
|
|
35230
35643
|
registerPay(program3);
|
|
35231
|
-
|
|
35644
|
+
registerModels(program3);
|
|
35645
|
+
registerConnect(program3);
|
|
35232
35646
|
registerVerify(program3);
|
|
35233
35647
|
registerServices(program3);
|
|
35234
35648
|
registerLimit(program3);
|