@gobing-ai/ts-ai-runner 0.4.27 → 0.4.30
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/README.md +5 -1
- package/dist/agents/auth-shims.d.ts.map +1 -1
- package/dist/agents/auth-shims.js +26 -2
- package/dist/ai-runner.d.ts.map +1 -1
- package/dist/ai-runner.js +2 -0
- package/dist/events.d.ts +6 -0
- package/dist/events.d.ts.map +1 -1
- package/dist/identity.d.ts +17 -3
- package/dist/identity.d.ts.map +1 -1
- package/dist/identity.js +33 -6
- package/dist/message-store.d.ts +3 -1
- package/dist/message-store.d.ts.map +1 -1
- package/dist/team-orchestrator.d.ts.map +1 -1
- package/dist/team-orchestrator.js +24 -10
- package/package.json +4 -4
- package/src/agents/auth-shims.ts +21 -2
- package/src/ai-runner.ts +2 -0
- package/src/events.ts +11 -3
- package/src/identity.ts +44 -6
- package/src/message-store.ts +1 -1
- package/src/team-orchestrator.ts +21 -9
package/README.md
CHANGED
|
@@ -287,10 +287,14 @@ Use `getGitContext()` to auto-detect the current branch and dirty state:
|
|
|
287
287
|
```ts
|
|
288
288
|
import { getGitContext } from '@gobing-ai/ts-ai-runner';
|
|
289
289
|
|
|
290
|
-
const gitBlock = getGitContext('/workspace/spur');
|
|
290
|
+
const gitBlock = await getGitContext('/workspace/spur');
|
|
291
291
|
// "Git context:\nbranch: feat/team-mode\ndirty: 3 files"
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
+
> `getGitContext` is async (returns `Promise<string | null>`) and defaults to the canonical
|
|
295
|
+
> `ProcessExecutor` from `@gobing-ai/ts-runtime`. A deprecated sync escape hatch `getGitContextSync`
|
|
296
|
+
> remains for one release for sync callers.
|
|
297
|
+
|
|
294
298
|
## Session Affinity (run-scoped sessions)
|
|
295
299
|
|
|
296
300
|
`PromptOptions` carries two additive fields for pinning or isolating sessions:
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"auth-shims.d.ts","sourceRoot":"","sources":["../../src/agents/auth-shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAA2B,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EAAmC,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAExE,qDAAqD;AACrD,MAAM,WAAW,WAAW;IACxB,0CAA0C;IAC1C,MAAM,EAAE,QAAQ,CAAC;IACjB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,0EAA0E;IAC1E,UAAU,EAAE,UAAU,CAAC;IACvB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAiB5F;
|
|
1
|
+
{"version":3,"file":"auth-shims.d.ts","sourceRoot":"","sources":["../../src/agents/auth-shims.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,UAAU,EAA2B,MAAM,uBAAuB,CAAC;AACjF,OAAO,KAAK,EAAmC,QAAQ,EAAE,MAAM,cAAc,CAAC;AAC9E,OAAO,EAAE,KAAK,SAAS,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvD;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,SAAS,GAAG,eAAe,GAAG,iBAAiB,GAAG,SAAS,CAAC;AAExE,qDAAqD;AACrD,MAAM,WAAW,WAAW;IACxB,0CAA0C;IAC1C,MAAM,EAAE,QAAQ,CAAC;IACjB,6EAA6E;IAC7E,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;IACzC,0EAA0E;IAC1E,UAAU,EAAE,UAAU,CAAC;IACvB,0CAA0C;IAC1C,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AA6CD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAsB,eAAe,CAAC,KAAK,EAAE,SAAS,EAAE,GAAG,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAiB5F;AAkFD,OAAO,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -97,14 +97,38 @@ async function checkGrokAuth(fs, home, env) {
|
|
|
97
97
|
return 'unknown';
|
|
98
98
|
}
|
|
99
99
|
async function geminiSettingsContainCredentials(fs, home) {
|
|
100
|
+
let content;
|
|
100
101
|
try {
|
|
101
|
-
|
|
102
|
-
return /auth|token|key/i.test(content) ? 'authenticated' : 'unauthenticated';
|
|
102
|
+
content = await fs.readFile(joinPath(home, '.gemini', 'settings.json'));
|
|
103
103
|
}
|
|
104
104
|
catch {
|
|
105
105
|
// Missing or unreadable settings — auth state genuinely unknown.
|
|
106
106
|
return 'unknown';
|
|
107
107
|
}
|
|
108
|
+
// Credential-shaped fields only (task 0060 R14): a loose /auth|token|key/i substring
|
|
109
|
+
// match would mark a UI banner flag ({"ui":{"showAuthBanner":true}}) or an empty
|
|
110
|
+
// apiKey as authenticated.
|
|
111
|
+
let settings;
|
|
112
|
+
try {
|
|
113
|
+
settings = JSON.parse(content);
|
|
114
|
+
}
|
|
115
|
+
catch {
|
|
116
|
+
return 'unauthenticated'; // Not JSON — no usable credentials.
|
|
117
|
+
}
|
|
118
|
+
if (typeof settings !== 'object' || settings === null)
|
|
119
|
+
return 'unauthenticated';
|
|
120
|
+
const record = settings;
|
|
121
|
+
if (typeof record.apiKey === 'string' && record.apiKey.length > 0)
|
|
122
|
+
return 'authenticated';
|
|
123
|
+
if (typeof record.accessToken === 'string' && record.accessToken.length > 0)
|
|
124
|
+
return 'authenticated';
|
|
125
|
+
const tokens = record.tokens;
|
|
126
|
+
if (tokens !== null && typeof tokens === 'object') {
|
|
127
|
+
const accessToken = tokens.access_token;
|
|
128
|
+
if (typeof accessToken === 'string' && accessToken.length > 0)
|
|
129
|
+
return 'authenticated';
|
|
130
|
+
}
|
|
131
|
+
return 'unauthenticated';
|
|
108
132
|
}
|
|
109
133
|
async function probeAuthOutput(runner, agent, timeout) {
|
|
110
134
|
const options = { timeout };
|
package/dist/ai-runner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ai-runner.d.ts","sourceRoot":"","sources":["../src/ai-runner.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"ai-runner.d.ts","sourceRoot":"","sources":["../src/ai-runner.ts"],"names":[],"mappings":"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"}
|
package/dist/ai-runner.js
CHANGED
|
@@ -118,6 +118,7 @@ export class AiRunner {
|
|
|
118
118
|
operation,
|
|
119
119
|
label,
|
|
120
120
|
...(options.correlation !== undefined ? { correlation: options.correlation } : {}),
|
|
121
|
+
severity: 'info',
|
|
121
122
|
});
|
|
122
123
|
const correlationEnv = options.correlation === undefined ? undefined : buildCorrelationEnv(options.correlation);
|
|
123
124
|
const result = await this.processExecutor.run({
|
|
@@ -147,6 +148,7 @@ export class AiRunner {
|
|
|
147
148
|
...(result.signal !== undefined ? { signal: result.signal } : {}),
|
|
148
149
|
durationMs: result.durationMs,
|
|
149
150
|
...(options.correlation !== undefined ? { correlation: options.correlation } : {}),
|
|
151
|
+
severity: result.exitCode === 0 || result.exitCode === null ? 'info' : 'error',
|
|
150
152
|
});
|
|
151
153
|
return {
|
|
152
154
|
exitCode: result.exitCode,
|
package/dist/events.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EventSeverity } from '@gobing-ai/ts-infra';
|
|
1
2
|
import type { ProcessEvents } from '@gobing-ai/ts-runtime';
|
|
2
3
|
import type { AgentRunCorrelation } from './ai-runner';
|
|
3
4
|
/** Typed event map for agent-runner observability. All events prefixed `agent.`. */
|
|
@@ -8,6 +9,7 @@ export type AgentEvents = {
|
|
|
8
9
|
operation: string;
|
|
9
10
|
label: string;
|
|
10
11
|
correlation?: AgentRunCorrelation;
|
|
12
|
+
severity: EventSeverity;
|
|
11
13
|
}) => void;
|
|
12
14
|
/** Emitted after an agent CLI invocation exits. */
|
|
13
15
|
'agent.invoke.exit': (data: {
|
|
@@ -18,22 +20,26 @@ export type AgentEvents = {
|
|
|
18
20
|
signal?: string;
|
|
19
21
|
durationMs: number;
|
|
20
22
|
correlation?: AgentRunCorrelation;
|
|
23
|
+
severity: EventSeverity;
|
|
21
24
|
}) => void;
|
|
22
25
|
/** Emitted when a long-running team agent process starts. */
|
|
23
26
|
'agent.started': (data: {
|
|
24
27
|
agentId: string;
|
|
25
28
|
agentType: string;
|
|
26
29
|
pid: number | null;
|
|
30
|
+
severity: EventSeverity;
|
|
27
31
|
}) => void;
|
|
28
32
|
/** Emitted when a long-running team agent process stops. */
|
|
29
33
|
'agent.stopped': (data: {
|
|
30
34
|
agentId: string;
|
|
31
35
|
exitCode: number | null;
|
|
36
|
+
severity: EventSeverity;
|
|
32
37
|
}) => void;
|
|
33
38
|
/** Emitted when a message is sent to a team agent process. */
|
|
34
39
|
'agent.message.sent': (data: {
|
|
35
40
|
agentId: string;
|
|
36
41
|
ok: boolean;
|
|
42
|
+
severity: EventSeverity;
|
|
37
43
|
}) => void;
|
|
38
44
|
};
|
|
39
45
|
/** Event map for process-level observability emitted by AiRunner-owned executors. */
|
package/dist/events.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG;IACtB,iEAAiE;IACjE,oBAAoB,EAAE,CAAC,IAAI,EAAE;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../src/events.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAEvD,oFAAoF;AACpF,MAAM,MAAM,WAAW,GAAG;IACtB,iEAAiE;IACjE,oBAAoB,EAAE,CAAC,IAAI,EAAE;QACzB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,WAAW,CAAC,EAAE,mBAAmB,CAAC;QAClC,QAAQ,EAAE,aAAa,CAAC;KAC3B,KAAK,IAAI,CAAC;IACX,mDAAmD;IACnD,mBAAmB,EAAE,CAAC,IAAI,EAAE;QACxB,KAAK,EAAE,MAAM,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;QAClB,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QACxB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,UAAU,EAAE,MAAM,CAAC;QACnB,WAAW,CAAC,EAAE,mBAAmB,CAAC;QAClC,QAAQ,EAAE,aAAa,CAAC;KAC3B,KAAK,IAAI,CAAC;IACX,6DAA6D;IAC7D,eAAe,EAAE,CAAC,IAAI,EAAE;QACpB,OAAO,EAAE,MAAM,CAAC;QAChB,SAAS,EAAE,MAAM,CAAC;QAClB,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;QACnB,QAAQ,EAAE,aAAa,CAAC;KAC3B,KAAK,IAAI,CAAC;IACX,4DAA4D;IAC5D,eAAe,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;QAAC,QAAQ,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,CAAC;IACvG,8DAA8D;IAC9D,oBAAoB,EAAE,CAAC,IAAI,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,aAAa,CAAA;KAAE,KAAK,IAAI,CAAC;CACnG,CAAC;AAEF,qFAAqF;AACrF,MAAM,MAAM,qBAAqB,GAAG,aAAa,CAAC"}
|
package/dist/identity.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type SyncProcessExecutor } from '@gobing-ai/ts-runtime';
|
|
1
|
+
import { type ProcessExecutor, type SyncProcessExecutor } from '@gobing-ai/ts-runtime';
|
|
2
2
|
/** Context used to construct the identity preamble injected into agent prompts. */
|
|
3
3
|
export interface IdentityContext {
|
|
4
4
|
agentId: string;
|
|
@@ -19,6 +19,20 @@ export interface IdentityContext {
|
|
|
19
19
|
}
|
|
20
20
|
/** Build a human-readable identity preamble string that describes the agent, its task, peers, guardrails, and git context. */
|
|
21
21
|
export declare function buildIdentityPreamble(ctx: IdentityContext): string;
|
|
22
|
-
/**
|
|
23
|
-
|
|
22
|
+
/**
|
|
23
|
+
* Query git for the current branch name and dirty file count in `workspacePath`.
|
|
24
|
+
*
|
|
25
|
+
* Returns a pre-formatted "Git context" block, or `null` if git is unavailable or the directory is
|
|
26
|
+
* not a repo. Uses the canonical async {@link ProcessExecutor} (defaulting to
|
|
27
|
+
* `nodeBunFactory.createProcessExecutor()`) per ADR-023 A2 — never the deprecated
|
|
28
|
+
* {@link BunSyncProcessExecutor}.
|
|
29
|
+
*/
|
|
30
|
+
export declare function getGitContext(workspacePath: string, executor?: ProcessExecutor): Promise<string | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Query git for the current branch name and dirty file count synchronously.
|
|
33
|
+
*
|
|
34
|
+
* @deprecated Use the async {@link getGitContext} instead. Kept for one release for sync callers.
|
|
35
|
+
* Defaults to the deprecated {@link BunSyncProcessExecutor}; new code must not rely on it.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getGitContextSync(workspacePath: string, executor?: SyncProcessExecutor): string | null;
|
|
24
38
|
//# sourceMappingURL=identity.d.ts.map
|
package/dist/identity.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"identity.d.ts","sourceRoot":"","sources":["../src/identity.ts"],"names":[],"mappings":"AAAA,OAAO,EAGH,KAAK,eAAe,EACpB,KAAK,mBAAmB,EAC3B,MAAM,uBAAuB,CAAC;AAE/B,mFAAmF;AACnF,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC9D,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;CACzB;AAED,8HAA8H;AAC9H,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,eAAe,GAAG,MAAM,CA8ClE;AAED;;;;;;;GAOG;AACH,wBAAsB,aAAa,CAC/B,aAAa,EAAE,MAAM,EACrB,QAAQ,GAAE,eAAwD,GACnE,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CASxB;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC7B,aAAa,EAAE,MAAM,EACrB,QAAQ,GAAE,mBAAkD,GAC7D,MAAM,GAAG,IAAI,CASf"}
|
package/dist/identity.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BunSyncProcessExecutor } from '@gobing-ai/ts-runtime';
|
|
1
|
+
import { BunSyncProcessExecutor, nodeBunFactory, } from '@gobing-ai/ts-runtime';
|
|
2
2
|
/** Build a human-readable identity preamble string that describes the agent, its task, peers, guardrails, and git context. */
|
|
3
3
|
export function buildIdentityPreamble(ctx) {
|
|
4
4
|
const sections = [
|
|
@@ -32,16 +32,43 @@ export function buildIdentityPreamble(ctx) {
|
|
|
32
32
|
}
|
|
33
33
|
return `${sections.join('\n\n')}\n`;
|
|
34
34
|
}
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
/**
|
|
36
|
+
* Query git for the current branch name and dirty file count in `workspacePath`.
|
|
37
|
+
*
|
|
38
|
+
* Returns a pre-formatted "Git context" block, or `null` if git is unavailable or the directory is
|
|
39
|
+
* not a repo. Uses the canonical async {@link ProcessExecutor} (defaulting to
|
|
40
|
+
* `nodeBunFactory.createProcessExecutor()`) per ADR-023 A2 — never the deprecated
|
|
41
|
+
* {@link BunSyncProcessExecutor}.
|
|
42
|
+
*/
|
|
43
|
+
export async function getGitContext(workspacePath, executor = nodeBunFactory.createProcessExecutor()) {
|
|
44
|
+
const branch = await runGit(executor, ['-C', workspacePath, 'branch', '--show-current']);
|
|
38
45
|
if (branch === null || branch === '')
|
|
39
46
|
return null;
|
|
40
|
-
const status = runGit(executor, ['-C', workspacePath, 'status', '--porcelain']);
|
|
47
|
+
const status = await runGit(executor, ['-C', workspacePath, 'status', '--porcelain']);
|
|
41
48
|
const dirtyCount = status === null || status === '' ? 0 : status.split('\n').filter(Boolean).length;
|
|
42
49
|
return ['Git context:', `branch: ${branch}`, `dirty: ${dirtyCount === 0 ? 'false' : `${dirtyCount} files`}`].join('\n');
|
|
43
50
|
}
|
|
44
|
-
|
|
51
|
+
/**
|
|
52
|
+
* Query git for the current branch name and dirty file count synchronously.
|
|
53
|
+
*
|
|
54
|
+
* @deprecated Use the async {@link getGitContext} instead. Kept for one release for sync callers.
|
|
55
|
+
* Defaults to the deprecated {@link BunSyncProcessExecutor}; new code must not rely on it.
|
|
56
|
+
*/
|
|
57
|
+
export function getGitContextSync(workspacePath, executor = new BunSyncProcessExecutor()) {
|
|
58
|
+
const branch = runGitSync(executor, ['-C', workspacePath, 'branch', '--show-current']);
|
|
59
|
+
if (branch === null || branch === '')
|
|
60
|
+
return null;
|
|
61
|
+
const status = runGitSync(executor, ['-C', workspacePath, 'status', '--porcelain']);
|
|
62
|
+
const dirtyCount = status === null || status === '' ? 0 : status.split('\n').filter(Boolean).length;
|
|
63
|
+
return ['Git context:', `branch: ${branch}`, `dirty: ${dirtyCount === 0 ? 'false' : `${dirtyCount} files`}`].join('\n');
|
|
64
|
+
}
|
|
65
|
+
async function runGit(executor, args) {
|
|
66
|
+
const result = await executor.run({ command: 'git', args, rejectOnError: false, forceBuffered: true });
|
|
67
|
+
if (result.exitCode !== 0)
|
|
68
|
+
return null;
|
|
69
|
+
return result.stdout.trim();
|
|
70
|
+
}
|
|
71
|
+
function runGitSync(executor, args) {
|
|
45
72
|
const result = executor.runSync({ command: 'git', args, rejectOnError: false, forceBuffered: true });
|
|
46
73
|
if (result.exitCode !== 0)
|
|
47
74
|
return null;
|
package/dist/message-store.d.ts
CHANGED
|
@@ -23,7 +23,9 @@ export interface DrainedMessage {
|
|
|
23
23
|
*/
|
|
24
24
|
export interface MessageStore {
|
|
25
25
|
enqueue(fromId: string | null, toId: string, body: string, inReplyTo?: string): Promise<string>;
|
|
26
|
-
drainPending(toId: string
|
|
26
|
+
drainPending(toId: string, options?: {
|
|
27
|
+
limit?: number;
|
|
28
|
+
}): Promise<DrainedMessage[]>;
|
|
27
29
|
markDelivered(msgId: string): Promise<void>;
|
|
28
30
|
markFailed(msgId: string, error: string): Promise<void>;
|
|
29
31
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-store.d.ts","sourceRoot":"","sources":["../src/message-store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChG,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;
|
|
1
|
+
{"version":3,"file":"message-store.d.ts","sourceRoot":"","sources":["../src/message-store.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACzB;AAED;;;;;GAKG;AACH,MAAM,WAAW,YAAY;IACzB,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IAChG,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC,CAAC;IACpF,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC5C,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3D"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"team-orchestrator.d.ts","sourceRoot":"","sources":["../src/team-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC;AAE5G,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACpC,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;CAC/C;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAOrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAP1B,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;gBAG1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,YAAY,EACpC,OAAO,GAAE,uBAA4B;IAUnC,SAAS,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAKjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAKnD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"team-orchestrator.d.ts","sourceRoot":"","sources":["../src/team-orchestrator.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,kBAAkB,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAC;AACxE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAI9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAC5C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAExD,KAAK,mBAAmB,GAAG,CAAC,OAAO,EAAE,qBAAqB,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAC,CAAC,KAAK,gBAAgB,CAAC;AAE5G,oDAAoD;AACpD,MAAM,WAAW,uBAAuB;IACpC,cAAc,CAAC,EAAE,mBAAmB,CAAC;IACrC,MAAM,CAAC,EAAE,QAAQ,CAAC,WAAW,CAAC,CAAC;IAC/B;;;;OAIG;IACH,YAAY,CAAC,EAAE,QAAQ,CAAC,kBAAkB,CAAC,CAAC;CAC/C;AAED;;;GAGG;AACH,qBAAa,gBAAgB;IAOrB,OAAO,CAAC,QAAQ,CAAC,SAAS;IAC1B,OAAO,CAAC,QAAQ,CAAC,KAAK;IAP1B,OAAO,CAAC,KAAK,CAAmB;IAChC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAuC;IAC/D,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAsB;IACrD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAwB;gBAG1B,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,YAAY,EACpC,OAAO,GAAE,uBAA4B;IAUnC,SAAS,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;IAKjC,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAKnD,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAkCjD,SAAS,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAapC,YAAY,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAKnD,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAQzG,gBAAgB,IAAI,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC;IAI3C,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,GAAG,SAAS,GAAG,SAAS,CAAC;IAMlF,YAAY,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAKzE,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAI9B,EAAE,CAAC,CAAC,SAAS,MAAM,WAAW,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI;YAKjE,WAAW;IAMzB,OAAO,CAAC,gBAAgB;YAMV,qBAAqB;YAIrB,UAAU;CAmB3B"}
|
|
@@ -59,6 +59,7 @@ export class TeamOrchestrator {
|
|
|
59
59
|
agentId: spec.id,
|
|
60
60
|
agentType: spec.type,
|
|
61
61
|
pid: process.getPid(),
|
|
62
|
+
severity: 'info',
|
|
62
63
|
});
|
|
63
64
|
return process;
|
|
64
65
|
}
|
|
@@ -68,7 +69,12 @@ export class TeamOrchestrator {
|
|
|
68
69
|
return;
|
|
69
70
|
await process.stop();
|
|
70
71
|
this.running.delete(id);
|
|
71
|
-
|
|
72
|
+
const exitCode = process.getExitCode();
|
|
73
|
+
void this.events.emit('agent.stopped', {
|
|
74
|
+
agentId: id,
|
|
75
|
+
exitCode,
|
|
76
|
+
severity: exitCode === 0 || exitCode === null ? 'info' : 'warning',
|
|
77
|
+
});
|
|
72
78
|
}
|
|
73
79
|
async restartAgent(id) {
|
|
74
80
|
await this.stopAgent(id);
|
|
@@ -78,7 +84,7 @@ export class TeamOrchestrator {
|
|
|
78
84
|
const msgId = await this.inbox.enqueue(fromId, toId, body, inReplyTo);
|
|
79
85
|
const process = this.running.get(toId);
|
|
80
86
|
const ok = process !== undefined ? await this.flushInbox(process, 'live stdin injection failed') : false;
|
|
81
|
-
void this.events.emit('agent.message.sent', { agentId: toId, ok });
|
|
87
|
+
void this.events.emit('agent.message.sent', { agentId: toId, ok, severity: ok ? 'info' : 'warning' });
|
|
82
88
|
return msgId;
|
|
83
89
|
}
|
|
84
90
|
getRunningAgents() {
|
|
@@ -118,16 +124,24 @@ export class TeamOrchestrator {
|
|
|
118
124
|
return this.flushInbox(process, 'startup stdin injection failed');
|
|
119
125
|
}
|
|
120
126
|
async flushInbox(process, failLabel) {
|
|
121
|
-
|
|
127
|
+
// Drain in pages (default 100 per drainPending — task 0060 F10) until a short page,
|
|
128
|
+
// so a backed-up inbox is fully flushed without one giant claim.
|
|
122
129
|
let ok = true;
|
|
123
|
-
for (
|
|
124
|
-
const
|
|
125
|
-
if (
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
+
for (;;) {
|
|
131
|
+
const messages = await this.inbox.drainPending(process.agentId);
|
|
132
|
+
if (messages.length === 0)
|
|
133
|
+
break;
|
|
134
|
+
for (const message of messages) {
|
|
135
|
+
const result = await process.send(formatMessage(message));
|
|
136
|
+
if (result.ok)
|
|
137
|
+
await this.inbox.markDelivered(message.id);
|
|
138
|
+
else {
|
|
139
|
+
ok = false;
|
|
140
|
+
await this.inbox.markFailed(message.id, failLabel);
|
|
141
|
+
}
|
|
130
142
|
}
|
|
143
|
+
if (messages.length < 100)
|
|
144
|
+
break;
|
|
131
145
|
}
|
|
132
146
|
return ok;
|
|
133
147
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@gobing-ai/ts-ai-runner",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.30",
|
|
4
4
|
"description": "@gobing-ai/ts-ai-runner — Coding-agent shims, detection, doctor checks, and prompt execution.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"typescript",
|
|
@@ -47,12 +47,12 @@
|
|
|
47
47
|
"release": "echo 'Manual publish is disabled. Releases go through GitHub Actions via Trusted Publishing — push a tag: git tag @gobing-ai/ts-ai-runner-v<version> && git push --tags' && exit 1"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"@gobing-ai/ts-infra": "^0.4.
|
|
51
|
-
"@gobing-ai/ts-runtime": "^0.4.
|
|
50
|
+
"@gobing-ai/ts-infra": "^0.4.30",
|
|
51
|
+
"@gobing-ai/ts-runtime": "^0.4.30"
|
|
52
52
|
},
|
|
53
53
|
"devDependencies": {
|
|
54
54
|
"@types/bun": "1.3.14",
|
|
55
|
-
"@gobing-ai/ts-db": "^0.4.
|
|
55
|
+
"@gobing-ai/ts-db": "^0.4.30"
|
|
56
56
|
},
|
|
57
57
|
"publishConfig": {
|
|
58
58
|
"access": "public"
|
package/src/agents/auth-shims.ts
CHANGED
|
@@ -136,13 +136,32 @@ async function checkGrokAuth(
|
|
|
136
136
|
}
|
|
137
137
|
|
|
138
138
|
async function geminiSettingsContainCredentials(fs: FileSystem, home: string): Promise<AuthState> {
|
|
139
|
+
let content: string;
|
|
139
140
|
try {
|
|
140
|
-
|
|
141
|
-
return /auth|token|key/i.test(content) ? 'authenticated' : 'unauthenticated';
|
|
141
|
+
content = await fs.readFile(joinPath(home, '.gemini', 'settings.json'));
|
|
142
142
|
} catch {
|
|
143
143
|
// Missing or unreadable settings — auth state genuinely unknown.
|
|
144
144
|
return 'unknown';
|
|
145
145
|
}
|
|
146
|
+
// Credential-shaped fields only (task 0060 R14): a loose /auth|token|key/i substring
|
|
147
|
+
// match would mark a UI banner flag ({"ui":{"showAuthBanner":true}}) or an empty
|
|
148
|
+
// apiKey as authenticated.
|
|
149
|
+
let settings: unknown;
|
|
150
|
+
try {
|
|
151
|
+
settings = JSON.parse(content);
|
|
152
|
+
} catch {
|
|
153
|
+
return 'unauthenticated'; // Not JSON — no usable credentials.
|
|
154
|
+
}
|
|
155
|
+
if (typeof settings !== 'object' || settings === null) return 'unauthenticated';
|
|
156
|
+
const record = settings as Record<string, unknown>;
|
|
157
|
+
if (typeof record.apiKey === 'string' && record.apiKey.length > 0) return 'authenticated';
|
|
158
|
+
if (typeof record.accessToken === 'string' && record.accessToken.length > 0) return 'authenticated';
|
|
159
|
+
const tokens = record.tokens;
|
|
160
|
+
if (tokens !== null && typeof tokens === 'object') {
|
|
161
|
+
const accessToken = (tokens as Record<string, unknown>).access_token;
|
|
162
|
+
if (typeof accessToken === 'string' && accessToken.length > 0) return 'authenticated';
|
|
163
|
+
}
|
|
164
|
+
return 'unauthenticated';
|
|
146
165
|
}
|
|
147
166
|
|
|
148
167
|
async function probeAuthOutput(runner: AiRunner, agent: AgentName, timeout: number): Promise<AuthState> {
|
package/src/ai-runner.ts
CHANGED
|
@@ -212,6 +212,7 @@ export class AiRunner {
|
|
|
212
212
|
operation,
|
|
213
213
|
label,
|
|
214
214
|
...(options.correlation !== undefined ? { correlation: options.correlation } : {}),
|
|
215
|
+
severity: 'info',
|
|
215
216
|
});
|
|
216
217
|
const correlationEnv = options.correlation === undefined ? undefined : buildCorrelationEnv(options.correlation);
|
|
217
218
|
const result: ProcessResult = await this.processExecutor.run({
|
|
@@ -241,6 +242,7 @@ export class AiRunner {
|
|
|
241
242
|
...(result.signal !== undefined ? { signal: result.signal } : {}),
|
|
242
243
|
durationMs: result.durationMs,
|
|
243
244
|
...(options.correlation !== undefined ? { correlation: options.correlation } : {}),
|
|
245
|
+
severity: result.exitCode === 0 || result.exitCode === null ? 'info' : 'error',
|
|
244
246
|
});
|
|
245
247
|
return {
|
|
246
248
|
exitCode: result.exitCode,
|
package/src/events.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { EventSeverity } from '@gobing-ai/ts-infra';
|
|
1
2
|
import type { ProcessEvents } from '@gobing-ai/ts-runtime';
|
|
2
3
|
import type { AgentRunCorrelation } from './ai-runner';
|
|
3
4
|
|
|
@@ -9,6 +10,7 @@ export type AgentEvents = {
|
|
|
9
10
|
operation: string;
|
|
10
11
|
label: string;
|
|
11
12
|
correlation?: AgentRunCorrelation;
|
|
13
|
+
severity: EventSeverity;
|
|
12
14
|
}) => void;
|
|
13
15
|
/** Emitted after an agent CLI invocation exits. */
|
|
14
16
|
'agent.invoke.exit': (data: {
|
|
@@ -19,13 +21,19 @@ export type AgentEvents = {
|
|
|
19
21
|
signal?: string;
|
|
20
22
|
durationMs: number;
|
|
21
23
|
correlation?: AgentRunCorrelation;
|
|
24
|
+
severity: EventSeverity;
|
|
22
25
|
}) => void;
|
|
23
26
|
/** Emitted when a long-running team agent process starts. */
|
|
24
|
-
'agent.started': (data: {
|
|
27
|
+
'agent.started': (data: {
|
|
28
|
+
agentId: string;
|
|
29
|
+
agentType: string;
|
|
30
|
+
pid: number | null;
|
|
31
|
+
severity: EventSeverity;
|
|
32
|
+
}) => void;
|
|
25
33
|
/** Emitted when a long-running team agent process stops. */
|
|
26
|
-
'agent.stopped': (data: { agentId: string; exitCode: number | null }) => void;
|
|
34
|
+
'agent.stopped': (data: { agentId: string; exitCode: number | null; severity: EventSeverity }) => void;
|
|
27
35
|
/** Emitted when a message is sent to a team agent process. */
|
|
28
|
-
'agent.message.sent': (data: { agentId: string; ok: boolean }) => void;
|
|
36
|
+
'agent.message.sent': (data: { agentId: string; ok: boolean; severity: EventSeverity }) => void;
|
|
29
37
|
};
|
|
30
38
|
|
|
31
39
|
/** Event map for process-level observability emitted by AiRunner-owned executors. */
|
package/src/identity.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
BunSyncProcessExecutor,
|
|
3
|
+
nodeBunFactory,
|
|
4
|
+
type ProcessExecutor,
|
|
5
|
+
type SyncProcessExecutor,
|
|
6
|
+
} from '@gobing-ai/ts-runtime';
|
|
2
7
|
|
|
3
8
|
/** Context used to construct the identity preamble injected into agent prompts. */
|
|
4
9
|
export interface IdentityContext {
|
|
@@ -64,22 +69,55 @@ export function buildIdentityPreamble(ctx: IdentityContext): string {
|
|
|
64
69
|
return `${sections.join('\n\n')}\n`;
|
|
65
70
|
}
|
|
66
71
|
|
|
67
|
-
/**
|
|
68
|
-
|
|
72
|
+
/**
|
|
73
|
+
* Query git for the current branch name and dirty file count in `workspacePath`.
|
|
74
|
+
*
|
|
75
|
+
* Returns a pre-formatted "Git context" block, or `null` if git is unavailable or the directory is
|
|
76
|
+
* not a repo. Uses the canonical async {@link ProcessExecutor} (defaulting to
|
|
77
|
+
* `nodeBunFactory.createProcessExecutor()`) per ADR-023 A2 — never the deprecated
|
|
78
|
+
* {@link BunSyncProcessExecutor}.
|
|
79
|
+
*/
|
|
80
|
+
export async function getGitContext(
|
|
81
|
+
workspacePath: string,
|
|
82
|
+
executor: ProcessExecutor = nodeBunFactory.createProcessExecutor(),
|
|
83
|
+
): Promise<string | null> {
|
|
84
|
+
const branch = await runGit(executor, ['-C', workspacePath, 'branch', '--show-current']);
|
|
85
|
+
if (branch === null || branch === '') return null;
|
|
86
|
+
|
|
87
|
+
const status = await runGit(executor, ['-C', workspacePath, 'status', '--porcelain']);
|
|
88
|
+
const dirtyCount = status === null || status === '' ? 0 : status.split('\n').filter(Boolean).length;
|
|
89
|
+
return ['Git context:', `branch: ${branch}`, `dirty: ${dirtyCount === 0 ? 'false' : `${dirtyCount} files`}`].join(
|
|
90
|
+
'\n',
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Query git for the current branch name and dirty file count synchronously.
|
|
96
|
+
*
|
|
97
|
+
* @deprecated Use the async {@link getGitContext} instead. Kept for one release for sync callers.
|
|
98
|
+
* Defaults to the deprecated {@link BunSyncProcessExecutor}; new code must not rely on it.
|
|
99
|
+
*/
|
|
100
|
+
export function getGitContextSync(
|
|
69
101
|
workspacePath: string,
|
|
70
102
|
executor: SyncProcessExecutor = new BunSyncProcessExecutor(),
|
|
71
103
|
): string | null {
|
|
72
|
-
const branch =
|
|
104
|
+
const branch = runGitSync(executor, ['-C', workspacePath, 'branch', '--show-current']);
|
|
73
105
|
if (branch === null || branch === '') return null;
|
|
74
106
|
|
|
75
|
-
const status =
|
|
107
|
+
const status = runGitSync(executor, ['-C', workspacePath, 'status', '--porcelain']);
|
|
76
108
|
const dirtyCount = status === null || status === '' ? 0 : status.split('\n').filter(Boolean).length;
|
|
77
109
|
return ['Git context:', `branch: ${branch}`, `dirty: ${dirtyCount === 0 ? 'false' : `${dirtyCount} files`}`].join(
|
|
78
110
|
'\n',
|
|
79
111
|
);
|
|
80
112
|
}
|
|
81
113
|
|
|
82
|
-
function runGit(executor:
|
|
114
|
+
async function runGit(executor: ProcessExecutor, args: string[]): Promise<string | null> {
|
|
115
|
+
const result = await executor.run({ command: 'git', args, rejectOnError: false, forceBuffered: true });
|
|
116
|
+
if (result.exitCode !== 0) return null;
|
|
117
|
+
return result.stdout.trim();
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function runGitSync(executor: SyncProcessExecutor, args: string[]): string | null {
|
|
83
121
|
const result = executor.runSync({ command: 'git', args, rejectOnError: false, forceBuffered: true });
|
|
84
122
|
if (result.exitCode !== 0) return null;
|
|
85
123
|
return result.stdout.trim();
|
package/src/message-store.ts
CHANGED
|
@@ -25,7 +25,7 @@ export interface DrainedMessage {
|
|
|
25
25
|
*/
|
|
26
26
|
export interface MessageStore {
|
|
27
27
|
enqueue(fromId: string | null, toId: string, body: string, inReplyTo?: string): Promise<string>;
|
|
28
|
-
drainPending(toId: string): Promise<DrainedMessage[]>;
|
|
28
|
+
drainPending(toId: string, options?: { limit?: number }): Promise<DrainedMessage[]>;
|
|
29
29
|
markDelivered(msgId: string): Promise<void>;
|
|
30
30
|
markFailed(msgId: string, error: string): Promise<void>;
|
|
31
31
|
}
|
package/src/team-orchestrator.ts
CHANGED
|
@@ -84,6 +84,7 @@ export class TeamOrchestrator {
|
|
|
84
84
|
agentId: spec.id,
|
|
85
85
|
agentType: spec.type,
|
|
86
86
|
pid: process.getPid(),
|
|
87
|
+
severity: 'info',
|
|
87
88
|
});
|
|
88
89
|
return process;
|
|
89
90
|
}
|
|
@@ -93,7 +94,12 @@ export class TeamOrchestrator {
|
|
|
93
94
|
if (process === undefined) return;
|
|
94
95
|
await process.stop();
|
|
95
96
|
this.running.delete(id);
|
|
96
|
-
|
|
97
|
+
const exitCode = process.getExitCode();
|
|
98
|
+
void this.events.emit('agent.stopped', {
|
|
99
|
+
agentId: id,
|
|
100
|
+
exitCode,
|
|
101
|
+
severity: exitCode === 0 || exitCode === null ? 'info' : 'warning',
|
|
102
|
+
});
|
|
97
103
|
}
|
|
98
104
|
|
|
99
105
|
async restartAgent(id: string): Promise<TeamAgentProcess> {
|
|
@@ -105,7 +111,7 @@ export class TeamOrchestrator {
|
|
|
105
111
|
const msgId = await this.inbox.enqueue(fromId, toId, body, inReplyTo);
|
|
106
112
|
const process = this.running.get(toId);
|
|
107
113
|
const ok = process !== undefined ? await this.flushInbox(process, 'live stdin injection failed') : false;
|
|
108
|
-
void this.events.emit('agent.message.sent', { agentId: toId, ok });
|
|
114
|
+
void this.events.emit('agent.message.sent', { agentId: toId, ok, severity: ok ? 'info' : 'warning' });
|
|
109
115
|
return msgId;
|
|
110
116
|
}
|
|
111
117
|
|
|
@@ -150,15 +156,21 @@ export class TeamOrchestrator {
|
|
|
150
156
|
}
|
|
151
157
|
|
|
152
158
|
private async flushInbox(process: TeamAgentProcess, failLabel: string): Promise<boolean> {
|
|
153
|
-
|
|
159
|
+
// Drain in pages (default 100 per drainPending — task 0060 F10) until a short page,
|
|
160
|
+
// so a backed-up inbox is fully flushed without one giant claim.
|
|
154
161
|
let ok = true;
|
|
155
|
-
for (
|
|
156
|
-
const
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
await this.inbox.
|
|
162
|
+
for (;;) {
|
|
163
|
+
const messages = await this.inbox.drainPending(process.agentId);
|
|
164
|
+
if (messages.length === 0) break;
|
|
165
|
+
for (const message of messages) {
|
|
166
|
+
const result = await process.send(formatMessage(message));
|
|
167
|
+
if (result.ok) await this.inbox.markDelivered(message.id);
|
|
168
|
+
else {
|
|
169
|
+
ok = false;
|
|
170
|
+
await this.inbox.markFailed(message.id, failLabel);
|
|
171
|
+
}
|
|
161
172
|
}
|
|
173
|
+
if (messages.length < 100) break;
|
|
162
174
|
}
|
|
163
175
|
return ok;
|
|
164
176
|
}
|