@agent-native/core 0.49.27 → 0.50.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (95) hide show
  1. package/dist/agent/harness/ai-sdk-adapter.d.ts +13 -0
  2. package/dist/agent/harness/ai-sdk-adapter.d.ts.map +1 -0
  3. package/dist/agent/harness/ai-sdk-adapter.js +232 -0
  4. package/dist/agent/harness/ai-sdk-adapter.js.map +1 -0
  5. package/dist/agent/harness/background.d.ts +15 -0
  6. package/dist/agent/harness/background.d.ts.map +1 -0
  7. package/dist/agent/harness/background.js +233 -0
  8. package/dist/agent/harness/background.js.map +1 -0
  9. package/dist/agent/harness/builtin.d.ts +2 -0
  10. package/dist/agent/harness/builtin.d.ts.map +1 -0
  11. package/dist/agent/harness/builtin.js +24 -0
  12. package/dist/agent/harness/builtin.js.map +1 -0
  13. package/dist/agent/harness/index.d.ts +9 -0
  14. package/dist/agent/harness/index.d.ts.map +1 -0
  15. package/dist/agent/harness/index.js +8 -0
  16. package/dist/agent/harness/index.js.map +1 -0
  17. package/dist/agent/harness/registry.d.ts +15 -0
  18. package/dist/agent/harness/registry.d.ts.map +1 -0
  19. package/dist/agent/harness/registry.js +70 -0
  20. package/dist/agent/harness/registry.js.map +1 -0
  21. package/dist/agent/harness/runner.d.ts +21 -0
  22. package/dist/agent/harness/runner.d.ts.map +1 -0
  23. package/dist/agent/harness/runner.js +86 -0
  24. package/dist/agent/harness/runner.js.map +1 -0
  25. package/dist/agent/harness/store.d.ts +46 -0
  26. package/dist/agent/harness/store.d.ts.map +1 -0
  27. package/dist/agent/harness/store.js +304 -0
  28. package/dist/agent/harness/store.js.map +1 -0
  29. package/dist/agent/harness/translate.d.ts +5 -0
  30. package/dist/agent/harness/translate.d.ts.map +1 -0
  31. package/dist/agent/harness/translate.js +120 -0
  32. package/dist/agent/harness/translate.js.map +1 -0
  33. package/dist/agent/harness/types.d.ts +127 -0
  34. package/dist/agent/harness/types.d.ts.map +1 -0
  35. package/dist/agent/harness/types.js +2 -0
  36. package/dist/agent/harness/types.js.map +1 -0
  37. package/dist/agent/production-agent.d.ts.map +1 -1
  38. package/dist/agent/production-agent.js +2 -0
  39. package/dist/agent/production-agent.js.map +1 -1
  40. package/dist/cli/create.d.ts.map +1 -1
  41. package/dist/cli/create.js +10 -1
  42. package/dist/cli/create.js.map +1 -1
  43. package/dist/cli/pr-visual-recap-workflow.d.ts +1 -1
  44. package/dist/cli/pr-visual-recap-workflow.d.ts.map +1 -1
  45. package/dist/cli/pr-visual-recap-workflow.js +1 -1
  46. package/dist/cli/pr-visual-recap-workflow.js.map +1 -1
  47. package/dist/cli/skills.d.ts +1 -1
  48. package/dist/cli/skills.d.ts.map +1 -1
  49. package/dist/cli/skills.js +8 -1
  50. package/dist/cli/skills.js.map +1 -1
  51. package/dist/client/blocks/library/wireframe.d.ts.map +1 -1
  52. package/dist/client/blocks/library/wireframe.js +0 -1
  53. package/dist/client/blocks/library/wireframe.js.map +1 -1
  54. package/dist/client/resources/use-resources.d.ts.map +1 -1
  55. package/dist/client/resources/use-resources.js +4 -2
  56. package/dist/client/resources/use-resources.js.map +1 -1
  57. package/dist/code-agents/background-run.d.ts +6 -4
  58. package/dist/code-agents/background-run.d.ts.map +1 -1
  59. package/dist/code-agents/background-run.js.map +1 -1
  60. package/dist/coding-tools/run-code.js +6 -4
  61. package/dist/coding-tools/run-code.js.map +1 -1
  62. package/dist/provider-api/index.d.ts +20 -12
  63. package/dist/provider-api/index.d.ts.map +1 -1
  64. package/dist/provider-api/index.js +157 -37
  65. package/dist/provider-api/index.js.map +1 -1
  66. package/dist/provider-api/quota-governor.d.ts +53 -0
  67. package/dist/provider-api/quota-governor.d.ts.map +1 -0
  68. package/dist/provider-api/quota-governor.js +395 -0
  69. package/dist/provider-api/quota-governor.js.map +1 -0
  70. package/dist/provider-api/staging.d.ts.map +1 -1
  71. package/dist/provider-api/staging.js +16 -0
  72. package/dist/provider-api/staging.js.map +1 -1
  73. package/dist/server/agent-chat-plugin.d.ts.map +1 -1
  74. package/dist/server/agent-chat-plugin.js +34 -10
  75. package/dist/server/agent-chat-plugin.js.map +1 -1
  76. package/dist/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +98 -0
  77. package/dist/workspace-files/index.d.ts +0 -1
  78. package/dist/workspace-files/index.d.ts.map +1 -1
  79. package/dist/workspace-files/index.js +0 -1
  80. package/dist/workspace-files/index.js.map +1 -1
  81. package/dist/workspace-files/store.d.ts +14 -9
  82. package/dist/workspace-files/store.d.ts.map +1 -1
  83. package/dist/workspace-files/store.js +89 -164
  84. package/dist/workspace-files/store.js.map +1 -1
  85. package/dist/workspace-files/tool.d.ts +3 -4
  86. package/dist/workspace-files/tool.d.ts.map +1 -1
  87. package/dist/workspace-files/tool.js +8 -7
  88. package/dist/workspace-files/tool.js.map +1 -1
  89. package/docs/content/deployment.md +1 -1
  90. package/package.json +2 -1
  91. package/src/templates/workspace-core/.agents/skills/harness-agents/SKILL.md +98 -0
  92. package/dist/workspace-files/schema.d.ts +0 -195
  93. package/dist/workspace-files/schema.d.ts.map +0 -1
  94. package/dist/workspace-files/schema.js +0 -48
  95. package/dist/workspace-files/schema.js.map +0 -1
