@htooayelwinict/appv23 2.3.1 → 2.3.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/README.md CHANGED
@@ -25,6 +25,14 @@ ghcr.io/htooayelwinict/appv23:production
25
25
 
26
26
  It mounts only the selected `--cwd` as `/workspace`, stores sandbox state in `~/.appv23/sandbox-home`, copies host `~/.agents/AGENTS.md` into the sandbox agent context, and copies host `~/.agents/skills` into the sandbox.
27
27
 
28
+ On startup, the package restores compact default agent files only when they are missing:
29
+
30
+ - `~/.agents/AGENTS.md`
31
+ - `~/.agents/skills/web-search/SKILL.md`
32
+ - bundled package skills such as `subagent-delegation`
33
+
34
+ Existing user files are never overwritten.
35
+
28
36
  ## Options
29
37
 
30
38
  ```bash
@@ -0,0 +1,25 @@
1
+ # appv23 Agent Kernel
2
+
3
+ This is the default appv23 user-level agent prompt. It is installed only when
4
+ `~/.agents/AGENTS.md` is missing. Edit the host file to customize behavior.
5
+
6
+ ## Core behavior
7
+
8
+ - Treat the selected `--cwd` as the normal workspace boundary.
9
+ - Do not read or write outside the workspace unless the user explicitly allows it.
10
+ - Keep the main agent direct and lightweight for ordinary requests.
11
+ - Use skills only when the user asks for that capability or the task clearly needs it.
12
+ - Prefer concise tool use and avoid repeated no-progress tool calls.
13
+ - Do not expose API keys, auth files, or other secrets.
14
+
15
+ ## Skill routing
16
+
17
+ - Use `web-search` only for current public information, recent facts, news, sports/results, or explicit web-search requests.
18
+ - Use `subagent-delegation` only for explicit subagent requests, `/subagents` workflows, review/QA delegation, or large independent workstreams.
19
+ - For normal coding, act as the main agent without spawning subagents.
20
+
21
+ ## Sandbox expectations
22
+
23
+ - The Docker sandbox mounts only the selected workspace and appv23 state.
24
+ - API keys configured through `/login` live in appv23 sandbox state, not in project files.
25
+ - If a path is blocked or outside scope, ask for explicit authorization instead of guessing.
package/bin/appv23.js CHANGED
@@ -225,10 +225,51 @@ function prepareSandboxImports(config, runtime = {}) {
225
225
  const homeDir = runtime.homeDir || os.homedir();
226
226
  const packageRoot = runtime.packageRoot || path.resolve(__dirname, "..");
227
227
  fs.mkdirSync(config.agentHome, { recursive: true, mode: 0o700 });
228
+ seedHostDefaults(homeDir, packageRoot);
228
229
  prepareAgentsFiles(config, homeDir);
229
230
  prepareSkills(config, homeDir, packageRoot);
230
231
  }
231
232
 
233
+ function seedHostDefaults(homeDir, packageRoot) {
234
+ seedHostAgentsFile(homeDir, packageRoot);
235
+ seedHostSkills(homeDir, packageRoot);
236
+ }
237
+
238
+ function seedHostAgentsFile(homeDir, packageRoot) {
239
+ const source = path.join(packageRoot, "agents", "AGENTS.md");
240
+ const target = path.join(homeDir, ".agents", "AGENTS.md");
241
+ if (!fs.existsSync(source) || fs.existsSync(target)) {
242
+ return;
243
+ }
244
+ copyFileSafe(source, target);
245
+ }
246
+
247
+ function seedHostSkills(homeDir, packageRoot) {
248
+ const sourceRoot = path.join(packageRoot, "skills");
249
+ const targetRoot = path.join(homeDir, ".agents", "skills");
250
+ if (!fs.existsSync(sourceRoot)) {
251
+ return;
252
+ }
253
+ for (const child of fs.readdirSync(sourceRoot).sort()) {
254
+ const source = path.join(sourceRoot, child);
255
+ if (shouldSkipImport(source)) {
256
+ continue;
257
+ }
258
+ const stat = fs.statSync(source);
259
+ if (stat.isDirectory()) {
260
+ const target = path.join(targetRoot, child);
261
+ if (!fs.existsSync(target)) {
262
+ copyTreeSafe(source, target);
263
+ }
264
+ } else if (stat.isFile() && path.extname(source) === ".md") {
265
+ const target = path.join(targetRoot, child);
266
+ if (!fs.existsSync(target)) {
267
+ copyFileSafe(source, target);
268
+ }
269
+ }
270
+ }
271
+ }
272
+
232
273
  function prepareAgentsFiles(config, homeDir = os.homedir()) {
233
274
  const sources = collectAgentsFiles(config, homeDir);
234
275
  const target = path.join(config.agentHome, "agent", "AGENTS.md");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@htooayelwinict/appv23",
3
- "version": "2.3.1",
3
+ "version": "2.3.2",
4
4
  "description": "npx-friendly Docker launcher for the appv23 coding-agent sandbox.",
5
5
  "license": "MIT",
6
6
  "bin": {
@@ -8,6 +8,7 @@
8
8
  "appv23-sandbox": "bin/appv23.js"
9
9
  },
10
10
  "files": [
11
+ "agents/**/*.md",
11
12
  "bin/appv23.js",
12
13
  "skills/**/*.md",
13
14
  "README.md",
@@ -0,0 +1,51 @@
1
+ ---
2
+ name: web-search
3
+ description: Use when the user explicitly asks for web search, current facts, latest news, recent public information, or sports/current-result lookup.
4
+ ---
5
+
6
+ # Web Search
7
+
8
+ Use this skill only for web/current-information tasks. Do not use it for local
9
+ repo inspection, code edits, or ordinary reasoning.
10
+
11
+ ## Rules
12
+
13
+ - Use `curl` plus Python standard library parsing.
14
+ - Prefer Google News RSS for news/current-result lookup:
15
+ `https://news.google.com/rss/search?q=<encoded-query>&hl=en-US&gl=US&ceid=US:en`
16
+ - Keep output small: show at most 5 useful results.
17
+ - Do not print raw HTML/XML.
18
+ - Do not write files.
19
+ - If live search fails, say exactly what failed and suggest a direct source.
20
+
21
+ ## Minimal command pattern
22
+
23
+ ```bash
24
+ python3 - <<'PY'
25
+ import html
26
+ import sys
27
+ import urllib.parse
28
+ import urllib.request
29
+ import xml.etree.ElementTree as ET
30
+
31
+ query = " ".join(sys.argv[1:]).strip() or "latest news"
32
+ url = "https://news.google.com/rss/search?q={}&hl=en-US&gl=US&ceid=US:en".format(
33
+ urllib.parse.quote_plus(query)
34
+ )
35
+ req = urllib.request.Request(url, headers={"User-Agent": "Mozilla/5.0"})
36
+ with urllib.request.urlopen(req, timeout=15) as response:
37
+ data = response.read()
38
+ root = ET.fromstring(data)
39
+ for index, item in enumerate(root.findall("./channel/item")[:5], 1):
40
+ title = html.unescape(item.findtext("title") or "").strip()
41
+ link = html.unescape(item.findtext("link") or "").strip()
42
+ pub_date = html.unescape(item.findtext("pubDate") or "").strip()
43
+ print(f"{index}. {title}")
44
+ if pub_date:
45
+ print(f" date: {pub_date}")
46
+ if link:
47
+ print(f" source: {link}")
48
+ PY
49
+ ```
50
+
51
+ Replace the query in the command with the user's requested search.