@poping/yome 0.0.2

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 (156) hide show
  1. package/README.md +54 -0
  2. package/bin/yome.js +2 -0
  3. package/dist/agent.d.ts +43 -0
  4. package/dist/agent.js +140 -0
  5. package/dist/agent.js.map +1 -0
  6. package/dist/config.d.ts +41 -0
  7. package/dist/config.js +108 -0
  8. package/dist/config.js.map +1 -0
  9. package/dist/context.d.ts +1 -0
  10. package/dist/context.js +101 -0
  11. package/dist/context.js.map +1 -0
  12. package/dist/index.d.ts +1 -0
  13. package/dist/index.js +65 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/llm.d.ts +13 -0
  16. package/dist/llm.js +317 -0
  17. package/dist/llm.js.map +1 -0
  18. package/dist/loops/chain.d.ts +15 -0
  19. package/dist/loops/chain.js +105 -0
  20. package/dist/loops/chain.js.map +1 -0
  21. package/dist/loops/evaluator.d.ts +12 -0
  22. package/dist/loops/evaluator.js +100 -0
  23. package/dist/loops/evaluator.js.map +1 -0
  24. package/dist/loops/index.d.ts +12 -0
  25. package/dist/loops/index.js +39 -0
  26. package/dist/loops/index.js.map +1 -0
  27. package/dist/loops/orchestrator.d.ts +13 -0
  28. package/dist/loops/orchestrator.js +107 -0
  29. package/dist/loops/orchestrator.js.map +1 -0
  30. package/dist/loops/parallel.d.ts +6 -0
  31. package/dist/loops/parallel.js +48 -0
  32. package/dist/loops/parallel.js.map +1 -0
  33. package/dist/loops/route.d.ts +13 -0
  34. package/dist/loops/route.js +88 -0
  35. package/dist/loops/route.js.map +1 -0
  36. package/dist/loops/simple.d.ts +6 -0
  37. package/dist/loops/simple.js +46 -0
  38. package/dist/loops/simple.js.map +1 -0
  39. package/dist/loops/types.d.ts +32 -0
  40. package/dist/loops/types.js +9 -0
  41. package/dist/loops/types.js.map +1 -0
  42. package/dist/permissions/checker.d.ts +18 -0
  43. package/dist/permissions/checker.js +89 -0
  44. package/dist/permissions/checker.js.map +1 -0
  45. package/dist/permissions/index.d.ts +4 -0
  46. package/dist/permissions/index.js +4 -0
  47. package/dist/permissions/index.js.map +1 -0
  48. package/dist/permissions/loader.d.ts +22 -0
  49. package/dist/permissions/loader.js +104 -0
  50. package/dist/permissions/loader.js.map +1 -0
  51. package/dist/permissions/ruleParser.d.ts +23 -0
  52. package/dist/permissions/ruleParser.js +59 -0
  53. package/dist/permissions/ruleParser.js.map +1 -0
  54. package/dist/permissions/types.d.ts +37 -0
  55. package/dist/permissions/types.js +2 -0
  56. package/dist/permissions/types.js.map +1 -0
  57. package/dist/sessions.d.ts +20 -0
  58. package/dist/sessions.js +119 -0
  59. package/dist/sessions.js.map +1 -0
  60. package/dist/skills/index.d.ts +2 -0
  61. package/dist/skills/index.js +2 -0
  62. package/dist/skills/index.js.map +1 -0
  63. package/dist/skills/loader.d.ts +4 -0
  64. package/dist/skills/loader.js +125 -0
  65. package/dist/skills/loader.js.map +1 -0
  66. package/dist/skills/types.d.ts +22 -0
  67. package/dist/skills/types.js +2 -0
  68. package/dist/skills/types.js.map +1 -0
  69. package/dist/subagent/agentTool.d.ts +7 -0
  70. package/dist/subagent/agentTool.js +121 -0
  71. package/dist/subagent/agentTool.js.map +1 -0
  72. package/dist/subagent/builtinAgents.d.ts +3 -0
  73. package/dist/subagent/builtinAgents.js +23 -0
  74. package/dist/subagent/builtinAgents.js.map +1 -0
  75. package/dist/subagent/index.d.ts +6 -0
  76. package/dist/subagent/index.js +5 -0
  77. package/dist/subagent/index.js.map +1 -0
  78. package/dist/subagent/loadAgents.d.ts +2 -0
  79. package/dist/subagent/loadAgents.js +98 -0
  80. package/dist/subagent/loadAgents.js.map +1 -0
  81. package/dist/subagent/runAgent.d.ts +18 -0
  82. package/dist/subagent/runAgent.js +115 -0
  83. package/dist/subagent/runAgent.js.map +1 -0
  84. package/dist/subagent/types.d.ts +20 -0
  85. package/dist/subagent/types.js +2 -0
  86. package/dist/subagent/types.js.map +1 -0
  87. package/dist/toggleState.d.ts +6 -0
  88. package/dist/toggleState.js +58 -0
  89. package/dist/toggleState.js.map +1 -0
  90. package/dist/tools/bash.d.ts +2 -0
  91. package/dist/tools/bash.js +78 -0
  92. package/dist/tools/bash.js.map +1 -0
  93. package/dist/tools/edit.d.ts +2 -0
  94. package/dist/tools/edit.js +103 -0
  95. package/dist/tools/edit.js.map +1 -0
  96. package/dist/tools/glob.d.ts +2 -0
  97. package/dist/tools/glob.js +44 -0
  98. package/dist/tools/glob.js.map +1 -0
  99. package/dist/tools/grep.d.ts +2 -0
  100. package/dist/tools/grep.js +89 -0
  101. package/dist/tools/grep.js.map +1 -0
  102. package/dist/tools/index.d.ts +15 -0
  103. package/dist/tools/index.js +99 -0
  104. package/dist/tools/index.js.map +1 -0
  105. package/dist/tools/ls.d.ts +2 -0
  106. package/dist/tools/ls.js +47 -0
  107. package/dist/tools/ls.js.map +1 -0
  108. package/dist/tools/read.d.ts +2 -0
  109. package/dist/tools/read.js +52 -0
  110. package/dist/tools/read.js.map +1 -0
  111. package/dist/tools/write.d.ts +2 -0
  112. package/dist/tools/write.js +46 -0
  113. package/dist/tools/write.js.map +1 -0
  114. package/dist/types.d.ts +82 -0
  115. package/dist/types.js +13 -0
  116. package/dist/types.js.map +1 -0
  117. package/dist/ui/AgentPicker.d.ts +12 -0
  118. package/dist/ui/AgentPicker.js +32 -0
  119. package/dist/ui/AgentPicker.js.map +1 -0
  120. package/dist/ui/App.d.ts +6 -0
  121. package/dist/ui/App.js +327 -0
  122. package/dist/ui/App.js.map +1 -0
  123. package/dist/ui/Banner.d.ts +1 -0
  124. package/dist/ui/Banner.js +14 -0
  125. package/dist/ui/Banner.js.map +1 -0
  126. package/dist/ui/InputBar.d.ts +17 -0
  127. package/dist/ui/InputBar.js +93 -0
  128. package/dist/ui/InputBar.js.map +1 -0
  129. package/dist/ui/Markdown.d.ts +4 -0
  130. package/dist/ui/Markdown.js +97 -0
  131. package/dist/ui/Markdown.js.map +1 -0
  132. package/dist/ui/MessageList.d.ts +17 -0
  133. package/dist/ui/MessageList.js +50 -0
  134. package/dist/ui/MessageList.js.map +1 -0
  135. package/dist/ui/ModelPicker.d.ts +9 -0
  136. package/dist/ui/ModelPicker.js +70 -0
  137. package/dist/ui/ModelPicker.js.map +1 -0
  138. package/dist/ui/PermissionPrompt.d.ts +10 -0
  139. package/dist/ui/PermissionPrompt.js +37 -0
  140. package/dist/ui/PermissionPrompt.js.map +1 -0
  141. package/dist/ui/SessionPicker.d.ts +8 -0
  142. package/dist/ui/SessionPicker.js +64 -0
  143. package/dist/ui/SessionPicker.js.map +1 -0
  144. package/dist/ui/Spinner.d.ts +3 -0
  145. package/dist/ui/Spinner.js +15 -0
  146. package/dist/ui/Spinner.js.map +1 -0
  147. package/dist/ui/TogglePicker.d.ts +16 -0
  148. package/dist/ui/TogglePicker.js +35 -0
  149. package/dist/ui/TogglePicker.js.map +1 -0
  150. package/dist/ui/ToolResult.d.ts +6 -0
  151. package/dist/ui/ToolResult.js +59 -0
  152. package/dist/ui/ToolResult.js.map +1 -0
  153. package/dist/utils/imagePaste.d.ts +12 -0
  154. package/dist/utils/imagePaste.js +54 -0
  155. package/dist/utils/imagePaste.js.map +1 -0
  156. package/package.json +44 -0
