golem-kit 0.1.1 → 0.2.0

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.
Files changed (61) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +8 -5
  3. package/docs/agents.md +64 -0
  4. package/docs/app-backend.md +259 -0
  5. package/docs/architecture.md +93 -0
  6. package/docs/builder.md +15 -0
  7. package/docs/knowledge.md +35 -0
  8. package/docs/local-cli.md +19 -12
  9. package/docs/source-development.md +31 -0
  10. package/index.html +9 -0
  11. package/package.json +24 -5
  12. package/src/backend/accounts.ts +287 -0
  13. package/src/backend/app.ts +269 -0
  14. package/src/backend/files.ts +68 -0
  15. package/src/backend/http.ts +276 -0
  16. package/src/backend/index.ts +10 -0
  17. package/src/backend/jobs.ts +302 -0
  18. package/src/backend/jsonl.ts +87 -0
  19. package/src/backend/knowledge.ts +264 -0
  20. package/src/backend/model.ts +129 -0
  21. package/src/backend/rules.ts +53 -0
  22. package/src/backend/sqlite.ts +73 -0
  23. package/src/backend/views.ts +216 -0
  24. package/src/brain.ts +94 -0
  25. package/src/browser/adapters.ts +229 -53
  26. package/src/browser/ansi.ts +104 -0
  27. package/src/browser/app.d.ts +5 -2
  28. package/src/browser/app.tsx +167 -39
  29. package/src/browser/groups.tsx +29 -0
  30. package/src/browser/main.tsx +1 -0
  31. package/src/browser/panekeys.ts +34 -0
  32. package/src/browser/sources.tsx +113 -0
  33. package/src/browser/styles.css +36 -0
  34. package/src/browser/terminal.tsx +89 -0
  35. package/src/browser-build.ts +20 -7
  36. package/src/chat.ts +74 -0
  37. package/src/cli.ts +85 -13
  38. package/src/client.ts +205 -0
  39. package/src/config.ts +139 -5
  40. package/src/dev-server.ts +336 -39
  41. package/src/entry.mjs +19 -0
  42. package/src/eslint.mjs +55 -0
  43. package/src/operations.ts +169 -0
  44. package/src/runtime/assistant.ts +141 -0
  45. package/src/runtime/discovery.ts +13 -7
  46. package/src/runtime/harness/agent-status.js +388 -0
  47. package/src/runtime/harness/claude-tmux.js +573 -0
  48. package/src/runtime/harness/codex-notify.js +95 -0
  49. package/src/runtime/harness/codex-tmux.js +292 -0
  50. package/src/runtime/harness/fake.js +430 -0
  51. package/src/runtime/harness/package.json +1 -0
  52. package/src/runtime/harness/port.js +208 -0
  53. package/src/runtime/harness/tmux-session.js +556 -0
  54. package/src/runtime/harness/tmux.js +285 -0
  55. package/src/runtime/harness/turnend-hook.js +105 -0
  56. package/src/runtime/session.ts +171 -34
  57. package/src/runtime/tmux.ts +173 -0
  58. package/src/runtime/tool-names.ts +19 -0
  59. package/src/source-mode.ts +56 -0
  60. package/vite.config.ts +2 -4
  61. package/src/runtime/codex.ts +0 -119
