@lazyingart/agintiflow 0.20.189 → 0.20.191
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 +1 -1
- package/references/agintiflow-intent-routing-overpatch-audit-2026-06-01.md +74 -0
- package/references/agintiflow-npm-publication-memory.md +23 -1
- package/references/lazyedit-publish-skill-installation-2026-06-03.md +88 -0
- package/references/paper-revision-skill-installation-2026-06-03.md +62 -0
- package/scripts/smoke-coding-tools.js +18 -0
- package/scripts/smoke-model-roles.js +10 -0
- package/scripts/smoke-skillmesh.js +23 -0
- package/scripts/smoke-web-ui.js +3 -2
- package/src/agent-runner.js +48 -3
- package/src/goal-intent.js +101 -0
- package/src/model-client.js +1 -1
- package/src/skill-library.js +11 -7
- package/src/skillmesh.js +56 -20
- package/src/task-profiles.js +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lazyingart/agintiflow",
|
|
3
|
-
"version": "0.20.
|
|
3
|
+
"version": "0.20.191",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "AgInTiFlow is a project-aware agent workspace for hybrid wet-dry R&D, hardware-aware intelligence, software automation, and industrial workflows.",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# AgInTiFlow Intent Routing Overpatch Audit
|
|
2
|
+
|
|
3
|
+
Date: 2026-06-01
|
|
4
|
+
|
|
5
|
+
## Problem
|
|
6
|
+
|
|
7
|
+
A bare user message, `hello`, was handled as an execution task. In the observed run, AgInTiFlow planned to inspect the workspace, created `hello.py`, and then stopped without a natural chat answer. That is the wrong default behavior for a general agent UI: a greeting should be answered directly, not converted into a workspace mutation.
|
|
8
|
+
|
|
9
|
+
## Evidence
|
|
10
|
+
|
|
11
|
+
Observed session:
|
|
12
|
+
|
|
13
|
+
- Session: `/home/lachlan/.agintiflow/sessions/web-agent-f798c7cc-b3c2-439f-b2be-2a2746b4944d/state.json`
|
|
14
|
+
- Provider/model: `deepseek/deepseek-v4-flash`
|
|
15
|
+
- Goal: `hello`
|
|
16
|
+
- Task profile: `auto`
|
|
17
|
+
- Selected skills: `[]`
|
|
18
|
+
- Outcome shown by user: AgInTiFlow wrote `hello.py` with `print("Hello from agent!")`
|
|
19
|
+
|
|
20
|
+
The selected skills list was empty, so this was not caused by a custom skill. The behavior came from the core runtime prompt and the lack of a direct-answer lane.
|
|
21
|
+
|
|
22
|
+
## Root Cause
|
|
23
|
+
|
|
24
|
+
The runtime had one dominant path:
|
|
25
|
+
|
|
26
|
+
1. Create a plan.
|
|
27
|
+
2. Continue with tools until completion.
|
|
28
|
+
3. Prefer real workspace edits/checks over advice-only answers.
|
|
29
|
+
|
|
30
|
+
The strongest prompt pressure was in:
|
|
31
|
+
|
|
32
|
+
- `src/agent-runner.js`: system prompt said the plan is not final and the agent should actively use tools until complete.
|
|
33
|
+
- `src/model-client.js`: planner prompt said to prefer real workspace edits/checks over advice-only answers.
|
|
34
|
+
- `src/task-profiles.js`: the `auto` profile told the agent to infer task type and choose a tool mix, but did not define a no-tool conversational mode.
|
|
35
|
+
|
|
36
|
+
That design is useful for real tasks, but over-applies tool use to short social turns.
|
|
37
|
+
|
|
38
|
+
## Design Fix
|
|
39
|
+
|
|
40
|
+
Add a deterministic pre-plan goal-intent classifier:
|
|
41
|
+
|
|
42
|
+
- Greetings, thanks, and explicit greeting requests finish directly.
|
|
43
|
+
- Explicit create/edit/run/read/search/download/build/test/coding/file/command requests remain agentic.
|
|
44
|
+
- File paths, file extensions, and command-looking inputs remain agentic.
|
|
45
|
+
- The direct path runs before planning, SCS, surgical context, snapshots, browser, shell, canvas, or file tools.
|
|
46
|
+
|
|
47
|
+
This keeps the fix general. It does not special-case `hello.py`, mock mode, DeepSeek, or a single UI path.
|
|
48
|
+
|
|
49
|
+
The prompts were also softened:
|
|
50
|
+
|
|
51
|
+
- Tool use is required only when the user actually asks for workspace/browser/shell/web/canvas/image/MCP/specialist work.
|
|
52
|
+
- Greetings and simple conversational turns should finish directly.
|
|
53
|
+
- Canvas should not be used for ordinary chat replies.
|
|
54
|
+
|
|
55
|
+
## Regression Contract
|
|
56
|
+
|
|
57
|
+
Required behavior:
|
|
58
|
+
|
|
59
|
+
- `hello` returns a direct greeting.
|
|
60
|
+
- `hello` does not create a plan.
|
|
61
|
+
- `hello` does not call tools.
|
|
62
|
+
- `hello` does not create `hello.py`.
|
|
63
|
+
- `create hello.py` still requires tools.
|
|
64
|
+
- `write a hello-world Python script and run it` still requires tools.
|
|
65
|
+
|
|
66
|
+
## Product Lesson
|
|
67
|
+
|
|
68
|
+
AgInTiFlow should solve problems at the correct layer:
|
|
69
|
+
|
|
70
|
+
- Core system flaw: no conversational/direct-answer lane. Fix in runtime intent routing.
|
|
71
|
+
- Core general skill incompleteness: missing reusable task classifier. Add deterministic classifier and tests.
|
|
72
|
+
- Custom skill issue: not applicable here because no skill was selected.
|
|
73
|
+
|
|
74
|
+
Avoid overpatching by not making every short input a file task and not routing every interaction through heavyweight planning/SCS/tool execution.
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Date: 2026-05-20
|
|
4
4
|
|
|
5
|
-
Updated: 2026-
|
|
5
|
+
Updated: 2026-06-01
|
|
6
6
|
|
|
7
7
|
This note records the working publication route for AgInTiFlow so future release work does not get blocked by stale local npm tokens or repeated discussion about why direct `npm publish` failed.
|
|
8
8
|
|
|
@@ -10,6 +10,28 @@ This note records the working publication route for AgInTiFlow so future release
|
|
|
10
10
|
|
|
11
11
|
Latest verified release:
|
|
12
12
|
|
|
13
|
+
- Version: `0.20.190`
|
|
14
|
+
- Commit: `f192f8e`
|
|
15
|
+
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26736284533`
|
|
16
|
+
- Workflow result: success
|
|
17
|
+
- npm registry check: `npm view @lazyingart/agintiflow version dist-tags.latest --registry=https://registry.npmjs.org` returned `0.20.190`.
|
|
18
|
+
- Installed verification: `npm install -g @lazyingart/agintiflow@0.20.190` then `aginti --version` returned `0.20.190`.
|
|
19
|
+
- Webapp verification: `aginti webapp restart --port 3210` then `curl -fsS http://127.0.0.1:3210/health` returned `version":"0.20.190"` from the global npm package path.
|
|
20
|
+
- Feature verification: `aginti --provider mock --routing manual --model mock-agent --no-shell --allow-file-tools --scs off "hello"` returned a direct greeting and did not create `hello.py`.
|
|
21
|
+
|
|
22
|
+
Previous verified release:
|
|
23
|
+
|
|
24
|
+
- Version: `0.20.189`
|
|
25
|
+
- Commit: `0095284`
|
|
26
|
+
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26734901522`
|
|
27
|
+
- Workflow result: success
|
|
28
|
+
- npm registry check: `npm view @lazyingart/agintiflow version dist-tags.latest --registry=https://registry.npmjs.org` returned `0.20.189`.
|
|
29
|
+
- Installed verification: `npm install -g @lazyingart/agintiflow@0.20.189` then `aginti --version` returned `0.20.189`.
|
|
30
|
+
- Webapp verification: `aginti webapp restart --port 3210` then `curl -fsS http://127.0.0.1:3210/health` returned `version":"0.20.189"` from the global npm package path.
|
|
31
|
+
- Feature verification: `npm run smoke:model-roles` covered `OPENAI_BASE_URL`, provider-default reasoning, OpenAI chat `reasoning_effort`, and retry-without-reasoning for OpenAI-compatible gateways.
|
|
32
|
+
|
|
33
|
+
Previous verified release:
|
|
34
|
+
|
|
13
35
|
- Version: `0.20.188`
|
|
14
36
|
- Commit: `939e2ec`
|
|
15
37
|
- GitHub Actions run: `https://github.com/lazyingart/AgInTiFlow/actions/runs/26705729544`
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# LazyEdit Publish Skill Installation
|
|
2
|
+
|
|
3
|
+
Date: 2026-06-03
|
|
4
|
+
|
|
5
|
+
## Installed Skill
|
|
6
|
+
|
|
7
|
+
Skill id:
|
|
8
|
+
|
|
9
|
+
- `lazyedit-publish-workflow`
|
|
10
|
+
|
|
11
|
+
Source skill:
|
|
12
|
+
|
|
13
|
+
- `/home/lachlan/.codex/skills/lazyedit-publish-workflow/SKILL.md`
|
|
14
|
+
|
|
15
|
+
AgInTiFlow project-local copy:
|
|
16
|
+
|
|
17
|
+
- `/home/lachlan/ProjectsLFS/Agent/AgInTiFlow/.aginti/skills/lazyedit-publish-workflow/SKILL.md`
|
|
18
|
+
|
|
19
|
+
Global AgInTiFlow custom copy:
|
|
20
|
+
|
|
21
|
+
- Skill Mesh storage under `/home/lachlan/.agintiflow/skillmesh/skills/lazyedit-publish-workflow/`
|
|
22
|
+
- Installed as a local-reviewed enabled Skill Mesh skill.
|
|
23
|
+
|
|
24
|
+
## Why Both Copies Exist
|
|
25
|
+
|
|
26
|
+
The project-local `.aginti/skills/` copy documents the skill in the AgInTiFlow repository and lets local development sessions load it as `source=project-local`.
|
|
27
|
+
|
|
28
|
+
The Skill Mesh copy makes the same skill available from other working directories such as LALACHAN, RARACHAN, LazyEdit, or Agent without requiring the user to start AgInTiFlow from the AgInTiFlow repo.
|
|
29
|
+
|
|
30
|
+
## Verification
|
|
31
|
+
|
|
32
|
+
Project-local loader:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
node -e "import { listSkills, selectSkillsForGoal } from './src/skill-library.js'; const skill=listSkills({projectRoot:process.cwd(), includeBody:true}).find(s=>s.id==='lazyedit-publish-workflow'); if(!skill) throw new Error('missing'); console.log(skill.source);"
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Expected result:
|
|
39
|
+
|
|
40
|
+
```text
|
|
41
|
+
project-local
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Global Skill Mesh install:
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
node bin/aginti-cli.js skillmesh export lazyedit-publish-workflow --out /tmp/lazyedit-publish-workflow.skillpack.json
|
|
48
|
+
node bin/aginti-cli.js skillmesh import /tmp/lazyedit-publish-workflow.skillpack.json --enable
|
|
49
|
+
node bin/aginti-cli.js skillmesh status
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Expected result includes:
|
|
53
|
+
|
|
54
|
+
```text
|
|
55
|
+
enabled lazyedit-publish-workflow: LazyEdit Publish Workflow
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Cross-directory discovery:
|
|
59
|
+
|
|
60
|
+
```bash
|
|
61
|
+
cd /home/lachlan/ProjectsLFS/Agent
|
|
62
|
+
aginti skills lazyedit
|
|
63
|
+
|
|
64
|
+
cd /home/lachlan/ProjectsLFS/LALACHAN
|
|
65
|
+
node /home/lachlan/ProjectsLFS/Agent/AgInTiFlow/bin/aginti-cli.js skills lazyedit
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
Expected result:
|
|
69
|
+
|
|
70
|
+
```text
|
|
71
|
+
lazyedit-publish-workflow ... source=skillmesh
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
Selection check:
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
node -e "import { selectSkillsForGoal } from '/home/lachlan/ProjectsLFS/Agent/AgInTiFlow/src/skill-library.js'; const selected=selectSkillsForGoal('publish latest LALACHAN generated video through LazyEdit to Shipinhao YouTube Instagram with corrected subtitles', {projectRoot:'/home/lachlan/ProjectsLFS/LALACHAN', includeBody:true}).map(s=>s.id); console.log(selected); if(!selected.includes('lazyedit-publish-workflow')) throw new Error('not selected');"
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Expected result:
|
|
81
|
+
|
|
82
|
+
- `lazyedit-publish-workflow` appears in the selected skill list.
|
|
83
|
+
|
|
84
|
+
## Operational Notes
|
|
85
|
+
|
|
86
|
+
The skill is prompt guidance, not a privileged tool. LazyEdit publishing still runs through normal AgInTiFlow permission policy and shell/tmux safeguards.
|
|
87
|
+
|
|
88
|
+
The subtitle correction rule is preserved: generated video scripts/stories are reference context for correcting ASR recognition errors, not verbatim targets. The agent should compare ASR output against the script, infer intended wording, preserve timing/line structure, and avoid blindly copying script text when the audio differs.
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Paper Revision Skill Installation
|
|
2
|
+
|
|
3
|
+
Date: 2026-06-03
|
|
4
|
+
|
|
5
|
+
Source repository:
|
|
6
|
+
|
|
7
|
+
- `/home/lachlan/ProjectsLFS/paper-revision-skill`
|
|
8
|
+
- `https://github.com/lachlanchen/paper-revision-skill`
|
|
9
|
+
|
|
10
|
+
Purpose:
|
|
11
|
+
|
|
12
|
+
- Add plan-gated academic manuscript revision as a reusable skill.
|
|
13
|
+
- Keep manuscript-specific revision policy in the skill, not in AgInTiFlow core.
|
|
14
|
+
- Let Codex, AgInTiFlow, Claude, Gemini, and Copilot consume the same workflow guidance with tool-specific entry files.
|
|
15
|
+
|
|
16
|
+
AgInTiFlow integration:
|
|
17
|
+
|
|
18
|
+
- The repository's root `SKILL.md` is Codex-style and uses `name:` plus `description:`.
|
|
19
|
+
- AgInTiFlow SkillMesh now accepts that dialect by normalizing `name:` to native `id:` and deriving `label:` when missing.
|
|
20
|
+
- Install the root `SKILL.md` as a reviewed local SkillMesh skill and enable it.
|
|
21
|
+
|
|
22
|
+
Suggested install command from the AgInTiFlow repository:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
node --input-type=module - <<'NODE'
|
|
26
|
+
import fs from "node:fs/promises";
|
|
27
|
+
import {
|
|
28
|
+
buildSkillPackFromMarkdown,
|
|
29
|
+
enableSkillMeshSkill,
|
|
30
|
+
installSkillPack,
|
|
31
|
+
} from "./src/skillmesh.js";
|
|
32
|
+
|
|
33
|
+
const content = await fs.readFile("/home/lachlan/ProjectsLFS/paper-revision-skill/SKILL.md", "utf8");
|
|
34
|
+
const pack = await buildSkillPackFromMarkdown(content, { valueScore: 95 });
|
|
35
|
+
await installSkillPack(pack, { enabled: true });
|
|
36
|
+
await enableSkillMeshSkill("paper-revision-skill", true);
|
|
37
|
+
console.log(JSON.stringify({ ok: true, installedSkills: pack.skills.map((skill) => skill.id), packHash: pack.packHash }, null, 2));
|
|
38
|
+
NODE
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
Validation:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
node scripts/smoke-skillmesh.js
|
|
45
|
+
node --input-type=module - <<'NODE'
|
|
46
|
+
import { selectSkillsForGoal } from "./src/skill-library.js";
|
|
47
|
+
const selected = selectSkillsForGoal(
|
|
48
|
+
"Use the paper revision workflow to answer reviewer comments before editing LaTeX.",
|
|
49
|
+
{ limit: 8, includeBody: false }
|
|
50
|
+
);
|
|
51
|
+
console.log(JSON.stringify(selected.map((skill) => ({ id: skill.id, source: skill.source })), null, 2));
|
|
52
|
+
if (!selected.some((skill) => skill.id === "paper-revision-skill")) {
|
|
53
|
+
throw new Error("paper-revision-skill was not selected");
|
|
54
|
+
}
|
|
55
|
+
NODE
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Boundary:
|
|
59
|
+
|
|
60
|
+
- Do not move manuscript-revision details into AgInTiFlow core.
|
|
61
|
+
- Improve AgInTiFlow core only when the issue is general skill compatibility, skill discovery, SkillMesh validation, evidence tracking, PDF/build tooling, or tool invocation reliability.
|
|
62
|
+
- Keep the skill's plan-first, edit-second, PDF-verified revision workflow in the skill repository.
|
|
@@ -939,6 +939,23 @@ try {
|
|
|
939
939
|
"surgical context message was not injected into model history"
|
|
940
940
|
);
|
|
941
941
|
|
|
942
|
+
const helloRun = await runMock("hello", "coding-direct-hello");
|
|
943
|
+
assert(helloRun.result.result.includes("Hello"), "bare hello did not finish with a direct greeting");
|
|
944
|
+
assert(!helloRun.state?.plan, "bare hello should not create an execution plan");
|
|
945
|
+
assert(
|
|
946
|
+
helloRun.events.some((event) => event.type === "session.finished" && event.data?.mode === "direct-answer"),
|
|
947
|
+
"bare hello did not finish through the direct-answer path"
|
|
948
|
+
);
|
|
949
|
+
assert(
|
|
950
|
+
!helloRun.events.some((event) => event.type === "tool.started" || event.type === "tool.completed"),
|
|
951
|
+
"bare hello should not call tools"
|
|
952
|
+
);
|
|
953
|
+
const helloPyExists = await fs
|
|
954
|
+
.stat(path.join(workspace, "hello.py"))
|
|
955
|
+
.then(() => true)
|
|
956
|
+
.catch(() => false);
|
|
957
|
+
assert(!helloPyExists, "bare hello should not create hello.py");
|
|
958
|
+
|
|
942
959
|
const writeRun = await runMock("Create notes/hello.md with a short coding smoke message.", "coding-write");
|
|
943
960
|
const written = await fs.readFile(path.join(workspace, "notes/hello.md"), "utf8");
|
|
944
961
|
assert(written.includes("Created by AgInTiFlow mock mode."), "mock write did not create expected file");
|
|
@@ -1214,6 +1231,7 @@ try {
|
|
|
1214
1231
|
"scout_blackboard",
|
|
1215
1232
|
"surgical_context_pack",
|
|
1216
1233
|
"mock_inspect_project",
|
|
1234
|
+
"direct_greeting_no_tools",
|
|
1217
1235
|
"write_file",
|
|
1218
1236
|
"duplicate_write_failed",
|
|
1219
1237
|
"resume_session_write",
|
|
@@ -23,6 +23,7 @@ import {
|
|
|
23
23
|
} from "../src/scs-controller.js";
|
|
24
24
|
import { buildScsEvidenceLedger, deriveScsTaskContract, evaluateScsEvidence } from "../src/scs-evidence.js";
|
|
25
25
|
import { resolveRuntimeConfig } from "../src/config.js";
|
|
26
|
+
import { classifyGoalIntent, isDirectAnswerIntent } from "../src/goal-intent.js";
|
|
26
27
|
|
|
27
28
|
const repoRoot = path.resolve(path.dirname(fileURLToPath(import.meta.url)), "..");
|
|
28
29
|
|
|
@@ -127,6 +128,14 @@ for (const [key, value] of Object.entries(envSnapshot)) {
|
|
|
127
128
|
else process.env[key] = value;
|
|
128
129
|
}
|
|
129
130
|
|
|
131
|
+
const helloIntent = classifyGoalIntent("hello");
|
|
132
|
+
assert(isDirectAnswerIntent(helloIntent), "bare hello should be classified as direct conversational intent");
|
|
133
|
+
assert(helloIntent.requiresTools === false, "bare hello should not require tools");
|
|
134
|
+
assert(classifyGoalIntent("你好").directAnswer.includes("你好"), "Chinese greeting should get a direct Chinese reply");
|
|
135
|
+
assert(classifyGoalIntent("say hello in Japanese").directAnswer.includes("こんにちは"), "Japanese greeting request should answer directly");
|
|
136
|
+
assert(classifyGoalIntent("create hello.py").requiresTools, "explicit file creation should remain agentic");
|
|
137
|
+
assert(classifyGoalIntent("write a hello-world Python script and run it").requiresTools, "explicit coding task should require tools");
|
|
138
|
+
|
|
130
139
|
const complexRoute = selectModelRoute({
|
|
131
140
|
routingMode: "complex",
|
|
132
141
|
provider: "deepseek",
|
|
@@ -732,6 +741,7 @@ console.log(
|
|
|
732
741
|
"openai-base-url",
|
|
733
742
|
"provider-default-reasoning",
|
|
734
743
|
"openai-chat-reasoning-payload",
|
|
744
|
+
"goal-intent-direct-answer",
|
|
735
745
|
"route-overrides",
|
|
736
746
|
"provider-groups",
|
|
737
747
|
"auxiliary-catalog",
|
|
@@ -64,6 +64,28 @@ assert(!listSkills({ includeBody: false }).some((skill) => skill.id === "mesh-an
|
|
|
64
64
|
await setSkillMeshMode("share");
|
|
65
65
|
const config = await loadSkillMeshConfig();
|
|
66
66
|
assert(config.mode === "share", "share mode should persist");
|
|
67
|
+
|
|
68
|
+
const codexStyleMarkdown = [
|
|
69
|
+
"---",
|
|
70
|
+
"name: paper-revision-skill",
|
|
71
|
+
"description: Plan-gated academic manuscript revision workflow for LaTeX papers, reviewer responses, proof corrections, redlines, PDF-backed audits, and submission packaging.",
|
|
72
|
+
"---",
|
|
73
|
+
"",
|
|
74
|
+
"Plan first, edit second, verify from compiled PDFs, and keep revision evidence under references/.",
|
|
75
|
+
"",
|
|
76
|
+
].join("\n");
|
|
77
|
+
const codexPack = await buildSkillPackFromMarkdown(codexStyleMarkdown, { valueScore: 90 });
|
|
78
|
+
assert(codexPack.skills[0].id === "paper-revision-skill", "Codex-style name should become SkillMesh id");
|
|
79
|
+
assert(codexPack.skills[0].content.includes("id: paper-revision-skill"), "Codex-style skill should be normalized with id");
|
|
80
|
+
assert(codexPack.skills[0].content.includes("label: Paper Revision Skill"), "Codex-style skill should receive a label");
|
|
81
|
+
await installSkillPack(codexPack, { enabled: true });
|
|
82
|
+
assert(
|
|
83
|
+
selectSkillsForGoal("use the paper revision workflow to answer reviewer comments before editing latex", { limit: 8 }).some(
|
|
84
|
+
(skill) => skill.id === "paper-revision-skill"
|
|
85
|
+
),
|
|
86
|
+
"Codex-style imported skill should be selectable"
|
|
87
|
+
);
|
|
88
|
+
|
|
67
89
|
const serviceUnit = buildSkillMeshServiceUnit({
|
|
68
90
|
dataDir: path.join(tempRoot, "relay-service"),
|
|
69
91
|
runScript: path.join(tempRoot, "relay-service", "aginti-skill-relay.run.sh"),
|
|
@@ -120,6 +142,7 @@ console.log(
|
|
|
120
142
|
"metadata-sync",
|
|
121
143
|
"soft-unreachable-node",
|
|
122
144
|
"systemd-service-unit",
|
|
145
|
+
"codex-style-skill-import",
|
|
123
146
|
],
|
|
124
147
|
},
|
|
125
148
|
null,
|
package/scripts/smoke-web-ui.js
CHANGED
|
@@ -204,10 +204,11 @@ try {
|
|
|
204
204
|
});
|
|
205
205
|
await page.fill("#maxSteps", "4");
|
|
206
206
|
await page.selectOption("#dynamicSteps", "off");
|
|
207
|
-
|
|
207
|
+
const composerGoal = "Create notes/web-ui-smoke.md with one concise sentence from the web UI composer.";
|
|
208
|
+
await page.fill("#chat-input", composerGoal);
|
|
208
209
|
await page.click("#chat-submit");
|
|
209
210
|
const firstPayload = JSON.parse(runPayloads.at(-1) || "{}");
|
|
210
|
-
if (firstPayload.goal !==
|
|
211
|
+
if (firstPayload.goal !== composerGoal) {
|
|
211
212
|
throw new Error("composer text was not used as the first run goal");
|
|
212
213
|
}
|
|
213
214
|
if (firstPayload.enableScs !== "off" || firstPayload.taskProfile !== "auto") {
|
package/src/agent-runner.js
CHANGED
|
@@ -42,6 +42,7 @@ import { summarizeMcpConfig } from "./mcp/config.js";
|
|
|
42
42
|
import { isMcpBridgeTool } from "./mcp/policy.js";
|
|
43
43
|
import { executeMcpBridgeTool } from "./mcp/tool-bridge.js";
|
|
44
44
|
import { longJobStatus, startLongJob } from "./long-job-tools.js";
|
|
45
|
+
import { classifyGoalIntent, isDirectAnswerIntent } from "./goal-intent.js";
|
|
45
46
|
import {
|
|
46
47
|
DEFAULT_SCS_MODE,
|
|
47
48
|
buildSupervisorInstruction,
|
|
@@ -589,11 +590,11 @@ async function createInitialState(config, sessionId) {
|
|
|
589
590
|
content: [
|
|
590
591
|
"You are a careful browser and shell agent with a small tool surface.",
|
|
591
592
|
"Use only the provided tools.",
|
|
592
|
-
"The execution plan is not the final answer. After planning, actively use tools until the requested task is complete or genuinely blocked.",
|
|
593
|
+
"The execution plan is not the final answer. After planning, actively use tools until the requested task is complete or genuinely blocked. If the user only sends a greeting, thanks, or another simple conversational turn, finish directly without creating files, running shell commands, opening browsers, or sending canvas artifacts.",
|
|
593
594
|
"If the shell tool can satisfy a local task, prefer it before opening a browser.",
|
|
594
595
|
"Do not open a browser page just because a start URL exists. Treat it as a suggestion only.",
|
|
595
596
|
"Only reference element ids from the latest browser snapshot.",
|
|
596
|
-
"Prefer short, deliberate actions over guessing.",
|
|
597
|
+
"Prefer short, deliberate actions over guessing. Use tools only when the request actually needs workspace, browser, shell, web, canvas, image, MCP, or specialist work.",
|
|
597
598
|
browserStateReconciliationGuidance(),
|
|
598
599
|
"Never navigate outside the allowed domains when an allowlist exists.",
|
|
599
600
|
"Avoid destructive actions, purchases, account changes, and sensitive workflows.",
|
|
@@ -645,7 +646,7 @@ async function createInitialState(config, sessionId) {
|
|
|
645
646
|
`Task profile: ${taskProfile.label}. ${taskProfile.prompt}`,
|
|
646
647
|
skillContext,
|
|
647
648
|
engineeringGuidance,
|
|
648
|
-
"A frontend canvas/artifacts tunnel exists. Use send_to_canvas when important markdown, diffs, screenshots, images, or workspace files should be highlighted in the UI. File paths sent to canvas are copied into session artifacts for durable preview, but user-requested outputs should also remain in a clear workspace path unless the user asked only for a temporary preview.",
|
|
649
|
+
"A frontend canvas/artifacts tunnel exists. Use send_to_canvas when important markdown, diffs, screenshots, images, or workspace files should be highlighted in the UI. File paths sent to canvas are copied into session artifacts for durable preview, but user-requested outputs should also remain in a clear workspace path unless the user asked only for a temporary preview. Do not use canvas for ordinary greetings or short chat replies.",
|
|
649
650
|
"For visual-output requests such as draw, plot, graph, chart, diagram, figure, image, or visualization, proactively publish a canvas artifact even when the user does not mention canvas. If workspace file tools are enabled, prefer creating a small SVG or markdown artifact and call send_to_canvas with selected=true.",
|
|
650
651
|
"Work like a practical coding agent: orient with inspect_project/search/read, patch code with apply_patch, run safe checks when they add confidence, iterate on failures, and keep outputs inside the workspace.",
|
|
651
652
|
"For large projects, decompose into useful files and milestones, identify entry points/tests/contracts first, implement a coherent minimal version, then iterate with checks rather than only describing what you would do.",
|
|
@@ -1107,6 +1108,40 @@ function appendChatEntry(state, role, content) {
|
|
|
1107
1108
|
});
|
|
1108
1109
|
}
|
|
1109
1110
|
|
|
1111
|
+
async function finishWithDirectAnswer({ config, state, store, observers, sessionId, intent }) {
|
|
1112
|
+
const result = redactSensitiveText(intent.directAnswer || "I'm here. How can I help?");
|
|
1113
|
+
state.meta = state.meta || {};
|
|
1114
|
+
state.meta.goalIntent = intent;
|
|
1115
|
+
state.updatedAt = new Date().toISOString();
|
|
1116
|
+
state.messages.push({
|
|
1117
|
+
role: "assistant",
|
|
1118
|
+
content: result,
|
|
1119
|
+
});
|
|
1120
|
+
appendChatEntry(state, "assistant", result);
|
|
1121
|
+
await store.saveState(state);
|
|
1122
|
+
await store.appendEvent("intent.classified", intent);
|
|
1123
|
+
await store.appendEvent("session.finished", {
|
|
1124
|
+
result,
|
|
1125
|
+
mode: "direct-answer",
|
|
1126
|
+
intent: {
|
|
1127
|
+
kind: intent.kind,
|
|
1128
|
+
reason: intent.reason,
|
|
1129
|
+
requiresTools: intent.requiresTools,
|
|
1130
|
+
},
|
|
1131
|
+
});
|
|
1132
|
+
observers.event("intent.classified", intent);
|
|
1133
|
+
observers.event("session.finished", {
|
|
1134
|
+
result,
|
|
1135
|
+
sessionId,
|
|
1136
|
+
mode: "direct-answer",
|
|
1137
|
+
});
|
|
1138
|
+
emitConsole(config, result, { kind: "assistant", markdown: true });
|
|
1139
|
+
return {
|
|
1140
|
+
sessionId,
|
|
1141
|
+
result,
|
|
1142
|
+
};
|
|
1143
|
+
}
|
|
1144
|
+
|
|
1110
1145
|
async function applyContinuationPrompt(state, config, observers) {
|
|
1111
1146
|
if (!config.resume || !config.goal) return;
|
|
1112
1147
|
|
|
@@ -2360,6 +2395,16 @@ export async function runAgent(config) {
|
|
|
2360
2395
|
|
|
2361
2396
|
try {
|
|
2362
2397
|
throwIfAborted(config);
|
|
2398
|
+
const goalIntent = classifyGoalIntent(config.goal);
|
|
2399
|
+
const canFinishDirectly =
|
|
2400
|
+
!config.resume && !state.plan && Number(state.stepsCompleted || 0) === 0 && isDirectAnswerIntent(goalIntent);
|
|
2401
|
+
if (canFinishDirectly) {
|
|
2402
|
+
return await finishWithDirectAnswer({ config, state, store, observers, sessionId, intent: goalIntent });
|
|
2403
|
+
}
|
|
2404
|
+
|
|
2405
|
+
state.meta = state.meta || {};
|
|
2406
|
+
state.meta.goalIntent = goalIntent;
|
|
2407
|
+
|
|
2363
2408
|
const scoutsWillRun = shouldRunParallelScouts(config, state);
|
|
2364
2409
|
if (!scoutsWillRun) {
|
|
2365
2410
|
await maybePrepareSurgicalContext(config, state, store, observers);
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
const GREETING_PATTERNS = [
|
|
2
|
+
/^(hi|hello|hey|hiya|yo|sup|howdy|good\s+(morning|afternoon|evening))[\s!.。!]*$/i,
|
|
3
|
+
/^(你好|您好|嗨|哈喽|哈啰|早上好|下午好|晚上好)[\s!.。!]*$/i,
|
|
4
|
+
/^(こんにちは|こんばんは|おはよう|おはようございます|やあ|もしもし)[\s!.。!]*$/i,
|
|
5
|
+
/^(안녕하세요|안녕|여보세요)[\s!.。!]*$/i,
|
|
6
|
+
/^(bonjour|salut|hola|hallo|ciao|olá|ola|namaste)[\s!.。!]*$/i,
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
const THANKS_PATTERNS = [
|
|
10
|
+
/^(thanks|thank\s+you|thx|ty|much\s+appreciated)[\s!.。!]*$/i,
|
|
11
|
+
/^(谢谢|多谢|感谢|辛苦了)[\s!.。!]*$/i,
|
|
12
|
+
/^(ありがとう|ありがとうございます|助かりました)[\s!.。!]*$/i,
|
|
13
|
+
];
|
|
14
|
+
|
|
15
|
+
const TOOL_INTENT_RE =
|
|
16
|
+
/\b(create|write|edit|update|fix|patch|modify|delete|remove|rename|move|copy|save|generate|draw|plot|build|compile|run|execute|test|debug|install|download|upload|clone|commit|push|publish|deploy|open|browse|search|read|inspect|analyze|analyse|summarize|summarise|convert|extract|classify|compare|review)\b/i;
|
|
17
|
+
|
|
18
|
+
const FILE_OR_COMMAND_HINT_RE =
|
|
19
|
+
/(^|\s)(\.{0,2}\/|~\/|[A-Za-z]:\\|[\w.-]+\.(js|ts|jsx|tsx|py|md|tex|json|csv|tsv|txt|yaml|yml|html|css|svg|png|jpg|jpeg|pdf|zip|tar|gz|sh|bash|zsh|rs|go|java|c|cpp|h|hpp|sql)\b|npm\s|node\s|python\s|pip\s|git\s|curl\s|wget\s|docker\s|tmux\s)/i;
|
|
20
|
+
|
|
21
|
+
function normalizedGoal(goal = "") {
|
|
22
|
+
return String(goal || "")
|
|
23
|
+
.replace(/\s+/g, " ")
|
|
24
|
+
.trim();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function directGreetingAnswer(goal) {
|
|
28
|
+
const text = normalizedGoal(goal);
|
|
29
|
+
if (/谢谢|多谢|感谢|辛苦了/.test(text)) return "不用谢。";
|
|
30
|
+
if (/ありがとう|ありがとうございます|助かりました/.test(text)) return "どういたしまして。";
|
|
31
|
+
if (/안녕|감사/.test(text)) return "천만에요.";
|
|
32
|
+
if (/你好|您好|嗨|哈喽|哈啰|早上好|下午好|晚上好/.test(text)) return "你好,我在。";
|
|
33
|
+
if (/こんにちは|こんばんは|おはよう|もしもし/.test(text)) return "こんにちは。";
|
|
34
|
+
if (/bonjour|salut/i.test(text)) return "Bonjour.";
|
|
35
|
+
if (/hola/i.test(text)) return "Hola.";
|
|
36
|
+
return "Hello. How can I help?";
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function looksLikeDirectGreetingRequest(text) {
|
|
40
|
+
return /^(say|reply|respond)\s+(hi|hello|hey)\b/i.test(text) && !TOOL_INTENT_RE.test(text.replace(/^(say|reply|respond)\s+/i, ""));
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export function classifyGoalIntent(goal, options = {}) {
|
|
44
|
+
const text = normalizedGoal(goal);
|
|
45
|
+
if (!text) {
|
|
46
|
+
return {
|
|
47
|
+
kind: "empty",
|
|
48
|
+
requiresTools: false,
|
|
49
|
+
directAnswer: "",
|
|
50
|
+
reason: "empty-input",
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (FILE_OR_COMMAND_HINT_RE.test(text) || TOOL_INTENT_RE.test(text)) {
|
|
55
|
+
return {
|
|
56
|
+
kind: "agentic",
|
|
57
|
+
requiresTools: true,
|
|
58
|
+
directAnswer: "",
|
|
59
|
+
reason: FILE_OR_COMMAND_HINT_RE.test(text) ? "file-or-command-hint" : "tool-intent-keyword",
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
if (GREETING_PATTERNS.some((pattern) => pattern.test(text)) || THANKS_PATTERNS.some((pattern) => pattern.test(text))) {
|
|
64
|
+
return {
|
|
65
|
+
kind: "casual",
|
|
66
|
+
requiresTools: false,
|
|
67
|
+
directAnswer: directGreetingAnswer(text),
|
|
68
|
+
reason: "short-social-turn",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (looksLikeDirectGreetingRequest(text)) {
|
|
73
|
+
return {
|
|
74
|
+
kind: "direct-answer",
|
|
75
|
+
requiresTools: false,
|
|
76
|
+
directAnswer: /japanese|日本語|日语|日文/i.test(text) ? "こんにちは。" : directGreetingAnswer(text),
|
|
77
|
+
reason: "explicit-greeting-answer",
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const shortQuestion = text.length <= 160 && /[??]$/.test(text);
|
|
82
|
+
if (shortQuestion && options.allowQuestionDirectAnswers) {
|
|
83
|
+
return {
|
|
84
|
+
kind: "direct-answer",
|
|
85
|
+
requiresTools: false,
|
|
86
|
+
directAnswer: "",
|
|
87
|
+
reason: "short-question",
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
kind: "agentic",
|
|
93
|
+
requiresTools: true,
|
|
94
|
+
directAnswer: "",
|
|
95
|
+
reason: "default-agentic",
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function isDirectAnswerIntent(intent = {}) {
|
|
100
|
+
return Boolean(intent && intent.requiresTools === false && (intent.kind === "casual" || intent.kind === "direct-answer"));
|
|
101
|
+
}
|
package/src/model-client.js
CHANGED
|
@@ -742,7 +742,7 @@ export async function createPlan(client, config, state) {
|
|
|
742
742
|
{
|
|
743
743
|
role: "system",
|
|
744
744
|
content:
|
|
745
|
-
`You are planning a browser, shell, workspace, and coding-agent task. The plan is only a launchpad: after planning, the runtime will continue with tools until the task is complete or genuinely blocked. Prefer real workspace edits/checks over advice-only answers. If a local shell command can satisfy
|
|
745
|
+
`You are planning a browser, shell, workspace, and coding-agent task. The plan is only a launchpad: after planning, the runtime will continue with tools until the task is complete or genuinely blocked. Use tools only when the user actually asks for workspace, browser, shell, web, canvas, image, MCP, or specialist work. For greetings, thanks, or simple conversational turns, finish directly; never invent file creation or shell work for them. Prefer real workspace edits/checks over advice-only answers only when the request is an explicit task or deliverable. If a local shell command can satisfy a local task, prefer that before browser actions. Treat any suggested start URL as optional. ${browserStateReconciliationGuidance()} ${formatBehaviorContractForPrompt({ mode: "plan" })} Write a concise execution plan with 3 to 6 steps only for requests that need execution. Mention risks or blockers when relevant. Keep it short and practical.`,
|
|
746
746
|
},
|
|
747
747
|
{
|
|
748
748
|
role: "user",
|
package/src/skill-library.js
CHANGED
|
@@ -100,15 +100,19 @@ function normalizeExternalTools(value) {
|
|
|
100
100
|
export function loadSkillFile(filePath) {
|
|
101
101
|
const text = fs.readFileSync(filePath, "utf8");
|
|
102
102
|
const { meta, body } = parseFrontmatter(text, filePath);
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
103
|
+
const id = String(meta.id || meta.name || "").trim();
|
|
104
|
+
if (!id) {
|
|
105
|
+
throw new Error(`${filePath}: id or name must be a non-empty string`);
|
|
106
|
+
}
|
|
107
|
+
const label = String(meta.label || titleCaseSkillId(id)).trim();
|
|
108
|
+
const description = String(meta.description || "").trim();
|
|
109
|
+
if (!description) {
|
|
110
|
+
throw new Error(`${filePath}: description must be a non-empty string`);
|
|
107
111
|
}
|
|
108
112
|
return {
|
|
109
|
-
id
|
|
110
|
-
label
|
|
111
|
-
description
|
|
113
|
+
id,
|
|
114
|
+
label,
|
|
115
|
+
description,
|
|
112
116
|
triggers: normalizeList(meta.triggers),
|
|
113
117
|
tools: normalizeList(meta.tools),
|
|
114
118
|
body,
|
package/src/skillmesh.js
CHANGED
|
@@ -321,6 +321,60 @@ function canonicalSkillContent(content = "") {
|
|
|
321
321
|
return String(content || "").replace(/\r\n/g, "\n").trim();
|
|
322
322
|
}
|
|
323
323
|
|
|
324
|
+
function titleCaseSkillId(id = "") {
|
|
325
|
+
return String(id || "")
|
|
326
|
+
.split(/[-_\s/]+/)
|
|
327
|
+
.filter(Boolean)
|
|
328
|
+
.map((part) => `${part.slice(0, 1).toUpperCase()}${part.slice(1)}`)
|
|
329
|
+
.join(" ");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
function parseSkillMarkdownContent(content = "", context = "SKILL.md") {
|
|
333
|
+
const text = String(content || "");
|
|
334
|
+
if (!text.trim()) throw new Error(`${context}: empty skill`);
|
|
335
|
+
if (Buffer.byteLength(text, "utf8") > MAX_SKILL_BYTES) throw new Error(`${context}: skill is too large`);
|
|
336
|
+
if (redactSensitiveText(text) !== text) throw new Error(`${context}: contains token-like secret text`);
|
|
337
|
+
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
338
|
+
if (!match) throw new Error(`${context}: missing YAML frontmatter`);
|
|
339
|
+
const frontmatter = match[1].replace(/\r\n/g, "\n");
|
|
340
|
+
const fields = {};
|
|
341
|
+
const passthrough = [];
|
|
342
|
+
for (const line of frontmatter.split(/\n/)) {
|
|
343
|
+
const scalar = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
344
|
+
if (scalar) {
|
|
345
|
+
const key = scalar[1];
|
|
346
|
+
const value = scalar[2].trim().replace(/^['"]|['"]$/g, "");
|
|
347
|
+
if (value) fields[key] = value;
|
|
348
|
+
if (["id", "name", "label", "description"].includes(key)) continue;
|
|
349
|
+
}
|
|
350
|
+
passthrough.push(line);
|
|
351
|
+
}
|
|
352
|
+
const id = fields.id || fields.name || "";
|
|
353
|
+
if (!id) throw new Error(`${context}: id or name is required`);
|
|
354
|
+
if (!safeSkillId(id)) throw new Error(`${context}: invalid skill id ${id}`);
|
|
355
|
+
const description = fields.description || "";
|
|
356
|
+
if (!description) throw new Error(`${context}: description is required`);
|
|
357
|
+
const label = fields.label || titleCaseSkillId(id);
|
|
358
|
+
return {
|
|
359
|
+
fields: { ...fields, id, label, description },
|
|
360
|
+
body: text.slice(match[0].length).trim(),
|
|
361
|
+
passthrough: passthrough.join("\n").trim(),
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
function normalizeSkillMarkdownForSkillMesh(content = "", context = "SKILL.md") {
|
|
366
|
+
const parsed = parseSkillMarkdownContent(content, context);
|
|
367
|
+
const frontmatter = [
|
|
368
|
+
"---",
|
|
369
|
+
`id: ${parsed.fields.id}`,
|
|
370
|
+
`label: ${parsed.fields.label}`,
|
|
371
|
+
`description: ${parsed.fields.description}`,
|
|
372
|
+
parsed.passthrough,
|
|
373
|
+
"---",
|
|
374
|
+
].filter((line) => line !== "");
|
|
375
|
+
return `${frontmatter.join("\n")}\n\n${parsed.body}`.trim();
|
|
376
|
+
}
|
|
377
|
+
|
|
324
378
|
function canonicalPackForSignature(pack) {
|
|
325
379
|
const copy = { ...pack };
|
|
326
380
|
delete copy.signature;
|
|
@@ -382,25 +436,7 @@ function verifyPackSignature(pack) {
|
|
|
382
436
|
}
|
|
383
437
|
|
|
384
438
|
function validateSkillMarkdownContent(content = "", context = "SKILL.md") {
|
|
385
|
-
|
|
386
|
-
if (!text.trim()) throw new Error(`${context}: empty skill`);
|
|
387
|
-
if (Buffer.byteLength(text, "utf8") > MAX_SKILL_BYTES) throw new Error(`${context}: skill is too large`);
|
|
388
|
-
if (redactSensitiveText(text) !== text) throw new Error(`${context}: contains token-like secret text`);
|
|
389
|
-
const match = text.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n?/);
|
|
390
|
-
if (!match) throw new Error(`${context}: missing YAML frontmatter`);
|
|
391
|
-
const frontmatter = match[1];
|
|
392
|
-
const fields = {};
|
|
393
|
-
for (const line of frontmatter.split(/\r?\n/)) {
|
|
394
|
-
const scalar = line.match(/^([A-Za-z0-9_-]+):\s*(.*)$/);
|
|
395
|
-
if (!scalar) continue;
|
|
396
|
-
const value = scalar[2].trim().replace(/^['"]|['"]$/g, "");
|
|
397
|
-
if (value) fields[scalar[1]] = value;
|
|
398
|
-
}
|
|
399
|
-
for (const field of ["id", "label", "description"]) {
|
|
400
|
-
if (!fields[field]) throw new Error(`${context}: ${field} is required`);
|
|
401
|
-
}
|
|
402
|
-
if (!safeSkillId(fields.id)) throw new Error(`${context}: invalid skill id ${fields.id}`);
|
|
403
|
-
return fields;
|
|
439
|
+
return parseSkillMarkdownContent(content, context).fields;
|
|
404
440
|
}
|
|
405
441
|
|
|
406
442
|
function builtInSkillIds() {
|
|
@@ -420,7 +456,7 @@ export async function buildSkillPack(skillId, { home = agintiflowHome(), author
|
|
|
420
456
|
export async function buildSkillPackFromMarkdown(content, { home = agintiflowHome(), author = "local-user", valueScore = 80 } = {}) {
|
|
421
457
|
const fields = validateSkillMarkdownContent(content, "SKILL.md");
|
|
422
458
|
const id = fields.id;
|
|
423
|
-
const normalized =
|
|
459
|
+
const normalized = normalizeSkillMarkdownForSkillMesh(content, "SKILL.md");
|
|
424
460
|
const entry = {
|
|
425
461
|
id,
|
|
426
462
|
path: `skills/${id}/SKILL.md`,
|
package/src/task-profiles.js
CHANGED
|
@@ -3,7 +3,7 @@ export const TASK_PROFILES = {
|
|
|
3
3
|
id: "auto",
|
|
4
4
|
label: "Auto",
|
|
5
5
|
prompt:
|
|
6
|
-
"Act as the general-purpose AgInTiFlow agent. Infer the task type from the request, then choose the right mix of browser, shell, files, web search, canvas, and sandbox tools. For short tasks, use the smallest safe tool sequence that completes the work. For browser form/composer workflows, reconcile toward the requested state: inspect, set missing controls, verify, then submit when requested. For codebase, writing, website, LaTeX, system, debugging, migration, data cleanup, reporting, or multi-language tasks, automatically borrow the relevant specialized profile habits without becoming narrowly constrained. When you create or repair a deliverable, verify the produced output and polish obvious noise, duplicates, broken formatting, stale filenames, or misleading summaries before finalizing.",
|
|
6
|
+
"Act as the general-purpose AgInTiFlow agent. Infer the task type from the request, then choose the right mix of browser, shell, files, web search, canvas, and sandbox tools only when tools are actually needed. For greetings, thanks, or simple conversational turns, answer directly without creating files, running commands, opening browsers, or sending canvas artifacts. For short explicit tasks, use the smallest safe tool sequence that completes the work. For browser form/composer workflows, reconcile toward the requested state: inspect, set missing controls, verify, then submit when requested. For codebase, writing, website, LaTeX, system, debugging, migration, data cleanup, reporting, or multi-language tasks, automatically borrow the relevant specialized profile habits without becoming narrowly constrained. When you create or repair a deliverable, verify the produced output and polish obvious noise, duplicates, broken formatting, stale filenames, or misleading summaries before finalizing.",
|
|
7
7
|
tools: ["browser", "shell", "files", "canvas", "inspect_project"],
|
|
8
8
|
},
|
|
9
9
|
code: {
|