@pencil-agent/nano-pencil 1.13.10 → 1.13.12

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 (228) hide show
  1. package/README.md +1 -1
  2. package/dist/build-meta.json +3 -3
  3. package/dist/builtin-extensions.js +10 -0
  4. package/dist/core/extensions/runner.d.ts +1 -0
  5. package/dist/core/extensions/runner.js +5 -0
  6. package/dist/core/extensions/types.d.ts +10 -0
  7. package/dist/core/model-resolver.js +2 -0
  8. package/dist/core/runtime/agent-session.d.ts +1 -0
  9. package/dist/core/runtime/agent-session.js +68 -4
  10. package/dist/core/tools/bash.d.ts +2 -0
  11. package/dist/core/tools/bash.js +118 -1
  12. package/dist/core/tools/edit.d.ts +2 -0
  13. package/dist/core/tools/edit.js +1 -0
  14. package/dist/core/tools/index.d.ts +6 -0
  15. package/dist/core/tools/index.js +4 -4
  16. package/dist/core/tools/write.d.ts +2 -0
  17. package/dist/core/tools/write.js +1 -0
  18. package/dist/core/utils/sleep.d.ts +1 -1
  19. package/dist/core/utils/sleep.js +8 -4
  20. package/dist/extensions/defaults/AGENT.md +19 -5
  21. package/dist/extensions/defaults/browser/AGENT.md +17 -0
  22. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/amazon/product-search.md +198 -0
  23. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/archive-org/scraping.md +341 -0
  24. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/arxiv/scraping.md +311 -0
  25. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/arxiv-bulk/scraping.md +333 -0
  26. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/atlas/overview.md +70 -0
  27. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/booking-com/scraping.md +578 -0
  28. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/capterra/scraping.md +440 -0
  29. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/centilebrain/generate-estimates.md +110 -0
  30. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/coingecko/scraping.md +325 -0
  31. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/coinmarketcap/scraping.md +463 -0
  32. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/coursera/scraping.md +360 -0
  33. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/craigslist/scraping.md +390 -0
  34. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/crossref/scraping.md +568 -0
  35. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/dev-to/scraping.md +323 -0
  36. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/duckduckgo/scraping.md +349 -0
  37. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/ebay/scraping.md +435 -0
  38. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/etsy/scraping.md +506 -0
  39. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/eventbrite/scraping.md +363 -0
  40. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/expedia/automation.md +168 -0
  41. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/facebook/groups.md +236 -0
  42. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/facebook/pages.md +295 -0
  43. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/framer/editor.md +108 -0
  44. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/fred/scraping.md +493 -0
  45. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/g2/scraping.md +580 -0
  46. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/genius/scraping.md +511 -0
  47. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/github/repo-actions.md +65 -0
  48. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/github/scraping.md +184 -0
  49. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/glassdoor/scraping.md +543 -0
  50. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/gmail/compose.md +122 -0
  51. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/goodreads/scraping.md +461 -0
  52. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/gutenberg/scraping.md +383 -0
  53. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/hackernews/scraping.md +243 -0
  54. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/howlongtobeat/scraping.md +473 -0
  55. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/imdb/scraping.md +271 -0
  56. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/itch-io/scraping.md +436 -0
  57. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/job-boards/indeed-glassdoor.md +1021 -0
  58. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/letterboxd/scraping.md +349 -0
  59. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/linkedin/invitation-manager.md +109 -0
  60. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/loom/folder-enumeration.md +170 -0
  61. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/macrotrends/scraping.md +537 -0
  62. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/medium/article-hydration.md +120 -0
  63. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/medium/scraping.md +414 -0
  64. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/metacritic/scraping.md +477 -0
  65. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/musicbrainz/scraping.md +478 -0
  66. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/nasa/scraping.md +339 -0
  67. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/news-aggregation/multi-source.md +205 -0
  68. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/open-library/scraping.md +472 -0
  69. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/openalex/scraping.md +470 -0
  70. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/openstreetmap/scraping.md +490 -0
  71. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/package-registries/npm-pypi.md +478 -0
  72. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/polymarket/scraping.md +234 -0
  73. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/producthunt/scraping.md +307 -0
  74. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/pubmed/scraping.md +421 -0
  75. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/quora/scraping.md +364 -0
  76. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/rawg/scraping.md +352 -0
  77. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/reddit/scraping.md +124 -0
  78. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/rest-countries/scraping.md +233 -0
  79. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/sec-edgar/scraping.md +361 -0
  80. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/shopify-admin/README.md +36 -0
  81. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/shopify-admin/embedded-apps.md +72 -0
  82. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/shopify-admin/knowledge-base.md +109 -0
  83. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/shopify-admin/polaris-inputs.md +137 -0
  84. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/soundcloud/scraping.md +362 -0
  85. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/spotify/scraping.md +339 -0
  86. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/stackoverflow/scraping.md +435 -0
  87. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/steam/scraping.md +575 -0
  88. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/substack/scraping.md +338 -0
  89. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/thetechgeeks/pricing.md +52 -0
  90. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/tiktok/upload.md +107 -0
  91. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/tradingview/scraping.md +309 -0
  92. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/trello/boards-and-lists.md +88 -0
  93. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/trustpilot/scraping.md +375 -0
  94. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/walmart/scraping.md +444 -0
  95. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/wayback-machine/scraping.md +306 -0
  96. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/weather/scraping.md +398 -0
  97. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/wellfound/scraping.md +596 -0
  98. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/world-bank/scraping.md +356 -0
  99. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/xiaohongshu/scraping.md +84 -0
  100. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/youtube/scraping.md +418 -0
  101. package/dist/extensions/defaults/browser/agent-workspace/domain-skills/zillow/scraping.md +433 -0
  102. package/dist/extensions/defaults/browser/browser.md +73 -0
  103. package/dist/extensions/defaults/browser/index.d.ts +8 -0
  104. package/dist/extensions/defaults/browser/index.js +395 -0
  105. package/dist/extensions/defaults/browser/install.md +142 -0
  106. package/dist/extensions/defaults/browser/interaction-skills/connection.md +48 -0
  107. package/dist/extensions/defaults/browser/interaction-skills/cookies.md +3 -0
  108. package/dist/extensions/defaults/browser/interaction-skills/cross-origin-iframes.md +3 -0
  109. package/dist/extensions/defaults/browser/interaction-skills/dialogs.md +64 -0
  110. package/dist/extensions/defaults/browser/interaction-skills/downloads.md +3 -0
  111. package/dist/extensions/defaults/browser/interaction-skills/drag-and-drop.md +3 -0
  112. package/dist/extensions/defaults/browser/interaction-skills/dropdowns.md +3 -0
  113. package/dist/extensions/defaults/browser/interaction-skills/iframes.md +3 -0
  114. package/dist/extensions/defaults/browser/interaction-skills/network-requests.md +3 -0
  115. package/dist/extensions/defaults/browser/interaction-skills/print-as-pdf.md +3 -0
  116. package/dist/extensions/defaults/browser/interaction-skills/profile-sync.md +90 -0
  117. package/dist/extensions/defaults/browser/interaction-skills/screenshots.md +17 -0
  118. package/dist/extensions/defaults/browser/interaction-skills/scrolling.md +3 -0
  119. package/dist/extensions/defaults/browser/interaction-skills/shadow-dom.md +3 -0
  120. package/dist/extensions/defaults/browser/interaction-skills/tabs.md +69 -0
  121. package/dist/extensions/defaults/browser/interaction-skills/uploads.md +1 -0
  122. package/dist/extensions/defaults/browser/interaction-skills/viewport.md +3 -0
  123. package/dist/extensions/defaults/browser/src/browser_harness/AGENT.md +15 -0
  124. package/dist/extensions/defaults/diagnostics/diagnostic-buffer.js +18 -4
  125. package/dist/extensions/defaults/diagnostics/index.d.ts +1 -1
  126. package/dist/extensions/defaults/diagnostics/index.js +30 -23
  127. package/dist/extensions/defaults/diagnostics/types.d.ts +1 -0
  128. package/dist/extensions/defaults/interview/index.js +486 -118
  129. package/dist/extensions/defaults/link-world/agent-workspace/README.md +16 -0
  130. package/dist/extensions/defaults/link-world/index.d.ts +3 -7
  131. package/dist/extensions/defaults/link-world/index.js +373 -39
  132. package/dist/extensions/defaults/link-world/link-world-agent.md +82 -0
  133. package/dist/extensions/defaults/link-world/network-routing.md +67 -0
  134. package/dist/extensions/defaults/team/AGENT.md +26 -8
  135. package/dist/extensions/defaults/team/TESTING.md +52 -0
  136. package/dist/extensions/defaults/team/index.d.ts +3 -0
  137. package/dist/extensions/defaults/team/index.js +232 -30
  138. package/dist/extensions/defaults/team/team-dashboard.js +50 -17
  139. package/dist/extensions/defaults/team/team-mailbox.d.ts +13 -9
  140. package/dist/extensions/defaults/team/team-mailbox.js +55 -9
  141. package/dist/extensions/defaults/team/team-parser.d.ts +16 -1
  142. package/dist/extensions/defaults/team/team-parser.js +73 -0
  143. package/dist/extensions/defaults/team/team-runtime.d.ts +17 -1
  144. package/dist/extensions/defaults/team/team-runtime.js +377 -164
  145. package/dist/extensions/defaults/team/team-task-store.d.ts +35 -0
  146. package/dist/extensions/defaults/team/team-task-store.js +93 -0
  147. package/dist/extensions/defaults/team/team-types.d.ts +16 -0
  148. package/dist/main.js +81 -11
  149. package/dist/modes/interactive/interactive-mode.d.ts +2 -0
  150. package/dist/modes/interactive/interactive-mode.js +80 -15
  151. package/dist/nanopencil-defaults.d.ts +84 -1
  152. package/dist/nanopencil-defaults.js +171 -4
  153. package/dist/node_modules/@pencil-agent/agent-core/agent-loop.js +83 -10
  154. package/dist/node_modules/@pencil-agent/agent-core/agent.js +2 -0
  155. package/dist/node_modules/@pencil-agent/agent-core/types.d.ts +15 -0
  156. package/dist/node_modules/@pencil-agent/ai/env-api-keys.js +2 -0
  157. package/dist/node_modules/@pencil-agent/ai/models.generated.d.ts +529 -77
  158. package/dist/node_modules/@pencil-agent/ai/models.generated.js +554 -120
  159. package/dist/node_modules/@pencil-agent/ai/providers/amazon-bedrock.js +5 -1
  160. package/dist/node_modules/@pencil-agent/ai/providers/anthropic.js +4 -1
  161. package/dist/node_modules/@pencil-agent/ai/providers/azure-openai-responses.d.ts +1 -0
  162. package/dist/node_modules/@pencil-agent/ai/providers/azure-openai-responses.js +4 -0
  163. package/dist/node_modules/@pencil-agent/ai/providers/google-gemini-cli.js +4 -0
  164. package/dist/node_modules/@pencil-agent/ai/providers/google-vertex.js +4 -0
  165. package/dist/node_modules/@pencil-agent/ai/providers/google.js +4 -1
  166. package/dist/node_modules/@pencil-agent/ai/providers/openai-responses.d.ts +1 -0
  167. package/dist/node_modules/@pencil-agent/ai/providers/openai-responses.js +4 -0
  168. package/dist/node_modules/@pencil-agent/ai/types.d.ts +3 -1
  169. package/dist/packages/mem-core/consolidation.d.ts +1 -1
  170. package/dist/packages/mem-core/consolidation.js +5 -2
  171. package/dist/packages/mem-core/diagnostics.d.ts +1 -1
  172. package/dist/packages/mem-core/diagnostics.js +3 -8
  173. package/dist/packages/mem-core/engine-insights.d.ts +1 -1
  174. package/dist/packages/mem-core/engine-insights.js +3 -6
  175. package/dist/packages/mem-core/engine.d.ts +1 -1
  176. package/dist/packages/mem-core/engine.js +3 -6
  177. package/dist/packages/mem-core/extension.js +85 -7
  178. package/dist/packages/mem-core/extraction.d.ts +1 -1
  179. package/dist/packages/mem-core/extraction.js +71 -15
  180. package/dist/packages/mem-core/full-insights.d.ts +1 -1
  181. package/dist/packages/mem-core/full-insights.js +3 -3
  182. package/dist/packages/mem-core/human-insights.d.ts +1 -1
  183. package/dist/packages/mem-core/human-insights.js +3 -3
  184. package/dist/packages/mem-core/llm-json.d.ts +10 -0
  185. package/dist/packages/mem-core/llm-json.js +101 -0
  186. package/dist/packages/soul-core/diagnostics.d.ts +1 -1
  187. package/dist/packages/soul-core/diagnostics.js +3 -8
  188. package/dist/packages/soul-core/evolution.d.ts +5 -3
  189. package/dist/packages/soul-core/evolution.js +23 -5
  190. package/dist/packages/soul-core/manager.js +3 -2
  191. package/dist/packages/soul-core/src/diagnostics.d.ts +1 -1
  192. package/dist/packages/soul-core/src/diagnostics.js +3 -8
  193. package/dist/packages/soul-core/src/evolution.d.ts +5 -3
  194. package/dist/packages/soul-core/src/evolution.js +23 -5
  195. package/dist/packages/soul-core/src/manager.js +3 -2
  196. package/dist/packages/soul-core/src/store.js +63 -7
  197. package/dist/packages/soul-core/store.js +63 -7
  198. package/dist/utils/diagnostics.d.ts +4 -5
  199. package/dist/utils/diagnostics.js +6 -12
  200. package/dist/utils/startup-profiler.d.ts +59 -3
  201. package/dist/utils/startup-profiler.js +105 -3
  202. package/docs/eval/AGENT.md +36 -0
  203. package/docs/eval/README.md +72 -0
  204. package/docs/eval/decision-log-template.md +51 -0
  205. package/docs/eval/experiment-protocol.md +77 -0
  206. package/docs/eval/issue-usage/README.md +32 -0
  207. package/docs/eval/issue-usage/cases.md +31 -0
  208. package/docs/eval/issue-usage/metrics.md +23 -0
  209. package/docs/eval/issue-usage/workflow.md +39 -0
  210. package/docs/eval/sal-memory-anchor/README.md +32 -0
  211. package/docs/eval/sal-memory-anchor/hypothesis.md +45 -0
  212. package/docs/eval/sal-memory-anchor/metrics.md +24 -0
  213. package/docs/eval/sal-memory-anchor/runs.md +29 -0
  214. package/docs/eval/tool-usage-analysis/README.md +32 -0
  215. package/docs/eval/tool-usage-analysis/invalid-data-rules.md +29 -0
  216. package/docs/eval/tool-usage-analysis/metrics.md +35 -0
  217. package/docs/eval/tool-usage-analysis/report-template.md +49 -0
  218. package/docs/eval/tool-usage-analysis/sop.md +63 -0
  219. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/200/273/347/273/223.md" +251 -0
  220. package/docs/loop /351/207/215/346/236/204/345/256/214/346/210/220/346/212/245/345/221/212.md" +123 -0
  221. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210.md" +1222 -0
  222. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/256/236/347/216/260/346/212/245/345/221/212.md" +158 -0
  223. package/docs/loop /351/207/215/346/236/204/346/226/271/346/241/210/345/257/271/346/257/224/345/210/206/346/236/220.md" +128 -0
  224. package/docs/loop /351/207/215/346/236/204/350/256/241/345/210/222.md" +321 -0
  225. package/docs/loop-usage-examples.md +215 -0
  226. package/docs/planmode.md +1987 -0
  227. package/docs//346/226/207/346/241/243/344/270/255/345/277/203.md +10 -0
  228. package/package.json +5 -2
