@asm-agent/coding-agent 0.9.3 → 0.9.4

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.
Files changed (39) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/bundled-extensions/00-COMECE-AQUI.txt +233 -0
  3. package/bundled-extensions/00-INDEX.md +267 -0
  4. package/bundled-extensions/OLLAMA-TOOL-FORCING-IMPLEMENTATION.md +323 -0
  5. package/bundled-extensions/OLLAMA-TOOL-FORCING-QUICK-START.txt +113 -0
  6. package/bundled-extensions/OLLAMA-TOOL-FORCING-TESTS.md +217 -0
  7. package/bundled-extensions/OLLAMA-TOOL-FORCING.md +155 -0
  8. package/bundled-extensions/README.txt +178 -0
  9. package/bundled-extensions/ollama-tool-forcing.ts +90 -0
  10. package/dist/asm-agent-runtime/run_test.py +19 -0
  11. package/dist/asm-agent-runtime/src/rlm/__pycache__/__init__.cpython-312.pyc +0 -0
  12. package/dist/asm-agent-runtime/src/rlm/__pycache__/bash.cpython-312.pyc +0 -0
  13. package/dist/asm-agent-runtime/src/rlm/__pycache__/repl.cpython-312.pyc +0 -0
  14. package/dist/asm-agent-runtime/test/__pycache__/test_bash.cpython-312.pyc +0 -0
  15. package/dist/asm-agent-runtime/test/test_bash.py +5 -3
  16. package/dist/bundle/{bundled-modules-ZKJOKVMT.js → bundled-modules-ABB56VC3.js} +2 -2
  17. package/dist/bundle/{chunk-IP6ZYRWR.js → chunk-GUPU2EEK.js} +13 -58
  18. package/dist/bundle/{chunk-YWSYGTH7.js → chunk-NESKY6T7.js} +2 -2
  19. package/dist/bundle/{cli-main-YZ2VGIP6.js → cli-main-ZYCGVTZE.js} +2 -2
  20. package/dist/bundle/cli.js +1 -1
  21. package/dist/bundle/{main-JTKNY7OB.js → main-J36EPND6.js} +2 -2
  22. package/dist/core/auth-storage.d.ts +0 -1
  23. package/dist/core/auth-storage.d.ts.map +1 -1
  24. package/dist/core/auth-storage.js +0 -49
  25. package/dist/core/auth-storage.js.map +1 -1
  26. package/dist/modes/interactive/auth-flows.d.ts.map +1 -1
  27. package/dist/modes/interactive/auth-flows.js +1 -1
  28. package/dist/modes/interactive/auth-flows.js.map +1 -1
  29. package/dist/postinstall.d.ts.map +1 -1
  30. package/dist/postinstall.js +40 -3
  31. package/dist/postinstall.js.map +1 -1
  32. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  33. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  34. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  35. package/examples/extensions/sandbox/package-lock.json +2 -2
  36. package/examples/extensions/sandbox/package.json +1 -1
  37. package/examples/extensions/with-deps/package-lock.json +2 -2
  38. package/examples/extensions/with-deps/package.json +1 -1
  39. package/package.json +7 -6
