code-ollama 0.0.0 → 0.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/LICENSE +22 -0
- package/README.md +64 -0
- package/dist/cli.js +70 -0
- package/dist/tui-Bu6wAbeu.js +559 -0
- package/dist/utils-DBXrYZEs.js +283 -0
- package/package.json +78 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Menglin "Mark" Xu <mark@remarkablemark.org>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
6
|
+
a copy of this software and associated documentation files (the
|
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
11
|
+
the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be
|
|
14
|
+
included in all copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
# code-ollama
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/code-ollama)
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/code-ollama)
|
|
6
|
+
[](https://github.com/ai-action/code-ollama/actions/workflows/build.yml)
|
|
7
|
+
[](https://codecov.io/gh/ai-action/code-ollama)
|
|
8
|
+
|
|
9
|
+
🦙 [Ollama](https://ollama.com/) coding agent that runs in your terminal.
|
|
10
|
+
|
|
11
|
+
## Quick Start
|
|
12
|
+
|
|
13
|
+
```sh
|
|
14
|
+
npx code-ollama
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Install
|
|
18
|
+
|
|
19
|
+
Install the [CLI](https://www.npmjs.com/package/code-ollama) globally:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npm install --global code-ollama
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
### TUI
|
|
28
|
+
|
|
29
|
+
Open the TUI:
|
|
30
|
+
|
|
31
|
+
```sh
|
|
32
|
+
code-ollama
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
Or use the alias:
|
|
36
|
+
|
|
37
|
+
```sh
|
|
38
|
+
collama
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### CLI
|
|
42
|
+
|
|
43
|
+
Show the version:
|
|
44
|
+
|
|
45
|
+
```sh
|
|
46
|
+
code-ollama --version
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
Show the help:
|
|
50
|
+
|
|
51
|
+
```sh
|
|
52
|
+
code-ollama --help
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Run a one-off prompt:
|
|
56
|
+
|
|
57
|
+
```sh
|
|
58
|
+
# code-ollama run <model> <prompt>
|
|
59
|
+
code-ollama run gemma4 "review diff"
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
## License
|
|
63
|
+
|
|
64
|
+
[MIT](https://github.com/ai-action/code-ollama/blob/master/LICENSE)
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { d as e, i as t, l as n, o as r, r as i, t as a, u as o } from "./utils-DBXrYZEs.js";
|
|
3
|
+
import { realpathSync as s } from "node:fs";
|
|
4
|
+
import c from "cac";
|
|
5
|
+
//#region src/cli.ts
|
|
6
|
+
var l = c("code-ollama");
|
|
7
|
+
l.version(e), l.help(), l.command("run <model> <prompt>", "Run a one-off prompt").action(async (e, t) => {
|
|
8
|
+
try {
|
|
9
|
+
await u(e, t);
|
|
10
|
+
} catch (e) {
|
|
11
|
+
// v8 ignore next
|
|
12
|
+
let t = e instanceof Error ? e.message : "Unknown error";
|
|
13
|
+
process.stderr.write(`Error: ${t}\n`), process.exitCode = 1;
|
|
14
|
+
}
|
|
15
|
+
});
|
|
16
|
+
async function u(e, t) {
|
|
17
|
+
await d([n(), {
|
|
18
|
+
role: o.USER,
|
|
19
|
+
content: t
|
|
20
|
+
}], e), process.stdout.write("\n");
|
|
21
|
+
}
|
|
22
|
+
async function d(e, t) {
|
|
23
|
+
let n = {
|
|
24
|
+
role: o.ASSISTANT,
|
|
25
|
+
content: ""
|
|
26
|
+
};
|
|
27
|
+
for await (let s of r(e, t, a)) {
|
|
28
|
+
if (s.type === "content") {
|
|
29
|
+
n.content += s.content, process.stdout.write(s.content);
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
for (let r of s.tool_calls) {
|
|
33
|
+
let a = await i(r.function.name, r.function.arguments), s = {
|
|
34
|
+
role: o.SYSTEM,
|
|
35
|
+
content: `Tool ${r.function.name} result:\n${a.content}${a.error ? `\nError: ${a.error}` : ""}`
|
|
36
|
+
};
|
|
37
|
+
await d([
|
|
38
|
+
...e,
|
|
39
|
+
n,
|
|
40
|
+
s
|
|
41
|
+
], t);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
async function f(e = process.argv.slice(2)) {
|
|
47
|
+
if (!e.length) {
|
|
48
|
+
let { renderApp: e } = await import("./tui-Bu6wAbeu.js");
|
|
49
|
+
t(), e();
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
l.parse([
|
|
53
|
+
"node",
|
|
54
|
+
"code-ollama",
|
|
55
|
+
...e
|
|
56
|
+
]);
|
|
57
|
+
}
|
|
58
|
+
/* v8 ignore start */
|
|
59
|
+
function p(e = process.argv[1]) {
|
|
60
|
+
if (!e) return !1;
|
|
61
|
+
try {
|
|
62
|
+
return s(e) === import.meta.filename;
|
|
63
|
+
} catch {
|
|
64
|
+
return !1;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
p() && f();
|
|
68
|
+
/* v8 ignore stop */
|
|
69
|
+
//#endregion
|
|
70
|
+
export { f as main };
|
|
@@ -0,0 +1,559 @@
|
|
|
1
|
+
import { a as e, c as t, d as n, l as r, n as i, o as a, r as o, s, t as c, u as l } from "./utils-DBXrYZEs.js";
|
|
2
|
+
import { homedir as u } from "node:os";
|
|
3
|
+
import { Box as d, Text as f, render as p, useInput as m } from "ink";
|
|
4
|
+
import { useCallback as h, useEffect as g, useState as _ } from "react";
|
|
5
|
+
import { Select as v, Spinner as y, TextInput as b } from "@inkjs/ui";
|
|
6
|
+
//#region \0rolldown/runtime.js
|
|
7
|
+
var x = (e, t) => () => (t || (e((t = { exports: {} }).exports, t), e = null), t.exports), S = /* @__PURE__ */ ((e) => typeof require < "u" ? require : typeof Proxy < "u" ? new Proxy(e, { get: (e, t) => (typeof require < "u" ? require : e)[t] }) : e)(function(e) {
|
|
8
|
+
if (typeof require < "u") return require.apply(this, arguments);
|
|
9
|
+
throw Error("Calling `require` for \"" + e + "\" in an environment that doesn't expose the `require` function. See https://rolldown.rs/in-depth/bundling-cjs#require-external-modules for more details.");
|
|
10
|
+
}), C = [{
|
|
11
|
+
name: "/model",
|
|
12
|
+
description: "switch the model"
|
|
13
|
+
}], w = "🦙", T = /* @__PURE__ */ x(((e) => {
|
|
14
|
+
var t = Symbol.for("react.transitional.element"), n = Symbol.for("react.fragment");
|
|
15
|
+
function r(e, n, r) {
|
|
16
|
+
var i = null;
|
|
17
|
+
if (r !== void 0 && (i = "" + r), n.key !== void 0 && (i = "" + n.key), "key" in n) for (var a in r = {}, n) a !== "key" && (r[a] = n[a]);
|
|
18
|
+
else r = n;
|
|
19
|
+
return n = r.ref, {
|
|
20
|
+
$$typeof: t,
|
|
21
|
+
type: e,
|
|
22
|
+
key: i,
|
|
23
|
+
ref: n === void 0 ? null : n,
|
|
24
|
+
props: r
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
e.Fragment = n, e.jsx = r, e.jsxs = r;
|
|
28
|
+
})), E = /* @__PURE__ */ x(((e) => {
|
|
29
|
+
process.env.NODE_ENV !== "production" && (function() {
|
|
30
|
+
function t(e) {
|
|
31
|
+
if (e == null) return null;
|
|
32
|
+
if (typeof e == "function") return e.$$typeof === k ? null : e.displayName || e.name || null;
|
|
33
|
+
if (typeof e == "string") return e;
|
|
34
|
+
switch (e) {
|
|
35
|
+
case _: return "Fragment";
|
|
36
|
+
case y: return "Profiler";
|
|
37
|
+
case v: return "StrictMode";
|
|
38
|
+
case w: return "Suspense";
|
|
39
|
+
case T: return "SuspenseList";
|
|
40
|
+
case O: return "Activity";
|
|
41
|
+
}
|
|
42
|
+
if (typeof e == "object") switch (typeof e.tag == "number" && console.error("Received an unexpected object in getComponentNameFromType(). This is likely a bug in React. Please file an issue."), e.$$typeof) {
|
|
43
|
+
case g: return "Portal";
|
|
44
|
+
case x: return e.displayName || "Context";
|
|
45
|
+
case b: return (e._context.displayName || "Context") + ".Consumer";
|
|
46
|
+
case C:
|
|
47
|
+
var n = e.render;
|
|
48
|
+
return e = e.displayName, e ||= (e = n.displayName || n.name || "", e === "" ? "ForwardRef" : "ForwardRef(" + e + ")"), e;
|
|
49
|
+
case E: return n = e.displayName || null, n === null ? t(e.type) || "Memo" : n;
|
|
50
|
+
case D:
|
|
51
|
+
n = e._payload, e = e._init;
|
|
52
|
+
try {
|
|
53
|
+
return t(e(n));
|
|
54
|
+
} catch {}
|
|
55
|
+
}
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
function n(e) {
|
|
59
|
+
return "" + e;
|
|
60
|
+
}
|
|
61
|
+
function r(e) {
|
|
62
|
+
try {
|
|
63
|
+
n(e);
|
|
64
|
+
var t = !1;
|
|
65
|
+
} catch {
|
|
66
|
+
t = !0;
|
|
67
|
+
}
|
|
68
|
+
if (t) {
|
|
69
|
+
t = console;
|
|
70
|
+
var r = t.error, i = typeof Symbol == "function" && Symbol.toStringTag && e[Symbol.toStringTag] || e.constructor.name || "Object";
|
|
71
|
+
return r.call(t, "The provided key is an unsupported type %s. This value must be coerced to a string before using it here.", i), n(e);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function i(e) {
|
|
75
|
+
if (e === _) return "<>";
|
|
76
|
+
if (typeof e == "object" && e && e.$$typeof === D) return "<...>";
|
|
77
|
+
try {
|
|
78
|
+
var n = t(e);
|
|
79
|
+
return n ? "<" + n + ">" : "<...>";
|
|
80
|
+
} catch {
|
|
81
|
+
return "<...>";
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
function a() {
|
|
85
|
+
var e = A.A;
|
|
86
|
+
return e === null ? null : e.getOwner();
|
|
87
|
+
}
|
|
88
|
+
function o() {
|
|
89
|
+
return Error("react-stack-top-frame");
|
|
90
|
+
}
|
|
91
|
+
function s(e) {
|
|
92
|
+
if (j.call(e, "key")) {
|
|
93
|
+
var t = Object.getOwnPropertyDescriptor(e, "key").get;
|
|
94
|
+
if (t && t.isReactWarning) return !1;
|
|
95
|
+
}
|
|
96
|
+
return e.key !== void 0;
|
|
97
|
+
}
|
|
98
|
+
function c(e, t) {
|
|
99
|
+
function n() {
|
|
100
|
+
P || (P = !0, console.error("%s: `key` is not a prop. Trying to access it will result in `undefined` being returned. If you need to access the same value within the child component, you should pass it as a different prop. (https://react.dev/link/special-props)", t));
|
|
101
|
+
}
|
|
102
|
+
n.isReactWarning = !0, Object.defineProperty(e, "key", {
|
|
103
|
+
get: n,
|
|
104
|
+
configurable: !0
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
function l() {
|
|
108
|
+
var e = t(this.type);
|
|
109
|
+
return F[e] || (F[e] = !0, console.error("Accessing element.ref was removed in React 19. ref is now a regular prop. It will be removed from the JSX Element type in a future release.")), e = this.props.ref, e === void 0 ? null : e;
|
|
110
|
+
}
|
|
111
|
+
function u(e, t, n, r, i, a) {
|
|
112
|
+
var o = n.ref;
|
|
113
|
+
return e = {
|
|
114
|
+
$$typeof: h,
|
|
115
|
+
type: e,
|
|
116
|
+
key: t,
|
|
117
|
+
props: n,
|
|
118
|
+
_owner: r
|
|
119
|
+
}, (o === void 0 ? null : o) === null ? Object.defineProperty(e, "ref", {
|
|
120
|
+
enumerable: !1,
|
|
121
|
+
value: null
|
|
122
|
+
}) : Object.defineProperty(e, "ref", {
|
|
123
|
+
enumerable: !1,
|
|
124
|
+
get: l
|
|
125
|
+
}), e._store = {}, Object.defineProperty(e._store, "validated", {
|
|
126
|
+
configurable: !1,
|
|
127
|
+
enumerable: !1,
|
|
128
|
+
writable: !0,
|
|
129
|
+
value: 0
|
|
130
|
+
}), Object.defineProperty(e, "_debugInfo", {
|
|
131
|
+
configurable: !1,
|
|
132
|
+
enumerable: !1,
|
|
133
|
+
writable: !0,
|
|
134
|
+
value: null
|
|
135
|
+
}), Object.defineProperty(e, "_debugStack", {
|
|
136
|
+
configurable: !1,
|
|
137
|
+
enumerable: !1,
|
|
138
|
+
writable: !0,
|
|
139
|
+
value: i
|
|
140
|
+
}), Object.defineProperty(e, "_debugTask", {
|
|
141
|
+
configurable: !1,
|
|
142
|
+
enumerable: !1,
|
|
143
|
+
writable: !0,
|
|
144
|
+
value: a
|
|
145
|
+
}), Object.freeze && (Object.freeze(e.props), Object.freeze(e)), e;
|
|
146
|
+
}
|
|
147
|
+
function d(e, n, i, o, l, d) {
|
|
148
|
+
var p = n.children;
|
|
149
|
+
if (p !== void 0) if (o) if (M(p)) {
|
|
150
|
+
for (o = 0; o < p.length; o++) f(p[o]);
|
|
151
|
+
Object.freeze && Object.freeze(p);
|
|
152
|
+
} else console.error("React.jsx: Static children should always be an array. You are likely explicitly calling React.jsxs or React.jsxDEV. Use the Babel transform instead.");
|
|
153
|
+
else f(p);
|
|
154
|
+
if (j.call(n, "key")) {
|
|
155
|
+
p = t(e);
|
|
156
|
+
var m = Object.keys(n).filter(function(e) {
|
|
157
|
+
return e !== "key";
|
|
158
|
+
});
|
|
159
|
+
o = 0 < m.length ? "{key: someKey, " + m.join(": ..., ") + ": ...}" : "{key: someKey}", R[p + o] || (m = 0 < m.length ? "{" + m.join(": ..., ") + ": ...}" : "{}", console.error("A props object containing a \"key\" prop is being spread into JSX:\n let props = %s;\n <%s {...props} />\nReact keys must be passed directly to JSX without using spread:\n let props = %s;\n <%s key={someKey} {...props} />", o, p, m, p), R[p + o] = !0);
|
|
160
|
+
}
|
|
161
|
+
if (p = null, i !== void 0 && (r(i), p = "" + i), s(n) && (r(n.key), p = "" + n.key), "key" in n) for (var h in i = {}, n) h !== "key" && (i[h] = n[h]);
|
|
162
|
+
else i = n;
|
|
163
|
+
return p && c(i, typeof e == "function" ? e.displayName || e.name || "Unknown" : e), u(e, p, i, a(), l, d);
|
|
164
|
+
}
|
|
165
|
+
function f(e) {
|
|
166
|
+
p(e) ? e._store && (e._store.validated = 1) : typeof e == "object" && e && e.$$typeof === D && (e._payload.status === "fulfilled" ? p(e._payload.value) && e._payload.value._store && (e._payload.value._store.validated = 1) : e._store && (e._store.validated = 1));
|
|
167
|
+
}
|
|
168
|
+
function p(e) {
|
|
169
|
+
return typeof e == "object" && !!e && e.$$typeof === h;
|
|
170
|
+
}
|
|
171
|
+
var m = S("react"), h = Symbol.for("react.transitional.element"), g = Symbol.for("react.portal"), _ = Symbol.for("react.fragment"), v = Symbol.for("react.strict_mode"), y = Symbol.for("react.profiler"), b = Symbol.for("react.consumer"), x = Symbol.for("react.context"), C = Symbol.for("react.forward_ref"), w = Symbol.for("react.suspense"), T = Symbol.for("react.suspense_list"), E = Symbol.for("react.memo"), D = Symbol.for("react.lazy"), O = Symbol.for("react.activity"), k = Symbol.for("react.client.reference"), A = m.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE, j = Object.prototype.hasOwnProperty, M = Array.isArray, N = console.createTask ? console.createTask : function() {
|
|
172
|
+
return null;
|
|
173
|
+
};
|
|
174
|
+
m = { react_stack_bottom_frame: function(e) {
|
|
175
|
+
return e();
|
|
176
|
+
} };
|
|
177
|
+
var P, F = {}, I = m.react_stack_bottom_frame.bind(m, o)(), L = N(i(o)), R = {};
|
|
178
|
+
e.Fragment = _, e.jsx = function(e, t, n) {
|
|
179
|
+
var r = 1e4 > A.recentlyCreatedOwnerStacks++;
|
|
180
|
+
return d(e, t, n, !1, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
|
|
181
|
+
}, e.jsxs = function(e, t, n) {
|
|
182
|
+
var r = 1e4 > A.recentlyCreatedOwnerStacks++;
|
|
183
|
+
return d(e, t, n, !0, r ? Error("react-stack-top-frame") : I, r ? N(i(e)) : L);
|
|
184
|
+
};
|
|
185
|
+
})();
|
|
186
|
+
})), D = (/* @__PURE__ */ x(((e, t) => {
|
|
187
|
+
process.env.NODE_ENV === "production" ? t.exports = T() : t.exports = E();
|
|
188
|
+
})))();
|
|
189
|
+
function O(e) {
|
|
190
|
+
return e.startsWith("/") ? C.filter((t) => t.name.startsWith(e)) : [];
|
|
191
|
+
}
|
|
192
|
+
function k({ isDisabled: e = !1, onSubmit: t }) {
|
|
193
|
+
let [n, r] = _(""), [i, a] = _(0), [o, s] = _(0), c = O(n), l = n.startsWith("/");
|
|
194
|
+
m((e, t) => {
|
|
195
|
+
if (l) {
|
|
196
|
+
if (t.upArrow) {
|
|
197
|
+
a((e) => Math.max(0, e - 1));
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
if (t.downArrow) {
|
|
201
|
+
a((e) => Math.min(c.length - 1, e + 1));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
if (t.tab && c.length > 0) {
|
|
205
|
+
r((c[i] ?? c[0]).name), a(0), s((e) => e + 1);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}, { isActive: !e && l });
|
|
210
|
+
let u = h((e) => {
|
|
211
|
+
let n = (l && c.length > 0 && c[i] ? c[i].name : e).trim();
|
|
212
|
+
n && (t(n), r(""), a(0), s((e) => e + 1));
|
|
213
|
+
}, [
|
|
214
|
+
l,
|
|
215
|
+
c,
|
|
216
|
+
t,
|
|
217
|
+
i
|
|
218
|
+
]);
|
|
219
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
220
|
+
flexDirection: "column",
|
|
221
|
+
children: [/* @__PURE__ */ (0, D.jsxs)(d, { children: [/* @__PURE__ */ (0, D.jsx)(f, { children: "> " }), /* @__PURE__ */ (0, D.jsx)(b, {
|
|
222
|
+
isDisabled: e,
|
|
223
|
+
defaultValue: n,
|
|
224
|
+
onChange: r,
|
|
225
|
+
onSubmit: u
|
|
226
|
+
}, o)] }), l && c.length > 0 && /* @__PURE__ */ (0, D.jsx)(d, {
|
|
227
|
+
flexDirection: "column",
|
|
228
|
+
marginLeft: 2,
|
|
229
|
+
children: c.map((e, t) => {
|
|
230
|
+
let n = t === i;
|
|
231
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
232
|
+
gap: 3,
|
|
233
|
+
children: [/* @__PURE__ */ (0, D.jsx)(f, {
|
|
234
|
+
color: n ? "cyan" : void 0,
|
|
235
|
+
bold: n,
|
|
236
|
+
children: e.name
|
|
237
|
+
}), /* @__PURE__ */ (0, D.jsx)(f, {
|
|
238
|
+
dimColor: !0,
|
|
239
|
+
children: e.description
|
|
240
|
+
})]
|
|
241
|
+
}, e.name);
|
|
242
|
+
})
|
|
243
|
+
})]
|
|
244
|
+
});
|
|
245
|
+
}
|
|
246
|
+
//#endregion
|
|
247
|
+
//#region src/components/Messages.tsx
|
|
248
|
+
function A(e) {
|
|
249
|
+
switch (e) {
|
|
250
|
+
case l.USER: return "black";
|
|
251
|
+
case l.ASSISTANT: return "blue";
|
|
252
|
+
case l.SYSTEM: return "gray";
|
|
253
|
+
default: return;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
function j({ messages: e, isLoading: t }) {
|
|
257
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
258
|
+
flexDirection: "column",
|
|
259
|
+
children: [e.map((e, t) => /* @__PURE__ */ (0, D.jsx)(d, {
|
|
260
|
+
marginBottom: 1,
|
|
261
|
+
children: /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
262
|
+
color: A(e.role),
|
|
263
|
+
dimColor: e.role === l.SYSTEM,
|
|
264
|
+
children: [e.role === l.USER ? "> " : "", e.content]
|
|
265
|
+
})
|
|
266
|
+
}, t)), t && e[e.length - 1]?.content === "" && /* @__PURE__ */ (0, D.jsx)(d, {
|
|
267
|
+
marginTop: -1,
|
|
268
|
+
marginBottom: 1,
|
|
269
|
+
children: /* @__PURE__ */ (0, D.jsx)(y, { label: "Thinking..." })
|
|
270
|
+
})]
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
//#endregion
|
|
274
|
+
//#region src/components/ToolApproval.tsx
|
|
275
|
+
function M({ toolCall: e, onApprove: t, onReject: n }) {
|
|
276
|
+
let [r, i] = _("yes");
|
|
277
|
+
m((e, a) => {
|
|
278
|
+
a.return ? r === "yes" ? t() : n() : (a.leftArrow || a.rightArrow) && i((e) => e === "yes" ? "no" : "yes");
|
|
279
|
+
// v8 ignore stop
|
|
280
|
+
});
|
|
281
|
+
let a = JSON.stringify(e.function.arguments, null, 2);
|
|
282
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
283
|
+
flexDirection: "column",
|
|
284
|
+
marginY: 1,
|
|
285
|
+
children: [
|
|
286
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
287
|
+
color: "yellow",
|
|
288
|
+
bold: !0,
|
|
289
|
+
children: "⚠️ Tool requires approval:"
|
|
290
|
+
}),
|
|
291
|
+
/* @__PURE__ */ (0, D.jsxs)(d, {
|
|
292
|
+
marginX: 2,
|
|
293
|
+
flexDirection: "column",
|
|
294
|
+
children: [/* @__PURE__ */ (0, D.jsxs)(f, { children: [
|
|
295
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
296
|
+
bold: !0,
|
|
297
|
+
children: "Tool:"
|
|
298
|
+
}),
|
|
299
|
+
" ",
|
|
300
|
+
e.function.name
|
|
301
|
+
] }), /* @__PURE__ */ (0, D.jsxs)(f, { children: [
|
|
302
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
303
|
+
bold: !0,
|
|
304
|
+
children: "Arguments:"
|
|
305
|
+
}),
|
|
306
|
+
" ",
|
|
307
|
+
a
|
|
308
|
+
] })]
|
|
309
|
+
}),
|
|
310
|
+
/* @__PURE__ */ (0, D.jsxs)(d, {
|
|
311
|
+
marginTop: 1,
|
|
312
|
+
gap: 2,
|
|
313
|
+
children: [/* @__PURE__ */ (0, D.jsx)(f, { children: /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
314
|
+
color: r === "yes" ? "green" : void 0,
|
|
315
|
+
children: [r === "yes" ? "▶ " : " ", "✓ Yes (Enter)"]
|
|
316
|
+
}) }), /* @__PURE__ */ (0, D.jsx)(f, { children: /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
317
|
+
color: r === "no" ? "red" : void 0,
|
|
318
|
+
children: [r === "no" ? "▶ " : " ", "✗ No (Esc)"]
|
|
319
|
+
}) })]
|
|
320
|
+
})
|
|
321
|
+
]
|
|
322
|
+
});
|
|
323
|
+
}
|
|
324
|
+
//#endregion
|
|
325
|
+
//#region src/components/Chat.tsx
|
|
326
|
+
function N({ model: e, onCommand: t, autoExecute: n }) {
|
|
327
|
+
let [s, u] = _([r()]), [f, p] = _(0), [m, g] = _(!1), [v, y] = _(null), b = h(async (t) => {
|
|
328
|
+
let r = {
|
|
329
|
+
role: l.ASSISTANT,
|
|
330
|
+
content: ""
|
|
331
|
+
};
|
|
332
|
+
u((e) => [...e, r]);
|
|
333
|
+
try {
|
|
334
|
+
for await (let s of a(t, e, c)) if (s.type === "content") r.content += s.content, u((e) => {
|
|
335
|
+
let t = [...e];
|
|
336
|
+
return t[t.length - 1] = { ...r }, t;
|
|
337
|
+
});
|
|
338
|
+
else if (s.type === "tool_calls") for (let e of s.tool_calls) {
|
|
339
|
+
let a = i.has(e.function.name);
|
|
340
|
+
if (!n && a) {
|
|
341
|
+
y(e), g(!1);
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
let s = await o(e.function.name, e.function.arguments), c = {
|
|
345
|
+
role: l.SYSTEM,
|
|
346
|
+
content: `Tool ${e.function.name} result:\n${s.content}${s.error ? `\nError: ${s.error}` : ""}`
|
|
347
|
+
}, d = [
|
|
348
|
+
...t,
|
|
349
|
+
r,
|
|
350
|
+
c
|
|
351
|
+
];
|
|
352
|
+
u((e) => [...e, c]), await b(d);
|
|
353
|
+
return;
|
|
354
|
+
}
|
|
355
|
+
} catch (e) {
|
|
356
|
+
r.content = `Error: ${e instanceof Error ? e.message : String(e)}`, u((e) => {
|
|
357
|
+
let t = [...e];
|
|
358
|
+
return t[t.length - 1] = { ...r }, t;
|
|
359
|
+
});
|
|
360
|
+
} finally {
|
|
361
|
+
g(!1);
|
|
362
|
+
}
|
|
363
|
+
}, [e, n]), x = h(async (e) => {
|
|
364
|
+
// v8 ignore next
|
|
365
|
+
if (!v) return;
|
|
366
|
+
let t = v;
|
|
367
|
+
if (y(null), g(!0), e) {
|
|
368
|
+
let e = await o(t.function.name, t.function.arguments), n = {
|
|
369
|
+
role: l.SYSTEM,
|
|
370
|
+
content: `Tool ${t.function.name} result:\n${e.content}${e.error ? `\nError: ${e.error}` : ""}`
|
|
371
|
+
}, r = [...s, n];
|
|
372
|
+
u((e) => [...e, n]), await b(r);
|
|
373
|
+
} else {
|
|
374
|
+
let e = {
|
|
375
|
+
role: l.SYSTEM,
|
|
376
|
+
content: `User declined to execute tool ${t.function.name}`
|
|
377
|
+
}, n = [...s, e];
|
|
378
|
+
u((t) => [...t, e]), await b(n);
|
|
379
|
+
}
|
|
380
|
+
}, [
|
|
381
|
+
v,
|
|
382
|
+
s,
|
|
383
|
+
b
|
|
384
|
+
]), S = h(async (e) => {
|
|
385
|
+
let n = e.trim();
|
|
386
|
+
if (!n) return;
|
|
387
|
+
if (p((e) => e + 1), n.startsWith("/")) {
|
|
388
|
+
t(n);
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
g(!0);
|
|
392
|
+
let r = {
|
|
393
|
+
role: l.USER,
|
|
394
|
+
content: n
|
|
395
|
+
};
|
|
396
|
+
u((e) => [...e, r]), await b([...s, r]);
|
|
397
|
+
}, [
|
|
398
|
+
s,
|
|
399
|
+
t,
|
|
400
|
+
b
|
|
401
|
+
]);
|
|
402
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
403
|
+
flexDirection: "column",
|
|
404
|
+
children: [
|
|
405
|
+
/* @__PURE__ */ (0, D.jsx)(j, {
|
|
406
|
+
messages: s.slice(1),
|
|
407
|
+
isLoading: m
|
|
408
|
+
}),
|
|
409
|
+
v && /* @__PURE__ */ (0, D.jsx)(M, {
|
|
410
|
+
toolCall: v,
|
|
411
|
+
onApprove: () => void x(!0),
|
|
412
|
+
onReject: () => void x(!1)
|
|
413
|
+
}),
|
|
414
|
+
!v && /* @__PURE__ */ (0, D.jsx)(k, {
|
|
415
|
+
isDisabled: m,
|
|
416
|
+
onSubmit: (e) => {
|
|
417
|
+
S(e);
|
|
418
|
+
}
|
|
419
|
+
}, f)
|
|
420
|
+
]
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
//#endregion
|
|
424
|
+
//#region src/components/Footer.tsx
|
|
425
|
+
function P({ autoExecute: e, onToggleMode: t }) {
|
|
426
|
+
return m((e, n) => {
|
|
427
|
+
n.tab && n.shift && t();
|
|
428
|
+
}), /* @__PURE__ */ (0, D.jsx)(d, {
|
|
429
|
+
justifyContent: "space-between",
|
|
430
|
+
marginTop: 1,
|
|
431
|
+
children: /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
432
|
+
dimColor: !0,
|
|
433
|
+
children: [
|
|
434
|
+
"Mode: ",
|
|
435
|
+
e ? "Auto" : "Safe",
|
|
436
|
+
" (Shift+Tab to toggle)"
|
|
437
|
+
]
|
|
438
|
+
})
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
//#endregion
|
|
442
|
+
//#region src/components/Header.tsx
|
|
443
|
+
function F(e) {
|
|
444
|
+
let t = u();
|
|
445
|
+
return e.startsWith(t) ? `~${e.slice(t.length)}` : e;
|
|
446
|
+
}
|
|
447
|
+
function I({ model: e }) {
|
|
448
|
+
let t = F(process.cwd());
|
|
449
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
450
|
+
borderStyle: "round",
|
|
451
|
+
flexDirection: "column",
|
|
452
|
+
paddingX: 1,
|
|
453
|
+
children: [
|
|
454
|
+
/* @__PURE__ */ (0, D.jsxs)(f, { children: [/* @__PURE__ */ (0, D.jsxs)(f, {
|
|
455
|
+
bold: !0,
|
|
456
|
+
children: [w, "Code Ollama"]
|
|
457
|
+
}), /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
458
|
+
dimColor: !0,
|
|
459
|
+
children: [
|
|
460
|
+
" (v",
|
|
461
|
+
n,
|
|
462
|
+
")"
|
|
463
|
+
]
|
|
464
|
+
})] }),
|
|
465
|
+
/* @__PURE__ */ (0, D.jsx)(f, { children: " " }),
|
|
466
|
+
/* @__PURE__ */ (0, D.jsxs)(d, { children: [
|
|
467
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
468
|
+
dimColor: !0,
|
|
469
|
+
children: "model:".padEnd(11)
|
|
470
|
+
}),
|
|
471
|
+
/* @__PURE__ */ (0, D.jsxs)(f, { children: [e, " "] }),
|
|
472
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
473
|
+
color: "cyan",
|
|
474
|
+
children: "/model"
|
|
475
|
+
}),
|
|
476
|
+
/* @__PURE__ */ (0, D.jsx)(f, {
|
|
477
|
+
dimColor: !0,
|
|
478
|
+
children: " to switch"
|
|
479
|
+
})
|
|
480
|
+
] }),
|
|
481
|
+
/* @__PURE__ */ (0, D.jsxs)(d, { children: [/* @__PURE__ */ (0, D.jsx)(f, {
|
|
482
|
+
dimColor: !0,
|
|
483
|
+
children: "directory:".padEnd(11)
|
|
484
|
+
}), /* @__PURE__ */ (0, D.jsx)(f, { children: t })] })
|
|
485
|
+
]
|
|
486
|
+
});
|
|
487
|
+
}
|
|
488
|
+
//#endregion
|
|
489
|
+
//#region src/components/ModelPicker.tsx
|
|
490
|
+
function L({ currentModel: t, onSelect: n, onCancel: r }) {
|
|
491
|
+
let [i, a] = _([]), [o, s] = _(null);
|
|
492
|
+
return g(() => {
|
|
493
|
+
async function t() {
|
|
494
|
+
try {
|
|
495
|
+
a((await e()).map((e) => ({
|
|
496
|
+
label: e,
|
|
497
|
+
value: e
|
|
498
|
+
})));
|
|
499
|
+
} catch (e) {
|
|
500
|
+
s(e instanceof Error ? e.message : String(e));
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
t();
|
|
504
|
+
}, []), m((e, t) => {
|
|
505
|
+
t.escape && r();
|
|
506
|
+
}), o ? /* @__PURE__ */ (0, D.jsxs)(f, {
|
|
507
|
+
color: "red",
|
|
508
|
+
children: ["Error loading models: ", o]
|
|
509
|
+
}) : i.length ? /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
510
|
+
flexDirection: "column",
|
|
511
|
+
children: [/* @__PURE__ */ (0, D.jsx)(f, {
|
|
512
|
+
dimColor: !0,
|
|
513
|
+
children: "Select a model (↑↓ + Enter to confirm, Esc to cancel)"
|
|
514
|
+
}), /* @__PURE__ */ (0, D.jsx)(v, {
|
|
515
|
+
options: i,
|
|
516
|
+
defaultValue: t,
|
|
517
|
+
onChange: n
|
|
518
|
+
})]
|
|
519
|
+
}) : /* @__PURE__ */ (0, D.jsx)(y, { label: "Loading models..." });
|
|
520
|
+
}
|
|
521
|
+
//#endregion
|
|
522
|
+
//#region src/components/App.tsx
|
|
523
|
+
function R() {
|
|
524
|
+
let [e, n] = _(() => s().model), [r, i] = _(!1), [a, o] = _(!1), c = h((e) => {
|
|
525
|
+
e === "/model" && i(!0);
|
|
526
|
+
}, []), l = h((e) => {
|
|
527
|
+
n(e), t({ model: e }), i(!1);
|
|
528
|
+
}, []), u = h(() => {
|
|
529
|
+
i(!1);
|
|
530
|
+
}, []);
|
|
531
|
+
return /* @__PURE__ */ (0, D.jsxs)(d, {
|
|
532
|
+
flexDirection: "column",
|
|
533
|
+
children: [
|
|
534
|
+
/* @__PURE__ */ (0, D.jsx)(I, { model: e }),
|
|
535
|
+
r ? /* @__PURE__ */ (0, D.jsx)(L, {
|
|
536
|
+
currentModel: e,
|
|
537
|
+
onSelect: l,
|
|
538
|
+
onCancel: u
|
|
539
|
+
}) : /* @__PURE__ */ (0, D.jsx)(N, {
|
|
540
|
+
model: e,
|
|
541
|
+
onCommand: c,
|
|
542
|
+
autoExecute: a
|
|
543
|
+
}),
|
|
544
|
+
/* @__PURE__ */ (0, D.jsx)(P, {
|
|
545
|
+
autoExecute: a,
|
|
546
|
+
onToggleMode: () => {
|
|
547
|
+
o((e) => !e);
|
|
548
|
+
}
|
|
549
|
+
})
|
|
550
|
+
]
|
|
551
|
+
});
|
|
552
|
+
}
|
|
553
|
+
//#endregion
|
|
554
|
+
//#region src/tui.tsx
|
|
555
|
+
function z() {
|
|
556
|
+
p(/* @__PURE__ */ (0, D.jsx)(R, {}));
|
|
557
|
+
}
|
|
558
|
+
//#endregion
|
|
559
|
+
export { z as renderApp };
|
|
@@ -0,0 +1,283 @@
|
|
|
1
|
+
import { existsSync as e, mkdirSync as t, readFileSync as n, readdirSync as r, writeFileSync as i } from "node:fs";
|
|
2
|
+
import { join as a } from "node:path";
|
|
3
|
+
import { homedir as o } from "node:os";
|
|
4
|
+
import { Ollama as s } from "ollama";
|
|
5
|
+
import { exec as c } from "node:child_process";
|
|
6
|
+
import { promisify as l } from "node:util";
|
|
7
|
+
//#endregion
|
|
8
|
+
//#region src/constants/package.ts
|
|
9
|
+
var u = "0.1.0", d = "You are a coding assistant that helps users write, edit, and understand code. You have access to tools for reading files, writing files, running shell commands, and searching code\n\nFollow these rules:\n1. Always use available tools rather than guessing file contents or code behavior\n2. Read files before editing them to understand context\n3. When writing files, provide complete, working code\n4. Explain your reasoning when making non-trivial changes\n5. Prefer minimal changes that achieve the goal\n6. Confirm with the user before destructive operations\n\nWhen tools return results, incorporate them into your response naturally", f = "Available tools:\n- read_file: Read file contents at a path\n- write_file: Write content to a file (requires approval)\n- edit_file: Make precise edits to a file\n- list_dir: List files in a directory\n- grep_search: Search code with regex\n- run_shell: Execute shell commands (requires approval)\n\nAlways use tools when you need to:\n- Check file contents before referencing them\n- Make file changes\n- Explore project structure\n- Search the codebase", p = {
|
|
10
|
+
USER: "user",
|
|
11
|
+
ASSISTANT: "assistant",
|
|
12
|
+
SYSTEM: "system"
|
|
13
|
+
}, m = {
|
|
14
|
+
READ_FILE: "read_file",
|
|
15
|
+
WRITE_FILE: "write_file",
|
|
16
|
+
RUN_SHELL: "run_shell",
|
|
17
|
+
LIST_DIR: "list_dir",
|
|
18
|
+
GREP_SEARCH: "grep_search",
|
|
19
|
+
VIEW_RANGE: "view_range"
|
|
20
|
+
}, h = "AGENTS.md";
|
|
21
|
+
function g() {
|
|
22
|
+
let t = a(process.cwd(), h);
|
|
23
|
+
if (!e(t)) return null;
|
|
24
|
+
try {
|
|
25
|
+
return n(t, "utf8");
|
|
26
|
+
} catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
function _() {
|
|
31
|
+
let e = [d], t = g();
|
|
32
|
+
return t && e.push("\n\nProject context from AGENTS.md:\n", t), e.push("\n\n", f), e.join("");
|
|
33
|
+
}
|
|
34
|
+
function v() {
|
|
35
|
+
return {
|
|
36
|
+
role: p.SYSTEM,
|
|
37
|
+
content: _()
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/utils/config.ts
|
|
42
|
+
var y = a(o(), ".code-ollama"), b = a(y, "config.json"), x = {
|
|
43
|
+
host: "http://localhost:11434",
|
|
44
|
+
model: "gemma4"
|
|
45
|
+
};
|
|
46
|
+
function S() {
|
|
47
|
+
if (!e(b)) return {};
|
|
48
|
+
try {
|
|
49
|
+
return JSON.parse(n(b, "utf8"));
|
|
50
|
+
} catch {
|
|
51
|
+
return {};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
function C() {
|
|
55
|
+
let e = S();
|
|
56
|
+
return {
|
|
57
|
+
host: process.env.OLLAMA_HOST ?? e.host ?? x.host,
|
|
58
|
+
model: process.env.OLLAMA_MODEL ?? e.model ?? x.model
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
function w(e) {
|
|
62
|
+
let n = {
|
|
63
|
+
...S(),
|
|
64
|
+
...e
|
|
65
|
+
};
|
|
66
|
+
t(y, { recursive: !0 }), i(b, JSON.stringify(n, null, 2) + "\n", "utf8");
|
|
67
|
+
}
|
|
68
|
+
//#endregion
|
|
69
|
+
//#region src/utils/ollama.ts
|
|
70
|
+
var { host: T, model: E } = C(), D = new s({ host: T });
|
|
71
|
+
async function* O(e, t = E, n) {
|
|
72
|
+
let r = await D.chat({
|
|
73
|
+
model: t,
|
|
74
|
+
messages: e,
|
|
75
|
+
stream: !0,
|
|
76
|
+
tools: n
|
|
77
|
+
});
|
|
78
|
+
for await (let e of r) e.message.content && (yield {
|
|
79
|
+
type: "content",
|
|
80
|
+
content: e.message.content
|
|
81
|
+
}), e.message.tool_calls && (yield {
|
|
82
|
+
type: "tool_calls",
|
|
83
|
+
tool_calls: e.message.tool_calls
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
async function k() {
|
|
87
|
+
let { models: e } = await D.list();
|
|
88
|
+
return e.map(({ name: e }) => e);
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/utils/screen.ts
|
|
92
|
+
var A = "\x1Bc";
|
|
93
|
+
function j() {
|
|
94
|
+
process.stdout.write(A);
|
|
95
|
+
}
|
|
96
|
+
//#endregion
|
|
97
|
+
//#region src/utils/tools.ts
|
|
98
|
+
var M = l(c);
|
|
99
|
+
function N(e, t, n, r) {
|
|
100
|
+
return {
|
|
101
|
+
type: "function",
|
|
102
|
+
function: {
|
|
103
|
+
name: e,
|
|
104
|
+
description: t,
|
|
105
|
+
parameters: {
|
|
106
|
+
type: "object",
|
|
107
|
+
properties: n,
|
|
108
|
+
required: r
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
var P = [
|
|
114
|
+
N(m.READ_FILE, "Read the contents of a file at the specified path", { path: {
|
|
115
|
+
type: "string",
|
|
116
|
+
description: "The path to the file to read"
|
|
117
|
+
} }, ["path"]),
|
|
118
|
+
N(m.WRITE_FILE, "Write content to a file at the specified path", {
|
|
119
|
+
path: {
|
|
120
|
+
type: "string",
|
|
121
|
+
description: "The path to the file to write"
|
|
122
|
+
},
|
|
123
|
+
content: {
|
|
124
|
+
type: "string",
|
|
125
|
+
description: "The content to write to the file"
|
|
126
|
+
}
|
|
127
|
+
}, ["path", "content"]),
|
|
128
|
+
N(m.RUN_SHELL, "Execute a shell command", { command: {
|
|
129
|
+
type: "string",
|
|
130
|
+
description: "The shell command to execute"
|
|
131
|
+
} }, ["command"]),
|
|
132
|
+
N(m.LIST_DIR, "List the contents of a directory", { path: {
|
|
133
|
+
type: "string",
|
|
134
|
+
description: "The path to the directory to list"
|
|
135
|
+
} }, ["path"]),
|
|
136
|
+
N(m.GREP_SEARCH, "Search for a pattern in files within a directory", {
|
|
137
|
+
pattern: {
|
|
138
|
+
type: "string",
|
|
139
|
+
description: "The regex pattern to search for"
|
|
140
|
+
},
|
|
141
|
+
path: {
|
|
142
|
+
type: "string",
|
|
143
|
+
description: "The directory path to search in"
|
|
144
|
+
}
|
|
145
|
+
}, ["pattern", "path"]),
|
|
146
|
+
N(m.VIEW_RANGE, "View a specific range of lines from a file", {
|
|
147
|
+
path: {
|
|
148
|
+
type: "string",
|
|
149
|
+
description: "The path to the file"
|
|
150
|
+
},
|
|
151
|
+
start: {
|
|
152
|
+
type: "number",
|
|
153
|
+
description: "The starting line number (1-indexed)"
|
|
154
|
+
},
|
|
155
|
+
end: {
|
|
156
|
+
type: "number",
|
|
157
|
+
description: "The ending line number (inclusive)"
|
|
158
|
+
}
|
|
159
|
+
}, [
|
|
160
|
+
"path",
|
|
161
|
+
"start",
|
|
162
|
+
"end"
|
|
163
|
+
])
|
|
164
|
+
], F = new Set([m.WRITE_FILE, m.RUN_SHELL]);
|
|
165
|
+
async function I(e, t) {
|
|
166
|
+
switch (e) {
|
|
167
|
+
case m.READ_FILE: return L(t.path);
|
|
168
|
+
case m.WRITE_FILE: return R(t.path, t.content);
|
|
169
|
+
case m.RUN_SHELL: return V(t.command);
|
|
170
|
+
case m.LIST_DIR: return H(t.path);
|
|
171
|
+
case m.GREP_SEARCH: return await U(t.pattern, t.path);
|
|
172
|
+
case m.VIEW_RANGE: return W(t.path, t.start, t.end);
|
|
173
|
+
default: return {
|
|
174
|
+
content: "",
|
|
175
|
+
error: `Unknown tool: ${e}`
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
function L(t) {
|
|
180
|
+
try {
|
|
181
|
+
return e(t) ? { content: n(t, "utf8") } : {
|
|
182
|
+
content: "",
|
|
183
|
+
error: `File not found: ${t}`
|
|
184
|
+
};
|
|
185
|
+
} catch (e) {
|
|
186
|
+
return {
|
|
187
|
+
content: "",
|
|
188
|
+
error: `Failed to read file: ${e instanceof Error ? e.message : String(e)}`
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
function R(e, t) {
|
|
193
|
+
try {
|
|
194
|
+
return i(e, t, "utf8"), { content: `File written successfully: ${e}` };
|
|
195
|
+
} catch (e) {
|
|
196
|
+
return {
|
|
197
|
+
content: "",
|
|
198
|
+
error: `Failed to write file: ${e instanceof Error ? e.message : String(e)}`
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
var z = {
|
|
203
|
+
timeout: 3e4,
|
|
204
|
+
maxBuffer: 1024 * 1024
|
|
205
|
+
};
|
|
206
|
+
function B(e) {
|
|
207
|
+
return M(e, z);
|
|
208
|
+
}
|
|
209
|
+
async function V(e) {
|
|
210
|
+
try {
|
|
211
|
+
let { stdout: t, stderr: n } = await B(e);
|
|
212
|
+
return { content: t || n };
|
|
213
|
+
} catch (e) {
|
|
214
|
+
return {
|
|
215
|
+
content: "",
|
|
216
|
+
error: `Command failed: ${e instanceof Error ? e.message : String(e)}`
|
|
217
|
+
};
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function H(t) {
|
|
221
|
+
try {
|
|
222
|
+
return e(t) ? { content: r(t, { withFileTypes: !0 }).map((e) => `[${e.isDirectory() ? "d" : "f"}] ${e.name}`).join("\n") } : {
|
|
223
|
+
content: "",
|
|
224
|
+
error: `Directory not found: ${t}`
|
|
225
|
+
};
|
|
226
|
+
} catch (e) {
|
|
227
|
+
return {
|
|
228
|
+
content: "",
|
|
229
|
+
error: `Failed to list directory: ${e instanceof Error ? e.message : String(e)}`
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
async function U(t, i) {
|
|
234
|
+
try {
|
|
235
|
+
let { stdout: e } = await B(`rg --line-number --no-heading --smart-case "${t.replace(/"/g, "\\\"")}" "${i}"`);
|
|
236
|
+
// v8 ignore next
|
|
237
|
+
return { content: e || "No matches found" };
|
|
238
|
+
} catch {}
|
|
239
|
+
try {
|
|
240
|
+
if (!e(i)) return {
|
|
241
|
+
content: "",
|
|
242
|
+
error: `Directory not found: ${i}`
|
|
243
|
+
};
|
|
244
|
+
let o = new RegExp(t, "g"), s = [];
|
|
245
|
+
function c(e) {
|
|
246
|
+
let t = r(e, { withFileTypes: !0 });
|
|
247
|
+
for (let r of t) {
|
|
248
|
+
let t = a(e, r.name);
|
|
249
|
+
if (r.isDirectory()) !r.name.startsWith(".") && r.name !== "node_modules" && c(t);
|
|
250
|
+
else if (r.isFile()) try {
|
|
251
|
+
let e = n(t, "utf8").split("\n");
|
|
252
|
+
for (let n = 0; n < e.length; n++) o.test(e[n]) && s.push(`${t}:${(n + 1).toString()}: ${e[n].trim()}`), o.lastIndex = 0;
|
|
253
|
+
} catch {}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
return c(i), s.length === 0 ? { content: "No matches found" } : { content: s.join("\n") };
|
|
257
|
+
} catch (e) {
|
|
258
|
+
return {
|
|
259
|
+
content: "",
|
|
260
|
+
error: `Search failed: ${e instanceof Error ? e.message : String(e)}`
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
function W(t, r, i) {
|
|
265
|
+
try {
|
|
266
|
+
if (!e(t)) return {
|
|
267
|
+
content: "",
|
|
268
|
+
error: `File not found: ${t}`
|
|
269
|
+
};
|
|
270
|
+
let a = n(t, "utf8").split("\n"), o = Math.max(0, r - 1), s = Math.min(a.length, i);
|
|
271
|
+
return o >= a.length || o > s ? {
|
|
272
|
+
content: "",
|
|
273
|
+
error: "Invalid line range"
|
|
274
|
+
} : { content: a.slice(o, s).join("\n") };
|
|
275
|
+
} catch (e) {
|
|
276
|
+
return {
|
|
277
|
+
content: "",
|
|
278
|
+
error: `Failed to view range: ${e instanceof Error ? e.message : String(e)}`
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
//#endregion
|
|
283
|
+
export { k as a, w as c, u as d, j as i, v as l, F as n, O as o, I as r, C as s, P as t, p as u };
|
package/package.json
CHANGED
|
@@ -1,4 +1,81 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "code-ollama",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Ollama coding agent that runs in your terminal",
|
|
5
|
+
"author": "Mark <mark@remarkablemark.org> (https://remarkablemark.org)",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"bin": {
|
|
8
|
+
"code-ollama": "./dist/cli.js",
|
|
9
|
+
"collama": "./dist/cli.js"
|
|
10
|
+
},
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "vite build",
|
|
13
|
+
"start": "tsx --tsconfig tsconfig.test.json src/cli.ts",
|
|
14
|
+
"clean": "rm -rf coverage dist docs",
|
|
15
|
+
"lint": "eslint .",
|
|
16
|
+
"lint:fix": "npm run lint -- --fix",
|
|
17
|
+
"lint:package": "publint",
|
|
18
|
+
"lint:tsc": "tsc --build",
|
|
19
|
+
"prepare": "husky",
|
|
20
|
+
"prepublishOnly": "npm run build && npm run lint && npm run lint:tsc && npm run test:ci",
|
|
21
|
+
"test": "vitest run",
|
|
22
|
+
"test:ci": "CI=true npm test -- --color --coverage",
|
|
23
|
+
"test:watch": "vitest --coverage.enabled=false"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "git+https://github.com/ai-action/code-ollama.git"
|
|
28
|
+
},
|
|
29
|
+
"bugs": {
|
|
30
|
+
"url": "https://github.com/ai-action/code-ollama/issues"
|
|
31
|
+
},
|
|
32
|
+
"keywords": [
|
|
33
|
+
"code-ollama",
|
|
34
|
+
"collama",
|
|
35
|
+
"code",
|
|
36
|
+
"ollama",
|
|
37
|
+
"tui",
|
|
38
|
+
"cli",
|
|
39
|
+
"ai"
|
|
40
|
+
],
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@inkjs/ui": "2.0.0",
|
|
43
|
+
"cac": "7.0.0",
|
|
44
|
+
"ink": "7.0.1",
|
|
45
|
+
"ollama": "0.6.3",
|
|
46
|
+
"react": "19.2.5"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@commitlint/cli": "20.5.3",
|
|
50
|
+
"@commitlint/config-conventional": "20.5.3",
|
|
51
|
+
"@eslint/compat": "2.0.5",
|
|
52
|
+
"@eslint/js": "10.0.1",
|
|
53
|
+
"@types/node": "25.6.0",
|
|
54
|
+
"@types/react": "19.2.14",
|
|
55
|
+
"@vitest/coverage-v8": "4.1.5",
|
|
56
|
+
"eslint": "10.3.0",
|
|
57
|
+
"eslint-plugin-prettier": "5.5.5",
|
|
58
|
+
"eslint-plugin-simple-import-sort": "13.0.0",
|
|
59
|
+
"globals": "17.6.0",
|
|
60
|
+
"husky": "9.1.7",
|
|
61
|
+
"ink-testing-library": "4.0.0",
|
|
62
|
+
"lint-staged": "16.4.0",
|
|
63
|
+
"prettier": "3.8.3",
|
|
64
|
+
"publint": "0.3.18",
|
|
65
|
+
"tsx": "4.21.0",
|
|
66
|
+
"typescript": "6.0.3",
|
|
67
|
+
"typescript-eslint": "8.59.1",
|
|
68
|
+
"vite": "8.0.10",
|
|
69
|
+
"vitest": "4.1.5"
|
|
70
|
+
},
|
|
71
|
+
"files": [
|
|
72
|
+
"dist/"
|
|
73
|
+
],
|
|
74
|
+
"funding": [
|
|
75
|
+
{
|
|
76
|
+
"type": "github",
|
|
77
|
+
"url": "https://github.com/sponsors/remarkablemark"
|
|
78
|
+
}
|
|
79
|
+
],
|
|
80
|
+
"license": "MIT"
|
|
4
81
|
}
|