@chat-js/cli 0.2.0 → 0.3.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 +209 -169
- package/package.json +48 -48
- package/templates/chat-app/CHANGELOG.md +19 -0
- package/templates/chat-app/app/(chat)/actions.ts +9 -5
- package/templates/chat-app/app/globals.css +1 -1
- package/templates/chat-app/chat.config.ts +15 -44
- package/templates/chat-app/lib/ai/followup-suggestions.ts +4 -1
- package/templates/chat-app/lib/ai/gateway-model-defaults.ts +154 -100
- package/templates/chat-app/lib/ai/gateways/openrouter-gateway.ts +2 -2
- package/templates/chat-app/lib/ai/tools/generate-image.ts +9 -2
- package/templates/chat-app/lib/ai/tools/generate-video.ts +3 -0
- package/templates/chat-app/lib/ai/types.ts +2 -2
- package/templates/chat-app/lib/config-schema.ts +126 -132
- package/templates/chat-app/lib/config.ts +2 -2
- package/templates/chat-app/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3914,17 +3914,17 @@ var {
|
|
|
3914
3914
|
// package.json
|
|
3915
3915
|
var package_default = {
|
|
3916
3916
|
name: "@chat-js/cli",
|
|
3917
|
-
version: "0.
|
|
3917
|
+
version: "0.3.0",
|
|
3918
3918
|
description: "CLI for creating and extending ChatJS apps",
|
|
3919
3919
|
license: "Apache-2.0",
|
|
3920
3920
|
repository: {
|
|
3921
3921
|
type: "git",
|
|
3922
|
-
url: "https://github.com/franciscomoretti/chat
|
|
3922
|
+
url: "https://github.com/franciscomoretti/chat-js.git",
|
|
3923
3923
|
directory: "packages/cli"
|
|
3924
3924
|
},
|
|
3925
|
-
homepage: "https://github.com/franciscomoretti/chat
|
|
3925
|
+
homepage: "https://github.com/franciscomoretti/chat-js/tree/main/packages/cli",
|
|
3926
3926
|
bugs: {
|
|
3927
|
-
url: "https://github.com/franciscomoretti/chat
|
|
3927
|
+
url: "https://github.com/franciscomoretti/chat-js/issues"
|
|
3928
3928
|
},
|
|
3929
3929
|
keywords: [
|
|
3930
3930
|
"chatjs",
|
|
@@ -17611,6 +17611,71 @@ var add = new Command().name("add").description("add a component or feature to a
|
|
|
17611
17611
|
}
|
|
17612
17612
|
});
|
|
17613
17613
|
|
|
17614
|
+
// src/commands/config.ts
|
|
17615
|
+
import { spawn } from "node:child_process";
|
|
17616
|
+
import path from "node:path";
|
|
17617
|
+
|
|
17618
|
+
// src/utils/get-package-manager.ts
|
|
17619
|
+
function inferPackageManager() {
|
|
17620
|
+
const ua = process.env.npm_config_user_agent ?? "";
|
|
17621
|
+
if (ua.startsWith("pnpm/"))
|
|
17622
|
+
return "pnpm";
|
|
17623
|
+
if (ua.startsWith("yarn/"))
|
|
17624
|
+
return "yarn";
|
|
17625
|
+
if (ua.startsWith("npm/"))
|
|
17626
|
+
return "npm";
|
|
17627
|
+
if (ua.startsWith("bun/"))
|
|
17628
|
+
return "bun";
|
|
17629
|
+
return "bun";
|
|
17630
|
+
}
|
|
17631
|
+
|
|
17632
|
+
// src/commands/config.ts
|
|
17633
|
+
var EVAL_SCRIPT = `
|
|
17634
|
+
import userConfig from "./chat.config.ts";
|
|
17635
|
+
import { applyDefaults } from "./lib/config-schema";
|
|
17636
|
+
console.log(JSON.stringify(applyDefaults(userConfig), null, 2));
|
|
17637
|
+
`;
|
|
17638
|
+
function getTsEvalCommand(pm) {
|
|
17639
|
+
switch (pm) {
|
|
17640
|
+
case "bun":
|
|
17641
|
+
return ["bun", ["--eval", EVAL_SCRIPT]];
|
|
17642
|
+
case "pnpm":
|
|
17643
|
+
return ["pnpm", ["dlx", "tsx", "--eval", EVAL_SCRIPT]];
|
|
17644
|
+
case "yarn":
|
|
17645
|
+
return ["yarn", ["dlx", "tsx", "--eval", EVAL_SCRIPT]];
|
|
17646
|
+
default:
|
|
17647
|
+
return ["npx", ["tsx", "--eval", EVAL_SCRIPT]];
|
|
17648
|
+
}
|
|
17649
|
+
}
|
|
17650
|
+
var config2 = new Command().name("config").description("print the resolved configuration for the current ChatJS project").option("-c, --cwd <cwd>", "the working directory (defaults to current directory)", process.cwd()).action(async (opts) => {
|
|
17651
|
+
try {
|
|
17652
|
+
const cwd = path.resolve(opts.cwd);
|
|
17653
|
+
const pm = inferPackageManager();
|
|
17654
|
+
const [cmd, args] = getTsEvalCommand(pm);
|
|
17655
|
+
await new Promise((resolve, reject) => {
|
|
17656
|
+
const child = spawn(cmd, args, {
|
|
17657
|
+
cwd,
|
|
17658
|
+
stdio: ["ignore", "inherit", "pipe"]
|
|
17659
|
+
});
|
|
17660
|
+
const stderr = [];
|
|
17661
|
+
child.stderr?.on("data", (data) => stderr.push(String(data)));
|
|
17662
|
+
child.on("error", (err) => {
|
|
17663
|
+
reject(new Error(`Could not spawn ${cmd}. Make sure ${pm} is installed.
|
|
17664
|
+
${err.message}`));
|
|
17665
|
+
});
|
|
17666
|
+
child.on("close", (code) => {
|
|
17667
|
+
if (code === 0)
|
|
17668
|
+
resolve();
|
|
17669
|
+
else
|
|
17670
|
+
reject(new Error(`Failed to resolve config:
|
|
17671
|
+
${stderr.join("").trim()}`));
|
|
17672
|
+
});
|
|
17673
|
+
});
|
|
17674
|
+
} catch (error48) {
|
|
17675
|
+
handleError(error48);
|
|
17676
|
+
}
|
|
17677
|
+
});
|
|
17678
|
+
|
|
17614
17679
|
// src/commands/create.ts
|
|
17615
17680
|
import { readFile, writeFile } from "node:fs/promises";
|
|
17616
17681
|
import { join as join2, resolve as resolve2 } from "node:path";
|
|
@@ -18661,7 +18726,7 @@ ${l}
|
|
|
18661
18726
|
} }).prompt();
|
|
18662
18727
|
|
|
18663
18728
|
// ../../apps/chat/lib/ai/gateway-model-defaults.ts
|
|
18664
|
-
var
|
|
18729
|
+
var vercelDefaults = {
|
|
18665
18730
|
providerOrder: ["openai", "google", "anthropic"],
|
|
18666
18731
|
disabledModels: [],
|
|
18667
18732
|
curatedDefaults: [
|
|
@@ -18684,36 +18749,66 @@ var multiProviderDefaults = {
|
|
|
18684
18749
|
chatImageCompatible: "openai/gpt-4o-mini"
|
|
18685
18750
|
},
|
|
18686
18751
|
tools: {
|
|
18687
|
-
webSearch: {
|
|
18688
|
-
|
|
18689
|
-
},
|
|
18690
|
-
|
|
18691
|
-
enabled: false
|
|
18692
|
-
},
|
|
18693
|
-
codeExecution: {
|
|
18694
|
-
enabled: false
|
|
18695
|
-
},
|
|
18696
|
-
mcp: {
|
|
18697
|
-
enabled: false
|
|
18698
|
-
},
|
|
18752
|
+
webSearch: { enabled: false },
|
|
18753
|
+
urlRetrieval: { enabled: false },
|
|
18754
|
+
codeExecution: { enabled: false },
|
|
18755
|
+
mcp: { enabled: false },
|
|
18699
18756
|
followupSuggestions: {
|
|
18700
18757
|
enabled: false,
|
|
18701
18758
|
default: "google/gemini-2.5-flash-lite"
|
|
18702
18759
|
},
|
|
18703
|
-
text: {
|
|
18704
|
-
|
|
18705
|
-
},
|
|
18706
|
-
|
|
18707
|
-
|
|
18708
|
-
|
|
18709
|
-
},
|
|
18710
|
-
code: {
|
|
18711
|
-
edits: "openai/gpt-5-mini"
|
|
18712
|
-
},
|
|
18713
|
-
image: {
|
|
18760
|
+
text: { polish: "openai/gpt-5-mini" },
|
|
18761
|
+
sheet: { format: "openai/gpt-5-mini", analyze: "openai/gpt-5-mini" },
|
|
18762
|
+
code: { edits: "openai/gpt-5-mini" },
|
|
18763
|
+
image: { enabled: false, default: "google/gemini-3-pro-image" },
|
|
18764
|
+
video: { enabled: false, default: "xai/grok-imagine-video" },
|
|
18765
|
+
deepResearch: {
|
|
18714
18766
|
enabled: false,
|
|
18715
|
-
|
|
18767
|
+
defaultModel: "google/gemini-2.5-flash-lite",
|
|
18768
|
+
finalReportModel: "google/gemini-3-flash",
|
|
18769
|
+
allowClarification: true,
|
|
18770
|
+
maxResearcherIterations: 1,
|
|
18771
|
+
maxConcurrentResearchUnits: 2,
|
|
18772
|
+
maxSearchQueries: 2
|
|
18773
|
+
}
|
|
18774
|
+
}
|
|
18775
|
+
};
|
|
18776
|
+
var openrouterDefaults = {
|
|
18777
|
+
providerOrder: ["openai", "google", "anthropic"],
|
|
18778
|
+
disabledModels: [],
|
|
18779
|
+
curatedDefaults: [
|
|
18780
|
+
"openai/gpt-5-nano",
|
|
18781
|
+
"openai/gpt-5-mini",
|
|
18782
|
+
"openai/gpt-5.2",
|
|
18783
|
+
"openai/gpt-5.2-chat",
|
|
18784
|
+
"google/gemini-2.5-flash-lite",
|
|
18785
|
+
"google/gemini-3-flash",
|
|
18786
|
+
"google/gemini-3-pro-preview",
|
|
18787
|
+
"anthropic/claude-sonnet-4.5",
|
|
18788
|
+
"anthropic/claude-opus-4.5",
|
|
18789
|
+
"xai/grok-4"
|
|
18790
|
+
],
|
|
18791
|
+
anonymousModels: ["google/gemini-2.5-flash-lite", "openai/gpt-5-nano"],
|
|
18792
|
+
workflows: {
|
|
18793
|
+
chat: "openai/gpt-5-mini",
|
|
18794
|
+
title: "openai/gpt-5-nano",
|
|
18795
|
+
pdf: "openai/gpt-5-mini",
|
|
18796
|
+
chatImageCompatible: "openai/gpt-4o-mini"
|
|
18797
|
+
},
|
|
18798
|
+
tools: {
|
|
18799
|
+
webSearch: { enabled: false },
|
|
18800
|
+
urlRetrieval: { enabled: false },
|
|
18801
|
+
codeExecution: { enabled: false },
|
|
18802
|
+
mcp: { enabled: false },
|
|
18803
|
+
followupSuggestions: {
|
|
18804
|
+
enabled: false,
|
|
18805
|
+
default: "google/gemini-2.5-flash-lite"
|
|
18716
18806
|
},
|
|
18807
|
+
text: { polish: "openai/gpt-5-mini" },
|
|
18808
|
+
sheet: { format: "openai/gpt-5-mini", analyze: "openai/gpt-5-mini" },
|
|
18809
|
+
code: { edits: "openai/gpt-5-mini" },
|
|
18810
|
+
image: { enabled: false },
|
|
18811
|
+
video: { enabled: false },
|
|
18717
18812
|
deepResearch: {
|
|
18718
18813
|
enabled: false,
|
|
18719
18814
|
defaultModel: "google/gemini-2.5-flash-lite",
|
|
@@ -18725,7 +18820,7 @@ var multiProviderDefaults = {
|
|
|
18725
18820
|
}
|
|
18726
18821
|
}
|
|
18727
18822
|
};
|
|
18728
|
-
var
|
|
18823
|
+
var openaiDefaults = {
|
|
18729
18824
|
providerOrder: ["openai"],
|
|
18730
18825
|
disabledModels: [],
|
|
18731
18826
|
curatedDefaults: [
|
|
@@ -18742,36 +18837,54 @@ var openaiOnlyDefaults = {
|
|
|
18742
18837
|
chatImageCompatible: "gpt-4o-mini"
|
|
18743
18838
|
},
|
|
18744
18839
|
tools: {
|
|
18745
|
-
webSearch: {
|
|
18746
|
-
|
|
18747
|
-
},
|
|
18748
|
-
|
|
18749
|
-
|
|
18750
|
-
},
|
|
18751
|
-
|
|
18752
|
-
|
|
18753
|
-
},
|
|
18754
|
-
|
|
18755
|
-
|
|
18756
|
-
},
|
|
18757
|
-
followupSuggestions: {
|
|
18758
|
-
enabled: false,
|
|
18759
|
-
default: "gpt-5-nano"
|
|
18760
|
-
},
|
|
18761
|
-
text: {
|
|
18762
|
-
polish: "gpt-5-mini"
|
|
18763
|
-
},
|
|
18764
|
-
sheet: {
|
|
18765
|
-
format: "gpt-5-mini",
|
|
18766
|
-
analyze: "gpt-5-mini"
|
|
18767
|
-
},
|
|
18768
|
-
code: {
|
|
18769
|
-
edits: "gpt-5-mini"
|
|
18770
|
-
},
|
|
18771
|
-
image: {
|
|
18840
|
+
webSearch: { enabled: false },
|
|
18841
|
+
urlRetrieval: { enabled: false },
|
|
18842
|
+
codeExecution: { enabled: false },
|
|
18843
|
+
mcp: { enabled: false },
|
|
18844
|
+
followupSuggestions: { enabled: false, default: "gpt-5-nano" },
|
|
18845
|
+
text: { polish: "gpt-5-mini" },
|
|
18846
|
+
sheet: { format: "gpt-5-mini", analyze: "gpt-5-mini" },
|
|
18847
|
+
code: { edits: "gpt-5-mini" },
|
|
18848
|
+
image: { enabled: false },
|
|
18849
|
+
video: { enabled: false },
|
|
18850
|
+
deepResearch: {
|
|
18772
18851
|
enabled: false,
|
|
18773
|
-
|
|
18774
|
-
|
|
18852
|
+
defaultModel: "gpt-5-nano",
|
|
18853
|
+
finalReportModel: "gpt-5-mini",
|
|
18854
|
+
allowClarification: true,
|
|
18855
|
+
maxResearcherIterations: 1,
|
|
18856
|
+
maxConcurrentResearchUnits: 2,
|
|
18857
|
+
maxSearchQueries: 2
|
|
18858
|
+
}
|
|
18859
|
+
}
|
|
18860
|
+
};
|
|
18861
|
+
var openaiCompatibleDefaults = {
|
|
18862
|
+
providerOrder: ["openai"],
|
|
18863
|
+
disabledModels: [],
|
|
18864
|
+
curatedDefaults: [
|
|
18865
|
+
"gpt-5-nano",
|
|
18866
|
+
"gpt-5-mini",
|
|
18867
|
+
"gpt-5.2",
|
|
18868
|
+
"gpt-5.2-chat-latest"
|
|
18869
|
+
],
|
|
18870
|
+
anonymousModels: ["gpt-5-nano"],
|
|
18871
|
+
workflows: {
|
|
18872
|
+
chat: "gpt-5-mini",
|
|
18873
|
+
title: "gpt-5-nano",
|
|
18874
|
+
pdf: "gpt-5-mini",
|
|
18875
|
+
chatImageCompatible: "gpt-4o-mini"
|
|
18876
|
+
},
|
|
18877
|
+
tools: {
|
|
18878
|
+
webSearch: { enabled: false },
|
|
18879
|
+
urlRetrieval: { enabled: false },
|
|
18880
|
+
codeExecution: { enabled: false },
|
|
18881
|
+
mcp: { enabled: false },
|
|
18882
|
+
followupSuggestions: { enabled: false, default: "gpt-5-nano" },
|
|
18883
|
+
text: { polish: "gpt-5-mini" },
|
|
18884
|
+
sheet: { format: "gpt-5-mini", analyze: "gpt-5-mini" },
|
|
18885
|
+
code: { edits: "gpt-5-mini" },
|
|
18886
|
+
image: { enabled: false },
|
|
18887
|
+
video: { enabled: false },
|
|
18775
18888
|
deepResearch: {
|
|
18776
18889
|
enabled: false,
|
|
18777
18890
|
defaultModel: "gpt-5-nano",
|
|
@@ -18784,10 +18897,10 @@ var openaiOnlyDefaults = {
|
|
|
18784
18897
|
}
|
|
18785
18898
|
};
|
|
18786
18899
|
var GATEWAY_MODEL_DEFAULTS = {
|
|
18787
|
-
vercel:
|
|
18788
|
-
openrouter:
|
|
18789
|
-
openai:
|
|
18790
|
-
"openai-compatible":
|
|
18900
|
+
vercel: vercelDefaults,
|
|
18901
|
+
openrouter: openrouterDefaults,
|
|
18902
|
+
openai: openaiDefaults,
|
|
18903
|
+
"openai-compatible": openaiCompatibleDefaults
|
|
18791
18904
|
};
|
|
18792
18905
|
|
|
18793
18906
|
// ../../apps/chat/lib/config-schema.ts
|
|
@@ -18850,14 +18963,26 @@ function createAiSchema(g) {
|
|
|
18850
18963
|
code: exports_external.object({
|
|
18851
18964
|
edits: gatewayModelId()
|
|
18852
18965
|
}),
|
|
18853
|
-
image: exports_external.
|
|
18854
|
-
|
|
18855
|
-
|
|
18856
|
-
|
|
18857
|
-
|
|
18858
|
-
|
|
18859
|
-
|
|
18860
|
-
|
|
18966
|
+
image: exports_external.discriminatedUnion("enabled", [
|
|
18967
|
+
exports_external.object({
|
|
18968
|
+
enabled: exports_external.literal(true),
|
|
18969
|
+
default: gatewayImageModelId()
|
|
18970
|
+
}),
|
|
18971
|
+
exports_external.object({
|
|
18972
|
+
enabled: exports_external.literal(false),
|
|
18973
|
+
default: gatewayImageModelId().optional()
|
|
18974
|
+
})
|
|
18975
|
+
]),
|
|
18976
|
+
video: exports_external.discriminatedUnion("enabled", [
|
|
18977
|
+
exports_external.object({
|
|
18978
|
+
enabled: exports_external.literal(true),
|
|
18979
|
+
default: gatewayVideoModelId()
|
|
18980
|
+
}),
|
|
18981
|
+
exports_external.object({
|
|
18982
|
+
enabled: exports_external.literal(false),
|
|
18983
|
+
default: gatewayVideoModelId().optional()
|
|
18984
|
+
})
|
|
18985
|
+
]),
|
|
18861
18986
|
deepResearch: deepResearchToolConfigSchema.extend({
|
|
18862
18987
|
enabled: exports_external.boolean(),
|
|
18863
18988
|
defaultModel: gatewayModelId(),
|
|
@@ -18879,72 +19004,7 @@ var aiConfigSchema = exports_external.discriminatedUnion("gateway", [
|
|
|
18879
19004
|
gatewaySchemaMap["openai-compatible"]
|
|
18880
19005
|
]).default({
|
|
18881
19006
|
gateway: DEFAULT_GATEWAY,
|
|
18882
|
-
|
|
18883
|
-
disabledModels: [],
|
|
18884
|
-
curatedDefaults: [
|
|
18885
|
-
"openai/gpt-5-nano",
|
|
18886
|
-
"openai/gpt-5-mini",
|
|
18887
|
-
"openai/gpt-5.2",
|
|
18888
|
-
"openai/gpt-5.2-chat",
|
|
18889
|
-
"google/gemini-2.5-flash-lite",
|
|
18890
|
-
"google/gemini-3-flash",
|
|
18891
|
-
"google/gemini-3-pro-preview",
|
|
18892
|
-
"anthropic/claude-sonnet-4.5",
|
|
18893
|
-
"anthropic/claude-opus-4.5",
|
|
18894
|
-
"xai/grok-4"
|
|
18895
|
-
],
|
|
18896
|
-
anonymousModels: ["google/gemini-2.5-flash-lite", "openai/gpt-5-nano"],
|
|
18897
|
-
workflows: {
|
|
18898
|
-
chat: "openai/gpt-5-mini",
|
|
18899
|
-
title: "openai/gpt-5-nano",
|
|
18900
|
-
pdf: "openai/gpt-5-mini",
|
|
18901
|
-
chatImageCompatible: "openai/gpt-4o-mini"
|
|
18902
|
-
},
|
|
18903
|
-
tools: {
|
|
18904
|
-
webSearch: {
|
|
18905
|
-
enabled: false
|
|
18906
|
-
},
|
|
18907
|
-
urlRetrieval: {
|
|
18908
|
-
enabled: false
|
|
18909
|
-
},
|
|
18910
|
-
codeExecution: {
|
|
18911
|
-
enabled: false
|
|
18912
|
-
},
|
|
18913
|
-
mcp: {
|
|
18914
|
-
enabled: false
|
|
18915
|
-
},
|
|
18916
|
-
followupSuggestions: {
|
|
18917
|
-
enabled: false,
|
|
18918
|
-
default: "google/gemini-2.5-flash-lite"
|
|
18919
|
-
},
|
|
18920
|
-
text: {
|
|
18921
|
-
polish: "openai/gpt-5-mini"
|
|
18922
|
-
},
|
|
18923
|
-
sheet: {
|
|
18924
|
-
format: "openai/gpt-5-mini",
|
|
18925
|
-
analyze: "openai/gpt-5-mini"
|
|
18926
|
-
},
|
|
18927
|
-
code: {
|
|
18928
|
-
edits: "openai/gpt-5-mini"
|
|
18929
|
-
},
|
|
18930
|
-
image: {
|
|
18931
|
-
enabled: false,
|
|
18932
|
-
default: "google/gemini-3-pro-image"
|
|
18933
|
-
},
|
|
18934
|
-
video: {
|
|
18935
|
-
enabled: false,
|
|
18936
|
-
default: "xai/grok-imagine-video"
|
|
18937
|
-
},
|
|
18938
|
-
deepResearch: {
|
|
18939
|
-
enabled: false,
|
|
18940
|
-
defaultModel: "google/gemini-2.5-flash-lite",
|
|
18941
|
-
finalReportModel: "google/gemini-3-flash",
|
|
18942
|
-
allowClarification: true,
|
|
18943
|
-
maxResearcherIterations: 1,
|
|
18944
|
-
maxConcurrentResearchUnits: 2,
|
|
18945
|
-
maxSearchQueries: 2
|
|
18946
|
-
}
|
|
18947
|
-
}
|
|
19007
|
+
...GATEWAY_MODEL_DEFAULTS[DEFAULT_GATEWAY]
|
|
18948
19008
|
});
|
|
18949
19009
|
var pricingConfigSchema = exports_external.object({
|
|
18950
19010
|
currency: exports_external.string().optional(),
|
|
@@ -19074,8 +19134,8 @@ function extractDescriptions(schema, prefix = "", result = new Map) {
|
|
|
19074
19134
|
if (unwrapped instanceof exports_external.ZodObject) {
|
|
19075
19135
|
const shape = unwrapped._zod.def.shape;
|
|
19076
19136
|
for (const [key, propSchema] of Object.entries(shape)) {
|
|
19077
|
-
const
|
|
19078
|
-
extractDescriptions(propSchema,
|
|
19137
|
+
const path2 = prefix ? `${prefix}.${key}` : key;
|
|
19138
|
+
extractDescriptions(propSchema, path2, result);
|
|
19079
19139
|
}
|
|
19080
19140
|
}
|
|
19081
19141
|
return result;
|
|
@@ -19117,11 +19177,11 @@ ${spaces}}`;
|
|
|
19117
19177
|
function generateConfig(obj, indent, pathPrefix, descs) {
|
|
19118
19178
|
const spaces = " ".repeat(indent);
|
|
19119
19179
|
return Object.entries(obj).map(([key, value]) => {
|
|
19120
|
-
const
|
|
19121
|
-
const desc = descs.get(
|
|
19180
|
+
const path2 = pathPrefix ? `${pathPrefix}.${key}` : key;
|
|
19181
|
+
const desc = descs.get(path2);
|
|
19122
19182
|
const comment = desc ? ` // ${desc}` : "";
|
|
19123
19183
|
if (typeof value === "object" && value !== null && !Array.isArray(value)) {
|
|
19124
|
-
const nested = generateConfig(value, indent + 1,
|
|
19184
|
+
const nested = generateConfig(value, indent + 1, path2, descs);
|
|
19125
19185
|
return `${spaces}${formatKey(key)}: {
|
|
19126
19186
|
${nested}
|
|
19127
19187
|
${spaces}},`;
|
|
@@ -19131,7 +19191,6 @@ ${spaces}},`;
|
|
|
19131
19191
|
`);
|
|
19132
19192
|
}
|
|
19133
19193
|
function buildConfigTs(input) {
|
|
19134
|
-
const modelDefaults = GATEWAY_MODEL_DEFAULTS[input.gateway];
|
|
19135
19194
|
const fullConfig = {
|
|
19136
19195
|
appPrefix: input.appPrefix,
|
|
19137
19196
|
appName: input.appName,
|
|
@@ -19160,7 +19219,7 @@ function buildConfigTs(input) {
|
|
|
19160
19219
|
terms: { title: "Terms of Service" }
|
|
19161
19220
|
},
|
|
19162
19221
|
authentication: input.auth,
|
|
19163
|
-
|
|
19222
|
+
ai: { gateway: input.gateway },
|
|
19164
19223
|
anonymous: {
|
|
19165
19224
|
credits: 10,
|
|
19166
19225
|
availableTools: [],
|
|
@@ -19177,15 +19236,9 @@ function buildConfigTs(input) {
|
|
|
19177
19236
|
"image/jpeg": [".jpg", ".jpeg"],
|
|
19178
19237
|
"application/pdf": [".pdf"]
|
|
19179
19238
|
}
|
|
19180
|
-
},
|
|
19181
|
-
deepResearch: {
|
|
19182
|
-
allowClarification: true,
|
|
19183
|
-
maxResearcherIterations: 1,
|
|
19184
|
-
maxConcurrentResearchUnits: 2,
|
|
19185
|
-
maxSearchQueries: 2
|
|
19186
19239
|
}
|
|
19187
19240
|
};
|
|
19188
|
-
return `import
|
|
19241
|
+
return `import { defineConfig } from "@/lib/config-schema";
|
|
19189
19242
|
|
|
19190
19243
|
/**
|
|
19191
19244
|
* ChatJS Configuration
|
|
@@ -19193,9 +19246,9 @@ function buildConfigTs(input) {
|
|
|
19193
19246
|
* Edit this file to customize your app.
|
|
19194
19247
|
* @see https://chatjs.dev/docs/reference/config
|
|
19195
19248
|
*/
|
|
19196
|
-
const config
|
|
19249
|
+
const config = defineConfig({
|
|
19197
19250
|
${generateConfig(fullConfig, 1, "", descriptions)}
|
|
19198
|
-
};
|
|
19251
|
+
});
|
|
19199
19252
|
|
|
19200
19253
|
export default config;
|
|
19201
19254
|
`;
|
|
@@ -19514,10 +19567,10 @@ import { dirname, join, resolve } from "node:path";
|
|
|
19514
19567
|
import { fileURLToPath } from "node:url";
|
|
19515
19568
|
|
|
19516
19569
|
// src/utils/run-command.ts
|
|
19517
|
-
import { spawn } from "node:child_process";
|
|
19570
|
+
import { spawn as spawn2 } from "node:child_process";
|
|
19518
19571
|
async function runCommand(command, args, cwd) {
|
|
19519
19572
|
await new Promise((resolvePromise, rejectPromise) => {
|
|
19520
|
-
const child =
|
|
19573
|
+
const child = spawn2(command, args, { cwd, stdio: "pipe" });
|
|
19521
19574
|
const stderr = [];
|
|
19522
19575
|
child.stderr?.on("data", (data) => {
|
|
19523
19576
|
stderr.push(String(data));
|
|
@@ -19552,20 +19605,6 @@ async function scaffoldFromGit(url2, destination) {
|
|
|
19552
19605
|
await rm(join(destination, ".git"), { recursive: true, force: true });
|
|
19553
19606
|
}
|
|
19554
19607
|
|
|
19555
|
-
// src/utils/get-package-manager.ts
|
|
19556
|
-
function inferPackageManager() {
|
|
19557
|
-
const ua = process.env.npm_config_user_agent ?? "";
|
|
19558
|
-
if (ua.startsWith("pnpm/"))
|
|
19559
|
-
return "pnpm";
|
|
19560
|
-
if (ua.startsWith("yarn/"))
|
|
19561
|
-
return "yarn";
|
|
19562
|
-
if (ua.startsWith("npm/"))
|
|
19563
|
-
return "npm";
|
|
19564
|
-
if (ua.startsWith("bun/"))
|
|
19565
|
-
return "bun";
|
|
19566
|
-
return "bun";
|
|
19567
|
-
}
|
|
19568
|
-
|
|
19569
19608
|
// ../../node_modules/ora/index.js
|
|
19570
19609
|
import process10 from "node:process";
|
|
19571
19610
|
|
|
@@ -21056,4 +21095,5 @@ process.on("SIGTERM", () => process.exit(0));
|
|
|
21056
21095
|
var program2 = new Command().name("chat-js").description("ChatJS CLI").version(package_default.version, "-v, --version", "display the version number");
|
|
21057
21096
|
program2.addCommand(create, { isDefault: true });
|
|
21058
21097
|
program2.addCommand(add);
|
|
21098
|
+
program2.addCommand(config2);
|
|
21059
21099
|
program2.parse();
|
package/package.json
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
1
|
{
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
2
|
+
"name": "@chat-js/cli",
|
|
3
|
+
"version": "0.3.0",
|
|
4
|
+
"description": "CLI for creating and extending ChatJS apps",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "https://github.com/franciscomoretti/chat-js.git",
|
|
9
|
+
"directory": "packages/cli"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/franciscomoretti/chat-js/tree/main/packages/cli",
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/franciscomoretti/chat-js/issues"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"chatjs",
|
|
17
|
+
"ai",
|
|
18
|
+
"cli",
|
|
19
|
+
"scaffold",
|
|
20
|
+
"nextjs"
|
|
21
|
+
],
|
|
22
|
+
"dependencies": {
|
|
23
|
+
"@clack/prompts": "^1.0.1",
|
|
24
|
+
"commander": "^14.0.0",
|
|
25
|
+
"kleur": "^4.1.5",
|
|
26
|
+
"ora": "^8.2.0",
|
|
27
|
+
"zod": "^4.3.6"
|
|
28
|
+
},
|
|
29
|
+
"bin": {
|
|
30
|
+
"chat-js": "./dist/index.js"
|
|
31
|
+
},
|
|
32
|
+
"files": [
|
|
33
|
+
"dist",
|
|
34
|
+
"templates"
|
|
35
|
+
],
|
|
36
|
+
"private": false,
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"access": "public"
|
|
39
|
+
},
|
|
40
|
+
"scripts": {
|
|
41
|
+
"start": "bun src/index.ts",
|
|
42
|
+
"build": "bun build ./src/index.ts --target=node --format=esm --outfile ./dist/index.js",
|
|
43
|
+
"template:sync": "bun ../../scripts/sync-template.ts",
|
|
44
|
+
"prepublishOnly": "bun run template:sync && bun run build && node ./dist/index.js --help >/dev/null"
|
|
45
|
+
},
|
|
46
|
+
"type": "module",
|
|
47
|
+
"devDependencies": {
|
|
48
|
+
"@types/bun": "latest"
|
|
49
|
+
}
|
|
50
50
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# @chatjs/chat
|
|
2
|
+
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#94](https://github.com/FranciscoMoretti/chat-js/pull/94) [`2a8a7cc`](https://github.com/FranciscoMoretti/chat-js/commit/2a8a7cc2b0649bd73e41999dbf0528a21e8065be) Thanks [@FranciscoMoretti](https://github.com/FranciscoMoretti)! - ## Config defaults & `defineConfig` helper
|
|
8
|
+
|
|
9
|
+
### New features
|
|
10
|
+
|
|
11
|
+
- **`defineConfig()` helper** — new type-safe wrapper for `chat.config.ts`. The gateway type is inferred from `ai.gateway`, so autocomplete and type errors are scoped to the model IDs available in the chosen gateway. Replace `satisfies ConfigInput` with `defineConfig({...})`.
|
|
12
|
+
- **Gateway-specific defaults** — all AI config fields (models, tools, workflows) are now optional. Omitted fields are automatically filled from per-gateway defaults at runtime via `applyDefaults()`. Only `ai.gateway` is required.
|
|
13
|
+
- **`chatjs config` CLI command** — new command that prints the fully-resolved configuration for the current project, applying all defaults. Useful for debugging and verifying your setup.
|
|
14
|
+
- **Separate defaults per gateway** — `vercel`, `openrouter`, `openai`, and `openai-compatible` each have their own typed defaults (`ModelDefaultsFor<G>`), ensuring model IDs are validated against the correct gateway's model registry.
|
|
15
|
+
- **Stricter image/video tool schemas** — `tools.image` and `tools.video` now use a discriminated union: `enabled: true` requires a `default` model, while `enabled: false` makes it optional.
|
|
16
|
+
|
|
17
|
+
### Breaking changes
|
|
18
|
+
|
|
19
|
+
None — existing configs using `satisfies ConfigInput` continue to work. Migrating to `defineConfig()` is recommended for better DX but not required.
|
|
@@ -12,11 +12,15 @@ export async function generateTitleFromUserMessage({
|
|
|
12
12
|
}) {
|
|
13
13
|
const { text: title } = await generateText({
|
|
14
14
|
model: await getLanguageModel(config.ai.workflows.title),
|
|
15
|
-
system:
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
15
|
+
system: `Generate a concise title for a chat conversation based on the user's first message.
|
|
16
|
+
|
|
17
|
+
Rules (strictly follow all):
|
|
18
|
+
- Maximum 40 characters — hard limit, never exceed this
|
|
19
|
+
- 3-6 words is ideal
|
|
20
|
+
- No quotes, colons, or punctuation at the end
|
|
21
|
+
- No filler words like "How to" or "Question about"
|
|
22
|
+
- Use title case
|
|
23
|
+
- Return ONLY the title, nothing else`,
|
|
20
24
|
prompt: JSON.stringify(message),
|
|
21
25
|
experimental_telemetry: { isEnabled: true },
|
|
22
26
|
});
|