package/README.md CHANGED
@@ -104,7 +104,7 @@ Built-in tools include:
104
104
  ### 🌐 Multi-Model Support
105
105
  Use the best model for each task.
106
106
 
107
- - 🇨🇳 **Alibaba DashScope** — Qwen series (optimized for coding)
107
+ - 🇨🇳 **Alibaba DashScope / Token Plan** — Qwen, GLM, MiniMax, DeepSeek text models
108
108
  - 🤖 **OpenAI** — GPT-4, GPT-3.5
109
109
  - 💬 **Anthropic** — Claude 3 Opus/Sonnet/Haiku
110
110
  - 🔍 **Google** — Gemini Pro/Ultra
@@ -1,6 +1,6 @@
1
1
  {
2
- "version": "1.13.10",
3
- "commitHash": "027d681",
2
+ "version": "1.13.12",
3
+ "commitHash": "6398d50",
4
4
  "branch": "main",
5
- "builtAt": "2026-04-27T10:15:14.235Z"
5
+ "builtAt": "2026-05-02T10:48:42.017Z"
6
6
  }
@@ -14,6 +14,7 @@ const require = createRequire(import.meta.url);
14
14
  const BUNDLED_NANOMEM_EXTENSION_PACKAGES = join(__dirname, "packages", "mem-core", "extension.js");
