Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
219552a
docs(lastcode): plan Codex thread tools
lastobelus Aug 22, 2026
98c256a
feat(lastcode): add Codex thread inspection (#54)
lastobelus Aug 22, 2026
d790297
feat(lastcode): send messages to live threads (#59)
lastobelus Aug 22, 2026
0972371
feat(lastcode): wait for exact thread replies (#61)
lastobelus Aug 22, 2026
73892c8
fix(lastcode): wait for finalized thread replies
lastobelus Aug 22, 2026
7418681
docs(lastcode): remove completed implementation plan
lastobelus Aug 22, 2026
9f9c2cf
fix(lastcode): finish empty tracked replies
lastobelus Aug 22, 2026
bb369c4
fix(lastcode): wait for assistant finalization
lastobelus Aug 22, 2026
d573e96
test(server): drain correlation reactor deterministically
lastobelus Aug 22, 2026
751be23
fix(lastcode): await complete assistant reply
lastobelus Aug 22, 2026
8aec709
fix(lastcode): interrupt superseded tracked turns
lastobelus Aug 22, 2026
df77a8d
test(server): drain steering ingestion deterministically
lastobelus Aug 22, 2026
06eb1e9
test(server): drain native identity ingestion
lastobelus Aug 22, 2026
d64b633
fix(server): preserve interrupted provider turns
lastobelus Aug 22, 2026
d8980c8
fix(server): finish tool-only tracked waits
lastobelus Aug 22, 2026
d197f2f
perf(server): ignore token wait wakeups
lastobelus Aug 22, 2026
1c80e6a
fix(lastcode): preserve commands in thread tool path
lastobelus Aug 24, 2026
a2c2002
fix(lastcode): wait for provider interruption
lastobelus Aug 24, 2026
56dbc30
fix(lastcode): finish interrupted thread waits
lastobelus Aug 24, 2026
f60fe4a
fix(lastcode): settle abandoned thread waits
lastobelus Aug 24, 2026
8bd2842
test(lastcode): verify aborted wait finalization
lastobelus Aug 24, 2026
f8c41d3
fix(lastcode): reject pending self waits
lastobelus Aug 24, 2026
664512f
fix(lastcode): preserve checkpoint assistant replies
lastobelus Aug 24, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,016 changes: 1,013 additions & 3 deletions apps/server/src/bin.test.ts

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions apps/server/src/bin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { runServerCommand, serveCommand, startCommand } from "./cli/server.ts";
import { serviceCommand } from "./cli/service.ts";
import { servicePreflightCommand } from "./cli/servicePreflight.ts";
import { triageCommand } from "./cli/triage.ts";
import { threadCommand } from "./cli/thread.ts";

const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, NetService.layer);

Expand Down Expand Up @@ -57,6 +58,7 @@ export const makeCli = ({ cloudEnabled = hasCloudPublicConfig } = {}) =>
serviceCommand,
servicePreflightCommand,
triageCommand,
threadCommand,
cloudEnabled ? connectCommand : connectUnavailableCommand,
]),
);
Expand Down
110 changes: 107 additions & 3 deletions apps/server/src/cli/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ import {
} from "@t3tools/contracts";
import * as NetService from "@t3tools/shared/Net";
import * as NodeServices from "@effect/platform-node/NodeServices";
import { deriveServerPaths } from "../config.ts";
import { resolveServerConfig } from "./config.ts";
import { DEFAULT_PORT, deriveServerPaths } from "../config.ts";
import { resolveServerConfig, resolveThreadInspectionConfig } from "./config.ts";

const deriveExplicitServerPaths = (baseDir: string, devUrl: URL | undefined) =>
deriveServerPaths(baseDir, devUrl, { baseDirIsExplicit: true });
Expand Down Expand Up @@ -79,7 +79,7 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => {
host: Option.none(),
baseDir: Option.none(),
cwd: Option.none(),
devUrl: Option.none(),
devUrl: Option.some(new URL("http://127.0.0.1:5173")),
noBrowser: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
Expand Down Expand Up @@ -619,4 +619,108 @@ it.layer(NodeServices.layer)("cli config resolution", (it) => {
});
}),
);

