@pencil-agent/nano-pencil 2.0.0-beta.2 → 2.0.0-beta.4

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 (179) hide show
  1. package/dist/build-meta.json +3 -3
  2. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-continuations.d.ts +17 -0
  3. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-continuations.js +60 -0
  4. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-stream-events.d.ts +19 -0
  5. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-stream-events.js +55 -0
  6. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-results.d.ts +10 -0
  7. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-results.js +137 -0
  8. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-summaries.d.ts +22 -0
  9. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop-tool-summaries.js +64 -0
  10. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.d.ts +26 -0
  11. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-loop.js +913 -0
  12. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-run-result.d.ts +9 -0
  13. package/dist/node_modules/@pencil-agent/agent-core/dist/agent-run-result.js +32 -0
  14. package/dist/node_modules/@pencil-agent/agent-core/dist/agent.d.ts +215 -0
  15. package/dist/node_modules/@pencil-agent/agent-core/dist/agent.js +522 -0
  16. package/dist/node_modules/@pencil-agent/agent-core/dist/errors.d.ts +62 -0
  17. package/dist/node_modules/@pencil-agent/agent-core/dist/errors.js +146 -0
  18. package/dist/node_modules/@pencil-agent/agent-core/dist/index.d.ts +14 -0
  19. package/dist/node_modules/@pencil-agent/agent-core/dist/index.js +19 -0
  20. package/dist/node_modules/@pencil-agent/agent-core/dist/proxy.d.ts +91 -0
  21. package/dist/node_modules/@pencil-agent/agent-core/dist/proxy.js +279 -0
  22. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.d.ts +15 -0
  23. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-agent-loop.js +625 -0
  24. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-streaming-tool-executor.d.ts +33 -0
  25. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-streaming-tool-executor.js +189 -0
  26. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-tool-orchestration.d.ts +35 -0
  27. package/dist/node_modules/@pencil-agent/agent-core/dist/structured-adaptive-tool-orchestration.js +319 -0
  28. package/dist/node_modules/@pencil-agent/agent-core/dist/types.d.ts +417 -0
  29. package/dist/node_modules/@pencil-agent/agent-core/dist/types.js +13 -0
  30. package/dist/node_modules/@pencil-agent/agent-core/package.json +28 -0
  31. package/dist/node_modules/@pencil-agent/ai/dist/api-registry.d.ts +27 -0
  32. package/dist/node_modules/@pencil-agent/ai/dist/api-registry.js +152 -0
  33. package/dist/node_modules/@pencil-agent/ai/dist/cli.d.ts +2 -0
  34. package/dist/node_modules/@pencil-agent/ai/dist/cli.js +121 -0
  35. package/dist/node_modules/@pencil-agent/ai/dist/config-path.d.ts +1 -0
  36. package/dist/node_modules/@pencil-agent/ai/dist/config-path.js +17 -0
  37. package/dist/node_modules/@pencil-agent/ai/dist/debug-logger.d.ts +94 -0
  38. package/dist/node_modules/@pencil-agent/ai/dist/debug-logger.js +218 -0
  39. package/dist/node_modules/@pencil-agent/ai/dist/env-api-keys.d.ts +8 -0
  40. package/dist/node_modules/@pencil-agent/ai/dist/env-api-keys.js +107 -0
  41. package/dist/node_modules/@pencil-agent/ai/dist/env.d.ts +7 -0
  42. package/dist/node_modules/@pencil-agent/ai/dist/env.js +7 -0
  43. package/dist/node_modules/@pencil-agent/ai/dist/events.d.ts +8 -0
  44. package/dist/node_modules/@pencil-agent/ai/dist/events.js +7 -0
  45. package/dist/node_modules/@pencil-agent/ai/dist/index.d.ts +27 -0
  46. package/dist/node_modules/@pencil-agent/ai/dist/index.js +20 -0
  47. package/dist/node_modules/@pencil-agent/ai/dist/json.d.ts +7 -0
  48. package/dist/node_modules/@pencil-agent/ai/dist/json.js +7 -0
  49. package/dist/node_modules/@pencil-agent/ai/dist/models.d.ts +31 -0
  50. package/dist/node_modules/@pencil-agent/ai/dist/models.generated.d.ts +15159 -0
  51. package/dist/node_modules/@pencil-agent/ai/dist/models.generated.js +14928 -0
  52. package/dist/node_modules/@pencil-agent/ai/dist/models.js +60 -0
  53. package/dist/node_modules/@pencil-agent/ai/dist/overflow.d.ts +7 -0
  54. package/dist/node_modules/@pencil-agent/ai/dist/overflow.js +7 -0
  55. package/dist/node_modules/@pencil-agent/ai/dist/providers/amazon-bedrock.d.ts +20 -0
  56. package/dist/node_modules/@pencil-agent/ai/dist/providers/amazon-bedrock.js +606 -0
  57. package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.d.ts +38 -0
  58. package/dist/node_modules/@pencil-agent/ai/dist/providers/anthropic.js +737 -0
  59. package/dist/node_modules/@pencil-agent/ai/dist/providers/azure-openai-responses.d.ts +21 -0
  60. package/dist/node_modules/@pencil-agent/ai/dist/providers/azure-openai-responses.js +193 -0
  61. package/dist/node_modules/@pencil-agent/ai/dist/providers/github-copilot-headers.d.ts +13 -0
  62. package/dist/node_modules/@pencil-agent/ai/dist/providers/github-copilot-headers.js +34 -0
  63. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-gemini-cli.d.ts +79 -0
  64. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-gemini-cli.js +753 -0
  65. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-shared.d.ts +70 -0
  66. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-shared.js +311 -0
  67. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-vertex.d.ts +20 -0
  68. package/dist/node_modules/@pencil-agent/ai/dist/providers/google-vertex.js +380 -0
  69. package/dist/node_modules/@pencil-agent/ai/dist/providers/google.d.ts +18 -0
  70. package/dist/node_modules/@pencil-agent/ai/dist/providers/google.js +360 -0
  71. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-codex-responses.d.ts +8 -0
  72. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-codex-responses.js +704 -0
  73. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.d.ts +20 -0
  74. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-completions.js +870 -0
  75. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses-shared.d.ts +22 -0
  76. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses-shared.js +432 -0
  77. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.d.ts +19 -0
  78. package/dist/node_modules/@pencil-agent/ai/dist/providers/openai-responses.js +207 -0
  79. package/dist/node_modules/@pencil-agent/ai/dist/providers/register-builtins.d.ts +8 -0
  80. package/dist/node_modules/@pencil-agent/ai/dist/providers/register-builtins.js +86 -0
  81. package/dist/node_modules/@pencil-agent/ai/dist/providers/simple-options.d.ts +13 -0
  82. package/dist/node_modules/@pencil-agent/ai/dist/providers/simple-options.js +40 -0
  83. package/dist/node_modules/@pencil-agent/ai/dist/providers/transform-messages.d.ts +13 -0
  84. package/dist/node_modules/@pencil-agent/ai/dist/providers/transform-messages.js +175 -0
  85. package/dist/node_modules/@pencil-agent/ai/dist/registry.d.ts +8 -0
  86. package/dist/node_modules/@pencil-agent/ai/dist/registry.js +8 -0
  87. package/dist/node_modules/@pencil-agent/ai/dist/schema.d.ts +10 -0
  88. package/dist/node_modules/@pencil-agent/ai/dist/schema.js +9 -0
  89. package/dist/node_modules/@pencil-agent/ai/dist/stream.d.ts +25 -0
  90. package/dist/node_modules/@pencil-agent/ai/dist/stream.js +324 -0
  91. package/dist/node_modules/@pencil-agent/ai/dist/types.d.ts +306 -0
  92. package/dist/node_modules/@pencil-agent/ai/dist/types.js +7 -0
  93. package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream-types.d.ts +12 -0
  94. package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream-types.js +7 -0
  95. package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream.d.ts +31 -0
  96. package/dist/node_modules/@pencil-agent/ai/dist/utils/event-stream.js +98 -0
  97. package/dist/node_modules/@pencil-agent/ai/dist/utils/http-proxy.d.ts +13 -0
  98. package/dist/node_modules/@pencil-agent/ai/dist/utils/http-proxy.js +20 -0
  99. package/dist/node_modules/@pencil-agent/ai/dist/utils/json-parse.d.ts +14 -0
  100. package/dist/node_modules/@pencil-agent/ai/dist/utils/json-parse.js +34 -0
  101. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/anthropic.d.ts +22 -0
  102. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/anthropic.js +109 -0
  103. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/decode-credential.d.ts +12 -0
  104. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/decode-credential.js +25 -0
  105. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/github-copilot.d.ts +35 -0
  106. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/github-copilot.js +286 -0
  107. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-antigravity.d.ts +31 -0
  108. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-antigravity.js +378 -0
  109. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-gemini-cli.d.ts +31 -0
  110. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/google-gemini-cli.js +483 -0
  111. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/index.d.ts +60 -0
  112. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/index.js +131 -0
  113. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/openai-codex.d.ts +39 -0
  114. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/openai-codex.js +385 -0
  115. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/pkce.d.ts +18 -0
  116. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/pkce.js +36 -0
  117. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/types.d.ts +52 -0
  118. package/dist/node_modules/@pencil-agent/ai/dist/utils/oauth/types.js +7 -0
  119. package/dist/node_modules/@pencil-agent/ai/dist/utils/overflow.d.ts +57 -0
  120. package/dist/node_modules/@pencil-agent/ai/dist/utils/overflow.js +120 -0
  121. package/dist/node_modules/@pencil-agent/ai/dist/utils/sanitize-unicode.d.ts +16 -0
  122. package/dist/node_modules/@pencil-agent/ai/dist/utils/sanitize-unicode.js +20 -0
  123. package/dist/node_modules/@pencil-agent/ai/dist/utils/typebox-helpers.d.ts +22 -0
  124. package/dist/node_modules/@pencil-agent/ai/dist/utils/typebox-helpers.js +26 -0
  125. package/dist/node_modules/@pencil-agent/ai/dist/utils/validation.d.ts +23 -0
  126. package/dist/node_modules/@pencil-agent/ai/dist/utils/validation.js +78 -0
  127. package/dist/node_modules/@pencil-agent/ai/package.json +106 -0
  128. package/dist/node_modules/@pencil-agent/tui/dist/autocomplete.d.ts +62 -0
  129. package/dist/node_modules/@pencil-agent/tui/dist/autocomplete.js +624 -0
  130. package/dist/node_modules/@pencil-agent/tui/dist/components/box.d.ts +27 -0
  131. package/dist/node_modules/@pencil-agent/tui/dist/components/box.js +109 -0
  132. package/dist/node_modules/@pencil-agent/tui/dist/components/cancellable-loader.d.ts +27 -0
  133. package/dist/node_modules/@pencil-agent/tui/dist/components/cancellable-loader.js +40 -0
  134. package/dist/node_modules/@pencil-agent/tui/dist/components/editor.d.ts +218 -0
  135. package/dist/node_modules/@pencil-agent/tui/dist/components/editor.js +1697 -0
  136. package/dist/node_modules/@pencil-agent/tui/dist/components/image.d.ts +33 -0
  137. package/dist/node_modules/@pencil-agent/tui/dist/components/image.js +74 -0
  138. package/dist/node_modules/@pencil-agent/tui/dist/components/input.d.ts +42 -0
  139. package/dist/node_modules/@pencil-agent/tui/dist/components/input.js +438 -0
  140. package/dist/node_modules/@pencil-agent/tui/dist/components/loader.d.ts +26 -0
  141. package/dist/node_modules/@pencil-agent/tui/dist/components/loader.js +54 -0
  142. package/dist/node_modules/@pencil-agent/tui/dist/components/markdown.d.ts +100 -0
  143. package/dist/node_modules/@pencil-agent/tui/dist/components/markdown.js +634 -0
  144. package/dist/node_modules/@pencil-agent/tui/dist/components/select-list.d.ts +37 -0
  145. package/dist/node_modules/@pencil-agent/tui/dist/components/select-list.js +157 -0
  146. package/dist/node_modules/@pencil-agent/tui/dist/components/settings-list.d.ts +55 -0
  147. package/dist/node_modules/@pencil-agent/tui/dist/components/settings-list.js +190 -0
  148. package/dist/node_modules/@pencil-agent/tui/dist/components/spacer.d.ts +17 -0
  149. package/dist/node_modules/@pencil-agent/tui/dist/components/spacer.js +28 -0
  150. package/dist/node_modules/@pencil-agent/tui/dist/components/text.d.ts +24 -0
  151. package/dist/node_modules/@pencil-agent/tui/dist/components/text.js +94 -0
  152. package/dist/node_modules/@pencil-agent/tui/dist/components/truncated-text.d.ts +18 -0
  153. package/dist/node_modules/@pencil-agent/tui/dist/components/truncated-text.js +56 -0
  154. package/dist/node_modules/@pencil-agent/tui/dist/editor-component.d.ts +51 -0
  155. package/dist/node_modules/@pencil-agent/tui/dist/editor-component.js +7 -0
  156. package/dist/node_modules/@pencil-agent/tui/dist/fuzzy.d.ts +32 -0
  157. package/dist/node_modules/@pencil-agent/tui/dist/fuzzy.js +152 -0
  158. package/dist/node_modules/@pencil-agent/tui/dist/index.d.ts +28 -0
  159. package/dist/node_modules/@pencil-agent/tui/dist/index.js +37 -0
  160. package/dist/node_modules/@pencil-agent/tui/dist/keybindings.d.ts +44 -0
  161. package/dist/node_modules/@pencil-agent/tui/dist/keybindings.js +119 -0
  162. package/dist/node_modules/@pencil-agent/tui/dist/keys.d.ts +149 -0
  163. package/dist/node_modules/@pencil-agent/tui/dist/keys.js +948 -0
  164. package/dist/node_modules/@pencil-agent/tui/dist/kill-ring.d.ts +33 -0
  165. package/dist/node_modules/@pencil-agent/tui/dist/kill-ring.js +49 -0
  166. package/dist/node_modules/@pencil-agent/tui/dist/stdin-buffer.d.ts +38 -0
  167. package/dist/node_modules/@pencil-agent/tui/dist/stdin-buffer.js +307 -0
  168. package/dist/node_modules/@pencil-agent/tui/dist/terminal-image.d.ts +73 -0
  169. package/dist/node_modules/@pencil-agent/tui/dist/terminal-image.js +287 -0
  170. package/dist/node_modules/@pencil-agent/tui/dist/terminal.d.ts +86 -0
  171. package/dist/node_modules/@pencil-agent/tui/dist/terminal.js +266 -0
  172. package/dist/node_modules/@pencil-agent/tui/dist/tui.d.ts +219 -0
  173. package/dist/node_modules/@pencil-agent/tui/dist/tui.js +1001 -0
  174. package/dist/node_modules/@pencil-agent/tui/dist/undo-stack.d.ts +22 -0
  175. package/dist/node_modules/@pencil-agent/tui/dist/undo-stack.js +30 -0
  176. package/dist/node_modules/@pencil-agent/tui/dist/utils.d.ts +83 -0
  177. package/dist/node_modules/@pencil-agent/tui/dist/utils.js +811 -0
  178. package/dist/node_modules/@pencil-agent/tui/package.json +37 -0
  179. package/package.json +3 -2
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "2.0.0-beta.2",
3
- "commitHash": "4afe936",
2
+ "version": "2.0.0-beta.4",
3
+ "commitHash": "9c42bd0",
4
4
  "branch": "refactor/arch-candidate-d",
