@chainingintention/pi-web-cn 1.202608.6 → 1.202608.7
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/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/config.js +69 -0
- package/dist/config.js.map +1 -1
- package/dist/server/app.js +4 -1
- package/dist/server/app.js.map +1 -1
- package/dist/server/audit/managementAuditStore.js +211 -0
- package/dist/server/audit/managementAuditStore.js.map +1 -0
- package/dist/server/audit/normalToolAuditCli.js +143 -0
- package/dist/server/audit/normalToolAuditCli.js.map +1 -0
- package/dist/server/audit/normalToolAuditStore.js +264 -0
- package/dist/server/audit/normalToolAuditStore.js.map +1 -0
- package/dist/server/managementEmbed.js +19 -1
- package/dist/server/managementEmbed.js.map +1 -1
- package/dist/server/requestLogging.js +10 -7
- package/dist/server/requestLogging.js.map +1 -1
- package/dist/server/sessiond/sessionProxyRoutes.js +13 -7
- package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
- package/dist/server/sessiond.js +90 -4
- package/dist/server/sessiond.js.map +1 -1
- package/dist/server/sessions/managementPermissionSystem.js +8 -8
- package/dist/server/sessions/managementPermissionSystem.js.map +1 -1
- package/dist/server/sessions/piSessionService.js +118 -7
- package/dist/server/sessions/piSessionService.js.map +1 -1
- package/dist/server/sessions/sessionRoutes.js +6 -2
- package/dist/server/sessions/sessionRoutes.js.map +1 -1
- package/dist/server/workbench/accessStateRoutes.js +30 -0
- package/dist/server/workbench/accessStateRoutes.js.map +1 -0
- package/dist/server/workbench/accessStateStore.js +29 -0
- package/dist/server/workbench/accessStateStore.js.map +1 -0
- package/dist/server/workbench/capabilitySearch.js +62 -0
- package/dist/server/workbench/capabilitySearch.js.map +1 -0
- package/dist/server/workbench/gatewayIntegration.js +56 -0
- package/dist/server/workbench/gatewayIntegration.js.map +1 -0
- package/dist/server/workbench/mcpClient.js +148 -0
- package/dist/server/workbench/mcpClient.js.map +1 -0
- package/dist/server/workbench/skillSync.js +375 -0
- package/dist/server/workbench/skillSync.js.map +1 -0
- package/dist/server/workbench/types.js +2 -0
- package/dist/server/workbench/types.js.map +1 -0
- package/dist/server/workbench/workbenchClient.js +136 -0
- package/dist/server/workbench/workbenchClient.js.map +1 -0
- package/dist/server/workbench/workbenchTools.js +145 -0
- package/dist/server/workbench/workbenchTools.js.map +1 -0
- package/dist/shared/apiTypes.d.ts +25 -0
- package/dist/shared/apiTypes.js.map +1 -1
- package/dist/shared/piWebConfigParsing.js +94 -0
- package/dist/shared/piWebConfigParsing.js.map +1 -1
- package/docs/config.md +65 -0
- package/package.json +7 -3
|
@@ -23,6 +23,7 @@ import { canonicalizeStoredCwd, cwdPathsEqual } from "../workingDirectory.js";
|
|
|
23
23
|
import { readSessionHeaderSummary } from "./sessionFileHeader.js";
|
|
24
24
|
import { countOutOfListingChildren, locateOutOfListingParents } from "./parentSessionLocator.js";
|
|
25
25
|
import { siblingWorkspaceCwds } from "../workspaces/projectWorkspaceCwds.js";
|
|
26
|
+
import { workbenchAccessHandle } from "../managementEmbed.js";
|
|
26
27
|
import { DEFAULT_EXTENSION_DIALOGS_TIMEOUT_MS, piWebDataDir } from "../../config.js";
|
|
27
28
|
import { createScopedSettingsManager, resolveSettingsScopeDirectory } from "./projectSettingsScope.js";
|
|
28
29
|
import { createAskUserToolDefinition } from "./askUserTool.js";
|
|
@@ -40,6 +41,8 @@ import { plainTextTheme } from "./plainTextTheme.js";
|
|
|
40
41
|
import { SessionUnreadStore } from "./sessionUnreadStore.js";
|
|
41
42
|
import { archiveCandidateFromActiveSession, archiveCandidateFromArchivedRecord, archiveCandidateFromListEntry, archiveInputFromActiveSession, archiveInputFromCandidate, archiveInputFromListEntry, clientSessionFromArchivedRecord, compareArchivedRecords, } from "./sessionArchiveMapping.js";
|
|
42
43
|
import { annotateAssistantThinkingLevel, getBoolean, getProperty, getString, toClientEvent } from "./sessionUiEvents.js";
|
|
44
|
+
import { WorkbenchHttpError } from "../workbench/workbenchClient.js";
|
|
45
|
+
import { createWorkbenchToolDefinitions } from "../workbench/workbenchTools.js";
|
|
43
46
|
const noopLogger = { info() { } };
|
|
44
47
|
const DEFAULT_UNREAD_PUBLICATION_RETRY_MS = 1_000;
|
|
45
48
|
/**
|
|
@@ -177,6 +180,22 @@ export function filterManagedProjectSkills(cwd, base) {
|
|
|
177
180
|
}),
|
|
178
181
|
};
|
|
179
182
|
}
|
|
183
|
+
export function filterManagedWorkbenchSkills(cwd, base, receipt) {
|
|
184
|
+
const projectRoot = realpathSync(cwd);
|
|
185
|
+
const allowedDirectories = new Set(receipt.skills.map((skill) => resolve(projectRoot, ".pi", "skills", skill.directory)));
|
|
186
|
+
return {
|
|
187
|
+
...base,
|
|
188
|
+
skills: base.skills.filter((skill) => {
|
|
189
|
+
try {
|
|
190
|
+
const path = realpathSync(skill.filePath);
|
|
191
|
+
return [...allowedDirectories].some((directory) => pathInsideOrEqual(directory, path));
|
|
192
|
+
}
|
|
193
|
+
catch {
|
|
194
|
+
return false;
|
|
195
|
+
}
|
|
196
|
+
}),
|
|
197
|
+
};
|
|
198
|
+
}
|
|
180
199
|
function pathInsideOrEqual(parent, child) {
|
|
181
200
|
const normalizedParent = resolve(parent);
|
|
182
201
|
const normalizedChild = resolve(child);
|
|
@@ -318,11 +337,11 @@ function createRuntimeWithContextAndOneShotSessionOptions(createRuntime, managem
|
|
|
318
337
|
});
|
|
319
338
|
};
|
|
320
339
|
}
|
|
321
|
-
function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, spawn, subsessions, askUser) {
|
|
340
|
+
function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRuntime, resolveSettingsScope, spawn, subsessions, askUser, workbench, logger = noopLogger, managementAudit, managementProjectIdForCwd) {
|
|
322
341
|
return async ({ cwd, agentDir, sessionManager, sessionStartEvent, managementContext, initialModel, initialThinkingLevel, delegationToolsEnabled = true }) => {
|
|
323
342
|
const scopedModelRuntime = managementContext === undefined ? await normalModelRuntimeForCwd(cwd) : await managementModelRuntime();
|
|
324
343
|
if (managementContext !== undefined) {
|
|
325
|
-
return createManagementRuntimeFactory(scopedModelRuntime, resolveSettingsScope, spawn, subsessions, askUser, managementContext)({
|
|
344
|
+
return createManagementRuntimeFactory(scopedModelRuntime, resolveSettingsScope, spawn, subsessions, askUser, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd)({
|
|
326
345
|
cwd,
|
|
327
346
|
agentDir,
|
|
328
347
|
sessionManager,
|
|
@@ -350,9 +369,41 @@ function createDefaultRuntimeFactory(normalModelRuntimeForCwd, managementModelRu
|
|
|
350
369
|
return { ...result, services, diagnostics: services.diagnostics };
|
|
351
370
|
};
|
|
352
371
|
}
|
|
353
|
-
function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, spawn, subsessions, askUser, managementContext) {
|
|
372
|
+
function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, spawn, subsessions, askUser, managementContext, workbench, logger, managementAudit, managementProjectIdForCwd) {
|
|
354
373
|
return async ({ cwd, agentDir, sessionManager, sessionStartEvent, initialModel, initialThinkingLevel, delegationToolsEnabled = true }) => {
|
|
355
|
-
const
|
|
374
|
+
const auditIdentity = await resolveManagementAuditIdentity(cwd, managementContext, managementProjectIdForCwd, logger);
|
|
375
|
+
const accessHandle = workbenchAccessHandle(managementContext);
|
|
376
|
+
const state = workbench === undefined ? undefined : workbench.accessStates.require(accessHandle);
|
|
377
|
+
let receipt;
|
|
378
|
+
try {
|
|
379
|
+
receipt = state === undefined ? undefined : await workbench?.skills.synchronize(cwd, state, {
|
|
380
|
+
...(managementAudit === undefined ? {} : { recorder: managementAudit }),
|
|
381
|
+
...auditIdentity,
|
|
382
|
+
sessionId: sessionManager.getSessionId(),
|
|
383
|
+
cwd,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
catch (error) {
|
|
387
|
+
if (error instanceof WorkbenchHttpError && error.status === 401 && accessHandle !== undefined)
|
|
388
|
+
workbench?.accessStates.delete(accessHandle);
|
|
389
|
+
throw error;
|
|
390
|
+
}
|
|
391
|
+
const workbenchTools = state === undefined || workbench === undefined ? [] : createWorkbenchToolDefinitions({
|
|
392
|
+
getState: () => workbench.accessStates.require(accessHandle),
|
|
393
|
+
workbench: workbench.client,
|
|
394
|
+
mcp: workbench.mcp,
|
|
395
|
+
invalidate: () => { if (accessHandle !== undefined)
|
|
396
|
+
workbench.accessStates.delete(accessHandle); },
|
|
397
|
+
logger,
|
|
398
|
+
...(managementAudit === undefined ? {} : { audit: managementAudit }),
|
|
399
|
+
auditContext: {
|
|
400
|
+
...auditIdentity,
|
|
401
|
+
sessionId: sessionManager.getSessionId(),
|
|
402
|
+
cwd,
|
|
403
|
+
},
|
|
404
|
+
});
|
|
405
|
+
const workbenchToolNames = workbenchTools.map((tool) => tool.name);
|
|
406
|
+
const policyAgentDir = await writeManagementPermissionSystemPolicy(agentDir, cwd, managementContext, workbenchToolNames);
|
|
356
407
|
return withRuntimeCreationEnvironment({ [PI_PERMISSION_SYSTEM_POLICY_AGENT_DIR]: policyAgentDir }, async () => {
|
|
357
408
|
const settingsManager = await createScopedSettingsManager({
|
|
358
409
|
cwd,
|
|
@@ -366,7 +417,7 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, spaw
|
|
|
366
417
|
settingsManager,
|
|
367
418
|
resourceLoaderOptions: {
|
|
368
419
|
agentsFilesOverride: (base) => filterManagedGlobalContextFiles(cwd, agentDir, base),
|
|
369
|
-
skillsOverride: (base) => filterManagedProjectSkills(cwd, base),
|
|
420
|
+
skillsOverride: (base) => receipt === undefined ? filterManagedProjectSkills(cwd, base) : filterManagedWorkbenchSkills(cwd, base, receipt),
|
|
370
421
|
},
|
|
371
422
|
});
|
|
372
423
|
const managedToolOptions = createManagedAgentToolOptions(cwd);
|
|
@@ -385,13 +436,14 @@ function createManagementRuntimeFactory(modelRuntime, resolveSettingsScope, spaw
|
|
|
385
436
|
...(delegationToolsEnabled && scopedSpawn !== undefined ? [defineTool(createSpawnSessionToolDefinition(cwd, { spawn: scopedSpawn }))] : []),
|
|
386
437
|
...(delegationToolsEnabled && scopedSubsessions !== undefined ? createSubsessionToolDefinitions(cwd, scopedSubsessions).map((tool) => defineTool(tool)) : []),
|
|
387
438
|
...(askUser === undefined ? [] : [createAskUserToolDefinition(askUser)]),
|
|
439
|
+
...workbenchTools,
|
|
388
440
|
];
|
|
389
441
|
const options = {
|
|
390
442
|
services,
|
|
391
443
|
sessionManager,
|
|
392
444
|
...(sessionStartEvent === undefined ? {} : { sessionStartEvent }),
|
|
393
445
|
customTools,
|
|
394
|
-
tools: managementAgentToolNames(managementContext),
|
|
446
|
+
tools: managementAgentToolNames(managementContext, workbenchToolNames),
|
|
395
447
|
...(initialModel === undefined ? {} : { model: initialModel }),
|
|
396
448
|
...(initialThinkingLevel === undefined ? {} : { thinkingLevel: initialThinkingLevel }),
|
|
397
449
|
};
|
|
@@ -521,6 +573,9 @@ export class PiSessionService {
|
|
|
521
573
|
this.spawnTargets = deps.spawnTargets;
|
|
522
574
|
this.projectWorkspaces = deps.projectWorkspaces;
|
|
523
575
|
this.logger = deps.logger ?? noopLogger;
|
|
576
|
+
this.normalToolAudit = deps.normalToolAudit;
|
|
577
|
+
this.managementAudit = deps.managementAudit;
|
|
578
|
+
this.managementProjectIdForCwd = deps.managementProjectIdForCwd;
|
|
524
579
|
this.now = deps.now ?? (() => new Date());
|
|
525
580
|
this.notificationStore = deps.notificationStore ?? new SessionNotificationStore();
|
|
526
581
|
this.unreadStore = deps.unreadStore ?? new SessionUnreadStore();
|
|
@@ -538,7 +593,7 @@ export class PiSessionService {
|
|
|
538
593
|
list: (parentSessionId, parentSessionFile) => this.listSubsessions(parentSessionId, parentSessionFile),
|
|
539
594
|
check: (parentSessionId, sessionId, parentSessionFile) => this.checkSubsession(parentSessionId, sessionId, parentSessionFile),
|
|
540
595
|
read: (parentSessionId, sessionId, query, parentSessionFile) => this.readSubsession(parentSessionId, sessionId, query, parentSessionFile),
|
|
541
|
-
}, deps.askUserEnabled === true ? { open: (input) => this.openAsk(input) } : undefined);
|
|
596
|
+
}, deps.askUserEnabled === true ? { open: (input) => this.openAsk(input) } : undefined, deps.workbench, this.logger, this.managementAudit, this.managementProjectIdForCwd);
|
|
542
597
|
this.createAgentRuntime = deps.createAgentRuntime ?? defaultCreateAgentRuntime;
|
|
543
598
|
this.workspaceActivity = deps.workspaceActivity;
|
|
544
599
|
this.heartbeat = setInterval(() => { this.publishHeartbeats(); }, deps.heartbeatIntervalMs ?? 2000);
|
|
@@ -2435,6 +2490,7 @@ export class PiSessionService {
|
|
|
2435
2490
|
}
|
|
2436
2491
|
active.unsubscribe = session.subscribe((event) => {
|
|
2437
2492
|
this.events.publish(session.sessionId, toClientEvent(event, session.thinkingLevel), active.eventScope);
|
|
2493
|
+
this.auditToolExecutionEvent(active, event);
|
|
2438
2494
|
this.publishActivityForEvent(session, event);
|
|
2439
2495
|
const eventType = getString(event, "type");
|
|
2440
2496
|
if (eventType === "agent_end")
|
|
@@ -2763,6 +2819,46 @@ export class PiSessionService {
|
|
|
2763
2819
|
if (this.hasActiveWork(session))
|
|
2764
2820
|
this.publishActivity(session, "正在处理", "active");
|
|
2765
2821
|
}
|
|
2822
|
+
auditToolExecutionEvent(active, event) {
|
|
2823
|
+
const eventType = getString(event, "type");
|
|
2824
|
+
if (eventType !== "tool_execution_start" && eventType !== "tool_execution_end")
|
|
2825
|
+
return;
|
|
2826
|
+
const isEnd = eventType === "tool_execution_end";
|
|
2827
|
+
const auditEvent = {
|
|
2828
|
+
sessionId: active.runtime.session.sessionId,
|
|
2829
|
+
cwd: active.runtime.cwd,
|
|
2830
|
+
toolName: getString(event, "toolName") ?? "unknown",
|
|
2831
|
+
toolCallId: getString(event, "toolCallId") ?? "unknown",
|
|
2832
|
+
status: isEnd ? (getBoolean(event, "isError") === true ? "failed" : "completed") : "started",
|
|
2833
|
+
};
|
|
2834
|
+
const managementIdentity = active.managementAuditIdentity;
|
|
2835
|
+
this.logger.info({
|
|
2836
|
+
mode: active.managementContextKey === undefined ? "normal" : "management",
|
|
2837
|
+
...(managementIdentity ?? {}),
|
|
2838
|
+
...auditEvent,
|
|
2839
|
+
}, "Pi tool execution audit");
|
|
2840
|
+
if (managementIdentity !== undefined) {
|
|
2841
|
+
try {
|
|
2842
|
+
this.managementAudit?.record({ action: "tool_execution", ...managementIdentity, ...auditEvent });
|
|
2843
|
+
}
|
|
2844
|
+
catch (error) {
|
|
2845
|
+
this.logger.info({ sessionId: auditEvent.sessionId, toolCallId: auditEvent.toolCallId, error: error instanceof Error ? error.message : String(error) }, "failed to enqueue management-mode tool audit");
|
|
2846
|
+
}
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
if (this.normalToolAudit === undefined)
|
|
2850
|
+
return;
|
|
2851
|
+
try {
|
|
2852
|
+
this.normalToolAudit.record(auditEvent);
|
|
2853
|
+
}
|
|
2854
|
+
catch (error) {
|
|
2855
|
+
this.logger.info({
|
|
2856
|
+
sessionId: auditEvent.sessionId,
|
|
2857
|
+
toolCallId: auditEvent.toolCallId,
|
|
2858
|
+
error: error instanceof Error ? error.message : String(error),
|
|
2859
|
+
}, "failed to persist ordinary-mode tool audit");
|
|
2860
|
+
}
|
|
2861
|
+
}
|
|
2766
2862
|
/**
|
|
2767
2863
|
* Build the reporter for one session construction.
|
|
2768
2864
|
*
|
|
@@ -3036,6 +3132,9 @@ export class PiSessionService {
|
|
|
3036
3132
|
unsubscribe: noop,
|
|
3037
3133
|
managementContextKey: managementContextKey(options.managementContext),
|
|
3038
3134
|
eventScope: eventScopeFromManagementContext(options.managementContext),
|
|
3135
|
+
...(options.managementContext === undefined ? {} : {
|
|
3136
|
+
managementAuditIdentity: await resolveManagementAuditIdentity(cwd, options.managementContext, this.managementProjectIdForCwd, this.logger),
|
|
3137
|
+
}),
|
|
3039
3138
|
};
|
|
3040
3139
|
let boundSession = runtime.session;
|
|
3041
3140
|
let notificationGeneration = options.notificationGeneration;
|
|
@@ -3708,4 +3807,16 @@ function finalAssistantText(messages) {
|
|
|
3708
3807
|
function isRecord(value) {
|
|
3709
3808
|
return typeof value === "object" && value !== null;
|
|
3710
3809
|
}
|
|
3810
|
+
async function resolveManagementAuditIdentity(cwd, context, resolveProjectId, logger) {
|
|
3811
|
+
let projectId = context.projects[0]?.id ?? "default-project";
|
|
3812
|
+
if (resolveProjectId !== undefined) {
|
|
3813
|
+
try {
|
|
3814
|
+
projectId = await resolveProjectId(cwd, context);
|
|
3815
|
+
}
|
|
3816
|
+
catch (error) {
|
|
3817
|
+
logger.info({ userId: context.user.id, cwd, error: error instanceof Error ? error.message : String(error) }, "failed to resolve management audit project; using the authorized default");
|
|
3818
|
+
}
|
|
3819
|
+
}
|
|
3820
|
+
return { userId: context.user.id, rootUserId: context.user.rootUserId, projectId };
|
|
3821
|
+
}
|
|
3711
3822
|
//# sourceMappingURL=piSessionService.js.map
|