@@ -1,119 +0,0 @@
1
- import { spawn, type ChildProcess } from 'node:child_process'
2
- import type { BackendEvent, SessionBackend } from './session.ts'
3
-
4
- type JsonEvent = { type?: string; thread_id?: string; item?: { type?: string; text?: string }; error?: string; message?: string }
5
- export type SandboxMode = 'read-only' | 'danger-full-access'
6
-
7
- /**
8
- * One native `codex exec --json` process per turn; the thread id preserves continuity.
9
- * `mode` is chosen by the caller (the dev server, from the session's explicit build intent),
10
- * never defaulted here: an explicit build intent selects `danger-full-access`, a supported
11
- * `-s`/`--sandbox` value (`codex exec --help`) that runs with the account's own ordinary
12
- * filesystem permissions — not the `--dangerously-bypass-approvals-and-sandbox` omnibus flag,
13
- * which is never used here; every other session stays `read-only`.
14
- *
15
- * `cwd`/`-C` are pinned to the resolved app root so Codex resolves relative paths correctly —
16
- * not as a security boundary. A build-mode session can write anywhere this account can.
17
- */
18
- export class CodexBackend implements SessionBackend {
19
- private emit!: (event: BackendEvent) => void
20
- private nativeThreadId: string | undefined
21
- private child: ChildProcess | undefined
22
- private request: Promise<void> | undefined
23
- private interrupted = false
24
- private childClosed: Promise<void> | undefined
25
- private readonly cwd: string
26
- private readonly mode: SandboxMode
27
- private readonly executable: string
28
- private readonly prefixArgs: string[]
29
-
30
- constructor(cwd: string, mode: SandboxMode, executable = 'codex', prefixArgs: string[] = [], threadId?: string) {
31
- this.cwd = cwd
32
- this.mode = mode
33
- this.executable = executable
34
- this.prefixArgs = prefixArgs
35
- this.nativeThreadId = threadId
36
- }
37
-
38
- async start(emit: (event: BackendEvent) => void): Promise<void> { this.emit = emit }
39
-
40
- threadId(): string | undefined { return this.nativeThreadId }
41
-
42
- send(text: string): Promise<void> {
43
- if (this.request) return Promise.reject(new Error('Codex is already handling a request'))
44
- const args = this.nativeThreadId
45
- ? [...this.prefixArgs, 'exec', 'resume', this.nativeThreadId, '--json', '-c', `sandbox_mode="${this.mode}"`, '--skip-git-repo-check', text]
46
- : [...this.prefixArgs, 'exec', '--json', '-s', this.mode, '-C', this.cwd, '--skip-git-repo-check', text]
47
- this.request = new Promise((resolve, reject) => {
48
- this.interrupted = false
49
- const child = spawn(this.executable, args, { cwd: this.cwd, stdio: ['ignore', 'pipe', 'pipe'], windowsHide: true, detached: process.platform !== 'win32' })
50
- this.child = child
51
- this.childClosed = new Promise((resolve) => child.once('close', () => resolve()))
52
- let stderr = ''
53
- let output = ''
54
- let settled = false
55
- const fail = (message: string) => {
56
- if (settled) return
57
- settled = true
58
- this.emit({ type: 'error', message })
59
- reject(new Error(message))
60
- void this.stopChild(child)
61
- }
62
- child.stderr.setEncoding('utf8').on('data', (chunk) => { stderr += chunk })
63
- child.stdout.setEncoding('utf8').on('data', (chunk) => {
64
- output += String(chunk)
65
- const lines = output.split('\n')
66
- output = lines.pop() ?? ''
67
- for (const line of lines.filter(Boolean)) {
68
- let event: JsonEvent
69
- try { event = JSON.parse(line) } catch { continue }
70
- if (event.type === 'thread.started' && event.thread_id) this.nativeThreadId = event.thread_id
71
- if (event.type === 'item.completed' && event.item?.type === 'agent_message' && event.item.text) {
72
- this.emit({ type: 'message', text: event.item.text })
73
- }
74
- if (event.type === 'error' || event.type === 'turn.failed') fail(event.error ?? event.message ?? 'Codex request failed')
75
- }
76
- })
77
- child.once('error', (error) => fail(error.message))
78
- child.once('close', (code, signal) => {
79
- this.child = undefined
80
- this.childClosed = undefined
81
- this.request = undefined
82
- if (settled) return
83
- if (code === 0 || this.interrupted) { settled = true; resolve(); return }
84
- fail(stderr.trim() || (signal ? `Codex terminated by ${signal}` : `Codex exited with code ${code}`))
85
- })
86
- })
87
- return this.request
88
- }
89
-
90
- async interrupt(): Promise<void> {
91
- if (!this.child) return
92
- this.interrupted = true
93
- await this.stopChild(this.child)
94
- }
95
-
96
- async shutdown(): Promise<void> {
97
- if (this.child) await this.stopChild(this.child)
98
- if (this.request) await this.request.catch(() => {})
99
- this.child = undefined
100
- }
101
-
102
- private async stopChild(child: ChildProcess): Promise<void> {
103
- const closed = this.childClosed ?? new Promise<void>((resolve) => child.once('close', () => resolve()))
104
- this.signal(child, 'SIGTERM')
105
- // Always escalate the request group: its leader may exit after TERM while a child survives.
106
- await new Promise<void>((resolve) => setTimeout(resolve, 250))
107
- this.signal(child, 'SIGKILL')
108
- await Promise.race([closed, new Promise<void>((resolve) => setTimeout(resolve, 750))])
109
- }
110
-
111
- private signal(child: ChildProcess, signal: NodeJS.Signals): void {
112
- try {
113
- if (process.platform !== 'win32' && child.pid) process.kill(-child.pid, signal)
114
- else child.kill(signal)
115
- } catch (error) {
116
- if ((error as NodeJS.ErrnoException).code !== 'ESRCH') throw error
117
- }
118
- }
119
- }