xcoder-jarvis-agent 1.3.0 → 1.4.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/README.md +23 -4
- package/dist/jarvis/agent.d.ts +1 -8
- package/dist/jarvis/agent.js +9 -10
- package/dist/jarvis/chat/session.d.ts +11 -3
- package/dist/jarvis/chat/session.js +7 -8
- package/dist/jarvis/exit.d.ts +17 -0
- package/dist/jarvis/exit.js +17 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
<!-- xcoder:version
|
|
2
|
-
#
|
|
1
|
+
<!-- xcoder:version 7 | xcoder:task task-691585 | xcoder:updated 2026-11-05T05:50:24.571Z | xcoder:subtask code-st-b5251b -->
|
|
2
|
+
# xcoder-jarvis-agent
|
|
3
3
|
|
|
4
4
|
Jarvis is a ReAct agent that runs as a local CLI inside a developer's
|
|
5
5
|
workspace. It reasons in a bounded loop, reads the workspace through a small
|
|
@@ -12,12 +12,31 @@ TypeScript, npm workspaces, vitest.
|
|
|
12
12
|
## Install and run
|
|
13
13
|
|
|
14
14
|
```bash
|
|
15
|
-
npm run build -w
|
|
15
|
+
npm run build -w xcoder-jarvis-agent
|
|
16
16
|
node packages/jarvis-agent/dist/program.js "summarise how the llm client picks a transport"
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
Once published, the binaries are `jarvis`.
|
|
20
20
|
|
|
21
|
+
### Reaching jarvis through `xcoder`
|
|
22
|
+
|
|
23
|
+
`xcoder` forwards a `jarvis` command to this binary, so you do not have to
|
|
24
|
+
leave it or remember a dist path:
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
xcoder jarvis --chat
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
Every argument is handed over verbatim, stdio is inherited (a chat session
|
|
31
|
+
keeps your terminal), and the exit code is jarvis's own — `xcoder` adds only
|
|
32
|
+
`127` when the binary cannot be found and `130` when the run was interrupted.
|
|
33
|
+
No jarvis flag is re-documented there: run `xcoder jarvis --help` for the
|
|
34
|
+
authoritative list. `jarvis` is one of only three delegable targets, alongside
|
|
35
|
+
`litebro` and `bugfinder`; anything else is refused. Jarvis keeps its own
|
|
36
|
+
environment variables, kill switch and run budget — delegation adds none.
|
|
37
|
+
See [DELEGATION.md](https://github.com/org/xcoder-sdlc/blob/main/docs/DELEGATION.md)
|
|
38
|
+
and [LICENSE](./LICENSE).
|
|
39
|
+
|
|
21
40
|
### Flags
|
|
22
41
|
|
|
23
42
|
| Flag | Meaning | Default |
|
|
@@ -215,7 +234,7 @@ script you were about to run.
|
|
|
215
234
|
## Development
|
|
216
235
|
|
|
217
236
|
```bash
|
|
218
|
-
npm run typecheck -w
|
|
237
|
+
npm run typecheck -w xcoder-jarvis-agent
|
|
219
238
|
npm test # full workspace suite
|
|
220
239
|
npx vitest run packages/jarvis-agent # just this package
|
|
221
240
|
npm run check:boundaries # dependency rules
|
package/dist/jarvis/agent.d.ts
CHANGED
|
@@ -4,14 +4,7 @@ import { type JarvisOutcome } from "./telemetry/provenance.js";
|
|
|
4
4
|
import { type ConfirmFn } from "./util/confirm.js";
|
|
5
5
|
import { type ToolDescriptor } from "./tools/registry.js";
|
|
6
6
|
export declare const JARVIS_AGENT_NAME: "jarvis-agent";
|
|
7
|
-
|
|
8
|
-
export declare const EXIT: {
|
|
9
|
-
readonly answered: 0;
|
|
10
|
-
readonly error: 1;
|
|
11
|
-
readonly iteration_limit: 2;
|
|
12
|
-
readonly budget_exceeded: 3;
|
|
13
|
-
readonly aborted: 4;
|
|
14
|
-
};
|
|
7
|
+
export { EXIT, type ExitCode } from "./exit.js";
|
|
15
8
|
export interface JarvisDeps {
|
|
16
9
|
createClient?: () => LlmCompleter;
|
|
17
10
|
now?: () => Date;
|
package/dist/jarvis/agent.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// xcoder:version
|
|
1
|
+
// xcoder:version 16 | xcoder:task task-482677 | xcoder:updated 2026-11-05T03:51:32.763Z | xcoder:subtask code-st-729fd8
|
|
2
2
|
import fsp from "node:fs/promises";
|
|
3
3
|
import path from "node:path";
|
|
4
4
|
import { createLlmClient, requestScope, shortId, XCODER_VERSION } from "xcoder-dna";
|
|
@@ -6,6 +6,7 @@ import { ArgvError, parseArgv, USAGE } from "./argv.js";
|
|
|
6
6
|
import { BudgetExceeded, clampIterations, DEFAULT_CAPS, RunBudget } from "./budget.js";
|
|
7
7
|
import { CHAT_DIRECTIVE } from "./chat/prompt.js";
|
|
8
8
|
import { runChatSession } from "./chat/session.js";
|
|
9
|
+
import { EXIT } from "./exit.js";
|
|
9
10
|
import { MemoryStore, resolveUserId, workspaceScopeId } from "./memory/store.js";
|
|
10
11
|
import { assembleSystemPrompt } from "./prompt/assemble.js";
|
|
11
12
|
import { POLICY_VERSION, renderPolicy } from "./prompt/policy.js";
|
|
@@ -19,14 +20,9 @@ import { DEFAULT_LIMITS, createToolRegistry } from "./tools/registry.js";
|
|
|
19
20
|
import { FS_TOOLS } from "./tools/fs-tools.js";
|
|
20
21
|
import { MEMORY_TOOLS } from "./tools/memory-tools.js";
|
|
21
22
|
export const JARVIS_AGENT_NAME = "jarvis-agent";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
error: 1,
|
|
26
|
-
iteration_limit: 2,
|
|
27
|
-
budget_exceeded: 3,
|
|
28
|
-
aborted: 4,
|
|
29
|
-
};
|
|
23
|
+
// Re-exported so `EXIT` keeps its documented public path (design §2.3, T7),
|
|
24
|
+
// even though the table itself now lives in a leaf module.
|
|
25
|
+
export { EXIT } from "./exit.js";
|
|
30
26
|
function emit(stream, text) {
|
|
31
27
|
try {
|
|
32
28
|
stream.write(text);
|
|
@@ -70,8 +66,11 @@ export async function runJarvisAgent(argv, deps = {}) {
|
|
|
70
66
|
return EXIT.answered;
|
|
71
67
|
}
|
|
72
68
|
// Chat runs many turns over one stdin/stdout pair; it owns its own loop.
|
|
69
|
+
// `runJarvisAgent` is injected rather than imported by the loop, so the two
|
|
70
|
+
// modules stay a DAG instead of a cycle (the loop calls back into this
|
|
71
|
+
// function once per turn, inheriting the same validation gate).
|
|
73
72
|
if (request.chat) {
|
|
74
|
-
return await runChatSession(request, deps);
|
|
73
|
+
return await runChatSession(request, runJarvisAgent, deps);
|
|
75
74
|
}
|
|
76
75
|
if (request.task.length === 0) {
|
|
77
76
|
emit(stderr, `jarvis: no task given\n\n${USAGE}\n`);
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { JarvisDeps } from "../agent.js";
|
|
2
2
|
import type { JarvisRunRequest } from "../argv.js";
|
|
3
3
|
import { CHAT_DIRECTIVE } from "./prompt.js";
|
|
4
4
|
/**
|
|
@@ -21,6 +21,14 @@ import { CHAT_DIRECTIVE } from "./prompt.js";
|
|
|
21
21
|
* session (K6/AC16/AC17).
|
|
22
22
|
*/
|
|
23
23
|
export type StopReason = "terminator" | "eof" | "max_turns" | "killed";
|
|
24
|
+
/**
|
|
25
|
+
* Executes one single-shot run and returns its exit code.
|
|
26
|
+
*
|
|
27
|
+
* Injected rather than imported: `agent.ts` imports this module, so importing
|
|
28
|
+
* `agent.ts` back would make the two a runtime cycle. Inverting the dependency
|
|
29
|
+
* keeps the graph a DAG and makes the loop trivially fakeable in a test.
|
|
30
|
+
*/
|
|
31
|
+
export type AgentRunner = (argv: readonly string[], deps: JarvisDeps) => Promise<number>;
|
|
24
32
|
export interface ChatResult {
|
|
25
33
|
exitCode: number;
|
|
26
34
|
stopReason: StopReason;
|
|
@@ -32,7 +40,7 @@ export interface ChatResult {
|
|
|
32
40
|
* gate instead of a second, divergent parser.
|
|
33
41
|
*/
|
|
34
42
|
export declare function turnArgv(request: JarvisRunRequest, session: string, text: string): string[];
|
|
35
|
-
export declare function runChatSession(request: JarvisRunRequest, deps?: JarvisDeps): Promise<number>;
|
|
36
|
-
export declare function runChatSessionDetailed(request: JarvisRunRequest, deps?: JarvisDeps): Promise<ChatResult>;
|
|
43
|
+
export declare function runChatSession(request: JarvisRunRequest, runAgent: AgentRunner, deps?: JarvisDeps): Promise<number>;
|
|
44
|
+
export declare function runChatSessionDetailed(request: JarvisRunRequest, runAgent: AgentRunner, deps?: JarvisDeps): Promise<ChatResult>;
|
|
37
45
|
/** Re-exported so a prompt test can pin the constant directive (AC15). */
|
|
38
46
|
export { CHAT_DIRECTIVE };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
|
|
2
|
-
import { EXIT, runJarvisAgent } from "../agent.js";
|
|
1
|
+
import { EXIT } from "../exit.js";
|
|
3
2
|
import { readKillState } from "../util/kill.js";
|
|
4
3
|
import { createChatConfirm } from "./confirm.js";
|
|
5
4
|
import { createStdinLineSource } from "./lines.js";
|
|
@@ -27,18 +26,18 @@ export function turnArgv(request, session, text) {
|
|
|
27
26
|
argv.push("--", text);
|
|
28
27
|
return argv;
|
|
29
28
|
}
|
|
30
|
-
export async function runChatSession(request, deps = {}) {
|
|
29
|
+
export async function runChatSession(request, runAgent, deps = {}) {
|
|
31
30
|
const stderr = deps.stderr ?? process.stderr;
|
|
32
31
|
const workspaceRoot = deps.workspaceRoot ?? process.cwd();
|
|
33
|
-
const result = await driveChat(request, deps, workspaceRoot, stderr);
|
|
32
|
+
const result = await driveChat(request, runAgent, deps, workspaceRoot, stderr);
|
|
34
33
|
return result.exitCode;
|
|
35
34
|
}
|
|
36
|
-
export async function runChatSessionDetailed(request, deps = {}) {
|
|
35
|
+
export async function runChatSessionDetailed(request, runAgent, deps = {}) {
|
|
37
36
|
const stderr = deps.stderr ?? process.stderr;
|
|
38
37
|
const workspaceRoot = deps.workspaceRoot ?? process.cwd();
|
|
39
|
-
return await driveChat(request, deps, workspaceRoot, stderr);
|
|
38
|
+
return await driveChat(request, runAgent, deps, workspaceRoot, stderr);
|
|
40
39
|
}
|
|
41
|
-
async function driveChat(request, deps, workspaceRoot, stderr) {
|
|
40
|
+
async function driveChat(request, runAgent, deps, workspaceRoot, stderr) {
|
|
42
41
|
// A stable session label is what makes the turns one conversation.
|
|
43
42
|
const session = request.session ?? `jarvis-chat-${Date.now().toString(36)}`;
|
|
44
43
|
const lines = deps.lines ?? createStdinLineSource({ stdin: deps.stdin });
|
|
@@ -90,7 +89,7 @@ async function driveChat(request, deps, workspaceRoot, stderr) {
|
|
|
90
89
|
if (isTerminator(next.text)) {
|
|
91
90
|
return { exitCode: EXIT.answered, stopReason: "terminator", turns };
|
|
92
91
|
}
|
|
93
|
-
const code = await
|
|
92
|
+
const code = await runAgent(turnArgv(request, session, next.text), turnDeps);
|
|
94
93
|
turns += 1;
|
|
95
94
|
if (code === EXIT.aborted) {
|
|
96
95
|
return { exitCode: EXIT.aborted, stopReason: "killed", turns };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CLI exit-code contract (design 2.3, tradeoff T7).
|
|
3
|
+
*
|
|
4
|
+
* These live in their own leaf module so the chat loop can name a code without
|
|
5
|
+
* importing `agent.ts`, which itself imports the chat loop. That keeps the
|
|
6
|
+
* module graph a DAG: a cycle would work under ESM only by accident of
|
|
7
|
+
* evaluation order and would break the first time a value were read at module
|
|
8
|
+
* scope.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EXIT: {
|
|
11
|
+
readonly answered: 0;
|
|
12
|
+
readonly error: 1;
|
|
13
|
+
readonly iteration_limit: 2;
|
|
14
|
+
readonly budget_exceeded: 3;
|
|
15
|
+
readonly aborted: 4;
|
|
16
|
+
};
|
|
17
|
+
export type ExitCode = (typeof EXIT)[keyof typeof EXIT];
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
// xcoder:version 1 | xcoder:task task-482677 | xcoder:updated 2026-11-05T03:51:06.005Z | xcoder:subtask code-st-729fd8
|
|
2
|
+
/**
|
|
3
|
+
* The CLI exit-code contract (design 2.3, tradeoff T7).
|
|
4
|
+
*
|
|
5
|
+
* These live in their own leaf module so the chat loop can name a code without
|
|
6
|
+
* importing `agent.ts`, which itself imports the chat loop. That keeps the
|
|
7
|
+
* module graph a DAG: a cycle would work under ESM only by accident of
|
|
8
|
+
* evaluation order and would break the first time a value were read at module
|
|
9
|
+
* scope.
|
|
10
|
+
*/
|
|
11
|
+
export const EXIT = {
|
|
12
|
+
answered: 0,
|
|
13
|
+
error: 1,
|
|
14
|
+
iteration_limit: 2,
|
|
15
|
+
budget_exceeded: 3,
|
|
16
|
+
aborted: 4,
|
|
17
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "xcoder-jarvis-agent",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"description": "Jarvis — a ReAct agent with scoped memory, skill-pack prompt assembly and a code-enforced tool allowlist, built on xcoder-dna.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Neural Node Labs",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"test": "vitest run"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"xcoder-dna": "^1.
|
|
35
|
+
"xcoder-dna": "^1.4.0",
|
|
36
36
|
"zod": "^4.4.3"
|
|
37
37
|
}
|
|
38
38
|
}
|