arcie 0.1.4 → 0.1.6
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/dist/agent/index.d.ts +1 -1
- package/dist/build-TWNCPXBU.js +82 -0
- package/dist/build-TWNCPXBU.js.map +1 -0
- package/dist/channels/index.d.ts +1 -1
- package/dist/{chunk-2ZSKZYWK.js → chunk-4WSILP75.js} +37 -164
- package/dist/chunk-4WSILP75.js.map +1 -0
- package/dist/chunk-HVBDOHTL.js +148 -0
- package/dist/chunk-HVBDOHTL.js.map +1 -0
- package/dist/chunk-HWD2Z2CH.js +742 -0
- package/dist/chunk-HWD2Z2CH.js.map +1 -0
- package/dist/chunk-KVSX4MLK.js +139 -0
- package/dist/chunk-KVSX4MLK.js.map +1 -0
- package/dist/chunk-N5R3TEEZ.js +15 -0
- package/dist/chunk-N5R3TEEZ.js.map +1 -0
- package/dist/chunk-SGWQZZ2A.js +54 -0
- package/dist/chunk-SGWQZZ2A.js.map +1 -0
- package/dist/chunk-XOFWQUOO.js +30 -0
- package/dist/chunk-XOFWQUOO.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.js +156 -231
- package/dist/cli/index.js.map +1 -1
- package/dist/context/index.d.ts +1 -1
- package/dist/dev-ZZDVOWUZ.js +1967 -0
- package/dist/dev-ZZDVOWUZ.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -1
- package/dist/{index-b4NcDl3m.d.ts → index-CElLRVTP.d.ts} +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/index.js +4 -2
- package/dist/index.js.map +1 -1
- package/dist/init-5F7CIVLN.js +822 -0
- package/dist/init-5F7CIVLN.js.map +1 -0
- package/dist/instructions/index.d.ts +1 -1
- package/dist/runner/index.d.ts +2 -2
- package/dist/runner/index.js +2 -1
- package/dist/scaffold-web-chat-OQL5C2GK.js +7 -0
- package/dist/scaffold-web-chat-OQL5C2GK.js.map +1 -0
- package/dist/schedules/index.d.ts +1 -1
- package/dist/skills/index.d.ts +1 -1
- package/dist/tools/index.d.ts +1 -1
- package/dist/{types-BxOQTzx1.d.ts → types-DwxwdSa2.d.ts} +1 -1
- package/package.json +1 -1
- package/templates/default/.env.local +12 -0
- package/templates/web-chat/.env.local.example +4 -0
- package/templates/web-chat/README.md +51 -0
- package/templates/web-chat/app/api/chat/route.ts +43 -0
- package/templates/web-chat/app/globals.css +65 -0
- package/templates/web-chat/app/layout.tsx +15 -0
- package/templates/web-chat/app/page.tsx +9 -0
- package/templates/web-chat/components/chat.tsx +219 -0
- package/templates/web-chat/components/input-bar.tsx +181 -0
- package/templates/web-chat/components/message.tsx +123 -0
- package/templates/web-chat/components/tool-call.tsx +79 -0
- package/templates/web-chat/components/ui/button.tsx +46 -0
- package/templates/web-chat/components/ui/input.tsx +19 -0
- package/templates/web-chat/components.json +20 -0
- package/templates/web-chat/lib/stream.ts +41 -0
- package/templates/web-chat/lib/types.ts +62 -0
- package/templates/web-chat/lib/utils.ts +6 -0
- package/templates/web-chat/next.config.mjs +6 -0
- package/templates/web-chat/package.json +33 -0
- package/templates/web-chat/postcss.config.mjs +6 -0
- package/templates/web-chat/tailwind.config.ts +61 -0
- package/templates/web-chat/tsconfig.json +23 -0
- package/dist/chunk-2ZSKZYWK.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/tui/renderer/live-region.ts","../src/cli/tui/attach-keys.ts","../src/cli/tui/key-parser.ts","../src/cli/tui/theme.ts","../src/cli/shared/text-boundaries.ts","../src/cli/ui/terminal-text.ts","../src/cli/tui/line-editor.ts"],"sourcesContent":["export interface TerminalOutput {\n readonly isTTY?: boolean;\n readonly columns?: number;\n readonly rows?: number;\n write(chunk: string): boolean;\n on(event: \"resize\", listener: () => void): unknown;\n off(event: \"resize\", listener: () => void): unknown;\n}\n\nexport interface LiveRegionCaret {\n readonly row: number;\n readonly col: number;\n}\n\nexport interface LiveRegionOptions {\n readonly output?: TerminalOutput;\n readonly onResize?: (size: { columns: number; rows: number }) => void;\n}\n\nconst ESC = \"\\x1B[\";\nconst ERASE_DOWN = `${ESC}J`;\nconst CURSOR_TO_COL_1 = `${ESC}G`;\nconst HIDE_CURSOR = `${ESC}?25l`;\nconst SHOW_CURSOR = `${ESC}?25h`;\n\nfunction cursorUp(rows: number): string {\n return rows > 0 ? `${ESC}${rows}A` : \"\";\n}\n\nfunction cursorDown(rows: number): string {\n return rows > 0 ? `${ESC}${rows}B` : \"\";\n}\n\nfunction cursorToColumn(col: number): string {\n return `${ESC}${Math.max(1, col)}G`;\n}\n\n/**\n * Bottom-anchored redraw region.\n *\n * `paint(rows)` diffs against the previously painted frame and rewrites only\n * what changed. `commit(rows)` scrolls new lines above the live region into\n * scrollback and repaints. Callers own the string contents; this class owns\n * cursor arithmetic.\n */\nexport class LiveRegion {\n readonly #output: TerminalOutput;\n readonly #resizeListener: () => void;\n #lastFrame: string[] = [];\n #caret: LiveRegionCaret = { row: 0, col: 1 };\n #stopped = false;\n\n constructor(options: LiveRegionOptions = {}) {\n this.#output = options.output ?? (process.stdout as unknown as TerminalOutput);\n this.#resizeListener = () => {\n if (this.#stopped) return;\n options.onResize?.({\n columns: this.#output.columns ?? 80,\n rows: this.#output.rows ?? 24,\n });\n const previous = this.#lastFrame;\n this.#lastFrame = [];\n this.paint(previous, this.#caret);\n };\n this.#output.on(\"resize\", this.#resizeListener);\n }\n\n get columns(): number {\n return this.#output.columns ?? 80;\n }\n\n get rows(): number {\n return this.#output.rows ?? 24;\n }\n\n /**\n * Redraws the live region to match `rows`. The cursor is positioned at\n * `caret` (1-indexed row within the region, 1-indexed column). Passing an\n * empty array clears the region without leaving trailing blank lines.\n */\n paint(rows: readonly string[], caret: LiveRegionCaret = { row: 1, col: 1 }): void {\n if (this.#stopped) return;\n const output = this.#output;\n const previousHeight = this.#lastFrame.length;\n\n let chunk = HIDE_CURSOR;\n if (previousHeight > 0) {\n chunk += cursorUp(previousHeight - 1) + CURSOR_TO_COL_1 + ERASE_DOWN;\n } else {\n chunk += CURSOR_TO_COL_1 + ERASE_DOWN;\n }\n chunk += rows.join(\"\\n\");\n\n const rowsBelowCaret = Math.max(0, rows.length - Math.max(1, caret.row));\n if (rowsBelowCaret > 0) chunk += cursorUp(rowsBelowCaret);\n chunk += cursorToColumn(caret.col);\n chunk += SHOW_CURSOR;\n\n output.write(chunk);\n this.#lastFrame = [...rows];\n this.#caret = caret;\n }\n\n /**\n * Commits `rows` to scrollback above the live region, then repaints the\n * region beneath them. Rows are terminated by newlines so the terminal\n * scrolls each into history.\n */\n commit(rows: readonly string[]): void {\n if (this.#stopped) return;\n if (rows.length === 0) return;\n const output = this.#output;\n const previousHeight = this.#lastFrame.length;\n\n let chunk = HIDE_CURSOR;\n if (previousHeight > 0) {\n chunk += cursorUp(previousHeight - 1) + CURSOR_TO_COL_1 + ERASE_DOWN;\n } else {\n chunk += CURSOR_TO_COL_1;\n }\n for (const row of rows) chunk += `${row}\\n`;\n output.write(chunk);\n\n const preserved = this.#lastFrame;\n const caret = this.#caret;\n this.#lastFrame = [];\n if (preserved.length > 0) {\n this.paint(preserved, caret);\n } else {\n output.write(SHOW_CURSOR);\n }\n }\n\n /**\n * Clears the live region and shows the cursor at the start of what used to\n * be the region's first row. Idempotent; safe to call from cleanup paths.\n */\n stop(): void {\n if (this.#stopped) return;\n this.#stopped = true;\n this.#output.off(\"resize\", this.#resizeListener);\n if (this.#lastFrame.length > 0) {\n const chunk =\n cursorUp(this.#lastFrame.length - 1) + CURSOR_TO_COL_1 + ERASE_DOWN + SHOW_CURSOR;\n this.#output.write(chunk);\n } else {\n this.#output.write(SHOW_CURSOR);\n }\n this.#lastFrame = [];\n }\n}\n","import { stdin as input } from \"node:process\";\nimport { isIncompletePaste, nextKey, type TerminalKey } from \"./key-parser\";\n\n/**\n * Puts stdin into raw mode, decodes bytes into `TerminalKey`s, and delivers\n * them to `onKey`. Returns a detach function that restores the previous raw\n * mode and stops delivering keys. Safe to call in a non-TTY (raw mode is\n * skipped; delivered keys become whatever the terminal sends).\n */\nexport function attachKeyStream(onKey: (key: TerminalKey) => void): () => void {\n let buffer = \"\";\n const originalRawMode = input.isRaw;\n\n const onData = (chunk: Buffer): void => {\n buffer += chunk.toString(\"utf8\");\n if (isIncompletePaste(buffer)) return;\n while (buffer.length > 0) {\n const token = nextKey(buffer);\n if (token.incomplete === true) break;\n buffer = buffer.slice(token.consumed);\n if (token.key !== undefined && token.key.type !== \"ignore\") onKey(token.key);\n }\n };\n\n try {\n input.setRawMode?.(true);\n } catch {\n // Non-TTY: raw mode not available; keystrokes still deliver.\n }\n input.resume();\n input.on(\"data\", onData);\n\n return () => {\n input.off(\"data\", onData);\n try {\n input.setRawMode?.(originalRawMode ?? false);\n } catch {\n /* ignore */\n }\n input.pause();\n };\n}\n","export type TerminalKey =\n | {\n type: \"text\";\n value: string;\n framing: \"unframed\" | \"bracketed-paste\";\n }\n | { type: \"newline\" }\n | { type: \"backspace\" }\n | { type: \"delete\" }\n | { type: \"enter\" }\n | { type: \"up\" }\n | { type: \"down\" }\n | { type: \"left\" }\n | { type: \"right\" }\n | { type: \"home\" }\n | { type: \"end\" }\n | { type: \"tab\" }\n | { type: \"escape\" }\n | { type: \"ctrl-a\" }\n | { type: \"ctrl-e\" }\n | { type: \"ctrl-d\" }\n | { type: \"ctrl-k\" }\n | { type: \"ctrl-n\" }\n | { type: \"ctrl-p\" }\n | { type: \"ctrl-u\" }\n | { type: \"ctrl-w\" }\n | { type: \"ctrl-l\" }\n | { type: \"ctrl-r\" }\n | { type: \"ctrl-c\" }\n | { type: \"ignore\" };\n\nexport interface KeyToken {\n key?: TerminalKey;\n consumed: number;\n incomplete?: boolean;\n}\n\nconst CSI_FINAL = /[@-~]/u;\nconst PASTE_START = \"\\x1B[200~\";\nconst PASTE_END = \"\\x1B[201~\";\n\nexport function sanitizePastedText(text: string): string {\n let printable = \"\";\n for (const character of text.replace(/\\r\\n?/gu, \"\\n\")) {\n if (character === \"\\n\" || character === \"\\t\") {\n printable += character;\n continue;\n }\n const code = character.codePointAt(0);\n if (code === undefined) continue;\n if (code < 0x20 || code === 0x7f || (code >= 0x80 && code <= 0x9f)) continue;\n printable += character;\n }\n return printable;\n}\n\nexport function isIncompletePaste(buffer: string): boolean {\n return buffer.startsWith(PASTE_START) && !buffer.includes(PASTE_END, PASTE_START.length);\n}\n\nexport function stripPasteStart(buffer: string): string {\n return buffer.startsWith(PASTE_START) ? buffer.slice(PASTE_START.length) : buffer;\n}\n\nexport function stripPromptControlCharacters(text: string): string {\n let printable = \"\";\n for (const character of text) {\n if (character >= \" \" && character !== \"\\x7f\") printable += character;\n }\n return printable;\n}\n\nexport function nextKey(buffer: string): KeyToken {\n const first = buffer[0];\n if (first === undefined) return { consumed: 0, incomplete: true };\n\n if (first === \"\\x1B\") {\n if (buffer.length === 1) return { consumed: 0, incomplete: true };\n const second = buffer[1];\n if (second === \"O\") {\n if (buffer.length < 3) return { consumed: 0, incomplete: true };\n return { key: parseKey(Buffer.from(buffer.slice(0, 3))), consumed: 3 };\n }\n if (second === \"[\") {\n if (buffer.startsWith(PASTE_START)) {\n const end = buffer.indexOf(PASTE_END, PASTE_START.length);\n if (end === -1) return { consumed: 0, incomplete: true };\n return {\n key: {\n type: \"text\",\n value: sanitizePastedText(buffer.slice(PASTE_START.length, end)),\n framing: \"bracketed-paste\",\n },\n consumed: end + PASTE_END.length,\n };\n }\n for (let i = 2; i < buffer.length; i += 1) {\n if (CSI_FINAL.test(buffer[i]!)) {\n return { key: parseKey(Buffer.from(buffer.slice(0, i + 1))), consumed: i + 1 };\n }\n }\n return { consumed: 0, incomplete: true };\n }\n return { key: { type: \"escape\" }, consumed: 1 };\n }\n\n if (first < \" \" || first === \"\\x7F\") {\n return { key: parseKey(Buffer.from(first)), consumed: 1 };\n }\n\n let end = 1;\n while (end < buffer.length) {\n const char = buffer[end]!;\n if (char === \"\\x1B\" || char < \" \" || char === \"\\x7F\") break;\n end += 1;\n }\n return { key: parseKey(Buffer.from(buffer.slice(0, end))), consumed: end };\n}\n\nexport function parseKey(chunk: Buffer): TerminalKey {\n const value = chunk.toString(\"utf8\");\n\n switch (value) {\n case \"\u0001\": return { type: \"ctrl-a\" };\n case \"\u0005\": return { type: \"ctrl-e\" };\n case \"\u0004\": return { type: \"ctrl-d\" };\n case \"\u000b\": return { type: \"ctrl-k\" };\n case \"\u000e\": return { type: \"ctrl-n\" };\n case \"\u0010\": return { type: \"ctrl-p\" };\n case \"\f\": return { type: \"ctrl-l\" };\n case \"\u0012\": return { type: \"ctrl-r\" };\n case \"\u0015\": return { type: \"ctrl-u\" };\n case \"\u0017\": return { type: \"ctrl-w\" };\n case \"\u0003\": return { type: \"ctrl-c\" };\n case \"\\r\":\n case \"\\n\":\n return { type: \"enter\" };\n case \"\\x1b[27;2;13~\":\n case \"\\x1b[13;2u\":\n return { type: \"newline\" };\n case \"\":\n case \"\\b\":\n return { type: \"backspace\" };\n case \"\\x1B[A\":\n case \"\\x1BOA\":\n return { type: \"up\" };\n case \"\\x1B[B\":\n case \"\\x1BOB\":\n return { type: \"down\" };\n case \"\\x1B[C\":\n case \"\\x1BOC\":\n return { type: \"right\" };\n case \"\\x1B[D\":\n case \"\\x1BOD\":\n return { type: \"left\" };\n case \"\\x1B[H\":\n case \"\\x1BOH\":\n case \"\\x1B[1~\":\n return { type: \"home\" };\n case \"\\x1B[F\":\n case \"\\x1BOF\":\n case \"\\x1B[4~\":\n return { type: \"end\" };\n case \"\\x1B[3~\":\n return { type: \"delete\" };\n case \"\\t\":\n return { type: \"tab\" };\n case \"\\x1B\":\n return { type: \"escape\" };\n default: {\n const printable = stripPromptControlCharacters(value);\n return printable.length > 0\n ? { type: \"text\", value: printable, framing: \"unframed\" }\n : { type: \"ignore\" };\n }\n }\n}\n","const ESC = \"\\x1b[\";\n\ntype Style = (text: string) => string;\n\nfunction ansi(open: number, close: number, enabled: boolean): Style {\n if (!enabled) return (text) => text;\n const prefix = `${ESC}${open}m`;\n const suffix = `${ESC}${close}m`;\n return (text) => `${prefix}${text}${suffix}`;\n}\n\nfunction ansi256(code: number, enabled: boolean): Style {\n if (!enabled) return (text) => text;\n const prefix = `${ESC}38;5;${code}m`;\n const suffix = `${ESC}39m`;\n return (text) => `${prefix}${text}${suffix}`;\n}\n\nexport interface ThemeColors {\n reset: Style;\n bold: Style;\n dim: Style;\n inverse: Style;\n italic: Style;\n white: Style;\n gray: Style;\n cyan: Style;\n green: Style;\n red: Style;\n yellow: Style;\n magenta: Style;\n blue: Style;\n orange: Style;\n}\n\nexport interface ThemeGlyphs {\n brand: string;\n user: string;\n reasoning: string;\n success: string;\n error: string;\n warning: string;\n subagent: string;\n rule: string;\n question: string;\n connection: string;\n arrow: string;\n pointer: string;\n selectedPointer: string;\n option: string;\n prompt: string;\n elbow: string;\n hrule: string;\n caret: string;\n dot: string;\n ellipsis: string;\n arrowUp: string;\n arrowDown: string;\n}\n\nconst UNICODE_GLYPHS: ThemeGlyphs = {\n brand: \"⚡\",\n user: \"▌\",\n reasoning: \"○\",\n success: \"✓\",\n error: \"⨯\",\n warning: \"⚠\",\n subagent: \"◆\",\n rule: \"│\",\n question: \"?\",\n connection: \"●\",\n arrow: \"→\",\n pointer: \"▷\",\n selectedPointer: \"▶\",\n option: \"◦\",\n prompt: \"❯\",\n elbow: \"⎿\",\n hrule: \"▔\",\n caret: \"▏\",\n dot: \"·\",\n ellipsis: \"…\",\n arrowUp: \"↑\",\n arrowDown: \"↓\",\n};\n\nconst ASCII_GLYPHS: ThemeGlyphs = {\n brand: \"*\",\n user: \"|\",\n reasoning: \"o\",\n success: \"+\",\n error: \"x\",\n warning: \"!\",\n subagent: \"*\",\n rule: \"|\",\n question: \"?\",\n connection: \"*\",\n arrow: \"->\",\n pointer: \">\",\n selectedPointer: \">\",\n option: \".\",\n prompt: \">\",\n elbow: \"`-\",\n hrule: \"=\",\n caret: \"_\",\n dot: \"-\",\n ellipsis: \"...\",\n arrowUp: \"^\",\n arrowDown: \"v\",\n};\n\nconst UNICODE_SPINNER = [\"⠋\", \"⠙\", \"⠹\", \"⠸\", \"⠼\", \"⠴\", \"⠦\", \"⠧\", \"⠇\", \"⠏\"];\nconst ASCII_SPINNER = [\"-\", \"\\\\\", \"|\", \"/\"];\n\nexport interface Theme {\n readonly color: boolean;\n readonly unicode: boolean;\n readonly colors: ThemeColors;\n readonly glyph: ThemeGlyphs;\n readonly spinner: readonly string[];\n}\n\nexport interface CreateThemeOptions {\n color?: boolean;\n unicode?: boolean;\n}\n\nexport function createTheme(options: CreateThemeOptions = {}): Theme {\n const color = options.color ?? true;\n const unicode = options.unicode ?? true;\n\n return {\n color,\n unicode,\n colors: {\n reset: ansi(0, 0, color),\n bold: ansi(1, 22, color),\n dim: ansi(2, 22, color),\n inverse: ansi(7, 27, color),\n italic: ansi(3, 23, color),\n white: ansi(97, 39, color),\n gray: ansi(90, 39, color),\n cyan: ansi(36, 39, color),\n green: ansi(32, 39, color),\n red: ansi(31, 39, color),\n yellow: ansi(33, 39, color),\n magenta: ansi(35, 39, color),\n blue: ansi(34, 39, color),\n orange: ansi256(208, color),\n },\n glyph: unicode ? UNICODE_GLYPHS : ASCII_GLYPHS,\n spinner: unicode ? UNICODE_SPINNER : ASCII_SPINNER,\n };\n}\n\nexport function detectUnicode(env: NodeJS.ProcessEnv = process.env): boolean {\n const override = env.ARCIE_TUI_UNICODE;\n if (override === \"0\" || override === \"false\") return false;\n if (override === \"1\" || override === \"true\") return true;\n\n if (env.TERM === \"dumb\") return false;\n if (process.platform === \"win32\") {\n return Boolean(env.WT_SESSION || env.TERM_PROGRAM === \"vscode\");\n }\n return true;\n}\n","interface GraphemeSpan {\n readonly text: string;\n readonly start: number;\n readonly end: number;\n}\n\nconst graphemeSegmenter = new Intl.Segmenter(undefined, { granularity: \"grapheme\" });\n\nexport function graphemes(text: string): GraphemeSpan[] {\n return Array.from(graphemeSegmenter.segment(text), ({ index, segment }) => ({\n text: segment,\n start: index,\n end: index + segment.length,\n }));\n}\n\nexport function previousGraphemeBoundary(text: string, offset: number): number {\n const clamped = Math.max(0, Math.min(offset, text.length));\n if (clamped === 0) return 0;\n return graphemeSegmenter.segment(text).containing(clamped - 1)?.index ?? 0;\n}\n\nexport function nextGraphemeBoundary(text: string, offset: number): number {\n const clamped = Math.max(0, Math.min(offset, text.length));\n if (clamped === text.length) return clamped;\n const grapheme = graphemeSegmenter.segment(text).containing(clamped);\n return grapheme === undefined ? text.length : grapheme.index + grapheme.segment.length;\n}\n\nexport function graphemeBoundaryAtOrAfter(text: string, offset: number): number {\n const clamped = Math.max(0, Math.min(offset, text.length));\n if (clamped === 0 || clamped === text.length) return clamped;\n const grapheme = graphemeSegmenter.segment(text).containing(clamped);\n if (grapheme === undefined || grapheme.index === clamped) return clamped;\n return grapheme.index + grapheme.segment.length;\n}\n","import { graphemes } from \"../shared/text-boundaries\";\n\nconst ansiEscape = String.fromCharCode(27);\n\nexport const ansiPattern = new RegExp(`${ansiEscape}\\\\[[0-?]*[ -/]*[@-~]`, \"g\");\nexport const ansiPrefixPattern = new RegExp(`^${ansiEscape}\\\\[[0-?]*[ -/]*[@-~]`);\nconst emojiPresentationPattern = /\\p{Emoji_Presentation}/u;\nconst extendedPictographicPattern = /\\p{Extended_Pictographic}/u;\nconst keycapPattern = /^[#*0-9]\\u{fe0f}?\\u{20e3}$/u;\n\nexport function stripAnsi(input: string): string {\n return stripTerminalControls(input.replaceAll(ansiPattern, \"\"));\n}\n\nexport function stripTerminalControls(input: string): string {\n let output = \"\";\n let index = 0;\n\n while (index < input.length) {\n const codePoint = input.codePointAt(index);\n if (codePoint == null) break;\n const character = String.fromCodePoint(codePoint);\n index += character.length;\n if (isUnsafeTerminalControlCodePoint(codePoint)) continue;\n output += character;\n }\n\n return output;\n}\n\nexport function visibleLength(input: string): number {\n let width = 0;\n for (const unit of terminalTextUnits(input)) width += unit.width;\n return width;\n}\n\nexport function sliceVisible(input: string, width: number): string {\n if (width <= 0) return \"\";\n\n let output = \"\";\n let visible = 0;\n const units = terminalTextUnits(input);\n let index = 0;\n while (index < units.length && visible < width) {\n const unit = units[index]!;\n if (unit.width > 0 && visible + unit.width > width) break;\n output += unit.text;\n visible += unit.width;\n index += 1;\n }\n\n while (units[index]?.ansi === true) {\n output += units[index]!.text;\n index += 1;\n }\n\n return output;\n}\n\nexport function clipVisible(input: string, width: number): string {\n if (visibleLength(input) <= width) return input;\n const sliced = sliceVisible(input, width);\n return sliced.includes(ansiEscape) ? `${sliced}${ansiEscape}[0m` : sliced;\n}\n\nexport function inputTextWidth(input: string): number {\n let width = 0;\n for (const grapheme of graphemes(input)) {\n width += terminalGraphemeWidth(grapheme.text);\n }\n return width;\n}\n\nexport function renderInputText(input: string): string {\n return input.replaceAll(\"\\t\", \" \");\n}\n\ninterface BlockCursorInput {\n readonly before: string;\n readonly under: string;\n readonly after: string;\n readonly visible: boolean;\n readonly inverse: (text: string) => string;\n readonly render?: (text: string) => string;\n}\n\nexport function renderInputWithBlockCursor(input: BlockCursorInput): string {\n const render = input.render ?? renderInputText;\n const cursorText = input.under.length > 0 ? input.under : \" \";\n const cursorCell = input.visible\n ? input.inverse(renderInputText(cursorText))\n : render(cursorText);\n return `${render(input.before)}${cursorCell}${render(input.after)}`;\n}\n\nexport function offsetAtVisibleColumn(input: string, column: number): number {\n if (column <= 0) return 0;\n\n let visible = 0;\n for (const grapheme of graphemes(input)) {\n const next = visible + terminalGraphemeWidth(grapheme.text);\n if (next > column) return grapheme.start;\n if (next === column) return grapheme.end;\n visible = next;\n }\n return input.length;\n}\n\nfunction terminalGraphemeWidth(grapheme: string): number {\n let width = 0;\n for (const character of grapheme) {\n const codePoint = character.codePointAt(0);\n if (codePoint !== undefined) width = Math.max(width, codePointWidth(codePoint));\n }\n const emojiPresentation =\n emojiPresentationPattern.test(grapheme) ||\n keycapPattern.test(grapheme) ||\n (grapheme.includes(\"\\u{fe0f}\") && extendedPictographicPattern.test(grapheme));\n return emojiPresentation ? Math.max(2, width) : width;\n}\n\ninterface TerminalTextUnit {\n readonly text: string;\n readonly width: number;\n readonly ansi: boolean;\n}\n\nfunction terminalTextUnits(input: string): TerminalTextUnit[] {\n const units: TerminalTextUnit[] = [];\n let index = 0;\n while (index < input.length) {\n const remaining = input.slice(index);\n const ansiMatch = remaining.match(ansiPrefixPattern);\n if (ansiMatch !== null) {\n units.push({ text: ansiMatch[0], width: 0, ansi: true });\n index += ansiMatch[0].length;\n continue;\n }\n\n const nextAnsi = remaining.search(ansiPattern);\n const plain = remaining.slice(0, nextAnsi === -1 ? remaining.length : nextAnsi);\n for (const grapheme of graphemes(plain)) {\n units.push({ text: grapheme.text, width: terminalGraphemeWidth(grapheme.text), ansi: false });\n }\n index += plain.length;\n }\n return units;\n}\n\nexport function wrapVisibleLine(line: string, width: number): string[] {\n if (width <= 0) return [line];\n if (line.length === 0) return [\"\"];\n\n const lines: string[] = [];\n let remaining = line;\n\n while (visibleLength(remaining) > width) {\n const breakAt = findVisibleBreakPoint(remaining, width);\n lines.push(remaining.slice(0, breakAt).trimEnd());\n remaining = remaining.slice(breakAt).trimStart();\n }\n\n if (remaining.length > 0 || lines.length === 0) lines.push(remaining);\n return lines;\n}\n\nfunction findVisibleBreakPoint(input: string, width: number): number {\n const slice = sliceVisible(input, width + 1);\n const lastSpace = slice.lastIndexOf(\" \");\n if (lastSpace > 0) return lastSpace;\n\n const hardSlice = sliceVisible(input, width);\n if (visibleLength(hardSlice) > 0) return hardSlice.length;\n\n let offset = 0;\n let foundVisibleUnit = false;\n for (const unit of terminalTextUnits(input)) {\n if (foundVisibleUnit && unit.width > 0) return offset;\n offset += unit.text.length;\n if (unit.width > 0) foundVisibleUnit = true;\n }\n return offset;\n}\n\nexport function codePointWidth(codePoint: number): number {\n if (codePoint === 0x09) return 4;\n if (codePoint < 0x20 || (codePoint >= 0x7f && codePoint < 0xa0)) return 0;\n if (isZeroWidthCodePoint(codePoint)) return 0;\n return isWideCodePoint(codePoint) ? 2 : 1;\n}\n\nfunction isUnsafeTerminalControlCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x00 && codePoint <= 0x08) ||\n (codePoint >= 0x0b && codePoint <= 0x1f) ||\n (codePoint >= 0x7f && codePoint <= 0x9f)\n );\n}\n\nfunction isZeroWidthCodePoint(codePoint: number): boolean {\n return (\n (codePoint >= 0x0300 && codePoint <= 0x036f) ||\n (codePoint >= 0x0483 && codePoint <= 0x0489) ||\n (codePoint >= 0x0591 && codePoint <= 0x05bd) ||\n codePoint === 0x05bf ||\n (codePoint >= 0x05c1 && codePoint <= 0x05c2) ||\n (codePoint >= 0x05c4 && codePoint <= 0x05c5) ||\n codePoint === 0x05c7 ||\n (codePoint >= 0x0610 && codePoint <= 0x061a) ||\n (codePoint >= 0x064b && codePoint <= 0x065f) ||\n codePoint === 0x0670 ||\n (codePoint >= 0x06d6 && codePoint <= 0x06dc) ||\n (codePoint >= 0x06df && codePoint <= 0x06e4) ||\n (codePoint >= 0x06e7 && codePoint <= 0x06e8) ||\n (codePoint >= 0x06ea && codePoint <= 0x06ed) ||\n codePoint === 0x0711 ||\n (codePoint >= 0x0730 && codePoint <= 0x074a) ||\n (codePoint >= 0x07a6 && codePoint <= 0x07b0) ||\n (codePoint >= 0x07eb && codePoint <= 0x07f3) ||\n (codePoint >= 0x0816 && codePoint <= 0x0819) ||\n (codePoint >= 0x081b && codePoint <= 0x0823) ||\n (codePoint >= 0x0825 && codePoint <= 0x0827) ||\n (codePoint >= 0x0829 && codePoint <= 0x082d) ||\n (codePoint >= 0x0859 && codePoint <= 0x085b) ||\n (codePoint >= 0x08d3 && codePoint <= 0x0902) ||\n codePoint === 0x093a ||\n codePoint === 0x093c ||\n (codePoint >= 0x0941 && codePoint <= 0x0948) ||\n codePoint === 0x094d ||\n (codePoint >= 0x0951 && codePoint <= 0x0957) ||\n codePoint === 0x200d ||\n (codePoint >= 0xfe00 && codePoint <= 0xfe0f) ||\n (codePoint >= 0xe0100 && codePoint <= 0xe01ef)\n );\n}\n\nfunction isWideCodePoint(codePoint: number): boolean {\n return (\n codePoint >= 0x1100 &&\n (codePoint <= 0x115f ||\n codePoint === 0x2329 ||\n codePoint === 0x232a ||\n (codePoint >= 0x2e80 && codePoint <= 0xa4cf && codePoint !== 0x303f) ||\n (codePoint >= 0xac00 && codePoint <= 0xd7a3) ||\n (codePoint >= 0xf900 && codePoint <= 0xfaff) ||\n (codePoint >= 0xfe10 && codePoint <= 0xfe19) ||\n (codePoint >= 0xfe30 && codePoint <= 0xfe6f) ||\n (codePoint >= 0xff00 && codePoint <= 0xff60) ||\n (codePoint >= 0xffe0 && codePoint <= 0xffe6) ||\n (codePoint >= 0x1f300 && codePoint <= 0x1f64f) ||\n (codePoint >= 0x1f900 && codePoint <= 0x1f9ff) ||\n (codePoint >= 0x20000 && codePoint <= 0x3fffd))\n );\n}\n","import {\n graphemeBoundaryAtOrAfter,\n graphemes,\n nextGraphemeBoundary,\n previousGraphemeBoundary,\n} from \"../shared/text-boundaries\";\nimport { inputTextWidth, offsetAtVisibleColumn } from \"../ui/terminal-text\";\nimport type { TerminalKey } from \"./key-parser\";\n\nexport interface LineState {\n readonly text: string;\n readonly cursor: number;\n}\n\nexport const EMPTY_LINE: LineState = { text: \"\", cursor: 0 };\n\nexport function lineOf(text: string): LineState {\n return { text, cursor: text.length };\n}\n\nexport function maskLine(state: LineState): LineState {\n return {\n text: \"•\".repeat(graphemes(state.text).length),\n cursor: graphemes(state.text.slice(0, state.cursor)).length,\n };\n}\n\nexport function insert(state: LineState, value: string): LineState {\n if (value.length === 0) return state;\n const text = state.text.slice(0, state.cursor) + value + state.text.slice(state.cursor);\n const cursor = graphemeBoundaryAtOrAfter(text, state.cursor + value.length);\n return { text, cursor };\n}\n\nexport function backspace(state: LineState): LineState {\n if (state.cursor === 0) return state;\n const cursor = previousGraphemeBoundary(state.text, state.cursor);\n const text = state.text.slice(0, cursor) + state.text.slice(state.cursor);\n return { text, cursor: graphemeBoundaryAtOrAfter(text, cursor) };\n}\n\nexport function deleteForward(state: LineState): LineState {\n if (state.cursor >= state.text.length) return state;\n const end = nextGraphemeBoundary(state.text, state.cursor);\n const text = state.text.slice(0, state.cursor) + state.text.slice(end);\n return { text, cursor: graphemeBoundaryAtOrAfter(text, state.cursor) };\n}\n\nexport function moveLeft(state: LineState): LineState {\n return state.cursor === 0\n ? state\n : { text: state.text, cursor: previousGraphemeBoundary(state.text, state.cursor) };\n}\n\nexport function moveRight(state: LineState): LineState {\n return state.cursor >= state.text.length\n ? state\n : { text: state.text, cursor: nextGraphemeBoundary(state.text, state.cursor) };\n}\n\nexport function moveHome(state: LineState): LineState {\n const cursor = logicalLineStart(state.text, state.cursor);\n return state.cursor === cursor ? state : { text: state.text, cursor };\n}\n\nexport function moveEnd(state: LineState): LineState {\n const cursor = logicalLineEnd(state.text, state.cursor);\n return state.cursor === cursor ? state : { text: state.text, cursor };\n}\n\nexport function killToEnd(state: LineState): LineState {\n const lineEnd = logicalLineEnd(state.text, state.cursor);\n if (state.cursor >= lineEnd) return state;\n return {\n text: state.text.slice(0, state.cursor) + state.text.slice(lineEnd),\n cursor: state.cursor,\n };\n}\n\nexport function killToStart(state: LineState): LineState {\n const lineStart = logicalLineStart(state.text, state.cursor);\n if (state.cursor <= lineStart) return state;\n return {\n text: state.text.slice(0, lineStart) + state.text.slice(state.cursor),\n cursor: lineStart,\n };\n}\n\nexport function deleteWord(state: LineState): LineState {\n if (state.cursor === 0) return state;\n const lineStart = logicalLineStart(state.text, state.cursor);\n let start = state.cursor;\n while (start > lineStart) {\n const previous = previousGraphemeBoundary(state.text, start);\n if (!isWhitespace(state.text.slice(previous, start))) break;\n start = previous;\n }\n while (start > lineStart) {\n const previous = previousGraphemeBoundary(state.text, start);\n if (isWhitespace(state.text.slice(previous, start))) break;\n start = previous;\n }\n const text = state.text.slice(0, start) + state.text.slice(state.cursor);\n return { text, cursor: graphemeBoundaryAtOrAfter(text, start) };\n}\n\nfunction logicalLineStart(text: string, cursor: number): number {\n if (cursor === 0) return 0;\n return text.lastIndexOf(\"\\n\", cursor - 1) + 1;\n}\n\nfunction logicalLineEnd(text: string, cursor: number): number {\n const newline = text.indexOf(\"\\n\", cursor);\n return newline === -1 ? text.length : newline;\n}\n\ninterface LineEditorOptions {\n readonly multiline?: boolean;\n}\n\nexport function applyLineEditorKey(\n state: LineState,\n key: TerminalKey,\n options?: LineEditorOptions,\n): LineState | undefined {\n const multiline = options?.multiline ?? false;\n switch (key.type) {\n case \"text\":\n return insert(state, multiline ? key.value : key.value.replaceAll(\"\\n\", \" \"));\n case \"newline\":\n return multiline ? insert(state, \"\\n\") : undefined;\n case \"backspace\":\n return backspace(state);\n case \"delete\":\n return deleteForward(state);\n case \"left\":\n return moveLeft(state);\n case \"right\":\n return moveRight(state);\n case \"home\":\n case \"ctrl-a\":\n return moveHome(state);\n case \"end\":\n case \"ctrl-e\":\n return moveEnd(state);\n case \"ctrl-k\":\n return killToEnd(state);\n case \"ctrl-u\":\n return killToStart(state);\n case \"ctrl-w\":\n return deleteWord(state);\n default:\n return undefined;\n }\n}\n\nfunction isWhitespace(text: string): boolean {\n return /^\\s+$/u.test(text);\n}\n\ninterface VisibleLine {\n readonly before: string;\n readonly under: string;\n readonly after: string;\n}\n\nexport function visibleLine(state: LineState, budget: number, ellipsis = \"…\"): VisibleLine {\n const width = Math.max(1, budget);\n const { text, cursor } = state;\n const segments = graphemes(text);\n const caretIndex = segments.findIndex((segment) => segment.start === cursor);\n const underIndex = caretIndex === -1 ? segments.length : caretIndex;\n const under = segments[underIndex]?.text ?? \"\";\n\n if (inputTextWidth(text) <= width) {\n return {\n before: text.slice(0, cursor),\n under,\n after: text.slice(cursor + under.length),\n };\n }\n\n let start = underIndex;\n let end = underIndex + (under.length > 0 ? 1 : 0);\n const windowWidth = (candidateStart: number, candidateEnd: number): number => {\n const startOffset = segments[candidateStart]?.start ?? text.length;\n const endOffset = segments[candidateEnd]?.start ?? text.length;\n return (\n inputTextWidth(text.slice(startOffset, endOffset)) +\n (candidateStart > 0 ? inputTextWidth(ellipsis) : 0) +\n (candidateEnd < segments.length ? inputTextWidth(ellipsis) : 0)\n );\n };\n\n let preferBefore = true;\n while (true) {\n const beforeFits = start > 0 && windowWidth(start - 1, end) <= width;\n const afterFits = end < segments.length && windowWidth(start, end + 1) <= width;\n if (!beforeFits && !afterFits) break;\n if ((preferBefore && beforeFits) || !afterFits) start -= 1;\n else end += 1;\n preferBefore = !preferBefore;\n }\n\n const startOffset = segments[start]?.start ?? text.length;\n const endOffset = segments[end]?.start ?? text.length;\n return {\n before: `${start > 0 ? ellipsis : \"\"}${text.slice(startOffset, cursor)}`,\n under,\n after: `${text.slice(cursor + under.length, endOffset)}${end < segments.length ? ellipsis : \"\"}`,\n };\n}\n\ninterface PromptLogicalRow {\n readonly text: string;\n readonly start: number;\n}\n\ninterface PromptLayout {\n readonly rows: PromptLogicalRow[];\n readonly caretRow: number;\n readonly caretOffset: number;\n}\n\nexport function layoutPromptInput(state: LineState): PromptLayout {\n const rows: PromptLogicalRow[] = [];\n let caretRow = 0;\n let caretOffset = 0;\n\n let start = 0;\n for (const text of state.text.split(\"\\n\")) {\n if (state.cursor >= start && state.cursor <= start + text.length) {\n caretRow = rows.length;\n caretOffset = state.cursor - start;\n }\n rows.push({ text, start });\n start += text.length + 1;\n }\n\n return { rows, caretRow, caretOffset };\n}\n\nexport function movePromptLine(state: LineState, direction: \"up\" | \"down\"): LineState | undefined {\n const layout = layoutPromptInput(state);\n const targetRow = direction === \"up\" ? layout.caretRow - 1 : layout.caretRow + 1;\n if (targetRow < 0 || targetRow >= layout.rows.length) return undefined;\n\n const current = layout.rows[layout.caretRow]!;\n const target = layout.rows[targetRow]!;\n const column = inputTextWidth(current.text.slice(0, layout.caretOffset));\n return {\n text: state.text,\n cursor: target.start + offsetAtVisibleColumn(target.text, column),\n };\n}\n\nexport class PromptHistory {\n readonly #entries: string[] = [];\n #index = 0;\n #draft = \"\";\n\n add(entry: string): void {\n const value = entry.trim();\n if (value.length === 0) return;\n if (this.#entries.at(-1) === entry) {\n this.#resetCursor();\n return;\n }\n this.#entries.push(entry);\n this.#resetCursor();\n }\n\n begin(draft: string): void {\n this.#index = this.#entries.length;\n this.#draft = draft;\n }\n\n previous(currentDraft: string): string | undefined {\n if (this.#entries.length === 0) return undefined;\n if (this.#index === this.#entries.length) this.#draft = currentDraft;\n if (this.#index === 0) return undefined;\n this.#index -= 1;\n return this.#entries[this.#index];\n }\n\n next(): string | undefined {\n if (this.#index >= this.#entries.length) return undefined;\n this.#index += 1;\n return this.#index === this.#entries.length ? this.#draft : this.#entries[this.#index];\n }\n\n #resetCursor(): void {\n this.#index = this.#entries.length;\n this.#draft = \"\";\n }\n}\n"],"mappings":"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","names":["end","ESC","input","input","input","startOffset","endOffset"]}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
// src/loader.ts
|
|
2
|
+
import { readFileSync, existsSync, readdirSync, statSync } from "fs";
|
|
3
|
+
import { resolve, basename, extname } from "path";
|
|
4
|
+
async function loadAgent(agentDir) {
|
|
5
|
+
const absDir = resolve(process.cwd(), agentDir);
|
|
6
|
+
if (!existsSync(absDir)) {
|
|
7
|
+
throw new Error(`Agent directory not found: ${absDir}`);
|
|
8
|
+
}
|
|
9
|
+
const agentFile = resolve(absDir, "agent.ts");
|
|
10
|
+
let config = { model: "gpt-4o" };
|
|
11
|
+
if (existsSync(agentFile)) {
|
|
12
|
+
try {
|
|
13
|
+
const mod = await import(agentFile);
|
|
14
|
+
if (mod.default) {
|
|
15
|
+
config = { ...config, ...mod.default };
|
|
16
|
+
}
|
|
17
|
+
} catch (err) {
|
|
18
|
+
console.warn(`[arcie] Failed to load agent.ts: ${err.message}. Using defaults.`);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const instructions = loadInstructionsFile(absDir);
|
|
22
|
+
const tools = await loadDirectory(absDir, "tools");
|
|
23
|
+
const skills = await loadDirectory(absDir, "skills");
|
|
24
|
+
const hooks = await loadDirectory(absDir, "hooks");
|
|
25
|
+
const channels = await loadDirectory(absDir, "channels");
|
|
26
|
+
const connections = await loadDirectory(absDir, "connections");
|
|
27
|
+
const schedules = await loadDirectory(absDir, "schedules");
|
|
28
|
+
const subagents = await loadSubagents(absDir);
|
|
29
|
+
const session = await loadSessionConfig(absDir);
|
|
30
|
+
const policy = await loadPolicyConfig(absDir);
|
|
31
|
+
return {
|
|
32
|
+
agentDir: absDir,
|
|
33
|
+
manifest: {
|
|
34
|
+
config,
|
|
35
|
+
instructions,
|
|
36
|
+
tools,
|
|
37
|
+
skills,
|
|
38
|
+
hooks,
|
|
39
|
+
channels,
|
|
40
|
+
connections,
|
|
41
|
+
schedules,
|
|
42
|
+
subagents,
|
|
43
|
+
session: session ?? void 0,
|
|
44
|
+
policy: policy ?? void 0
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
async function loadSubagents(agentDir) {
|
|
49
|
+
const dirPath = resolve(agentDir, "subagents");
|
|
50
|
+
if (!existsSync(dirPath)) return {};
|
|
51
|
+
const result = {};
|
|
52
|
+
for (const entry of readdirSync(dirPath, { withFileTypes: true })) {
|
|
53
|
+
if (!entry.isDirectory() || entry.name.startsWith(".")) continue;
|
|
54
|
+
const id = entry.name;
|
|
55
|
+
const subDir = resolve(dirPath, id);
|
|
56
|
+
const agentFile = resolve(subDir, "agent.ts");
|
|
57
|
+
if (!existsSync(agentFile)) {
|
|
58
|
+
throw new Error(`Subagent "${id}" is missing agent.ts`);
|
|
59
|
+
}
|
|
60
|
+
let mod;
|
|
61
|
+
try {
|
|
62
|
+
mod = await import(agentFile);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
throw new Error(`Failed to load subagent "${id}": ${err.message}`);
|
|
65
|
+
}
|
|
66
|
+
const config = mod.default;
|
|
67
|
+
if (!config) {
|
|
68
|
+
throw new Error(`Subagent "${id}" agent.ts must have a default export`);
|
|
69
|
+
}
|
|
70
|
+
if (!config.description) {
|
|
71
|
+
throw new Error(`Subagent "${id}" must declare a description in agent.ts`);
|
|
72
|
+
}
|
|
73
|
+
result[id] = {
|
|
74
|
+
config,
|
|
75
|
+
instructions: loadInstructionsFile(subDir),
|
|
76
|
+
tools: await loadDirectory(subDir, "tools"),
|
|
77
|
+
skills: await loadDirectory(subDir, "skills")
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
return result;
|
|
81
|
+
}
|
|
82
|
+
function loadInstructionsFile(agentDir) {
|
|
83
|
+
const mdPath = resolve(agentDir, "instructions.md");
|
|
84
|
+
if (existsSync(mdPath)) {
|
|
85
|
+
return readFileSync(mdPath, "utf-8");
|
|
86
|
+
}
|
|
87
|
+
return "You are a helpful AI agent.";
|
|
88
|
+
}
|
|
89
|
+
async function loadDirectory(agentDir, dirName) {
|
|
90
|
+
const dirPath = resolve(agentDir, dirName);
|
|
91
|
+
if (!existsSync(dirPath)) return {};
|
|
92
|
+
const entries = readdirSync(dirPath).filter(
|
|
93
|
+
(f) => !f.startsWith(".") && (f.endsWith(".ts") || f.endsWith(".js"))
|
|
94
|
+
);
|
|
95
|
+
const result = {};
|
|
96
|
+
for (const entry of entries) {
|
|
97
|
+
const name = basename(entry, extname(entry));
|
|
98
|
+
const filePath = resolve(dirPath, entry);
|
|
99
|
+
if (statSync(filePath).isFile()) {
|
|
100
|
+
try {
|
|
101
|
+
const mod = await import(filePath);
|
|
102
|
+
if (mod.default) {
|
|
103
|
+
result[name] = mod.default;
|
|
104
|
+
}
|
|
105
|
+
} catch {
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return result;
|
|
110
|
+
}
|
|
111
|
+
async function loadSessionConfig(agentDir) {
|
|
112
|
+
const tsPath = resolve(agentDir, "sessions", "config.ts");
|
|
113
|
+
if (existsSync(tsPath)) {
|
|
114
|
+
try {
|
|
115
|
+
const mod = await import(tsPath);
|
|
116
|
+
return mod.default ?? null;
|
|
117
|
+
} catch {
|
|
118
|
+
return null;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
}
|
|
123
|
+
async function loadPolicyConfig(agentDir) {
|
|
124
|
+
const tsPath = resolve(agentDir, "policies", "index.ts");
|
|
125
|
+
if (existsSync(tsPath)) {
|
|
126
|
+
try {
|
|
127
|
+
const mod = await import(tsPath);
|
|
128
|
+
return mod.default ?? null;
|
|
129
|
+
} catch {
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
export {
|
|
137
|
+
loadAgent
|
|
138
|
+
};
|
|
139
|
+
//# sourceMappingURL=chunk-KVSX4MLK.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/loader.ts"],"sourcesContent":["import { readFileSync, existsSync, readdirSync, statSync } from \"node:fs\";\nimport { resolve, basename, extname } from \"node:path\";\nimport type {\n AgentManifest,\n AgentConfig,\n ToolConfig,\n SkillConfig,\n HookConfig,\n ChannelConfig,\n ConnectionConfig,\n ScheduleConfig,\n SessionConfig,\n PolicyConfig,\n SubagentManifest,\n} from \"./types\";\n\nexport interface LoadedAgent {\n manifest: AgentManifest;\n agentDir: string;\n}\n\nexport async function loadAgent(agentDir: string): Promise<LoadedAgent> {\n const absDir = resolve(process.cwd(), agentDir);\n\n if (!existsSync(absDir)) {\n throw new Error(`Agent directory not found: ${absDir}`);\n }\n\n const agentFile = resolve(absDir, \"agent.ts\");\n let config: AgentConfig = { model: \"gpt-4o\" };\n\n if (existsSync(agentFile)) {\n try {\n const mod = await import(agentFile);\n if (mod.default) {\n config = { ...config, ...mod.default };\n }\n } catch (err) {\n console.warn(`[arcie] Failed to load agent.ts: ${(err as Error).message}. Using defaults.`);\n }\n }\n\n const instructions = loadInstructionsFile(absDir);\n const tools = await loadDirectory<ToolConfig>(absDir, \"tools\");\n const skills = await loadDirectory<SkillConfig>(absDir, \"skills\");\n const hooks = await loadDirectory<HookConfig>(absDir, \"hooks\");\n const channels = await loadDirectory<ChannelConfig>(absDir, \"channels\");\n const connections = await loadDirectory<ConnectionConfig>(absDir, \"connections\");\n const schedules = await loadDirectory<ScheduleConfig>(absDir, \"schedules\");\n const subagents = await loadSubagents(absDir);\n const session = await loadSessionConfig(absDir);\n const policy = await loadPolicyConfig(absDir);\n\n return {\n agentDir: absDir,\n manifest: {\n config,\n instructions,\n tools,\n skills,\n hooks,\n channels,\n connections,\n schedules,\n subagents,\n session: session ?? undefined,\n policy: policy ?? undefined,\n },\n };\n}\n\n/**\n * Loads each `subagents/<id>/` directory as a self-contained child agent.\n * Unlike the other slots, subagents are *directories* (not flat files): every\n * one is a mini-agent with its own config, instructions, tools, and skills.\n * A subagent must declare a `description` so the orchestrator knows when to\n * delegate to it — a missing one is a hard authoring error.\n */\nasync function loadSubagents(\n agentDir: string\n): Promise<Record<string, SubagentManifest>> {\n const dirPath = resolve(agentDir, \"subagents\");\n if (!existsSync(dirPath)) return {};\n\n const result: Record<string, SubagentManifest> = {};\n\n for (const entry of readdirSync(dirPath, { withFileTypes: true })) {\n if (!entry.isDirectory() || entry.name.startsWith(\".\")) continue;\n const id = entry.name;\n const subDir = resolve(dirPath, id);\n\n const agentFile = resolve(subDir, \"agent.ts\");\n if (!existsSync(agentFile)) {\n throw new Error(`Subagent \"${id}\" is missing agent.ts`);\n }\n\n let mod: { default?: AgentConfig };\n try {\n mod = await import(agentFile);\n } catch (err) {\n throw new Error(`Failed to load subagent \"${id}\": ${(err as Error).message}`);\n }\n\n const config = mod.default;\n if (!config) {\n throw new Error(`Subagent \"${id}\" agent.ts must have a default export`);\n }\n if (!config.description) {\n throw new Error(`Subagent \"${id}\" must declare a description in agent.ts`);\n }\n\n result[id] = {\n config,\n instructions: loadInstructionsFile(subDir),\n tools: await loadDirectory<ToolConfig>(subDir, \"tools\"),\n skills: await loadDirectory<SkillConfig>(subDir, \"skills\"),\n };\n }\n\n return result;\n}\n\nfunction loadInstructionsFile(agentDir: string): string {\n const mdPath = resolve(agentDir, \"instructions.md\");\n if (existsSync(mdPath)) {\n return readFileSync(mdPath, \"utf-8\");\n }\n return \"You are a helpful AI agent.\";\n}\n\nasync function loadDirectory<T>(\n agentDir: string,\n dirName: string\n): Promise<Record<string, T>> {\n const dirPath = resolve(agentDir, dirName);\n if (!existsSync(dirPath)) return {};\n\n const entries = readdirSync(dirPath).filter(\n (f) => !f.startsWith(\".\") && (f.endsWith(\".ts\") || f.endsWith(\".js\"))\n );\n\n const result: Record<string, T> = {};\n\n for (const entry of entries) {\n const name = basename(entry, extname(entry));\n const filePath = resolve(dirPath, entry);\n\n if (statSync(filePath).isFile()) {\n try {\n const mod = await import(filePath);\n if (mod.default) {\n result[name] = mod.default;\n }\n } catch {\n // skip unloadable files\n }\n }\n }\n\n return result;\n}\n\nasync function loadSessionConfig(agentDir: string): Promise<SessionConfig | null> {\n const tsPath = resolve(agentDir, \"sessions\", \"config.ts\");\n if (existsSync(tsPath)) {\n try {\n const mod = await import(tsPath);\n return mod.default ?? null;\n } catch {\n return null;\n }\n }\n return null;\n}\n\nasync function loadPolicyConfig(agentDir: string): Promise<PolicyConfig | null> {\n const tsPath = resolve(agentDir, \"policies\", \"index.ts\");\n if (existsSync(tsPath)) {\n try {\n const mod = await import(tsPath);\n return mod.default ?? null;\n } catch {\n return null;\n }\n }\n return null;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// src/cli/style.ts
|
|
2
|
+
var RESET = "\x1B[0m";
|
|
3
|
+
var GREY = "\x1B[38;5;242m";
|
|
4
|
+
function grey(text) {
|
|
5
|
+
return `${GREY}${text}${RESET}`;
|
|
6
|
+
}
|
|
7
|
+
function dimmed(text) {
|
|
8
|
+
return grey(text);
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export {
|
|
12
|
+
grey,
|
|
13
|
+
dimmed
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=chunk-N5R3TEEZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/style.ts"],"sourcesContent":["const RESET = \"\\x1B[0m\";\nconst BOLD = \"\\x1B[1m\";\nconst GREY = \"\\x1B[38;5;242m\";\nconst DIM = \"\\x1B[38;5;238m\";\nconst RED = \"\\x1B[38;5;1m\";\nconst GREEN = \"\\x1B[38;5;2m\";\nconst YELLOW = \"\\x1B[38;5;3m\";\nconst WHITE = \"\\x1B[38;5;15m\";\n\nexport function bold(text: string): string {\n return `${BOLD}${text}${RESET}`;\n}\n\nexport function grey(text: string): string {\n return `${GREY}${text}${RESET}`;\n}\n\nexport function dim(text: string): string {\n return `${DIM}${text}${RESET}`;\n}\n\nexport function dimmed(text: string): string {\n return grey(text);\n}\n\nexport function red(text: string): string {\n return `${RED}${text}${RESET}`;\n}\n\nexport function green(text: string): string {\n return `${GREEN}${text}${RESET}`;\n}\n\nexport function yellow(text: string): string {\n return `${YELLOW}${text}${RESET}`;\n}\n\nexport function white(text: string): string {\n return `${WHITE}${text}${RESET}`;\n}\n\nexport const glyph = {\n user: \"\\u25B2\",\n assistant: \"\\u25BC\",\n tool: \"\\u25C7\",\n error: \"\\u25B2\",\n check: \"\\u2713\",\n cross: \"\\u2717\",\n bullet: \"\\u00B7\",\n divider: \"\\u2500\",\n}\n"],"mappings":";AAAA,IAAM,QAAQ;AAEd,IAAM,OAAO;AAWN,SAAS,KAAK,MAAsB;AACzC,SAAO,GAAG,IAAI,GAAG,IAAI,GAAG,KAAK;AAC/B;AAMO,SAAS,OAAO,MAAsB;AAC3C,SAAO,KAAK,IAAI;AAClB;","names":[]}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// src/cli/scaffold-web-chat.ts
|
|
2
|
+
import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from "fs";
|
|
3
|
+
import { dirname, join, resolve } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
6
|
+
function resolveTemplatesDir() {
|
|
7
|
+
let current = __dirname;
|
|
8
|
+
for (let i = 0; i < 6; i += 1) {
|
|
9
|
+
const candidate = resolve(current, "templates");
|
|
10
|
+
if (existsSync(candidate)) return candidate;
|
|
11
|
+
const parent = dirname(current);
|
|
12
|
+
if (parent === current) break;
|
|
13
|
+
current = parent;
|
|
14
|
+
}
|
|
15
|
+
return resolve(__dirname, "../../templates");
|
|
16
|
+
}
|
|
17
|
+
function collectFiles(dir) {
|
|
18
|
+
const results = [];
|
|
19
|
+
for (const entry of readdirSync(dir)) {
|
|
20
|
+
const full = join(dir, entry);
|
|
21
|
+
if (statSync(full).isDirectory()) results.push(...collectFiles(full));
|
|
22
|
+
else results.push(full);
|
|
23
|
+
}
|
|
24
|
+
return results;
|
|
25
|
+
}
|
|
26
|
+
function copyTemplateTree(src, dest) {
|
|
27
|
+
for (const entry of collectFiles(src)) {
|
|
28
|
+
const relative = entry.replace(src, "").replace(/^\//, "");
|
|
29
|
+
const destPath = join(dest, relative);
|
|
30
|
+
if (entry.endsWith(".gitkeep")) {
|
|
31
|
+
const parentDir = destPath.replace("/.gitkeep", "");
|
|
32
|
+
mkdirSync(parentDir, { recursive: true });
|
|
33
|
+
writeFileSync(join(parentDir, ".gitkeep"), "");
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
mkdirSync(dirname(destPath), { recursive: true });
|
|
37
|
+
copyFileSync(entry, destPath);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function scaffoldWebChat(agentDir) {
|
|
41
|
+
const source = resolve(resolveTemplatesDir(), "web-chat");
|
|
42
|
+
const target = join(agentDir, "channels", "web");
|
|
43
|
+
if (existsSync(target)) {
|
|
44
|
+
return { targetPath: target, alreadyExisted: true };
|
|
45
|
+
}
|
|
46
|
+
mkdirSync(target, { recursive: true });
|
|
47
|
+
copyTemplateTree(source, target);
|
|
48
|
+
return { targetPath: target, alreadyExisted: false };
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export {
|
|
52
|
+
scaffoldWebChat
|
|
53
|
+
};
|
|
54
|
+
//# sourceMappingURL=chunk-SGWQZZ2A.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/scaffold-web-chat.ts"],"sourcesContent":["import { copyFileSync, existsSync, mkdirSync, readdirSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\n\nfunction resolveTemplatesDir(): string {\n let current = __dirname;\n for (let i = 0; i < 6; i += 1) {\n const candidate = resolve(current, \"templates\");\n if (existsSync(candidate)) return candidate;\n const parent = dirname(current);\n if (parent === current) break;\n current = parent;\n }\n return resolve(__dirname, \"../../templates\");\n}\n\nfunction collectFiles(dir: string): string[] {\n const results: string[] = [];\n for (const entry of readdirSync(dir)) {\n const full = join(dir, entry);\n if (statSync(full).isDirectory()) results.push(...collectFiles(full));\n else results.push(full);\n }\n return results;\n}\n\nfunction copyTemplateTree(src: string, dest: string): void {\n for (const entry of collectFiles(src)) {\n const relative = entry.replace(src, \"\").replace(/^\\//, \"\");\n const destPath = join(dest, relative);\n if (entry.endsWith(\".gitkeep\")) {\n const parentDir = destPath.replace(\"/.gitkeep\", \"\");\n mkdirSync(parentDir, { recursive: true });\n writeFileSync(join(parentDir, \".gitkeep\"), \"\");\n continue;\n }\n mkdirSync(dirname(destPath), { recursive: true });\n copyFileSync(entry, destPath);\n }\n}\n\nexport interface ScaffoldWebChatResult {\n readonly targetPath: string;\n readonly alreadyExisted: boolean;\n}\n\n/**\n * Copies the web-chat template into `<agentDir>/channels/web`. If the target\n * already exists, leaves it untouched and reports so callers can decide\n * whether to prompt for overwrite.\n */\nexport function scaffoldWebChat(agentDir: string): ScaffoldWebChatResult {\n const source = resolve(resolveTemplatesDir(), \"web-chat\");\n const target = join(agentDir, \"channels\", \"web\");\n if (existsSync(target)) {\n return { targetPath: target, alreadyExisted: true };\n }\n mkdirSync(target, { recursive: true });\n copyTemplateTree(source, target);\n return { targetPath: target, alreadyExisted: false };\n}\n"],"mappings":";AAAA,SAAS,cAAc,YAAY,WAAW,aAAa,UAAU,qBAAqB;AAC1F,SAAS,SAAS,MAAM,eAAe;AACvC,SAAS,qBAAqB;AAE9B,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AAExD,SAAS,sBAA8B;AACrC,MAAI,UAAU;AACd,WAAS,IAAI,GAAG,IAAI,GAAG,KAAK,GAAG;AAC7B,UAAM,YAAY,QAAQ,SAAS,WAAW;AAC9C,QAAI,WAAW,SAAS,EAAG,QAAO;AAClC,UAAM,SAAS,QAAQ,OAAO;AAC9B,QAAI,WAAW,QAAS;AACxB,cAAU;AAAA,EACZ;AACA,SAAO,QAAQ,WAAW,iBAAiB;AAC7C;AAEA,SAAS,aAAa,KAAuB;AAC3C,QAAM,UAAoB,CAAC;AAC3B,aAAW,SAAS,YAAY,GAAG,GAAG;AACpC,UAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,QAAI,SAAS,IAAI,EAAE,YAAY,EAAG,SAAQ,KAAK,GAAG,aAAa,IAAI,CAAC;AAAA,QAC/D,SAAQ,KAAK,IAAI;AAAA,EACxB;AACA,SAAO;AACT;AAEA,SAAS,iBAAiB,KAAa,MAAoB;AACzD,aAAW,SAAS,aAAa,GAAG,GAAG;AACrC,UAAM,WAAW,MAAM,QAAQ,KAAK,EAAE,EAAE,QAAQ,OAAO,EAAE;AACzD,UAAM,WAAW,KAAK,MAAM,QAAQ;AACpC,QAAI,MAAM,SAAS,UAAU,GAAG;AAC9B,YAAM,YAAY,SAAS,QAAQ,aAAa,EAAE;AAClD,gBAAU,WAAW,EAAE,WAAW,KAAK,CAAC;AACxC,oBAAc,KAAK,WAAW,UAAU,GAAG,EAAE;AAC7C;AAAA,IACF;AACA,cAAU,QAAQ,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAChD,iBAAa,OAAO,QAAQ;AAAA,EAC9B;AACF;AAYO,SAAS,gBAAgB,UAAyC;AACvE,QAAM,SAAS,QAAQ,oBAAoB,GAAG,UAAU;AACxD,QAAM,SAAS,KAAK,UAAU,YAAY,KAAK;AAC/C,MAAI,WAAW,MAAM,GAAG;AACtB,WAAO,EAAE,YAAY,QAAQ,gBAAgB,KAAK;AAAA,EACpD;AACA,YAAU,QAAQ,EAAE,WAAW,KAAK,CAAC;AACrC,mBAAiB,QAAQ,MAAM;AAC/B,SAAO,EAAE,YAAY,QAAQ,gBAAgB,MAAM;AACrD;","names":[]}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
// src/cli/banner.ts
|
|
2
|
+
import { readFileSync } from "fs";
|
|
3
|
+
import { resolve, dirname } from "path";
|
|
4
|
+
import { fileURLToPath } from "url";
|
|
5
|
+
import chalk from "chalk";
|
|
6
|
+
var __dirname = dirname(fileURLToPath(import.meta.url));
|
|
7
|
+
var _version = "0.0.0";
|
|
8
|
+
try {
|
|
9
|
+
const pkg = JSON.parse(readFileSync(resolve(__dirname, "../package.json"), "utf-8"));
|
|
10
|
+
_version = pkg.version;
|
|
11
|
+
} catch {
|
|
12
|
+
}
|
|
13
|
+
var ARCIE_WORDMARK = "arcie";
|
|
14
|
+
function version() {
|
|
15
|
+
return _version;
|
|
16
|
+
}
|
|
17
|
+
function arcieCliBanner() {
|
|
18
|
+
return `${chalk.bgBlack.white(` ${ARCIE_WORDMARK} `)} ${chalk.dim(`v${_version}`)}`;
|
|
19
|
+
}
|
|
20
|
+
function showHeader() {
|
|
21
|
+
console.log(` ${chalk.bold("arcie")} ${chalk.dim(`v${_version}`)}`);
|
|
22
|
+
console.log();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export {
|
|
26
|
+
version,
|
|
27
|
+
arcieCliBanner,
|
|
28
|
+
showHeader
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=chunk-XOFWQUOO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/cli/banner.ts"],"sourcesContent":["import { readFileSync } from \"node:fs\";\nimport { resolve, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport chalk from \"chalk\";\n\nconst __dirname = dirname(fileURLToPath(import.meta.url));\nlet _version = \"0.0.0\";\ntry {\n const pkg = JSON.parse(readFileSync(resolve(__dirname, \"../package.json\"), \"utf-8\"));\n _version = pkg.version;\n} catch {}\n\nexport const ARCIE_WORDMARK = \"arcie\";\n\nexport function version(): string {\n return _version;\n}\n\nexport function arcieCliBanner(): string {\n return `${chalk.bgBlack.white(` ${ARCIE_WORDMARK} `)} ${chalk.dim(`v${_version}`)}`;\n}\n\nexport function showHeader(): void {\n console.log(` ${chalk.bold(\"arcie\")} ${chalk.dim(`v${_version}`)}`);\n console.log();\n}\n\nexport function divider(): void {\n console.log();\n console.log(` ${chalk.dim(\"─\".repeat(50))}`);\n console.log();\n}\n"],"mappings":";AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS,eAAe;AACjC,SAAS,qBAAqB;AAC9B,OAAO,WAAW;AAElB,IAAM,YAAY,QAAQ,cAAc,YAAY,GAAG,CAAC;AACxD,IAAI,WAAW;AACf,IAAI;AACF,QAAM,MAAM,KAAK,MAAM,aAAa,QAAQ,WAAW,iBAAiB,GAAG,OAAO,CAAC;AACnF,aAAW,IAAI;AACjB,QAAQ;AAAC;AAEF,IAAM,iBAAiB;AAEvB,SAAS,UAAkB;AAChC,SAAO;AACT;AAEO,SAAS,iBAAyB;AACvC,SAAO,GAAG,MAAM,QAAQ,MAAM,IAAI,cAAc,GAAG,CAAC,IAAI,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;AACnF;AAEO,SAAS,aAAmB;AACjC,UAAQ,IAAI,KAAK,MAAM,KAAK,OAAO,CAAC,IAAI,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC,EAAE;AACnE,UAAQ,IAAI;AACd;","names":[]}
|