5
- "builtAt": "2026-06-05T15:33:54.463Z"
5
+ "builtAt": "2026-06-05T16:25:13.633Z"
6
6
  }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * [WHO]: Provides output-token recovery and token-budget continuation helpers for agent loops.
3
+ * [FROM]: Depends on @pencil-agent/ai message types and AgentLoopConfig budget settings.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-continuations.ts within agent-core; shared loop continuation policy.
6
+ */
7
+ import type { AssistantMessage, UserMessage } from "@pencil-agent/ai/types";
8
+ import type { AgentLoopConfig } from "./types.js";
9
+ export declare const DEFAULT_OUTPUT_TOKEN_BUDGET_THRESHOLD_PCT = 0.9;
10
+ export declare const DEFAULT_OUTPUT_TOKEN_BUDGET_CONTINUATIONS = 3;
11
+ export declare function computeRecoveryMaxTokens(config: AgentLoopConfig, message: AssistantMessage): number | undefined;
12
+ export declare function createOutputTokenRecoveryMessage(attempt: number): UserMessage;
13
+ export declare function createTokenBudgetContinuation(config: AgentLoopConfig, outputTokens: number, continuationCount: number): {
14
+ message: UserMessage;
15
+ outputTokens: number;
16
+ targetTokens: number;
17
+ } | undefined;
@@ -0,0 +1,60 @@
1
+ /**
2
+ * [WHO]: Provides output-token recovery and token-budget continuation helpers for agent loops.
3
+ * [FROM]: Depends on @pencil-agent/ai message types and AgentLoopConfig budget settings.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-continuations.ts within agent-core; shared loop continuation policy.
6
+ */
7
+ export const DEFAULT_OUTPUT_TOKEN_BUDGET_THRESHOLD_PCT = 0.9;
8
+ export const DEFAULT_OUTPUT_TOKEN_BUDGET_CONTINUATIONS = 3;
9
+ export function computeRecoveryMaxTokens(config, message) {
10
+ const modelMaxTokens = Math.max(1, Math.floor(config.model.maxTokens || 1));
11
+ const configured = config.maxTokens !== undefined ? Math.max(1, Math.floor(config.maxTokens)) : undefined;
12
+ const observedOutput = Math.max(1, Math.floor(message.usage.output || 1));
13
+ const baseline = configured ?? observedOutput;
14
+ const expanded = Math.max(baseline + 1, Math.ceil(Math.max(baseline, observedOutput) * 1.5));
15
+ return Math.min(modelMaxTokens, expanded);
16
+ }
17
+ export function createOutputTokenRecoveryMessage(attempt) {
18
+ return {
19
+ role: "user",
20
+ content: [
21
+ {
22
+ type: "text",
23
+ text: `Continue the previous response from exactly where it stopped. This is automatic output-token recovery attempt ${attempt}.`,
24
+ },
25
+ ],
26
+ timestamp: Date.now(),
27
+ };
28
+ }
29
+ export function createTokenBudgetContinuation(config, outputTokens, continuationCount) {
30
+ const budget = config.outputTokenBudget;
31
+ if (!budget)
32
+ return undefined;
33
+ const targetTokens = Math.max(1, Math.floor(budget.targetTokens));
34
+ const thresholdPct = clamp(budget.thresholdPct ?? DEFAULT_OUTPUT_TOKEN_BUDGET_THRESHOLD_PCT, 0, 1);
35
+ const maxContinuations = Math.max(0, Math.floor(budget.maxContinuations ?? DEFAULT_OUTPUT_TOKEN_BUDGET_CONTINUATIONS));
36
+ if (maxContinuations <= continuationCount)
37
+ return undefined;
38
+ const normalizedOutputTokens = Math.max(0, Math.floor(outputTokens));
39
+ const requiredTokens = Math.ceil(targetTokens * thresholdPct);
40
+ if (normalizedOutputTokens >= requiredTokens)
41
+ return undefined;
42
+ const message = {
43
+ role: "user",
44
+ content: [
45
+ {
46
+ type: "text",
47
+ text: `Continue because the output token budget is underused ` +
48
+ `(${normalizedOutputTokens}/${targetTokens} tokens). Add the missing useful detail directly; ` +
49
+ `do not recap or apologize.`,
50
+ },
51
+ ],
52
+ timestamp: Date.now(),
53
+ };
54
+ return { message, outputTokens: normalizedOutputTokens, targetTokens };
55
+ }
56
+ function clamp(value, min, max) {
57
+ if (!Number.isFinite(value))
58
+ return min;
59
+ return Math.min(max, Math.max(min, value));
60
+ }
@@ -0,0 +1,19 @@
1
+ /**
2
+ * [WHO]: Provides waitForAbortableOperation(), waitForAssistantStream(), waitForAssistantStreamEvent()
3
+ * [FROM]: Depends on @pencil-agent/ai AssistantMessageEvent/AssistantMessageEventStream contracts.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-stream-events.ts within agent-core; shared abortable operation and assistant-stream iterator utilities.
6
+ */
7
+ import type { AssistantMessageEvent } from "@pencil-agent/ai/types";
8
+ import type { AssistantMessageEventStream } from "@pencil-agent/ai/events";
9
+ export type AssistantStreamNext = IteratorResult<AssistantMessageEvent> | "aborted";
10
+ export type AssistantStreamStart = AssistantMessageEventStream | "aborted";
11
+ export type AbortableOperationResult<T> = {
12
+ type: "resolved";
13
+ value: T;
14
+ } | {
15
+ type: "aborted";
16
+ };
17
+ export declare function waitForAbortableOperation<T>(valueOrPromise: T | Promise<T>, signal?: AbortSignal): Promise<AbortableOperationResult<T>>;
18
+ export declare function waitForAssistantStream(streamOrPromise: AssistantMessageEventStream | Promise<AssistantMessageEventStream>, signal?: AbortSignal): Promise<AssistantStreamStart>;
19
+ export declare function waitForAssistantStreamEvent(iterator: AsyncIterator<AssistantMessageEvent>, signal?: AbortSignal): Promise<AssistantStreamNext>;
@@ -0,0 +1,55 @@
1
+ /**
2
+ * [WHO]: Provides waitForAbortableOperation(), waitForAssistantStream(), waitForAssistantStreamEvent()
3
+ * [FROM]: Depends on @pencil-agent/ai AssistantMessageEvent/AssistantMessageEventStream contracts.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-stream-events.ts within agent-core; shared abortable operation and assistant-stream iterator utilities.
6
+ */
7
+ export function waitForAbortableOperation(valueOrPromise, signal) {
8
+ if (signal?.aborted)
9
+ return Promise.resolve({ type: "aborted" });
10
+ return new Promise((resolve, reject) => {
11
+ const cleanup = () => {
12
+ signal?.removeEventListener("abort", onAbort);
13
+ };
14
+ const onAbort = () => {
15
+ cleanup();
16
+ resolve({ type: "aborted" });
17
+ };
18
+ signal?.addEventListener("abort", onAbort, { once: true });
19
+ Promise.resolve(valueOrPromise).then((value) => {
20
+ cleanup();
21
+ resolve({ type: "resolved", value });
22
+ }, (error) => {
23
+ cleanup();
24
+ reject(error);
25
+ });
26
+ });
27
+ }
28
+ export function waitForAssistantStream(streamOrPromise, signal) {
29
+ return waitForAbortableOperation(streamOrPromise, signal).then((result) => {
30
+ if (result.type === "aborted")
31
+ return "aborted";
32
+ return result.value;
33
+ });
34
+ }
35
+ export function waitForAssistantStreamEvent(iterator, signal) {
36
+ if (signal?.aborted)
37
+ return Promise.resolve("aborted");
38
+ return new Promise((resolve, reject) => {
39
+ const cleanup = () => {
40
+ signal?.removeEventListener("abort", onAbort);
41
+ };
42
+ const onAbort = () => {
43
+ cleanup();
44
+ resolve("aborted");
45
+ };
46
+ signal?.addEventListener("abort", onAbort, { once: true });
47
+ iterator.next().then((result) => {
48
+ cleanup();
49
+ resolve(result);
50
+ }, (error) => {
51
+ cleanup();
52
+ reject(error);
53
+ });
54
+ });
55
+ }
@@ -0,0 +1,10 @@
1
+ /**
2
+ * [WHO]: Provides enforceToolResultBatchSize(), createInterruptedToolResults(), and createSkippedToolCallLimitResults() for bounded and complete tool-result batches.
3
+ * [FROM]: Depends on @pencil-agent/ai AssistantMessage/ToolResultMessage/TextContent shapes.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops before appending tool results.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-tool-results.ts within agent-core; shared tool-result budget policy.
6
+ */
7
+ import type { AssistantMessage, ToolResultMessage } from "@pencil-agent/ai/types";
8
+ export declare function enforceToolResultBatchSize(toolResults: ToolResultMessage[], maxChars: number | undefined): ToolResultMessage[];
9
+ export declare function createInterruptedToolResults(assistantMessage: AssistantMessage, existingToolResultIds?: ReadonlySet<string>): ToolResultMessage[];
10
+ export declare function createSkippedToolCallLimitResults(assistantMessage: AssistantMessage, reasonText: string): ToolResultMessage[];
@@ -0,0 +1,137 @@
1
+ /**
2
+ * [WHO]: Provides enforceToolResultBatchSize(), createInterruptedToolResults(), and createSkippedToolCallLimitResults() for bounded and complete tool-result batches.
3
+ * [FROM]: Depends on @pencil-agent/ai AssistantMessage/ToolResultMessage/TextContent shapes.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops before appending tool results.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-tool-results.ts within agent-core; shared tool-result budget policy.
6
+ */
7
+ export function enforceToolResultBatchSize(toolResults, maxChars) {
8
+ if (!maxChars || maxChars <= 0 || toolResults.length === 0) {
9
+ return toolResults;
10
+ }
11
+ const limit = Math.floor(maxChars);
12
+ let currentTotal = sumToolResultTextChars(toolResults);
13
+ if (currentTotal <= limit) {
14
+ return toolResults;
15
+ }
16
+ const next = [...toolResults];
17
+ const ranked = toolResults
18
+ .map((result, index) => ({
19
+ index,
20
+ size: sumTextContentChars(result.content),
21
+ isError: result.isError,
22
+ }))
23
+ .filter((candidate) => candidate.size > 0)
24
+ .sort((a, b) => {
25
+ if (a.isError !== b.isError)
26
+ return a.isError ? 1 : -1;
27
+ return b.size - a.size || a.index - b.index;
28
+ });
29
+ for (const candidate of ranked) {
30
+ if (currentTotal <= limit)
31
+ break;
32
+ const reductionNeeded = currentTotal - limit;
33
+ const targetSize = Math.max(0, candidate.size - reductionNeeded);
34
+ const truncated = truncateToolResultToTextChars(next[candidate.index], targetSize, limit);
35
+ next[candidate.index] = truncated.result;
36
+ currentTotal = currentTotal - candidate.size + truncated.textChars;
37
+ }
38
+ return next;
39
+ }
40
+ export function createInterruptedToolResults(assistantMessage, existingToolResultIds = new Set()) {
41
+ const toolCalls = assistantMessage.content.filter((part) => part.type === "toolCall");
42
+ if (toolCalls.length === 0) {
43
+ return [];
44
+ }
45
+ const stopReason = assistantMessage.stopReason;
46
+ const reasonText = stopReason === "aborted"
47
+ ? "Tool call interrupted because the assistant response was aborted."
48
+ : "Tool call interrupted because the assistant response ended with an error.";
49
+ return toolCalls
50
+ .filter((toolCall) => !existingToolResultIds.has(toolCall.id))
51
+ .map((toolCall) => ({
52
+ role: "toolResult",
53
+ toolCallId: toolCall.id,
54
+ toolName: toolCall.name,
55
+ content: [{ type: "text", text: reasonText }],
56
+ details: {
57
+ errorType: "interrupted_tool_call",
58
+ stopReason,
59
+ errorMessage: assistantMessage.errorMessage,
60
+ },
61
+ isError: true,
62
+ timestamp: Date.now(),
63
+ }));
64
+ }
65
+ export function createSkippedToolCallLimitResults(assistantMessage, reasonText) {
66
+ const toolCalls = assistantMessage.content.filter((part) => part.type === "toolCall");
67
+ return toolCalls.map((toolCall) => ({
68
+ role: "toolResult",
69
+ toolCallId: toolCall.id,
70
+ toolName: toolCall.name,
71
+ content: [{ type: "text", text: reasonText }],
72
+ details: {
73
+ errorType: "tool_call_limit_reached",
74
+ toolName: toolCall.name,
75
+ toolCallId: toolCall.id,
76
+ },
77
+ isError: true,
78
+ timestamp: Date.now(),
79
+ }));
80
+ }
81
+ function truncateToolResultToTextChars(result, targetChars, maxToolResultBatchSizeChars) {
82
+ const originalTextChars = sumTextContentChars(result.content);
83
+ if (originalTextChars <= targetChars) {
84
+ return { result, textChars: originalTextChars };
85
+ }
86
+ const note = `[Tool result truncated by batch budget: original ${originalTextChars} chars.]`;
87
+ let nextText = "";
88
+ if (targetChars > 0) {
89
+ if (targetChars <= note.length) {
90
+ nextText = note.slice(0, targetChars);
91
+ }
92
+ else {
93
+ const suffix = `\n\n${note}`;
94
+ const bodyBudget = Math.max(0, targetChars - suffix.length);
95
+ nextText = `${flattenTextContent(result.content).slice(0, bodyBudget)}${suffix}`;
96
+ }
97
+ }
98
+ let hasWrittenText = false;
99
+ const content = result.content.map((part) => {
100
+ if (part.type !== "text")
101
+ return part;
102
+ if (hasWrittenText) {
103
+ return { ...part, text: "" };
104
+ }
105
+ hasWrittenText = true;
106
+ return { ...part, text: nextText };
107
+ });
108
+ if (!hasWrittenText) {
109
+ content.push({ type: "text", text: nextText });
110
+ }
111
+ return {
112
+ result: {
113
+ ...result,
114
+ content,
115
+ details: {
116
+ ...(typeof result.details === "object" && result.details !== null ? result.details : {}),
117
+ truncationReason: "tool_result_batch_budget",
118
+ originalTextChars,
119
+ retainedTextChars: nextText.length,
120
+ maxToolResultBatchSizeChars,
121
+ },
122
+ },
123
+ textChars: nextText.length,
124
+ };
125
+ }
126
+ function sumToolResultTextChars(toolResults) {
127
+ return toolResults.reduce((total, result) => total + sumTextContentChars(result.content), 0);
128
+ }
129
+ function sumTextContentChars(content) {
130
+ return content.reduce((total, part) => total + (part.type === "text" ? part.text.length : 0), 0);
131
+ }
132
+ function flattenTextContent(content) {
133
+ return content
134
+ .filter((part) => part.type === "text")
135
+ .map((part) => part.text)
136
+ .join("");
137
+ }
@@ -0,0 +1,22 @@
1
+ /**
2
+ * [WHO]: Provides PendingToolUseSummary, flushReadyToolUseSummaries(), and startToolUseSummary().
3
+ * [FROM]: Depends on AgentLoopConfig/AgentMessage contracts and tool result message shapes.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops for non-blocking tool summaries.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-tool-summaries.ts within agent-core; shared tool summary policy.
6
+ */
7
+ import type { ToolResultMessage } from "@pencil-agent/ai/types";
8
+ import type { EventStream } from "@pencil-agent/ai/events";
9
+ import type { AgentEvent, AgentLoopConfig, AgentMessage } from "./types.js";
10
+ export type PendingToolUseSummary = {
11
+ read(): {
12
+ settled: boolean;
13
+ value?: AgentMessage;
14
+ };
15
+ };
16
+ export declare function flushReadyToolUseSummaries(pendingSummaries: PendingToolUseSummary[], currentMessages: AgentMessage[], newMessages: AgentMessage[], stream: EventStream<AgentEvent, AgentMessage[]>): PendingToolUseSummary[];
17
+ export declare function startToolUseSummary(config: AgentLoopConfig, event: {
18
+ assistantMessage: AgentMessage;
19
+ toolResults: ToolResultMessage[];
20
+ contextMessages: AgentMessage[];
21
+ messages: AgentMessage[];
22
+ }): PendingToolUseSummary | undefined;
@@ -0,0 +1,64 @@
1
+ /**
2
+ * [WHO]: Provides PendingToolUseSummary, flushReadyToolUseSummaries(), and startToolUseSummary().
3
+ * [FROM]: Depends on AgentLoopConfig/AgentMessage contracts and tool result message shapes.
4
+ * [TO]: Consumed by standard and structured-adaptive agent loops for non-blocking tool summaries.
5
+ * [HERE]: core/lib/agent-core/src/agent-loop-tool-summaries.ts within agent-core; shared tool summary policy.
6
+ */
7
+ export function flushReadyToolUseSummaries(pendingSummaries, currentMessages, newMessages, stream) {
8
+ if (pendingSummaries.length === 0) {
9
+ return pendingSummaries;
10
+ }
11
+ const pending = [];
12
+ for (const summary of pendingSummaries) {
13
+ const result = summary.read();
14
+ if (!result.settled) {
15
+ pending.push(summary);
16
+ continue;
17
+ }
18
+ if (!result.value) {
19
+ continue;
20
+ }
21
+ currentMessages.push(result.value);
22
+ newMessages.push(result.value);
23
+ stream.push({ type: "message_start", message: result.value });
24
+ stream.push({ type: "message_end", message: result.value });
25
+ }
26
+ return pending;
27
+ }
28
+ export function startToolUseSummary(config, event) {
29
+ if (!config.createToolUseSummary) {
30
+ return undefined;
31
+ }
32
+ try {
33
+ const value = config.createToolUseSummary({
34
+ ...event,
35
+ messages: [...event.messages],
36
+ });
37
+ return trackToolUseSummary(value);
38
+ }
39
+ catch {
40
+ return undefined;
41
+ }
42
+ }
43
+ function trackToolUseSummary(value) {
44
+ if (!value) {
45
+ return undefined;
46
+ }
47
+ if (typeof value.then !== "function") {
48
+ return {
49
+ read: () => ({ settled: true, value: value }),
50
+ };
51
+ }
52
+ let settled = false;
53
+ let settledValue;
54
+ value.then((summary) => {
55
+ settled = true;
56
+ settledValue = summary;
57
+ }, () => {
58
+ settled = true;
59
+ settledValue = undefined;
60
+ });
61
+ return {
62
+ read: () => ({ settled, value: settledValue }),
63
+ };
64
+ }
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Agent loop that works with AgentMessage throughout.
3
+ * Transforms to Message[] only at the LLM call boundary.
4
+ */
5
+ /**
6
+ * [WHO]: Provides agentLoop(), agentLoopContinue(), standard loop event emission, continuation recovery, recovered-error tombstoning, and serial tool execution.
7
+ * [FROM]: Depends on @pencil-agent/ai streams/messages, ./types contracts, ./errors, and shared loop helpers.
8
+ * [TO]: Consumed by agent.ts and package exports as the default agent execution loop.
9
+ * [HERE]: core/lib/agent-core/src/agent-loop.ts within agent-core; standard counterpart to structured-adaptive-agent-loop.ts.
10
+ */
11
+ import { EventStream } from "@pencil-agent/ai/events";
12
+ import type { AgentContext, AgentEvent, AgentLoopConfig, AgentMessage, StreamFn } from "./types.js";
13
+ /**
14
+ * Start an agent loop with a new prompt message.
15
+ * The prompt is added to the context and events are emitted for it.
16
+ */
17
+ export declare function agentLoop(prompts: AgentMessage[], context: AgentContext, config: AgentLoopConfig, signal?: AbortSignal, streamFn?: StreamFn): EventStream<AgentEvent, AgentMessage[]>;
18
+ /**
19
+ * Continue an agent loop from the current context without adding a new message.
20
+ * Used for retries - context already has user message or tool results.
21
+ *
22
+ * **Important:** The last message in context must convert to a `user` or `toolResult` message
23
+ * via `convertToLlm`. If it doesn't, the LLM provider will reject the request.
24
+ * This cannot be validated here since `convertToLlm` is only called once per turn.
25
+ */
26
+ export declare function agentLoopContinue(context: AgentContext, config: AgentLoopConfig, signal?: AbortSignal, streamFn?: StreamFn): EventStream<AgentEvent, AgentMessage[]>;