@agentprojectcontext/apx 1.8.1 → 1.9.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.
@@ -0,0 +1,66 @@
1
+ import { execFile } from "node:child_process";
2
+ import { promisify } from "node:util";
3
+ import { resolveProject, safePathJoin } from "../helpers.js";
4
+
5
+ const execFileAsync = promisify(execFile);
6
+
7
+ export default {
8
+ name: "search_files",
9
+ schema: {
10
+ type: "function",
11
+ function: {
12
+ name: "search_files",
13
+ description: "Search for text patterns inside project files using ripgrep or grep.",
14
+ parameters: {
15
+ type: "object",
16
+ properties: {
17
+ query: { type: "string", description: "The text or regex pattern to search for." },
18
+ project: { type: "string" },
19
+ path: { type: "string", description: "relative path inside the project to restrict search; default '.'" },
20
+ },
21
+ required: ["query"],
22
+ },
23
+ },
24
+ },
25
+ makeHandler: ({ projects, requirePermission }) => async ({ query, project, path: sub = "." } = {}) => {
26
+ // Optional permission check if it's considered destructive, but search is safe read-only
27
+ await requirePermission("search_files", { query, project, path: sub }, "safe");
28
+
29
+ const p = resolveProject(projects, project);
30
+ const target = safePathJoin(p.path, sub);
31
+
32
+ try {
33
+ const { stdout } = await execFileAsync("rg", ["-n", "--no-heading", "--color=never", query, target], {
34
+ cwd: p.path,
35
+ maxBuffer: 5 * 1024 * 1024,
36
+ });
37
+ return formatResults(stdout);
38
+ } catch (e) {
39
+ if (e.code === "ENOENT" || e.message.includes("ENOENT")) {
40
+ try {
41
+ const { stdout } = await execFileAsync("grep", ["-rn", query, target], {
42
+ cwd: p.path,
43
+ maxBuffer: 5 * 1024 * 1024,
44
+ });
45
+ return formatResults(stdout);
46
+ } catch (e2) {
47
+ if (e2.code === 1) return { result: "No matches found." };
48
+ throw new Error(`grep failed: ${e2.message}`);
49
+ }
50
+ }
51
+ if (e.code === 1) return { result: "No matches found." };
52
+ return { error: `search failed: ${e.message}` };
53
+ }
54
+ },
55
+ };
56
+
57
+ function formatResults(stdout) {
58
+ if (!stdout) return { result: "No matches found." };
59
+ const lines = stdout.split('\n').slice(0, 100);
60
+ const out = lines.join('\n');
61
+ if (lines.length >= 100) {
62
+ return { result: out + '\n...(truncated)' };
63
+ }
64
+ return { result: out };
65
+ }
66
+
@@ -34,6 +34,7 @@ Useful CLI facts:
34
34
  - Permission mode: apx permission show; apx permission set total|automatico|permiso.
35
35
  - Routines: apx routine list|get|history|run|add. Autonomous super-agent routines use kind super_agent.
36
36
  - Routine design: if the user asks for an agent to think, decide, write, or reply, create an exec_agent routine with spec.agent and spec.prompt. If the user asks APX itself to orchestrate tools or Telegram, create a super_agent routine. If the request is only a deterministic command, create a shell routine. If unclear, ask one short question: "agent routine or simple command routine?"
37
+ - Routine schedules: APX supports standard cron expressions (e.g. '*/5 * * * *'), OR 'every:<number><s|m|h|d>' (e.g. 'every:60s'), OR 'once:<iso-8601>'.
37
38
  - Safe read-only shell checks such as apx --help, apx routine list, docker ps, find, ls, rg, grep can run in automatico without asking.
38
39
 
39
40
  Channel context:
@@ -42,20 +43,6 @@ Channel context:
42
43
 
43
44
  You HAVE tools. THE FIRST THING you do for any factual question is call a tool. Do not ask the user to specify a project unless the tool itself fails.
44
45
 
45
- Available tools:
46
- - list_projects, list_agents, list_mcps — discovery (call WITHOUT project to get all of them across every registered project; specify project only to filter)
47
- - list_vault_agents, import_agent, add_project — inspect the agent vault, install a vault agent into a project, register an APC project
48
- - read_agent_memory — what an agent knows
49
- - list_files, read_file, write_file, edit_file — inspect/create/edit files in default or a project
50
- - run_shell — execute shell commands in default or a project
51
- - tail_messages, search_messages — see history
52
- - call_agent — delegate to a project agent
53
- - call_mcp — call an installed MCP tool when MCP is the right protocol
54
- - call_runtime — spawn a separate claude-code/codex/opencode/aider session when the user wants an external runtime/chat
55
- - send_telegram — send a message
56
- - set_identity — update agent name, personality, owner, language (persists to disk)
57
- - set_permission_mode — set total/automatico/permiso in ~/.apx/config.json
58
-
59
46
  HARD RULES (do not deviate):
