clanka 0.6.2 → 0.7.1
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/CodeChunker.d.ts.map +1 -1
- package/dist/CodeChunker.js +17 -2
- package/dist/CodeChunker.js.map +1 -1
- package/dist/CodeChunker.test.js +49 -2
- package/dist/CodeChunker.test.js.map +1 -1
- package/dist/SemanticSearch.js +2 -2
- package/dist/SemanticSearch.js.map +1 -1
- package/dist/Xai.d.ts +19 -0
- package/dist/Xai.d.ts.map +1 -0
- package/dist/Xai.js +40 -0
- package/dist/Xai.js.map +1 -0
- package/dist/Xai.test.d.ts +2 -0
- package/dist/Xai.test.d.ts.map +1 -0
- package/dist/Xai.test.js +105 -0
- package/dist/Xai.test.js.map +1 -0
- package/dist/XaiAuth.d.ts +43 -0
- package/dist/XaiAuth.d.ts.map +1 -0
- package/dist/XaiAuth.js +172 -0
- package/dist/XaiAuth.js.map +1 -0
- package/dist/XaiAuth.test.d.ts +2 -0
- package/dist/XaiAuth.test.d.ts.map +1 -0
- package/dist/XaiAuth.test.js +354 -0
- package/dist/XaiAuth.test.js.map +1 -0
- package/dist/cli.js +23 -14
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/CodeChunker.test.ts +62 -2
- package/src/CodeChunker.ts +30 -2
- package/src/SemanticSearch.ts +2 -2
- package/src/Xai.test.ts +160 -0
- package/src/Xai.ts +57 -0
- package/src/XaiAuth.test.ts +495 -0
- package/src/XaiAuth.ts +272 -0
- package/src/cli.ts +30 -22
- package/src/index.ts +5 -0
package/dist/cli.js
CHANGED
|
@@ -11,6 +11,7 @@ import * as Acp from "./Acp.js";
|
|
|
11
11
|
import * as AgentExecutor from "./AgentExecutor.js";
|
|
12
12
|
import * as Codex from "./Codex.js";
|
|
13
13
|
import * as Copilot from "./Copilot.js";
|
|
14
|
+
import * as Xai from "./Xai.js";
|
|
14
15
|
import * as Agent from "./Agent.js";
|
|
15
16
|
import * as Compaction from "./Compaction.js";
|
|
16
17
|
import * as Stream from "effect/Stream";
|
|
@@ -28,11 +29,13 @@ import { OpenAiClient, OpenAiEmbeddingModel } from "@effect/ai-openai";
|
|
|
28
29
|
import { DeviceCodeHandler } from "./index.js";
|
|
29
30
|
import packageJson from "../package.json" with { type: "json" };
|
|
30
31
|
const version = packageJson.version;
|
|
31
|
-
const providers = ["openai", "copilot"];
|
|
32
|
+
const providers = ["openai", "copilot", "xai"];
|
|
32
33
|
const withSubagentModel = (model) => Layer.merge(model, Agent.layerSubagentModel(model));
|
|
33
34
|
const modelLayer = (provider, model, effort) => provider === "openai"
|
|
34
35
|
? withSubagentModel(Codex.modelWebSocket(model, { reasoning: { effort: effort } })).pipe(Layer.provide(Codex.layerClient))
|
|
35
|
-
:
|
|
36
|
+
: provider === "xai"
|
|
37
|
+
? withSubagentModel(Xai.model(model, { reasoning: { effort: effort } })).pipe(Layer.provide(Xai.layerClient))
|
|
38
|
+
: withSubagentModel(Copilot.model(model, { reasoning: { effort } })).pipe(Layer.provide(Copilot.layerClient));
|
|
36
39
|
const parseModelId = (modelId) => {
|
|
37
40
|
const [provider, model, effort, ...rest] = modelId.split("/");
|
|
38
41
|
return provider !== undefined &&
|
|
@@ -57,19 +60,13 @@ const provider = Flag.Literals("provider", providers).pipe(Flag.withAlias("p"),
|
|
|
57
60
|
title: "copilot",
|
|
58
61
|
value: "copilot",
|
|
59
62
|
},
|
|
63
|
+
{
|
|
64
|
+
title: "xai",
|
|
65
|
+
value: "xai",
|
|
66
|
+
},
|
|
60
67
|
],
|
|
61
68
|
})));
|
|
62
|
-
const model = Flag.String("model").pipe(Flag.withAlias("m"), Flag.
|
|
63
|
-
message: "Enter a model",
|
|
64
|
-
default: "gpt-6-astra/medium",
|
|
65
|
-
validate(value) {
|
|
66
|
-
const parts = value.split("/");
|
|
67
|
-
if (parts.length !== 2) {
|
|
68
|
-
return Effect.fail("Invalid model");
|
|
69
|
-
}
|
|
70
|
-
return Effect.succeed(value);
|
|
71
|
-
},
|
|
72
|
-
})));
|
|
69
|
+
const model = Flag.String("model").pipe(Flag.withAlias("m"), Flag.optional);
|
|
73
70
|
const semantic = Flag.Directory("search").pipe(Flag.withDescription("Directory for semantic search data (uses OPENAI_API_KEY env var)"), Flag.withAlias("s"), Flag.optional);
|
|
74
71
|
const prompt = Flag.String("prompt").pipe(Flag.withDescription("Pass a prompt in non-interactive mode"), Flag.optional);
|
|
75
72
|
// Kill switch: `--no-compaction` or CLANKA_COMPACTION=false.
|
|
@@ -111,7 +108,19 @@ Command.make("clanka", {
|
|
|
111
108
|
compaction,
|
|
112
109
|
}).pipe(Command.withHandler(Effect.fnUntraced(function* ({ provider, model: modelRaw, semantic, prompt: nonInteractivePrompt, }) {
|
|
113
110
|
const stdio = yield* Stdio.Stdio;
|
|
114
|
-
const
|
|
111
|
+
const selectedModel = yield* Option.match(modelRaw, {
|
|
112
|
+
onSome: Effect.succeed,
|
|
113
|
+
onNone: () => Prompt.String({
|
|
114
|
+
message: "Enter a model",
|
|
115
|
+
default: provider === "xai" ? "grok-4.6/high" : "gpt-6-astra/medium",
|
|
116
|
+
validate(value) {
|
|
117
|
+
return value.split("/").length === 2
|
|
118
|
+
? Effect.succeed(value)
|
|
119
|
+
: Effect.fail("Invalid model");
|
|
120
|
+
},
|
|
121
|
+
}),
|
|
122
|
+
});
|
|
123
|
+
const [model, reasoning] = selectedModel.split("/");
|
|
115
124
|
const Model = modelLayer(provider, model, reasoning);
|
|
116
125
|
return yield* Effect.gen(function* () {
|
|
117
126
|
const agent = yield* Agent.Agent;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAA;AACpD,OAAO,KAAK,cAAc,MAAM,sCAAsC,CAAA;AACtE,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAA;AACtD,OAAO,KAAK,IAAI,MAAM,0BAA0B,CAAA;AAChD,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAA;AAClE,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAChE,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAA;AAC1E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAE/D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAA;AAInC,MAAM,SAAS,GAA4B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":";AACA,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,MAAM,MAAM,4BAA4B,CAAA;AACpD,OAAO,KAAK,cAAc,MAAM,sCAAsC,CAAA;AACtE,OAAO,KAAK,OAAO,MAAM,6BAA6B,CAAA;AACtD,OAAO,KAAK,IAAI,MAAM,0BAA0B,CAAA;AAChD,OAAO,KAAK,YAAY,MAAM,oCAAoC,CAAA;AAClE,OAAO,KAAK,WAAW,MAAM,mCAAmC,CAAA;AAChE,OAAO,KAAK,UAAU,MAAM,kCAAkC,CAAA;AAC9D,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AACvC,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAC/B,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AACnC,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAC7C,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,IAAI,EAAE,MAAM,iBAAiB,CAAA;AACtC,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,IAAI,MAAM,aAAa,CAAA;AACnC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AAGvC,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,KAAK,aAAa,MAAM,2CAA2C,CAAA;AAC1E,OAAO,KAAK,MAAM,MAAM,eAAe,CAAA;AACvC,OAAO,EAAE,YAAY,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AACtE,OAAO,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAC9C,OAAO,WAAW,MAAM,iBAAiB,CAAC,OAAO,IAAI,EAAE,MAAM,EAAE,CAAA;AAE/D,MAAM,OAAO,GAAG,WAAW,CAAC,OAAO,CAAA;AAInC,MAAM,SAAS,GAA4B,CAAC,QAAQ,EAAE,SAAS,EAAE,KAAK,CAAC,CAAA;AAEvE,MAAM,iBAAiB,GAAG,CACxB,KAIC,EACD,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,EAAE,KAAK,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAA;AAExD,MAAM,UAAU,GAAG,CAAC,QAAkB,EAAE,KAAa,EAAE,MAAc,EAAE,EAAE,CACvE,QAAQ,KAAK,QAAQ;IACnB,CAAC,CAAC,iBAAiB,CACf,KAAK,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAa,EAAE,EAAE,CAAC,CACtE,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC,CAAC,QAAQ,KAAK,KAAK;QAClB,CAAC,CAAC,iBAAiB,CACf,GAAG,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,MAAa,EAAE,EAAE,CAAC,CAC3D,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QACxC,CAAC,CAAC,iBAAiB,CAAC,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,EAAE,SAAS,EAAE,EAAE,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CACrE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,WAAW,CAAC,CACnC,CAAA;AAET,MAAM,YAAY,GAAG,CAAC,OAAe,EAAE,EAAE;IACvC,MAAM,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAA;IAC7D,OAAO,QAAQ,KAAK,SAAS;QAC3B,SAAS,CAAC,QAAQ,CAAC,QAAoB,CAAC;QACxC,KAAK,KAAK,SAAS;QACnB,MAAM,KAAK,SAAS;QACpB,IAAI,CAAC,MAAM,KAAK,CAAC;QACjB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,QAAQ,EAAE,QAAoB,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAChE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAA;AACnB,CAAC,CAAA;AAED,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAChC,MAAM,CAAC,KAAK,CACV,MAAM,CAAC,UAAU,CACf,CAAC,OAAe,EAAE,EAAE,CAClB,MAAM,CAAC,MAAM,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACpC,kBAAkB,OAAO,yCAAyC,CACrE,CACF,CACF,CAAA;AAED,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC,IAAI,CACxD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EACnB,IAAI,CAAC,kBAAkB,CACrB,MAAM,CAAC,MAAM,CAAC;IACZ,OAAO,EAAE,mBAAmB;IAC5B,OAAO,EAAE;QACP;YACE,KAAK,EAAE,QAAQ;YACf,KAAK,EAAE,QAAQ;YACf,QAAQ,EAAE,IAAI;SACf;QACD;YACE,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,SAAS;SACjB;QACD;YACE,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,KAAK;SACb;KACF;CACF,CAAC,CACH,CACF,CAAA;AAED,MAAM,KAAK,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAA;AAE3E,MAAM,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC,IAAI,CAC5C,IAAI,CAAC,eAAe,CAClB,kEAAkE,CACnE,EACD,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EACnB,IAAI,CAAC,QAAQ,CACd,CAAA;AAED,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,IAAI,CACvC,IAAI,CAAC,eAAe,CAAC,uCAAuC,CAAC,EAC7D,IAAI,CAAC,QAAQ,CACd,CAAA;AAED,6DAA6D;AAC7D,MAAM,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,YAAY,CAAC,CAAC,IAAI,CAChD,IAAI,CAAC,eAAe,CAClB,mKAAmK,CACpK,EACD,IAAI,CAAC,kBAAkB,CACrB,MAAM,CAAC,OAAO,CAAC,mBAAmB,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CACnE,CACF,CAAA;AAED,MAAM,GAAG,GAAG,KAAK,CAAC,MAAM,CACtB,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAE7B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC,IAAI,CACrE,MAAM,CAAC,MAAM,CAAC,GAAG,EAAE,CACjB,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAChC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CACjD,CACF,CACF,CAAA;IACD,OAAO,aAAa,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC,CAAA;AACvE,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC,CAAA;AAEzC,MAAM,MAAM,GAAG,CAAC,SAAiB,EAAE,EAAE,CACnC,KAAK,CAAC,MAAM,CACV,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;IAClB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC,IAAI,CAC1D,MAAM,CAAC,MAAM,CACd,CAAA;IAED,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,KAAK,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAA;QACrD,OAAO,KAAK,CAAC,KAAK,CAAA;IACpB,CAAC;IAED,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,IAAI,CAAA;IAE7B,MAAM,cAAc,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,OAAO,CAC1C,GAAG,EAAE,CAAC,MAAM,CAAC,qBAAqB,CAAC,CACpC,CAAA;IAED,OAAO,cAAc,CAAC,KAAK,CAAC;QAC1B,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE;QACxB,QAAQ,EAAE,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,eAAe,CAAC;KAChD,CAAC,CAAC,IAAI,CACL,KAAK,CAAC,OAAO,CACX,oBAAoB,CAAC,KAAK,CAAC,wBAAwB,EAAE;QACnD,UAAU,EAAE,IAAI;KACjB,CAAC,CACH,EACD,KAAK,CAAC,OAAO,CACX,YAAY,CAAC,KAAK,CAAC;QACjB,MAAM,EAAE,MAAM,CAAC,KAAK;KACrB,CAAC,CACH,CACF,CAAA;AACH,CAAC,CAAC,CACH,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,KAAK,EAAE,cAAc,CAAC,WAAW,CAAC,CAAC,CAAC,CAAA;AAEzE,MAAM,QAAQ,GAAG,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CACxC,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,EACnB,IAAI,CAAC,eAAe,CAClB,8EAA8E,CAC/E,EACD,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EACxB,IAAI,CAAC,WAAW,CAAC,2BAA2B,CAAC,CAC9C,CAAA;AAED,MAAM,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,CAAC,CAAC,IAAI,CACnE,OAAO,CAAC,eAAe,CACrB,yDAAyD,CAC1D,EACD,OAAO,CAAC,WAAW,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAChC,GAAG,CAAC,QAAQ,CAAC;IACX,OAAO;IACP,YAAY,EAAE,KAAK;IACnB,SAAS,EAAE,CAAC,GAAG,EAAE,EAAE,CACjB,KAAK,CAAC,IAAI,CAAC,IAAI,CACb,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,UAAU,CAAC,EAAE,SAAS,EAAE,GAAG,EAAE,CAAC,CAAC,CAC7D;IACH,SAAS,EAAE,CAAC,OAAO,EAAE,EAAE,CACrB,MAAM,CAAC,GAAG,CAAC,YAAY,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,CAChE,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAM,CAAC,CACpC;CACJ,CAAC,CACH,EACD,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CACjC,KAAK,CAAC,QAAQ,CACZ,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,IAAI,CAAC,EAClC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,IAAI,CAAC,EACvC,iBAAiB,CAAC,QAAQ,EAC1B,UAAU,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAC3D,CACF,CACF,CAAA;AAED,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE;IACrB,QAAQ;IACR,KAAK;IACL,QAAQ;IACR,MAAM;IACN,UAAU;CACX,CAAC,CAAC,IAAI,CACL,OAAO,CAAC,WAAW,CACjB,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,EAC3B,QAAQ,EACR,KAAK,EAAE,QAAQ,EACf,QAAQ,EACR,MAAM,EAAE,oBAAoB,GAC7B;IACC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;IAChC,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE;QAClD,MAAM,EAAE,MAAM,CAAC,OAAO;QACtB,MAAM,EAAE,GAAG,EAAE,CACX,MAAM,CAAC,MAAM,CAAC;YACZ,OAAO,EAAE,eAAe;YACxB,OAAO,EACL,QAAQ,KAAK,KAAK,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,oBAAoB;YAC7D,QAAQ,CAAC,KAAK;gBACZ,OAAO,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,KAAK,CAAC;oBAClC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;oBACvB,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;YAClC,CAAC;SACF,CAAC;KACL,CAAC,CAAA;IACF,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,aAAa,CAAC,KAAK,CAAC,GAAG,CAAqB,CAAA;IACvE,MAAM,KAAK,GAAG,UAAU,CAAC,QAAQ,EAAE,KAAK,EAAE,SAAS,CAAC,CAAA;IAEpD,OAAO,KAAK,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,QAAQ,CAAC;QAChC,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,KAAK,CAAC,KAAK,CAAA;QAEhC,IAAI,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,EAAE,CAAC;YACxC,OAAO,KAAK,CAAC,CAAC,IAAI,CAChB,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,oBAAoB,CAAC,KAAK,EAAE,CAAC,EAClD,MAAM,CAAC,MAAM,EACb,eAAe,CAAC,MAAM,EAAE,EACxB,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAC3B,CAAA;QACH,CAAC;QAED,OAAO,IAAI,EAAE,CAAC;YACZ,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;gBAClC,OAAO,EAAE,GAAG;aACb,CAAC,CAAA;YAEF,KAAK,CAAC,CAAC,IAAI,CACT,KAAK,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAC,EACtB,MAAM,CAAC,MAAM,EACb,eAAe,CAAC,MAAM,CAAC,EAAE,gBAAgB,EAAE,EAAE,EAAE,CAAC,EAChD,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAC3B,CAAA;YAED,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;QACjB,CAAC;IACH,CAAC,CAAC,CAAC,IAAI,CACL,MAAM,CAAC,OAAO,CAAC;QACb,KAAK,CAAC,UAAU,CAAC;YACf,SAAS,EAAE,OAAO,CAAC,GAAG,EAAE;SACzB,CAAC,CAAC,IAAI,CACL,KAAK,CAAC,OAAO,CACX,MAAM,CAAC,KAAK,CAAC,QAAQ,EAAE;YACrB,MAAM,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,KAAK;YACzB,MAAM,EAAE,MAAM;SACf,CAAC,CACH,CACF;QACD,KAAK;KACN,CAAC,CACH,CAAA;AACH,CAAC,CAAC,CACH,EACD,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,CACzC,KAAK,CAAC,QAAQ,CACZ,KAAK,CAAC,gBAAgB,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,EACnD,UAAU,CAAC,gBAAgB,CAAC,KAAK,CAAC,EAAE,OAAO,EAAE,UAAU,EAAE,CAAC,CAC3D,CACF,EACD,OAAO,CAAC,eAAe,CAAC,CAAC,GAAG,CAAC,CAAC,EAC9B,OAAO,CAAC,GAAG,CAAC;IACV,OAAO;CACR,CAAC,EACF,MAAM,CAAC,OAAO,CAAC;IACb,YAAY,CAAC,KAAK;IAClB,GAAG;IACH,cAAc,CAAC,WAAW;IAC1B,UAAU,CAAC,2BAA2B;IACtC,iBAAiB,CAAC,YAAY;CAC/B,CAAC,EACF,WAAW,CAAC,OAAO,CACpB,CAAA"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;GAEG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;GAEG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;GAEG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA;AAE/B;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,aAAa,MAAM,oBAAoB,CAAA;AACnD,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,UAAU,MAAM,iBAAiB,CAAA;AAE7C;;GAEG;AACH,OAAO,KAAK,KAAK,MAAM,YAAY,CAAA;AAEnC;;GAEG;AACH,OAAO,KAAK,OAAO,MAAM,cAAc,CAAA;AAEvC;;GAEG;AACH,OAAO,KAAK,iBAAiB,MAAM,wBAAwB,CAAA;AAE3D;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,cAAc,MAAM,qBAAqB,CAAA;AAErD;;GAEG;AACH,OAAO,KAAK,eAAe,MAAM,sBAAsB,CAAA;AAEvD;;GAEG;AACH,OAAO,KAAK,WAAW,MAAM,kBAAkB,CAAA;AAE/C;;GAEG;AACH,OAAO,KAAK,GAAG,MAAM,UAAU,CAAA"}
|
package/package.json
CHANGED
package/src/CodeChunker.test.ts
CHANGED
|
@@ -177,14 +177,22 @@ describe("chunkFileContent", () => {
|
|
|
177
177
|
chunkMaxCharacters: 21,
|
|
178
178
|
})
|
|
179
179
|
|
|
180
|
-
expect(chunks).
|
|
180
|
+
expect(chunks.every((chunk) => chunk.content.length <= 21)).toBe(true)
|
|
181
|
+
expect(chunks).toHaveLength(5)
|
|
181
182
|
expect(chunks).toMatchObject([
|
|
182
183
|
{
|
|
183
184
|
startLine: 1,
|
|
184
185
|
endLine: 1,
|
|
185
186
|
name: "demo",
|
|
186
187
|
type: "function",
|
|
187
|
-
content: "export function demo(
|
|
188
|
+
content: "export function demo(",
|
|
189
|
+
},
|
|
190
|
+
{
|
|
191
|
+
startLine: 1,
|
|
192
|
+
endLine: 1,
|
|
193
|
+
name: "demo",
|
|
194
|
+
type: "function",
|
|
195
|
+
content: ") {",
|
|
188
196
|
},
|
|
189
197
|
{
|
|
190
198
|
startLine: 2,
|
|
@@ -239,6 +247,58 @@ describe("chunkFileContent", () => {
|
|
|
239
247
|
])
|
|
240
248
|
})
|
|
241
249
|
|
|
250
|
+
it.each(["src/long.ts", "docs/long.txt"])(
|
|
251
|
+
"splits oversized lines in %s without losing content or line metadata",
|
|
252
|
+
(path) => {
|
|
253
|
+
const longLine = ` const value = "${"x".repeat(25_000)}"`
|
|
254
|
+
const content = [
|
|
255
|
+
"function demo() {",
|
|
256
|
+
longLine,
|
|
257
|
+
" return value",
|
|
258
|
+
"}",
|
|
259
|
+
].join("\n")
|
|
260
|
+
const chunks = chunkFileContent(path, content, {
|
|
261
|
+
chunkSize: 30,
|
|
262
|
+
chunkOverlap: 1,
|
|
263
|
+
chunkMaxCharacters: 10_000,
|
|
264
|
+
})
|
|
265
|
+
|
|
266
|
+
expect(chunks.length).toBeGreaterThan(0)
|
|
267
|
+
expect(chunks.every((chunk) => chunk.content.length <= 10_000)).toBe(true)
|
|
268
|
+
const pieces = chunks.filter((chunk) => chunk.startLine === 2)
|
|
269
|
+
expect(pieces).toHaveLength(3)
|
|
270
|
+
expect(pieces.map((chunk) => chunk.content).join("")).toBe(longLine)
|
|
271
|
+
for (const piece of pieces) {
|
|
272
|
+
expect(piece).toMatchObject({ path, startLine: 2, endLine: 2 })
|
|
273
|
+
if (path.endsWith(".ts")) {
|
|
274
|
+
expect(piece).toMatchObject({ name: "demo", type: "function" })
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
expect(
|
|
278
|
+
chunks.some((chunk) => chunk.content.includes("return value")),
|
|
279
|
+
).toBe(true)
|
|
280
|
+
},
|
|
281
|
+
)
|
|
282
|
+
|
|
283
|
+
it("preserves a line exactly at the character limit", () => {
|
|
284
|
+
const line = "x".repeat(10_000)
|
|
285
|
+
const chunks = chunkFileContent(
|
|
286
|
+
"docs/limit.txt",
|
|
287
|
+
`before\n${line}\nafter`,
|
|
288
|
+
{
|
|
289
|
+
chunkSize: 30,
|
|
290
|
+
chunkOverlap: 0,
|
|
291
|
+
chunkMaxCharacters: 10_000,
|
|
292
|
+
},
|
|
293
|
+
)
|
|
294
|
+
|
|
295
|
+
expect(chunks.map((chunk) => chunk.content)).toEqual([
|
|
296
|
+
"before",
|
|
297
|
+
line,
|
|
298
|
+
"after",
|
|
299
|
+
])
|
|
300
|
+
})
|
|
301
|
+
|
|
242
302
|
it("keeps only the first oversized class segment when methods are present", () => {
|
|
243
303
|
const content = [
|
|
244
304
|
"class Example {",
|
package/src/CodeChunker.ts
CHANGED
|
@@ -821,6 +821,31 @@ const chunkWithLineWindows = (
|
|
|
821
821
|
return out
|
|
822
822
|
}
|
|
823
823
|
|
|
824
|
+
const splitOversizedChunks = (
|
|
825
|
+
chunks: ReadonlyArray<CodeChunk>,
|
|
826
|
+
maxCharacters: number,
|
|
827
|
+
): ReadonlyArray<CodeChunk> =>
|
|
828
|
+
chunks.flatMap((chunk) => {
|
|
829
|
+
if (chunk.content.length <= maxCharacters) {
|
|
830
|
+
return [chunk]
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
// Line-based splitting can only exceed the limit for a single long line.
|
|
834
|
+
// Each piece retains that line number and the original AST metadata.
|
|
835
|
+
const pieces = [] as Array<CodeChunk>
|
|
836
|
+
for (
|
|
837
|
+
let offset = 0;
|
|
838
|
+
offset < chunk.content.length;
|
|
839
|
+
offset += maxCharacters
|
|
840
|
+
) {
|
|
841
|
+
pieces.push({
|
|
842
|
+
...chunk,
|
|
843
|
+
content: chunk.content.slice(offset, offset + maxCharacters),
|
|
844
|
+
})
|
|
845
|
+
}
|
|
846
|
+
return pieces
|
|
847
|
+
})
|
|
848
|
+
|
|
824
849
|
/**
|
|
825
850
|
* @since 1.0.0
|
|
826
851
|
* @category Constructors
|
|
@@ -858,11 +883,14 @@ export const chunkFileContent = (
|
|
|
858
883
|
settings,
|
|
859
884
|
)
|
|
860
885
|
if (astChunks.length > 0) {
|
|
861
|
-
return astChunks
|
|
886
|
+
return splitOversizedChunks(astChunks, settings.chunkMaxCharacters)
|
|
862
887
|
}
|
|
863
888
|
}
|
|
864
889
|
|
|
865
|
-
return
|
|
890
|
+
return splitOversizedChunks(
|
|
891
|
+
chunkWithLineWindows(normalizedPath, lines, settings),
|
|
892
|
+
settings.chunkMaxCharacters,
|
|
893
|
+
)
|
|
866
894
|
}
|
|
867
895
|
|
|
868
896
|
/**
|
package/src/SemanticSearch.ts
CHANGED
|
@@ -37,7 +37,7 @@ const resolveChunkConfig = (options: {
|
|
|
37
37
|
}) => ({
|
|
38
38
|
chunkSize: 30,
|
|
39
39
|
chunkOverlap: 0,
|
|
40
|
-
chunkMaxCharacters: options.chunkMaxCharacters ??
|
|
40
|
+
chunkMaxCharacters: options.chunkMaxCharacters ?? 15_000,
|
|
41
41
|
})
|
|
42
42
|
|
|
43
43
|
export const makeEmbeddingResolver = (
|
|
@@ -51,7 +51,7 @@ export const makeEmbeddingResolver = (
|
|
|
51
51
|
RequestResolver.setDelay(
|
|
52
52
|
options.embeddingRequestDelay ?? Duration.millis(50),
|
|
53
53
|
),
|
|
54
|
-
RequestResolver.batchN(options.embeddingBatchSize ??
|
|
54
|
+
RequestResolver.batchN(options.embeddingBatchSize ?? 32),
|
|
55
55
|
)
|
|
56
56
|
|
|
57
57
|
export const chunkEmbeddingInput = (chunk: CodeChunker.CodeChunk): string => {
|
package/src/Xai.test.ts
ADDED
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
import { assert, describe, it } from "@effect/vitest"
|
|
2
|
+
import * as Effect from "effect/Effect"
|
|
3
|
+
import * as Exit from "effect/Exit"
|
|
4
|
+
import * as Layer from "effect/Layer"
|
|
5
|
+
import * as Stream from "effect/Stream"
|
|
6
|
+
import * as LanguageModel from "effect/unstable/ai/LanguageModel"
|
|
7
|
+
import * as Model from "effect/unstable/ai/Model"
|
|
8
|
+
import {
|
|
9
|
+
HttpClient,
|
|
10
|
+
type HttpClientRequest,
|
|
11
|
+
HttpClientResponse,
|
|
12
|
+
} from "effect/unstable/http"
|
|
13
|
+
import * as KeyValueStore from "effect/unstable/persistence/KeyValueStore"
|
|
14
|
+
import * as Compaction from "./Compaction.ts"
|
|
15
|
+
import { DeviceCodeHandler } from "./DeviceCodeHandler.ts"
|
|
16
|
+
import * as Public from "./index.ts"
|
|
17
|
+
import * as Xai from "./Xai.ts"
|
|
18
|
+
import { TokenData, toTokenStore } from "./XaiAuth.ts"
|
|
19
|
+
|
|
20
|
+
const capture = () => {
|
|
21
|
+
const requests: Array<HttpClientRequest.HttpClientRequest> = []
|
|
22
|
+
const client = HttpClient.make((request) =>
|
|
23
|
+
Effect.sync(() => {
|
|
24
|
+
requests.push(request)
|
|
25
|
+
return HttpClientResponse.fromWeb(
|
|
26
|
+
request,
|
|
27
|
+
new Response(
|
|
28
|
+
JSON.stringify({
|
|
29
|
+
error: {
|
|
30
|
+
message: "transport probe",
|
|
31
|
+
type: "invalid_request_error",
|
|
32
|
+
},
|
|
33
|
+
}),
|
|
34
|
+
{ status: 400, headers: { "content-type": "application/json" } },
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
}),
|
|
38
|
+
)
|
|
39
|
+
return { requests, layer: Layer.succeed(HttpClient.HttpClient, client) }
|
|
40
|
+
}
|
|
41
|
+
const body = (
|
|
42
|
+
request: HttpClientRequest.HttpClientRequest,
|
|
43
|
+
): Record<string, unknown> => {
|
|
44
|
+
if (request.body._tag !== "Uint8Array") throw new Error("Expected JSON body")
|
|
45
|
+
return JSON.parse(new TextDecoder().decode(request.body.body))
|
|
46
|
+
}
|
|
47
|
+
const seed = Effect.gen(function* () {
|
|
48
|
+
yield* toTokenStore(yield* KeyValueStore.KeyValueStore)
|
|
49
|
+
.set(
|
|
50
|
+
"token",
|
|
51
|
+
new TokenData({
|
|
52
|
+
access: "subscription-token",
|
|
53
|
+
refresh: "refresh",
|
|
54
|
+
expires: Date.now() + 3600000,
|
|
55
|
+
}),
|
|
56
|
+
)
|
|
57
|
+
.pipe(Effect.orDie)
|
|
58
|
+
})
|
|
59
|
+
const noLogin = Layer.succeed(DeviceCodeHandler, {
|
|
60
|
+
onCode: () => Effect.die("Cached credentials must not prompt"),
|
|
61
|
+
})
|
|
62
|
+
|
|
63
|
+
describe("Xai provider", () => {
|
|
64
|
+
it("exports Xai, but not XaiAuth, from the public entry point", () => {
|
|
65
|
+
assert.strictEqual(Public.Xai, Xai)
|
|
66
|
+
assert.isFalse("XaiAuth" in Public)
|
|
67
|
+
assert.strictEqual(Xai.model("grok-4.6").provider, "xai")
|
|
68
|
+
})
|
|
69
|
+
|
|
70
|
+
for (const effort of [undefined, "low"] as const) {
|
|
71
|
+
it.effect(
|
|
72
|
+
"uses authenticated HTTP Responses with " +
|
|
73
|
+
(effort ?? "default high") +
|
|
74
|
+
" reasoning",
|
|
75
|
+
() =>
|
|
76
|
+
Effect.gen(function* () {
|
|
77
|
+
yield* seed
|
|
78
|
+
const http = capture()
|
|
79
|
+
yield* Effect.gen(function* () {
|
|
80
|
+
assert.lengthOf(
|
|
81
|
+
http.requests,
|
|
82
|
+
0,
|
|
83
|
+
"Client construction must not trigger login or inference",
|
|
84
|
+
)
|
|
85
|
+
assert.strictEqual(yield* Model.ProviderName, "xai")
|
|
86
|
+
assert.strictEqual(yield* Model.ModelName, "grok-4.6")
|
|
87
|
+
const ai = yield* LanguageModel.LanguageModel
|
|
88
|
+
const exit = yield* ai
|
|
89
|
+
.streamText({ prompt: "hello" })
|
|
90
|
+
.pipe(Stream.runDrain, Effect.exit)
|
|
91
|
+
assert.isTrue(Exit.isFailure(exit))
|
|
92
|
+
}).pipe(
|
|
93
|
+
Effect.provide(
|
|
94
|
+
Xai.model(
|
|
95
|
+
"grok-4.6",
|
|
96
|
+
effort === undefined ? undefined : { reasoning: { effort } },
|
|
97
|
+
).pipe(
|
|
98
|
+
Layer.provide(Xai.layerClient),
|
|
99
|
+
Layer.provide(http.layer),
|
|
100
|
+
Layer.provide(noLogin),
|
|
101
|
+
),
|
|
102
|
+
),
|
|
103
|
+
)
|
|
104
|
+
assert.lengthOf(http.requests, 1)
|
|
105
|
+
const request = http.requests[0]!
|
|
106
|
+
assert.strictEqual(request.method, "POST")
|
|
107
|
+
assert.strictEqual(request.url, "https://api.x.ai/v1/responses")
|
|
108
|
+
assert.strictEqual(
|
|
109
|
+
request.headers.authorization,
|
|
110
|
+
"Bearer subscription-token",
|
|
111
|
+
)
|
|
112
|
+
assert.match(request.headers["user-agent"]!, /clanka/i)
|
|
113
|
+
assert.notMatch(request.headers["user-agent"]!, /opencode/i)
|
|
114
|
+
assert.deepInclude(body(request), {
|
|
115
|
+
model: "grok-4.6",
|
|
116
|
+
store: false,
|
|
117
|
+
stream: true,
|
|
118
|
+
})
|
|
119
|
+
assert.deepInclude(body(request).reasoning, {
|
|
120
|
+
effort: effort ?? "high",
|
|
121
|
+
})
|
|
122
|
+
assert.isFalse("max_output_tokens" in body(request))
|
|
123
|
+
}).pipe(Effect.provide(KeyValueStore.layerMemory)),
|
|
124
|
+
)
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
it.effect(
|
|
128
|
+
"caps summaries at 4k without leaking the cap into subsequent requests",
|
|
129
|
+
() =>
|
|
130
|
+
Effect.gen(function* () {
|
|
131
|
+
yield* seed
|
|
132
|
+
const http = capture()
|
|
133
|
+
yield* Effect.gen(function* () {
|
|
134
|
+
const ai = yield* LanguageModel.LanguageModel
|
|
135
|
+
const summarize = yield* Compaction.SummarizerTransform
|
|
136
|
+
yield* summarize(
|
|
137
|
+
ai.streamText({ prompt: "summarize" }).pipe(Stream.runDrain),
|
|
138
|
+
).pipe(Effect.exit)
|
|
139
|
+
yield* ai
|
|
140
|
+
.streamText({ prompt: "continue" })
|
|
141
|
+
.pipe(Stream.runDrain, Effect.exit)
|
|
142
|
+
}).pipe(
|
|
143
|
+
Effect.provide(
|
|
144
|
+
Xai.model("grok-4.6").pipe(
|
|
145
|
+
Layer.provide(Xai.layerClient),
|
|
146
|
+
Layer.provide(http.layer),
|
|
147
|
+
Layer.provide(noLogin),
|
|
148
|
+
),
|
|
149
|
+
),
|
|
150
|
+
)
|
|
151
|
+
assert.lengthOf(http.requests, 2)
|
|
152
|
+
assert.strictEqual(body(http.requests[0]!).max_output_tokens, 4000)
|
|
153
|
+
assert.isFalse("max_output_tokens" in body(http.requests[1]!))
|
|
154
|
+
for (const request of http.requests) {
|
|
155
|
+
assert.strictEqual(request.url, "https://api.x.ai/v1/responses")
|
|
156
|
+
assert.strictEqual(body(request).store, false)
|
|
157
|
+
}
|
|
158
|
+
}).pipe(Effect.provide(KeyValueStore.layerMemory)),
|
|
159
|
+
)
|
|
160
|
+
})
|
package/src/Xai.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @since 1.0.0
|
|
3
|
+
*/
|
|
4
|
+
import { OpenAiClient, OpenAiLanguageModel } from "@effect/ai-openai"
|
|
5
|
+
import * as Layer from "effect/Layer"
|
|
6
|
+
import * as Struct from "effect/Struct"
|
|
7
|
+
import { XaiAuth } from "./XaiAuth.ts"
|
|
8
|
+
import { AgentModelConfig } from "./Agent.ts"
|
|
9
|
+
import * as Compaction from "./Compaction.ts"
|
|
10
|
+
import * as Model from "effect/unstable/ai/Model"
|
|
11
|
+
import type * as LanguageModel from "effect/unstable/ai/LanguageModel"
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* @since 1.0.0
|
|
15
|
+
* @category Layers
|
|
16
|
+
*/
|
|
17
|
+
export const layerClient = OpenAiClient.layer({
|
|
18
|
+
apiUrl: "https://api.x.ai/v1",
|
|
19
|
+
}).pipe(Layer.provide(XaiAuth.layerClient))
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* @since 1.0.0
|
|
23
|
+
* @category Layers
|
|
24
|
+
*/
|
|
25
|
+
export const model = (
|
|
26
|
+
model: string,
|
|
27
|
+
options?:
|
|
28
|
+
| (OpenAiLanguageModel.Config["Service"] & typeof AgentModelConfig.Service)
|
|
29
|
+
| undefined,
|
|
30
|
+
): Model.Model<"xai", LanguageModel.LanguageModel, OpenAiClient.OpenAiClient> =>
|
|
31
|
+
Model.make(
|
|
32
|
+
"xai",
|
|
33
|
+
model,
|
|
34
|
+
Layer.mergeAll(
|
|
35
|
+
OpenAiLanguageModel.layer({
|
|
36
|
+
model,
|
|
37
|
+
config: {
|
|
38
|
+
...Struct.omit(options ?? {}, [
|
|
39
|
+
"systemPromptTransform",
|
|
40
|
+
"supportsImages",
|
|
41
|
+
]),
|
|
42
|
+
store: false,
|
|
43
|
+
reasoning: { effort: "high", ...options?.reasoning },
|
|
44
|
+
},
|
|
45
|
+
}),
|
|
46
|
+
AgentModelConfig.layer({
|
|
47
|
+
systemPromptTransform: options?.systemPromptTransform,
|
|
48
|
+
supportsImages: options?.supportsImages,
|
|
49
|
+
}),
|
|
50
|
+
// Cap compaction summaries; xAI honours max_output_tokens.
|
|
51
|
+
Layer.succeed(Compaction.SummarizerTransform, (effect) =>
|
|
52
|
+
OpenAiLanguageModel.withConfigOverride(effect, {
|
|
53
|
+
max_output_tokens: Compaction.summarizerMaxOutputTokens,
|
|
54
|
+
}),
|
|
55
|
+
),
|
|
56
|
+
),
|
|
57
|
+
)
|