@11agents/cli 0.1.9 → 0.1.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -102,6 +102,8 @@ On startup, and every 30 minutes after that, the daemon syncs project metadata a
102
102
 
103
103
  Codex runs from `~/.11agents/<project>/` by default. Treat that directory as read-only project context. Task code may write temporary files only under `./tmp/<taskId>/`; the daemon removes that task scratch directory after the task finishes. Agent environment variables from the control plane are injected into the Codex child process and are not written to disk.
104
104
 
105
+ The built-in Codex worker starts task executions with `codex --ask-for-approval never --yolo exec` and prefixes the task prompt with `/goal ` by default so remote runtime tasks can run without approval prompts or sandbox restrictions. To opt a daemon back into a Codex sandbox, start it with `--codex-sandbox read-only`, `--codex-sandbox workspace-write`, or `--codex-sandbox danger-full-access`.
106
+
105
107
  The built-in task runner currently supports Codex tasks. A custom handler may export:
106
108
 
107
109
  ```js
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@11agents/cli",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "11agents local runtime and telemetry CLI",
5
5
  "type": "module",
6
6
  "bin": {
@@ -234,6 +234,174 @@ function extractJsonObject(text) {
234
234
  return null
235
235
  }
236
236
 
237
+ function extractUrls(text) {
238
+ const matches = String(text || '').match(/https?:\/\/[^\s`),]+/g) || []
239
+ return [...new Set(matches.map(url => url.replace(/[.]+$/, '')))]
240
+ }
241
+
242
+ function recoveredKnowledgeNode(localPath, kind, title, body, sourceUrl) {
243
+ return {
244
+ id: slugify(localPath.replace(/\.(md|txt)$/i, ''), 'node'),
245
+ kind,
246
+ title,
247
+ body,
248
+ local_path: localPath,
249
+ metadata: {
250
+ compiler: 'runtime-deep-organize-recovery',
251
+ ...(sourceUrl ? { source_url: sourceUrl } : {}),
252
+ },
253
+ }
254
+ }
255
+
256
+ function buildRecoveredDeepKnowledgeSnapshot(task, output) {
257
+ const text = String(output || '').trim()
258
+ if (!text) return null
259
+ const lower = text.toLowerCase()
260
+ const hasPreparedWiki = lower.includes('prepared the intended wiki') || lower.includes('intended wiki structure')
261
+ const hasSourceMaterial = lower.includes('sources checked') || lower.includes('official source material')
262
+ const hasToolingFailure = lower.includes('blocked by runtime tooling') || lower.includes('knowledge_sync') || lower.includes('apply_patch')
263
+ if (!hasPreparedWiki && !(hasSourceMaterial && hasToolingFailure)) return null
264
+
265
+ const deepOrganize = knowledgeDeepOrganizeSpec(task) || {}
266
+ const sourceUrls = extractUrls(text)
267
+ const primarySource = sourceUrls[0] || deepOrganize.source_url || ''
268
+ const sourceList = sourceUrls.length ? sourceUrls.map(url => `- ${url}`).join('\n') : `- ${primarySource || 'Source URL was not recoverable from worker output.'}`
269
+ const workspaceName = task.workspace?.name || task.workspace?.slug || 'Project'
270
+ const recoveredAt = new Date().toISOString()
271
+ const recoveryNote = [
272
+ 'Recovered from a deep organization worker response that could not write local files or push MCP state.',
273
+ '',
274
+ 'The worker reported that it inspected source material and prepared the wiki content in memory. This snapshot preserves that result so the platform can write cloud knowledge during task completion.',
275
+ '',
276
+ 'Sources:',
277
+ sourceList,
278
+ ].join('\n')
279
+ const sourceSummaryBody = [
280
+ recoveryNote,
281
+ '',
282
+ 'Worker output:',
283
+ text,
284
+ ].join('\n')
285
+ const compactSourceBody = [
286
+ recoveryNote,
287
+ '',
288
+ 'Use `resources/source-summary.md` as the recovery audit trail and refine this page during the next successful deep organization pass.',
289
+ ].join('\n')
290
+
291
+ const nodes = [
292
+ recoveredKnowledgeNode('CLAUDE.md', 'document', 'Agent Instructions', [
293
+ `# ${workspaceName} Knowledge Base Instructions`,
294
+ '',
295
+ 'Read `index.md` first, then load the most relevant semantic pages before executing project work.',
296
+ '',
297
+ 'This wiki was recovered from an interrupted deep organization run. Preserve source-backed facts, remove duplication, and update durable pages when new facts are learned.',
298
+ ].join('\n'), primarySource),
299
+ recoveredKnowledgeNode('README.md', 'document', 'README', [
300
+ `# ${workspaceName} Knowledge Base`,
301
+ '',
302
+ '## Where to Start',
303
+ '',
304
+ '- `index.md` maps the recovered wiki.',
305
+ '- `information/product-overview.md` captures product context.',
306
+ '- `resources/source-summary.md` records checked source material and the recovery audit trail.',
307
+ '',
308
+ compactSourceBody,
309
+ ].join('\n'), primarySource),
310
+ recoveredKnowledgeNode('index.md', 'document', 'Knowledge Map', [
311
+ '# Knowledge Map',
312
+ '',
313
+ '## Node Map',
314
+ '',
315
+ '- `llms.txt` - compact LLM-readable context.',
316
+ '- `llms-full.txt` - fuller recovered context.',
317
+ '- `information/product-overview.md` - product overview.',
318
+ '- `audience/README.md` - audience and jobs-to-be-done.',
319
+ '- `voice/brand-voice.md` - voice guidance.',
320
+ '- `marketing/README.md` - marketing positioning.',
321
+ '- `information/feature-map.md` - feature map.',
322
+ '- `information/solvea.md` - Solvea context.',
323
+ '- `information/review-analysis-api.md` - Review Analysis API context.',
324
+ '- `resources/source-summary.md` - checked sources and recovery notes.',
325
+ '- `decisions/knowledge-organization.md` - organization decisions.',
326
+ '',
327
+ `Recovered at: ${recoveredAt}`,
328
+ ].join('\n'), primarySource),
329
+ recoveredKnowledgeNode('llms.txt', 'document', 'LLMs Compact Context', [
330
+ `# ${workspaceName}`,
331
+ '',
332
+ '## Knowledge',
333
+ '',
334
+ compactSourceBody,
335
+ ].join('\n'), primarySource),
336
+ recoveredKnowledgeNode('llms-full.txt', 'document', 'LLMs Full Context', sourceSummaryBody, primarySource),
337
+ recoveredKnowledgeNode('information/product-overview.md', 'fact', 'Product Overview', [
338
+ '# Product Overview',
339
+ '',
340
+ 'The recovered worker output identified VOC AI source material for voice-of-customer analysis, market insight, LiveScript, Review Analysis API, and Solvea context.',
341
+ '',
342
+ compactSourceBody,
343
+ ].join('\n'), primarySource),
344
+ recoveredKnowledgeNode('audience/README.md', 'insight', 'Audience', [
345
+ '# Audience',
346
+ '',
347
+ 'The recovered source set points to Amazon sellers, ecommerce brands, product researchers, and teams using review analysis or market insight workflows.',
348
+ '',
349
+ compactSourceBody,
350
+ ].join('\n'), primarySource),
351
+ recoveredKnowledgeNode('voice/brand-voice.md', 'document', 'Brand Voice', [
352
+ '# Brand Voice',
353
+ '',
354
+ 'Use a practical, source-backed analyst voice. Prefer concrete review, market, and customer evidence over generic AI claims.',
355
+ '',
356
+ compactSourceBody,
357
+ ].join('\n'), primarySource),
358
+ recoveredKnowledgeNode('marketing/README.md', 'document', 'Marketing', [
359
+ '# Marketing',
360
+ '',
361
+ 'Position around customer voice analysis, market insight, and review intelligence. Tie claims back to the checked official sources.',
362
+ '',
363
+ compactSourceBody,
364
+ ].join('\n'), primarySource),
365
+ recoveredKnowledgeNode('information/feature-map.md', 'fact', 'Feature Map', [
366
+ '# Feature Map',
367
+ '',
368
+ 'Recovered feature areas: Voice of Customer Analysis, Market Insight, Review Analysis API, LiveScript, and Solvea.',
369
+ '',
370
+ compactSourceBody,
371
+ ].join('\n'), primarySource),
372
+ recoveredKnowledgeNode('information/solvea.md', 'fact', 'Solvea', [
373
+ '# Solvea',
374
+ '',
375
+ 'Solvea context was included in the checked source set. Refine this page from `https://solvea.cx/` during the next successful deep organization pass.',
376
+ '',
377
+ compactSourceBody,
378
+ ].join('\n'), primarySource),
379
+ recoveredKnowledgeNode('information/review-analysis-api.md', 'fact', 'Review Analysis API', [
380
+ '# Review Analysis API',
381
+ '',
382
+ 'The Review Analysis API page was included in the checked official source set. Treat it as a core product/API context page and refine with source-backed details on the next pass.',
383
+ '',
384
+ compactSourceBody,
385
+ ].join('\n'), primarySource),
386
+ recoveredKnowledgeNode('resources/source-summary.md', 'resource', 'Source Summary', sourceSummaryBody, primarySource),
387
+ recoveredKnowledgeNode('decisions/knowledge-organization.md', 'decision', 'Knowledge Organization Decisions', [
388
+ '# Knowledge Organization Decisions',
389
+ '',
390
+ 'Decision: preserve the worker-prepared wiki as semantic pages instead of marking the task blocked when runtime tooling prevents shell, local writes, or MCP push.',
391
+ '',
392
+ 'Reason: deep organization can still produce a platform-writable `knowledge_snapshot` through task completion.',
393
+ '',
394
+ compactSourceBody,
395
+ ].join('\n'), primarySource),
396
+ ]
397
+ return {
398
+ nodes,
399
+ edges: nodes
400
+ .filter(node => node.local_path !== 'index.md')
401
+ .map(node => ({ from: 'index', to: node.id, relation: 'references', metadata: {} })),
402
+ }
403
+ }
404
+
237
405
  async function loadTaskHandler(handlerPath, deps) {
238
406
  if (!handlerPath) return null
239
407
  const handlerModule = await deps.importHandler(handlerPath)
@@ -633,17 +801,29 @@ function buildCodexPrompt(task) {
633
801
  async function runCodex({ task, prompt, flags = {}, deps }) {
634
802
  const codexBin = flag(flags, 'codex-bin', 'codex')
635
803
  const workdir = flag(flags, 'codex-workdir', task.execution_context?.workdir || process.cwd())
636
- const args = [
637
- '--ask-for-approval',
638
- 'never',
639
- 'exec',
640
- '--skip-git-repo-check',
641
- '--sandbox',
642
- flag(flags, 'codex-sandbox', 'workspace-write'),
643
- '-C',
644
- workdir,
645
- '-',
646
- ]
804
+ const sandbox = flag(flags, 'codex-sandbox')
805
+ const args = sandbox
806
+ ? [
807
+ '--ask-for-approval',
808
+ 'never',
809
+ 'exec',
810
+ '--skip-git-repo-check',
811
+ '--sandbox',
812
+ sandbox,
813
+ '-C',
814
+ workdir,
815
+ '-',
816
+ ]
817
+ : [
818
+ '--ask-for-approval',
819
+ 'never',
820
+ '--yolo',
821
+ 'exec',
822
+ '--skip-git-repo-check',
823
+ '-C',
824
+ workdir,
825
+ '-',
826
+ ]
647
827
  const model = flag(flags, 'codex-model')
648
828
  const profile = flag(flags, 'codex-profile')
649
829
  const execIndex = args.indexOf('exec')
@@ -652,7 +832,7 @@ async function runCodex({ task, prompt, flags = {}, deps }) {
652
832
 
653
833
  const commandLine = [codexBin, ...args].map(value => JSON.stringify(String(value))).join(' ')
654
834
  deps.log(JSON.stringify({ running: 'codex exec', command: commandLine, workdir }, null, 2))
655
- const result = await deps.runProcess(codexBin, args, { input: prompt, cwd: workdir, env: task.execution_context?.env || process.env })
835
+ const result = await deps.runProcess(codexBin, args, { input: `/goal ${prompt}`, cwd: workdir, env: task.execution_context?.env || process.env })
656
836
  const output = String(result.stdout || '').trim()
657
837
  const error = String(result.stderr || '').trim()
658
838
  if (result.code !== 0) {
@@ -675,6 +855,25 @@ async function runCodex({ task, prompt, flags = {}, deps }) {
675
855
  status: structured.status ? String(structured.status) : 'in_review',
676
856
  }
677
857
  }
858
+ const recoveredSnapshot = buildRecoveredDeepKnowledgeSnapshot(task, [
859
+ structured?.comment || structured?.summary || '',
860
+ structured?.memory_delta || structured?.memoryDelta || '',
861
+ output,
862
+ ].filter(Boolean).join('\n\n'))
863
+ if (recoveredSnapshot) {
864
+ return {
865
+ comment: [
866
+ String(structured?.comment || structured?.summary || output || `Codex completed task ${task.id}.`).trim(),
867
+ 'Recovered a knowledge_snapshot from the worker output because local tooling or MCP push was unavailable.',
868
+ ].filter(Boolean).join('\n\n'),
869
+ memory_delta: [
870
+ String(structured?.memory_delta || structured?.memoryDelta || '').trim(),
871
+ 'Recovered deep knowledge organization snapshot from worker output.',
872
+ ].filter(Boolean).join('\n'),
873
+ status: 'in_review',
874
+ knowledge_snapshot: recoveredSnapshot,
875
+ }
876
+ }
678
877
  }
679
878
  return {
680
879
  comment: output || `Codex completed task ${task.id}.`,