it.effect("pins every derived path to the explicitly active dev state", () =>
Effect.gen(function* () {
const { join } = yield* Path.Path;
const fs = yield* FileSystem.FileSystem;
const baseDir = yield* fs.makeTempDirectoryScoped({ prefix: "thread-active-home-" });
const stateDir = join(baseDir, "dev");
const inheritedDevUrl = new URL("http://127.0.0.1:5173");
const resolved = yield* resolveServerConfig(
{
mode: Option.none(),
port: Option.some(3773),
host: Option.none(),
baseDir: Option.some(baseDir),
cwd: Option.none(),
devUrl: Option.some(inheritedDevUrl),
noBrowser: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
tailscaleServeEnabled: Option.none(),
tailscaleServePort: Option.none(),
},
Option.none(),
{ activeStateDir: Option.some(stateDir) },
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })),
NetService.layer,
),
),
);
assert.equal(resolved.baseDir, baseDir);
assert.equal(resolved.stateDir, stateDir);
assert.equal(resolved.devUrl, inheritedDevUrl);
assert.equal(resolved.dbPath, join(stateDir, "state.sqlite"));
assert.equal(resolved.environmentIdPath, join(stateDir, "environment-id"));
assert.equal(resolved.serverRuntimeStatePath, join(stateDir, "server-runtime.json"));
assert.equal(resolved.secretsDir, join(stateDir, "secrets"));

const userdataStateDir = join(baseDir, "userdata");
const userdata = yield* resolveServerConfig(
{
mode: Option.none(),
port: Option.some(3773),
host: Option.none(),
baseDir: Option.some(baseDir),
cwd: Option.none(),
devUrl: Option.some(new URL("http://127.0.0.1:5173")),
noBrowser: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
tailscaleServeEnabled: Option.none(),
tailscaleServePort: Option.none(),
},
Option.none(),
{ activeStateDir: Option.some(userdataStateDir) },
).pipe(
Effect.provide(
Layer.mergeAll(
ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })),
NetService.layer,
),
),
);
assert.equal(userdata.stateDir, userdataStateDir);
assert.equal(userdata.devUrl?.href, "http://127.0.0.1:5173/");
}).pipe(Effect.scoped),
);

it.effect("derives thread inspection config without probing ports or provisioning paths", () =>
Effect.gen(function* () {
const fs = yield* FileSystem.FileSystem;
const { join } = yield* Path.Path;
const root = yield* fs.makeTempDirectoryScoped({ prefix: "thread-config-read-only-" });
const baseDir = join(root, "missing-home");
let portProbeCount = 0;
const netLayer = Layer.succeed(NetService.NetService, {
canListenOnHost: () => Effect.die("unexpected port probe"),
isPortAvailableOnLoopback: () => Effect.die("unexpected port probe"),
hasListenerOnHost: () => Effect.die("unexpected port probe"),
reserveLoopbackPort: () => Effect.die("unexpected port probe"),
findAvailablePort: () => {
portProbeCount += 1;
return Effect.die("unexpected port probe");
},
});
const resolved = yield* resolveThreadInspectionConfig(
{ baseDir: Option.some(baseDir) },
Option.none(),
).pipe(
Effect.provide(
Layer.mergeAll(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })), netLayer),
),
);

assert.equal(resolved.port, DEFAULT_PORT);
assert.equal(resolved.baseDir, baseDir);
assert.equal(portProbeCount, 0);
assert.isFalse(yield* fs.exists(baseDir));
}).pipe(Effect.scoped),
);
});
88 changes: 65 additions & 23 deletions apps/server/src/cli/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ import { readBootstrapEnvelope } from "../bootstrap.ts";
import * as ServerConfig from "../config.ts";
import { expandHomePath, resolveBaseDir } from "../os-jank.ts";

export class CliLocationError extends Schema.TaggedErrorClass<CliLocationError>()(
"CliLocationError",
{ message: Schema.String },
) {}