@@ -1,10 +1,9 @@
1
1
  /**
2
- * `workspace-files` agent tool.
2
+ * `workspace-files` bridge tool.
3
3
  *
4
4
  * A single tool with an `action` discriminator covering write, append, read,
5
- * list, delete, and grep. Files persist across conversations; the agent uses
6
- * them to stage large intermediate results (fetched pages, per-item memos)
7
- * and then read back selectively for synthesis.
5
+ * list, delete, and grep. It is kept for `run-code` workspaceRead/workspaceWrite
6
+ * compatibility and delegates storage to the Resources table.
8
7
  *
9
8
  * Scope is automatically resolved from the active request context:
10
9
  * - org scope when a request orgId is present (shared across users in the org)
@@ -27,10 +26,12 @@ function resolveScope() {
27
26
  export function createWorkspaceFilesTool() {
28
27
  return {
29
28
  "workspace-files": {
29
+ agentTool: false,
30
30
  readOnly: false,
31
31
  tool: {
32
32
  description: [
33
- "Durable scratch-file storage for the agent. Files persist across conversations and are scoped to the current org/user.",
33
+ "Bridge-only workspace file storage backed by Resources. Files are scoped to the current org/user and appear in the Resources workspace.",
34
+ "Use scratch/... for temporary intermediate results; scratch files are hidden from the Resources view by default and expire. Use durable folder names for files the user explicitly wants to keep/manage.",
34
35
  "Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.",
35
36
  "",
36
37
  "Typical fusion-style workflow:",
@@ -40,7 +41,7 @@ export function createWorkspaceFilesTool() {
40
41
  " 4. `delete` temp files when no longer needed.",
41
42
  "",
42
43
  "Actions:",
43
- " write — create or overwrite a file. Max 2 MB per file, 200 MB total.",
44
+ " write — create or overwrite a file. Max 2 MB per file.",
44
45
  " append — append text to a file (or create if absent).",
45
46
  " read — read content, optionally with offset/maxChars for paging large files.",
46
47
  " list — list files (with optional path prefix filter) showing name, size, updated.",
@@ -57,7 +58,7 @@ export function createWorkspaceFilesTool() {
57
58
  },
58
59
  path: {
59
60
  type: "string",
60
- description: 'File path relative to the scope root, e.g. "analysis/q2-memos/acme.md". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',
61
+ description: 'File path relative to the scope root, e.g. "scratch/analysis/q2-memos/acme.md". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',
61
62
  },
62
63
  content: {
63
64
  type: "string",
@@ -1 +1 @@
1
- {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `workspace-files` agent tool.\n *\n * A single tool with an `action` discriminator covering write, append, read,\n * list, delete, and grep. Files persist across conversations; the agent uses\n * them to stage large intermediate results (fetched pages, per-item memos)\n * and then read back selectively for synthesis.\n *\n * Scope is automatically resolved from the active request context:\n * - org scope when a request orgId is present (shared across users in the org)\n * - user scope otherwise (personal to the requesting user's email)\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"../server/request-context.js\";\nimport {\n writeWorkspaceFile,\n appendWorkspaceFile,\n readWorkspaceFile,\n listWorkspaceFiles,\n deleteWorkspaceFile,\n grepWorkspaceFiles,\n type WorkspaceFilesScope,\n} from \"./store.js\";\n\nconst MAX_READ_CHARS = 100_000;\nconst DEFAULT_READ_CHARS = 40_000;\n\n/** Resolve scope from the current request context (org-preferred). */\nfunction resolveScope(): WorkspaceFilesScope | null {\n const orgId = getRequestOrgId();\n if (orgId) return { scope: \"org\", scopeId: orgId };\n const email = getRequestUserEmail();\n if (email) return { scope: \"user\", scopeId: email };\n return null;\n}\n\nexport function createWorkspaceFilesTool(): Record<string, ActionEntry> {\n return {\n \"workspace-files\": {\n readOnly: false,\n tool: {\n description: [\n \"Durable scratch-file storage for the agent. Files persist across conversations and are scoped to the current org/user.\",\n \"Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.\",\n \"\",\n \"Typical fusion-style workflow:\",\n \" 1. Fan out: for each item, fetch data and `write` a per-item memo file.\",\n \" 2. Synthesize: `list` files, then `read` each memo (with offset/maxChars to page large ones).\",\n \" 3. Optionally `grep` across all memos to find patterns.\",\n \" 4. `delete` temp files when no longer needed.\",\n \"\",\n \"Actions:\",\n \" write — create or overwrite a file. Max 2 MB per file, 200 MB total.\",\n \" append — append text to a file (or create if absent).\",\n \" read — read content, optionally with offset/maxChars for paging large files.\",\n \" list — list files (with optional path prefix filter) showing name, size, updated.\",\n \" delete — delete a file by path.\",\n \" grep — search content across files for a substring or regex.\",\n ].join(\"\\n\"),\n parameters: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"write\", \"append\", \"read\", \"list\", \"delete\", \"grep\"],\n description: \"Operation to perform.\",\n },\n path: {\n type: \"string\",\n description:\n 'File path relative to the scope root, e.g. \"analysis/q2-memos/acme.md\". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',\n },\n content: {\n type: \"string\",\n description:\n \"Text content to write or append. Required for write/append.\",\n },\n contentType: {\n type: \"string\",\n description:\n 'MIME type for new files. Default: \"text/plain\". Use \"application/json\" for JSON, \"text/markdown\" for Markdown.',\n },\n offset: {\n type: \"number\",\n description:\n \"Character offset to start reading from (for paging large files). Default: 0.\",\n },\n maxChars: {\n type: \"number\",\n description: `Maximum characters to return when reading. Default: ${DEFAULT_READ_CHARS}. Max: ${MAX_READ_CHARS}.`,\n },\n pattern: {\n type: \"string\",\n description:\n \"Search pattern for grep. Required for grep action. A plain substring by default; set useRegex to true for a regex.\",\n },\n useRegex: {\n type: \"boolean\",\n description:\n \"When true, treat `pattern` as a JavaScript regex (case-insensitive). Default: false.\",\n },\n },\n required: [\"action\"],\n },\n },\n\n run: async (args: Record<string, unknown>): Promise<string> => {\n const scope = resolveScope();\n if (!scope) {\n return \"Error: workspace-files requires an authenticated request context.\";\n }\n\n const action = String(args.action ?? \"\").trim();\n\n try {\n switch (action) {\n case \"write\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for write.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await writeWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"write\",\n path: meta.path,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"append\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for append.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await appendWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"append\",\n path: meta.path,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"read\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for read.\";\n const rawOffset = Number(args.offset);\n const offset =\n Number.isFinite(rawOffset) && rawOffset > 0 ? rawOffset : 0;\n const rawMax = Number(args.maxChars);\n const maxChars =\n Number.isFinite(rawMax) && rawMax > 0\n ? Math.min(rawMax, MAX_READ_CHARS)\n : DEFAULT_READ_CHARS;\n\n const file = await readWorkspaceFile(scope, path, {\n offset,\n maxChars,\n });\n if (!file) {\n return JSON.stringify({\n ok: false,\n error: `File not found: \"${path}\"`,\n });\n }\n\n const truncated = file.content.length >= maxChars;\n return JSON.stringify({\n ok: true,\n path: file.path,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n updatedAt: file.updatedAt,\n content: file.content,\n ...(truncated\n ? {\n truncated: true,\n nextOffset: offset + file.content.length,\n hint: `File has more content. Call again with offset: ${offset + file.content.length}`,\n }\n : {}),\n });\n }\n\n case \"list\": {\n const prefix = args.path ? String(args.path).trim() : undefined;\n const files = await listWorkspaceFiles(\n scope,\n prefix || undefined,\n );\n return JSON.stringify({\n ok: true,\n count: files.length,\n files: files.map((f) => ({\n path: f.path,\n sizeBytes: f.sizeBytes,\n contentType: f.contentType,\n updatedAt: f.updatedAt,\n })),\n });\n }\n\n case \"delete\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for delete.\";\n const deleted = await deleteWorkspaceFile(scope, path);\n return JSON.stringify({\n ok: true,\n deleted,\n path,\n });\n }\n\n case \"grep\": {\n const pattern = String(args.pattern ?? \"\").trim();\n if (!pattern) return \"Error: pattern is required for grep.\";\n const prefix = args.path ? String(args.path).trim() : undefined;\n const useRegex =\n args.useRegex === true || String(args.useRegex) === \"true\";\n const matches = await grepWorkspaceFiles(scope, pattern, {\n pathPrefix: prefix || undefined,\n useRegex,\n maxMatchesPerFile: 20,\n maxFiles: 50,\n });\n return JSON.stringify({\n ok: true,\n pattern,\n matchCount: matches.length,\n matches: matches.map((m) => ({\n path: m.path,\n line: m.lineNumber,\n text: m.line,\n })),\n });\n }\n\n default:\n return `Error: unknown action \"${action}\". Valid actions: write, append, read, list, delete, grep.`;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return JSON.stringify({ ok: false, error: msg });\n }\n },\n },\n };\n}\n"]}
1
+ {"version":3,"file":"tool.js","sourceRoot":"","sources":["../../src/workspace-files/tool.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * `workspace-files` bridge tool.\n *\n * A single tool with an `action` discriminator covering write, append, read,\n * list, delete, and grep. It is kept for `run-code` workspaceRead/workspaceWrite\n * compatibility and delegates storage to the Resources table.\n *\n * Scope is automatically resolved from the active request context:\n * - org scope when a request orgId is present (shared across users in the org)\n * - user scope otherwise (personal to the requesting user's email)\n */\n\nimport type { ActionEntry } from \"../agent/production-agent.js\";\nimport {\n getRequestOrgId,\n getRequestUserEmail,\n} from \"../server/request-context.js\";\nimport {\n writeWorkspaceFile,\n appendWorkspaceFile,\n readWorkspaceFile,\n listWorkspaceFiles,\n deleteWorkspaceFile,\n grepWorkspaceFiles,\n type WorkspaceFilesScope,\n} from \"./store.js\";\n\nconst MAX_READ_CHARS = 100_000;\nconst DEFAULT_READ_CHARS = 40_000;\n\n/** Resolve scope from the current request context (org-preferred). */\nfunction resolveScope(): WorkspaceFilesScope | null {\n const orgId = getRequestOrgId();\n if (orgId) return { scope: \"org\", scopeId: orgId };\n const email = getRequestUserEmail();\n if (email) return { scope: \"user\", scopeId: email };\n return null;\n}\n\nexport function createWorkspaceFilesTool(): Record<string, ActionEntry> {\n return {\n \"workspace-files\": {\n agentTool: false,\n readOnly: false,\n tool: {\n description: [\n \"Bridge-only workspace file storage backed by Resources. Files are scoped to the current org/user and appear in the Resources workspace.\",\n \"Use scratch/... for temporary intermediate results; scratch files are hidden from the Resources view by default and expire. Use durable folder names for files the user explicitly wants to keep/manage.\",\n \"Use this to stage large intermediate results (fetched pages, per-item analysis memos, API payloads) so they don't consume context window, then read them back selectively for synthesis.\",\n \"\",\n \"Typical fusion-style workflow:\",\n \" 1. Fan out: for each item, fetch data and `write` a per-item memo file.\",\n \" 2. Synthesize: `list` files, then `read` each memo (with offset/maxChars to page large ones).\",\n \" 3. Optionally `grep` across all memos to find patterns.\",\n \" 4. `delete` temp files when no longer needed.\",\n \"\",\n \"Actions:\",\n \" write — create or overwrite a file. Max 2 MB per file.\",\n \" append — append text to a file (or create if absent).\",\n \" read — read content, optionally with offset/maxChars for paging large files.\",\n \" list — list files (with optional path prefix filter) showing name, size, updated.\",\n \" delete — delete a file by path.\",\n \" grep — search content across files for a substring or regex.\",\n ].join(\"\\n\"),\n parameters: {\n type: \"object\",\n properties: {\n action: {\n type: \"string\",\n enum: [\"write\", \"append\", \"read\", \"list\", \"delete\", \"grep\"],\n description: \"Operation to perform.\",\n },\n path: {\n type: \"string\",\n description:\n 'File path relative to the scope root, e.g. \"scratch/analysis/q2-memos/acme.md\". Required for write/append/read/delete. Optional for list/grep (acts as prefix filter).',\n },\n content: {\n type: \"string\",\n description:\n \"Text content to write or append. Required for write/append.\",\n },\n contentType: {\n type: \"string\",\n description:\n 'MIME type for new files. Default: \"text/plain\". Use \"application/json\" for JSON, \"text/markdown\" for Markdown.',\n },\n offset: {\n type: \"number\",\n description:\n \"Character offset to start reading from (for paging large files). Default: 0.\",\n },\n maxChars: {\n type: \"number\",\n description: `Maximum characters to return when reading. Default: ${DEFAULT_READ_CHARS}. Max: ${MAX_READ_CHARS}.`,\n },\n pattern: {\n type: \"string\",\n description:\n \"Search pattern for grep. Required for grep action. A plain substring by default; set useRegex to true for a regex.\",\n },\n useRegex: {\n type: \"boolean\",\n description:\n \"When true, treat `pattern` as a JavaScript regex (case-insensitive). Default: false.\",\n },\n },\n required: [\"action\"],\n },\n },\n\n run: async (args: Record<string, unknown>): Promise<string> => {\n const scope = resolveScope();\n if (!scope) {\n return \"Error: workspace-files requires an authenticated request context.\";\n }\n\n const action = String(args.action ?? \"\").trim();\n\n try {\n switch (action) {\n case \"write\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for write.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await writeWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"write\",\n path: meta.path,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"append\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for append.\";\n const content = String(args.content ?? \"\");\n const contentType = String(args.contentType ?? \"text/plain\");\n const meta = await appendWorkspaceFile(\n scope,\n path,\n content,\n contentType,\n );\n return JSON.stringify({\n ok: true,\n action: \"append\",\n path: meta.path,\n sizeBytes: meta.sizeBytes,\n updatedAt: meta.updatedAt,\n });\n }\n\n case \"read\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for read.\";\n const rawOffset = Number(args.offset);\n const offset =\n Number.isFinite(rawOffset) && rawOffset > 0 ? rawOffset : 0;\n const rawMax = Number(args.maxChars);\n const maxChars =\n Number.isFinite(rawMax) && rawMax > 0\n ? Math.min(rawMax, MAX_READ_CHARS)\n : DEFAULT_READ_CHARS;\n\n const file = await readWorkspaceFile(scope, path, {\n offset,\n maxChars,\n });\n if (!file) {\n return JSON.stringify({\n ok: false,\n error: `File not found: \"${path}\"`,\n });\n }\n\n const truncated = file.content.length >= maxChars;\n return JSON.stringify({\n ok: true,\n path: file.path,\n contentType: file.contentType,\n sizeBytes: file.sizeBytes,\n updatedAt: file.updatedAt,\n content: file.content,\n ...(truncated\n ? {\n truncated: true,\n nextOffset: offset + file.content.length,\n hint: `File has more content. Call again with offset: ${offset + file.content.length}`,\n }\n : {}),\n });\n }\n\n case \"list\": {\n const prefix = args.path ? String(args.path).trim() : undefined;\n const files = await listWorkspaceFiles(\n scope,\n prefix || undefined,\n );\n return JSON.stringify({\n ok: true,\n count: files.length,\n files: files.map((f) => ({\n path: f.path,\n sizeBytes: f.sizeBytes,\n contentType: f.contentType,\n updatedAt: f.updatedAt,\n })),\n });\n }\n\n case \"delete\": {\n const path = String(args.path ?? \"\").trim();\n if (!path) return \"Error: path is required for delete.\";\n const deleted = await deleteWorkspaceFile(scope, path);\n return JSON.stringify({\n ok: true,\n deleted,\n path,\n });\n }\n\n case \"grep\": {\n const pattern = String(args.pattern ?? \"\").trim();\n if (!pattern) return \"Error: pattern is required for grep.\";\n const prefix = args.path ? String(args.path).trim() : undefined;\n const useRegex =\n args.useRegex === true || String(args.useRegex) === \"true\";\n const matches = await grepWorkspaceFiles(scope, pattern, {\n pathPrefix: prefix || undefined,\n useRegex,\n maxMatchesPerFile: 20,\n maxFiles: 50,\n });\n return JSON.stringify({\n ok: true,\n pattern,\n matchCount: matches.length,\n matches: matches.map((m) => ({\n path: m.path,\n line: m.lineNumber,\n text: m.line,\n })),\n });\n }\n\n default:\n return `Error: unknown action \"${action}\". Valid actions: write, append, read, list, delete, grep.`;\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n return JSON.stringify({ ok: false, error: msg });\n }\n },\n },\n };\n}\n"]}
@@ -306,7 +306,7 @@ export default createAgentChatPlugin({
306
306
  The available modes are:
307
307
 
308
308
  - `off` — the default. No code-execution tools are registered in production.
309
- - `sandboxed` — registers `run-code`, an isolated Node.js JavaScript runner with a scrubbed environment, a fresh temp directory, output/time limits, and a localhost bridge to allowlisted registered tools such as `provider-api-request`, `provider-api-docs`, `provider-api-catalog`, `web-request`, and `workspace-files`.
309
+ - `sandboxed` — registers `run-code`, an isolated Node.js JavaScript runner with a scrubbed environment, a fresh temp directory, output/time limits, and a localhost bridge to allowlisted registered tools such as `provider-api-request`, `provider-api-docs`, `provider-api-catalog`, `web-request`, and the Resources-backed workspace file bridge used by `workspaceRead` / `workspaceWrite`.
310
310
  - `trusted` — registers `run-code` plus the full coding tool registry (`bash`, `read`, `edit`, `write`). Use this only for single-tenant or operator-controlled deployments where full shell access to the host is intentional.
311
311
 
312
312
  Set `AGENT_PROD_CODE_EXECUTION=sandboxed` or `AGENT_PROD_CODE_EXECUTION=trusted` to override the plugin option for a specific deployment without a code change. `AGENT_PROD_CODE_EXECUTION=off` forces code execution off even when the plugin option enables it.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agent-native/core",
3
- "version": "0.49.27",
3
+ "version": "0.50.0",
4
4
  "type": "module",
5
5
  "engines": {
6
6
  "node": ">=22"
@@ -132,6 +132,7 @@
132
132
  "./tailwind": "./dist/tailwind.preset.js",
133
133
  "./styles/agent-native.css": "./dist/styles/agent-native.css",
134
134
  "./agent/engine": "./dist/agent/engine/index.js",
135
+ "./agent/harness": "./dist/agent/harness/index.js",
135
136
  "./tsconfig.base.json": "./tsconfig.base.json"
136
137
  },
137
138
  "sideEffects": [
@@ -0,0 +1,98 @@
1
+ ---
2
+ name: harness-agents
3
+ description: >-
4
+ Add or use full agent harness runtimes like Claude Code, Codex, Pi, Cursor, or Mastra inside Agent Native.
5
+ scope: dev
6
+ ---
7
+
8
+ # Harness Agents
9
+
10
+ ## Rule
11
+
12
+ Full agent harnesses are not `AgentEngine` providers. Use the `AgentHarness`
13
+ substrate in `@agent-native/core/agent/harness`.
14
+
15
+ ## Why
16
+
17
+ `AgentEngine` is for one model round trip beneath `runAgentLoop`. Harnesses like
18
+ Claude Code, Codex, Pi, Cursor, and Mastra own their own loop, workspace,
19
+ native tools, session state, compaction, approval model, and sandbox behavior.
20
+ Putting a harness under `AgentEngine.stream()` double-runs the loop and loses
21
+ session lifecycle semantics.
22
+
23
+ ## How
24
+
25
+ 1. Register or resolve a harness adapter.
26
+
27
+ ```ts
28
+ import {
29
+ registerBuiltinAgentHarnesses,
30
+ resolveAgentHarness,
31
+ } from "@agent-native/core/agent/harness";
32
+
33
+ registerBuiltinAgentHarnesses();
34
+ const harness = resolveAgentHarness("ai-sdk-harness:codex");
35
+ ```
36
+
37
+ 2. Start a turn through the run-manager bridge.
38
+
39
+ ```ts
40
+ import { startAgentHarnessRun } from "@agent-native/core/agent/harness";
41
+
42
+ startAgentHarnessRun({
43
+ runId,
44
+ threadId,
45
+ adapter: harness,
46
+ input: { prompt },
47
+ createSession: {
48
+ sessionId,
49
+ resumeState,
50
+ instructions,
51
+ sandbox,
52
+ permissionMode: "allow-reads",
53
+ },
54
+ ownerEmail,
55
+ orgId,
56
+ });
57
+ ```
58
+
59
+ 3. Persist native session state in SQL.
60
+
61
+ Use `saveAgentHarnessSession`, `updateAgentHarnessSession`, and
62
+ `getLatestAgentHarnessSessionForThread`. The `resumeState` is opaque; Agent
63
+ Native stores it but does not inspect it.
64
+
65
+ 4. Surface runs through background agents.
66
+
67
+ Harness runs are projected into the shared `BackgroundAgentRun` shape with
68
+ `createAgentHarnessBackgroundAgentController()` and are available through the
69
+ existing run routes as `goalId=agent-harness`.
70
+
71
+ ## Adapter Guidance
72
+
73
+ - Keep harness packages optional. Use dynamic imports in adapters and expose an
74
+ install hint through `installPackage`.
75
+ - Use the AI SDK harness adapter as one implementation, not as Agent Native's
76
+ public abstraction.
77
+ - For bridge-backed coding harnesses, require a real sandbox/workspace provider.
78
+ Do not run arbitrary coding agents in the host process by default.
79
+ - Pass only a narrow, intentional set of Agent Native actions as host tools.
80
+ Preserve `defineAction` auth, request context, timeouts, truncation, and
81
+ read-only metadata.
82
+
83
+ ## Don't
84
+
85
+ - Don't add Claude Code, Codex, Cursor, Mastra, or Pi as an `AgentEngine`.
86
+ - Don't replay full Agent Native chat history into a native harness each turn.
87
+ Resume the harness session instead.
88
+ - Don't store resume state in `application_state`; it belongs in the harness
89
+ session SQL table.
90
+ - Don't expose every app action to every harness session by default.
91
+
92
+ ## Related Skills
93
+
94
+ - `adding-a-feature` — feature parity across UI/actions/instructions/state.
95
+ - `delegate-to-agent` — background agents use run-manager infrastructure.
96
+ - `external-agents` — expose openable resources and external-agent surfaces.
97
+ - `storing-data` — durable SQL state and additive schema changes.
98
+
@@ -1,195 +0,0 @@
1
- /**
2
- * SQL schema for workspace_files — durable scratch storage for the agent.
3
- *
4
- * Files are scoped to either a user (scope="user", scope_id=email) or a
5
- * workspace / org (scope="org", scope_id=orgId), mirroring the secrets table
6
- * pattern. Paths are unique per scope+scope_id pair and may include path
7
- * separators (e.g. "analysis/2026-q2/step1.md").
8
- *
9
- * Size limits:
10
- * - Per-file content: 2 MB (enforced in the store layer).
11
- * - Per-scope total: 200 MB (enforced in the store layer).
12
- */
13
- export declare const workspaceFiles: import("drizzle-orm/sqlite-core").SQLiteTableWithColumns<{
14
- name: "workspace_files";
15
- schema: undefined;
16
- columns: {
17
- id: import("drizzle-orm/sqlite-core").SQLiteColumn<{
18
- name: "id";
19
- tableName: "workspace_files";
20
- dataType: "string";
21
- columnType: "SQLiteText";
22
- data: string;
23
- driverParam: string;
24
- notNull: true;
25
- hasDefault: false;
26
- isPrimaryKey: true;
27
- isAutoincrement: false;
28
- hasRuntimeDefault: false;
29
- enumValues: [string, ...string[]];
30
- baseColumn: never;
31
- identity: undefined;
32
- generated: undefined;
33
- }, {}, {
34
- length: number;
35
- }>;
36
- scope: import("drizzle-orm/sqlite-core").SQLiteColumn<{
37
- name: "scope";
38
- tableName: "workspace_files";
39
- dataType: "string";
40
- columnType: "SQLiteText";
41
- data: string;
42
- driverParam: string;
43
- notNull: true;
44
- hasDefault: false;
45
- isPrimaryKey: false;
46
- isAutoincrement: false;
47
- hasRuntimeDefault: false;
48
- enumValues: [string, ...string[]];
49
- baseColumn: never;
50
- identity: undefined;
51
- generated: undefined;
52
- }, {}, {
53
- length: number;
54
- }>;
55
- scopeId: import("drizzle-orm/sqlite-core").SQLiteColumn<{
56
- name: "scope_id";
57
- tableName: "workspace_files";
58
- dataType: "string";
59
- columnType: "SQLiteText";
60
- data: string;
61
- driverParam: string;
62
- notNull: true;
63
- hasDefault: false;
64
- isPrimaryKey: false;
65
- isAutoincrement: false;
66
- hasRuntimeDefault: false;
67
- enumValues: [string, ...string[]];
68
- baseColumn: never;
69
- identity: undefined;
70
- generated: undefined;
71
- }, {}, {
72
- length: number;
73
- }>;
74
- path: import("drizzle-orm/sqlite-core").SQLiteColumn<{
75
- name: "path";
76
- tableName: "workspace_files";
77
- dataType: "string";
78
- columnType: "SQLiteText";
79
- data: string;
80
- driverParam: string;
81
- notNull: true;
82
- hasDefault: false;
83
- isPrimaryKey: false;
84
- isAutoincrement: false;
85
- hasRuntimeDefault: false;
86
- enumValues: [string, ...string[]];
87
- baseColumn: never;
88
- identity: undefined;
89
- generated: undefined;
90
- }, {}, {
91
- length: number;
92
- }>;
93
- content: import("drizzle-orm/sqlite-core").SQLiteColumn<{
94
- name: "content";
95
- tableName: "workspace_files";
96
- dataType: "string";
97
- columnType: "SQLiteText";
98
- data: string;
99
- driverParam: string;
100
- notNull: true;
101
- hasDefault: true;
102
- isPrimaryKey: false;
103
- isAutoincrement: false;
104
- hasRuntimeDefault: false;
105
- enumValues: [string, ...string[]];
106
- baseColumn: never;
107
- identity: undefined;
108
- generated: undefined;
109
- }, {}, {
110
- length: number;
111
- }>;
112
- contentType: import("drizzle-orm/sqlite-core").SQLiteColumn<{
113
- name: "content_type";
114
- tableName: "workspace_files";
115
- dataType: "string";
116
- columnType: "SQLiteText";
117
- data: string;
118
- driverParam: string;
119
- notNull: true;
120
- hasDefault: true;
121
- isPrimaryKey: false;
122
- isAutoincrement: false;
123
- hasRuntimeDefault: false;
124
- enumValues: [string, ...string[]];
125
- baseColumn: never;
126
- identity: undefined;
127
- generated: undefined;
128
- }, {}, {
129
- length: number;
130
- }>;
131
- sizeBytes: import("drizzle-orm/sqlite-core").SQLiteColumn<{
132
- name: "size_bytes";
133
- tableName: "workspace_files";
134
- dataType: "number";
135
- columnType: "SQLiteInteger";
136
- data: number;
137
- driverParam: number;
138
- notNull: true;
139
- hasDefault: true;
140
- isPrimaryKey: false;
141
- isAutoincrement: false;
142
- hasRuntimeDefault: false;
143
- enumValues: undefined;
144
- baseColumn: never;
145
- identity: undefined;
146
- generated: undefined;
147
- }, {}, {}>;
148
- createdAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
149
- name: "created_at";
150
- tableName: "workspace_files";
151
- dataType: "string";
152
- columnType: "SQLiteText";
153
- data: string;
154
- driverParam: string;
155
- notNull: true;
156
- hasDefault: false;
157
- isPrimaryKey: false;
158
- isAutoincrement: false;
159
- hasRuntimeDefault: false;
160
- enumValues: [string, ...string[]];
161
- baseColumn: never;
162
- identity: undefined;
163
- generated: undefined;
164
- }, {}, {
165
- length: number;
166
- }>;
167
- updatedAt: import("drizzle-orm/sqlite-core").SQLiteColumn<{
168
- name: "updated_at";
169
- tableName: "workspace_files";
170
- dataType: "string";
171
- columnType: "SQLiteText";
172
- data: string;
173
- driverParam: string;
174
- notNull: true;
175
- hasDefault: false;
176
- isPrimaryKey: false;
177
- isAutoincrement: false;
178
- hasRuntimeDefault: false;
179
- enumValues: [string, ...string[]];
180
- baseColumn: never;
181
- identity: undefined;
182
- generated: undefined;
183
- }, {}, {
184
- length: number;
185
- }>;
186
- };
187
- dialect: "sqlite";
188
- }>;
189
- /**
190
- * Raw CREATE TABLE SQL used by the on-demand migration path.
191
- * Written for SQLite; the migration runner adapts it for Postgres.
192
- */
193
- export declare const WORKSPACE_FILES_CREATE_SQL = "CREATE TABLE IF NOT EXISTS workspace_files (\n id TEXT PRIMARY KEY,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL,\n path TEXT NOT NULL,\n content TEXT NOT NULL DEFAULT '',\n content_type TEXT NOT NULL DEFAULT 'text/plain',\n size_bytes INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(scope, scope_id, path)\n)";
194
- export declare const WORKSPACE_FILES_INDEX_SQL = "CREATE INDEX IF NOT EXISTS workspace_files_scope_idx ON workspace_files (scope, scope_id, updated_at)";
195
- //# sourceMappingURL=schema.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/workspace-files/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,eAAO,MAAM,cAAc;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAgBzB,CAAC;AAEH;;;GAGG;AACH,eAAO,MAAM,0BAA0B,oXAWrC,CAAC;AAEH,eAAO,MAAM,yBAAyB,0GAA0G,CAAC"}
@@ -1,48 +0,0 @@
1
- /**
2
- * SQL schema for workspace_files — durable scratch storage for the agent.
3
- *
4
- * Files are scoped to either a user (scope="user", scope_id=email) or a
5
- * workspace / org (scope="org", scope_id=orgId), mirroring the secrets table
6
- * pattern. Paths are unique per scope+scope_id pair and may include path
7
- * separators (e.g. "analysis/2026-q2/step1.md").
8
- *
9
- * Size limits:
10
- * - Per-file content: 2 MB (enforced in the store layer).
11
- * - Per-scope total: 200 MB (enforced in the store layer).
12
- */
13
- import { table, text, integer } from "../db/schema.js";
14
- export const workspaceFiles = table("workspace_files", {
15
- id: text("id").primaryKey(),
16
- /** "user" or "org" */
17
- scope: text("scope").notNull(),
18
- /** Email for user-scope; orgId for org-scope. */
19
- scopeId: text("scope_id").notNull(),
20
- /** Relative path within the scope, e.g. "memos/q2.md". Unique per scope+scopeId. */
21
- path: text("path").notNull(),
22
- /** File content (text). */
23
- content: text("content").notNull().default(""),
24
- /** MIME type, e.g. "text/plain", "application/json". */
25
- contentType: text("content_type").notNull().default("text/plain"),
26
- /** Byte length of content (utf-8). */
27
- sizeBytes: integer("size_bytes").notNull().default(0),
28
- createdAt: text("created_at").notNull(),
29
- updatedAt: text("updated_at").notNull(),
30
- });
31
- /**
32
- * Raw CREATE TABLE SQL used by the on-demand migration path.
33
- * Written for SQLite; the migration runner adapts it for Postgres.
34
- */
35
- export const WORKSPACE_FILES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS workspace_files (
36
- id TEXT PRIMARY KEY,
37
- scope TEXT NOT NULL,
38
- scope_id TEXT NOT NULL,
39
- path TEXT NOT NULL,
40
- content TEXT NOT NULL DEFAULT '',
41
- content_type TEXT NOT NULL DEFAULT 'text/plain',
42
- size_bytes INTEGER NOT NULL DEFAULT 0,
43
- created_at TEXT NOT NULL,
44
- updated_at TEXT NOT NULL,
45
- UNIQUE(scope, scope_id, path)
46
- )`;
47
- export const WORKSPACE_FILES_INDEX_SQL = `CREATE INDEX IF NOT EXISTS workspace_files_scope_idx ON workspace_files (scope, scope_id, updated_at)`;
48
- //# sourceMappingURL=schema.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/workspace-files/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAEvD,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,CAAC,iBAAiB,EAAE;IACrD,EAAE,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC,UAAU,EAAE;IAC3B,sBAAsB;IACtB,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE;IAC9B,iDAAiD;IACjD,OAAO,EAAE,IAAI,CAAC,UAAU,CAAC,CAAC,OAAO,EAAE;IACnC,oFAAoF;IACpF,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC,OAAO,EAAE;IAC5B,2BAA2B;IAC3B,OAAO,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC;IAC9C,wDAAwD;IACxD,WAAW,EAAE,IAAI,CAAC,cAAc,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,YAAY,CAAC;IACjE,sCAAsC;IACtC,SAAS,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACrD,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;IACvC,SAAS,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC,OAAO,EAAE;CACxC,CAAC,CAAC;AAEH;;;GAGG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG;;;;;;;;;;;EAWxC,CAAC;AAEH,MAAM,CAAC,MAAM,yBAAyB,GAAG,uGAAuG,CAAC","sourcesContent":["/**\n * SQL schema for workspace_files — durable scratch storage for the agent.\n *\n * Files are scoped to either a user (scope=\"user\", scope_id=email) or a\n * workspace / org (scope=\"org\", scope_id=orgId), mirroring the secrets table\n * pattern. Paths are unique per scope+scope_id pair and may include path\n * separators (e.g. \"analysis/2026-q2/step1.md\").\n *\n * Size limits:\n * - Per-file content: 2 MB (enforced in the store layer).\n * - Per-scope total: 200 MB (enforced in the store layer).\n */\n\nimport { table, text, integer } from \"../db/schema.js\";\n\nexport const workspaceFiles = table(\"workspace_files\", {\n id: text(\"id\").primaryKey(),\n /** \"user\" or \"org\" */\n scope: text(\"scope\").notNull(),\n /** Email for user-scope; orgId for org-scope. */\n scopeId: text(\"scope_id\").notNull(),\n /** Relative path within the scope, e.g. \"memos/q2.md\". Unique per scope+scopeId. */\n path: text(\"path\").notNull(),\n /** File content (text). */\n content: text(\"content\").notNull().default(\"\"),\n /** MIME type, e.g. \"text/plain\", \"application/json\". */\n contentType: text(\"content_type\").notNull().default(\"text/plain\"),\n /** Byte length of content (utf-8). */\n sizeBytes: integer(\"size_bytes\").notNull().default(0),\n createdAt: text(\"created_at\").notNull(),\n updatedAt: text(\"updated_at\").notNull(),\n});\n\n/**\n * Raw CREATE TABLE SQL used by the on-demand migration path.\n * Written for SQLite; the migration runner adapts it for Postgres.\n */\nexport const WORKSPACE_FILES_CREATE_SQL = `CREATE TABLE IF NOT EXISTS workspace_files (\n id TEXT PRIMARY KEY,\n scope TEXT NOT NULL,\n scope_id TEXT NOT NULL,\n path TEXT NOT NULL,\n content TEXT NOT NULL DEFAULT '',\n content_type TEXT NOT NULL DEFAULT 'text/plain',\n size_bytes INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n updated_at TEXT NOT NULL,\n UNIQUE(scope, scope_id, path)\n)`;\n\nexport const WORKSPACE_FILES_INDEX_SQL = `CREATE INDEX IF NOT EXISTS workspace_files_scope_idx ON workspace_files (scope, scope_id, updated_at)`;\n"]}