@nac3/forge-cli 1.8.1 → 1.8.3
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/bin/yf.js +0 -0
- package/dist/chat/project_slug.d.ts +13 -3
- package/dist/chat/project_slug.d.ts.map +1 -1
- package/dist/chat/project_slug.js +32 -25
- package/dist/chat/project_slug.js.map +1 -1
- package/dist/chat/server.d.ts +10 -0
- package/dist/chat/server.d.ts.map +1 -1
- package/dist/chat/server.js +87 -11
- package/dist/chat/server.js.map +1 -1
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +8 -27
- package/dist/commands/chat.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +20 -18
package/dist/bin/yf.js
CHANGED
|
File without changes
|
|
@@ -10,8 +10,18 @@
|
|
|
10
10
|
* a stable slug. Returns '' only when the input is empty. */
|
|
11
11
|
export declare function sanitizeProjectSlug(raw: string): string;
|
|
12
12
|
export declare function resolveProjectSlug(projectRoot: string): Promise<string>;
|
|
13
|
-
/** Sync variant for
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
/** Sync variant for callers that cannot await (el scope del cerebro en
|
|
14
|
+
* `yf chat`, `yf graph`, el anuncio mDNS). Mismo orden de resolucion que
|
|
15
|
+
* la async: yujin.forge.json -> package.json -> basename.
|
|
16
|
+
*
|
|
17
|
+
* 2026-10-02 -- esto leia los archivos con un require de node:fs. El CLI es
|
|
18
|
+
* ESM puro ("type": "module"), asi que ahi `require` no existe: tiraba
|
|
19
|
+
* ReferenceError, el catch exterior se lo tragaba y SIEMPRE devolvia el
|
|
20
|
+
* basename. En C:\adip\kikan daba "kikan" en vez de "yujin-kikan" (el name
|
|
21
|
+
* del package.json), asi que `yf chat` ataba el cerebro al slug equivocado
|
|
22
|
+
* y arrancaba con el cerebro COMPARTIDO en vez del del proyecto -- habia que
|
|
23
|
+
* tocar Plan en el panel para enderezarlo. Con el import estatico de
|
|
24
|
+
* readFileSync las dos variantes dan siempre lo mismo. Returns '' cuando no
|
|
25
|
+
* hay nada que sirva. */
|
|
16
26
|
export declare function resolveProjectSlugSync(projectRoot: string): string;
|
|
17
27
|
//# sourceMappingURL=project_slug.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_slug.d.ts","sourceRoot":"","sources":["../../src/chat/project_slug.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;8DAS8D;AAC9D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB7E;AAED
|
|
1
|
+
{"version":3,"file":"project_slug.d.ts","sourceRoot":"","sources":["../../src/chat/project_slug.ts"],"names":[],"mappings":"AAsBA;;;;;;;;;8DAS8D;AAC9D,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAYvD;AAED,wBAAsB,kBAAkB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAsB7E;AAED;;;;;;;;;;;;0BAY0B;AAC1B,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAsBlE"}
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
*
|
|
18
18
|
* ASCII-only.
|
|
19
19
|
*/
|
|
20
|
-
import { promises as fs } from 'node:fs';
|
|
20
|
+
import { promises as fs, readFileSync } from 'node:fs';
|
|
21
21
|
import path from 'node:path';
|
|
22
22
|
/** Make a raw slug filesystem-safe + stable (PND/dogfood
|
|
23
23
|
* 2026-06-10). The graph/pending/wiring stores reject slugs with
|
|
@@ -69,35 +69,42 @@ export async function resolveProjectSlug(projectRoot) {
|
|
|
69
69
|
/* 3. basename */
|
|
70
70
|
return sanitizeProjectSlug(path.basename(projectRoot));
|
|
71
71
|
}
|
|
72
|
-
/** Sync variant for
|
|
73
|
-
*
|
|
74
|
-
*
|
|
72
|
+
/** Sync variant for callers that cannot await (el scope del cerebro en
|
|
73
|
+
* `yf chat`, `yf graph`, el anuncio mDNS). Mismo orden de resolucion que
|
|
74
|
+
* la async: yujin.forge.json -> package.json -> basename.
|
|
75
|
+
*
|
|
76
|
+
* 2026-10-02 -- esto leia los archivos con un require de node:fs. El CLI es
|
|
77
|
+
* ESM puro ("type": "module"), asi que ahi `require` no existe: tiraba
|
|
78
|
+
* ReferenceError, el catch exterior se lo tragaba y SIEMPRE devolvia el
|
|
79
|
+
* basename. En C:\adip\kikan daba "kikan" en vez de "yujin-kikan" (el name
|
|
80
|
+
* del package.json), asi que `yf chat` ataba el cerebro al slug equivocado
|
|
81
|
+
* y arrancaba con el cerebro COMPARTIDO en vez del del proyecto -- habia que
|
|
82
|
+
* tocar Plan en el panel para enderezarlo. Con el import estatico de
|
|
83
|
+
* readFileSync las dos variantes dan siempre lo mismo. Returns '' cuando no
|
|
84
|
+
* hay nada que sirva. */
|
|
75
85
|
export function resolveProjectSlugSync(projectRoot) {
|
|
76
|
-
/*
|
|
86
|
+
/* 1. yujin.forge.json -> project_slug / project_name */
|
|
77
87
|
try {
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
const parsed = JSON.parse(raw);
|
|
83
|
-
if (parsed && typeof parsed.project_slug === 'string' && parsed.project_slug.trim() !== '') {
|
|
84
|
-
return sanitizeProjectSlug(parsed.project_slug);
|
|
85
|
-
}
|
|
86
|
-
if (parsed && typeof parsed.project_name === 'string' && parsed.project_name.trim() !== '') {
|
|
87
|
-
return sanitizeProjectSlug(parsed.project_name);
|
|
88
|
-
}
|
|
88
|
+
const raw = readFileSync(path.join(projectRoot, 'yujin.forge.json'), 'utf-8');
|
|
89
|
+
const parsed = JSON.parse(raw);
|
|
90
|
+
if (parsed && typeof parsed.project_slug === 'string' && parsed.project_slug.trim() !== '') {
|
|
91
|
+
return sanitizeProjectSlug(parsed.project_slug);
|
|
89
92
|
}
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
const raw = fsSync.readFileSync(path.join(projectRoot, 'package.json'), 'utf-8');
|
|
93
|
-
const parsed = JSON.parse(raw);
|
|
94
|
-
if (parsed && typeof parsed.name === 'string' && parsed.name.trim() !== '') {
|
|
95
|
-
return sanitizeProjectSlug(parsed.name);
|
|
96
|
-
}
|
|
93
|
+
if (parsed && typeof parsed.project_name === 'string' && parsed.project_name.trim() !== '') {
|
|
94
|
+
return sanitizeProjectSlug(parsed.project_name);
|
|
97
95
|
}
|
|
98
|
-
catch { /* */ }
|
|
99
96
|
}
|
|
100
|
-
catch { /* */ }
|
|
97
|
+
catch { /* fall through */ }
|
|
98
|
+
/* 2. package.json -> name */
|
|
99
|
+
try {
|
|
100
|
+
const raw = readFileSync(path.join(projectRoot, 'package.json'), 'utf-8');
|
|
101
|
+
const parsed = JSON.parse(raw);
|
|
102
|
+
if (parsed && typeof parsed.name === 'string' && parsed.name.trim() !== '') {
|
|
103
|
+
return sanitizeProjectSlug(parsed.name);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
catch { /* fall through */ }
|
|
107
|
+
/* 3. basename */
|
|
101
108
|
return sanitizeProjectSlug(path.basename(projectRoot));
|
|
102
109
|
}
|
|
103
110
|
//# sourceMappingURL=project_slug.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project_slug.js","sourceRoot":"","sources":["../../src/chat/project_slug.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AACH,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"project_slug.js","sourceRoot":"","sources":["../../src/chat/project_slug.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/server.d.ts
CHANGED
|
@@ -71,6 +71,16 @@ export interface StartedServer {
|
|
|
71
71
|
* publish its result on the typed 'session_reply' lane back to the
|
|
72
72
|
* parent (yujin.session.*). */
|
|
73
73
|
bridge?: import('./bridge.js').BridgeHandle | null;
|
|
74
|
+
/** Hot re-anchor: re-apunta ESTA instancia viva a otro proyecto (lo que
|
|
75
|
+
* hace yujin.project.set-root). Expuesto porque es un cambio de estado de
|
|
76
|
+
* sesion -- scope del cerebro, modalidad Plan/Console, grafo, watcher --
|
|
77
|
+
* y hasta ahora solo se alcanzaba por un verbo con token, asi que los
|
|
78
|
+
* tests tenian que mockearlo. */
|
|
79
|
+
reanchor: (newRoot: string) => Promise<{
|
|
80
|
+
projectRoot: string;
|
|
81
|
+
projectName: string;
|
|
82
|
+
projectSlug: string;
|
|
83
|
+
}>;
|
|
74
84
|
}
|
|
75
85
|
export declare function startChatServer(opts: StartOptions): Promise<StartedServer>;
|
|
76
86
|
interface Ctx {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AACH,OAAO,EAA2D,KAAK,MAAM,EAAE,MAAM,WAAW,CAAC;AAKjG,OAAO,EAAoD,KAAK,aAAa,EAAoB,MAAM,aAAa,CAAC;AAErH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAInD,OAAO,EAEL,KAAK,SAAS,EACf,MAAM,iBAAiB,CAAC;AAczB,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAsBjD,OAAO,EAAyD,KAAK,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAsB1H,MAAM,WAAW,YAAY;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,yDAAyD;IACzD,MAAM,CAAC,EAAE,aAAa,CAAC;IACvB;;;;;;;;wDAQoD;IACpD,YAAY,CAAC,EAAE,eAAe,GAAG,iBAAiB,CAAC;IACnD;;2DAEuD;IACvD,mBAAmB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC/B;+CAC2C;IAC3C,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB;;;kEAG8D;IAC9D,OAAO,CAAC,EAAE,OAAO,sBAAsB,EAAE,OAAO,CAAC;IACjD;;;;;;;iDAO6C;IAC7C,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;oDAEgD;IAChD,kBAAkB,CAAC,EAAE,OAAO,CAAC;CAC9B;AAED,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ;qEACiE;IACjE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,eAAe,CAAC;IACvB,KAAK,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC3B;;;oCAGgC;IAChC,MAAM,CAAC,EAAE,OAAO,aAAa,EAAE,YAAY,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/chat/server.ts"],"names":[],"mappings":"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"}
|
package/dist/chat/server.js
CHANGED
|
@@ -131,6 +131,20 @@ export async function startChatServer(opts) {
|
|
|
131
131
|
* CLI + panel converge. */
|
|
132
132
|
const { resolveProjectSlug } = await import('./project_slug.js');
|
|
133
133
|
const projectSlug = await resolveProjectSlug(opts.projectRoot);
|
|
134
|
+
/* Cerebro por instancia (Pablo, 2026-09-30). Habia una sola config para
|
|
135
|
+
* todas: cambiar el cerebro en un `yf chat` lo cambiaba en todos. Este
|
|
136
|
+
* proceso queda atado al cerebro de SU proyecto -- lee el del proyecto si
|
|
137
|
+
* existe y cae al global si no, asi que nada cambia hasta que alguien
|
|
138
|
+
* elige uno aca, y ahi el cambio se queda aca.
|
|
139
|
+
*
|
|
140
|
+
* 2026-10-03 -- esto estaba DESPUES de construir el brain client, asi que
|
|
141
|
+
* la modalidad (Plan/Console) se decidia con el scope todavia sin atar.
|
|
142
|
+
* Va antes de cualquier lectura de brain_config. */
|
|
143
|
+
try {
|
|
144
|
+
const { setBrainConfigScope } = await import('../core/brain_config.js');
|
|
145
|
+
setBrainConfigScope(projectSlug);
|
|
146
|
+
}
|
|
147
|
+
catch { /* sin scope se sigue usando el global, como antes */ }
|
|
134
148
|
/* Director sprint slice 9 -- hydrate ingest sessions from disk
|
|
135
149
|
* for this project so spec extract+plan survive restarts. */
|
|
136
150
|
try {
|
|
@@ -234,9 +248,42 @@ export async function startChatServer(opts) {
|
|
|
234
248
|
}
|
|
235
249
|
return new ClaudeClient();
|
|
236
250
|
}
|
|
251
|
+
/* De donde sale la modalidad cuando el llamador no la fija: la config del
|
|
252
|
+
* cerebro de ESTE proyecto (ya scopeada arriba) y, si no dice nada, el
|
|
253
|
+
* camino que eligio el wizard. Prioridad: --provider > brain_config >
|
|
254
|
+
* wizard_state > anthropic-api.
|
|
255
|
+
*
|
|
256
|
+
* 2026-10-03 -- esto se derivaba en `yf chat` ANTES de arrancar el server,
|
|
257
|
+
* con un scope resuelto por otro camino (resolveProjectSlugSync). Cuando
|
|
258
|
+
* los dos slugs no coincidian, el boot leia la config del proyecto
|
|
259
|
+
* equivocado: el panel mostraba la modalidad correcta (lee la config ya
|
|
260
|
+
* scopeada) y el cerebro vivo era el de arrastre. Ahora la cadena vive
|
|
261
|
+
* aca, que es donde se resuelve el slug autoritativo. */
|
|
262
|
+
async function providerFromBrainConfig() {
|
|
263
|
+
try {
|
|
264
|
+
const { readBrainConfig } = await import('../core/brain_config.js');
|
|
265
|
+
const bc = await readBrainConfig();
|
|
266
|
+
if (bc.anthropic_mode === 'plan')
|
|
267
|
+
return 'claude-code-cli';
|
|
268
|
+
if (bc.anthropic_mode === 'console')
|
|
269
|
+
return 'anthropic-api';
|
|
270
|
+
}
|
|
271
|
+
catch { /* sin config -> probamos el wizard */ }
|
|
272
|
+
try {
|
|
273
|
+
const { readWizardState } = await import('../core/wizard_state.js');
|
|
274
|
+
if ((await readWizardState()).path_chosen === 'claude_plan')
|
|
275
|
+
return 'claude-code-cli';
|
|
276
|
+
}
|
|
277
|
+
catch { /* swallow */ }
|
|
278
|
+
return null;
|
|
279
|
+
}
|
|
280
|
+
/* `--provider` -- y el anthropic-api forzado de una sub-sesion agentMode,
|
|
281
|
+
* que es lo que hace que el scope de verbos aplique -- pisan la config y
|
|
282
|
+
* NO se re-derivan: ni al boot ni al cambiar de proyecto. */
|
|
283
|
+
const providerPinned = !!opts.chatProvider;
|
|
237
284
|
/* MUTABLE per-session provider state, so flipping Plan/Console in the
|
|
238
285
|
* panel applies LIVE (mirrors the reanchor pattern). */
|
|
239
|
-
let activeChatProvider = opts.chatProvider ?? 'anthropic-api';
|
|
286
|
+
let activeChatProvider = opts.chatProvider ?? (await providerFromBrainConfig()) ?? 'anthropic-api';
|
|
240
287
|
let claude = opts.claude ?? await buildClaudeClient(activeChatProvider);
|
|
241
288
|
/** Hot-swap the brain provider when the user flips the mode in the
|
|
242
289
|
* panel. 'plan' -> claude-code-cli (subscription); 'console' ->
|
|
@@ -256,6 +303,25 @@ export async function startChatServer(opts) {
|
|
|
256
303
|
catch { /* */ }
|
|
257
304
|
return true;
|
|
258
305
|
}
|
|
306
|
+
/** El cerebro sigue al proyecto activo: despues de un reanchor hay que
|
|
307
|
+
* re-derivar la modalidad del proyecto NUEVO. Sin esto el provider
|
|
308
|
+
* quedaba de arrastre (el del proyecto anterior) mientras el selector del
|
|
309
|
+
* panel -- que lee la config ya re-scopeada -- mostraba la del nuevo, y
|
|
310
|
+
* solo se enderezaba al tocar Plan/Console a mano. */
|
|
311
|
+
async function applyProviderFromBrainConfig() {
|
|
312
|
+
if (providerPinned || opts.claude)
|
|
313
|
+
return false;
|
|
314
|
+
const target = (await providerFromBrainConfig()) ?? 'anthropic-api';
|
|
315
|
+
if (target === activeChatProvider)
|
|
316
|
+
return false;
|
|
317
|
+
claude = await buildClaudeClient(target);
|
|
318
|
+
activeChatProvider = target;
|
|
319
|
+
try {
|
|
320
|
+
console.error('[brain] provider del proyecto activo -> ' + target);
|
|
321
|
+
}
|
|
322
|
+
catch { /* */ }
|
|
323
|
+
return true;
|
|
324
|
+
}
|
|
259
325
|
const voice = opts.voice ?? new VoiceRouter({
|
|
260
326
|
configDir: configDir(),
|
|
261
327
|
registry: buildDefaultRegistry(),
|
|
@@ -289,16 +355,6 @@ export async function startChatServer(opts) {
|
|
|
289
355
|
* handlers (que leen de `session`) pasan a apuntar al nuevo root
|
|
290
356
|
* sin reiniciar el panel. */
|
|
291
357
|
const session = { projectRoot: opts.projectRoot, projectName, projectSlug };
|
|
292
|
-
/* Cerebro por instancia (Pablo, 2026-09-30). Habia una sola config para
|
|
293
|
-
* todas: cambiar el cerebro en un `yf chat` lo cambiaba en todos. Este
|
|
294
|
-
* proceso queda atado al cerebro de SU proyecto -- lee el del proyecto si
|
|
295
|
-
* existe y cae al global si no, asi que nada cambia hasta que alguien
|
|
296
|
-
* elige uno aca, y ahi el cambio se queda aca. */
|
|
297
|
-
try {
|
|
298
|
-
const { setBrainConfigScope } = await import('../core/brain_config.js');
|
|
299
|
-
setBrainConfigScope(projectSlug);
|
|
300
|
-
}
|
|
301
|
-
catch { /* sin scope se sigue usando el global, como antes */ }
|
|
302
358
|
/* Project registry (task #33) -- record the project we just opened in
|
|
303
359
|
* ~/.yujin-forge/projects.json + mark it active, so the project
|
|
304
360
|
* selector (panel + mobile) always lists at least the current one.
|
|
@@ -344,6 +400,15 @@ export async function startChatServer(opts) {
|
|
|
344
400
|
setBrainConfigScope(session.projectSlug);
|
|
345
401
|
}
|
|
346
402
|
catch { /* best-effort */ }
|
|
403
|
+
/* ...y con el scope nuevo, la modalidad (Plan/Console) del proyecto
|
|
404
|
+
* nuevo. Antes se quedaba la del anterior hasta tocarla a mano. */
|
|
405
|
+
try {
|
|
406
|
+
if (await applyProviderFromBrainConfig()) {
|
|
407
|
+
chatLog('Cerebro de este proyecto: '
|
|
408
|
+
+ (activeChatProvider === 'claude-code-cli' ? 'Plan (suscripcion)' : 'Console (API)') + '.');
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
catch { /* best-effort */ }
|
|
347
412
|
/* keep the registry in sync after a hot switch (task #33) */
|
|
348
413
|
try {
|
|
349
414
|
await upsertProject({ slug: session.projectSlug, path: abs });
|
|
@@ -492,6 +557,16 @@ export async function startChatServer(opts) {
|
|
|
492
557
|
};
|
|
493
558
|
tryListen(opts.port);
|
|
494
559
|
});
|
|
560
|
+
/* El puerto REAL, no el pedido (2026-10-03). El retry de EADDRINUSE ya
|
|
561
|
+
* reescribia opts.port, pero un port:0 (liga uno efimero) no pasa por ahi:
|
|
562
|
+
* opts.port se quedaba en 0 y entonces la url, el lock de instancia y el
|
|
563
|
+
* panelBridge del subproceso apuntaban a un puerto que no existe. */
|
|
564
|
+
{
|
|
565
|
+
const addr = server.address();
|
|
566
|
+
if (addr && typeof addr === 'object' && typeof addr.port === 'number' && addr.port > 0) {
|
|
567
|
+
opts.port = addr.port;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
495
570
|
/* Port-race fix (2026-09-01). The eager `claude` client above was built
|
|
496
571
|
* BEFORE the EADDRINUSE retry could finalize opts.port. The CLI client
|
|
497
572
|
* FREEZES panelBridge.port at construction, so when two instances race for
|
|
@@ -605,6 +680,7 @@ export async function startChatServer(opts) {
|
|
|
605
680
|
port: opts.port,
|
|
606
681
|
store,
|
|
607
682
|
bridge: bridgeHandle,
|
|
683
|
+
reanchor,
|
|
608
684
|
close: () => new Promise((resolve) => {
|
|
609
685
|
/* alpha.59w -- stop the component watcher on shutdown so
|
|
610
686
|
* vitest does not hang on lingering fs watchers. */
|