@visual-z/xeno 0.1.0 → 0.1.2
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 +1 -1
- package/package.json +1 -1
- package/src/apps/startup.ts +23 -2
- package/src/runtime/oauth.ts +1 -1
package/README.md
CHANGED
|
@@ -17,7 +17,7 @@ is ever summarized by a model, and nothing is ever rewritten in place.
|
|
|
17
17
|
messages[] frozen system prefix + handoff + this node's events
|
|
18
18
|
```
|
|
19
19
|
|
|
20
|
-
Version **0.1.
|
|
20
|
+
Version **0.1.2**. The on-disk session format will still change; `0.x` is that
|
|
21
21
|
statement. Published as `@visual-z/xeno`; the license is `UNLICENSED` (readable and installable, no reuse granted).
|
|
22
22
|
|
|
23
23
|
## Install
|
package/package.json
CHANGED
package/src/apps/startup.ts
CHANGED
|
@@ -125,12 +125,29 @@ export function cliSessionConfig(args: Args): { continuationAfter: number; timeB
|
|
|
125
125
|
return { continuationAfter: Infinity, ...(args.timeBudgetMs === undefined ? {} : { timeBudgetMs: args.timeBudgetMs }) };
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
/**
|
|
129
|
+
* Pure: where each kind of state lives for this workspace. Tool observations
|
|
130
|
+
* are not listed: Session keeps them in `<logDir>/artifacts`, inside the
|
|
131
|
+
* session, so fork and copy carry them -- moving sessions moves them too.
|
|
132
|
+
*/
|
|
133
|
+
export function statePaths(workspace: string, stateDir?: string): { blobs: string; sessions: string } {
|
|
134
|
+
const root = stateDir ?? join(workspace, ".xeno");
|
|
135
|
+
return { blobs: join(root, "blobs"), sessions: join(root, "sessions") };
|
|
136
|
+
}
|
|
137
|
+
|
|
128
138
|
export type AskSlot = {
|
|
129
139
|
current?: (request: PermissionRequest) => Promise<ApprovalChoice>;
|
|
130
140
|
};
|
|
131
141
|
|
|
132
142
|
export interface Args {
|
|
133
143
|
workspace: string;
|
|
144
|
+
/**
|
|
145
|
+
* `--state-dir <dir>`: where every xeno write goes -- snapshots, tool
|
|
146
|
+
* observations and, unless --session-dir says otherwise, sessions. Absent
|
|
147
|
+
* means `<workspace>/.xeno`. Evaluations need it outside the workspace:
|
|
148
|
+
* patches and verifiers see whatever is written there.
|
|
149
|
+
*/
|
|
150
|
+
stateDir?: string;
|
|
134
151
|
/** `--time-budget <seconds>`, in ms: when to warn the model its run is nearly out of time. */
|
|
135
152
|
timeBudgetMs?: number;
|
|
136
153
|
/**
|
|
@@ -213,6 +230,7 @@ export interface Args {
|
|
|
213
230
|
const KNOWN_FLAGS: readonly string[] = [
|
|
214
231
|
"--workspace", "-w",
|
|
215
232
|
"--path-root",
|
|
233
|
+
"--state-dir",
|
|
216
234
|
"--time-budget",
|
|
217
235
|
"--log",
|
|
218
236
|
"--max-turns",
|
|
@@ -346,6 +364,7 @@ export function parseArgs(argv: string[]): Args {
|
|
|
346
364
|
const a = argv[i]!;
|
|
347
365
|
if (a === "--workspace" || a === "-w") args.workspace = argv[++i] ?? args.workspace;
|
|
348
366
|
else if (a === "--path-root") args.pathRoot = resolve(argv[++i] ?? "/");
|
|
367
|
+
else if (a === "--state-dir") args.stateDir = resolve(argv[++i] ?? ".");
|
|
349
368
|
else if (a === "--time-budget") {
|
|
350
369
|
const seconds = Number(argv[++i]);
|
|
351
370
|
if (!Number.isFinite(seconds) || seconds <= 0) throw new Error("--time-budget requires a positive number of seconds");
|
|
@@ -447,6 +466,7 @@ export function parseArgs(argv: string[]): Args {
|
|
|
447
466
|
" --no-builtin-tools drops built-ins and keeps any other source; --tools still wins.\n" +
|
|
448
467
|
" bash asks before it runs. --allow-tools bash skips the ask for this process.\n" +
|
|
449
468
|
" --time-budget <seconds> tells the model, once, when 75% of the run's wall-clock budget is used.\n" +
|
|
469
|
+
" --state-dir <dir> keeps snapshots, observations and sessions out of the workspace.\n" +
|
|
450
470
|
" --path-root <dir> lets file tools reach absolute paths under <dir> (e.g. / in a container);\n" +
|
|
451
471
|
" relative paths, fingerprints and /back stay in the workspace, so edits outside it are not rewound.\n" +
|
|
452
472
|
" --approve loads .xeno/settings.json this run; --no-approve skips it.\n" +
|
|
@@ -1098,7 +1118,8 @@ export async function startup(args: Args): Promise<App> {
|
|
|
1098
1118
|
* log stays where it is, still resumable by pointing --log at it. A leftover
|
|
1099
1119
|
* `.xeno/log` from before named sessions is the same: pointed at, not moved.
|
|
1100
1120
|
*/
|
|
1101
|
-
const
|
|
1121
|
+
const paths = statePaths(workspace, args.stateDir);
|
|
1122
|
+
const sessionDir = (args.sessionDir ?? "").length > 0 ? args.sessionDir : args.stateDir !== undefined ? paths.sessions : undefined;
|
|
1102
1123
|
const sessionPick =
|
|
1103
1124
|
(args.session ?? "").length > 0
|
|
1104
1125
|
? args.session
|
|
@@ -1147,7 +1168,7 @@ export async function startup(args: Args): Promise<App> {
|
|
|
1147
1168
|
// read-only branch has nothing to snapshot, but a session a person drives is
|
|
1148
1169
|
// exactly the one that will want to go back, and the content has to have been
|
|
1149
1170
|
// stored before the turn a person wants back -- it cannot be opted into after.
|
|
1150
|
-
const blobDir =
|
|
1171
|
+
const blobDir = paths.blobs;
|
|
1151
1172
|
await mkdir(logDir, { recursive: true });
|
|
1152
1173
|
await mkdir(blobDir, { recursive: true });
|
|
1153
1174
|
|
package/src/runtime/oauth.ts
CHANGED
|
@@ -17,7 +17,7 @@ import { createServer, type Server } from "node:http";
|
|
|
17
17
|
import { pollDeviceCode } from "./oauth-device.ts";
|
|
18
18
|
|
|
19
19
|
/** Matches package.json. Sent as User-Agent so the server can see who we are (D18). */
|
|
20
|
-
export const XENO_VERSION = "0.1.
|
|
20
|
+
export const XENO_VERSION = "0.1.2";
|
|
21
21
|
|
|
22
22
|
/**
|
|
23
23
|
* Minutes subtracted from server expiry so a request issued at the edge
|