@agentprojectcontext/apx 1.8.1 → 1.8.2

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentprojectcontext/apx",
3
- "version": "1.8.1",
3
+ "version": "1.8.2",
4
4
  "description": "APX — unified CLI + daemon for the Agent Project Context (APC) standard.",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -26,13 +26,15 @@ export async function cmdRoutineList(args = {}) {
26
26
  const pid = await resolveProjectId(args?.flags?.project);
27
27
  const rows = await http.get(`/projects/${pid}/routines`);
28
28
  if (rows.length === 0) {
29
- console.log("(no routines)");
29
+ console.log(`(no routines in project #${pid})`);
30
30
  return;
31
31
  }
32
- console.log("NAME".padEnd(20) + " EN " + "KIND".padEnd(11) + " SCHEDULE".padEnd(20) + " NEXT_RUN".padEnd(22) + " LAST");
32
+ // Show project ID in header so user knows which project's routines are displayed.
33
+ console.log(`project #${pid} routines:`);
34
+ console.log("NAME".padEnd(22) + " EN " + "KIND".padEnd(11) + " SCHEDULE".padEnd(20) + " NEXT_RUN".padEnd(22) + " LAST");
33
35
  for (const r of rows) {
34
36
  console.log(
35
- r.name.padEnd(20) + " " +
37
+ r.name.padEnd(22) + " " +
36
38
  (r.enabled ? "✓" : "✗").padEnd(2) + " " +
37
39
  (r.kind || "?").padEnd(10) + " " +
38
40
  (r.schedule || "?").padEnd(20) + " " +
@@ -6,8 +6,9 @@ import path from "node:path";
6
6
  const nowIso = () => new Date().toISOString().replace(/\.\d{3}Z$/, "Z");
7
7
  const isoToMs = (iso) => (iso ? Date.parse(iso) : 0);
8
8
 
9
- function routinesPath(projectPath) {
10
- return path.join(projectPath, ".apc", "routines.json");
9
+ function routinesPath(storagePath) {
10
+ // storagePath is always ~/.apx/projects/{apxId}/ — flat, no .apc subdir needed.
11
+ return path.join(storagePath, "routines.json");
11
12
  }
12
13
 
13
14
  function readFile(projectPath) {
package/src/daemon/api.js CHANGED
@@ -797,13 +797,13 @@ export function buildApi({ projects, registries, plugins, scheduler, version, st
797
797
  app.get("/projects/:pid/routines", (req, res) => {
798
798
  const p = project(req, res);
799
799
  if (!p) return;
800
- res.json(listRoutines(p.path));
800
+ res.json(listRoutines(p.storagePath));
801
801
  });
802
802
 
803
803
  app.get("/projects/:pid/routines/:name", (req, res) => {
804
804
  const p = project(req, res);
805
805
  if (!p) return;
806
- const r = getRoutine(p.path, req.params.name);
806
+ const r = getRoutine(p.storagePath, req.params.name);
807
807
  if (!r) return res.status(404).json({ error: "routine not found" });
808
808
  res.json(r);
809
809
  });
@@ -812,7 +812,7 @@ export function buildApi({ projects, registries, plugins, scheduler, version, st
812
812
  const p = project(req, res);
813
813
  if (!p) return;
814
814
  try {
815
- const r = upsertRoutine(p.path, req.body || {});
815
+ const r = upsertRoutine(p.storagePath, req.body || {});
816
816
  res.status(201).json(r);
817
817
  } catch (e) {
818
818
  res.status(400).json({ error: e.message });
@@ -822,28 +822,28 @@ export function buildApi({ projects, registries, plugins, scheduler, version, st
822
822
  app.delete("/projects/:pid/routines/:name", (req, res) => {
823
823
  const p = project(req, res);
824
824
  if (!p) return;
825
- const ok = deleteRoutine(p.path, req.params.name);
825
+ const ok = deleteRoutine(p.storagePath, req.params.name);
826
826
  res.status(ok ? 204 : 404).end();
827
827
  });
828
828
 
829
829
  app.post("/projects/:pid/routines/:name/enable", (req, res) => {
830
830
  const p = project(req, res);
831
831
  if (!p) return;
832
- setRoutineEnabled(p.path, req.params.name, true);
832
+ setRoutineEnabled(p.storagePath, req.params.name, true);
833
833
  res.json({ ok: true });
834
834
  });
835
835
 
836
836
  app.post("/projects/:pid/routines/:name/disable", (req, res) => {
837
837
  const p = project(req, res);
838
838
  if (!p) return;
839
- setRoutineEnabled(p.path, req.params.name, false);
839
+ setRoutineEnabled(p.storagePath, req.params.name, false);
840
840
  res.json({ ok: true });
841
841
  });
842
842
 
843
843
  app.post("/projects/:pid/routines/:name/run", async (req, res) => {
844
844
  const p = project(req, res);
845
845
  if (!p) return;
846
- const r = getRoutine(p.path, req.params.name);
846
+ const r = getRoutine(p.storagePath, req.params.name);
847
847
  if (!r) return res.status(404).json({ error: "routine not found" });
848
848
  try {
849
849
  const result = await runRoutineNow({ project: p, projects, plugins, registries, globalConfig: config }, r);
@@ -191,7 +191,7 @@ export async function runRoutineNow(ctx, routine) {
191
191
  const lastRun = nowIso();
192
192
  const next = computeNextRun({ schedule: routine.schedule, last_run_at: lastRun });
193
193
  const isOnce = parseSchedule(routine.schedule).kind === "once";
194
- updateRunState(ctx.project.path, routine.name, {
194
+ updateRunState(ctx.project.storagePath, routine.name, {
195
195
  last_run_at: lastRun,
196
196
  last_status: status,
197
197
  last_error: errMsg,
@@ -246,7 +246,7 @@ export class RoutineScheduler {
246
246
  const nowStr = nowIso();
247
247
  for (const proj of this.projects.list().map((p) => this.projects.get(p.id))) {
248
248
  if (!proj) continue;
249
- const due = getDueRoutines(proj.path, nowStr);
249
+ const due = getDueRoutines(proj.storagePath, nowStr);
250
250
  for (const r of due) {
251
251
  this.log(`routine ${r.name} (${r.kind}) firing in project #${proj.id}`);
252
252
  await runRoutineNow(
@@ -71,7 +71,8 @@ HARD RULES (do not deviate):
71
71
  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
72
  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
73
  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.`;
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.
75
+ 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
76
 
76
77
  function isShortConfirmation(text) {
77
78
  return /^(yes|y|si|si dale|dale|ok|okay|confirm|confirmed|go|proceed|do it)\b/i