@@ -0,0 +1,155 @@
1
+ # Ollama Tool-Forcing Extension
2
+
3
+ Esta extensão resolve um problema comum ao usar modelos abertos menores (Qwen 27b, Llama, etc) rodando via Ollama com o ASM Agent.
4
+
5
+ ## Problema
6
+
7
+ Quando você roda um modelo menor localmente via Ollama, o seguinte comportamento pode ocorrer:
8
+
9
+ 1. O modelo começa a **gerar seu raciocínio** (thinking/internal reasoning)
10
+ 2. **Após pensar**, o modelo **não chama nenhuma ferramenta**
11
+ 3. O modelo **não gera nenhum texto final** para o usuário
12
+ 4. O modelo simplesmente **emite um "token de parada"** e encerra
13
+ 5. O ASM Agent fica **parado esperando você falar**
14
+
15
+ Isso não é um "bug" — é um comportamento comum de modelos menores quando não há instrução explícita.
16
+
17
+ ## Solução
18
+
19
+ Esta extensão **injeta automaticamente** uma instrução forte no system prompt que:
20
+
21
+ - ✅ **Força o modelo a chamar ferramentas** antes de parar
22
+ - ✅ **Proíbe gerações vazias** (só thinking sem ação)
23
+ - ✅ **Mantém o loop autônomo** funcionando continuamente
24
+ - ✅ **Funciona automaticamente** — sem precisar de comandos especiais
25
+
26
+ ## Como Usar
27
+
28
+ ### 1. Ativar a Extensão
29
+
30
+ A extensão já foi colocada em:
31
+ ```
32
+ ~/.asm-agent/extensions/ollama-tool-forcing.ts
33
+ ```
34
+
35
+ Ela é **auto-descoberta** — não precisa fazer nada especial. Será carregada automaticamente na próxima vez que você iniciar o ASM Agent.
36
+
37
+ ### 2. Recarregar em Tempo Real
38
+
39
+ Se o ASM Agent já está rodando, use o comando:
40
+ ```
41
+ /reload
42
+ ```
43
+
44
+ Isso recarrega todas as extensões sem precisar reiniciar.
45
+
46
+ ### 3. Verificar Status
47
+
48
+ Use o comando:
49
+ ```
50
+ /ollama-tools-info
51
+ ```
52
+
53
+ Ele mostra se a extensão está ativa (✅) e permite fazer toggle (ligar/desligar).
54
+
55
+ ## O Que a Extensão Faz
56
+
57
+ Quando você envia uma tarefa, a extensão adiciona isto ao final do system prompt:
58
+
59
+ ```
60
+ ## ⚠️ REGRA CRÍTICA: TOOL-FORCING PARA MODELOS LOCAIS
61
+
62
+ Você está rodando num modelo aberto (Ollama/local). Para garantir que trabalhe autonomamente:
63
+
64
+ 1. **NUNCA pare sem chamar uma ferramenta**: Depois de pensar/raciocinar, você DEVE chamar
65
+ uma ferramenta (bash, edit, ipython, etc) para continuar o trabalho.
66
+
67
+ 2. **Sem gerações vazias**: Não é permitido apenas gerar um "thinking" e depois parar.
68
+
69
+ 3. **Ferramentas = Continuidade**: Use-as para:
70
+ - Verificar status (bash, ipython)
71
+ - Fazer alterações (edit, bash)
72
+ - Validar resultados (bash com testes)
73
+ - Avançar a tarefa passo a passo
74
+
75
+ 4. **Padrão de turno correto**:
76
+ a) Receber tarefa e pensar (thinking)
77
+ b) Chamar uma ferramenta para agir
78
+ c) Observar resultado
79
+ d) Voltar ao passo (a) se precisar avançar
80
+
81
+ 5. **Proibido**: Terminar turno com apenas uma seção vazia de thinking.
82
+ ```
83
+
84
+ ## Quando Usar
85
+
86
+ - ✅ Rodando **Qwen 27b/32b** via Ollama
87
+ - ✅ Rodando **Llama** via Ollama
88
+ - ✅ Rodando qualquer **modelo aberto local**
89
+ - ✅ Modelo que às vezes **congela ou gera vazio**
90
+
91
+ ## Quando Pode Desativar
92
+
93
+ - Se rodando **Claude/GPT** (APIs online)
94
+ - Se o modelo está **funcionando bem** sem a regra
95
+ - Quando quer testar comportamento natural
96
+
97
+ Use `/ollama-tools-info` para toggle sem reiniciar.
98
+
99
+ ## Dicas Adicionais
100
+
101
+ ### Para melhor desempenho com Qwen:
102
+
103
+ ```bash
104
+ # Use a versão Coder (superior para tool-calling)
105
+ ollama pull qwen2.5-coder:32b
106
+
107
+ # Rode com mais contexto
108
+ ollama run qwen2.5-coder:32b
109
+ ```
110
+
111
+ ### Atualize o Ollama:
112
+
113
+ Versões antigas do Ollama podem engolir chamadas de ferramenta do Qwen. Mantenha atualizado:
114
+
115
+ ```bash
116
+ ollama --version
117
+ # Se antigo, atualize
118
+ ```
119
+
120
+ ### Use a extensão + instruções diretas:
121
+
122
+ Se o modelo ainda ficar preso, você pode também dar um empurrãozinho manualmente:
123
+
124
+ ```
125
+ "Como está o andamento? Use a ferramenta de bash para verificar e continue o trabalho imediatamente."
126
+ ```
127
+
128
+ ## Removendo a Extensão
129
+
130
+ Se quiser remover a regra permanentemente:
131
+
132
+ ```bash
133
+ rm ~/.asm-agent/extensions/ollama-tool-forcing.ts
134
+ /reload
135
+ ```
136
+
137
+ ## Arquivos Relacionados
138
+
139
+ - **Extensão**: `~/.asm-agent/extensions/ollama-tool-forcing.ts`
140
+ - **Documentação**: Este arquivo
141
+ - **Comando**: `/ollama-tools-info` (dentro do ASM Agent)
142
+ - **Reload**: `/reload` (para recarregar extensões)
143
+
144
+ ## Suporte
145
+
146
+ Se a extensão não funcionar:
147
+
148
+ 1. Verifique se o arquivo está em `~/.asm-agent/extensions/`
149
+ 2. Use `/reload` para recarregar
150
+ 3. Use `/ollama-tools-info` para verificar status
151
+ 4. Verifique logs do ASM Agent para erros de compilação TypeScript
152
+
153
+ ---
154
+
155
+ **Criado para resolver o problema de modelos abertos gerando vazios com ASM Agent.**
@@ -0,0 +1,178 @@
1
+
2
+ ╔════════════════════════════════════════════════════════════════════════════════╗
3
+ ║ 🎉 CUSTOM RULE CRIADA E PRONTA! ║
4
+ ║ Ollama Tool-Forcing Extension v1.0 ║
5
+ ╚════════════════════════════════════════════════════════════════════════════════╝
6
+
7
+ 📂 LOCALIZAÇÃO:
8
+ ~/.asm-agent/extensions/
9
+
10
+ 📦 ARQUIVOS CRIADOS (5 arquivos, ~18 KB total):
11
+
12
+ 1. ollama-tool-forcing.ts (3.2 KB)
13
+ → Extensão principal (TypeScript)
14
+ → Auto-descoberta pelo ASM Agent
15
+ → Sem dependências externas
16
+
17
+ 2. OLLAMA-TOOL-FORCING.md (4.4 KB)
18
+ → Manual completo
19
+ → Explicação detalhada do problema
20
+ → Quando usar/não usar
21
+ → Dicas de otimização
22
+
23
+ 3. OLLAMA-TOOL-FORCING-QUICK-START.txt (5.8 KB)
24
+ → Referência rápida visual
25
+ → Instruções em poucas linhas
26
+ → Próximos passos
27
+
28
+ 4. OLLAMA-TOOL-FORCING-TESTS.md (4.5 KB)
29
+ → 5 exemplos de teste
30
+ → Como verificar se funciona
31
+ → Troubleshooting
32
+
33
+ 5. OLLAMA-TOOL-FORCING-IMPLEMENTATION.md (6.5 KB)
34
+ → Guia de implementação
35
+ → Como funciona internamente
36
+ → Personalização avançada
37
+
38
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
39
+
40
+ ✨ O QUE ESSA CUSTOM RULE FAZ:
41
+
42
+ ┌─ PROBLEMA ORIGINAL ────────────────────────────────────────────────────────┐
43
+ │ │
44
+ │ Você roda Qwen/Llama via Ollama com ASM Agent: │
45
+ │ ❌ Modelo pensa um pouco │
46
+ │ ❌ Modelo para (emit stop token) │
47
+ │ ❌ Modelo não chama ferramenta │
48
+ │ ❌ ASM Agent fica esperando "e aí?" │
49
+ │ ❌ Loop autônomo quebrado │
50
+ │ │
51
+ └────────────────────────────────────────────────────────────────────────────┘
52
+
53
+ ↓ SOLUÇÃO ↓
54
+
55
+ ┌─ COM A EXTENSÃO ──────────────────────────────────────────────────────────┐
56
+ │ │
57
+ │ ✅ Extensão intercepta requisição (before_agent_start) │
58
+ │ ✅ Injeta regra CRÍTICA no system prompt │
59
+ │ ✅ Modelo recebe instrução forte: "NUNCA PARE SEM CHAMAR FERRAMENTA" │
60
+ │ ✅ Modelo é forçado a chamar bash/edit/ipython │
61
+ │ ✅ Loop autônomo continua funcionando │
62
+ │ ✅ Tarefa completada sem intervenção │
63
+ │ │
64
+ └────────────────────────────────────────────────────────────────────────────┘
65
+
66
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
67
+
68
+ 🚀 USAR AGORA (3 PASSOS):
69
+
70
+ 1️⃣ NADA! A extensão já está em ~/.asm-agent/extensions/
71
+
72
+ 2️⃣ Próxima vez que iniciar ASM Agent:
73
+ - Extensão será auto-descoberta
74
+ - Regra será injetada automaticamente
75
+ - Funcionará em TODAS as requisições
76
+
77
+ 3️⃣ Se ASM Agent já está rodando:
78
+ /reload (recarrega extensões)
79
+ /ollama-tools-info (verifica status)
80
+
81
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
82
+
83
+ 📋 REGRA INJETADA NO SYSTEM PROMPT:
84
+
85
+ ## ⚠️ REGRA CRÍTICA: TOOL-FORCING PARA MODELOS LOCAIS
86
+
87
+ 1. NUNCA pare sem chamar uma ferramenta
88
+ 2. Sem gerações vazias (só thinking não é permitido)
89
+ 3. Ferramentas = continuidade (use bash, edit, ipython constantemente)
90
+ 4. Padrão correto: pensar → agir → observar → repetir
91
+ 5. Proibido: terminar turno sem chamar ferramenta
92
+
93
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
94
+
95
+ 💻 TESTE AGORA:
96
+
97
+ Cole isso no ASM Agent com seu Qwen/Llama rodando:
98
+
99
+ "Crie um arquivo 'test.txt' com conteúdo 'Olá Ollama!' e use bash
100
+ para verificar que foi criado corretamente."
101
+
102
+ Resultado esperado:
103
+ ✅ Modelo chama edit (criar arquivo)
104
+ ✅ Modelo chama bash (verificar)
105
+ ✅ Tarefa completa, sem ele ficar preso
106
+
107
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
108
+
109
+ 📚 DOCUMENTAÇÃO:
110
+
111
+ Arquivo │ Objetivo │ Leia quando...
112
+ ──────────────────────┼─────────────────────────────────┼──────────────────
113
+ OLLAMA-TOOL-FORCING.md │ Manual completo │ Quer detalhes
114
+ QUICK-START.txt │ Referência rápida │ Quer começar logo
115
+ TESTS.md │ 5 exemplos de teste │ Quer testar agora
116
+ IMPLEMENTATION.md │ Como funciona internamente │ Quer customizar
117
+
118
+ Todos em ~/.asm-agent/extensions/
119
+
120
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
121
+
122
+ ⚙️ PERSONALIZAÇÃO:
123
+
124
+ Quer mudar o comportamento?
125
+
126
+ Edite: ~/.asm-agent/extensions/ollama-tool-forcing.ts
127
+ Depois: /reload
128
+
129
+ Quer desativar temporariamente?
130
+
131
+ /ollama-tools-info (faz toggle)
132
+
133
+ Quer remover permanentemente?
134
+
135
+ rm ~/.asm-agent/extensions/ollama-tool-forcing.ts
136
+ /reload
137
+
138
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
139
+
140
+ 🎯 RESUMO TÉCNICO:
141
+
142
+ • TYPE: Custom Rule (Extensão ASM Agent)
143
+ • LINGUAGEM: TypeScript (compilado automaticamente)
144
+ • TAMANHO: ~3 KB executável, impacto ZERO em performance
145
+ • COMPATIBILIDADE: Qualquer modelo aberto (Qwen, Llama, Mistral, etc)
146
+ • DEPENDÊNCIAS: Nenhuma (usa API nativa do ASM Agent)
147
+ • ATIVAÇÃO: Auto-descoberta (~/.asm-agent/extensions/)
148
+ • SCOPO: Injeta regra no system prompt (antes do modelo pensar)
149
+ • REVERT: Pode ser desativado ou removido a qualquer hora
150
+
151
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
152
+
153
+ ✅ CHECKLIST DE IMPLEMENTAÇÃO:
154
+
155
+ ☑ Extensão criada: ~/.asm-agent/extensions/ollama-tool-forcing.ts
156
+ ☑ Documentação escrita: 4 arquivos .md/.txt
157
+ ☑ Comando registrado: /ollama-tools-info
158
+ ☑ Auto-descoberta: Funcionará na próxima sessão
159
+ ☑ Exemplos de teste: OLLAMA-TOOL-FORCING-TESTS.md
160
+ ☑ Troubleshooting: Incluído em OLLAMA-TOOL-FORCING.md
161
+ ☑ Sem dependencies: 100% nativo do ASM Agent
162
+
163
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
164
+
165
+ 🎬 PRÓXIMA AÇÃO:
166
+
167
+ 1. Reinicie ASM Agent (ou use /reload se já estiver rodando)
168
+ 2. Teste com uma tarefa simples
169
+ 3. Observe o modelo chamar ferramentas continuamente
170
+ 4. Aproveite o loop autônomo sem interrupções!
171
+
172
+ ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
173
+
174
+ ╔════════════════════════════════════════════════════════════════════════════════╗
175
+ ║ 🎊 Configuração completa! Bom trabalho! 🎊 ║
176
+ ║ Seus modelos Ollama agora trabalham melhor ║
177
+ ║ com o ASM Agent autonomamente. ║
178
+ ╚════════════════════════════════════════════════════════════════════════════════╝
@@ -0,0 +1,90 @@
1
+ /**
2
+ * Ollama Tool-Forcing Extension
3
+ *
4
+ * Força modelos open-weights rodando via Ollama a sempre chamar uma ferramenta
5
+ * antes de parar, evitando que gerem apenas tokens de parada sem completar tarefas.
6
+ *
7
+ * Problema: Modelos menores (Qwen 27b, Llama, etc) às vezes apenas pensam
8
+ * e depois emitem um stop token sem chamar ferramentas ou gerar texto.
9
+ *
10
+ * Solução: Injeta no system prompt uma instrução forte que força o modelo a:
11
+ * 1. Nunca parar sem chamar uma ferramenta
12
+ * 2. Usar ferramentas para continuar o trabalho
13
+ * 3. Sempre completar o ciclo de tarefas
14
+ *
15
+ * Uso:
16
+ * 1. Copie este arquivo para ~/.asm-agent/extensions/ (global)
17
+ * ou .asm-agent/extensions/ (projeto-local)
18
+ * 2. Use /reload para ativar (se em modo interativo)
19
+ * 3. A extensão funciona automaticamente em todas as requisições
20
+ *
21
+ * Opcional: Use /ollama-tools-info para ver o status
22
+ */
23
+
24
+ import type { ExtensionAPI } from "@asm-agent/coding-agent";
25
+
26
+ export default function ollamaToolForcingExtension(pi: ExtensionAPI) {
27
+ let enabled = true;
28
+
29
+ // Comando para ver status e toggle
30
+ pi.registerCommand("ollama-tools-info", {
31
+ description: "Mostra status do Ollama Tool-Forcing e permite toggle",
32
+ handler: async (_args, ctx) => {
33
+ enabled = !enabled;
34
+ const status = enabled ? "✅ ATIVADO" : "❌ DESATIVADO";
35
+ ctx.ui.notify(
36
+ `Ollama Tool-Forcing: ${status}\n\n` +
37
+ `Este modo força modelos abertos a chamar ferramentas antes de parar, ` +
38
+ `evitando gerações vazias que interrompem o loop autônomo do ASM Agent.`,
39
+ "info"
40
+ );
41
+ },
42
+ });
43
+
44
+ // Injetar instrução no system prompt antes de cada turno
45
+ pi.on("before_agent_start", async (event) => {
46
+ if (!enabled) {
47
+ return undefined;
48
+ }
49
+
50
+ // Instrução forte para forçar uso de ferramentas
51
+ const toolForceRule = \`
52
+
53
+ ## ⚠️ REGRA CRÍTICA: TOOL-FORCING PARA MODELOS LOCAIS
54
+
55
+ Você está rodando num modelo aberto (Ollama/local). Para garantir que trabalhe autonomamente:
56
+
57
+ 1. **NUNCA pare sem chamar uma ferramenta**: Depois de pensar/raciocinar, você DEVE chamar
58
+ uma ferramenta (bash, edit, ipython, etc) para continuar o trabalho.
59
+
60
+ 2. **Sem gerações vazias**: Não é permitido apenas gerar um "thinking" e depois parar.
61
+ Se terminou um ciclo, chame uma ferramenta para validar ou avançar.
62
+
63
+ 3. **Ferramentas = Continuidade**: As ferramentas são como seus "pulmões". Use-as para:
64
+ - Verificar status (bash, ipython)
65
+ - Fazer alterações (edit, bash)
66
+ - Validar resultados (bash com testes)
67
+ - Avançar a tarefa passo a passo
68
+
69
+ 4. **Padrão de turno correto**:
70
+ a) Receber tarefa e pensar (thinking)
71
+ b) Chamar uma ferramenta para agir
72
+ c) Observar resultado
73
+ d) Voltar ao passo (a) se precisar avançar
74
+
75
+ 5. **Proibido**: Terminar turno com apenas:
76
+ - Uma seção de "thinking" vazia
77
+ - Sem nenhuma tool call
78
+ - Sem texto de resposta
79
+
80
+ Se não tiver nada para fazer, ainda assim chame bash ou ipython para verificar status.
81
+
82
+ ESSA REGRA SE APLICA SEMPRE. Sem exceções. Modelos menores têm tendência de "congelar"
83
+ se deixados livres — use ferramentas constantemente para manter-se "vivo".
84
+ \`;
85
+
86
+ return {
87
+ systemPrompt: event.systemPrompt + toolForceRule,
88
+ };
89
+ });
90
+ }
@@ -0,0 +1,19 @@
1
+ import asyncio
2
+ import os
3
+ import sys
4
+ import unittest
5
+ import logging
6
+ from test.test_bash import BashTest
7
+
8
+ class CustomTestResult(unittest.TextTestResult):
9
+ def addFailure(self, test, err):
10
+ super().addFailure(test, err)
11
+ print("\n=== FAILURE DETAILS ===")
12
+ print(f"Failed test: {test.id()}")
13
+ print(f"Error: {err}")
14
+
15
+ if __name__ == '__main__':
16
+ suite = unittest.TestSuite()
17
+ suite.addTest(BashTest("test_undelivered_kill_leaves_journal_record_active"))
18
+ runner = unittest.TextTestRunner(resultclass=CustomTestResult)
19
+ runner.run(suite)
@@ -1121,12 +1121,12 @@ class BashTest(unittest.IsolatedAsyncioTestCase):
1121
1121
  ):
1122
1122
  handle = bash("sleep 30")
1123
1123
  try:
1124
- records = await _poll_journal(journal, count=1)
1124
+ records = await _poll_journal(journal, count=1, pid=handle.pid)
1125
1125
  self.assertTrue(records[-1]["active"])
1126
1126
  with mock.patch.object(bash_module, "_signal_group", return_value=False):
1127
1127
  bash_module._kill_live_handles()
1128
1128
  await asyncio.sleep(0.2) # give any (wrong) inactive write time to land
1129
- records = await _poll_journal(journal, count=1)
1129
+ records = await _poll_journal(journal, count=1, pid=handle.pid)
1130
1130
  self.assertEqual(len(records), 1)
1131
1131
  self.assertTrue(records[-1]["active"])
1132
1132
  finally:
@@ -1260,12 +1260,14 @@ async def _poll_group_dead(pgid: int, timeout: float = 5.0) -> None:
1260
1260
  raise AssertionError(f"process group {pgid} still alive after {timeout}s")
1261
1261
 
1262
1262
 
1263
- async def _poll_journal(path: str, count: int, timeout: float = 2.0) -> list[dict]:
1263
+ async def _poll_journal(path: str, count: int, timeout: float = 2.0, pid: int | None = None) -> list[dict]:
1264
1264
  deadline = asyncio.get_running_loop().time() + timeout
1265
1265
  records: list[dict] = []
1266
1266
  while asyncio.get_running_loop().time() < deadline:
1267
1267
  with open(path) as f:
1268
1268
  records = [json.loads(line) for line in f if line.strip()]
1269
+ if pid is not None:
1270
+ records = [r for r in records if r.get("pid") == pid]
1269
1271
  if len(records) >= count:
1270
1272
  return records
1271
1273
  await asyncio.sleep(0.05)
@@ -52,7 +52,7 @@ import {
52
52
  oauth_exports,
53
53
  runPrintMode,
54
54
  runRpcMode
55
- } from "./chunk-IP6ZYRWR.js";
55
+ } from "./chunk-GUPU2EEK.js";
56
56
  import {
57
57
  AgentSession,
58
58
  CURRENT_SESSION_VERSION,
@@ -136,7 +136,7 @@ import {
136
136
  withFileMutationQueue,
137
137
  wrapRegisteredTool,
138
138
  wrapRegisteredTools
139
- } from "./chunk-YWSYGTH7.js";
139
+ } from "./chunk-NESKY6T7.js";
140
140
  import "./chunk-VWR3YFK5.js";
141
141
  import "./chunk-N2CSAETN.js";
142
142
  import "./chunk-5QCJ5DQU.js";
@@ -329,7 +329,7 @@ import {
329
329
  waitForPromptAdmission,
330
330
  watchWithErrorHandler,
331
331
  wrapTextWithAnsi
332
- } from "./chunk-YWSYGTH7.js";
332
+ } from "./chunk-NESKY6T7.js";
333
333
  import {
334
334
  array,
335
335
  boolean,
@@ -10216,7 +10216,6 @@ __export(oauth_exports, {
10216
10216
  // dist/core/auth-storage.js
10217
10217
  var import_proper_lockfile = __toESM(require_proper_lockfile(), 1);
10218
10218
  import { chmodSync as chmodSync2, existsSync as existsSync2, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
10219
- import { homedir as homedir2 } from "os";
10220
10219
  import { dirname as dirname3, join as join3 } from "path";
10221
10220
 
10222
10221
  // dist/core/prime-inference-auth.js
@@ -10895,31 +10894,6 @@ var AuthStorage = class _AuthStorage {
10895
10894
  })
10896
10895
  };
10897
10896
  }
10898
- getAntigravityAuthCandidate(provider) {
10899
- if (provider !== "google" && provider !== "gemini") {
10900
- return void 0;
10901
- }
10902
- const credsPath = join3(homedir2(), ".gemini", "oauth_creds.json");
10903
- if (!existsSync2(credsPath)) {
10904
- return void 0;
10905
- }
10906
- try {
10907
- const data = JSON.parse(readFileSync2(credsPath, "utf-8"));
10908
- if (data && data.access_token) {
10909
- return {
10910
- label: "Antigravity CLI",
10911
- ...this.createAuthSourceCandidate({
10912
- configured: false,
10913
- source: "antigravity",
10914
- identityMaterial: provider,
10915
- valueMaterial: data.access_token
10916
- })
10917
- };
10918
- }
10919
- } catch {
10920
- }
10921
- return void 0;
10922
- }
10923
10897
  getStoredAuthCandidate(provider, options) {
10924
10898
  const credential = this.data[provider] ?? (provider === "google" ? this.data.gemini : provider === "gemini" ? this.data.google : void 0);
10925
10899
  if (!credential) {
@@ -11004,7 +10978,6 @@ var AuthStorage = class _AuthStorage {
11004
10978
  fallbackCandidate
11005
10979
  ] : [
11006
10980
  this.getRuntimeAuthCandidate(provider),
11007
- this.getAntigravityAuthCandidate(provider),
11008
10981
  this.getStoredAuthCandidate(provider),
11009
10982
  this.getEnvironmentAuthCandidate(provider),
11010
10983
  fallbackCandidate
@@ -11327,24 +11300,6 @@ var AuthStorage = class _AuthStorage {
11327
11300
  };
11328
11301
  }
11329
11302
  }
11330
- if (providerId === "google" || providerId === "gemini") {
11331
- const agyCandidate = this.getAntigravityAuthCandidate(providerId);
11332
- if (agyCandidate && !this.isAuthSourceStale(providerId, agyCandidate)) {
11333
- const credsPath = join3(homedir2(), ".gemini", "oauth_creds.json");
11334
- if (existsSync2(credsPath)) {
11335
- try {
11336
- const data = JSON.parse(readFileSync2(credsPath, "utf-8"));
11337
- if (data && data.access_token) {
11338
- return {
11339
- apiKey: data.access_token,
11340
- sourceToken: this.getAuthSourceTokenForCandidate(providerId, agyCandidate)
11341
- };
11342
- }
11343
- } catch {
11344
- }
11345
- }
11346
- }
11347
- }
11348
11303
  const cred = this.get(providerId);
11349
11304
  if (cred?.type === "api_key") {
11350
11305
  const storedCandidate = this.getStoredAuthCandidate(providerId);
@@ -11776,7 +11731,7 @@ function requireCount(args, count, usage) {
11776
11731
  // dist/core/settings-manager.js
11777
11732
  var import_proper_lockfile2 = __toESM(require_proper_lockfile(), 1);
11778
11733
  import { existsSync as existsSync3, mkdirSync as mkdirSync3, readFileSync as readFileSync3, renameSync as renameSync2, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
11779
- import { homedir as homedir3 } from "os";
11734
+ import { homedir as homedir2 } from "os";
11780
11735
  import { dirname as dirname4, join as join4 } from "path";
11781
11736
  var RECENT_MODELS_LIMIT = 20;
11782
11737
  var DEFAULT_IDLE_EVICTION_MINUTES = 90;
@@ -12141,10 +12096,10 @@ var SettingsManager = class _SettingsManager {
12141
12096
  return sessionDir;
12142
12097
  }
12143
12098
  if (sessionDir === "~") {
12144
- return homedir3();
12099
+ return homedir2();
12145
12100
  }
12146
12101
  if (sessionDir.startsWith("~/")) {
12147
- return join4(homedir3(), sessionDir.slice(2));
12102
+ return join4(homedir2(), sessionDir.slice(2));
12148
12103
  }
12149
12104
  return sessionDir;
12150
12105
  }
@@ -13542,7 +13497,7 @@ async function launchDaemonUpdateRestartCoordinator(options) {
13542
13497
  import { spawn as spawn2, spawnSync } from "node:child_process";
13543
13498
  import { createHash as createHash3 } from "node:crypto";
13544
13499
  import { existsSync as existsSync4, mkdirSync as mkdirSync5, readdirSync, readFileSync as readFileSync5, rmSync as rmSync3, statSync, writeFileSync as writeFileSync5 } from "node:fs";
13545
- import { homedir as homedir4, tmpdir } from "node:os";
13500
+ import { homedir as homedir3, tmpdir } from "node:os";
13546
13501
  import { basename as basename3, dirname as dirname6, join as join6, relative as relative2, resolve as resolve3, sep as sep2 } from "node:path";
13547
13502
 
13548
13503
  // ../../node_modules/glob/dist/esm/index.min.js
@@ -18495,7 +18450,7 @@ function toPosixPath(p) {
18495
18450
  return p.split(sep2).join("/");
18496
18451
  }
18497
18452
  function getHomeDir() {
18498
- return process.env.HOME || homedir4();
18453
+ return process.env.HOME || homedir3();
18499
18454
  }
18500
18455
  function prefixIgnorePattern(line, prefix) {
18501
18456
  const trimmed = line.trim();
@@ -20320,7 +20275,7 @@ var DefaultPackageManager = class {
20320
20275
  var import_proper_lockfile4 = __toESM(require_proper_lockfile(), 1);
20321
20276
  import { createHash as createHash4, randomUUID as randomUUID2 } from "node:crypto";
20322
20277
  import { existsSync as existsSync5, mkdirSync as mkdirSync6, readdirSync as readdirSync2, readFileSync as readFileSync6, realpathSync, renameSync as renameSync4, rmSync as rmSync4, writeFileSync as writeFileSync6 } from "node:fs";
20323
- import { homedir as homedir5 } from "node:os";
20278
+ import { homedir as homedir4 } from "node:os";
20324
20279
  import { basename as basename4, dirname as dirname7, join as join7, resolve as resolve4 } from "node:path";
20325
20280
  var DAEMON_SUPERVISOR_REGISTRY_DIR_ENV = "ASM_AGENT_INTERNAL_DAEMON_SUPERVISOR_REGISTRY_DIR";
20326
20281
  var OWNER_VERSION = 1;
@@ -20509,7 +20464,7 @@ var DaemonShutdownAdmission = class {
20509
20464
  }
20510
20465
  };
20511
20466
  function defaultDaemonSupervisorRegistryDir(environment = process.env) {
20512
- return environment[DAEMON_SUPERVISOR_REGISTRY_DIR_ENV] ?? join7(homedir5(), ".asm-agent", "supervisor-owners");
20467
+ return environment[DAEMON_SUPERVISOR_REGISTRY_DIR_ENV] ?? join7(homedir4(), ".asm-agent", "supervisor-owners");
20513
20468
  }
20514
20469
  function legacyDaemonSupervisorRegistryDir(environment = process.env) {
20515
20470
  return environment[DAEMON_SUPERVISOR_REGISTRY_DIR_ENV] ? void 0 : resolve4(defaultDaemonSocketDir(), "supervisor-owners");
@@ -26930,7 +26885,7 @@ File: ${modelsJsonPath}`);
26930
26885
 
26931
26886
  // dist/core/resource-loader.js
26932
26887
  import { existsSync as existsSync9, readdirSync as readdirSync4, readFileSync as readFileSync10, statSync as statSync3 } from "node:fs";
26933
- import { homedir as homedir6 } from "node:os";
26888
+ import { homedir as homedir5 } from "node:os";
26934
26889
  import { join as join10, resolve as resolve8, sep as sep4 } from "node:path";
26935
26890
  function resolvePromptInput(input, description) {
26936
26891
  if (!input) {
@@ -27406,11 +27361,11 @@ var DefaultResourceLoader = class {
27406
27361
  const trimmed = p.trim();
27407
27362
  let expanded = trimmed;
27408
27363
  if (trimmed === "~") {
27409
- expanded = homedir6();
27364
+ expanded = homedir5();
27410
27365
  } else if (trimmed.startsWith("~/")) {
27411
- expanded = join10(homedir6(), trimmed.slice(2));
27366
+ expanded = join10(homedir5(), trimmed.slice(2));
27412
27367
  } else if (trimmed.startsWith("~")) {
27413
- expanded = join10(homedir6(), trimmed.slice(1));
27368
+ expanded = join10(homedir5(), trimmed.slice(1));
27414
27369
  }
27415
27370
  return resolve8(this.cwd, expanded);
27416
27371
  }
@@ -40328,7 +40283,7 @@ var PrimeTeamSelectorComponent = class extends Container {
40328
40283
 
40329
40284
  // dist/modes/interactive/auth-flows.js
40330
40285
  var BEDROCK_PROVIDER_ID = "amazon-bedrock";
40331
- var ASM_AGENT_LOGIN_PROVIDER_IDS = /* @__PURE__ */ new Set(["openai-codex", "anthropic", "google", "gemini"]);
40286
+ var ASM_AGENT_LOGIN_PROVIDER_IDS = /* @__PURE__ */ new Set(["openai-codex", "anthropic"]);
40332
40287
  var ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
40333
40288
  function isAnthropicSubscriptionAuthKey(apiKey) {
40334
40289
  return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");