@@ -0,0 +1,13 @@
1
+ import type { AgentLoop, AgentLoopContext, AgentLoopCallbacks, UserInput } from './types.js';
2
+ /**
3
+ * Orchestrator-Workers: a central LLM dynamically breaks down the task,
4
+ * delegates subtasks to worker LLM calls (with tools), then synthesizes results.
5
+ *
6
+ * Flow: In → Orchestrator → [Worker1, Worker2, ...] (parallel) → Synthesizer → Out
7
+ */
8
+ export declare class OrchestratorAgentLoop implements AgentLoop {
9
+ readonly name = "orchestrator";
10
+ readonly description = "Orchestrator-workers: decompose, delegate in parallel, synthesize";
11
+ run(userMessage: UserInput, ctx: AgentLoopContext, cb: AgentLoopCallbacks): Promise<void>;
12
+ private runWorker;
13
+ }
@@ -0,0 +1,107 @@
1
+ import { callLLM, extractText, callLLMStream } from '../llm.js';
2
+ import { userInputAsText } from './types.js';
3
+ const MAX_WORKER_ITERATIONS = 15;
4
+ /**
5
+ * Orchestrator-Workers: a central LLM dynamically breaks down the task,
6
+ * delegates subtasks to worker LLM calls (with tools), then synthesizes results.
7
+ *
8
+ * Flow: In → Orchestrator → [Worker1, Worker2, ...] (parallel) → Synthesizer → Out
9
+ */
10
+ export class OrchestratorAgentLoop {
11
+ name = 'orchestrator';
12
+ description = 'Orchestrator-workers: decompose, delegate in parallel, synthesize';
13
+ async run(userMessage, ctx, cb) {
14
+ ctx.messages.push({ role: 'user', content: userMessage });
15
+ let totalInput = 0;
16
+ let totalOutput = 0;
17
+ try {
18
+ // Step 1: Orchestrator decomposes the task
19
+ const decomposeResponse = await callLLM(ctx.config, ctx.systemPrompt, [
20
+ ...ctx.messages,
21
+ {
22
+ role: 'user',
23
+ content: 'Break this task into independent subtasks that can be executed in parallel. ' +
24
+ 'Output ONLY a JSON array of objects: [{"id": 1, "task": "description"}, ...]. ' +
25
+ 'Keep it to 2-5 subtasks. No other text.',
26
+ },
27
+ ]);
28
+ totalInput += decomposeResponse.usage.input_tokens;
29
+ totalOutput += decomposeResponse.usage.output_tokens;
30
+ const decomposeText = extractText(decomposeResponse);
31
+ let subtasks;
32
+ try {
33
+ const match = decomposeText.match(/\[[\s\S]*\]/);
34
+ subtasks = match ? JSON.parse(match[0]) : [{ id: 1, task: userInputAsText(userMessage) }];
35
+ }
36
+ catch {
37
+ subtasks = [{ id: 1, task: userInputAsText(userMessage) }];
38
+ }
39
+ cb.onTextDelta(`**Orchestrator** dispatching ${subtasks.length} workers:\n`);
40
+ subtasks.forEach((s) => cb.onTextDelta(`- Worker ${s.id}: ${s.task}\n`));
41
+ cb.onTextDelta('\n');
42
+ // Step 2: Execute workers in parallel
43
+ const workerResults = await Promise.all(subtasks.map((subtask) => this.runWorker(subtask, ctx, cb).then((r) => {
44
+ totalInput += r.inputTokens;
45
+ totalOutput += r.outputTokens;
46
+ return r;
47
+ })));
48
+ // Step 3: Synthesizer combines results
49
+ cb.onTextDelta('\n---\n**Synthesizing results...**\n\n');
50
+ const synthesisContext = `Original task: ${userMessage}\n\n` +
51
+ workerResults
52
+ .map((r) => `## Worker ${r.id} (${r.task})\n${r.result}`)
53
+ .join('\n\n');
54
+ const synthesizeMessages = [
55
+ ...ctx.messages,
56
+ {
57
+ role: 'user',
58
+ content: `Here are the results from parallel workers. Synthesize them into a coherent final answer.\n\n${synthesisContext}`,
59
+ },
60
+ ];
61
+ const synthResponse = await callLLMStream(ctx.config, ctx.systemPrompt, synthesizeMessages, [], (event) => {
62
+ if (event.type === 'text_delta' && event.text) {
63
+ cb.onTextDelta(event.text);
64
+ }
65
+ });
66
+ totalInput += synthResponse.usage.input_tokens;
67
+ totalOutput += synthResponse.usage.output_tokens;
68
+ ctx.messages.push({ role: 'assistant', content: synthResponse.content });
69
+ }
70
+ catch (err) {
71
+ cb.onError(err);
72
+ return;
73
+ }
74
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
75
+ }
76
+ async runWorker(subtask, ctx, cb) {
77
+ const workerMessages = [
78
+ { role: 'user', content: `Execute this subtask: ${subtask.task}\nBe concise and focused.` },
79
+ ];
80
+ let inputTokens = 0;
81
+ let outputTokens = 0;
82
+ let resultText = '';
83
+ for (let i = 0; i < MAX_WORKER_ITERATIONS; i++) {
84
+ const response = await callLLMStream(ctx.config, ctx.systemPrompt, workerMessages, ctx.tools, (event) => {
85
+ if (event.type === 'text_delta' && event.text) {
86
+ resultText += event.text;
87
+ }
88
+ });
89
+ inputTokens += response.usage.input_tokens;
90
+ outputTokens += response.usage.output_tokens;
91
+ workerMessages.push({ role: 'assistant', content: response.content });
92
+ const toolUseBlocks = response.content.filter((b) => b.type === 'tool_use');
93
+ if (toolUseBlocks.length === 0 || response.stop_reason === 'end_turn')
94
+ break;
95
+ const toolResults = [];
96
+ for (const block of toolUseBlocks) {
97
+ cb.onToolUse(block.name, block.input);
98
+ const result = await ctx.executeTool(block.name, block.input);
99
+ cb.onToolResult(block.name, result);
100
+ toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: result });
101
+ }
102
+ workerMessages.push({ role: 'user', content: toolResults });
103
+ }
104
+ return { id: subtask.id, task: subtask.task, result: resultText || '(no output)', inputTokens, outputTokens };
105
+ }
106
+ }
107
+ //# sourceMappingURL=orchestrator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"orchestrator.js","sourceRoot":"","sources":["../../src/loops/orchestrator.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AgentLoop, AgentLoopContext, AgentLoopCallbacks, UserInput } from './types.js';
2
+ export declare class ParallelAgentLoop implements AgentLoop {
3
+ readonly name = "parallel";
4
+ readonly description = "Parallel tool execution loop";
5
+ run(userMessage: UserInput, ctx: AgentLoopContext, cb: AgentLoopCallbacks): Promise<void>;
6
+ }
@@ -0,0 +1,48 @@
1
+ import { callLLMStream } from '../llm.js';
2
+ const MAX_ITERATIONS = 30;
3
+ export class ParallelAgentLoop {
4
+ name = 'parallel';
5
+ description = 'Parallel tool execution loop';
6
+ async run(userMessage, ctx, cb) {
7
+ ctx.messages.push({ role: 'user', content: userMessage });
8
+ let totalInput = 0;
9
+ let totalOutput = 0;
10
+ for (let i = 0; i < MAX_ITERATIONS; i++) {
11
+ try {
12
+ const response = await callLLMStream(ctx.config, ctx.systemPrompt, ctx.messages, ctx.tools, (event) => {
13
+ if (event.type === 'text_delta' && event.text) {
14
+ cb.onTextDelta(event.text);
15
+ }
16
+ });
17
+ totalInput += response.usage.input_tokens;
18
+ totalOutput += response.usage.output_tokens;
19
+ ctx.messages.push({ role: 'assistant', content: response.content });
20
+ const toolUseBlocks = response.content.filter((b) => b.type === 'tool_use');
21
+ if (toolUseBlocks.length === 0 || response.stop_reason === 'end_turn') {
22
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
23
+ return;
24
+ }
25
+ // Execute all tools in parallel
26
+ for (const block of toolUseBlocks) {
27
+ cb.onToolUse(block.name, block.input);
28
+ }
29
+ const results = await Promise.all(toolUseBlocks.map((block) => ctx.executeTool(block.name, block.input)));
30
+ const toolResults = toolUseBlocks.map((block, idx) => {
31
+ cb.onToolResult(block.name, results[idx]);
32
+ return {
33
+ type: 'tool_result',
34
+ tool_use_id: block.id,
35
+ content: results[idx],
36
+ };
37
+ });
38
+ ctx.messages.push({ role: 'user', content: toolResults });
39
+ }
40
+ catch (err) {
41
+ cb.onError(err);
42
+ return;
43
+ }
44
+ }
45
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
46
+ }
47
+ }
48
+ //# sourceMappingURL=parallel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"parallel.js","sourceRoot":"","sources":["../../src/loops/parallel.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { AgentLoop, AgentLoopContext, AgentLoopCallbacks, UserInput } from './types.js';
2
+ /**
3
+ * Routing: classify input then dispatch to a specialized handler.
4
+ *
5
+ * Flow: In → LLM Router → [route1 | route2 | route3 | ...] → Out
6
+ *
7
+ * Each route has a specialized system prompt so the LLM focuses on that domain.
8
+ */
9
+ export declare class RouteAgentLoop implements AgentLoop {
10
+ readonly name = "route";
11
+ readonly description = "Routing: classify input then dispatch to specialized handler";
12
+ run(userMessage: UserInput, ctx: AgentLoopContext, cb: AgentLoopCallbacks): Promise<void>;
13
+ }
@@ -0,0 +1,88 @@
1
+ import { callLLM, extractText, callLLMStream } from '../llm.js';
2
+ const MAX_ITERATIONS = 30;
3
+ const ROUTES = [
4
+ {
5
+ name: 'code',
6
+ description: 'Writing, editing, debugging, or refactoring code',
7
+ systemPrompt: 'You are a coding specialist. Focus on writing clean, correct code. ' +
8
+ 'Read files before editing. Use tools to verify your changes compile/run.',
9
+ },
10
+ {
11
+ name: 'analyze',
12
+ description: 'Reading, understanding, explaining, or reviewing code/files',
13
+ systemPrompt: 'You are an analysis specialist. Focus on reading and understanding code. ' +
14
+ 'Provide clear explanations. Use Read/Grep/Glob to gather information before answering.',
15
+ },
16
+ {
17
+ name: 'shell',
18
+ description: 'Running commands, managing files, git operations, build/test tasks',
19
+ systemPrompt: 'You are a shell operations specialist. Focus on running commands efficiently. ' +
20
+ 'Prefer Bash tool for system operations. Be careful with destructive commands.',
21
+ },
22
+ {
23
+ name: 'general',
24
+ description: 'General questions, planning, brainstorming, or anything else',
25
+ systemPrompt: 'You are a helpful assistant. Answer the user concisely and accurately. ' +
26
+ 'Use tools only when needed to verify facts or gather information.',
27
+ },
28
+ ];
29
+ /**
30
+ * Routing: classify input then dispatch to a specialized handler.
31
+ *
32
+ * Flow: In → LLM Router → [route1 | route2 | route3 | ...] → Out
33
+ *
34
+ * Each route has a specialized system prompt so the LLM focuses on that domain.
35
+ */
36
+ export class RouteAgentLoop {
37
+ name = 'route';
38
+ description = 'Routing: classify input then dispatch to specialized handler';
39
+ async run(userMessage, ctx, cb) {
40
+ ctx.messages.push({ role: 'user', content: userMessage });
41
+ let totalInput = 0;
42
+ let totalOutput = 0;
43
+ try {
44
+ // Step 1: Classify
45
+ const routeList = ROUTES.map((r) => `- ${r.name}: ${r.description}`).join('\n');
46
+ const classifyResponse = await callLLM(ctx.config, 'You are a router.', [
47
+ {
48
+ role: 'user',
49
+ content: `Classify this request into exactly one category. Reply with ONLY the category name.\n\nCategories:\n${routeList}\n\nRequest: ${userMessage}`,
50
+ },
51
+ ]);
52
+ totalInput += classifyResponse.usage.input_tokens;
53
+ totalOutput += classifyResponse.usage.output_tokens;
54
+ const classification = extractText(classifyResponse).trim().toLowerCase();
55
+ const route = ROUTES.find((r) => classification.includes(r.name)) ?? ROUTES[ROUTES.length - 1];
56
+ cb.onTextDelta(`*[routed to: ${route.name}]*\n\n`);
57
+ // Step 2: Execute with specialized system prompt
58
+ const specializedPrompt = `${route.systemPrompt}\n\n${ctx.systemPrompt}`;
59
+ for (let i = 0; i < MAX_ITERATIONS; i++) {
60
+ const response = await callLLMStream(ctx.config, specializedPrompt, ctx.messages, ctx.tools, (event) => {
61
+ if (event.type === 'text_delta' && event.text) {
62
+ cb.onTextDelta(event.text);
63
+ }
64
+ });
65
+ totalInput += response.usage.input_tokens;
66
+ totalOutput += response.usage.output_tokens;
67
+ ctx.messages.push({ role: 'assistant', content: response.content });
68
+ const toolUseBlocks = response.content.filter((b) => b.type === 'tool_use');
69
+ if (toolUseBlocks.length === 0 || response.stop_reason === 'end_turn')
70
+ break;
71
+ const toolResults = [];
72
+ for (const block of toolUseBlocks) {
73
+ cb.onToolUse(block.name, block.input);
74
+ const result = await ctx.executeTool(block.name, block.input);
75
+ cb.onToolResult(block.name, result);
76
+ toolResults.push({ type: 'tool_result', tool_use_id: block.id, content: result });
77
+ }
78
+ ctx.messages.push({ role: 'user', content: toolResults });
79
+ }
80
+ }
81
+ catch (err) {
82
+ cb.onError(err);
83
+ return;
84
+ }
85
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
86
+ }
87
+ }
88
+ //# sourceMappingURL=route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"route.js","sourceRoot":"","sources":["../../src/loops/route.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ import type { AgentLoop, AgentLoopContext, AgentLoopCallbacks, UserInput } from './types.js';
2
+ export declare class SimpleAgentLoop implements AgentLoop {
3
+ readonly name = "simple";
4
+ readonly description = "Sequential tool-call loop (default)";
5
+ run(userMessage: UserInput, ctx: AgentLoopContext, cb: AgentLoopCallbacks): Promise<void>;
6
+ }
@@ -0,0 +1,46 @@
1
+ import { callLLMStream } from '../llm.js';
2
+ const MAX_ITERATIONS = 30;
3
+ export class SimpleAgentLoop {
4
+ name = 'simple';
5
+ description = 'Sequential tool-call loop (default)';
6
+ async run(userMessage, ctx, cb) {
7
+ ctx.messages.push({ role: 'user', content: userMessage });
8
+ let totalInput = 0;
9
+ let totalOutput = 0;
10
+ for (let i = 0; i < MAX_ITERATIONS; i++) {
11
+ try {
12
+ const response = await callLLMStream(ctx.config, ctx.systemPrompt, ctx.messages, ctx.tools, (event) => {
13
+ if (event.type === 'text_delta' && event.text) {
14
+ cb.onTextDelta(event.text);
15
+ }
16
+ });
17
+ totalInput += response.usage.input_tokens;
18
+ totalOutput += response.usage.output_tokens;
19
+ ctx.messages.push({ role: 'assistant', content: response.content });
20
+ const toolUseBlocks = response.content.filter((b) => b.type === 'tool_use');
21
+ if (toolUseBlocks.length === 0 || response.stop_reason === 'end_turn') {
22
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
23
+ return;
24
+ }
25
+ const toolResults = [];
26
+ for (const block of toolUseBlocks) {
27
+ cb.onToolUse(block.name, block.input);
28
+ const result = await ctx.executeTool(block.name, block.input);
29
+ cb.onToolResult(block.name, result);
30
+ toolResults.push({
31
+ type: 'tool_result',
32
+ tool_use_id: block.id,
33
+ content: result,
34
+ });
35
+ }
36
+ ctx.messages.push({ role: 'user', content: toolResults });
37
+ }
38
+ catch (err) {
39
+ cb.onError(err);
40
+ return;
41
+ }
42
+ }
43
+ cb.onDone({ inputTokens: totalInput, outputTokens: totalOutput });
44
+ }
45
+ }
46
+ //# sourceMappingURL=simple.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"simple.js","sourceRoot":"","sources":["../../src/loops/simple.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AAI1C,MAAM,cAAc,GAAG,EAAE,CAAC;AAE1B,MAAM,OAAO,eAAe;IACjB,IAAI,GAAG,QAAQ,CAAC;IAChB,WAAW,GAAG,qCAAqC,CAAC;IAE7D,KAAK,CAAC,GAAG,CACP,WAAsB,EACtB,GAAqB,EACrB,EAAsB;QAEtB,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;QAE1D,IAAI,UAAU,GAAG,CAAC,CAAC;QACnB,IAAI,WAAW,GAAG,CAAC,CAAC;QAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,cAAc,EAAE,CAAC,EAAE,EAAE,CAAC;YACxC,IAAI,CAAC;gBACH,MAAM,QAAQ,GAAG,MAAM,aAAa,CAClC,GAAG,CAAC,MAAM,EACV,GAAG,CAAC,YAAY,EAChB,GAAG,CAAC,QAAQ,EACZ,GAAG,CAAC,KAAK,EACT,CAAC,KAAK,EAAE,EAAE;oBACR,IAAI,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC;wBAC9C,EAAE,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;oBAC7B,CAAC;gBACH,CAAC,CACF,CAAC;gBAEF,UAAU,IAAI,QAAQ,CAAC,KAAK,CAAC,YAAY,CAAC;gBAC1C,WAAW,IAAI,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC;gBAC5C,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,CAAC,CAAC;gBAEpE,MAAM,aAAa,GAAG,QAAQ,CAAC,OAAO,CAAC,MAAM,CAC3C,CAAC,CAAC,EAA4C,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CACvE,CAAC;gBAEF,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC,IAAI,QAAQ,CAAC,WAAW,KAAK,UAAU,EAAE,CAAC;oBACtE,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;oBAClE,OAAO;gBACT,CAAC;gBAED,MAAM,WAAW,GAAmB,EAAE,CAAC;gBACvC,KAAK,MAAM,KAAK,IAAI,aAAa,EAAE,CAAC;oBAClC,EAAE,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;oBACtC,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;oBAC9D,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;oBACpC,WAAW,CAAC,IAAI,CAAC;wBACf,IAAI,EAAE,aAAa;wBACnB,WAAW,EAAE,KAAK,CAAC,EAAE;wBACrB,OAAO,EAAE,MAAM;qBAChB,CAAC,CAAC;gBACL,CAAC;gBAED,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,GAAQ,EAAE,CAAC;gBAClB,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;gBAChB,OAAO;YACT,CAAC;QACH,CAAC;QAED,EAAE,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,CAAC,CAAC;IACpE,CAAC;CACF"}
@@ -0,0 +1,32 @@
1
+ import type { YomeConfig } from '../config.js';
2
+ import type { ContentBlock, AgentMessage, AnthropicTool } from '../types.js';
3
+ export interface AgentLoopCallbacks {
4
+ onTextDelta: (text: string) => void;
5
+ onToolUse: (name: string, input: Record<string, unknown>) => void;
6
+ onToolResult: (name: string, result: string) => void;
7
+ onDone: (usage: {
8
+ inputTokens: number;
9
+ outputTokens: number;
10
+ }) => void;
11
+ onError: (error: Error) => void;
12
+ }
13
+ export interface AgentLoopContext {
14
+ config: YomeConfig;
15
+ systemPrompt: string;
16
+ messages: AgentMessage[];
17
+ tools: AnthropicTool[];
18
+ executeTool: (name: string, input: Record<string, unknown>) => Promise<string>;
19
+ }
20
+ export type UserInput = string | ContentBlock[];
21
+ export declare function userInputAsText(input: UserInput): string;
22
+ export interface AgentLoop {
23
+ readonly name: string;
24
+ readonly description: string;
25
+ run(userMessage: UserInput, context: AgentLoopContext, callbacks: AgentLoopCallbacks): Promise<void>;
26
+ }
27
+ export interface AgentLoopRegistry {
28
+ get(name: string): AgentLoop | undefined;
29
+ list(): AgentLoop[];
30
+ register(loop: AgentLoop): void;
31
+ default(): AgentLoop;
32
+ }
@@ -0,0 +1,9 @@
1
+ export function userInputAsText(input) {
2
+ if (typeof input === 'string')
3
+ return input;
4
+ return input
5
+ .filter((b) => b.type === 'text')
6
+ .map((b) => b.text)
7
+ .join('\n');
8
+ }
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/loops/types.ts"],"names":[],"mappings":"AAqBA,MAAM,UAAU,eAAe,CAAC,KAAgB;IAC9C,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IAC5C,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAwC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC;SACtE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;SAClB,IAAI,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC"}
@@ -0,0 +1,18 @@
1
+ import type { ToolPermissionContext, PermissionDecision, PermissionResult } from './types.js';
2
+ /**
3
+ * Check if a specific command/path is allowed by a content-specific rule.
4
+ */
5
+ export declare function isContentAllowed(ctx: ToolPermissionContext, toolName: string, content: string): boolean;
6
+ /**
7
+ * Check if a specific command/path is denied by a content-specific rule.
8
+ */
9
+ export declare function isContentDenied(ctx: ToolPermissionContext, toolName: string, content: string): boolean;
10
+ /**
11
+ * Main permission check for a tool invocation.
12
+ *
13
+ * @param toolName - The tool being invoked
14
+ * @param isReadOnly - Whether the tool is read-only
15
+ * @param ctx - Current permission context
16
+ * @param toolResult - Optional result from the tool's own checkPermissions()
17
+ */
18
+ export declare function checkPermission(toolName: string, isReadOnly: boolean, ctx: ToolPermissionContext, toolResult?: PermissionResult): PermissionDecision;
@@ -0,0 +1,89 @@
1
+ import { parseRuleValue, toolMatchesRule, contentMatchesRule } from './ruleParser.js';
2
+ const RULE_SOURCES = ['cliArg', 'session', 'userSettings', 'projectSettings'];
3
+ function getAllowRules(ctx) {
4
+ return RULE_SOURCES.flatMap((source) => (ctx.allowRules[source] ?? []).map((s) => ({
5
+ source,
6
+ ruleBehavior: 'allow',
7
+ ruleValue: parseRuleValue(s),
8
+ })));
9
+ }
10
+ function getDenyRules(ctx) {
11
+ return RULE_SOURCES.flatMap((source) => (ctx.denyRules[source] ?? []).map((s) => ({
12
+ source,
13
+ ruleBehavior: 'deny',
14
+ ruleValue: parseRuleValue(s),
15
+ })));
16
+ }
17
+ /**
18
+ * Check if the entire tool is denied by a rule.
19
+ */
20
+ function isToolDenied(ctx, toolName) {
21
+ return getDenyRules(ctx).some((r) => toolMatchesRule(toolName, r.ruleValue));
22
+ }
23
+ /**
24
+ * Check if the entire tool is allowed by a rule.
25
+ */
26
+ function isToolAllowed(ctx, toolName) {
27
+ return getAllowRules(ctx).some((r) => toolMatchesRule(toolName, r.ruleValue));
28
+ }
29
+ /**
30
+ * Check if a specific command/path is allowed by a content-specific rule.
31
+ */
32
+ export function isContentAllowed(ctx, toolName, content) {
33
+ return getAllowRules(ctx).some((r) => contentMatchesRule(toolName, content, r.ruleValue));
34
+ }
35
+ /**
36
+ * Check if a specific command/path is denied by a content-specific rule.
37
+ */
38
+ export function isContentDenied(ctx, toolName, content) {
39
+ return getDenyRules(ctx).some((r) => contentMatchesRule(toolName, content, r.ruleValue));
40
+ }
41
+ /**
42
+ * Main permission check for a tool invocation.
43
+ *
44
+ * @param toolName - The tool being invoked
45
+ * @param isReadOnly - Whether the tool is read-only
46
+ * @param ctx - Current permission context
47
+ * @param toolResult - Optional result from the tool's own checkPermissions()
48
+ */
49
+ export function checkPermission(toolName, isReadOnly, ctx, toolResult) {
50
+ // 1. Check deny rules (always respected)
51
+ if (isToolDenied(ctx, toolName)) {
52
+ return { behavior: 'deny', message: `Permission to use ${toolName} has been denied.` };
53
+ }
54
+ // 2. Tool-specific deny
55
+ if (toolResult?.behavior === 'deny') {
56
+ return toolResult;
57
+ }
58
+ // 3. Bypass mode allows everything
59
+ if (ctx.mode === 'bypassPermissions') {
60
+ return { behavior: 'allow' };
61
+ }
62
+ // 4. Accept-edits mode: allow read-only tools + file edit tools
63
+ if (ctx.mode === 'acceptEdits') {
64
+ if (isReadOnly)
65
+ return { behavior: 'allow' };
66
+ const editTools = ['Edit', 'Write'];
67
+ if (editTools.includes(toolName))
68
+ return { behavior: 'allow' };
69
+ // Bash still needs ask unless explicitly allowed
70
+ }
71
+ // 5. Explicit allow rules
72
+ if (isToolAllowed(ctx, toolName)) {
73
+ return { behavior: 'allow' };
74
+ }
75
+ // 6. Tool-specific ask/allow
76
+ if (toolResult?.behavior === 'allow') {
77
+ return toolResult;
78
+ }
79
+ if (toolResult?.behavior === 'ask') {
80
+ return toolResult;
81
+ }
82
+ // 7. Read-only tools are always allowed
83
+ if (isReadOnly) {
84
+ return { behavior: 'allow' };
85
+ }
86
+ // 8. Default: ask for write operations
87
+ return { behavior: 'ask', message: `Allow ${toolName} to proceed?` };
88
+ }
89
+ //# sourceMappingURL=checker.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checker.js","sourceRoot":"","sources":["../../src/permissions/checker.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export type { PermissionMode, PermissionBehavior, PermissionRule, PermissionRuleValue, PermissionRuleSource, PermissionDecision, PermissionResult, ToolPermissionContext, PermissionRulesBySource, } from './types.js';
2
+ export { parseRuleValue, serializeRuleValue, toolMatchesRule, contentMatchesRule } from './ruleParser.js';
3
+ export { loadAllPermissionRules, loadDefaultMode, initializePermissionContext, addPermissionRuleToUserSettings } from './loader.js';
4
+ export { checkPermission, isContentAllowed, isContentDenied } from './checker.js';
@@ -0,0 +1,4 @@
1
+ export { parseRuleValue, serializeRuleValue, toolMatchesRule, contentMatchesRule } from './ruleParser.js';
2
+ export { loadAllPermissionRules, loadDefaultMode, initializePermissionContext, addPermissionRuleToUserSettings } from './loader.js';
3
+ export { checkPermission, isContentAllowed, isContentDenied } from './checker.js';
4
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/permissions/index.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,cAAc,EAAE,kBAAkB,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAC1G,OAAO,EAAE,sBAAsB,EAAE,eAAe,EAAE,2BAA2B,EAAE,+BAA+B,EAAE,MAAM,aAAa,CAAC;AACpI,OAAO,EAAE,eAAe,EAAE,gBAAgB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { PermissionBehavior, PermissionRule, PermissionMode, ToolPermissionContext } from './types.js';
2
+ /**
3
+ * Load all permission rules from user settings (~/.yome/settings.json)
4
+ * and project settings (.yome/settings.json).
5
+ */
6
+ export declare function loadAllPermissionRules(): PermissionRule[];
7
+ /**
8
+ * Load the default permission mode from settings.
9
+ */
10
+ export declare function loadDefaultMode(): PermissionMode;
11
+ /**
12
+ * Build an initial ToolPermissionContext from disk settings and CLI args.
13
+ */
14
+ export declare function initializePermissionContext(opts?: {
15
+ allowedTools?: string[];
16
+ disallowedTools?: string[];
17
+ mode?: PermissionMode;
18
+ }): ToolPermissionContext;
19
+ /**
20
+ * Persist a new allow/deny rule to user settings.
21
+ */
22
+ export declare function addPermissionRuleToUserSettings(ruleString: string, behavior: PermissionBehavior): void;