@dot-agent/cli 1.0.0 → 1.0.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/AGENTS.md +9 -0
- package/LICENSE +185 -0
- package/dist/{chunk-PSDRJRNL.js → chunk-BTLKCX2G.js} +1 -1
- package/dist/chunk-BTLKCX2G.js.map +1 -0
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +1 -1
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +26 -1
- package/scripts/ensure-license-headers.sh +54 -0
- package/.github/workflows/publish.yml +0 -28
- package/dist/chunk-PSDRJRNL.js.map +0 -1
- package/file structure.md +0 -484
- package/plan.md +0 -665
- package/src/cli.ts +0 -97
- package/src/commands/init.ts +0 -103
- package/src/commands/pack.ts +0 -216
- package/src/commands/run.ts +0 -194
- package/src/commands/unpack.ts +0 -65
- package/src/core/envelope.ts +0 -69
- package/src/core/id.ts +0 -41
- package/src/core/lint.ts +0 -202
- package/src/core/types.ts +0 -46
- package/src/core/zip.ts +0 -76
- package/src/index.ts +0 -22
- package/src/types.kernel-dsl.d.ts +0 -21
- package/src/types.ts +0 -114
- package/src/types.wts.d.ts +0 -10
- package/tests/envelope.test.ts +0 -62
- package/tests/id.test.ts +0 -26
- package/tsconfig.json +0 -21
- package/tsup.config.ts +0 -10
- package/vitest.config.ts +0 -13
package/plan.md
DELETED
|
@@ -1,665 +0,0 @@
|
|
|
1
|
-
# dot-agent CLI — Spec V1
|
|
2
|
-
|
|
3
|
-
## Repositório
|
|
4
|
-
|
|
5
|
-
```
|
|
6
|
-
https://github.com/dot-agent-spec/dot-agent
|
|
7
|
-
```
|
|
8
|
-
|
|
9
|
-
Publicado no npm como `dot-agent` (bin: `dot-agent`).
|
|
10
|
-
|
|
11
|
-
## Referência Canônica
|
|
12
|
-
|
|
13
|
-
A estrutura do arquivo `.agent` (ZIP) e o formato do `aboutme.json` seguem a especificação em [`file structure.md`](./file%20structure.md). O CLI implementa a validação, empacotamento e execução dessa especificação.
|
|
14
|
-
|
|
15
|
-
---
|
|
16
|
-
|
|
17
|
-
## Ecossistema de Dependências
|
|
18
|
-
|
|
19
|
-
O CLI **não reimplementa parsing nem execução de FSM**. Consome os pacotes já existentes na org:
|
|
20
|
-
|
|
21
|
-
| Pacote | Repo | Papel no CLI |
|
|
22
|
-
|---|---|---|
|
|
23
|
-
| `@dot-agent/tree-sitter` | `dot-agent-spec/tree-sitter` v0.3.2+ | Parse + lint sintaxe de `.description` e `.behavior` via WASM |
|
|
24
|
-
| `@dot-agent/kernel-dsl` | `dot-agent-spec/kernel-dsl` | Carregamento de `.behavior` (usa tree-sitter internamente + valida semântica) + execução FSM ao runtime |
|
|
25
|
-
|
|
26
|
-
**Tree-sitter** exporta `agentWasmPath` e `behaviorWasmPath` — caminhos absolutos para os `.wasm` pré-compilados em `dist/`:
|
|
27
|
-
- `tree-sitter-agent.wasm` para `.description` / `.type`
|
|
28
|
-
- `tree-sitter-behavior.wasm` para `.behavior` (sintaxe)
|
|
29
|
-
|
|
30
|
-
O CLI carrega ambos via `web-tree-sitter` (já WASM, sem binding C nativo).
|
|
31
|
-
|
|
32
|
-
**Kernel-dsl** (`AgentDSLKernel`) é instanciado no `pack` (para validação semântica via `load_behavior()`) e no `run` (para execução FSM). Internamente, o kernel:
|
|
33
|
-
- Usa tree-sitter para parse robusto
|
|
34
|
-
- Valida semântica (referências de estados, memory, etc)
|
|
35
|
-
- Executa como FSM (intents, transitions, effects)
|
|
36
|
-
|
|
37
|
-
Se `load_behavior()` retorna `parse_error` effect, o lint mapeia para E006.
|
|
38
|
-
|
|
39
|
-
---
|
|
40
|
-
|
|
41
|
-
## Visão Geral
|
|
42
|
-
|
|
43
|
-
O `dot-agent` expõe dois pontos de entrada com a mesma base de código:
|
|
44
|
-
|
|
45
|
-
| Ponto de entrada | Quem usa | Como | Status |
|
|
46
|
-
|---|---|---|---|
|
|
47
|
-
| `index.ts` (API JS) | Electron / app | `import { run, pack, unpack, init } from 'dot-agent'` | ✅ Implementado |
|
|
48
|
-
| `cli.ts` (bin) | Terminal / npx | `npx dot-agent <comando>` | ✅ Implementado |
|
|
49
|
-
|
|
50
|
-
O `cli.ts` é um wrapper fino: parse de args → chama a mesma função de `index.ts`.
|
|
51
|
-
|
|
52
|
-
---
|
|
53
|
-
|
|
54
|
-
## Estrutura do Pacote
|
|
55
|
-
|
|
56
|
-
```
|
|
57
|
-
dot-agent/
|
|
58
|
-
├── src/
|
|
59
|
-
│ ├── commands/
|
|
60
|
-
│ │ ├── init.ts ← gera scaffold
|
|
61
|
-
│ │ ├── pack.ts ← valida + empacota → .agent
|
|
62
|
-
│ │ ├── unpack.ts ← extrai .agent → fontes
|
|
63
|
-
│ │ └── run.ts ← carrega .agent, retorna AgentContext
|
|
64
|
-
│ ├── core/
|
|
65
|
-
│ │ ├── lint.ts ← orquestra validação (tree-sitter + kernel-dsl)
|
|
66
|
-
│ │ ├── zip.ts ← leitura/escrita ZIP (jszip)
|
|
67
|
-
│ │ ├── envelope.ts ← parse/geração do aboutme.json
|
|
68
|
-
│ │ ├── id.ts ← geração e parsing de id (namespace/name:version~digest)
|
|
69
|
-
│ │ └── types.ts ← validação e geração de types.json (tipos públicos)
|
|
70
|
-
│ ├── index.ts ← export público da API
|
|
71
|
-
│ └── cli.ts ← bin entry point
|
|
72
|
-
├── tests/
|
|
73
|
-
├── package.json
|
|
74
|
-
└── tsconfig.json
|
|
75
|
-
```
|
|
76
|
-
|
|
77
|
-
---
|
|
78
|
-
|
|
79
|
-
## package.json (estrutura relevante)
|
|
80
|
-
|
|
81
|
-
```json
|
|
82
|
-
{
|
|
83
|
-
"name": "dot-agent",
|
|
84
|
-
"type": "module",
|
|
85
|
-
"main": "dist/index.js",
|
|
86
|
-
"types": "dist/index.d.ts",
|
|
87
|
-
"bin": {
|
|
88
|
-
"dot-agent": "dist/cli.js"
|
|
89
|
-
},
|
|
90
|
-
"exports": {
|
|
91
|
-
".": {
|
|
92
|
-
"import": "./dist/index.js",
|
|
93
|
-
"require": "./dist/index.cjs"
|
|
94
|
-
}
|
|
95
|
-
},
|
|
96
|
-
"engines": {
|
|
97
|
-
"node": ">=18.0.0"
|
|
98
|
-
},
|
|
99
|
-
"dependencies": {
|
|
100
|
-
"@dot-agent/tree-sitter": "^0.3.2",
|
|
101
|
-
"@dot-agent/kernel-dsl": "latest",
|
|
102
|
-
"jszip": "^3.10.1",
|
|
103
|
-
"web-tree-sitter": "^0.25.0"
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
```
|
|
107
|
-
|
|
108
|
-
**Nota:** `"type": "module"` é obrigatório pois `@dot-agent/kernel-dsl` é ESM-only. Requer Node 18+.
|
|
109
|
-
|
|
110
|
-
---
|
|
111
|
-
|
|
112
|
-
## WASM Initialization
|
|
113
|
-
|
|
114
|
-
O CLI deve inicializar tree-sitter e kernel-dsl uma vez, antes de qualquer lint ou run. Ambas as bibliotecas fornecem WASM via `fetch()` nativo (Node 18+).
|
|
115
|
-
|
|
116
|
-
### Tree-sitter
|
|
117
|
-
|
|
118
|
-
O pacote `@dot-agent/tree-sitter` exporta **apenas paths**, não instâncias Parser:
|
|
119
|
-
|
|
120
|
-
```typescript
|
|
121
|
-
import Parser from 'web-tree-sitter'
|
|
122
|
-
import { agentWasmPath, behaviorWasmPath } from '@dot-agent/tree-sitter'
|
|
123
|
-
|
|
124
|
-
// Chamado uma vez, preferencialmente em core/lint.ts
|
|
125
|
-
async function initTreeSitter() {
|
|
126
|
-
await Parser.init()
|
|
127
|
-
const agentLang = await Parser.Language.load(agentWasmPath)
|
|
128
|
-
const behaviorLang = await Parser.Language.load(behaviorWasmPath)
|
|
129
|
-
return { agentParser: new Parser(), behaviorParser: new Parser(), agentLang, behaviorLang }
|
|
130
|
-
}
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Após `initTreeSitter()`, as instâncias são **reutilizadas** via `parser.setLanguage()`:
|
|
134
|
-
|
|
135
|
-
```typescript
|
|
136
|
-
const { agentParser, agentLang } = await initTreeSitter()
|
|
137
|
-
agentParser.setLanguage(agentLang)
|
|
138
|
-
const tree = agentParser.parse(descriptionText)
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
### Kernel-dsl
|
|
142
|
-
|
|
143
|
-
O pacote `@dot-agent/kernel-dsl` exporta `{ AgentDSLKernel, init }` — `init()` é async, sem parâmetros, idempotente:
|
|
144
|
-
|
|
145
|
-
```typescript
|
|
146
|
-
import { AgentDSLKernel, init as initKernel } from '@dot-agent/kernel-dsl'
|
|
147
|
-
|
|
148
|
-
await initKernel() // carrega WASM (~1.7MB via fetch)
|
|
149
|
-
const kernel = new AgentDSLKernel()
|
|
150
|
-
```
|
|
151
|
-
|
|
152
|
-
Se `new AgentDSLKernel()` for chamado antes de `initKernel()`, lança erro. Seguro chamar `initKernel()` múltiplas vezes — é idempotente.
|
|
153
|
-
|
|
154
|
-
### Padrão para o CLI
|
|
155
|
-
|
|
156
|
-
Em `core/lint.ts`, implementar lazy singleton:
|
|
157
|
-
|
|
158
|
-
```typescript
|
|
159
|
-
let _initialized = false
|
|
160
|
-
|
|
161
|
-
async function ensureWasmInit() {
|
|
162
|
-
if (_initialized) return
|
|
163
|
-
await Parser.init()
|
|
164
|
-
await initKernel()
|
|
165
|
-
_initialized = true
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
// Exportado
|
|
169
|
-
export async function createLinter() {
|
|
170
|
-
await ensureWasmInit()
|
|
171
|
-
// ... retorna funções de lint
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
|
-
---
|
|
176
|
-
|
|
177
|
-
## Mapeamento de Erros (tree-sitter → lint codes)
|
|
178
|
-
|
|
179
|
-
Tree-sitter retorna uma AST onde erros são nós nomeados `ERROR` ou nodes com `isMissing === true`. O CLI coleta erros via:
|
|
180
|
-
|
|
181
|
-
```typescript
|
|
182
|
-
function collectSyntaxErrors(node: Parser.SyntaxNode): Parser.SyntaxNode[] {
|
|
183
|
-
const errors: Parser.SyntaxNode[] = []
|
|
184
|
-
if (node.isError || node.isMissing) errors.push(node)
|
|
185
|
-
for (const child of node.children) errors.push(...collectSyntaxErrors(child))
|
|
186
|
-
return errors
|
|
187
|
-
}
|
|
188
|
-
```
|
|
189
|
-
|
|
190
|
-
**Mapeamento para lint codes:**
|
|
191
|
-
|
|
192
|
-
- Erros em `.description` (tree-sitter):
|
|
193
|
-
- Campo obrigatório ausente (ex: `domain`, `name`, `version`) → E001
|
|
194
|
-
- Campo obrigatório em `capability` (ex: `type`) ausente → E002
|
|
195
|
-
- `.description` arquivo não encontrado → E003
|
|
196
|
-
|
|
197
|
-
- Erros em `.behavior` (tree-sitter sintaxe):
|
|
198
|
-
- Erro de sintaxe DSL (state, on, transition, if, etc) → E004
|
|
199
|
-
- `.behavior` arquivo não encontrado → E007
|
|
200
|
-
|
|
201
|
-
- Erros do kernel (`load_behavior()` effects):
|
|
202
|
-
- `parse_error` effect com message → E006
|
|
203
|
-
- Estado referenciado não existe (pode ser detectado via `get_graph()` comparado com `on intent "..."`) → E005
|
|
204
|
-
|
|
205
|
-
- Erros manuais:
|
|
206
|
-
- Arquivo referenciado em `files.json` não existe → E008
|
|
207
|
-
|
|
208
|
-
---
|
|
209
|
-
|
|
210
|
-
## Estrutura do `.agent` (ZIP)
|
|
211
|
-
|
|
212
|
-
Conforme especificado em [`file structure.md`](./file%20structure.md):
|
|
213
|
-
|
|
214
|
-
```
|
|
215
|
-
meu-agente.agent (ZIP)
|
|
216
|
-
│
|
|
217
|
-
│ # Metadados gerados — Layer 2 🤖
|
|
218
|
-
├── .agent/
|
|
219
|
-
│ ├── aboutme.json ← sempre presente
|
|
220
|
-
│ ├── types.json ← quando há tipos públicos
|
|
221
|
-
│ └── files.json ← quando há fontes
|
|
222
|
-
│
|
|
223
|
-
│ # Comportamento — Layer 1 👤
|
|
224
|
-
├── agent.description
|
|
225
|
-
├── agent.behavior
|
|
226
|
-
├── behaviors/
|
|
227
|
-
│ └── *.behavior
|
|
228
|
-
├── guides/
|
|
229
|
-
│ └── *.md
|
|
230
|
-
├── knowledge/
|
|
231
|
-
│ └── *.md
|
|
232
|
-
└── SOUL.md
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
O `aboutme.json` é o único arquivo obrigatório. Os fontes ficam na raiz do ZIP. O `files.json` referencia arquivos relativos à raiz:
|
|
236
|
-
|
|
237
|
-
```json
|
|
238
|
-
{
|
|
239
|
-
"description": "agent.description",
|
|
240
|
-
"behavior": "agent.behavior",
|
|
241
|
-
"behaviors": ["behaviors/*.behavior"],
|
|
242
|
-
"guides": ["guides/*.md"],
|
|
243
|
-
"knowledge": ["knowledge/*.md"]
|
|
244
|
-
}
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
### Exemplo concreto de `aboutme.json` V1
|
|
248
|
-
|
|
249
|
-
```json
|
|
250
|
-
{
|
|
251
|
-
"schemaVersion": "dot-agent/1.0",
|
|
252
|
-
"id": "entelekheia.ai/doctor:v1.0~a1b2c3d",
|
|
253
|
-
"name": "Doctor",
|
|
254
|
-
"description": "Agente médico para triagem inicial de pacientes.",
|
|
255
|
-
"version": "v1.0",
|
|
256
|
-
"domain": "entelekheia.ai",
|
|
257
|
-
"license": "Apache-2.0",
|
|
258
|
-
"persona": "SOUL.md",
|
|
259
|
-
"compiler": "dot-agent/1.0.0",
|
|
260
|
-
"commit": "a1b2c3d",
|
|
261
|
-
"skills": [
|
|
262
|
-
{ "id": "TriagePatient", "description": "Triagem inicial de pacientes" }
|
|
263
|
-
],
|
|
264
|
-
"requires": ["UserProfile"],
|
|
265
|
-
"integrity": {
|
|
266
|
-
"sha256": "e3b0c44298fc1c149afbaf8b2b...",
|
|
267
|
-
"files": ".agent/files.json"
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
```
|
|
271
|
-
|
|
272
|
-
**Notas:**
|
|
273
|
-
- `purpose` omitido no V1 (mapeado futuramente por `builder.agent` + LLM)
|
|
274
|
-
- `integrity.types` só aparece quando há tipos públicos
|
|
275
|
-
- `compiler` é a versão do dot-agent CLI que gerou o pacote
|
|
276
|
-
- `commit` fica ausente se o projeto não usa Git
|
|
277
|
-
|
|
278
|
-
---
|
|
279
|
-
|
|
280
|
-
## API Pública (`index.ts`)
|
|
281
|
-
|
|
282
|
-
```typescript
|
|
283
|
-
export function init(options: InitOptions): Promise<InitResult>
|
|
284
|
-
export function pack(options: PackOptions): Promise<PackResult>
|
|
285
|
-
export function unpack(options: UnpackOptions): Promise<UnpackResult>
|
|
286
|
-
export function run(options: RunOptions): Promise<AgentContext>
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
---
|
|
290
|
-
|
|
291
|
-
## Comandos
|
|
292
|
-
|
|
293
|
-
---
|
|
294
|
-
|
|
295
|
-
### ✅ `dot-agent init`
|
|
296
|
-
|
|
297
|
-
Gera o scaffold completo do projeto.
|
|
298
|
-
Não é interativo na V1 — o desenvolvedor edita os arquivos gerados.
|
|
299
|
-
|
|
300
|
-
**CLI:**
|
|
301
|
-
```
|
|
302
|
-
dot-agent init [--name <nome>] [--domain <domínio>] [--dir <pasta>]
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
**API:**
|
|
306
|
-
```typescript
|
|
307
|
-
interface InitOptions {
|
|
308
|
-
name?: string // padrão: nome da pasta atual
|
|
309
|
-
domain?: string // padrão: "example.com" (⚠ W003 no pack)
|
|
310
|
-
dir?: string // padrão: process.cwd()
|
|
311
|
-
}
|
|
312
|
-
|
|
313
|
-
interface InitResult {
|
|
314
|
-
dir: string
|
|
315
|
-
files: string[] // lista de arquivos criados
|
|
316
|
-
}
|
|
317
|
-
```
|
|
318
|
-
|
|
319
|
-
**Arquivos gerados:**
|
|
320
|
-
```
|
|
321
|
-
<dir>/
|
|
322
|
-
├── agent.description
|
|
323
|
-
├── agent.behavior
|
|
324
|
-
├── behaviors/ (.gitkeep)
|
|
325
|
-
├── guides/ (.gitkeep)
|
|
326
|
-
├── knowledge/ (.gitkeep)
|
|
327
|
-
├── SOUL.md
|
|
328
|
-
├── AGENTS.md (vazio — para documentação de dependências)
|
|
329
|
-
├── README.md
|
|
330
|
-
└── LICENSE (Apache 2.0)
|
|
331
|
-
```
|
|
332
|
-
|
|
333
|
-
**Templates:**
|
|
334
|
-
|
|
335
|
-
`agent.description`:
|
|
336
|
-
```
|
|
337
|
-
agent {{Name}}
|
|
338
|
-
domain {{domain}}
|
|
339
|
-
license Apache-2.0
|
|
340
|
-
|
|
341
|
-
description
|
|
342
|
-
{{Describe what this agent does.}}
|
|
343
|
-
|
|
344
|
-
behavior agent.behavior
|
|
345
|
-
|
|
346
|
-
capabilities
|
|
347
|
-
{{ActionName}} "{{Describe this capability}}"
|
|
348
|
-
```
|
|
349
|
-
|
|
350
|
-
`agent.behavior`:
|
|
351
|
-
```
|
|
352
|
-
state init
|
|
353
|
-
next responsive
|
|
354
|
-
|
|
355
|
-
state responsive
|
|
356
|
-
goal "{{Help the user with their task.}}"
|
|
357
|
-
interact
|
|
358
|
-
on intent "start" next responsive
|
|
359
|
-
```
|
|
360
|
-
|
|
361
|
-
`SOUL.md`: Texto livre sobre persona/voz do agente. Placeholder:
|
|
362
|
-
```markdown
|
|
363
|
-
# {{Name}} — Persona
|
|
364
|
-
|
|
365
|
-
## Voice and Tone
|
|
366
|
-
|
|
367
|
-
{{Describe the agent's voice, personality, and communication style.}}
|
|
368
|
-
```
|
|
369
|
-
|
|
370
|
-
`README.md`: Título + descrição + seção de uso (placeholders).
|
|
371
|
-
|
|
372
|
-
**Comportamento:**
|
|
373
|
-
- Aborta se o diretório já contiver `agent.description`
|
|
374
|
-
- Não preenche `version` no `.description` — versão é resolvida em tempo de `pack`
|
|
375
|
-
- Developer edita os templates antes de chamar `pack`
|
|
376
|
-
|
|
377
|
-
---
|
|
378
|
-
|
|
379
|
-
### ✅ `dot-agent pack`
|
|
380
|
-
|
|
381
|
-
Valida a DSL e empacota os fontes em um arquivo `.agent` (ZIP).
|
|
382
|
-
|
|
383
|
-
**CLI:**
|
|
384
|
-
```
|
|
385
|
-
dot-agent pack [--dir <pasta>] [--out <arquivo.agent>] [--commit <hash>] [--version <tag>]
|
|
386
|
-
```
|
|
387
|
-
|
|
388
|
-
**API:**
|
|
389
|
-
```typescript
|
|
390
|
-
interface PackOptions {
|
|
391
|
-
dir?: string
|
|
392
|
-
out?: string // padrão: <name>.agent no dir
|
|
393
|
-
commit?: string // override para git rev-parse --short HEAD
|
|
394
|
-
version?: string // override para git describe --tags --abbrev=0
|
|
395
|
-
}
|
|
396
|
-
|
|
397
|
-
interface PackResult {
|
|
398
|
-
path: string
|
|
399
|
-
id: string // namespace/name:version~digest (conforme file structure.md)
|
|
400
|
-
warnings: LintMessage[]
|
|
401
|
-
}
|
|
402
|
-
|
|
403
|
-
interface LintMessage {
|
|
404
|
-
file: string
|
|
405
|
-
line: number
|
|
406
|
-
col: number
|
|
407
|
-
severity: 'error' | 'warning'
|
|
408
|
-
code: string
|
|
409
|
-
message: string
|
|
410
|
-
}
|
|
411
|
-
```
|
|
412
|
-
|
|
413
|
-
**Resolução de `version` e `commit`:**
|
|
414
|
-
|
|
415
|
-
| Campo | Prioridade |
|
|
416
|
-
|---|---|
|
|
417
|
-
| `version` | 1. `--version <tag>` 2. `git describe --tags --abbrev=0` 3. Interativo: `Agent version (e.g. v1.0):` |
|
|
418
|
-
| `commit` | 1. `--commit <hash>` 2. `git rev-parse --short HEAD` 3. Ausente (não bloqueia pack) |
|
|
419
|
-
|
|
420
|
-
Se Git não estiver disponível e versão não for passada, o pack pergunta interativamente.
|
|
421
|
-
|
|
422
|
-
**Fluxo interno:**
|
|
423
|
-
1. Localiza `agent.description` e `agent.behavior` no `dir`
|
|
424
|
-
|
|
425
|
-
**Lint do `.description`:**
|
|
426
|
-
2. Parse via `@dot-agent/tree-sitter` (WASM)
|
|
427
|
-
3. Valida campos obrigatórios: `domain`, `name`, `version`, `capability` com `type`
|
|
428
|
-
4. Valida semântica: tipos bem-formados, nomes únicos, referências válidas → mapeia erros para E001
|
|
429
|
-
|
|
430
|
-
**Lint do `.behavior`:**
|
|
431
|
-
5. Parse via `@dot-agent/tree-sitter` (WASM)
|
|
432
|
-
6. Valida sintaxe DSL (if/on/state/transition/etc) → mapeia erros para E007
|
|
433
|
-
7. Carrega kernel: `AgentDSLKernel.load_behavior()` para validação semântica
|
|
434
|
-
8. Se retorna `parse_error`, mapeia para E006
|
|
435
|
-
9. Extrai grafo (via `kernel.get_graph()`) para detectar states sem transições → W001
|
|
436
|
-
|
|
437
|
-
10. **Se houver qualquer `error`: aborta, não gera `.agent`**
|
|
438
|
-
11. Warnings incluídos no `PackResult` mas não bloqueiam
|
|
439
|
-
12. Coleta todos os arquivos: `agent.description`, `agent.behavior`, `SOUL.md` (opt), `behaviors/`, `guides/`, `knowledge/`
|
|
440
|
-
13. Computa SHA-256 do conteúdo do ZIP → extrai primeiros 8 chars → `<digest>`
|
|
441
|
-
14. Gera `id`: `<domain>/<name>:<version>~<digest>` (ex: `entelekheia.ai/doctor:v1.0~a1b2c3d`)
|
|
442
|
-
15. Monta `.agent/aboutme.json` com `id`, `schemaVersion`, `compiler`, `commit`, `integrity`, etc (conforme file structure.md)
|
|
443
|
-
16. Monta `.agent/files.json` com mapa de fontes
|
|
444
|
-
17. Monta `.agent/types.json` (opcional, se agente expõe tipos públicos)
|
|
445
|
-
18. Cria ZIP:
|
|
446
|
-
- Raiz: `.agent/aboutme.json`, `.agent/types.json` (opt), `.agent/files.json`
|
|
447
|
-
- Raiz: todos os fontes
|
|
448
|
-
19. Salva como `<name>.agent`
|
|
449
|
-
|
|
450
|
-
**Saída CLI (sucesso):**
|
|
451
|
-
```
|
|
452
|
-
✓ Lint passed (0 errors, 2 warnings)
|
|
453
|
-
⚠ agent.behavior:12:3 W001 state "idle" has no transitions
|
|
454
|
-
⚠ agent.description:2:1 W003 domain still has default value "example.com"
|
|
455
|
-
✓ Packed → ./doctor.agent
|
|
456
|
-
ID: entelekheia.ai/doctor:v1.0~a1b2c3d
|
|
457
|
-
```
|
|
458
|
-
|
|
459
|
-
**Saída CLI (erro):**
|
|
460
|
-
```
|
|
461
|
-
✗ Lint failed (2 errors)
|
|
462
|
-
✗ agent.description:5:1 E001 missing required field: domain
|
|
463
|
-
✗ agent.behavior:23:7 E006 parse error: unknown state reference "triage_v2"
|
|
464
|
-
Pack aborted.
|
|
465
|
-
```
|
|
466
|
-
|
|
467
|
-
---
|
|
468
|
-
|
|
469
|
-
### ✅ `dot-agent unpack`
|
|
470
|
-
|
|
471
|
-
Extrai um `.agent` e restaura os fontes.
|
|
472
|
-
|
|
473
|
-
**CLI:**
|
|
474
|
-
```
|
|
475
|
-
dot-agent unpack <arquivo.agent> [--out <pasta>] [--force]
|
|
476
|
-
```
|
|
477
|
-
|
|
478
|
-
**API:**
|
|
479
|
-
```typescript
|
|
480
|
-
interface UnpackOptions {
|
|
481
|
-
file: string
|
|
482
|
-
out?: string // padrão: ./<name>/ no cwd
|
|
483
|
-
force?: boolean // sobrescreve se pasta já existir
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
interface UnpackResult {
|
|
487
|
-
dir: string
|
|
488
|
-
id: string // extraído do aboutme.json
|
|
489
|
-
files: string[]
|
|
490
|
-
aboutme: object // conteúdo do aboutme.json
|
|
491
|
-
}
|
|
492
|
-
```
|
|
493
|
-
|
|
494
|
-
**Fluxo interno:**
|
|
495
|
-
1. Valida se arquivo `.agent` é ZIP válido (magic bytes)
|
|
496
|
-
2. Valida ZIP bomb (soma descompactado; aborta se > 500 MB ou ratio > 100×)
|
|
497
|
-
3. Lê `.agent/aboutme.json` → valida e extrai `id`
|
|
498
|
-
4. Extrai todos os arquivos da raiz para `out/<arquivo>`
|
|
499
|
-
5. Aborta se `out` já existir, a menos que `--force`
|
|
500
|
-
6. Restaura estrutura de pastas original
|
|
501
|
-
|
|
502
|
-
**Comportamento:**
|
|
503
|
-
- Valida integridade: lê `integrity.sha256` e compara com ZIP recompactado
|
|
504
|
-
- Se hash não bate, avisa mas continua (⚠ —verbose mostra detalhes)
|
|
505
|
-
- Extrai apenas fontes por padrão
|
|
506
|
-
- `--verbose` exibe também o conteúdo do `aboutme.json`
|
|
507
|
-
|
|
508
|
-
---
|
|
509
|
-
|
|
510
|
-
### ✅ `dot-agent run`
|
|
511
|
-
|
|
512
|
-
Carrega um `.agent` (ou pasta de fontes) e retorna o `AgentContext`.
|
|
513
|
-
|
|
514
|
-
No terminal é usado para smoke-test. O Electron usa a API.
|
|
515
|
-
|
|
516
|
-
**CLI:**
|
|
517
|
-
```
|
|
518
|
-
dot-agent run <arquivo.agent | pasta>
|
|
519
|
-
```
|
|
520
|
-
|
|
521
|
-
**API:**
|
|
522
|
-
```typescript
|
|
523
|
-
interface RunOptions {
|
|
524
|
-
source: string // caminho do .agent ou pasta com fontes
|
|
525
|
-
}
|
|
526
|
-
|
|
527
|
-
interface FileEntry {
|
|
528
|
-
path: string // caminho relativo
|
|
529
|
-
content: string // conteúdo em memória
|
|
530
|
-
}
|
|
531
|
-
|
|
532
|
-
// AgentContext é EventEmitter + objeto com tudo parsed
|
|
533
|
-
interface AgentContext extends EventEmitter {
|
|
534
|
-
id: string // namespace/name:version~digest
|
|
535
|
-
description: ParsedDescription // AST parseada pelo tree-sitter
|
|
536
|
-
behavior: ParsedBehavior // AST parseada pelo kernel-dsl
|
|
537
|
-
kernel: AgentDSLKernel // instância pronta para executar
|
|
538
|
-
files: {
|
|
539
|
-
soul?: string
|
|
540
|
-
guides: FileEntry[]
|
|
541
|
-
knowledge: FileEntry[]
|
|
542
|
-
behaviors: FileEntry[]
|
|
543
|
-
}
|
|
544
|
-
aboutme: object // conteúdo do aboutme.json
|
|
545
|
-
|
|
546
|
-
// Eventos emitidos durante o carregamento:
|
|
547
|
-
// 'progress' → { step: string, pct: number }
|
|
548
|
-
// 'warning' → LintMessage
|
|
549
|
-
// 'ready' → AgentContext
|
|
550
|
-
// 'error' → Error
|
|
551
|
-
}
|
|
552
|
-
```
|
|
553
|
-
|
|
554
|
-
**Fluxo interno:**
|
|
555
|
-
1. Emite `progress` { step: 'opening', pct: 0 }
|
|
556
|
-
2. Detecta se é `.agent` (ZIP) ou pasta de fontes
|
|
557
|
-
3. Se `.agent`: valida ZIP bomb (soma descompactado; aborta se > 500 MB ou ratio > 100×)
|
|
558
|
-
4. Emite `progress` { step: 'parsing', pct: 30 }
|
|
559
|
-
5. Lê `.agent/aboutme.json` (se ZIP) → extrai `id`
|
|
560
|
-
6. Lê `agent.description`; parse via `@dot-agent/tree-sitter` → `ParsedDescription`
|
|
561
|
-
7. Lê `agent.behavior`; parse via `@dot-agent/tree-sitter` (sintaxe)
|
|
562
|
-
8. Carrega kernel: `AgentDSLKernel.load_behavior()` (tree-sitter + semântica + FSM)
|
|
563
|
-
9. Emite warnings do lint se houver
|
|
564
|
-
10. Emite `progress` { step: 'loading-files', pct: 60 }
|
|
565
|
-
11. Carrega guides, knowledge, behaviors em memória
|
|
566
|
-
12. Emite `progress` { step: 'ready', pct: 100 }
|
|
567
|
-
13. Emite `ready` e resolve a Promise com o `AgentContext`
|
|
568
|
-
|
|
569
|
-
**O runtime recebe o `AgentContext` e:**
|
|
570
|
-
- Usa `context.kernel` (já carregado) para enviar intents via `send_intent()`
|
|
571
|
-
- Usa `context.description` para montar system prompt do LLM
|
|
572
|
-
- Usa `context.files.soul` e `context.files.guides` como contexto adicional
|
|
573
|
-
- Reage aos `Effect[]` retornados pelo kernel para orquestrar estados
|
|
574
|
-
|
|
575
|
-
---
|
|
576
|
-
|
|
577
|
-
## Lint — Códigos de Erro V1
|
|
578
|
-
|
|
579
|
-
| Código | Severidade | Detecção | Descrição |
|
|
580
|
-
|---|---|---|---|
|
|
581
|
-
| E001 | error | tree-sitter (`.description` lint) | Campo obrigatório ausente (`domain`, `name`, `version`) |
|
|
582
|
-
| E002 | error | tree-sitter (`.description` lint) | Campo obrigatório ausente em `capability` (tipo ou descrição) |
|
|
583
|
-
| E003 | error | manual | Arquivo `.description` ausente |
|
|
584
|
-
| E004 | error | tree-sitter (`.behavior` lint) | Erro de sintaxe DSL (state, on, transition, if, etc) |
|
|
585
|
-
| E005 | error | kernel-dsl (semântica) | Estado referenciado não existe (ex: `transition to unknown`) |
|
|
586
|
-
| E006 | error | kernel-dsl (`load_behavior()`) | `parse_error` effect — erro semântico no FSM |
|
|
587
|
-
| E007 | error | manual | Arquivo `.behavior` ausente |
|
|
588
|
-
| E008 | error | manual | Arquivo referenciado em `files.json` não existe |
|
|
589
|
-
| W001 | warning | kernel-dsl (`get_graph()`) | State sem transições de entrada ou saída |
|
|
590
|
-
| W002 | warning | tree-sitter (`.behavior` lint) | Text block acima de 280 chars (goal, guide, teach) |
|
|
591
|
-
| W003 | warning | tree-sitter (`.description` lint) | Campo `domain` ainda com valor padrão (`example.com`) |
|
|
592
|
-
|
|
593
|
-
---
|
|
594
|
-
|
|
595
|
-
## Relação com os Outros Pacotes da Org
|
|
596
|
-
|
|
597
|
-
```
|
|
598
|
-
dot-agent (CLI / npm)
|
|
599
|
-
├── depende de → @dot-agent/tree-sitter (parse + lint ambos .description e .behavior, WASM)
|
|
600
|
-
│ ├── dist/tree-sitter-agent.wasm (para .description / .type)
|
|
601
|
-
│ └── dist/tree-sitter-behavior.wasm (para .behavior sintaxe)
|
|
602
|
-
│
|
|
603
|
-
├── depende de → @dot-agent/kernel-dsl (semântica + FSM + execução, WASM)
|
|
604
|
-
│ └── usa tree-sitter internamente via Rust FFI
|
|
605
|
-
│ para parse de .behavior com validação semântica
|
|
606
|
-
│
|
|
607
|
-
├── depende de → jszip (leitura/escrita ZIP)
|
|
608
|
-
│
|
|
609
|
-
├── produz → AgentContext
|
|
610
|
-
│ ├── .id (namespace/name:version~digest)
|
|
611
|
-
│ ├── .description (ParsedDescription via tree-sitter)
|
|
612
|
-
│ ├── .behavior (ParsedBehavior, kernel carregado)
|
|
613
|
-
│ ├── .kernel (AgentDSLKernel instância pronta)
|
|
614
|
-
│ └── .files (guides, knowledge, behaviors em memória)
|
|
615
|
-
│
|
|
616
|
-
├── consumido por → Electron / Runtime (recebe AgentContext)
|
|
617
|
-
│
|
|
618
|
-
└── não depende de → language-server (tooling de editor, LSP standalone)
|
|
619
|
-
→ vscode-dot-agent (extensão VSCode, cliente LSP)
|
|
620
|
-
```
|
|
621
|
-
|
|
622
|
-
---
|
|
623
|
-
|
|
624
|
-
## Estratégia de Migração para Rust (VNext)
|
|
625
|
-
|
|
626
|
-
O pacote npm mantém a mesma API pública.
|
|
627
|
-
Os binários nativos entram como `optionalDependencies`:
|
|
628
|
-
|
|
629
|
-
```json
|
|
630
|
-
{
|
|
631
|
-
"optionalDependencies": {
|
|
632
|
-
"dot-agent-darwin-arm64": "1.x",
|
|
633
|
-
"dot-agent-darwin-x64": "1.x",
|
|
634
|
-
"dot-agent-linux-x64": "1.x",
|
|
635
|
-
"dot-agent-win32-x64": "1.x"
|
|
636
|
-
}
|
|
637
|
-
}
|
|
638
|
-
```
|
|
639
|
-
|
|
640
|
-
O `index.ts` detecta se o binário nativo está disponível e delega; caso contrário, cai no fallback JS. Zero breaking change para o Electron.
|
|
641
|
-
|
|
642
|
-
---
|
|
643
|
-
|
|
644
|
-
## Decisões V1
|
|
645
|
-
|
|
646
|
-
| Decisão | Resultado |
|
|
647
|
-
|---|---|
|
|
648
|
-
| **Nome do pacote npm** | ✅ `dot-agent` — publicado como bin e import padrão |
|
|
649
|
-
| **Estrutura do ZIP** | ✅ `.agent/` contém metadados; raiz contém fontes (conforme `file structure.md`) |
|
|
650
|
-
| **Nomenclatura** | ✅ `id` no formato `namespace/name:version~digest` em vez de URN |
|
|
651
|
-
| **Arquivo de metadados** | ✅ `aboutme.json` em `.agent/` (não `envelope.json` na raiz) |
|
|
652
|
-
| **CLI module format** | ✅ ESM (`"type": "module"`) — obrigatório para `@dot-agent/kernel-dsl` |
|
|
653
|
-
| **Campo `purpose`** | ✅ Omitido no V1 — mapeado futuramente por `builder.agent` + LLM |
|
|
654
|
-
| **Resolução de `version`** | ✅ Prioridade: `--version`, git tags, interativo |
|
|
655
|
-
| **Resolução de `commit`** | ✅ Prioridade: `--commit`, git HEAD, ausente (não bloqueia) |
|
|
656
|
-
|
|
657
|
-
---
|
|
658
|
-
|
|
659
|
-
## Questões Abertas VNext
|
|
660
|
-
|
|
661
|
-
1. **`inputModes` / `outputModes` em `skills[]`** — Runtime converte tipos estruturados para formato de transporte. A2A-compatibility completa ainda em exploração.
|
|
662
|
-
|
|
663
|
-
2. **`ui/` e `assets/` no ZIP** — Onde empacotar UI gerada? Na raiz do ZIP (fonts) ou em `.agent/` (artifacts gerados)? Exploração pendente.
|
|
664
|
-
|
|
665
|
-
3. **Tipagem de `requires[]`** — Hoje é string simples (`UserProfile`). Granularidade de ação (`Read:`, `Edit:`) e escopo (`resource.write`) em exploração para VNext.
|