15
15
  const BUNDLED_SIMPLIFY_EXTENSION = join(__dirname, "extensions", "optional", "simplify", "index.js");
16
16
  const BUNDLED_LINK_WORLD_EXTENSION = join(__dirname, "extensions", "defaults", "link-world", "index.js");
17
+ const BUNDLED_BROWSER_EXTENSION = join(__dirname, "extensions", "defaults", "browser", "index.js");
17
18
  const BUNDLED_SECURITY_AUDIT_EXTENSION = join(__dirname, "extensions", "defaults", "security-audit", "index.js");
18
19
  const BUNDLED_SOUL_EXTENSION = join(__dirname, "extensions", "defaults", "soul", "index.js");
19
20
  const BUNDLED_PRESENCE_EXTENSION = join(__dirname, "extensions", "defaults", "presence", "index.js");
@@ -142,6 +143,15 @@ export function getBuiltinExtensionPaths() {
142
143
  if (existsSync(linkWorldTs))
143
144
  paths.push(linkWorldTs);
144
145
  }
146
+ // === Browser Harness extension (built-in CDP browser automation) ===
147
+ if (existsSync(BUNDLED_BROWSER_EXTENSION)) {
148
+ paths.push(BUNDLED_BROWSER_EXTENSION);
149
+ }
150
+ else {
151
+ const browserTs = join(__dirname, "extensions", "defaults", "browser", "index.ts");
152
+ if (existsSync(browserTs))
153
+ paths.push(browserTs);
154
+ }
145
155
  // === Security Audit extension (built-in source, compiled to dist/extensions/defaults/security-audit) ===
