@agentprojectcontext/apx 1.15.2 → 1.15.4
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
|
@@ -65,12 +65,14 @@ export async function cmdIdentity(args) {
|
|
|
65
65
|
console.log("No identity configured. Run: apx identity wizard");
|
|
66
66
|
return;
|
|
67
67
|
}
|
|
68
|
+
const { readConfig } = await import("../../core/config.js");
|
|
69
|
+
const cfg = readConfig();
|
|
68
70
|
console.log("");
|
|
69
71
|
console.log(` Agent name : ${id.agent_name}`);
|
|
70
72
|
console.log(` Personality : ${id.personality || "(not set)"}`);
|
|
71
73
|
console.log(` Owner : ${id.owner_name}`);
|
|
72
74
|
console.log(` Context : ${id.owner_context || "(not set)"}`);
|
|
73
|
-
console.log(` Language : ${
|
|
75
|
+
console.log(` Language : ${cfg.user?.language || "en"} (set via: apx config set user.language <code>)`);
|
|
74
76
|
console.log(` Last wakeup : ${id.last_wakeup || "(never)"}`);
|
|
75
77
|
console.log(` File : ~/.apx/identity.json`);
|
|
76
78
|
console.log("");
|
|
@@ -113,14 +115,14 @@ export async function runWizard() {
|
|
|
113
115
|
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
114
116
|
|
|
115
117
|
console.log("\n APX Identity Setup\n");
|
|
116
|
-
console.log("
|
|
117
|
-
console.log("
|
|
118
|
+
console.log(" Defines who the agent is, who it works for, and what extra context");
|
|
119
|
+
console.log(" it carries in every conversation (injected into the system prompt).");
|
|
120
|
+
console.log(" Language is configured separately via: apx config set user.language <code>\n");
|
|
118
121
|
|
|
119
122
|
const agent_name = await ask(rl, " Agent name", existing.agent_name || "APX");
|
|
120
123
|
const personality = await ask(rl, " Personality (comma-separated traits)", existing.personality || "direct, curious, helpful");
|
|
121
124
|
const owner_name = await ask(rl, " Your name", existing.owner_name || "");
|
|
122
|
-
const owner_context = await ask(rl, "
|
|
123
|
-
const language = await ask(rl, " Language for agent messages (e.g. Spanish, English)", existing.language || "English");
|
|
125
|
+
const owner_context = await ask(rl, " Context for the agent (what you build / work on — added to every system prompt)", existing.owner_context || "");
|
|
124
126
|
|
|
125
127
|
console.log("\n Claude Code permissions");
|
|
126
128
|
console.log(" APX can configure Claude Code to allow terminal commands without prompts.");
|
|
@@ -130,7 +132,7 @@ export async function runWizard() {
|
|
|
130
132
|
|
|
131
133
|
rl.close();
|
|
132
134
|
|
|
133
|
-
const id = writeIdentity({ agent_name, personality, owner_name, owner_context,
|
|
135
|
+
const id = writeIdentity({ agent_name, personality, owner_name, owner_context, last_wakeup: null });
|
|
134
136
|
console.log(`\n Identity saved to ~/.apx/identity.json`);
|
|
135
137
|
|
|
136
138
|
if (setupPerms) {
|
|
@@ -4,6 +4,29 @@ import { getLatestVersion } from "../../core/update-check.js";
|
|
|
4
4
|
|
|
5
5
|
const PACKAGE_NAME = "@agentprojectcontext/apx";
|
|
6
6
|
|
|
7
|
+
function isNewer(cur, lat) {
|
|
8
|
+
const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
9
|
+
const [ma, mi, pa] = parse(cur);
|
|
10
|
+
const [mb, mib, pb] = parse(lat);
|
|
11
|
+
if (mb > ma) return true;
|
|
12
|
+
if (mb === ma && mib > mi) return true;
|
|
13
|
+
if (mb === ma && mib === mi && pb > pa) return true;
|
|
14
|
+
return false;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
function hasPnpmGlobal() {
|
|
18
|
+
const r = spawnSync("pnpm", ["--version"], { encoding: "utf8", stdio: "pipe" });
|
|
19
|
+
if (r.status !== 0) return false;
|
|
20
|
+
// pnpm needs PNPM_HOME configured to manage global packages
|
|
21
|
+
const check = spawnSync("pnpm", ["root", "-g"], { encoding: "utf8", stdio: "pipe" });
|
|
22
|
+
return check.status === 0 && !!check.stdout?.trim();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function daemonRunning() {
|
|
26
|
+
const r = spawnSync("apx", ["daemon", "status", "--json"], { encoding: "utf8", stdio: "pipe" });
|
|
27
|
+
try { return JSON.parse(r.stdout)?.running === true; } catch { return false; }
|
|
28
|
+
}
|
|
29
|
+
|
|
7
30
|
export async function cmdUpdate(args, currentVersion) {
|
|
8
31
|
const force = args.flags.force || args.flags.yes || args.flags.y;
|
|
9
32
|
|
|
@@ -15,24 +38,12 @@ export async function cmdUpdate(args, currentVersion) {
|
|
|
15
38
|
process.exit(1);
|
|
16
39
|
}
|
|
17
40
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
function isNewer(cur, lat) {
|
|
21
|
-
const parse = (v) => v.replace(/^v/, "").split(".").map(Number);
|
|
22
|
-
const [ma, mi, pa] = parse(cur);
|
|
23
|
-
const [mb, mib, pb] = parse(lat);
|
|
24
|
-
if (mb > ma) return true;
|
|
25
|
-
if (mb === ma && mib > mi) return true;
|
|
26
|
-
if (mb === ma && mib === mi && pb > pa) return true;
|
|
27
|
-
return false;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
if (!isNewer(current, latest)) {
|
|
31
|
-
console.log(`✅ Already up to date (${current})`);
|
|
41
|
+
if (!isNewer(currentVersion, latest)) {
|
|
42
|
+
console.log(`✅ Already up to date (${currentVersion})`);
|
|
32
43
|
return;
|
|
33
44
|
}
|
|
34
45
|
|
|
35
|
-
console.log(`\n Current: ${
|
|
46
|
+
console.log(`\n Current: ${currentVersion}`);
|
|
36
47
|
console.log(` Latest: ${latest}`);
|
|
37
48
|
|
|
38
49
|
if (!force) {
|
|
@@ -43,20 +54,41 @@ export async function cmdUpdate(args, currentVersion) {
|
|
|
43
54
|
}
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
{ stdio: "inherit" }
|
|
51
|
-
|
|
57
|
+
// Stop daemon before replacing the binary so Node doesn't lock files on Windows.
|
|
58
|
+
const wasDaemonRunning = daemonRunning();
|
|
59
|
+
if (wasDaemonRunning) {
|
|
60
|
+
process.stdout.write("\nStopping daemon... ");
|
|
61
|
+
spawnSync("apx", ["daemon", "stop"], { stdio: "inherit" });
|
|
62
|
+
console.log("stopped.");
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
// Prefer pnpm global if configured, fall back to npm.
|
|
66
|
+
const usePnpm = hasPnpmGlobal();
|
|
67
|
+
const pm = usePnpm ? "pnpm" : "npm";
|
|
68
|
+
const installArgs = usePnpm
|
|
69
|
+
? ["add", "-g", `${PACKAGE_NAME}@${latest}`]
|
|
70
|
+
: ["install", "-g", `${PACKAGE_NAME}@${latest}`];
|
|
71
|
+
|
|
72
|
+
console.log(`\nInstalling ${PACKAGE_NAME}@${latest} via ${pm}...\n`);
|
|
73
|
+
const result = spawnSync(pm, installArgs, { stdio: "inherit" });
|
|
52
74
|
|
|
53
75
|
if (result.status !== 0) {
|
|
54
76
|
console.error(`\n❌ Update failed (exit ${result.status})`);
|
|
77
|
+
if (wasDaemonRunning) {
|
|
78
|
+
console.log("Restarting daemon with old version...");
|
|
79
|
+
spawnSync("apx", ["daemon", "start"], { stdio: "inherit" });
|
|
80
|
+
}
|
|
55
81
|
process.exit(result.status || 1);
|
|
56
82
|
}
|
|
57
83
|
|
|
58
|
-
|
|
59
|
-
|
|
84
|
+
// Restart daemon with new version.
|
|
85
|
+
if (wasDaemonRunning) {
|
|
86
|
+
process.stdout.write("\nStarting daemon... ");
|
|
87
|
+
spawnSync("apx", ["daemon", "start"], { stdio: "inherit" });
|
|
88
|
+
console.log("done.");
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
console.log(`\n✅ Updated to ${latest}.`);
|
|
60
92
|
}
|
|
61
93
|
|
|
62
94
|
function confirm(prompt) {
|
package/src/core/scaffold.js
CHANGED
|
@@ -176,7 +176,12 @@ export function installIdeSkills(root, targetIds = null) {
|
|
|
176
176
|
return results;
|
|
177
177
|
}
|
|
178
178
|
|
|
179
|
-
// Install bundled APX/APC skills
|
|
179
|
+
// Install bundled APX/APC skills to global ~/.../skills/ dirs.
|
|
180
|
+
// Only apx and apc-context are installed everywhere — they teach IDE tools
|
|
181
|
+
// (Claude Code, Cursor, Codex) about the APX CLI and APC project standard.
|
|
182
|
+
// Runtime CLI skills (claude-code, codex-cli, etc.) are APX-internal; APX
|
|
183
|
+
// loads them from src/daemon/runtime-skills/ at startup and does NOT push
|
|
184
|
+
// them to other tools' global skill dirs.
|
|
180
185
|
// Returns an array of result objects with { dir, skill, status }.
|
|
181
186
|
export function installGlobalSkills() {
|
|
182
187
|
const results = [];
|
|
@@ -186,7 +191,8 @@ export function installGlobalSkills() {
|
|
|
186
191
|
const apcRaw = readBundledSkill("apc-context");
|
|
187
192
|
if (apxRaw) skills.push({ slug: "apx", md: apxRaw });
|
|
188
193
|
if (apcRaw) skills.push({ slug: "apc-context", md: apcRaw });
|
|
189
|
-
skills
|
|
194
|
+
// Runtime skills (claude-code, codex-cli, opencode-cli, openrouter, …) are
|
|
195
|
+
// NOT included here — they are APX-only internals, not for IDE consumption.
|
|
190
196
|
|
|
191
197
|
for (const base of GLOBAL_SKILL_DIRS) {
|
|
192
198
|
for (const { slug, md } of skills) {
|
|
@@ -13,20 +13,20 @@ export default {
|
|
|
13
13
|
properties: {
|
|
14
14
|
agent_name: { type: "string", description: "new agent name" },
|
|
15
15
|
owner_name: { type: "string", description: "owner name" },
|
|
16
|
+
owner_context: { type: "string", description: "context injected into every system prompt — what the owner builds / works on" },
|
|
16
17
|
personality: { type: "string", description: "comma-separated personality traits" },
|
|
17
|
-
language: { type: "string", description: "preferred language" },
|
|
18
18
|
confirmed: confirmedProperty("true only after explicit user confirmation for this exact identity update"),
|
|
19
19
|
},
|
|
20
20
|
},
|
|
21
21
|
},
|
|
22
22
|
},
|
|
23
|
-
makeHandler: ({ requirePermission }) => ({ agent_name, owner_name,
|
|
23
|
+
makeHandler: ({ requirePermission }) => ({ agent_name, owner_name, owner_context, personality, confirmed = false } = {}) => {
|
|
24
24
|
requirePermission("set_identity", { dangerous: true, confirmed });
|
|
25
25
|
const fields = {};
|
|
26
26
|
if (agent_name) fields.agent_name = agent_name;
|
|
27
27
|
if (owner_name) fields.owner_name = owner_name;
|
|
28
|
+
if (owner_context !== undefined) fields.owner_context = owner_context;
|
|
28
29
|
if (personality) fields.personality = personality;
|
|
29
|
-
if (language) fields.language = language;
|
|
30
30
|
if (Object.keys(fields).length === 0) {
|
|
31
31
|
return { ok: true, identity: readIdentity() };
|
|
32
32
|
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
extractPseudoToolCalls,
|
|
19
19
|
cleanTextOfPseudoToolCalls,
|
|
20
20
|
} from "./tool-call-parser.js";
|
|
21
|
+
import { readIdentity } from "../core/identity.js";
|
|
21
22
|
|
|
22
23
|
const MAX_TOOL_ITERS = 6;
|
|
23
24
|
|
|
@@ -201,8 +202,23 @@ export async function runSuperAgent({
|
|
|
201
202
|
].join("\n");
|
|
202
203
|
})();
|
|
203
204
|
|
|
205
|
+
// Identity: who the agent is, who it works for, and what extra context the owner provided.
|
|
206
|
+
// Language comes from config.user.language (ISO 639-1) so it stays in sync with transcription.
|
|
207
|
+
const identity = (() => { try { return readIdentity(); } catch { return null; } })();
|
|
208
|
+
const userLang = globalConfig?.user?.language || "en";
|
|
209
|
+
const identityBlock = (() => {
|
|
210
|
+
const lines = ["# Identity"];
|
|
211
|
+
if (identity?.agent_name) lines.push(`Your name is ${identity.agent_name}.`);
|
|
212
|
+
if (identity?.personality) lines.push(`Your personality: ${identity.personality}.`);
|
|
213
|
+
if (identity?.owner_name) lines.push(`Your owner is ${identity.owner_name}.`);
|
|
214
|
+
if (identity?.owner_context) lines.push(`Owner context: ${identity.owner_context}`);
|
|
215
|
+
lines.push(`Always reply in the language with ISO code "${userLang}" unless the user explicitly switches.`);
|
|
216
|
+
return lines.join("\n");
|
|
217
|
+
})();
|
|
218
|
+
|
|
204
219
|
const system = [
|
|
205
220
|
sa.system || DEFAULT_SYSTEM,
|
|
221
|
+
identityBlock,
|
|
206
222
|
permissionNote,
|
|
207
223
|
contextNote,
|
|
208
224
|
"# Registered projects (just the index — call tools for details)",
|