refactor: align package folder names with npm package names
CI / check (pull_request) Failing after 8m30s
CI / check (pull_request) Failing after 8m30s
Rename packages/ subdirectories to match their @united-workforce/* scope: cli-workflow → cli workflow-agent-builtin → agent-builtin workflow-agent-claude-code → agent-claude-code workflow-agent-hermes → agent-hermes workflow-dashboard → dashboard workflow-protocol → protocol workflow-util-agent → util-agent workflow-util → util Updated all tsconfig references, scripts, and active docs. Historical docs (docs/plans/, docs/superpowers/) left as-is. Closes #21
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
export { createProcessLogger } from "./process-logger.js";
|
||||
export type {
|
||||
CreateProcessLoggerOptions,
|
||||
ProcessLogFn,
|
||||
ProcessLogger,
|
||||
ProcessLoggerContext,
|
||||
} from "./types.js";
|
||||
@@ -0,0 +1,21 @@
|
||||
import { CROCKFORD_BASE32_ALPHABET } from "../base32.js";
|
||||
|
||||
const TAG_LENGTH = 8;
|
||||
|
||||
const TAG_CHAR_SET: ReadonlySet<string> = new Set(CROCKFORD_BASE32_ALPHABET.split(""));
|
||||
|
||||
export function assertValidLogTag(tag: string): void {
|
||||
if (tag.length !== TAG_LENGTH) {
|
||||
throw new Error(`log tag must be exactly ${TAG_LENGTH} characters`);
|
||||
}
|
||||
for (let i = 0; i < tag.length; i++) {
|
||||
const ch = tag[i];
|
||||
if (ch === undefined) {
|
||||
throw new Error("log tag validation failed");
|
||||
}
|
||||
const upper = ch.toUpperCase();
|
||||
if (!TAG_CHAR_SET.has(upper)) {
|
||||
throw new Error(`invalid Crockford Base32 character in log tag: ${ch}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
import { appendFileSync, mkdirSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
import { getDefaultStorageRoot } from "../storage-root.js";
|
||||
import { assertValidLogTag } from "./log-tag.js";
|
||||
import type { CreateProcessLoggerOptions, ProcessLogger, ProcessLoggerContext } from "./types.js";
|
||||
|
||||
const INIT_TAG = "W9F3RK2M";
|
||||
|
||||
function logDateKey(date: Date): string {
|
||||
return date.toISOString().slice(0, 10);
|
||||
}
|
||||
|
||||
function getProcessLogsDir(storageRoot: string): string {
|
||||
return join(storageRoot, "logs");
|
||||
}
|
||||
|
||||
function getProcessLogFilePath(storageRoot: string, date: Date): string {
|
||||
return join(getProcessLogsDir(storageRoot), `${logDateKey(date)}.jsonl`);
|
||||
}
|
||||
|
||||
function buildEntry(
|
||||
processId: string,
|
||||
tag: string,
|
||||
msg: string,
|
||||
baseContext: ProcessLoggerContext,
|
||||
extra: Record<string, string> | null,
|
||||
): Record<string, string> {
|
||||
const entry: Record<string, string> = {
|
||||
ts: new Date().toISOString(),
|
||||
pid: processId,
|
||||
tag: tag.toUpperCase(),
|
||||
msg,
|
||||
};
|
||||
if (baseContext.thread !== null) {
|
||||
entry.thread = baseContext.thread;
|
||||
}
|
||||
if (baseContext.workflow !== null) {
|
||||
entry.workflow = baseContext.workflow;
|
||||
}
|
||||
if (extra !== null) {
|
||||
for (const [key, value] of Object.entries(extra)) {
|
||||
entry[key] = value;
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
function appendEntry(filePath: string, entry: Record<string, string>): void {
|
||||
appendFileSync(filePath, `${JSON.stringify(entry)}\n`, "utf8");
|
||||
}
|
||||
|
||||
/** Process-scoped debug logger — append-only JSONL under `<storageRoot>/logs/YYYY-MM-DD.jsonl`. */
|
||||
export function createProcessLogger(options: CreateProcessLoggerOptions): ProcessLogger {
|
||||
const storageRoot = options.storageRoot ?? getDefaultStorageRoot();
|
||||
const processId = `${Date.now()}-${process.pid}`;
|
||||
const baseContext = options.context;
|
||||
const logFilePath = getProcessLogFilePath(storageRoot, new Date());
|
||||
|
||||
mkdirSync(getProcessLogsDir(storageRoot), { recursive: true });
|
||||
|
||||
const log: ProcessLogger["log"] = (tag, msg, context = null) => {
|
||||
assertValidLogTag(tag);
|
||||
appendEntry(logFilePath, buildEntry(processId, tag, msg, baseContext, context));
|
||||
};
|
||||
|
||||
const argvSummary = JSON.stringify(process.argv);
|
||||
const initParts = [`argv=${argvSummary}`, `node=${process.version}`];
|
||||
if (baseContext.thread !== null) {
|
||||
initParts.push(`thread=${baseContext.thread}`);
|
||||
}
|
||||
if (baseContext.workflow !== null) {
|
||||
initParts.push(`workflow=${baseContext.workflow}`);
|
||||
}
|
||||
log(INIT_TAG, `process start ${initParts.join(" ")}`, null);
|
||||
|
||||
return { pid: processId, log };
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
export type ProcessLoggerContext = {
|
||||
thread: string | null;
|
||||
workflow: string | null;
|
||||
};
|
||||
|
||||
export type CreateProcessLoggerOptions = {
|
||||
storageRoot: string | null;
|
||||
context: ProcessLoggerContext;
|
||||
};
|
||||
|
||||
export type ProcessLogFn = (
|
||||
tag: string,
|
||||
msg: string,
|
||||
context: Record<string, string> | null,
|
||||
) => void;
|
||||
|
||||
export type ProcessLogger = {
|
||||
pid: string;
|
||||
log: ProcessLogFn;
|
||||
};
|
||||
Reference in New Issue
Block a user