146
156
  if (existsSync(BUNDLED_SECURITY_AUDIT_EXTENSION)) {
147
157
  paths.push(BUNDLED_SECURITY_AUDIT_EXTENSION);
@@ -69,6 +69,7 @@ export declare class ExtensionRunner {
69
69
  private errorListeners;
70
70
  private getModel;
71
71
  private completeSimpleFn;
72
+ private completeJsonFn;
72
73
  private isIdleFn;
73
74
  private waitForIdleFn;
74
75
  private abortFn;
@@ -87,6 +87,7 @@ export class ExtensionRunner {
87
87
  errorListeners = new Set();
88
88
  getModel = () => undefined;
89
89
  completeSimpleFn = async () => undefined;
90
+ completeJsonFn;
90
91
  isIdleFn = () => true;
91
92
  waitForIdleFn = async () => { };
92
93
  abortFn = () => { };
@@ -159,6 +160,7 @@ export class ExtensionRunner {
159
160
  // Context actions (required)
160
161
  this.getModel = contextActions.getModel;
161
162
  this.completeSimpleFn = contextActions.completeSimple;
163
+ this.completeJsonFn = contextActions.completeJson;
162
164
  this.isIdleFn = contextActions.isIdle;
163
165
  this.runtime.isIdle = () => this.isIdleFn();
164
166
  this.abortFn = contextActions.abort;
@@ -393,6 +395,9 @@ export class ExtensionRunner {
393
395
  return getModel();
394
396
  },
395
397
  completeSimple: (systemPrompt, userMessage) => this.completeSimpleFn(systemPrompt, userMessage),
398
+ completeJson: this.completeJsonFn
399
+ ? (systemPrompt, userMessage, schema, options) => this.completeJsonFn(systemPrompt, userMessage, schema, options)
400
+ : undefined,
396
401
  isIdle: () => this.isIdleFn(),
397
402
  abort: () => this.abortFn(),
398
403
  hasPendingMessages: () => this.hasPendingMessagesFn(),
@@ -190,6 +190,11 @@ export interface ExtensionContext {
190
190
  model: Model<any> | undefined;
191
191
  /** One-shot LLM completion with current model (e.g. for memory extraction). Undefined when no model or no API key. */
192
192
  completeSimple(systemPrompt: string, userMessage: string): Promise<string | undefined>;
193
+ /** One-shot structured JSON completion with current model. Uses provider tool-calling when available. */
194
+ completeJson?(systemPrompt: string, userMessage: string, schema: Record<string, unknown>, options?: {
195
+ toolName?: string;
196
+ resultKey?: string;
197
+ }): Promise<string | undefined>;
193
198
  /** Whether the agent is idle (not streaming) */
194
199
  isIdle(): boolean;
195
200
  /** Abort the current agent operation */
@@ -937,6 +942,11 @@ export interface ExtensionContextActions {
937
942
  getModel: () => Model<any> | undefined;
938
943
  /** One-shot completion with current model for extensions (e.g. memory extraction). Returns undefined if no model or no API key. */
939
944
  completeSimple: (systemPrompt: string, userMessage: string) => Promise<string | undefined>;
945
+ /** One-shot structured JSON completion with current model. Returns undefined if no model, no API key, or no structured payload. */
946
+ completeJson?: (systemPrompt: string, userMessage: string, schema: Record<string, unknown>, options?: {
947
+ toolName?: string;
948
+ resultKey?: string;
949
+ }) => Promise<string | undefined>;
940
950
  isIdle: () => boolean;
941
951
  abort: () => void;
942
952
  hasPendingMessages: () => boolean;
@@ -28,6 +28,8 @@ export const defaultModelPerProvider = {
28
28
  opencode: "claude-opus-4-6",
29
29
  "opencode-go": "claude-opus-4-6",
30
30
  "kimi-coding": "kimi-k2-thinking",
31
+ "ali-token-plan-openai": "qwen3.6-plus",
32
+ "ali-token-plan-anthropic": "qwen3.6-plus",
31
33
  };
32
34
  /**
33
35
  * Helper to check if a model ID looks like an alias (no date suffix)
@@ -151,6 +151,7 @@ export declare class AgentSession {
151
151
  readonly settingsManager: SettingsManager;
152
152
  private _scopedModels;
153
153
  private _unsubscribeAgent?;
154
+ private _detachExternalAbort?;
154
155
  private _eventListeners;
155
156
  /** Tracks pending steering messages for UI display. Removed when delivered. */
156
157
  private _steeringMessages;
@@ -10,6 +10,21 @@ import { completeSimple, isContextOverflow, modelsAreEqual, resetApiProviders, s
10
10
  import { getDocsPath } from "../../config.js";
11
11
  import { theme } from "../../modes/interactive/theme/theme.js";
12
12
  import { stripFrontmatter } from "../../utils/frontmatter.js";
13
+ function getStructuredToolChoice(model, toolName) {
14
+ switch (model.api) {
15
+ case "openai-completions":
16
+ return { type: "function", function: { name: toolName } };
17
+ case "anthropic-messages":
18
+ case "bedrock-converse-stream":
19
+ return { type: "tool", name: toolName };
20
+ case "google-generative-ai":
21
+ case "google-gemini-cli":
22
+ case "google-vertex":
23
+ return "any";
24
+ default:
25
+ return "required";
26
+ }
27
+ }
13
28
  /**
14
29
  * Custom error for model cycling with additional context.
15
30
  */
@@ -86,6 +101,7 @@ export class AgentSession {
86
101
  _scopedModels;
87
102
  // Event subscription state
88
103
  _unsubscribeAgent;
104
+ _detachExternalAbort;
89
105
  _eventListeners = [];
90
106
  /** Tracks pending steering messages for UI display. Removed when delivered. */
91
107
  _steeringMessages = [];
@@ -155,11 +171,16 @@ export class AgentSession {
155
171
  // Always subscribe to agent events for internal handling
156
172
  // (session persistence, extensions, auto-compaction, retry logic)
157
173
  this._unsubscribeAgent = this.agent.subscribe(this._handleAgentEvent);
158
- // Listen to external abort signal (e.g., from SubAgent runtime)
174
+ // Listen to external abort signal (e.g., from SubAgent runtime).
175
+ // Track the handler and remove it on dispose so a long-lived parent
176
+ // signal that spawns many short-lived AgentSessions does not accumulate
177
+ // listeners (Node fires MaxListenersExceededWarning at 11).
159
178
  if (config.signal) {
160
- config.signal.addEventListener("abort", () => {
161
- this.abort();
162
- });
179
+ const externalAbortHandler = () => { this.abort(); };
180
+ config.signal.addEventListener("abort", externalAbortHandler, { once: true });
181
+ this._detachExternalAbort = () => {
182
+ config.signal?.removeEventListener("abort", externalAbortHandler);
183
+ };
163
184
  }
164
185
  this._buildRuntime({
165
186
  activeToolNames: this._initialActiveToolNames,
@@ -558,6 +579,10 @@ export class AgentSession {
558
579
  this._disconnectFromAgent();
559
580
  this._extensionRunner?.dispose();
560
581
  this._eventListeners = [];
582
+ if (this._detachExternalAbort) {
583
+ this._detachExternalAbort();
584
+ this._detachExternalAbort = undefined;
585
+ }
561
586
  }
562
587
  // =========================================================================
563
588
  // Read-only State Access
@@ -1939,6 +1964,45 @@ export class AgentSession {
1939
1964
  return undefined;
1940
1965
  }
1941
1966
  },
1967
+ completeJson: async (systemPrompt, userMessage, schema, options) => {
1968
+ const model = this.model;
1969
+ if (!model)
1970
+ return undefined;
1971
+ const apiKey = await this.modelRegistry.getApiKey(model);
1972
+ if (!apiKey)
1973
+ return undefined;
1974
+ const toolName = options?.toolName || "submit_json";
1975
+ try {
1976
+ const response = await completeSimple(model, {
1977
+ systemPrompt: `${systemPrompt}\n\nYou must call the ${toolName} tool exactly once with the final structured JSON payload. Do not answer in prose.`,
1978
+ messages: [
1979
+ { role: "user", content: userMessage, timestamp: Date.now() },
1980
+ ],
1981
+ tools: [
1982
+ {
1983
+ name: toolName,
1984
+ description: "Submit the final structured JSON payload.",
1985
+ parameters: schema,
1986
+ },
1987
+ ],
1988
+ }, {
1989
+ maxTokens: 1500,
1990
+ temperature: 0,
1991
+ apiKey,
1992
+ toolChoice: getStructuredToolChoice(model, toolName),
1993
+ });
1994
+ const toolCall = response.content?.find((b) => b.type === "toolCall" && b.name === toolName);
1995
+ if (!toolCall)
1996
+ return undefined;
1997
+ const payload = options?.resultKey
1998
+ ? toolCall.arguments?.[options.resultKey]
1999
+ : toolCall.arguments;
2000
+ return JSON.stringify(payload);
2001
+ }
2002
+ catch {
2003
+ return undefined;
2004
+ }
2005
+ },
1942
2006
  getSettings: () => this.settingsManager.getSettings(),
1943
2007
  isIdle: () => !this.isStreaming,
1944
2008
  abort: () => this.abort(),
@@ -56,6 +56,8 @@ export interface BashSandboxOptions {
56
56
  additionalBlockedPatterns?: RegExp[];
57
57
  /** Custom error message for blocked commands */
58
58
  blockedMessage?: string;
59
+ /** Optional path allowlist hook for simple write commands. Defaults to denying all writes. */
60
+ allowWritePath?: (absolutePath: string) => boolean;
59
61
  }
60
62
  /**
61
63
  * Create a sandboxed bash hook that blocks dangerous write operations.
@@ -7,7 +7,7 @@
7
7
  import { randomBytes } from "node:crypto";
8
8
  import { createWriteStream, existsSync } from "node:fs";
9
9
  import { tmpdir } from "node:os";
10
- import { join } from "node:path";
10
+ import { isAbsolute, join, resolve } from "node:path";
11
11
  import { Type } from "@sinclair/typebox";
12
12
  import { spawn } from "child_process";
13
13
  import { getShellConfig, getShellEnv, killProcessTree } from "../utils/shell.js";
@@ -284,6 +284,23 @@ export function createSandboxHook(options) {
284
284
  const blockedMessage = options?.blockedMessage ?? "Write operations are not allowed in sandbox mode";
285
285
  return (context) => {
286
286
  const command = context.command.trim();
287
+ const writePaths = extractSimpleWritePaths(command, context.cwd);
288
+ if (writePaths === null) {
289
+ return {
290
+ ...context,
291
+ command: `echo "${blockedMessage}" >&2; exit 1`,
292
+ };
293
+ }
294
+ if (writePaths.length > 0) {
295
+ const allAllowed = writePaths.every((path) => options?.allowWritePath?.(path) === true);
296
+ if (!allAllowed) {
297
+ return {
298
+ ...context,
299
+ command: `echo "${blockedMessage}" >&2; exit 1`,
300
+ };
301
+ }
302
+ return context;
303
+ }
287
304
  // Check if command contains any blocked patterns
288
305
  for (const pattern of blockedPatterns) {
289
306
  if (pattern.test(command)) {
@@ -296,3 +313,103 @@ export function createSandboxHook(options) {
296
313
  return context;
297
314
  };
298
315
  }
316
+ function extractSimpleWritePaths(command, cwd) {
317
+ if (/[;&|`$()]/.test(command))
318
+ return null;
319
+ const tokens = tokenizeSimpleShell(command);
320
+ if (tokens.length === 0)
321
+ return [];
322
+ const paths = [];
323
+ for (let index = 0; index < tokens.length; index++) {
324
+ const token = tokens[index];
325
+ if (token === ">" || token === ">>" || /^&?\d?>&?\d?$/.test(token)) {
326
+ const next = tokens[index + 1];
327
+ if (!next)
328
+ return null;
329
+ paths.push(resolveSandboxPath(next, cwd));
330
+ index++;
331
+ continue;
332
+ }
333
+ const redirectMatch = /^(?:\d?>|>>)(.+)$/.exec(token);
334
+ if (redirectMatch?.[1]) {
335
+ paths.push(resolveSandboxPath(redirectMatch[1], cwd));
336
+ continue;
337
+ }
338
+ }
339
+ const cmd = tokens[0];
340
+ if (cmd === "mkdir") {
341
+ const targets = tokens.slice(1).filter((token) => !token.startsWith("-"));
342
+ if (targets.length === 0)
343
+ return null;
344
+ paths.push(...targets.map((target) => resolveSandboxPath(target, cwd)));
345
+ }
346
+ else if (cmd === "cp" || cmd === "mv") {
347
+ const operands = tokens.slice(1).filter((token) => !token.startsWith("-"));
348
+ if (operands.length < 2)
349
+ return null;
350
+ paths.push(resolveSandboxPath(operands[operands.length - 1], cwd));
351
+ }
352
+ else if (cmd === "rm") {
353
+ const targets = tokens.slice(1).filter((token) => !token.startsWith("-"));
354
+ if (targets.length === 0)
355
+ return null;
356
+ paths.push(...targets.map((target) => resolveSandboxPath(target, cwd)));
357
+ }
358
+ else if (cmd === "tee") {
359
+ const targets = tokens.slice(1).filter((token) => !token.startsWith("-"));
360
+ if (targets.length === 0)
361
+ return null;
362
+ paths.push(...targets.map((target) => resolveSandboxPath(target, cwd)));
363
+ }
364
+ else if (cmd === "touch") {
365
+ const targets = tokens.slice(1).filter((token) => !token.startsWith("-"));
366
+ if (targets.length === 0)
367
+ return null;
368
+ paths.push(...targets.map((target) => resolveSandboxPath(target, cwd)));
369
+ }
370
+ return paths;
371
+ }
372
+ function tokenizeSimpleShell(command) {
373
+ const tokens = [];
374
+ let current = "";
375
+ let quote;
376
+ let escaped = false;
377
+ for (const ch of command) {
378
+ if (escaped) {
379
+ current += ch;
380
+ escaped = false;
381
+ continue;
382
+ }
383
+ if (ch === "\\") {
384
+ escaped = true;
385
+ continue;
386
+ }
387
+ if (quote) {
388
+ if (ch === quote) {
389
+ quote = undefined;
390
+ }
391
+ else {
392
+ current += ch;
393
+ }
394
+ continue;
395
+ }
396
+ if (ch === "'" || ch === "\"") {
397
+ quote = ch;
398
+ continue;
399
+ }
400
+ if (/\s/.test(ch)) {
401
+ if (current) {
402
+ tokens.push(current);
403
+ current = "";
404
+ }
405
+ continue;
406
+ }
407
+ current += ch;
408
+ }
409
+ if (current)
410
+ tokens.push(current);
411
+ return tokens;
412
+ }
413
+ function resolveSandboxPath(path, cwd) {
414
+ return resolve(isAbsolute(path) ? path : join(cwd, path));
415
+ }
@@ -33,6 +33,8 @@ export interface EditOperations {
33
33
  export interface EditToolOptions {
34
34
  /** Custom operations for file editing. Default: local filesystem */
35
35
  operations?: EditOperations;
36
+ /** Optional guard called with the resolved absolute path before writing. */
37
+ beforeWrite?: (absolutePath: string) => void | Promise<void>;
36
38
  }
37
39
  export declare function createEditTool(cwd: string, options?: EditToolOptions): AgentTool<typeof editSchema>;
38
40
  /** Default edit tool using process.cwd() - for backwards compatibility */
@@ -22,6 +22,7 @@ export function createEditTool(cwd, options) {
22
22
  parameters: editSchema,
23
23
  execute: async (_toolCallId, { path, oldText, newText }, signal) => {
24
24
  const absolutePath = resolveToCwd(path, cwd);
25
+ await options?.beforeWrite?.(absolutePath);
25
26
  return new Promise((resolve, reject) => {
26
27
  // Check if already aborted
27
28
  if (signal?.aborted) {
@@ -15,7 +15,9 @@ export { DEFAULT_MAX_BYTES, DEFAULT_MAX_LINES, formatSize, type TruncationOption
15
15
  export { createWriteTool, type WriteOperations, type WriteToolInput, type WriteToolOptions, writeTool, } from "./write.js";
16
16
  import type { AgentTool } from "@pencil-agent/agent-core";
17
17
  import { type BashToolOptions } from "./bash.js";
18
+ import { type EditToolOptions } from "./edit.js";
18
19
  import { type ReadToolOptions } from "./read.js";
20
+ import { type WriteToolOptions } from "./write.js";
19
21
  /** Tool type (AgentTool from nanopencil-ai) */
20
22
  export type Tool = AgentTool<any>;
21
23
  export declare const codingTools: Tool[];
@@ -68,6 +70,10 @@ export interface ToolsOptions {
68
70
  read?: ReadToolOptions;
69
71
  /** Options for the bash tool */
70
72
  bash?: BashToolOptions;
73
+ /** Options for the edit tool */
74
+ edit?: EditToolOptions;
75
+ /** Options for the write tool */
76
+ write?: WriteToolOptions;
71
77
  }
72
78
  /**
73
79
  * Create coding tools configured for a specific working directory.
@@ -43,8 +43,8 @@ export function createCodingTools(cwd, options) {
43
43
  return [
44
44
  createReadTool(cwd, options?.read),
45
45
  createBashTool(cwd, options?.bash),
46
- createEditTool(cwd),
47
- createWriteTool(cwd),
46
+ createEditTool(cwd, options?.edit),
47
+ createWriteTool(cwd, options?.write),
48
48
  createTimeTool(),
49
49
  ];
50
50
  }
@@ -61,8 +61,8 @@ export function createAllTools(cwd, options) {
61
61
  return {
62
62
  read: createReadTool(cwd, options?.read),
63
63
  bash: createBashTool(cwd, options?.bash),
64
- edit: createEditTool(cwd),
65
- write: createWriteTool(cwd),
64
+ edit: createEditTool(cwd, options?.edit),
65
+ write: createWriteTool(cwd, options?.write),
66
66
  grep: createGrepTool(cwd),
67
67
  find: createFindTool(cwd),
68
68
  ls: createLsTool(cwd),
@@ -24,6 +24,8 @@ export interface WriteOperations {
24
24
  export interface WriteToolOptions {
25
25
  /** Custom operations for file writing. Default: local filesystem */
26
26
  operations?: WriteOperations;
27
+ /** Optional guard called with the resolved absolute path before writing. */
28
+ beforeWrite?: (absolutePath: string) => void | Promise<void>;
27
29
  }
28
30
  export declare function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema>;
29
31
  /** Default write tool using process.cwd() - for backwards compatibility */
@@ -20,6 +20,7 @@ export function createWriteTool(cwd, options) {
20
20
  execute: async (_toolCallId, { path, content }, signal) => {
21
21
  const absolutePath = resolveToCwd(path, cwd);
22
22
  const dir = dirname(absolutePath);
23
+ await options?.beforeWrite?.(absolutePath);
23
24
  return new Promise((resolve, reject) => {
24
25
  // Check if already aborted
25
26
  if (signal?.aborted) {
@@ -2,6 +2,6 @@
2
2
  * [WHO]: sleep()
3
3
  * [FROM]: No external dependencies
4
4
  * [TO]: Consumed by core/runtime/agent-session.ts
5
- * [HERE]: core/utils/sleep.ts - sleep helper that respects abort signal
5
+ * [HERE]: core/utils/sleep.ts - sleep helper that respects abort signal; cleans the abort listener on both resolve and reject so repeated sleeps against the same long-lived signal do not stack listeners (Node fires MaxListenersExceededWarning at 11)
6
6
  */
7
7
  export declare function sleep(ms: number, signal?: AbortSignal): Promise<void>;
@@ -2,7 +2,7 @@
2
2
  * [WHO]: sleep()
3
3
  * [FROM]: No external dependencies
4
4
  * [TO]: Consumed by core/runtime/agent-session.ts
5
- * [HERE]: core/utils/sleep.ts - sleep helper that respects abort signal
5
+ * [HERE]: core/utils/sleep.ts - sleep helper that respects abort signal; cleans the abort listener on both resolve and reject so repeated sleeps against the same long-lived signal do not stack listeners (Node fires MaxListenersExceededWarning at 11)
6
6
  */
7
7
  export function sleep(ms, signal) {
8
8
  return new Promise((resolve, reject) => {
@@ -10,10 +10,14 @@ export function sleep(ms, signal) {
10
10
  reject(new Error("Aborted"));
11
11
  return;
12
12
  }
13
- const timeout = setTimeout(resolve, ms);
14
- signal?.addEventListener("abort", () => {
13
+ const onAbort = () => {
15
14
  clearTimeout(timeout);
16
15
  reject(new Error("Aborted"));
17
- });
16
+ };
17
+ const timeout = setTimeout(() => {
18
+ signal?.removeEventListener("abort", onAbort);
19
+ resolve();
20
+ }, ms);
21
+ signal?.addEventListener("abort", onAbort, { once: true });
18
22
  });
19
23
  }
@@ -8,7 +8,16 @@ diagnostics/types.ts: Diagnostic event/report type contract and diagnostic:event
8
8
  diagnostics/diagnostic-buffer.ts: DiagnosticBuffer, event coercion, fingerprint dedupe, prompt gating
9
9
  diagnostics/reporter.ts: User-approved InsForge pencil_issue_events reporter, configured via NANOPENCIL_ISSUE_* env vars
10
10
  diagnostics/redaction.ts: Diagnostic message normalization and secret/path redaction helpers
11
- link-world/index.ts: Internet access extension, provides internet-search Skill after setup
11
+ browser/index.ts: Browser Harness extension entry, registers browser/browser_admin tools, /browser command, Browser Harness resource discovery, project-local browser workspace seeding
12
+ browser/browser.md: Browser Harness day-to-day skill instructions for NanoPencil tool use and workspace contribution
13
+ browser/install.md: Browser Harness setup and troubleshooting instructions, exposed as a skill resource
14
+ browser/src/browser_harness/: Vendored Browser Harness Python package, CDP daemon, IPC bridge, admin commands, and helper functions
15
+ browser/interaction-skills/: Reusable Browser Harness mechanics guides for browser interactions
16
+ browser/agent-workspace/: Seed workspace copied to .nanopencil/browser-workspace for editable helpers and domain skills
17
+ link-world/index.ts: Internet access integration entry, registers link_world_admin/link_world_exec/web_search/web_fetch tools, /link-world status/doctor/version/install commands, and bundled internet-search resources
18
+ link-world/link-world-agent.md: Agent-facing skill that tells models to prefer web_search/web_fetch and link_world_admin/link_world_exec over bash for internet tasks
19
+ link-world/network-routing.md: Routing skill that tells models when to use web_search/web_fetch/link-world versus browser automation
20
+ link-world/agent-workspace/: Seed workspace copied to .nanopencil/link-world-workspace for project-local domain skills and notes
12
21
  mcp/index.ts: MCP protocol integration extension, MCP guidance resources
13
22
  presence/index.ts: AI-driven opening + idle presence lines, uses NanoMemEngine episodes/preferences/lessons + git/cwd snapshot, injects latest line into agent systemPrompt every turn for main-conversation perception, 30s debounce + idle in-flight lock, configurable via settings.presence.enabled, PRESENCE_MESSAGE_TYPE renderer
14
23
  plan/index.ts: Plan Mode extension entry, /plan /plan:validate /plan:approve commands, EnterPlanMode/ExitPlanMode tools, permission gating, TUI status/widget, workflow prompt injection
@@ -52,13 +61,18 @@ sal/eval/noop-sink.ts: noopSink — silent EvalSink used when eval disabled or n
52
61
  sal/eval/insforge-sink.ts: InsForgeEvalSink — PostgREST adapter, routes run_start→eval_runs INSERT (merge-duplicates) with legacy-schema fallback, writes turn_anchor/tool_trace/memory_recalls/run_end only after parent run confirmation, tool_trace→eval_tool_traces with PGRST204 fallback, memory_recalls→eval_memory_recalls batch INSERT, run_end→eval_runs PATCH; allowSelfSigned TLS option logs only in development runtime, batching with default 2000ms interval
53
62
  sal/eval/jsonl-sink.ts: JsonlEvalSink — append-only filesystem adapter, one JSON object per line, accepts file:// URLs or plain paths, auto-creates parent dir, batched writes
54
63
  sal/README.md: SAL extension usage, sidecar output layout, weights override, pluggability contract
55
- team/index.ts: AgentTeam extension entry, /team:/team:spawn/:send/:status/:stop/:terminate/:approve/:mode commands, TEAM_MESSAGE_TYPE renderer
56
- team/team-types.ts: TeammateRole/TeammateMode/TeammateStatus/TeammateIdentity/TeammateMessage/PersistedTeammate/TeamSpawnSpec/TeamSendResult types
64
+ team/index.ts: AgentTeam extension entry, /team <task>, /team:spawn/:preset/:send/:status/:progress/:psyche/:dashboard/:task/:mail/:allow-path/:stop/:terminate/:approve/:mode commands, TEAM_MESSAGE_TYPE renderer, realtime status/dashboard updates
65
+ team/team-types.ts: TeammateRole/TeammateMode/TeammateStatus/TeamTask/HarnessState/PsycheWeights/TeammateLiveState/TeammateIdentity/TeammateMessage/PersistedTeammate/TeamSpawnSpec/TeamSendResult types
57
66
  team/team-state-store.ts: TeamStateStore class - durable teammate persistence via JSON files in <agentDir>/teams/
58
67
  team/team-parser.ts: Team command parser - parseTeamCommand/buildTeamHelp for /team:* subcommands
59
- team/team-runtime.ts: TeamRuntime class - teammate registry, lifecycle, mailbox + permission + transcript wiring
68
+ team/team-runtime.ts: TeamRuntime class - teammate registry, per-teammate send queue, task/mailbox prompt context, lifecycle, realtime status/live events, durable tasks, mailbox + permission + transcript wiring
69
+ team/team-task-store.ts: TeamTaskStore class - durable shared task list in <storageDir>/tasks.json
70
+ team/team-harness.ts: Harness protocol helpers - context files, phase instructions, checkpoint/revert, feature validation
71
+ team/team-presets.ts: Preset definitions and executor - solo/duo/squad spawning, model-assisted auto team selection, heuristic fallback
72
+ team/team-dashboard.ts: Text dashboard/status rendering - teammate cards, live stream preview, progress bars, footer summary
73
+ team/team-psyche.ts: Psyche prompt layer - role/phase weighted Id/Ego/Superego prompt construction
60
74
  team/team-permissions.ts: PermissionStore - pending permission request queue, approve/deny, path allowlists
61
- team/team-mailbox.ts: TeamMailbox - typed append-only message log for leader↔teammate
75
+ team/team-mailbox.ts: TeamMailbox - typed JSONL-backed append-only message log for leader↔teammate and teammate↔teammate
62
76
  team/team-transcript.ts: TeamTranscriptWriter - per-teammate JSONL transcripts
63
77
  team/TESTING.md: Manual & smoke-test guide for Phase B AgentTeam
64
78
 
@@ -0,0 +1,17 @@
1
+ # extensions/defaults/browser/
2
+
3
+ > P2 | Parent: ../AGENT.md
4
+
5
+ Member List
6
+ index.ts: Browser Harness extension entry, registers browser/browser_admin tools, /browser command, Browser Harness resource discovery for core/interaction/domain skills, project-local browser workspace seeding
7
+ browser.md: Browser Harness day-to-day skill instructions for NanoPencil tool use and workspace contribution
8
+ install.md: Browser Harness setup and troubleshooting instructions, exposed as a skill resource
9
+ src/browser_harness/: Vendored Browser Harness Python package, CDP daemon, IPC bridge, admin commands, and helper functions
10
+ src/browser_harness/AGENT.md: P2 module map for the vendored Browser Harness Python package
11
+ interaction-skills/: Reusable Browser Harness mechanics guides for tabs, screenshots, iframes, cookies, uploads, dialogs, scrolling, and related browser interactions
12
+ agent-workspace/: Seed workspace copied to .nanopencil/browser-workspace for editable helpers and domain skills
13
+ .env.example: Browser Harness environment variable template for Browser Use cloud integration
14
+
15
+ Rule: Members complete, one item per line, parent links valid, precise terms first
16
+
17
+ [COVENANT]: Update this file header on changes and verify against parent AGENT.md