@autonomos/core 0.0.1 → 0.1.0
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/dist/index.d.mts +277 -7
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +30 -11
- package/dist/index.mjs.map +1 -0
- package/dist/workflows/protocol-crystallize.md +48 -0
- package/dist/workflows/protocol-session.md +50 -0
- package/dist/workflows/protocol-task.md +37 -0
- package/package.json +29 -10
- package/.turbo/turbo-build.log +0 -15
- package/eslint.config.ts +0 -18
- package/lint-staged.config.mjs +0 -4
- package/prettier.config.mjs +0 -3
- package/src/constants.ts +0 -35
- package/src/index.ts +0 -17
- package/src/parsers/agent-parser.test.ts +0 -61
- package/src/parsers/agent-parser.ts +0 -80
- package/src/parsers/task-parser.test.ts +0 -60
- package/src/parsers/task-parser.ts +0 -40
- package/src/schemas/manifest.ts +0 -13
- package/src/templates/agent.ts +0 -43
- package/src/templates/manifest.test.ts +0 -26
- package/src/templates/manifest.ts +0 -30
- package/src/templates/protocol.ts +0 -157
- package/src/templates/tasks.ts +0 -18
- package/src/templates/worklog.test.ts +0 -37
- package/src/templates/worklog.ts +0 -55
- package/src/types.ts +0 -51
- package/tsconfig.json +0 -36
- package/tsdown.config.ts +0 -10
- package/vitest.config.ts +0 -9
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: protocol-crystallize
|
|
3
|
+
description: 'Mandatory close-out procedure for any session. Invoked before declaring the session done. Forces the agent to crystallize learnings into AGENT.md files.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Protocol Crystallize
|
|
7
|
+
|
|
8
|
+
**Goal:** Convert session activity into durable project knowledge.
|
|
9
|
+
**Your Role:** Reflective agent that improves the project for the next session.
|
|
10
|
+
|
|
11
|
+
## STEP 0 — STOP
|
|
12
|
+
|
|
13
|
+
DO NOT close the session before every step below is complete.
|
|
14
|
+
|
|
15
|
+
## STEP 1 — Worklog
|
|
16
|
+
|
|
17
|
+
Create or complete `.autonomos/worklogs/YYYY-MM-DD-[TASK_ID].md`. Free format, but MUST contain:
|
|
18
|
+
|
|
19
|
+
- A summary of what was done
|
|
20
|
+
- The technical decisions made and why
|
|
21
|
+
- The files modified
|
|
22
|
+
- Clear next steps (for the next session)
|
|
23
|
+
|
|
24
|
+
## STEP 2 — Crystallize into AGENT.md files
|
|
25
|
+
|
|
26
|
+
Ask yourself these three questions. For each, you MUST answer honestly. Do NOT say "nothing new".
|
|
27
|
+
|
|
28
|
+
**Question 1:** `What did I learn of significance about this project during this session?` (preferences, constraints, discovered conventions, user corrections, etc.)
|
|
29
|
+
|
|
30
|
+
If the answer is not `nothing`, write it to the relevant AGENT.md (root or subfolder). No format is imposed. One line is enough if it is clear.
|
|
31
|
+
|
|
32
|
+
**Question 2:** `Has any AGENT.md entry been contradicted or superseded?` If yes, update the relevant AGENT.md entry **in place** — the file is a current-state document, not a changelog. Then record the change in the worklog of this session (e.g. `PREF-007: GSAP → Motion, superseded by PREF-009`). Do NOT append superseded entries to AGENT.md; do NOT keep both.
|
|
33
|
+
|
|
34
|
+
**Question 3:** `Is there something in the worklog that should have been in an AGENT.md and is not yet?` If yes, lift it out of the worklog and put it in the AGENT.md.
|
|
35
|
+
|
|
36
|
+
## STEP 3 — Task status
|
|
37
|
+
|
|
38
|
+
Mark the task as `[x]` (or `[!]` if blocked) in `.autonomos/TASKS.md`.
|
|
39
|
+
|
|
40
|
+
## STEP 4 — Final verification
|
|
41
|
+
|
|
42
|
+
RESPOND to the user with:
|
|
43
|
+
|
|
44
|
+
- `Task: [x] / [!] — [ID]`
|
|
45
|
+
- `Worklog created: .autonomos/worklogs/...`
|
|
46
|
+
- `AGENT.md updated: [yes / no, and why]`
|
|
47
|
+
|
|
48
|
+
If you cannot produce these three lines, the session is not complete. Resume from Step 1.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: protocol-session
|
|
3
|
+
description: 'Mandatory bootstrap for any new session on a project following the Autonomos protocol. Invoked at the start of every session, before any work begins.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Protocol Session
|
|
7
|
+
|
|
8
|
+
**Goal:** Load all project context, identify the next task, and establish a clean working state.
|
|
9
|
+
**Your Role:** Disciplined agent that respects the project's accumulated knowledge.
|
|
10
|
+
|
|
11
|
+
## STEP 0 — STOP
|
|
12
|
+
|
|
13
|
+
You are starting a new session. You MUST complete Steps 1, 2, and 3 before any other action.
|
|
14
|
+
|
|
15
|
+
DO NOT skip steps. DO NOT begin work before Step 3 is complete.
|
|
16
|
+
|
|
17
|
+
## STEP 1 — Load context (three mandatory reads)
|
|
18
|
+
|
|
19
|
+
1. Read the root `AGENT.md`. This is your project identity.
|
|
20
|
+
2. Run `autonomos agents` (no argument) to get the **full tree of all AGENT.md files in the project**. Read each one. This is your full fractal context — it lets you discover shared packages, cross-cutting conventions, and traps before starting any work.
|
|
21
|
+
3. Read the most recent file in `.autonomos/worklogs/`. This is the memory of the previous session — read it to avoid repeating the same mistakes.
|
|
22
|
+
|
|
23
|
+
RESPOND to the user with a 5-line maximum summary of what you have retained. You are FORBIDDEN to continue without this response.
|
|
24
|
+
|
|
25
|
+
## STEP 2 — Identify the next task
|
|
26
|
+
|
|
27
|
+
Open `.autonomos/TASKS.md`. Identify the highest-priority task that is not yet `[x]`. If none qualify, ask the user what to work on.
|
|
28
|
+
|
|
29
|
+
RESPOND with: `Task selected: [ID] — [title]. Starting.`
|
|
30
|
+
|
|
31
|
+
## STEP 3 — Mark the task and begin
|
|
32
|
+
|
|
33
|
+
- Edit `.autonomos/TASKS.md` to change this task's status from `[ ]` to `[/]`.
|
|
34
|
+
- NOW you may begin working.
|
|
35
|
+
|
|
36
|
+
## REMINDER — applies to the entire session
|
|
37
|
+
|
|
38
|
+
- **RAPPEL 1:** For every non-trivial decision (library choice, naming, structure, framework), STOP and ask: "Does an AGENT.md say something about this?" If yes, apply it. If no, propose the decision to the user.
|
|
39
|
+
- **RAPPEL 2:** Every time you learn something important (the user corrects you, you discover a convention, you make a technical choice), STOP. Write it immediately to an AGENT.md (root or subfolder, depending on scope). Do NOT say "I'll note it later". It is NOW.
|
|
40
|
+
- **RAPPEL 3:** No format is imposed on AGENT.md content. One line is enough if it's clear. What matters is that the next session can use it.
|
|
41
|
+
|
|
42
|
+
## FINAL STEP (MANDATORY before saying "session done")
|
|
43
|
+
|
|
44
|
+
You CANNOT end a session without all three of the following. DO NOT say "done" until each box is checked.
|
|
45
|
+
|
|
46
|
+
- [ ] Task status in TASKS.md is `[x]` (or `[!]` if blocked)
|
|
47
|
+
- [ ] A worklog exists at `.autonomos/worklogs/YYYY-MM-DD-[TASK_ID].md` containing: what was done, decisions made, files modified, and clear next steps
|
|
48
|
+
- [ ] You have asked the user the following question and recorded the answer in the worklog: `What did this session learn about this project that deserves to live in an AGENT.md?`
|
|
49
|
+
|
|
50
|
+
When all three boxes are checked, you may say `session complete`.
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: protocol-task
|
|
3
|
+
description: 'Mandatory procedure for starting a new task within an active session. Invoked at task start, before any code is touched.'
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Protocol Task
|
|
7
|
+
|
|
8
|
+
**Goal:** Confirm context, declare intent, and avoid scope drift.
|
|
9
|
+
**Your Role:** Disciplined agent that respects local conventions.
|
|
10
|
+
|
|
11
|
+
## STEP 0 — STOP
|
|
12
|
+
|
|
13
|
+
You are about to begin a new task. DO NOT touch code before the end of Step 2.
|
|
14
|
+
|
|
15
|
+
## STEP 1 — Build the precise fractal context for this task
|
|
16
|
+
|
|
17
|
+
1. Run `autonomos agents <path-to-target-file-or-folder>` to get the **ordered list of ancestor AGENT.md files** for the file or folder you'll be working in. The output is root-first; non-existent ancestors are silently skipped.
|
|
18
|
+
2. Read each returned AGENT.md **in order** (root → target). This is your precise fractal context for this task.
|
|
19
|
+
3. If no local `AGENT.md` exists at the target AND you have worked in that folder multiple times before, propose to the user: `This folder has no AGENT.md yet. Should we create one to crystallize the conventions we have established here?`
|
|
20
|
+
|
|
21
|
+
## STEP 2 — Declare the plan
|
|
22
|
+
|
|
23
|
+
State in 3 to 5 steps what you intend to do for this task. No more. The user must be able to say `OK` or adjust before you begin.
|
|
24
|
+
|
|
25
|
+
## STEP 3 — Execute
|
|
26
|
+
|
|
27
|
+
Mark the task `[/]` in TASKS.md, then execute your plan.
|
|
28
|
+
|
|
29
|
+
## DURING EXECUTION — three reminders
|
|
30
|
+
|
|
31
|
+
- **REMINDER 1:** For every non-trivial decision, consult the relevant AGENT.md.
|
|
32
|
+
- **REMINDER 2:** For every new learning, append a new line to an AGENT.md. If the new learning contradicts an existing one, replace the old entry in place and log the change in the worklog. AGENT.md stays a sharp current-state document, not a log.
|
|
33
|
+
- **REMINDER 3:** You may edit any AGENT.md at any time. No format is imposed. What matters is that the next session can use it.
|
|
34
|
+
|
|
35
|
+
## END OF TASK
|
|
36
|
+
|
|
37
|
+
When the task is complete, mark it `[x]` in TASKS.md and invoke the `protocol-crystallize` workflow.
|
package/package.json
CHANGED
|
@@ -1,27 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@autonomos/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.1.0",
|
|
4
4
|
"description": "SDK and core definitions for the Agent Protocol",
|
|
5
5
|
"type": "module",
|
|
6
|
-
"main": "./dist/index.mjs",
|
|
7
6
|
"types": "./dist/index.d.mts",
|
|
8
7
|
"keywords": [
|
|
9
8
|
"agent",
|
|
10
9
|
"protocol",
|
|
11
10
|
"ai",
|
|
12
|
-
"workflow"
|
|
11
|
+
"workflow",
|
|
12
|
+
"ai-agent",
|
|
13
|
+
"mcp",
|
|
14
|
+
"autonomy"
|
|
13
15
|
],
|
|
14
16
|
"author": "Autonomos",
|
|
15
17
|
"license": "MIT",
|
|
18
|
+
"repository": {
|
|
19
|
+
"type": "git",
|
|
20
|
+
"url": "git+https://github.com/saoudi-h/autonomos.git",
|
|
21
|
+
"directory": "packages/core"
|
|
22
|
+
},
|
|
23
|
+
"bugs": {
|
|
24
|
+
"url": "https://github.com/saoudi-h/autonomos/issues"
|
|
25
|
+
},
|
|
26
|
+
"homepage": "https://github.com/saoudi-h/autonomos/tree/main/packages/core#readme",
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"files": [
|
|
31
|
+
"dist",
|
|
32
|
+
"README.md",
|
|
33
|
+
"LICENSE"
|
|
34
|
+
],
|
|
16
35
|
"devDependencies": {
|
|
36
|
+
"@tala-tools/eslint": "0.1.3",
|
|
37
|
+
"@tala-tools/prettier": "0.0.3",
|
|
38
|
+
"@tala-tools/tsconfig": "0.0.1",
|
|
39
|
+
"@tala-tools/tsdown": "0.1.3",
|
|
17
40
|
"@types/js-yaml": "4.0.9",
|
|
18
41
|
"typescript": "^5.0.0",
|
|
19
|
-
"@repo/eslint": "1.0.0",
|
|
20
|
-
"@repo/prettier": "1.0.0",
|
|
21
|
-
"@repo/tsdown": "1.0.0",
|
|
22
42
|
"@repo/vitest": "1.0.0"
|
|
23
43
|
},
|
|
24
|
-
"module": "./dist/index.mjs",
|
|
25
44
|
"exports": {
|
|
26
45
|
".": "./dist/index.mjs",
|
|
27
46
|
"./package.json": "./package.json"
|
|
@@ -32,13 +51,13 @@
|
|
|
32
51
|
},
|
|
33
52
|
"scripts": {
|
|
34
53
|
"dev": "tsdown --watch",
|
|
35
|
-
"build": "tsdown",
|
|
54
|
+
"build": "tsdown && cp ../../LICENSE .",
|
|
36
55
|
"lint": "eslint . --max-warnings 0",
|
|
37
56
|
"lint:fix": "eslint . --max-warnings 0 --fix",
|
|
38
57
|
"format:check": "prettier \"**/*\" --ignore-unknown --list-different",
|
|
39
58
|
"format:fix": "prettier \"**/*\" --ignore-unknown --write",
|
|
40
|
-
"clean": "rimraf node_modules dist",
|
|
41
|
-
"typecheck": "
|
|
59
|
+
"clean": "rimraf node_modules dist LICENSE",
|
|
60
|
+
"typecheck": "tsgo --noEmit",
|
|
42
61
|
"test": "vitest",
|
|
43
62
|
"test:ui": "vitest --ui",
|
|
44
63
|
"test:run": "vitest run",
|
package/.turbo/turbo-build.log
DELETED
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
> @autonomos/core@0.0.1 build /home/runner/work/autonomos/autonomos/packages/core
|
|
3
|
-
> tsdown
|
|
4
|
-
|
|
5
|
-
[34mℹ[39m tsdown [2mv0.18.4[22m powered by rolldown [2mv1.0.0-beta.57[22m
|
|
6
|
-
[34mℹ[39m config file: [4m/home/runner/work/autonomos/autonomos/packages/core/tsdown.config.ts[24m
|
|
7
|
-
[34mℹ[39m entry: [34msrc/index.ts[39m
|
|
8
|
-
[34mℹ[39m tsconfig: [34mtsconfig.json[39m
|
|
9
|
-
[34mℹ[39m Build start
|
|
10
|
-
[34mℹ[39m [2mdist/[22m[1mindex.mjs[22m [2m 9.78 kB[22m [2m│ gzip: 4.19 kB[22m
|
|
11
|
-
[34mℹ[39m [2mdist/[22m[32m[1mindex.d.mts[22m[39m [2m17.09 kB[22m [2m│ gzip: 4.28 kB[22m
|
|
12
|
-
[34mℹ[39m 2 files, total: 26.88 kB
|
|
13
|
-
[32m✔[39m Build complete in [32m1302ms[39m
|
|
14
|
-
[32m✔[39m [2m[publint][22m No issues found [2m(329ms)[22m
|
|
15
|
-
🙏 Build succeeded!
|
package/eslint.config.ts
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import type { Config } from '@repo/eslint'
|
|
2
|
-
import { base } from '@repo/eslint'
|
|
3
|
-
import { defineConfig } from 'eslint/config'
|
|
4
|
-
|
|
5
|
-
const config: Config[] = defineConfig([
|
|
6
|
-
...base,
|
|
7
|
-
{
|
|
8
|
-
ignores: [
|
|
9
|
-
'eslint.config.ts',
|
|
10
|
-
'eslint-types.d.ts',
|
|
11
|
-
'prettier.config.mjs',
|
|
12
|
-
'lint-staged.config.mjs',
|
|
13
|
-
'tsdown.config.ts',
|
|
14
|
-
],
|
|
15
|
-
},
|
|
16
|
-
])
|
|
17
|
-
|
|
18
|
-
export default config
|
package/lint-staged.config.mjs
DELETED
package/prettier.config.mjs
DELETED
package/src/constants.ts
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Protocol version using SemVer
|
|
3
|
-
* Alpha phase - not yet published to npm
|
|
4
|
-
*/
|
|
5
|
-
export const PROTOCOL_VERSION = '0.1.0-alpha'
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Directory name for Autonomos configuration
|
|
9
|
-
*/
|
|
10
|
-
export const AUTONOMOS_DIR = '.autonomos'
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Manifest filename
|
|
14
|
-
*/
|
|
15
|
-
export const MANIFEST_FILE = 'manifest.json'
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Protocol filename
|
|
19
|
-
*/
|
|
20
|
-
export const PROTOCOL_FILE = 'PROTOCOL.md'
|
|
21
|
-
|
|
22
|
-
/**
|
|
23
|
-
* Tasks filename
|
|
24
|
-
*/
|
|
25
|
-
export const TASKS_FILE = 'TASKS.md'
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Agent context filename (at project root)
|
|
29
|
-
*/
|
|
30
|
-
export const AGENT_FILE = 'AGENT.md'
|
|
31
|
-
|
|
32
|
-
/**
|
|
33
|
-
* Worklogs directory name
|
|
34
|
-
*/
|
|
35
|
-
export const WORKLOGS_DIR = 'worklogs'
|
package/src/index.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
// Constants
|
|
2
|
-
export * from './constants'
|
|
3
|
-
export * from './schemas/manifest'
|
|
4
|
-
|
|
5
|
-
// Types
|
|
6
|
-
export * from './types'
|
|
7
|
-
|
|
8
|
-
// Templates
|
|
9
|
-
export * from './templates/agent'
|
|
10
|
-
export * from './templates/manifest'
|
|
11
|
-
export * from './templates/protocol'
|
|
12
|
-
export * from './templates/tasks'
|
|
13
|
-
export * from './templates/worklog'
|
|
14
|
-
|
|
15
|
-
// Parsers
|
|
16
|
-
export * from './parsers/agent-parser'
|
|
17
|
-
export * from './parsers/task-parser'
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { AgentParser } from './agent-parser'
|
|
3
|
-
|
|
4
|
-
describe('AgentParser', () => {
|
|
5
|
-
it('should parse an AGENT.md with standard title correctly', () => {
|
|
6
|
-
const markdown = '# AGENT CONTEXT: My Project\n\n## Section 1\nHello'
|
|
7
|
-
const context = AgentParser.parse(markdown)
|
|
8
|
-
expect(context.title).toBe('My Project')
|
|
9
|
-
expect(context.sections).toHaveLength(1)
|
|
10
|
-
expect(context.sections[0]!.title).toBe('Section 1')
|
|
11
|
-
expect(context.sections[0]!.content).toBe('Hello')
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
it('should parse multiple sections correctly', () => {
|
|
15
|
-
const markdown = `
|
|
16
|
-
# AGENT CONTEXT: Test
|
|
17
|
-
## Context & Objectives
|
|
18
|
-
Objective 1
|
|
19
|
-
## Workflow & Preferences
|
|
20
|
-
Strict Linting
|
|
21
|
-
`
|
|
22
|
-
const context = AgentParser.parse(markdown)
|
|
23
|
-
expect(context.sections).toHaveLength(2)
|
|
24
|
-
expect(context.sections[0]!.title).toBe('Context & Objectives')
|
|
25
|
-
expect(context.sections[0]!.content).toBe('Objective 1')
|
|
26
|
-
expect(context.sections[1]!.title).toBe('Workflow & Preferences')
|
|
27
|
-
expect(context.sections[1]!.content).toBe('Strict Linting')
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
it('should handle alternative title format', () => {
|
|
31
|
-
const markdown = '# Simple Title\n## Content'
|
|
32
|
-
const context = AgentParser.parse(markdown)
|
|
33
|
-
expect(context.title).toBe('Simple Title')
|
|
34
|
-
})
|
|
35
|
-
|
|
36
|
-
it('should parse YAML frontmatter correctly', () => {
|
|
37
|
-
const markdown = `---
|
|
38
|
-
name: "Advanced Agent"
|
|
39
|
-
stack: ["React", "Node"]
|
|
40
|
-
status: "Active"
|
|
41
|
-
---
|
|
42
|
-
# AGENT CONTEXT: Should ignore H1 if name exists
|
|
43
|
-
## Section 1
|
|
44
|
-
Content`
|
|
45
|
-
const context = AgentParser.parse(markdown)
|
|
46
|
-
expect(context.title).toBe('Advanced Agent')
|
|
47
|
-
expect(context.metadata).toEqual({
|
|
48
|
-
name: 'Advanced Agent',
|
|
49
|
-
stack: ['React', 'Node'],
|
|
50
|
-
status: 'Active',
|
|
51
|
-
})
|
|
52
|
-
expect(context.sections).toHaveLength(1)
|
|
53
|
-
expect(context.sections[0]!.title).toBe('Section 1')
|
|
54
|
-
})
|
|
55
|
-
|
|
56
|
-
it('should return default title if missing', () => {
|
|
57
|
-
const markdown = '## No Title'
|
|
58
|
-
const context = AgentParser.parse(markdown)
|
|
59
|
-
expect(context.title).toBe('Unknown Agent')
|
|
60
|
-
})
|
|
61
|
-
})
|
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import yaml from 'js-yaml'
|
|
2
|
-
import type { AgentContext, AgentSection } from '../types'
|
|
3
|
-
|
|
4
|
-
export class AgentParser {
|
|
5
|
-
/**
|
|
6
|
-
* Parse an AGENT.md content into a structured AgentContext
|
|
7
|
-
*/
|
|
8
|
-
static parse(markdown: string): AgentContext {
|
|
9
|
-
let content = markdown
|
|
10
|
-
let metadata: Record<string, any> = {}
|
|
11
|
-
|
|
12
|
-
// Parse Frontmatter
|
|
13
|
-
const frontmatterRegex = /^---\r?\n([\s\S]*?)\r?\n---/
|
|
14
|
-
const match = markdown.match(frontmatterRegex)
|
|
15
|
-
if (match) {
|
|
16
|
-
try {
|
|
17
|
-
metadata = yaml.load(match[1] as string) as Record<string, any>
|
|
18
|
-
content = markdown.slice(match[0].length).trim()
|
|
19
|
-
} catch (e) {
|
|
20
|
-
console.error('Failed to parse Agent frontmatter:', e)
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const lines = content.split(/\r?\n/)
|
|
25
|
-
const sections: AgentSection[] = []
|
|
26
|
-
let title = metadata.name ?? 'Unknown Agent'
|
|
27
|
-
let currentSection: AgentSection | null = null
|
|
28
|
-
let currentContent: string[] = []
|
|
29
|
-
|
|
30
|
-
for (const line of lines) {
|
|
31
|
-
// Parse Title (Only if not already set by frontmatter)
|
|
32
|
-
if (line.startsWith('# ') && !metadata.name) {
|
|
33
|
-
const rawTitle = line.replace('# ', '').trim()
|
|
34
|
-
// Handle "AGENT CONTEXT: [Name]" format
|
|
35
|
-
if (rawTitle.toUpperCase().startsWith('AGENT CONTEXT:')) {
|
|
36
|
-
title = rawTitle
|
|
37
|
-
.slice(14)
|
|
38
|
-
.replace(/^[:\s-]+/, '')
|
|
39
|
-
.trim()
|
|
40
|
-
} else {
|
|
41
|
-
title = rawTitle
|
|
42
|
-
}
|
|
43
|
-
continue
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Parse Sections
|
|
47
|
-
if (line.startsWith('## ')) {
|
|
48
|
-
// Save previous section
|
|
49
|
-
if (currentSection) {
|
|
50
|
-
currentSection.content = currentContent.join('\n').trim()
|
|
51
|
-
sections.push(currentSection)
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
currentSection = {
|
|
55
|
-
title: line.replace('## ', '').trim(),
|
|
56
|
-
content: '',
|
|
57
|
-
}
|
|
58
|
-
currentContent = []
|
|
59
|
-
continue
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
// Collect content
|
|
63
|
-
if (currentSection) {
|
|
64
|
-
currentContent.push(line)
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Save last section
|
|
69
|
-
if (currentSection) {
|
|
70
|
-
currentSection.content = currentContent.join('\n').trim()
|
|
71
|
-
sections.push(currentSection)
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
return {
|
|
75
|
-
title,
|
|
76
|
-
sections,
|
|
77
|
-
metadata,
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
@@ -1,60 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { TaskParser } from './task-parser'
|
|
3
|
-
|
|
4
|
-
describe('TaskParser', () => {
|
|
5
|
-
it('should parse a TODO task correctly', () => {
|
|
6
|
-
const markdown = '- [ ] **[TASK-01]** Initial task `Priority: 🔴 Critical` `Complexity: S`'
|
|
7
|
-
const tasks = TaskParser.parse(markdown)
|
|
8
|
-
expect(tasks).toHaveLength(1)
|
|
9
|
-
expect(tasks[0]).toEqual({
|
|
10
|
-
id: 'TASK-01',
|
|
11
|
-
title: 'Initial task',
|
|
12
|
-
priority: '🔴 Critical',
|
|
13
|
-
complexity: 'S',
|
|
14
|
-
status: 'TODO',
|
|
15
|
-
})
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
it('should parse an IN_PROGRESS task correctly', () => {
|
|
19
|
-
const markdown = '- [/] **[CLI-01]** Coding `Priority: 🟠 High` `Complexity: M`'
|
|
20
|
-
const tasks = TaskParser.parse(markdown)
|
|
21
|
-
expect(tasks).toHaveLength(1)
|
|
22
|
-
expect(tasks[0]!.status).toBe('IN_PROGRESS')
|
|
23
|
-
})
|
|
24
|
-
|
|
25
|
-
it('should parse a DONE task correctly', () => {
|
|
26
|
-
const markdown = '- [x] **[DOC-01]** Writing `Priority: 🔵 Medium` `Complexity: L`'
|
|
27
|
-
const tasks = TaskParser.parse(markdown)
|
|
28
|
-
expect(tasks).toHaveLength(1)
|
|
29
|
-
expect(tasks[0]!.status).toBe('DONE')
|
|
30
|
-
})
|
|
31
|
-
|
|
32
|
-
it('should parse a BLOCKED task correctly', () => {
|
|
33
|
-
const markdown = '- [!] **[CORE-01]** Waiting `Priority: ⚪ Low` `Complexity: XL`'
|
|
34
|
-
const tasks = TaskParser.parse(markdown)
|
|
35
|
-
expect(tasks).toHaveLength(1)
|
|
36
|
-
expect(tasks[0]!.status).toBe('BLOCKED')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should parse multiple tasks across lines', () => {
|
|
40
|
-
const markdown = `
|
|
41
|
-
# Tasks
|
|
42
|
-
- [ ] **[T1]** One \`Priority: 🔴 Critical\` \`Complexity: S\`
|
|
43
|
-
- [x] **[T2]** Two \`Priority: 🟠 High\` \`Complexity: M\`
|
|
44
|
-
`
|
|
45
|
-
const tasks = TaskParser.parse(markdown)
|
|
46
|
-
expect(tasks).toHaveLength(2)
|
|
47
|
-
expect(tasks[0]!.id).toBe('T1')
|
|
48
|
-
expect(tasks[1]!.id).toBe('T2')
|
|
49
|
-
})
|
|
50
|
-
|
|
51
|
-
it('should ignore non-task lines', () => {
|
|
52
|
-
const markdown = `
|
|
53
|
-
# Legend
|
|
54
|
-
This is some text.
|
|
55
|
-
- This is a list but not a task.
|
|
56
|
-
`
|
|
57
|
-
const tasks = TaskParser.parse(markdown)
|
|
58
|
-
expect(tasks).toHaveLength(0)
|
|
59
|
-
})
|
|
60
|
-
})
|
|
@@ -1,40 +0,0 @@
|
|
|
1
|
-
import type { Complexity, Priority, Task, TaskStatus } from '../types'
|
|
2
|
-
|
|
3
|
-
export class TaskParser {
|
|
4
|
-
static parse(markdown: string): Task[] {
|
|
5
|
-
const tasks: Task[] = []
|
|
6
|
-
const lines = markdown.split(/\r?\n/)
|
|
7
|
-
const taskRegex = /- \[([ x/!])\] \*\*\[(.+)\]\*\* (.+) `Priority: (.+)` `Complexity: (.+)`/
|
|
8
|
-
|
|
9
|
-
for (const line of lines) {
|
|
10
|
-
const match = line.match(taskRegex)
|
|
11
|
-
if (match) {
|
|
12
|
-
const [, statusChar = ' ', id = '', title = '', priority = '', complexity = ''] =
|
|
13
|
-
match
|
|
14
|
-
tasks.push({
|
|
15
|
-
id,
|
|
16
|
-
title: title.trim(),
|
|
17
|
-
priority: priority as Priority,
|
|
18
|
-
complexity: complexity as Complexity,
|
|
19
|
-
status: this.mapStatus(statusChar),
|
|
20
|
-
})
|
|
21
|
-
}
|
|
22
|
-
}
|
|
23
|
-
return tasks
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
private static mapStatus(char: string): TaskStatus {
|
|
27
|
-
switch (char) {
|
|
28
|
-
case ' ':
|
|
29
|
-
return 'TODO'
|
|
30
|
-
case '/':
|
|
31
|
-
return 'IN_PROGRESS'
|
|
32
|
-
case 'x':
|
|
33
|
-
return 'DONE'
|
|
34
|
-
case '!':
|
|
35
|
-
return 'BLOCKED'
|
|
36
|
-
default:
|
|
37
|
-
return 'TODO'
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
}
|
package/src/schemas/manifest.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { z } from 'zod'
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Manifest Schema for .autonomos/manifest.json
|
|
5
|
-
*/
|
|
6
|
-
export const ManifestSchema = z.object({
|
|
7
|
-
protocolVersion: z.string().describe('Version of the Agent Protocol specification'),
|
|
8
|
-
cliVersion: z.string().describe('Version of the CLI that last updated this project'),
|
|
9
|
-
initializedAt: z.string().datetime().describe('ISO timestamp of project initialization'),
|
|
10
|
-
lastUpdated: z.string().datetime().describe('ISO timestamp of last protocol update'),
|
|
11
|
-
})
|
|
12
|
-
|
|
13
|
-
export type Manifest = z.infer<typeof ManifestSchema>
|
package/src/templates/agent.ts
DELETED
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Template for AGENT.md - The context anchor at project root
|
|
3
|
-
* @param projectName - Name of the project to personalize the template
|
|
4
|
-
*/
|
|
5
|
-
export function generateAgentTemplate(projectName: string = 'Project'): string {
|
|
6
|
-
return `---
|
|
7
|
-
name: "${projectName}"
|
|
8
|
-
type: "project"
|
|
9
|
-
status: "active"
|
|
10
|
-
---
|
|
11
|
-
# AGENT CONTEXT: ${projectName}
|
|
12
|
-
|
|
13
|
-
## 🧠 Context & Objectives
|
|
14
|
-
|
|
15
|
-
*Describe what this project does and its main goals.*
|
|
16
|
-
|
|
17
|
-
## ⚙️ Workflow & Preferences
|
|
18
|
-
|
|
19
|
-
- **Commits:** Conventional Commits
|
|
20
|
-
- **Language:** English
|
|
21
|
-
|
|
22
|
-
## 🏗 Stack & Architecture
|
|
23
|
-
|
|
24
|
-
- **Tech:** *(List frameworks, libraries)*
|
|
25
|
-
- **Patterns:** *(Architecture patterns used)*
|
|
26
|
-
|
|
27
|
-
## 📁 Key Directories
|
|
28
|
-
|
|
29
|
-
| Path | Description |
|
|
30
|
-
|------|-------------|
|
|
31
|
-
| \`src/\` | Source code |
|
|
32
|
-
| \`.autonomos/\` | Agent Protocol files |
|
|
33
|
-
|
|
34
|
-
## ⚠️ Known Constraints
|
|
35
|
-
|
|
36
|
-
*List any technical debts, missing features, or external limitations.*
|
|
37
|
-
`
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Default AGENT.md template
|
|
42
|
-
*/
|
|
43
|
-
export const AGENT_TEMPLATE = generateAgentTemplate()
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest'
|
|
2
|
-
import { createManifest, parseManifest } from './manifest'
|
|
3
|
-
|
|
4
|
-
describe('Manifest Parser', () => {
|
|
5
|
-
it('should validate a correct manifest correctly', () => {
|
|
6
|
-
const manifest = createManifest('0.0.1')
|
|
7
|
-
const json = JSON.stringify(manifest)
|
|
8
|
-
const parsed = parseManifest(json)
|
|
9
|
-
expect(parsed.cliVersion).toBe('0.0.1')
|
|
10
|
-
})
|
|
11
|
-
|
|
12
|
-
it('should throw error on invalid manifest', () => {
|
|
13
|
-
const invalidJson = JSON.stringify({
|
|
14
|
-
protocolVersion: '1.0',
|
|
15
|
-
// Missing fields or invalid types
|
|
16
|
-
})
|
|
17
|
-
expect(() => parseManifest(invalidJson)).toThrow()
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
it('should throw error on invalid date format', () => {
|
|
21
|
-
const manifest = createManifest('0.0.1')
|
|
22
|
-
manifest.initializedAt = 'invalid-date'
|
|
23
|
-
const json = JSON.stringify(manifest)
|
|
24
|
-
expect(() => parseManifest(json)).toThrow()
|
|
25
|
-
})
|
|
26
|
-
})
|
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { PROTOCOL_VERSION } from '../constants'
|
|
2
|
-
import { ManifestSchema, type Manifest } from '../schemas/manifest'
|
|
3
|
-
|
|
4
|
-
/**
|
|
5
|
-
* Creates a new manifest object with current timestamps
|
|
6
|
-
*/
|
|
7
|
-
export function createManifest(cliVersion: string): Manifest {
|
|
8
|
-
const now = new Date().toISOString()
|
|
9
|
-
return {
|
|
10
|
-
protocolVersion: PROTOCOL_VERSION,
|
|
11
|
-
cliVersion,
|
|
12
|
-
initializedAt: now,
|
|
13
|
-
lastUpdated: now,
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Generates the manifest.json content as a formatted string
|
|
19
|
-
*/
|
|
20
|
-
export function generateManifestContent(manifest: Manifest): string {
|
|
21
|
-
return JSON.stringify(manifest, null, 4) + '\n'
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
/**
|
|
25
|
-
* Parses manifest.json content into a Manifest object with validation
|
|
26
|
-
*/
|
|
27
|
-
export function parseManifest(content: string): Manifest {
|
|
28
|
-
const data = JSON.parse(content)
|
|
29
|
-
return ManifestSchema.parse(data)
|
|
30
|
-
}
|