60
47
  1. NEVER invent project names, agent slugs, model ids, MCP names or paths. ALWAYS look them up via list_* first.
61
48
  2. If the user asks for agents, lists, inventory, or "what exists" without specifying a project, that means **all of them** — call the tool WITHOUT a project argument and the result will include every project.
@@ -66,12 +53,13 @@ HARD RULES (do not deviate):
66
53
  7. Stay brief: under 6 sentences unless asked for detail.
67
54
  8. You DO see recent prior turns of this chat as previous messages when applicable. **Use them ONLY to disambiguate references** (e.g. "el primero" → first project mentioned earlier). For ANY factual data — agent details, MCP details, file contents, memory — RE-CALL the tool. Past turns are context, not a cache. Models change, agents change, files change.
68
55
  9. /reset or /new from the user means "forget previous turns and answer this one fresh" — if you see those prefixes the operator already cleared the context for you.
69
- 10. ACTION RULE: use direct tools for direct work. run_shell executes commands; write_file/edit_file modify files. call_runtime is only for spawning a separate external runtime/chat. call_mcp is only for an MCP server/tool.
70
- 11. DISPATCH RULE: when the user asks a named agent to work inside Claude, Codex, OpenCode, or Aider, that is a call_runtime request. Look up the agent slug with list_agents if needed, then call call_runtime({agent: <slug>, runtime: 'claude-code'|'codex'|'opencode'|'aider', prompt: <user's request>}). The agent's declared model (in AGENTS.md) is IGNORED in this case; the runtime supplies the model. Memory + skills of the agent become the system prompt of the runtime.
56
+ 10. DELEGATION RULE: when the user asks an agent to do a task, use call_agent (unless they specify opening it in a runtime, then see rule 11).
57
+ 11. DISPATCH RULE: when the user asks to work inside Claude, Codex, OpenCode, or Aider, use call_runtime({runtime: 'claude-code'|'codex'|'opencode'|'aider', prompt: <user's request>}). If they explicitly name an agent to spawn, pass agent: <slug>. If they don't name an agent, DO NOT pass an agent argument. When an agent is passed, its memory + skills become the system prompt of the runtime.
71
58
  12. PROJECT RULE: when the user gives no project, use project "default". Do not infer a non-default project from old chat history unless the user references it. If they mention a path or project name, look it up or add it with add_project.
72
59
  13. VAULT RULE: when the user wants a new existing agent/template, call list_vault_agents first. If a suitable vault agent exists, import_agent into the chosen project. If none fits, say briefly what is missing.
73
60
  14. NO-PENDING RULE: never say "give me a second", "I will do it", or "I will try later" as a final answer. Either call the tool in this same turn or say what blocks you.
74
- 15. IDENTITY RULE: when the user asks you to change your name, call yourself something, or update your personality/language, call set_identity and persist the change. Then confirm with your new name.`;
61
+ 15. IDENTITY RULE: when the user asks you to change your name, call yourself something, or update your personality/language, call set_identity and persist the change. Then confirm with your new name.
62
+ 16. ROUTINES RULE: NEVER create a routine in the default project (id=0). Routines MUST be tied to a specific registered project. Before adding a routine, call list_projects to find the correct project id or name. Then pass --project <id|name> to apx routine add. If no project fits, ask the user which project to use. Creating routines in project 0/default mixes unrelated projects' schedules and corrupts state.`;
75
63
 
76
64
  function isShortConfirmation(text) {
77
65
  return /^(yes|y|si|si dale|dale|ok|okay|confirm|confirmed|go|proceed|do it)\b/i
@@ -98,11 +86,13 @@ export async function runSuperAgent({
98
86
  prompt,
99
87
  contextNote = "",
100
88
  previousMessages = [],
89
+ overrideModel = null,
101
90
  }) {
102
91
  if (!isSuperAgentEnabled(globalConfig)) {
103
92
  throw new Error("super-agent not enabled (set super_agent.enabled and .model in ~/.apx/config.json)");
104
93
  }
105
94
  const sa = globalConfig.super_agent;
95
+ const activeModel = overrideModel || sa.model;
106
96
 
107
97
  // Tiny project hint — JUST names + ids, no detail. The model is expected to
108
98
  // call list_agents / list_mcps / read_agent_memory / etc. for everything
@@ -152,7 +142,7 @@ export async function runSuperAgent({
152
142
 
153
143
  for (let iter = 0; iter < MAX_TOOL_ITERS; iter++) {
154
144
  const result = await callEngine({
155
- modelId: sa.model,
145
+ modelId: activeModel,
156
146
  system,
157
147
  messages: conversation,
158
148
  config: globalConfig,