export const modeFlag = Flag.choice("mode", ServerConfig.RuntimeMode.literals).pipe(
Flag.withDescription("Runtime mode. `desktop` keeps loopback defaults unless overridden."),
Flag.optional,
Expand Down Expand Up @@ -159,6 +164,7 @@ export interface CliServerFlags {
export interface CliAuthLocationFlags {
readonly baseDir: Option.Option<string>;
readonly devUrl?: Option.Option<URL>;
readonly stateDir?: Option.Option<string>;
}

export const sharedServerLocationFlags = {
Expand Down Expand Up @@ -213,6 +219,9 @@ export const resolveServerConfig = (
options?: {
readonly startupPresentation?: ServerConfig.StartupPresentation;
readonly forceAutoBootstrapProjectFromCwd?: boolean;
readonly activeStateDir?: Option.Option<string>;
readonly provisionPaths?: boolean;
readonly discoverPort?: boolean;
},
) =>
Effect.gen(function* () {
Expand Down Expand Up @@ -259,7 +268,7 @@ export const resolveServerConfig = (
{
onSome: (value) => Effect.succeed(value),
onNone: () => {
if (mode === "desktop") {
if (mode === "desktop" || options?.discoverPort === false) {
return Effect.succeed(ServerConfig.DEFAULT_PORT);
}
return findAvailablePort(ServerConfig.DEFAULT_PORT);
Expand All @@ -281,16 +290,38 @@ export const resolveServerConfig = (
);
const rawCwd = Option.getOrElse(normalizedFlags.cwd, () => process.cwd());
const cwd = path.resolve(yield* expandHomePath(rawCwd.trim()));
yield* fs.makeDirectory(cwd, { recursive: true });
const derivedPaths = yield* ServerConfig.deriveServerPaths(baseDir, devUrl, {
baseDirIsExplicit: Option.isSome(explicitBaseDir),
const provisionPaths = options?.provisionPaths ?? true;
if (provisionPaths) yield* fs.makeDirectory(cwd, { recursive: true });
const requestedStateDir = yield* Option.match(options?.activeStateDir ?? Option.none(), {
onNone: () => Effect.void,
onSome: (value) => Effect.map(expandHomePath(value.trim()), path.resolve),
});
yield* ServerConfig.ensureServerDirectories(derivedPaths);
const userdataStateDir = path.join(baseDir, "userdata");
const devStateDir = path.join(baseDir, "dev");
if (
requestedStateDir !== undefined &&
requestedStateDir !== userdataStateDir &&
requestedStateDir !== devStateDir
) {
return yield* new CliLocationError({
message: "--state-dir must select the userdata or dev directory within --base-dir.",
});
}
const derivedPaths = yield* ServerConfig.deriveServerPaths(
baseDir,
requestedStateDir === userdataStateDir
? undefined
: requestedStateDir === devStateDir
? (devUrl ?? new URL("http://127.0.0.1"))
: devUrl,
{ baseDirIsExplicit: requestedStateDir === undefined && Option.isSome(explicitBaseDir) },
);
if (provisionPaths) yield* ServerConfig.ensureServerDirectories(derivedPaths);
const persistedObservabilitySettings = yield* loadPersistedObservabilitySettings(
derivedPaths.settingsPath,
);
const serverTracePath = env.traceFile ?? derivedPaths.serverTracePath;
yield* fs.makeDirectory(path.dirname(serverTracePath), { recursive: true });
if (provisionPaths) yield* fs.makeDirectory(path.dirname(serverTracePath), { recursive: true });
const startupPresentation = options?.startupPresentation ?? "browser";
const isHeadlessStartup = startupPresentation === "headless";
const noBrowser = Option.getOrElse(
Expand Down Expand Up @@ -391,27 +422,38 @@ export const resolveServerConfig = (
return config;
});

const cliAuthServerFlags = (flags: CliAuthLocationFlags): CliServerFlags => ({
mode: Option.none(),
port: Option.none(),
host: Option.none(),
baseDir: flags.baseDir,
cwd: Option.none(),
devUrl: flags.devUrl ?? Option.none(),
noBrowser: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
tailscaleServeEnabled: Option.none(),
tailscaleServePort: Option.none(),
});

export const resolveCliAuthConfig = (
flags: CliAuthLocationFlags,
cliLogLevel: Option.Option<LogLevel.LogLevel>,
) =>
resolveServerConfig(
{
mode: Option.none(),
port: Option.none(),
host: Option.none(),
baseDir: flags.baseDir,
cwd: Option.none(),
devUrl: flags.devUrl ?? Option.none(),
noBrowser: Option.none(),
bootstrapFd: Option.none(),
autoBootstrapProjectFromCwd: Option.none(),
logWebSocketEvents: Option.none(),
tailscaleServeEnabled: Option.none(),
tailscaleServePort: Option.none(),
},
cliLogLevel,
);
resolveServerConfig(cliAuthServerFlags(flags), cliLogLevel, {
activeStateDir: flags.stateDir ?? Option.none(),
});

export const resolveThreadInspectionConfig = (
flags: CliAuthLocationFlags,
cliLogLevel: Option.Option<LogLevel.LogLevel>,
) =>
resolveServerConfig(cliAuthServerFlags(flags), cliLogLevel, {
activeStateDir: flags.stateDir ?? Option.none(),
provisionPaths: false,
discoverPort: false,
});

const DurationShorthandPattern = /^(?<value>\d+)(?<unit>ms|s|m|h|d|w)$/i;

Expand Down
Loading