@namzu/cli 11.0.0 → 12.0.1
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 +390 -46
- package/dist/cli.d.ts +15 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +132 -4
- package/dist/cli.js.map +1 -1
- package/dist/commands/acp.d.ts +29 -0
- package/dist/commands/acp.d.ts.map +1 -0
- package/dist/commands/acp.js +156 -0
- package/dist/commands/acp.js.map +1 -0
- package/dist/commands/doctor.d.ts +12 -1
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +18 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/drain.d.ts +2 -2
- package/dist/commands/drain.d.ts.map +1 -1
- package/dist/commands/drain.js +31 -8
- package/dist/commands/drain.js.map +1 -1
- package/dist/commands/run-flags.d.ts.map +1 -1
- package/dist/commands/run-flags.js +33 -0
- package/dist/commands/run-flags.js.map +1 -1
- package/dist/commands/run-stream.d.ts +3 -3
- package/dist/commands/run-stream.d.ts.map +1 -1
- package/dist/commands/run-stream.js +27 -10
- package/dist/commands/run-stream.js.map +1 -1
- package/dist/commands/run.d.ts.map +1 -1
- package/dist/commands/run.js +50 -4
- package/dist/commands/run.js.map +1 -1
- package/dist/commands/types.d.ts +10 -0
- package/dist/commands/types.d.ts.map +1 -1
- package/dist/config/load.d.ts +64 -0
- package/dist/config/load.d.ts.map +1 -1
- package/dist/config/load.js +137 -20
- package/dist/config/load.js.map +1 -1
- package/dist/config/schema.d.ts +51 -0
- package/dist/config/schema.d.ts.map +1 -1
- package/dist/config/schema.js.map +1 -1
- package/dist/context/capabilities.d.ts +88 -0
- package/dist/context/capabilities.d.ts.map +1 -0
- package/dist/context/capabilities.js +160 -0
- package/dist/context/capabilities.js.map +1 -0
- package/dist/context/sandbox.d.ts +13 -0
- package/dist/context/sandbox.d.ts.map +1 -1
- package/dist/context/sandbox.js +15 -0
- package/dist/context/sandbox.js.map +1 -1
- package/dist/doctor/checks/index.d.ts +6 -1
- package/dist/doctor/checks/index.d.ts.map +1 -1
- package/dist/doctor/checks/index.js +45 -2
- package/dist/doctor/checks/index.js.map +1 -1
- package/dist/doctor/checks/invariants.d.ts +23 -0
- package/dist/doctor/checks/invariants.d.ts.map +1 -0
- package/dist/doctor/checks/invariants.js +79 -0
- package/dist/doctor/checks/invariants.js.map +1 -0
- package/dist/doctor/checks/logging.d.ts +10 -0
- package/dist/doctor/checks/logging.d.ts.map +1 -0
- package/dist/doctor/checks/logging.js +69 -0
- package/dist/doctor/checks/logging.js.map +1 -0
- package/dist/doctor/checks/session-export.d.ts +21 -0
- package/dist/doctor/checks/session-export.d.ts.map +1 -0
- package/dist/doctor/checks/session-export.js +62 -0
- package/dist/doctor/checks/session-export.js.map +1 -0
- package/dist/doctor/checks/telemetry.d.ts +15 -28
- package/dist/doctor/checks/telemetry.d.ts.map +1 -1
- package/dist/doctor/checks/telemetry.js +34 -54
- package/dist/doctor/checks/telemetry.js.map +1 -1
- package/dist/doctor/checks/vault.d.ts +4 -20
- package/dist/doctor/checks/vault.d.ts.map +1 -1
- package/dist/doctor/checks/vault.js +58 -19
- package/dist/doctor/checks/vault.js.map +1 -1
- package/dist/doctor/registry.d.ts.map +1 -1
- package/dist/doctor/registry.js +13 -6
- package/dist/doctor/registry.js.map +1 -1
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/index.js.map +1 -1
- package/dist/integrations/files/attachment-store.d.ts +44 -0
- package/dist/integrations/files/attachment-store.d.ts.map +1 -0
- package/dist/integrations/files/attachment-store.js +86 -0
- package/dist/integrations/files/attachment-store.js.map +1 -0
- package/dist/integrations/providers/credential-provider.d.ts +39 -0
- package/dist/integrations/providers/credential-provider.d.ts.map +1 -0
- package/dist/integrations/providers/credential-provider.js +74 -0
- package/dist/integrations/providers/credential-provider.js.map +1 -0
- package/dist/integrations/providers/discover.d.ts.map +1 -1
- package/dist/integrations/providers/discover.js +15 -3
- package/dist/integrations/providers/discover.js.map +1 -1
- package/dist/integrations/providers/oauth.d.ts.map +1 -1
- package/dist/integrations/providers/oauth.js +24 -1
- package/dist/integrations/providers/oauth.js.map +1 -1
- package/dist/integrations/sessions/store.d.ts +2 -2
- package/dist/integrations/sessions/store.d.ts.map +1 -1
- package/dist/integrations/sessions/store.js +21 -9
- package/dist/integrations/sessions/store.js.map +1 -1
- package/dist/integrations/subagents/runtime.d.ts +3 -3
- package/dist/integrations/subagents/runtime.d.ts.map +1 -1
- package/dist/integrations/subagents/runtime.js +12 -12
- package/dist/integrations/subagents/runtime.js.map +1 -1
- package/dist/integrations/telemetry/session-export.d.ts +99 -0
- package/dist/integrations/telemetry/session-export.d.ts.map +1 -0
- package/dist/integrations/telemetry/session-export.js +119 -0
- package/dist/integrations/telemetry/session-export.js.map +1 -0
- package/dist/logging.d.ts +79 -0
- package/dist/logging.d.ts.map +1 -0
- package/dist/logging.js +67 -0
- package/dist/logging.js.map +1 -0
- package/dist/permissions/rules.d.ts +3 -3
- package/dist/permissions/rules.d.ts.map +1 -1
- package/dist/permissions/rules.js +1 -1
- package/dist/permissions/rules.js.map +1 -1
- package/dist/skills/store.d.ts +1 -1
- package/dist/skills/store.js +1 -1
- package/dist/tui/App.d.ts.map +1 -1
- package/dist/tui/App.js +92 -6
- package/dist/tui/App.js.map +1 -1
- package/dist/tui/StatusBar.d.ts +1 -1
- package/dist/tui/StatusBar.d.ts.map +1 -1
- package/dist/tui/agent.d.ts +54 -24
- package/dist/tui/agent.d.ts.map +1 -1
- package/dist/tui/agent.js +330 -127
- package/dist/tui/agent.js.map +1 -1
- package/dist/tui/index.d.ts.map +1 -1
- package/dist/tui/index.js +17 -6
- package/dist/tui/index.js.map +1 -1
- package/dist/tui/log-pane.d.ts +48 -0
- package/dist/tui/log-pane.d.ts.map +1 -0
- package/dist/tui/log-pane.js +106 -0
- package/dist/tui/log-pane.js.map +1 -0
- package/dist/tui/slashCommands.d.ts +134 -11
- package/dist/tui/slashCommands.d.ts.map +1 -1
- package/dist/tui/slashCommands.js +169 -15
- package/dist/tui/slashCommands.js.map +1 -1
- package/dist/tui/types.d.ts +11 -2
- package/dist/tui/types.d.ts.map +1 -1
- package/package.json +8 -6
|
@@ -29,7 +29,9 @@
|
|
|
29
29
|
* was written back to the Keychain would be a no-op off macOS, leaving the
|
|
30
30
|
* real store holding a token that is refreshed again on every launch.
|
|
31
31
|
*/
|
|
32
|
-
import {
|
|
32
|
+
import { buildProbeContext, probe } from '@namzu/sdk';
|
|
33
|
+
import { SUBSCRIPTION_CREDENTIAL_REF } from './credential-provider.js';
|
|
34
|
+
import { credentialsPath, readStoredSubscriptionCredential, writeStoredSubscriptionCredential, } from './credential-store.js';
|
|
33
35
|
import { OAUTH_CLIENT_ID, OAUTH_TOKEN_URL } from './identity.js';
|
|
34
36
|
import { readAgentKeychainCredential, writeAgentKeychainCredential, } from './keychain.js';
|
|
35
37
|
/** Refresh a few seconds early so an about-to-expire token isn't used. */
|
|
@@ -79,6 +81,23 @@ export async function ensureFreshAnthropicToken(accessToken, oauth) {
|
|
|
79
81
|
* the token is already in hand and usable for this session, so a store that
|
|
80
82
|
* will not take it costs a re-refresh next launch, not the session.
|
|
81
83
|
*/
|
|
84
|
+
/**
|
|
85
|
+
* Say that a credential turned over, without saying what it turned into.
|
|
86
|
+
*
|
|
87
|
+
* Through the probe registry that already carries `vault_lookup`, because a
|
|
88
|
+
* second bus means a subscriber that sees lookups and not rotations, or the
|
|
89
|
+
* reverse, depending on which one it happened to find.
|
|
90
|
+
*/
|
|
91
|
+
function announceRotation(replaced) {
|
|
92
|
+
probe.dispatch({
|
|
93
|
+
type: 'vault_credential_changed',
|
|
94
|
+
kind: replaced ? 'rotated' : 'set',
|
|
95
|
+
source: credentialsPath(),
|
|
96
|
+
// The NAME. This event exists to be logged and retained, which is
|
|
97
|
+
// exactly what the value must not be.
|
|
98
|
+
ref: SUBSCRIPTION_CREDENTIAL_REF,
|
|
99
|
+
}, buildProbeContext());
|
|
100
|
+
}
|
|
82
101
|
function persistRefreshed(cred, origin) {
|
|
83
102
|
if (origin === 'keychain') {
|
|
84
103
|
writeAgentKeychainCredential(cred);
|
|
@@ -86,6 +105,10 @@ function persistRefreshed(cred, origin) {
|
|
|
86
105
|
}
|
|
87
106
|
try {
|
|
88
107
|
writeStoredSubscriptionCredential(cred);
|
|
108
|
+
// Announced only after the store proved the file private. A rotation
|
|
109
|
+
// event for a write that refused would have a reader chasing a
|
|
110
|
+
// credential turn-over that never happened.
|
|
111
|
+
announceRotation(cred.accessToken !== undefined);
|
|
89
112
|
}
|
|
90
113
|
catch {
|
|
91
114
|
// The store refused to prove the file private and therefore wrote
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/integrations/providers/oauth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,OAAO,EACN,gCAAgC,EAChC,iCAAiC,GACjC,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAChE,OAAO,EAEN,2BAA2B,EAC3B,4BAA4B,GAC5B,MAAM,eAAe,CAAA;AAEtB,0EAA0E;AAC1E,MAAM,cAAc,GAAG,MAAM,CAAA;AAE7B;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,0BAA0B,CAAC,MAAwB;IAClE,OAAO,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,gCAAgC,EAAE,CAAC,CAAC,CAAC,2BAA2B,EAAE,CAAA;AAChG,CAAC;AAYD;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,yBAAyB,CAC9C,WAAmB,EACnB,KAAoB;IAEpB,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,KAAK,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,cAAc,CAAA;IAC5F,IAAI,KAAK;QAAE,OAAO,WAAW,CAAA;IAC7B,IAAI,CAAC,KAAK,CAAC,YAAY;QAAE,OAAO,WAAW,CAAA;IAE3C,MAAM,SAAS,GAAG,MAAM,sBAAsB,CAAC,KAAK,CAAC,YAAY,CAAC,CAAA;IAClE,IAAI,CAAC,SAAS;QAAE,OAAO,WAAW,CAAA;IAClC,gBAAgB,CAAC,SAAS,EAAE,KAAK,CAAC,MAAM,IAAI,UAAU,CAAC,CAAA;IACvD,OAAO,SAAS,CAAC,WAAW,CAAA;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,SAAS,gBAAgB,CAAC,IAA0B,EAAE,MAAwB;IAC7E,IAAI,MAAM,KAAK,UAAU,EAAE,CAAC;QAC3B,4BAA4B,CAAC,IAAI,CAAC,CAAA;QAClC,OAAM;IACP,CAAC;IACD,IAAI,CAAC;QACJ,iCAAiC,CAAC,IAAI,CAAC,CAAA;
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../../src/integrations/providers/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -10,11 +10,11 @@
|
|
|
10
10
|
* `<cwd>/.namzu`, the same root `query()` writes its runs under, so a
|
|
11
11
|
* session's `session.json` and its `runs/` live in one place.
|
|
12
12
|
*/
|
|
13
|
-
import { DiskSessionStore, type Message, type ProjectId, type SessionId, type TenantId, type
|
|
13
|
+
import { DiskSessionStore, type Message, type ProjectId, type SessionId, type TenantId, type TopicId } from '@namzu/sdk';
|
|
14
14
|
export interface CliSessions {
|
|
15
15
|
readonly store: DiskSessionStore;
|
|
16
16
|
readonly projectId: ProjectId;
|
|
17
|
-
readonly
|
|
17
|
+
readonly topicId: TopicId;
|
|
18
18
|
readonly tenantId: TenantId;
|
|
19
19
|
/** Absolute path of the cwd's `.namzu` root (where pointers live). */
|
|
20
20
|
readonly root: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/integrations/sessions/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EACN,gBAAgB,EAChB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/integrations/sessions/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EACN,gBAAgB,EAChB,KAAK,OAAO,EACZ,KAAK,SAAS,EACd,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,OAAO,EAMZ,MAAM,YAAY,CAAA;AAOnB,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,gBAAgB,CAAA;IAChC,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAA;IAC7B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAA;IAC3B,sEAAsE;IACtE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CACrB;AAED,MAAM,WAAW,kBAAkB;IAClC,QAAQ,CAAC,EAAE,EAAE,SAAS,CAAA;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAA;IAC1B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CACtB;AAED;;;;GAIG;AACH,wBAAsB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CA4BpE;AAgBD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CAAC,CAAC,EAAE,WAAW,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,CAAC,CAezF;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,EAAE,WAAW,GAAG,OAAO,CAAC,SAAS,CAAC,CAO1E;AAED,oDAAoD;AACpD,wBAAsB,cAAc,CACnC,CAAC,EAAE,WAAW,EACd,SAAS,EAAE,SAAS,EACpB,QAAQ,EAAE,SAAS,OAAO,EAAE,GAC1B,OAAO,CAAC,IAAI,CAAC,CAIf;AAED,kDAAkD;AAClD,wBAAsB,gBAAgB,CAAC,CAAC,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC,CAE/F;AAED,6EAA6E;AAC7E,wBAAsB,UAAU,CAAC,CAAC,EAAE,WAAW,EAAE,KAAK,SAAK,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAc1F"}
|
|
@@ -12,9 +12,11 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
14
14
|
import { join } from 'node:path';
|
|
15
|
-
import { DiskSessionStore, UNKNOWN_TENANT_ID, requireOpenProject, } from '@namzu/sdk';
|
|
15
|
+
import { DiskSessionStore, UNKNOWN_TENANT_ID, asProjectId, asSessionId, asTopicId, requireOpenProject, } from '@namzu/sdk';
|
|
16
|
+
// `UNKNOWN_TENANT_ID` is already a `TenantId`; the assertion this replaced
|
|
17
|
+
// re-stated a type the constant carries.
|
|
16
18
|
const TENANT = UNKNOWN_TENANT_ID;
|
|
17
|
-
const THREAD = '
|
|
19
|
+
const THREAD = asTopicId('top_namzu-cli');
|
|
18
20
|
/**
|
|
19
21
|
* Open (or initialize) the cwd's CLI project. Returns the handle used by
|
|
20
22
|
* the other helpers. Throws only on unexpected store errors; callers treat
|
|
@@ -27,8 +29,13 @@ export async function openSessions(cwd) {
|
|
|
27
29
|
let projectId;
|
|
28
30
|
try {
|
|
29
31
|
const ptr = JSON.parse(readFileSync(pointerPath, 'utf8'));
|
|
30
|
-
|
|
31
|
-
|
|
32
|
+
// Prefix-checked, and a bad pointer is treated exactly like a stale one:
|
|
33
|
+
// the next lines already drop a projectId whose directory is gone, so a
|
|
34
|
+
// hand-edited `cli.json` takes the same path instead of carrying a
|
|
35
|
+
// non-id into a store lookup.
|
|
36
|
+
if (typeof ptr.projectId === 'string' && ptr.projectId.startsWith('prj_')) {
|
|
37
|
+
projectId = asProjectId(ptr.projectId);
|
|
38
|
+
}
|
|
32
39
|
}
|
|
33
40
|
catch {
|
|
34
41
|
// no pointer yet
|
|
@@ -42,7 +49,7 @@ export async function openSessions(cwd) {
|
|
|
42
49
|
mkdirSync(root, { recursive: true });
|
|
43
50
|
writeFileSync(pointerPath, `${JSON.stringify({ projectId }, null, 2)}\n`, { mode: 0o600 });
|
|
44
51
|
}
|
|
45
|
-
return { store, projectId,
|
|
52
|
+
return { store, projectId, topicId: THREAD, tenantId: TENANT, root };
|
|
46
53
|
}
|
|
47
54
|
// Maps an embedder's own session key (e.g. a desktop host's uuid) to a
|
|
48
55
|
// namzu conversation id, so reopening that session resumes the same
|
|
@@ -66,8 +73,13 @@ function readDesktopMap(root) {
|
|
|
66
73
|
export async function resolveConversation(s, key) {
|
|
67
74
|
const map = readDesktopMap(s.root);
|
|
68
75
|
const existing = map[key];
|
|
69
|
-
|
|
70
|
-
|
|
76
|
+
// Same treatment as the project pointer above: a mapped id that is not an
|
|
77
|
+
// id is indistinguishable from one whose session was wiped, and this
|
|
78
|
+
// function already knows what to do about that — mint a fresh one.
|
|
79
|
+
if (existing?.startsWith('ses_')) {
|
|
80
|
+
const mapped = asSessionId(existing);
|
|
81
|
+
if (await s.store.getSession(mapped, s.tenantId))
|
|
82
|
+
return mapped;
|
|
71
83
|
}
|
|
72
84
|
const id = await startConversation(s);
|
|
73
85
|
map[key] = id;
|
|
@@ -92,7 +104,7 @@ export async function resolveConversation(s, key) {
|
|
|
92
104
|
*/
|
|
93
105
|
export async function startConversation(s) {
|
|
94
106
|
await requireOpenProject(s.store, s.projectId, s.tenantId, 'cli-session');
|
|
95
|
-
const session = await s.store.createSession({
|
|
107
|
+
const session = await s.store.createSession({ topicId: s.topicId, projectId: s.projectId, currentActor: null }, s.tenantId);
|
|
96
108
|
return session.id;
|
|
97
109
|
}
|
|
98
110
|
/** Append messages (in order) to a conversation. */
|
|
@@ -107,7 +119,7 @@ export async function loadConversation(s, sessionId) {
|
|
|
107
119
|
}
|
|
108
120
|
/** Recent non-empty conversations, newest first — for the `/resume` list. */
|
|
109
121
|
export async function listRecent(s, limit = 20) {
|
|
110
|
-
const sessions = await s.store.
|
|
122
|
+
const sessions = await s.store.listSessionsByTopic(s.topicId, s.tenantId);
|
|
111
123
|
const out = [];
|
|
112
124
|
for (const sess of sessions) {
|
|
113
125
|
const messages = await s.store.loadMessages(sess.id, s.tenantId);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/integrations/sessions/store.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAChE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAA;AAChC,OAAO,EACN,gBAAgB,EAMhB,iBAAiB,EACjB,kBAAkB,GAClB,MAAM,YAAY,CAAA;AAEnB,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"store.js","sourceRoot":"","sources":["../../../src/integrations/sessions/store.ts"],"names":[],"mappings":"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"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* store backs the AgentManager, so sub-agent bookkeeping never touches the
|
|
12
12
|
* CLI's on-disk `/resume` conversation store.
|
|
13
13
|
*/
|
|
14
|
-
import { type LLMProvider, type RunEvent, type
|
|
14
|
+
import { type AuthorizationGateConfig, type LLMProvider, type RunEvent, type TaskScheduler, type ToolDefinition, type ToolRegistryContract } from '@namzu/sdk';
|
|
15
15
|
export declare const GENERAL_PURPOSE_SUBAGENT = "general-purpose";
|
|
16
16
|
export interface SubagentRuntimeOptions {
|
|
17
17
|
readonly cwd: string;
|
|
@@ -20,7 +20,7 @@ export interface SubagentRuntimeOptions {
|
|
|
20
20
|
readonly buildProvider: () => LLMProvider;
|
|
21
21
|
/** Build the sub-agent's tool registry (its own working set). */
|
|
22
22
|
readonly buildTools: () => ToolRegistryContract;
|
|
23
|
-
readonly
|
|
23
|
+
readonly authorizationGate?: AuthorizationGateConfig;
|
|
24
24
|
/**
|
|
25
25
|
* The project's own instruction block, already composed, or absent when the
|
|
26
26
|
* working directory declares none.
|
|
@@ -46,7 +46,7 @@ export interface SubagentRuntimeOptions {
|
|
|
46
46
|
readonly onEvent?: (event: RunEvent) => void;
|
|
47
47
|
}
|
|
48
48
|
export interface SubagentRuntime {
|
|
49
|
-
readonly gateway:
|
|
49
|
+
readonly gateway: TaskScheduler;
|
|
50
50
|
readonly agentTool: ToolDefinition;
|
|
51
51
|
readonly allowedAgentIds: readonly string[];
|
|
52
52
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/integrations/subagents/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,
|
|
1
|
+
{"version":3,"file":"runtime.d.ts","sourceRoot":"","sources":["../../../src/integrations/subagents/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAMN,KAAK,uBAAuB,EAO5B,KAAK,WAAW,EAIhB,KAAK,QAAQ,EAEb,KAAK,aAAa,EAClB,KAAK,cAAc,EACnB,KAAK,oBAAoB,EASzB,MAAM,YAAY,CAAA;AAEnB,eAAO,MAAM,wBAAwB,oBAAoB,CAAA;AAczD,MAAM,WAAW,sBAAsB;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;IACtB,yEAAyE;IACzE,QAAQ,CAAC,aAAa,EAAE,MAAM,WAAW,CAAA;IACzC,iEAAiE;IACjE,QAAQ,CAAC,UAAU,EAAE,MAAM,oBAAoB,CAAA;IAC/C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,uBAAuB,CAAA;IACpD;;;;;;;;;OASG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,MAAM,CAAA;IACrC;;;;;;;;OAQG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,CAAC,CAAA;IAChD,4EAA4E;IAC5E,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,QAAQ,KAAK,IAAI,CAAA;CAC5C;AAED,MAAM,WAAW,eAAe;IAC/B,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAA;IAC/B,QAAQ,CAAC,SAAS,EAAE,cAAc,CAAA;IAClC,QAAQ,CAAC,eAAe,EAAE,SAAS,MAAM,EAAE,CAAA;CAC3C;AAED;;;GAGG;AACH,wBAAsB,qBAAqB,CAC1C,IAAI,EAAE,sBAAsB,GAC1B,OAAO,CAAC,eAAe,CAAC,CA4J1B"}
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* store backs the AgentManager, so sub-agent bookkeeping never touches the
|
|
12
12
|
* CLI's on-disk `/resume` conversation store.
|
|
13
13
|
*/
|
|
14
|
-
import { AgentManager, AgentRegistry, DefaultCapacityValidator, InMemorySessionStore,
|
|
14
|
+
import { AgentManager, AgentRegistry, DefaultCapacityValidator, InMemorySessionStore, InMemoryTopicStore, LocalTaskScheduler, ReactiveAgent, SessionSummaryMaterializer, TopicManager, WorkspaceBackendRegistry, asRunId, asSummaryId, asTenantId, asUserId, defineTool, mcpJsonSchemaToZod, } from '@namzu/sdk';
|
|
15
15
|
export const GENERAL_PURPOSE_SUBAGENT = 'general-purpose';
|
|
16
16
|
const SUBAGENT_PROMPT = [
|
|
17
17
|
'You are a focused sub-agent dispatched by namzu to complete one self-contained task and report back.',
|
|
@@ -29,12 +29,12 @@ const SUBAGENT_PROMPT = [
|
|
|
29
29
|
* register on the parent and the gateway to pass to `query({ taskGateway })`.
|
|
30
30
|
*/
|
|
31
31
|
export async function createSubagentRuntime(opts) {
|
|
32
|
-
const tenantId = 'tnt_namzu-cli';
|
|
32
|
+
const tenantId = asTenantId('tnt_namzu-cli');
|
|
33
33
|
const store = new InMemorySessionStore();
|
|
34
|
-
const
|
|
35
|
-
const userActor = { kind: 'user', userId: 'usr_namzu', tenantId };
|
|
34
|
+
const topicStore = new InMemoryTopicStore();
|
|
35
|
+
const userActor = { kind: 'user', userId: asUserId('usr_namzu'), tenantId };
|
|
36
36
|
const project = await store.createProject({ tenantId, name: 'namzu-cli' }, tenantId);
|
|
37
|
-
const thread = await
|
|
37
|
+
const thread = await topicStore.createTopic({ projectId: project.id, title: 'namzu-cli' }, tenantId);
|
|
38
38
|
// No workspace gate here, and that is a finding rather than an omission.
|
|
39
39
|
//
|
|
40
40
|
// A direct `createSession` bypasses `requireOpenProject`, which is why the
|
|
@@ -48,16 +48,16 @@ export async function createSubagentRuntime(opts) {
|
|
|
48
48
|
//
|
|
49
49
|
// The trigger to add one is the day this store is replaced by a persistent
|
|
50
50
|
// one, or the project id starts arriving from a caller.
|
|
51
|
-
const parentSession = await store.createSession({
|
|
51
|
+
const parentSession = await store.createSession({ topicId: thread.id, projectId: project.id, currentActor: userActor }, tenantId);
|
|
52
52
|
await store.updateSession({ ...parentSession, status: 'active' }, tenantId);
|
|
53
53
|
let summaryCounter = 0;
|
|
54
54
|
const materializer = new SessionSummaryMaterializer({
|
|
55
55
|
store,
|
|
56
|
-
generateSummaryId: () => `sum_namzu_${++summaryCounter}
|
|
56
|
+
generateSummaryId: () => asSummaryId(`sum_namzu_${++summaryCounter}`),
|
|
57
57
|
});
|
|
58
58
|
const registry = new AgentRegistry();
|
|
59
59
|
registry.register(buildDefinition(GENERAL_PURPOSE_SUBAGENT, 'A general-purpose sub-agent.', SUBAGENT_PROMPT, opts));
|
|
60
|
-
const threadManager = new
|
|
60
|
+
const threadManager = new TopicManager({ topicStore, sessionStore: store });
|
|
61
61
|
const manager = new AgentManager(registry, undefined, {
|
|
62
62
|
sessionStore: store,
|
|
63
63
|
summaryMaterializer: materializer,
|
|
@@ -66,18 +66,18 @@ export async function createSubagentRuntime(opts) {
|
|
|
66
66
|
threadManager,
|
|
67
67
|
});
|
|
68
68
|
const taskContext = {
|
|
69
|
-
parentRunId: 'run_namzu-cli',
|
|
69
|
+
parentRunId: asRunId('run_namzu-cli'),
|
|
70
70
|
parentAgentId: 'namzu',
|
|
71
71
|
parentAbortController: new AbortController(),
|
|
72
72
|
depth: 0,
|
|
73
73
|
budgetTracker: { total: 1_000_000, remaining: 1_000_000 },
|
|
74
74
|
tenantId,
|
|
75
|
-
|
|
75
|
+
topicId: thread.id,
|
|
76
76
|
sessionId: parentSession.id,
|
|
77
77
|
projectId: project.id,
|
|
78
78
|
parentActor: userActor,
|
|
79
79
|
};
|
|
80
|
-
const gateway = new
|
|
80
|
+
const gateway = new LocalTaskScheduler(manager, taskContext, opts.onEvent);
|
|
81
81
|
// Dynamic `Agent` tool: the model passes an optional `role` (the persona /
|
|
82
82
|
// system prompt) and we register + spawn a fresh specialist for it at call
|
|
83
83
|
// time — no pre-defined agent file needed. Omit `role` → general-purpose.
|
|
@@ -211,7 +211,7 @@ function buildDefinition(id, description, systemPrompt, opts) {
|
|
|
211
211
|
provider: opts.buildProvider(),
|
|
212
212
|
tools: opts.buildTools(),
|
|
213
213
|
systemPrompt: environment ? `${prompt}\n\n${environment}` : prompt,
|
|
214
|
-
...(opts.
|
|
214
|
+
...(opts.authorizationGate ? { authorizationGate: opts.authorizationGate } : {}),
|
|
215
215
|
};
|
|
216
216
|
},
|
|
217
217
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/integrations/subagents/runtime.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAGN,YAAY,EACZ,aAAa,
|
|
1
|
+
{"version":3,"file":"runtime.js","sourceRoot":"","sources":["../../../src/integrations/subagents/runtime.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import type { RunEventListener } from '@namzu/sdk';
|
|
2
|
+
import type { SessionExportConfig } from '../../config/schema.js';
|
|
3
|
+
/**
|
|
4
|
+
* Turning `telemetry.sessionExport` in a config file into a live listener.
|
|
5
|
+
*
|
|
6
|
+
* Two things this file is careful about, and both are the reason it exists
|
|
7
|
+
* rather than the wiring being inline at the call site.
|
|
8
|
+
*
|
|
9
|
+
* **`@namzu/telemetry` is optional, and its absence is a REFUSAL here.**
|
|
10
|
+
* Everywhere else in this CLI an absent optional package degrades a feature:
|
|
11
|
+
* no sandbox package, no sandbox, say so and continue. Not here. An operator
|
|
12
|
+
* who wrote `sessionExport` into a config asked for a session to be
|
|
13
|
+
* recorded, and continuing without it means the run happens and the record
|
|
14
|
+
* they were counting on does not exist — the failure is invisible until the
|
|
15
|
+
* moment they go looking for the session that was supposed to be there.
|
|
16
|
+
*
|
|
17
|
+
* **The redaction chain is never silently empty.** Omitting `redactors`
|
|
18
|
+
* installs the shipped secret redactor. Turning redaction off takes an
|
|
19
|
+
* explicit `redactors: []`, because reaching "no redaction" by forgetting a
|
|
20
|
+
* key is the shape this whole seam exists to prevent.
|
|
21
|
+
*/
|
|
22
|
+
/** What the CLI needs back: a listener to attach, and a way to drain it. */
|
|
23
|
+
export interface AttachedSessionExport {
|
|
24
|
+
readonly listener: RunEventListener;
|
|
25
|
+
/** Flush before the process exits. */
|
|
26
|
+
shutdown(): Promise<void>;
|
|
27
|
+
/** The sentence to show a user — `describeSessionExport`'s output. */
|
|
28
|
+
readonly disclosure: string;
|
|
29
|
+
}
|
|
30
|
+
/** Why a configured export could not be started. */
|
|
31
|
+
export declare class SessionExportUnavailableError extends Error {
|
|
32
|
+
readonly reason: 'absent' | 'broken';
|
|
33
|
+
constructor(reason: 'absent' | 'broken', cause?: string);
|
|
34
|
+
}
|
|
35
|
+
/** The slice of `@namzu/telemetry` this uses. Structural, so a test needs no install. */
|
|
36
|
+
interface TelemetryModule {
|
|
37
|
+
createSessionExportListener(config: {
|
|
38
|
+
sink: {
|
|
39
|
+
emit(record: unknown): void;
|
|
40
|
+
shutdown(): Promise<void>;
|
|
41
|
+
};
|
|
42
|
+
destination: string;
|
|
43
|
+
eventTypes?: readonly string[];
|
|
44
|
+
redactors?: readonly ((record: unknown) => unknown)[];
|
|
45
|
+
}): RunEventListener;
|
|
46
|
+
describeSessionExport(config?: unknown): string;
|
|
47
|
+
secretRedactor(): (record: unknown) => unknown;
|
|
48
|
+
}
|
|
49
|
+
export type TelemetryLoader = () => Promise<TelemetryModule>;
|
|
50
|
+
/**
|
|
51
|
+
* Load the optional package, separating "not installed" from "installed and
|
|
52
|
+
* unusable" the same way `context/capabilities.ts` does — and for the same
|
|
53
|
+
* reason: the two send a reader to different places.
|
|
54
|
+
*
|
|
55
|
+
* Takes the specifier so a test can drive the REAL resolution path with a
|
|
56
|
+
* name that cannot resolve. Everything else in this file is tested through
|
|
57
|
+
* an injected loader, which proves what `attachSessionExport` does with a
|
|
58
|
+
* refusal and proves nothing about where the refusal comes from — a
|
|
59
|
+
* mutation replacing this `throw` with a stub module survived until this was
|
|
60
|
+
* separated out.
|
|
61
|
+
*/
|
|
62
|
+
export declare function loadTelemetryFrom(specifier: string): Promise<TelemetryModule>;
|
|
63
|
+
/**
|
|
64
|
+
* A JSONL file, one record per line.
|
|
65
|
+
*
|
|
66
|
+
* `appendFileSync` rather than a stream, and that is a deliberate trade: a
|
|
67
|
+
* stream would not block, but a stream's buffered tail is lost when the
|
|
68
|
+
* process exits on a signal, and the whole value of an exported session is
|
|
69
|
+
* that it survives the run that produced it. The listener already never
|
|
70
|
+
* waits on `emit` — the synchronous write happens inside a call the run does
|
|
71
|
+
* not await, so the cost lands on the exporting call and not on the model
|
|
72
|
+
* loop.
|
|
73
|
+
*/
|
|
74
|
+
export declare function fileSink(destinationPath: string): {
|
|
75
|
+
emit(record: unknown): void;
|
|
76
|
+
shutdown(): Promise<void>;
|
|
77
|
+
};
|
|
78
|
+
export interface AttachSessionExportOptions {
|
|
79
|
+
readonly config: SessionExportConfig;
|
|
80
|
+
/** Injectable for tests; production resolves `@namzu/telemetry` itself. */
|
|
81
|
+
readonly loader?: TelemetryLoader;
|
|
82
|
+
/** Injectable for tests; production appends to the configured file. */
|
|
83
|
+
readonly sink?: {
|
|
84
|
+
emit(record: unknown): void;
|
|
85
|
+
shutdown(): Promise<void>;
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
export declare function attachSessionExport(options: AttachSessionExportOptions): Promise<AttachedSessionExport>;
|
|
89
|
+
/**
|
|
90
|
+
* The disclosure when export is NOT configured.
|
|
91
|
+
*
|
|
92
|
+
* Goes through the same function as the configured case so the two cannot
|
|
93
|
+
* drift into reading alike — which is the property
|
|
94
|
+
* `describeSessionExport`'s own test pins, and which is worth nothing if
|
|
95
|
+
* this branch hand-writes its own sentence instead.
|
|
96
|
+
*/
|
|
97
|
+
export declare function describeSessionExportOff(loader?: TelemetryLoader): Promise<string | null>;
|
|
98
|
+
export {};
|
|
99
|
+
//# sourceMappingURL=session-export.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-export.d.ts","sourceRoot":"","sources":["../../../src/integrations/telemetry/session-export.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAA;AAIlD,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEjE;;;;;;;;;;;;;;;;;;GAkBG;AAEH,4EAA4E;AAC5E,MAAM,WAAW,qBAAqB;IACrC,QAAQ,CAAC,QAAQ,EAAE,gBAAgB,CAAA;IACnC,sCAAsC;IACtC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;IACzB,sEAAsE;IACtE,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAA;CAC3B;AAED,oDAAoD;AACpD,qBAAa,6BAA8B,SAAQ,KAAK;IAEtD,QAAQ,CAAC,MAAM,EAAE,QAAQ,GAAG,QAAQ;gBAA3B,MAAM,EAAE,QAAQ,GAAG,QAAQ,EACpC,KAAK,CAAC,EAAE,MAAM;CASf;AAED,yFAAyF;AACzF,UAAU,eAAe;IACxB,2BAA2B,CAAC,MAAM,EAAE;QACnC,IAAI,EAAE;YAAE,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;YAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;SAAE,CAAA;QAChE,WAAW,EAAE,MAAM,CAAA;QACnB,UAAU,CAAC,EAAE,SAAS,MAAM,EAAE,CAAA;QAC9B,SAAS,CAAC,EAAE,SAAS,CAAC,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAC,EAAE,CAAA;KACrD,GAAG,gBAAgB,CAAA;IACpB,qBAAqB,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;IAC/C,cAAc,IAAI,CAAC,MAAM,EAAE,OAAO,KAAK,OAAO,CAAA;CAC9C;AAED,MAAM,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,eAAe,CAAC,CAAA;AAI5D;;;;;;;;;;;GAWG;AACH,wBAAsB,iBAAiB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC,CAcnF;AAOD;;;;;;;;;;GAUG;AACH,wBAAgB,QAAQ,CAAC,eAAe,EAAE,MAAM,GAAG;IAClD,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAA;IAC3B,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;CACzB,CAeA;AAED,MAAM,WAAW,0BAA0B;IAC1C,QAAQ,CAAC,MAAM,EAAE,mBAAmB,CAAA;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,MAAM,CAAC,EAAE,eAAe,CAAA;IACjC,uEAAuE;IACvE,QAAQ,CAAC,IAAI,CAAC,EAAE;QAAE,IAAI,CAAC,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;QAAC,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC,CAAA;KAAE,CAAA;CAC1E;AAED,wBAAsB,mBAAmB,CACxC,OAAO,EAAE,0BAA0B,GACjC,OAAO,CAAC,qBAAqB,CAAC,CAyBhC;AAED;;;;;;;GAOG;AACH,wBAAsB,wBAAwB,CAAC,MAAM,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAU/F"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { appendFileSync, mkdirSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { probeOptionalPackage } from '../../context/capabilities.js';
|
|
4
|
+
/** Why a configured export could not be started. */
|
|
5
|
+
export class SessionExportUnavailableError extends Error {
|
|
6
|
+
reason;
|
|
7
|
+
constructor(reason, cause) {
|
|
8
|
+
super(reason === 'absent'
|
|
9
|
+
? 'telemetry.sessionExport is configured but "@namzu/telemetry" is not installed, so nothing would be recorded. Install it (npm i @namzu/telemetry), or remove telemetry.sessionExport from your config. Refusing rather than running a session whose export silently does not exist.'
|
|
10
|
+
: `telemetry.sessionExport is configured but "@namzu/telemetry" failed to load (${cause ?? 'no detail'}). Reinstall it, or remove telemetry.sessionExport from your config.`);
|
|
11
|
+
this.reason = reason;
|
|
12
|
+
this.name = 'SessionExportUnavailableError';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const TELEMETRY_SPECIFIER = '@namzu/telemetry';
|
|
16
|
+
/**
|
|
17
|
+
* Load the optional package, separating "not installed" from "installed and
|
|
18
|
+
* unusable" the same way `context/capabilities.ts` does — and for the same
|
|
19
|
+
* reason: the two send a reader to different places.
|
|
20
|
+
*
|
|
21
|
+
* Takes the specifier so a test can drive the REAL resolution path with a
|
|
22
|
+
* name that cannot resolve. Everything else in this file is tested through
|
|
23
|
+
* an injected loader, which proves what `attachSessionExport` does with a
|
|
24
|
+
* refusal and proves nothing about where the refusal comes from — a
|
|
25
|
+
* mutation replacing this `throw` with a stub module survived until this was
|
|
26
|
+
* separated out.
|
|
27
|
+
*/
|
|
28
|
+
export async function loadTelemetryFrom(specifier) {
|
|
29
|
+
// Through the SAME probe the doctor and the boot narrative use, rather
|
|
30
|
+
// than a second resolution here. Two answers to "is @namzu/telemetry
|
|
31
|
+
// installed" is two chances to disagree, and the one that drifted would be
|
|
32
|
+
// the one deciding whether a session gets recorded.
|
|
33
|
+
//
|
|
34
|
+
// It also inherits the fix: `require.resolve` reports an installed
|
|
35
|
+
// ESM-only package as absent, which would have produced this refusal
|
|
36
|
+
// against a machine that was configured correctly.
|
|
37
|
+
const probe = await probeOptionalPackage(specifier);
|
|
38
|
+
if (probe.state === 'absent')
|
|
39
|
+
throw new SessionExportUnavailableError('absent');
|
|
40
|
+
if (probe.state === 'broken')
|
|
41
|
+
throw new SessionExportUnavailableError('broken', probe.error.message);
|
|
42
|
+
return (await import(specifier));
|
|
43
|
+
}
|
|
44
|
+
async function loadTelemetry(loader) {
|
|
45
|
+
if (loader)
|
|
46
|
+
return await loader();
|
|
47
|
+
return await loadTelemetryFrom(TELEMETRY_SPECIFIER);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* A JSONL file, one record per line.
|
|
51
|
+
*
|
|
52
|
+
* `appendFileSync` rather than a stream, and that is a deliberate trade: a
|
|
53
|
+
* stream would not block, but a stream's buffered tail is lost when the
|
|
54
|
+
* process exits on a signal, and the whole value of an exported session is
|
|
55
|
+
* that it survives the run that produced it. The listener already never
|
|
56
|
+
* waits on `emit` — the synchronous write happens inside a call the run does
|
|
57
|
+
* not await, so the cost lands on the exporting call and not on the model
|
|
58
|
+
* loop.
|
|
59
|
+
*/
|
|
60
|
+
export function fileSink(destinationPath) {
|
|
61
|
+
const path = resolve(destinationPath);
|
|
62
|
+
let ensured = false;
|
|
63
|
+
return {
|
|
64
|
+
emit(record) {
|
|
65
|
+
if (!ensured) {
|
|
66
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
67
|
+
ensured = true;
|
|
68
|
+
}
|
|
69
|
+
appendFileSync(path, `${JSON.stringify(record)}\n`, 'utf-8');
|
|
70
|
+
},
|
|
71
|
+
// Nothing is buffered, so there is nothing to drain — and saying so is
|
|
72
|
+
// better than an empty function that reads as an unfinished one.
|
|
73
|
+
shutdown: async () => { },
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
export async function attachSessionExport(options) {
|
|
77
|
+
const telemetry = await loadTelemetry(options.loader);
|
|
78
|
+
const sink = options.sink ?? fileSink(options.config.destination);
|
|
79
|
+
// Omitted means the shipped redactor; `[]` means none. A config reaches
|
|
80
|
+
// "no redaction" only by saying so.
|
|
81
|
+
const redactors = (options.config.redactors ?? ['secrets']).map((name) => {
|
|
82
|
+
switch (name) {
|
|
83
|
+
case 'secrets':
|
|
84
|
+
return telemetry.secretRedactor();
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
const exportConfig = {
|
|
88
|
+
sink,
|
|
89
|
+
destination: options.config.destination,
|
|
90
|
+
...(options.config.eventTypes !== undefined ? { eventTypes: options.config.eventTypes } : {}),
|
|
91
|
+
redactors,
|
|
92
|
+
};
|
|
93
|
+
return {
|
|
94
|
+
listener: telemetry.createSessionExportListener(exportConfig),
|
|
95
|
+
shutdown: () => sink.shutdown(),
|
|
96
|
+
disclosure: telemetry.describeSessionExport(exportConfig),
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* The disclosure when export is NOT configured.
|
|
101
|
+
*
|
|
102
|
+
* Goes through the same function as the configured case so the two cannot
|
|
103
|
+
* drift into reading alike — which is the property
|
|
104
|
+
* `describeSessionExport`'s own test pins, and which is worth nothing if
|
|
105
|
+
* this branch hand-writes its own sentence instead.
|
|
106
|
+
*/
|
|
107
|
+
export async function describeSessionExportOff(loader) {
|
|
108
|
+
try {
|
|
109
|
+
const telemetry = await loadTelemetry(loader);
|
|
110
|
+
return telemetry.describeSessionExport();
|
|
111
|
+
}
|
|
112
|
+
catch {
|
|
113
|
+
// `@namzu/telemetry` absent AND export unconfigured is the ordinary
|
|
114
|
+
// case, not a problem: there is nothing to disclose because there is
|
|
115
|
+
// nothing installed that could export.
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
//# sourceMappingURL=session-export.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-export.js","sourceRoot":"","sources":["../../../src/integrations/telemetry/session-export.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAA;AAI5C,OAAO,EAAE,oBAAoB,EAAE,MAAM,+BAA+B,CAAA;AAiCpE,oDAAoD;AACpD,MAAM,OAAO,6BAA8B,SAAQ,KAAK;IAE7C;IADV,YACU,MAA2B,EACpC,KAAc;QAEd,KAAK,CACJ,MAAM,KAAK,QAAQ;YAClB,CAAC,CAAC,oRAAoR;YACtR,CAAC,CAAC,gFAAgF,KAAK,IAAI,WAAW,sEAAsE,CAC7K,CAAA;QAPQ,WAAM,GAAN,MAAM,CAAqB;QAQpC,IAAI,CAAC,IAAI,GAAG,+BAA+B,CAAA;IAC5C,CAAC;CACD;AAgBD,MAAM,mBAAmB,GAAG,kBAAkB,CAAA;AAE9C;;;;;;;;;;;GAWG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB;IACxD,uEAAuE;IACvE,qEAAqE;IACrE,2EAA2E;IAC3E,oDAAoD;IACpD,EAAE;IACF,mEAAmE;IACnE,qEAAqE;IACrE,mDAAmD;IACnD,MAAM,KAAK,GAAG,MAAM,oBAAoB,CAAC,SAAS,CAAC,CAAA;IACnD,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;QAAE,MAAM,IAAI,6BAA6B,CAAC,QAAQ,CAAC,CAAA;IAC/E,IAAI,KAAK,CAAC,KAAK,KAAK,QAAQ;QAC3B,MAAM,IAAI,6BAA6B,CAAC,QAAQ,EAAE,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAA;IACvE,OAAO,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAA+B,CAAA;AAC/D,CAAC;AAED,KAAK,UAAU,aAAa,CAAC,MAAwB;IACpD,IAAI,MAAM;QAAE,OAAO,MAAM,MAAM,EAAE,CAAA;IACjC,OAAO,MAAM,iBAAiB,CAAC,mBAAmB,CAAC,CAAA;AACpD,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,QAAQ,CAAC,eAAuB;IAI/C,MAAM,IAAI,GAAG,OAAO,CAAC,eAAe,CAAC,CAAA;IACrC,IAAI,OAAO,GAAG,KAAK,CAAA;IACnB,OAAO;QACN,IAAI,CAAC,MAAM;YACV,IAAI,CAAC,OAAO,EAAE,CAAC;gBACd,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;gBAC7C,OAAO,GAAG,IAAI,CAAA;YACf,CAAC;YACD,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,CAAA;QAC7D,CAAC;QACD,uEAAuE;QACvE,iEAAiE;QACjE,QAAQ,EAAE,KAAK,IAAI,EAAE,GAAE,CAAC;KACxB,CAAA;AACF,CAAC;AAUD,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAAmC;IAEnC,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;IACrD,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAEjE,wEAAwE;IACxE,oCAAoC;IACpC,MAAM,SAAS,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxE,QAAQ,IAAI,EAAE,CAAC;YACd,KAAK,SAAS;gBACb,OAAO,SAAS,CAAC,cAAc,EAAE,CAAA;QACnC,CAAC;IACF,CAAC,CAAC,CAAA;IAEF,MAAM,YAAY,GAAG;QACpB,IAAI;QACJ,WAAW,EAAE,OAAO,CAAC,MAAM,CAAC,WAAW;QACvC,GAAG,CAAC,OAAO,CAAC,MAAM,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC7F,SAAS;KACT,CAAA;IAED,OAAO;QACN,QAAQ,EAAE,SAAS,CAAC,2BAA2B,CAAC,YAAY,CAAC;QAC7D,QAAQ,EAAE,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC/B,UAAU,EAAE,SAAS,CAAC,qBAAqB,CAAC,YAAY,CAAC;KACzD,CAAA;AACF,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAAC,MAAwB;IACtE,IAAI,CAAC;QACJ,MAAM,SAAS,GAAG,MAAM,aAAa,CAAC,MAAM,CAAC,CAAA;QAC7C,OAAO,SAAS,CAAC,qBAAqB,EAAE,CAAA;IACzC,CAAC;IAAC,MAAM,CAAC;QACR,oEAAoE;QACpE,qEAAqE;QACrE,uCAAuC;QACvC,OAAO,IAAI,CAAA;IACZ,CAAC;AACF,CAAC"}
|