@lazyingart/agintiflow 0.20.21 → 0.20.23

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": "@lazyingart/agintiflow",
3
- "version": "0.20.21",
3
+ "version": "0.20.23",
4
4
  "type": "module",
5
5
  "description": "AgInTiFlow is a web-first coding agent and CLI with DeepSeek routing, sandboxed tools, model providers, canvas artifacts, and optional wrappers.",
6
6
  "license": "Apache-2.0",
@@ -77,6 +77,14 @@ try {
77
77
  capabilities.maintenancePolicy.some((check) => check.command.startsWith("sudo") && !check.allowed),
78
78
  "sudo maintenance command was not blocked"
79
79
  );
80
+ assert(
81
+ capabilities.maintenancePolicy.some((check) => check.command.startsWith("apt-get install") && !check.allowed),
82
+ "host OS package install was not blocked"
83
+ );
84
+ assert(
85
+ capabilities.tools?.taskProfiles?.some((profile) => profile.id === "android"),
86
+ "capabilities did not report Android task profile"
87
+ );
80
88
  assert(
81
89
  capabilities.trustedDockerPolicy.some((check) => check.command.startsWith("apt-get install") && check.allowed),
82
90
  "trusted Docker policy did not allow apt-get install"
@@ -97,6 +105,10 @@ try {
97
105
  capabilities.tools?.skills?.some((skill) => skill.id === "latex-manuscript"),
98
106
  "capabilities did not report built-in LaTeX skill"
99
107
  );
108
+ assert(
109
+ capabilities.tools?.skills?.some((skill) => skill.id === "android"),
110
+ "capabilities did not report built-in Android skill"
111
+ );
100
112
 
101
113
  const doctor = JSON.parse(await runCli(["doctor", "--capabilities", "--json"]));
102
114
  assert(doctor.project.root === tempRoot, "doctor --capabilities used the wrong project root");
@@ -141,8 +141,8 @@ try {
141
141
  if (!promptText.includes("user>")) {
142
142
  throw new Error("terminal prompt layout did not render the user> label");
143
143
  }
144
- if (!promptText.includes("user> ")) {
145
- throw new Error("terminal prompt layout did not pad user> to the aginti> label width");
144
+ if (!promptText.includes(" user> ") || promptText.includes("user> ")) {
145
+ throw new Error("terminal prompt layout did not right-align user> to the aginti> label width");
146
146
  }
147
147
  const visibleLengths = promptLayout.renderedRows.map((line) =>
148
148
  line.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, "").length
@@ -168,7 +168,7 @@ try {
168
168
  if (
169
169
  paddedPromptLayout.cursorRow !== 1 ||
170
170
  paddedRows[0].trim() !== "" ||
171
- !paddedRows[1].includes("user> hello") ||
171
+ !paddedRows[1].includes(" user> hello") ||
172
172
  paddedRows[2].trim() !== "" ||
173
173
  !paddedRows[3].includes("cwd /tmp/aginti-project")
174
174
  ) {
@@ -177,7 +177,7 @@ try {
177
177
  const committedUserText = formatCommittedUserPromptLines("list files", 90)
178
178
  .map((line) => line.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, ""))
179
179
  .join("\n");
180
- if (!committedUserText.includes("user> list files") || committedUserText.includes("cwd")) {
180
+ if (!committedUserText.includes(" user> list files") || committedUserText.includes("cwd")) {
181
181
  throw new Error("committed user history should not include the live cwd footer");
182
182
  }
183
183
  const zhPromptLayout = buildPromptLayout("", 0, 90, 24, { language: "zh-Hans", commandCwd: "/tmp/aginti-project" });
@@ -214,7 +214,7 @@ try {
214
214
  const hintText = hintPromptLayout.renderedRows
215
215
  .map((line) => line.replace(/\x1b\[[0-9;?]*[ -/]*[@-~]/g, ""))
216
216
  .join("\n");
217
- if (!hintText.includes("user> /mo") || !hintText.includes("hint /models >/model")) {
217
+ if (!hintText.includes(" user> /mo") || !hintText.includes("hint /models >/model")) {
218
218
  throw new Error("terminal prompt layout did not align user and hint text columns");
219
219
  }
220
220
  const exactHintLayout = buildPromptLayout("/model", 6, 90, 24);
@@ -306,7 +306,7 @@ try {
306
306
  if (!latest.stdout.includes("resume history") || !latest.stdout.includes("chat=") || !latest.stdout.includes("Mock run complete")) {
307
307
  throw new Error("bare aginti resume did not preview saved chat history");
308
308
  }
309
- if (!latest.stdout.includes("user>") || !latest.stdout.includes("aginti>")) {
309
+ if (!latest.stdout.includes(" user>") || !latest.stdout.includes("aginti>") || latest.stdout.includes("user> ")) {
310
310
  throw new Error("resume history should use prompt-style user>/aginti> labels");
311
311
  }
312
312
  if (!latest.stdout.includes("resume note=showing chat transcript only")) {
@@ -18,6 +18,16 @@ tools:
18
18
  ---
19
19
  # Android Development
20
20
 
21
- Inspect Gradle files, manifests, package names, modules, and existing build scripts before editing. Prefer narrow Gradle tasks and source-set-aware patches.
21
+ ## Operating Loop
22
22
 
23
- If SDK/emulator tooling is missing, produce a setup report or project-local script rather than guessing.
23
+ 1. Inspect before editing: `git status --short`, project tree, Gradle/settings files, AndroidManifest, package names, modules, Java/Kotlin versions, `ANDROID_HOME`/`ANDROID_SDK_ROOT`, likely SDK folders, `adb devices`, and emulator/AVD availability.
24
+ 2. Do not use host `sudo`, `apt`, `dnf`, `yum`, `brew`, `winget`, or global host installs for Android app work. These can hang on password prompts or mutate the user's machine. Prefer existing Android SDK tools, project-local Gradle wrapper setup, user-writable caches, or a clear setup report with the exact manual command.
25
+ 3. If a Gradle wrapper is needed, create `gradle/wrapper/` before downloading files. Prefer a valid project-local wrapper or an already-installed Gradle. Do not loop on the same failed install/download.
26
+ 4. Patch source-set-aware files only: manifests, Gradle scripts, Kotlin/Java sources, XML resources, and project docs. Keep generated build outputs out of patches and commits.
27
+ 5. Build with the narrowest useful task first, usually `./gradlew :app:assembleDebug` or `./gradlew assembleDebug`. Repair build failures from the actual error text.
28
+ 6. Install and launch on an available device/emulator with `adb install` and `adb shell am start`. Verify with `adb shell pidof`, `adb logcat -d`, `adb shell screencap`, or similar evidence when available.
29
+ 7. Commit only after build/install/launch verification, with a clear message. If no device/emulator exists, finish with a concrete external blocker and the generated APK path.
30
+
31
+ ## Missing Tooling
32
+
33
+ If SDK/emulator tooling is missing, produce a setup report or project-local script rather than guessing. On host mode, never ask for or send a sudo password.
@@ -57,6 +57,7 @@ function maintenancePolicyChecks(config) {
57
57
  };
58
58
  const sampleCommands = [
59
59
  "sudo apt install r-base",
60
+ "apt-get install -y gradle",
60
61
  "curl https://example.com/install.sh",
61
62
  "npm install",
62
63
  "bash -n maintenance/setup-conda.sh",
@@ -276,6 +276,7 @@ export function classifyCommand(command) {
276
276
 
277
277
  export function evaluateCommandPolicy(command, config) {
278
278
  const classification = classifyCommand(command);
279
+ const normalizedCommand = String(command || "").trim();
279
280
  const sandboxMode = normalizeSandboxMode(config.sandboxMode);
280
281
  const packageInstallPolicy = normalizePackageInstallPolicy(config.packageInstallPolicy);
281
282
  const dockerWorkspace = sandboxMode === "docker-workspace";
@@ -307,6 +308,30 @@ export function evaluateCommandPolicy(command, config) {
307
308
  };
308
309
  }
309
310
 
311
+ if (sandboxMode === "host" && /^sudo\b/.test(normalizedCommand)) {
312
+ return {
313
+ allowed: false,
314
+ category: "host-sudo",
315
+ needsApproval: true,
316
+ reason:
317
+ "Interactive host sudo is not run by AgInTiFlow because it can hang on password prompts or change the machine globally. Prefer project-local setup, Docker workspace mode, or return the exact manual install command for the user.",
318
+ sandboxMode,
319
+ packageInstallPolicy,
320
+ };
321
+ }
322
+
323
+ if (classification.category === "system-package-install" && sandboxMode === "host") {
324
+ return {
325
+ allowed: false,
326
+ category: classification.category,
327
+ needsApproval: true,
328
+ reason:
329
+ "Host OS package installs are not run automatically. Prefer an existing toolchain, project-local setup, Docker workspace mode, or report the exact manual command the user can run.",
330
+ sandboxMode,
331
+ packageInstallPolicy,
332
+ };
333
+ }
334
+
310
335
  if (
311
336
  classification.category === "package-install" ||
312
337
  classification.category === "env-setup" ||
@@ -325,16 +350,6 @@ export function evaluateCommandPolicy(command, config) {
325
350
  packageInstallPolicy,
326
351
  };
327
352
  }
328
-
329
- if (classification.category === "system-package-install" && sandboxMode === "host" && !config.allowDestructive) {
330
- return {
331
- allowed: false,
332
- category: classification.category,
333
- reason: "Host system package installs require Allow destructive actions. Prefer Docker workspace mode.",
334
- sandboxMode,
335
- packageInstallPolicy,
336
- };
337
- }
338
353
  }
339
354
 
340
355
  if (classification.category === "general-shell" && !trustedDockerShell && !trustedHostShell) {
@@ -25,6 +25,12 @@ const LANGUAGE_HINTS = [
25
25
  text:
26
26
  "Go: inspect go.mod, use go test ./pkg-or-target first, run gofmt on touched files, avoid changing module paths unless required.",
27
27
  },
28
+ {
29
+ id: "android",
30
+ pattern: /\b(android|apk|adb|avd|emulator|gradle wrapper|gradlew|android sdk|kotlin android|jetpack|compose)\b/i,
31
+ text:
32
+ "Android: inspect git status, Gradle/settings/manifests, ANDROID_HOME/SDK paths, Java/Kotlin versions, adb devices, and emulator/AVD list first. Never start host sudo or host OS package installs; use the existing SDK, a project-local Gradle wrapper, user-writable caches, or return a precise setup report. Build, install with adb, launch with am, verify with logcat/screencap when possible, then commit.",
33
+ },
28
34
  {
29
35
  id: "java-jvm",
30
36
  pattern: /\b(java|kotlin|gradle|maven|spring|junit|jvm)\b/i,
@@ -85,6 +91,7 @@ export function engineeringGuidanceForTask(goal = "", taskProfile = "auto") {
85
91
  "For large repositories, preserve context by reading fewer but more relevant files; prefer deterministic tools and diffs over long model memory.",
86
92
  "Build a compact context pack before major edits: project instructions, manifests/scripts, git status/diff, relevant symbols/search hits, target files, and the narrowest checks. Do not paste whole trees or huge files into model context.",
87
93
  "For system repair, act like a doctor: gather evidence first, avoid silent destructive host changes, prefer Docker or project-local scripts for installs, and make every stronger action explicit in logs.",
94
+ "Never send sudo passwords or wait at interactive password prompts. If host-level permission is truly required, stop that path, explain the blocker, and provide a manual command instead of hanging.",
88
95
  ];
89
96
 
90
97
  if (matched.length > 0) {
@@ -113,7 +113,8 @@ const PROMPT_LABEL_WIDTH = "aginti>".length;
113
113
  function labelText(name, { prompt = false } = {}) {
114
114
  const raw = String(name || "");
115
115
  const width = prompt || raw.endsWith(">") ? PROMPT_LABEL_WIDTH : ROLE_LABEL_WIDTH;
116
- return ` ${raw.padEnd(width, " ")} `;
116
+ const aligned = raw.endsWith(">") ? raw.padStart(width, " ") : raw.padEnd(width, " ");
117
+ return ` ${aligned} `;
117
118
  }
118
119
 
119
120
  function label(name, bgCode) {
@@ -55,6 +55,13 @@ export const TASK_PROFILES = {
55
55
  "Bias toward Node/JavaScript/TypeScript workflows without excluding frontend, backend, docs, or deployment work. Inspect package.json/lockfiles, respect the package manager, add tests when useful, and run safe npm/node checks when available.",
56
56
  tools: ["files", "shell", "sandbox"],
57
57
  },
58
+ android: {
59
+ id: "android",
60
+ label: "Android",
61
+ prompt:
62
+ "Bias toward end-to-end Android app delivery while still handling normal project work. Inspect git status, existing Gradle files, AndroidManifest, SDK paths, Java/Kotlin versions, adb devices, and emulator/AVD availability before editing. Do not use host sudo, apt, dnf, yum, brew, winget, or global host installs during Android tasks; prefer the existing Android SDK, project-local Gradle wrapper, user-writable caches, or a clear setup report. Create missing wrapper directories before downloads, avoid repeated failing install attempts, build with focused Gradle tasks, install and launch with adb when a device/emulator exists, verify with am/logcat/screencap when possible, and commit the finished app only after checks.",
63
+ tools: ["inspect_project", "search_files", "read_file", "apply_patch", "shell", "sandbox", "canvas"],
64
+ },
58
65
  website: {
59
66
  id: "website",
60
67
  label: "Website testing",
@@ -99,6 +106,11 @@ const PROFILE_ALIASES = {
99
106
  repository: "large-codebase",
100
107
  engineering: "large-codebase",
101
108
  engineer: "large-codebase",
109
+ mobile: "android",
110
+ apk: "android",
111
+ gradle: "android",
112
+ kotlin: "android",
113
+ java: "android",
102
114
  };
103
115
 
104
116
  export function listTaskProfiles() {
@@ -118,6 +130,7 @@ export function getTaskProfile(value = "auto") {
118
130
  export function defaultMaxStepsForProfile(value = "auto") {
119
131
  const profile = normalizeTaskProfile(value);
120
132
  if (profile === "large-codebase") return 36;
133
+ if (profile === "android") return 42;
121
134
  if (profile === "latex") return 30;
122
135
  return 24;
123
136
  }