Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
4 changes: 3 additions & 1 deletion apps/daemon/e2e/startup.e2e.ts
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,9 @@ async function main(): Promise<void> {
.map((row) => (row as { name: string }).name),
);
sqlite.close();
for (const table of ['__drizzle_migrations', 'sessions', 'workspaces', 'schedules', 'loops']) {
const expectedTables = ['__drizzle_migrations', 'sessions', 'workspaces', 'schedules', 'loops'];
for (let i = 0, len = expectedTables.length; i < len; i++) {
const table = expectedTables[i];
assert(tables.has(table), `missing migrated table ${table}`);
}

Expand Down
3 changes: 2 additions & 1 deletion apps/daemon/scripts/dev-clean.mts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ import { databasePath, runtimeFilePath } from '../src/config';

// Resolves through config.ts so a fork's renamed state dir, the resolved channel, or an active
// LINKCODE_PROFILE cleans the same universe the dev daemon will actually use.
for (const path of [databasePath(), runtimeFilePath()]) rmSync(path, { force: true });
const paths = [databasePath(), runtimeFilePath()];
for (let i = 0, len = paths.length; i < len; i++) rmSync(paths[i], { force: true });
11 changes: 8 additions & 3 deletions apps/daemon/scripts/package-daemon.mts
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ run('pnpm', ['--filter', '@linkcode/daemon', '--prod', 'deploy', '--legacy', out
rmSync(join(outDir, 'dist'), { recursive: true, force: true });
cpSync(join(daemonDir, 'dist'), join(outDir, 'dist'), { recursive: true });

for (const [scope, prefix] of PRUNE) {
for (let i = 0, len = PRUNE.length; i < len; i++) {
const [scope, prefix] = PRUNE[i];
const scopeDir = join(outDir, 'node_modules', scope);
if (!existsSync(scopeDir)) continue;
for (const entry of readdirSync(scopeDir)) {
const entries = readdirSync(scopeDir);
for (let entryIndex = 0, entryCount = entries.length; entryIndex < entryCount; entryIndex++) {
const entry = entries[entryIndex];
if (entry.startsWith(prefix)) rmSync(join(scopeDir, entry), { recursive: true, force: true });
}
}
Expand All @@ -73,7 +76,9 @@ console.log(`daemon packaged at ${outDir} (${Math.round(bytes / 1e6)} MB)`);

function dirSize(dir: string): number {
let total = 0;
for (const entry of readdirSync(dir, { withFileTypes: true })) {
const entries = readdirSync(dir, { withFileTypes: true });
for (let i = 0, len = entries.length; i < len; i++) {
const entry = entries[i];
const full = join(dir, entry.name);
if (entry.isDirectory()) total += dirSize(full);
else if (entry.isFile()) total += statSync(full).size;
Expand Down
10 changes: 8 additions & 2 deletions apps/daemon/src/__tests__/ai-gateway.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,10 +30,16 @@ class FakeChild implements SidecarChildProcess {
this.killed = true;
}
emitStdout(text: string): void {
for (const listener of this.dataListeners) listener(text);
for (let i = 0, len = this.dataListeners.length; i < len; i++) {
const listener = this.dataListeners[i];
listener(text);
}
}
emitExit(code: number | null): void {
for (const listener of this.exitListeners) listener(code);
for (let i = 0, len = this.exitListeners.length; i < len; i++) {
const listener = this.exitListeners[i];
listener(code);
}
}
}

Expand Down
5 changes: 3 additions & 2 deletions apps/daemon/src/__tests__/secrets-vault.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ const noKeyring = (): MasterKey | null => null;
* Secrets are only reachable through a namespace, so every case goes through one. On disk the same
* entry is the full `cloud:session` ref — asserting against that is what proves the prefixing.
*/
const open = (file: string, loadKey: () => MasterKey | null): SecretStore =>
createSecretVault(file, loadKey).namespace('cloud');
function open(file: string, loadKey: () => MasterKey | null): SecretStore {
return createSecretVault(file, loadKey).namespace('cloud');
}

let file: string;
const realPlatform = process.platform;
Expand Down
3 changes: 2 additions & 1 deletion apps/daemon/src/ai-gateway.ts
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,8 @@ export function createAiGatewaySidecar(options: AiGatewaySidecarOptions = {}): T
const pending = [...running.values()];
running.clear();
const settled = await Promise.allSettled(pending);
for (const result of settled) {
for (let i = 0, len = settled.length; i < len; i++) {
const result = settled[i];
if (result.status === 'fulfilled') result.value.child.kill('SIGTERM');
}
},
Expand Down
7 changes: 5 additions & 2 deletions apps/daemon/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,8 @@ function parseAccounts(store: SecretStore, raw: unknown): Parsed<Accounts> {
}
const accounts: Accounts = [];
let migrated = false;
for (const value of raw) {
for (let i = 0, len = raw.length; i < len; i++) {
const value = raw[i];
// The credential secret lives in the vault (CODE-371); merge it back before validating, so a
// secret that is gone fails the schema and lands in the same drop-and-log path as a malformed one.
const attached = withAccountSecret(store, value);
Expand All @@ -214,7 +215,9 @@ function parseProviders(store: SecretStore, raw: unknown): Parsed<ProvidersConfi
}
const providers: ProvidersConfig = {};
let migrated = false;
for (const [key, value] of Object.entries(raw)) {
const entries = Object.entries(raw);
for (let i = 0, len = entries.length; i < len; i++) {
const [key, value] = entries[i];
const kind = AgentKindSchema.safeParse(key);
if (!kind.success) {
logger.warn(
Expand Down
13 changes: 10 additions & 3 deletions apps/daemon/src/diagnostic-sanitizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@ function sanitizeValue(value: unknown, seen: WeakMap<object, unknown>): unknown
seen.set(value, sanitized);
const cause = Reflect.get(value, 'cause');
if (cause !== undefined) sanitized.cause = sanitizeValue(cause, seen);
for (const [key, entry] of Object.entries(value)) {
const entries = Object.entries(value);
for (let i = 0, len = entries.length; i < len; i++) {
const [key, entry] = entries[i];
sanitized[key] = SENSITIVE_KEY.test(key) ? REDACTED : sanitizeValue(entry, seen);
}
return sanitized;
Expand All @@ -49,7 +51,10 @@ function sanitizeValue(value: unknown, seen: WeakMap<object, unknown>): unknown
if (Array.isArray(value)) {
const sanitized: unknown[] = [];
seen.set(value, sanitized);
for (const entry of value) sanitized.push(sanitizeValue(entry, seen));
for (let i = 0, len = value.length; i < len; i++) {
const entry = value[i];
sanitized.push(sanitizeValue(entry, seen));
}
return sanitized;
}

Expand All @@ -59,7 +64,9 @@ function sanitizeValue(value: unknown, seen: WeakMap<object, unknown>): unknown

const sanitized: Record<string, unknown> = {};
seen.set(value, sanitized);
for (const [key, entry] of Object.entries(value)) {
const entries = Object.entries(value);
for (let i = 0, len = entries.length; i < len; i++) {
const [key, entry] = entries[i];
sanitized[key] = SENSITIVE_KEY.test(key) ? REDACTED : sanitizeValue(entry, seen);
}
return sanitized;
Expand Down
4 changes: 3 additions & 1 deletion apps/daemon/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -276,7 +276,9 @@ async function main(): Promise<void> {
const engine = yield* EngineService;
void agentRuntimesReady
.then((agentRuntimes) => {
for (const kind of agentsToRefresh(consentedAgents, agentRuntimes, assets)) {
const agents = agentsToRefresh(consentedAgents, agentRuntimes, assets);
for (let i = 0, len = agents.length; i < len; i++) {
const kind = agents[i];
void assets
.ensure(managedAgentAssetId(kind))
.catch((err) => {
Expand Down
8 changes: 5 additions & 3 deletions apps/daemon/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ export function createDaemonLogger(
name: 'linkcode-daemon',
hooks: {
logMethod(args, method) {
for (let index = 0; index < args.length; index += 1) {
for (let index = 0, len = args.length; index < len; index += 1) {
args[index] = sanitizeDiagnostic(args[index]);
}
method.apply(this, args);
Expand All @@ -78,9 +78,11 @@ export const logger = createDaemonLogger();

function effectBindings(messages: readonly unknown[]): Record<string, string | number> {
const bindings: Record<string, string | number> = { source: 'effect' };
for (const message of messages) {
for (let i = 0, len = messages.length; i < len; i++) {
const message = messages[i];
if (typeof message !== 'object' || message === null) continue;
for (const key of EFFECT_BINDING_KEYS) {
for (let keyIndex = 0, keyCount = EFFECT_BINDING_KEYS.length; keyIndex < keyCount; keyIndex++) {
const key = EFFECT_BINDING_KEYS[keyIndex];
const value = Reflect.get(message, key);
if (typeof value === 'string' || typeof value === 'number') bindings[key] = value;
}
Expand Down
3 changes: 2 additions & 1 deletion apps/daemon/src/loop-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ export function createLoopStore(dbPath: string): LoopStore {
/** Parse each row through its schema; drop and log a row that fails rather than failing the load. */
function parseAll<Row, T>(rows: Row[], parse: (row: Row) => T): T[] {
const parsed: T[] = [];
for (const row of rows) {
for (let i = 0, len = rows.length; i < len; i++) {
const row = rows[i];
try {
parsed.push(parse(row));
} catch {
Expand Down
4 changes: 3 additions & 1 deletion apps/daemon/src/pty/bench-throughput.mts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,9 @@ async function runLinkCodePty(
const pending = new Map<string, { resolve(ms: number): void; reject(error: Error): void }>();

child.stdout.on('data', (chunk: Buffer) => {
for (const frame of decoder.feed(chunk)) {
const frames = decoder.feed(chunk);
for (let i = 0, len = frames.length; i < len; i++) {
const frame = frames[i];
switch (frame.type) {
case OPENED:
case OUTPUT:
Expand Down
13 changes: 10 additions & 3 deletions apps/daemon/src/pty/sidecar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,8 @@ export class SidecarPtyBackend implements PtyBackend {
this.child = child;
child.stdout.on('data', (chunk: Buffer) => {
try {
for (const frame of this.decoder.feed(chunk)) this.handleFrame(frame);
const frames = this.decoder.feed(chunk);
for (let i = 0, len = frames.length; i < len; i++) this.handleFrame(frames[i]);
} catch (err) {
logger.error(
{
Expand Down Expand Up @@ -219,7 +220,10 @@ export class SidecarPtyBackend implements PtyBackend {
const unsub = terminal.exited ? noop : terminal.data.add(cb);
if (!terminal.dataSubscribed) {
terminal.dataSubscribed = true;
for (const data of terminal.bufferedData) cb(data);
for (let i = 0, len = terminal.bufferedData.length; i < len; i++) {
const data = terminal.bufferedData[i];
cb(data);
}
terminal.bufferedData.length = 0;
}
return unsub;
Expand Down Expand Up @@ -271,7 +275,10 @@ export class SidecarPtyBackend implements PtyBackend {
}
this.pending.clear();
const terminalIds = Array.from(this.terminals.keys());
for (const terminalId of terminalIds) this.finish(terminalId, null, false);
for (let i = 0, len = terminalIds.length; i < len; i++) {
const terminalId = terminalIds[i];
this.finish(terminalId, null, false);
}
}
}

Expand Down
3 changes: 2 additions & 1 deletion apps/daemon/src/schedule-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ export function createScheduleStore(dbPath: string): ScheduleStore {
/** Parse each row through its schema; drop and log a row that fails rather than failing the load. */
function parseAll<Row, T>(rows: Row[], parse: (row: Row) => T): T[] {
const parsed: T[] = [];
for (const row of rows) {
for (let i = 0, len = rows.length; i < len; i++) {
const row = rows[i];
try {
parsed.push(parse(row));
} catch {
Expand Down
4 changes: 3 additions & 1 deletion apps/daemon/src/secrets/provider-credentials.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,9 @@ export function detachProviderSecrets(
const stripped: ProvidersConfig = {};
const secrets = new Map<string, string>();

for (const [kind, config] of Object.entries(providers)) {
const entries = Object.entries(providers);
for (let i = 0, len = entries.length; i < len; i++) {
const [kind, config] = entries[i];
const { apiKey, ...rest } = config;
if (apiKey !== undefined) secrets.set(kind, apiKey);
Reflect.set(stripped, kind, rest);
Expand Down
4 changes: 3 additions & 1 deletion apps/daemon/src/secrets/vault.ts
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,9 @@ function parseEntries(raw: unknown, file: string): Map<string, string> {
return new Map();
}
const secrets = new Map<string, string>();
for (const [ref, value] of Object.entries(raw)) {
const entries = Object.entries(raw);
for (let i = 0, len = entries.length; i < len; i++) {
const [ref, value] = entries[i];
if (typeof value === 'string') secrets.set(ref, value);
else logger.warn({ operation: 'secrets.vault', ref }, 'Dropping a malformed stored secret');
}
Expand Down
7 changes: 5 additions & 2 deletions apps/daemon/src/session-store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@ function reconcileMigrationLedger(sqlite: Sqlite.Database, migrationsFolder: str
'UPDATE __drizzle_migrations SET created_at = ? WHERE hash = ? AND created_at <> ?',
);
sqlite.transaction(() => {
for (const migration of readMigrationFiles({ migrationsFolder })) {
const migrations = readMigrationFiles({ migrationsFolder });
for (let i = 0, len = migrations.length; i < len; i++) {
const migration = migrations[i];
realign.run(migration.folderMillis, migration.hash, migration.folderMillis);
}
})();
Expand Down Expand Up @@ -59,7 +61,8 @@ export function createSessionStore(dbPath: string): SessionStore {
.orderBy(asc(sessionRuns.sessionId), asc(sessionRuns.seq))
.all();
const runsBySession = new Map<string, RunRow[]>();
for (const run of runRows) {
for (let i = 0, len = runRows.length; i < len; i++) {
const run = runRows[i];
const bucket = runsBySession.get(run.sessionId);
if (bucket) bucket.push(run);
else runsBySession.set(run.sessionId, [run]);
Expand Down
8 changes: 4 additions & 4 deletions apps/desktop/e2e/browser-broker.e2e.mts
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,11 @@ function createWireClient(): {
} {
const socket = io(`http://127.0.0.1:${PORT}`, { transports: ['websocket'] });
let seq = 0;
const backlog: Record<string, unknown>[] = [];
const waiters: {
const backlog: Array<Record<string, unknown>> = [];
const waiters: Array<{
predicate: (payload: Record<string, unknown>) => boolean;
resolve: (payload: Record<string, unknown>) => void;
}[] = [];
}> = [];
socket.on('frame', (frame: WireFrame) => {
const index = waiters.findIndex((waiter) => waiter.predicate(frame.payload));
if (index === -1) {
Expand Down Expand Up @@ -160,7 +160,7 @@ async function main(): Promise<void> {
url: 'https://example.com/',
});
if (opened.ok !== true) fail(`tabs.open failed: ${JSON.stringify(opened)}`);
const tabs = opened.data as { id: string; url: string | null; active: boolean }[];
const tabs = opened.data as Array<{ id: string; url: string | null; active: boolean }>;
const active = tabs.find((tab) => tab.active);
if (active?.url !== 'https://example.com/') {
fail(`expected an active example.com tab, got ${JSON.stringify(tabs)}`);
Expand Down
3 changes: 2 additions & 1 deletion apps/desktop/e2e/browser-tabs.e2e.mts
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,8 @@ function logPageErrors(page: Page): void {
}

function watchAppErrors(app: ElectronApplication): void {
for (const page of app.windows()) logPageErrors(page);
const pages = app.windows();
for (let i = 0, len = pages.length; i < len; i++) logPageErrors(pages[i]);
app.on('window', logPageErrors);
}

Expand Down
4 changes: 3 additions & 1 deletion apps/desktop/e2e/simulator-live.mts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,9 @@ async function main(): Promise<void> {
await win.waitForTimeout(1200);
}
const plus = win.locator('button[aria-label="Open window"]:visible');
for (const candidate of await plus.all()) {
const candidates = await plus.all();
for (let i = 0, len = candidates.length; i < len; i++) {
const candidate = candidates[i];
try {
await candidate.click({ timeout: 2000 });
break;
Expand Down
10 changes: 7 additions & 3 deletions apps/desktop/e2e/simulator-panel.e2e.mts
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,9 @@ async function run(
let plusTarget = null as Awaited<ReturnType<typeof plus.all>>[number] | null;
const plusDeadline = Date.now() + 15000;
while (plusTarget === null && Date.now() < plusDeadline) {
for (const candidate of await plus.all()) {
const candidates = await plus.all();
for (let i = 0, len = candidates.length; i < len; i++) {
const candidate = candidates[i];
try {
await candidate.click({ trial: true, timeout: 1000 });
plusTarget = candidate;
Expand All @@ -259,7 +261,9 @@ async function run(
await win.screenshot({ path: shot });
console.error(`screenshot: ${shot}`);
console.error(`toggle aria-pressed: ${await toggle.getAttribute('aria-pressed')}`);
for (const candidate of await plus.all()) {
const candidates = await plus.all();
for (let i = 0, len = candidates.length; i < len; i++) {
const candidate = candidates[i];
console.error(`plus box: ${JSON.stringify(await candidate.boundingBox())}`);
}
fail('the section strip + trigger never became clickable');
Expand Down Expand Up @@ -382,7 +386,7 @@ async function run(
ctx.drawImage(source, 0, 0, 32, 64);
const data = ctx.getImageData(0, 0, 32, 64).data;
let hash = 0;
for (let i = 0; i < data.length; i += 16) {
for (let i = 0, len = data.length; i < len; i += 16) {
hash = ((hash * 31 + data[i]) & 0xff_ff_ff) >>> 0;
}
return hash;
Expand Down
4 changes: 3 additions & 1 deletion apps/desktop/scripts/build.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ async function main(): Promise<void> {
const desktopDir = resolve(import.meta.dirname, '..');
// Main goes first: its closeBundle stages out/daemon + out/drizzle, matching electron-vite's
// main → preload → renderer order.
for (const target of ['main', 'preload', 'renderer']) {
const targets = ['main', 'preload', 'renderer'];
for (let i = 0, len = targets.length; i < len; i++) {
const target = targets[i];
await build({ configFile: resolve(desktopDir, `vite.${target}.config.ts`), mode });
}
}
Expand Down
6 changes: 4 additions & 2 deletions apps/desktop/scripts/dev.mts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ async function main(): Promise<void> {
const args = process.argv.slice(2);
const electronArgs: string[] = [];
let mode = 'development';
for (let i = 0; i < args.length; i++) {
for (let i = 0, len = args.length; i < len; i++) {
const arg = args[i];
if (arg === '--') continue;
if (arg === '--mode') {
Expand All @@ -30,7 +30,9 @@ async function main(): Promise<void> {
process.env.NODE_ENV ??= 'development';

const desktopDir = resolve(import.meta.dirname, '..');
for (const target of ['main', 'preload']) {
const targets = ['main', 'preload'];
for (let i = 0, len = targets.length; i < len; i++) {
const target = targets[i];
await build({ configFile: resolve(desktopDir, `vite.${target}.config.ts`), mode });
}

Expand Down
Loading