evolcore 0.0.31 → 0.0.33
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/CHANGELOG.md +35 -0
- package/bin/install-codex-managed-hooks.mjs +124 -37
- package/dist/agents/claude-runner.js +29 -2
- package/dist/agents/codex/app-server-client.js +3 -0
- package/dist/agents/codex/diagnostics.js +76 -44
- package/dist/agents/codex-runner.js +51 -24
- package/dist/agents/ecagent-runner.js +9 -13
- package/dist/agents/gemini-runner.js +4 -0
- package/dist/aun/aid/store.js +0 -81
- package/dist/aun/group/fs-download.js +1 -10
- package/dist/aun/group/operations.js +0 -1
- package/dist/aun/msg/history.js +1 -0
- package/dist/aun/msg/managed-operation.js +130 -32
- package/dist/aun/msg/p2p.js +0 -1
- package/dist/aun/outbox.js +50 -1
- package/dist/aun/service-proxy.js +12 -18
- package/dist/aun/storage/index.js +29 -0
- package/dist/channels/aun.js +38 -137
- package/dist/channels/daemon.js +257 -2
- package/dist/cli/agent-command.js +64 -31
- package/dist/cli/agent-create.js +43 -24
- package/dist/cli/agent.js +16 -70
- package/dist/cli/aun-commands.js +512 -32
- package/dist/cli/contact.js +8 -2
- package/dist/cli/ctl-command.js +1 -2
- package/dist/cli/daemon-commands.js +82 -13
- package/dist/cli/debug-mode.js +154 -0
- package/dist/cli/diag.js +2 -2
- package/dist/cli/handoff-command.js +18 -5
- package/dist/cli/index.js +81 -64
- package/dist/cli/init.js +2 -2
- package/dist/cli/managed-command-guard.js +5 -0
- package/dist/cli/memory-command.js +93 -12
- package/dist/cli/model.js +14 -138
- package/dist/cli/queue-command.js +51 -0
- package/dist/cli/response.js +5 -54
- package/dist/cli/session-command.js +194 -0
- package/dist/cli/skill-command.js +85 -3
- package/dist/cli/stats.js +10 -4
- package/dist/cli/task-command.js +1 -0
- package/dist/cli/task-context.js +16 -0
- package/dist/cli/thread-command.js +620 -0
- package/dist/cli/trigger-command.js +76 -50
- package/dist/config/builtin-roles.js +9 -7
- package/dist/config/config-field-policy.js +2 -3
- package/dist/config/config-manager.js +7 -2
- package/dist/config/resolved-config-op.js +3 -0
- package/dist/config-store.js +15 -0
- package/dist/core/agent-ipc-registration.js +65 -22
- package/dist/core/auth/agent-delegation.js +42 -2
- package/dist/core/auth/debug-context.js +139 -0
- package/dist/core/auth/delegation-authorization.js +1 -0
- package/dist/core/auth/operation-authorizer.js +24 -1
- package/dist/core/auth/operation-catalog.js +44 -3
- package/dist/core/background-session/session-cleanup.js +212 -0
- package/dist/core/background-session/types.js +10 -0
- package/dist/core/bootstrap-messages.js +1 -1
- package/dist/core/bootstrap-service.js +6 -3
- package/dist/core/command/command-handler.js +224 -45
- package/dist/core/command/diag-service.js +5 -1
- package/dist/core/command/memory-slash.js +6 -2
- package/dist/core/command/menu-catalog.js +48 -1
- package/dist/core/command/menu-handler.js +92 -16
- package/dist/core/command/menu-protocol.js +24 -1
- package/dist/core/command/skill-slash.js +322 -0
- package/dist/core/command/slash-gate.js +6 -4
- package/dist/core/command/slash-handler.js +193 -13
- package/dist/core/command/topic-slash.js +528 -0
- package/dist/core/evolagent-registry.js +20 -5
- package/dist/core/handoff/ipc-registration.js +38 -0
- package/dist/core/handoff/runtime.js +5 -11
- package/dist/core/handoff/store.js +5 -0
- package/dist/core/ipc-registration.js +210 -9
- package/dist/core/memory/consolidation-context.js +49 -16
- package/dist/core/memory/consolidation-ops-records.js +35 -0
- package/dist/core/memory/consolidation-queue-format.js +21 -0
- package/dist/core/memory/consolidation.js +174 -180
- package/dist/core/message/aun-ipc-sender.js +207 -8
- package/dist/core/message/im-renderer.js +149 -6
- package/dist/core/message/message-bridge.js +13 -3
- package/dist/core/message/message-log.js +1 -0
- package/dist/core/message/message-queue.js +131 -3
- package/dist/core/message/peer-mode.js +6 -1
- package/dist/core/message/response-engine.js +379 -69
- package/dist/core/message/subtask-tool-projection.js +140 -0
- package/dist/core/model/catalog-service.js +17 -12
- package/dist/core/permission/ec-command-parser.js +126 -7
- package/dist/core/permission/sandbox-runtime.js +14 -1
- package/dist/core/session/session-idle-monitor.js +249 -22
- package/dist/core/session/session-manager.js +54 -9
- package/dist/core/skill/command-parser.js +13 -0
- package/dist/core/skill/index-generator.js +4 -1
- package/dist/core/skill/startup.js +41 -0
- package/dist/core/skill/switch-resolver.js +55 -29
- package/dist/core/task/task-recovery-service.js +2 -0
- package/dist/core/task/task-resume-operation.js +11 -0
- package/dist/core/thread/command-parser.js +125 -0
- package/dist/core/thread/index.js +1 -0
- package/dist/core/thread/ipc-operation.js +95 -0
- package/dist/core/thread/thread-context-storage.js +131 -0
- package/dist/core/thread/thread-operation.js +258 -0
- package/dist/core/thread/thread-route.js +33 -0
- package/dist/core/thread/thread-service.js +777 -0
- package/dist/core/thread/types.js +1 -0
- package/dist/eck/message-renderer.js +35 -0
- package/dist/index.js +10 -7
- package/dist/ipc.js +234 -17
- package/dist/paths.js +23 -0
- package/dist/response-system/engines/v1/proactive-flow.js +169 -80
- package/dist/trigger/authorization.js +59 -29
- package/dist/trigger/feedback.js +7 -1
- package/dist/trigger/ipc-service.js +49 -35
- package/dist/trigger/parser.js +63 -1
- package/dist/trigger/script-sandbox.js +58 -77
- package/dist/trigger/validation.js +14 -0
- package/dist/utils/error-utils.js +22 -1
- package/kits/docs/AUTHORING.md +1 -1
- package/kits/docs/channels/aun.md +8 -0
- package/kits/docs/context-assembly.md +1 -0
- package/kits/docs/evolcore/INDEX.md +3 -2
- package/kits/docs/evolcore/agent-create.md +39 -28
- package/kits/docs/evolcore/agent.md +19 -4
- package/kits/docs/evolcore/ec-capabilities.md +4 -0
- package/kits/docs/evolcore/group-collaboration.md +3 -5
- package/kits/docs/evolcore/group.md +3 -4
- package/kits/docs/evolcore/memory-consolidation.md +1 -1
- package/kits/docs/evolcore/menu-exec-schema-commands.md +2 -2
- package/kits/docs/evolcore/menu-protocol.md +7 -0
- package/kits/docs/evolcore/msg.md +5 -8
- package/kits/docs/evolcore/task.md +2 -0
- package/kits/docs/evolcore/thread-chain.md +267 -0
- package/kits/docs/evolcore/trigger.md +2 -2
- package/kits/docs/prompt-loading-architecture.md +1 -0
- package/kits/eck_manifest.json +61 -26
- package/kits/eck_message_manifest.json +169 -10
- package/kits/rules/01-overview.md +0 -9
- package/kits/rules/05-venue.md +1 -1
- package/kits/rules/06-channel.md +7 -1
- package/kits/rules/07-memory-and-thread.md +202 -0
- package/kits/schemas/relation-config.schema.9.json +18 -3
- package/kits/schemas/role-config.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.1.json +6 -6
- package/kits/schemas/single-session.schema.2.json +6 -6
- package/kits/schemas/single-session.schema.3.json +6 -6
- package/kits/skills/.switches.json +12 -1
- package/kits/skills/ec-group/SKILL.md +234 -0
- package/kits/skills/ec-skill/SKILL.md +10 -1
- package/kits/skills/ec-skill/scripts/cli.mjs +15 -1
- package/kits/skills/scrapling-article-fetch/SKILL.md +128 -0
- package/kits/skills/scrapling-article-fetch/scripts/check_python_env.py +54 -0
- package/kits/skills/scrapling-article-fetch/scripts/render_markdown_reply.py +35 -0
- package/kits/skills/scrapling-article-fetch/scripts/run_pipeline.sh +16 -0
- package/kits/skills/scrapling-article-fetch/scripts/scrapling_fetch.py +344 -0
- package/kits/skills/thread-ops/SKILL.md +492 -0
- package/kits/skills/wechat-article-media-download/SKILL.md +65 -0
- package/kits/skills/wechat-article-media-download/scripts/download.py +163 -0
- package/kits/skills/wechat-article-reader/SKILL.md +97 -0
- package/kits/skills/wechat-article-reader/scripts/fetch.mjs +256 -0
- package/kits/templates/bootstrap-welcome.md +7 -7
- package/kits/templates/memory-consolidation/forget.md +5 -0
- package/kits/templates/memory-consolidation/generalize.md +5 -0
- package/kits/templates/memory-consolidation/profile.md +5 -0
- package/kits/templates/memory-consolidation/promote.md +5 -0
- package/kits/templates/message-fragments/item.md +2 -1
- package/kits/templates/message-fragments/thread-context.md +6 -0
- package/kits/templates/message-fragments/trigger-session.md +2 -0
- package/kits/templates/message-fragments/trigger-thread-check.md +2 -0
- package/kits/templates/roles/member.json +2 -0
- package/kits/templates/roles/visitor.json +2 -0
- package/kits/templates/system-fragments/bootstrap.md +66 -72
- package/kits/templates/system-fragments/channel.md +3 -6
- package/kits/templates/system-fragments/commands.md +2 -1
- package/kits/templates/system-fragments/managed-runtime.md +15 -0
- package/kits/templates/system-fragments/reply.md +3 -2
- package/kits/templates/system-fragments/session.md +5 -14
- package/package.json +3 -1
- package/kits/docs/evolcore/group-fs.md +0 -17
- package/kits/docs/venues/aun-group.md +0 -45
- package/kits/docs/venues/group.md +0 -43
|
@@ -177,10 +177,10 @@ function parseManagedPreToolUseDenial(value) {
|
|
|
177
177
|
reason = 'EvolCore PreToolUse policy denied this tool call';
|
|
178
178
|
const policyCode = /当前汇报命令(?:未通过规范解析|不符合当前会话)/.test(reason)
|
|
179
179
|
? 'proactive_send_invalid'
|
|
180
|
-
:
|
|
181
|
-
? '
|
|
182
|
-
:
|
|
183
|
-
? '
|
|
180
|
+
: /连续违规\s*\d+\s*次,任务已中断/.test(reason)
|
|
181
|
+
? 'proactive_circuit_break'
|
|
182
|
+
: /未包含意图表达,本轮只允许\s+ec\s+(?:group\s+send|msg\s+send)/.test(reason)
|
|
183
|
+
? 'proactive_intent_required'
|
|
184
184
|
: 'managed_pre_tool_use_denied';
|
|
185
185
|
return { policyCode, reason };
|
|
186
186
|
}
|
|
@@ -1954,6 +1954,8 @@ export class CodexRunner {
|
|
|
1954
1954
|
openToolCalls: new Map(),
|
|
1955
1955
|
activeSubagentThreads: new Set(),
|
|
1956
1956
|
turnCompleted: false,
|
|
1957
|
+
inputId: turn?.inputId,
|
|
1958
|
+
inputAcceptedEmitted: false,
|
|
1957
1959
|
};
|
|
1958
1960
|
const unsubscribe = appServer.onNotification(notification => {
|
|
1959
1961
|
// 仅从 turn/started 锁定权威 turnId — resume 时会有上一轮 turn 的残留通知
|
|
@@ -2204,12 +2206,21 @@ export class CodexRunner {
|
|
|
2204
2206
|
const pending = [...this.unconfirmedInterrupts.entries()].filter(([, record]) => record.sessionId === sessionId || (threadId && record.threadId === threadId));
|
|
2205
2207
|
await Promise.all(pending.map(async ([key, record]) => {
|
|
2206
2208
|
try {
|
|
2207
|
-
|
|
2208
|
-
|
|
2209
|
-
|
|
2210
|
-
|
|
2209
|
+
const response = await withInterruptDeadline(record.client.threadRead(record.threadId, false, 2_000), 'Codex interrupt verification', 2_000);
|
|
2210
|
+
const threadStatus = response.thread?.status?.type;
|
|
2211
|
+
if (threadStatus === 'idle' || threadStatus === 'notLoaded') {
|
|
2212
|
+
if (this.unconfirmedInterrupts.get(key) === record) {
|
|
2213
|
+
this.unconfirmedInterrupts.delete(key);
|
|
2214
|
+
record.unsubscribe?.();
|
|
2215
|
+
}
|
|
2216
|
+
return;
|
|
2217
|
+
}
|
|
2218
|
+
if (threadStatus !== undefined)
|
|
2219
|
+
return;
|
|
2220
|
+
const history = await withInterruptDeadline(record.client.threadRead(record.threadId, true, 2_000), 'Codex interrupt history verification', 2_000);
|
|
2221
|
+
const turn = history.thread?.turns?.find(turn => turn.id === record.turnId);
|
|
2211
2222
|
if (turn && ['completed', 'failed', 'interrupted'].includes(String(turn.status))
|
|
2212
|
-
&& !
|
|
2223
|
+
&& !history.thread?.turns?.some(turn => turn.status === 'inProgress')
|
|
2213
2224
|
&& this.unconfirmedInterrupts.get(key) === record) {
|
|
2214
2225
|
this.unconfirmedInterrupts.delete(key);
|
|
2215
2226
|
record.unsubscribe?.();
|
|
@@ -4088,18 +4099,32 @@ export class CodexRunner {
|
|
|
4088
4099
|
const requiresSandboxExpansionApproval = hasFileChangeExpansion
|
|
4089
4100
|
|| hasFilesystemPermissions
|
|
4090
4101
|
|| hasUnknownPermissions;
|
|
4102
|
+
const resolveRuntimeApproval = (decision) => {
|
|
4103
|
+
if (decision === 'deny' && permissionContext?.approvalInteractionPolicy === 'deny') {
|
|
4104
|
+
return {
|
|
4105
|
+
decision: 'deny',
|
|
4106
|
+
decisionSource: 'policy',
|
|
4107
|
+
policyCode: 'permission_mode_denied',
|
|
4108
|
+
reason: 'permission mode denied runtime approval',
|
|
4109
|
+
};
|
|
4110
|
+
}
|
|
4111
|
+
return decision;
|
|
4112
|
+
};
|
|
4091
4113
|
if (requiresSandboxExpansionApproval) {
|
|
4092
|
-
if (!this.permissionGateway || !permissionPrompt)
|
|
4093
|
-
return 'deny'
|
|
4114
|
+
if (!this.permissionGateway || !permissionPrompt) {
|
|
4115
|
+
return permissionContext?.approvalInteractionPolicy === 'deny'
|
|
4116
|
+
? resolveRuntimeApproval('deny')
|
|
4117
|
+
: 'deny';
|
|
4118
|
+
}
|
|
4094
4119
|
if (policyToolName === 'FileChange') {
|
|
4095
|
-
return this.permissionGateway.requestPermission(sessionKey, policyToolName, policyInput, permissionPrompt, this.permissionContexts.get(sessionKey), summary, reason || 'Codex 请求扩大当前命令或 turn 的文件系统权限', grantScope, undefined, { fileChangeCwd: workspacePath });
|
|
4120
|
+
return resolveRuntimeApproval(await this.permissionGateway.requestPermission(sessionKey, policyToolName, policyInput, permissionPrompt, this.permissionContexts.get(sessionKey), summary, reason || 'Codex 请求扩大当前命令或 turn 的文件系统权限', grantScope, undefined, { fileChangeCwd: workspacePath }));
|
|
4096
4121
|
}
|
|
4097
|
-
return this.permissionGateway.requestPermission(sessionKey, toolName, checkedInput, permissionPrompt, this.permissionContexts.get(sessionKey), summary, reason || 'Codex 请求扩大当前命令或 turn 的文件系统权限', grantScope);
|
|
4122
|
+
return resolveRuntimeApproval(await this.permissionGateway.requestPermission(sessionKey, toolName, checkedInput, permissionPrompt, this.permissionContexts.get(sessionKey), summary, reason || 'Codex 请求扩大当前命令或 turn 的文件系统权限', grantScope));
|
|
4098
4123
|
}
|
|
4099
4124
|
if (mode === 'request' || mode === 'bypass') {
|
|
4100
4125
|
const dangerous = await requestDangerousCommandPermission(this.permissionGateway, sessionKey, toolName, checkedInput, permissionPrompt, this.permissionContexts.get(sessionKey), grantScope, mode);
|
|
4101
4126
|
if (dangerous.matched)
|
|
4102
|
-
return dangerous.decision;
|
|
4127
|
+
return resolveRuntimeApproval(dangerous.decision);
|
|
4103
4128
|
return 'allow';
|
|
4104
4129
|
}
|
|
4105
4130
|
// Network is already part of every profile, so a defensive
|
|
@@ -4657,6 +4682,13 @@ export class CodexRunner {
|
|
|
4657
4682
|
state.turnId = turnId;
|
|
4658
4683
|
this.activeTurns.set(sessionId, { threadId: state.threadId, turnId });
|
|
4659
4684
|
}
|
|
4685
|
+
// turn/start 已落地并回执 turn/started ⇒ 用户输入已被 app-server 接受。
|
|
4686
|
+
// 此后中断不能把该输入当作「未提交」重放,否则会产生重复用户轮次。
|
|
4687
|
+
// 缺少 turn lease inputId 时宁可不报,也不要用占位值造成误判。
|
|
4688
|
+
if (!state.inputAcceptedEmitted && state.inputId) {
|
|
4689
|
+
state.inputAcceptedEmitted = true;
|
|
4690
|
+
yield { type: 'input_accepted', inputId: state.inputId };
|
|
4691
|
+
}
|
|
4660
4692
|
yield { type: 'state_changed', state: 'running' };
|
|
4661
4693
|
break;
|
|
4662
4694
|
}
|
|
@@ -4942,17 +4974,12 @@ export class CodexRunner {
|
|
|
4942
4974
|
}
|
|
4943
4975
|
: undefined;
|
|
4944
4976
|
const itemErrorText = outputTextForManagedHook(typeof item.error === 'string' ? item.error : item.error?.message);
|
|
4945
|
-
const
|
|
4946
|
-
|
|
4947
|
-
|
|
4948
|
-
const managedHookDenial = (item.status === 'failed' || item.status === 'declined' || hookErrorText)
|
|
4949
|
-
? parseManagedPreToolUseDenial([
|
|
4950
|
-
item.aggregatedOutput,
|
|
4951
|
-
item.output,
|
|
4952
|
-
item.result,
|
|
4953
|
-
hookErrorText,
|
|
4954
|
-
].filter(value => value !== undefined && value !== null).map(outputTextForManagedHook).join('\n'))
|
|
4977
|
+
const hookOutput = item.type === 'commandExecution' && item.exitCode == null && !itemErrorText
|
|
4978
|
+
&& (item.status === 'failed' || item.status === 'declined')
|
|
4979
|
+
? [item.aggregatedOutput, item.output, item.result].map(outputTextForManagedHook).find(text => /^\s*(?:Script failed\s+)?(?:Script error:\s*)?(?:Command|Tool call) blocked by PreToolUse hook\s*:/i.test(text))
|
|
4955
4980
|
: undefined;
|
|
4981
|
+
const managedHookDenial = parseManagedPreToolUseDenial(itemErrorText)
|
|
4982
|
+
?? parseManagedPreToolUseDenial(hookOutput);
|
|
4956
4983
|
const managedHookFields = !denial && managedHookDenial
|
|
4957
4984
|
? {
|
|
4958
4985
|
isError: true,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { getRunnerCatalog, catalogEfforts, assertCatalogSelectable,
|
|
1
|
+
import { getRunnerCatalog, catalogEfforts, assertCatalogSelectable, } from '../core/model/model-catalog.js';
|
|
2
2
|
// Ecagent/OpenAI API 不认识 Claude Code SDK 的窗口后缀,必须传入基础模型 ID。
|
|
3
3
|
import { stripContextWindowSuffix } from '../core/model/context-window-suffix.js';
|
|
4
4
|
import fs from 'fs';
|
|
@@ -762,15 +762,7 @@ export class EcagentRunner {
|
|
|
762
762
|
return catalog.models.map(m => m.id);
|
|
763
763
|
}
|
|
764
764
|
async getAvailableEfforts(model) {
|
|
765
|
-
|
|
766
|
-
const efforts = catalogEfforts(catalog, model, 'ecagent');
|
|
767
|
-
if (efforts.length > 0)
|
|
768
|
-
return efforts;
|
|
769
|
-
// The embedded transport advertises reasoning support for every model it
|
|
770
|
-
// constructs. Older gateways may omit reasoningLevels from /models; keep
|
|
771
|
-
// menu.options aligned with the actual runner capability in that case.
|
|
772
|
-
const entry = catalog.models.find(item => item.id === resolveCatalogModel(catalog, model));
|
|
773
|
-
return entry && entry.reasoningLevels === undefined ? [...TRANSPORT_EFFORTS.ecagent] : efforts;
|
|
765
|
+
return catalogEfforts(await this.getModelCatalog(), model, 'ecagent');
|
|
774
766
|
}
|
|
775
767
|
registerStream(key, stream) { this.activeStreams.set(key, stream); }
|
|
776
768
|
cleanupStream(key) {
|
|
@@ -917,12 +909,16 @@ export class EcagentRunner {
|
|
|
917
909
|
if (pauseResult === 'cancelled')
|
|
918
910
|
return { block: true, reason: '工具调用已取消' };
|
|
919
911
|
}
|
|
920
|
-
const decision = await this.authorizeTool(request.sessionId, request.projectPath, permissionMode, event.toolName, event.input);
|
|
912
|
+
const decision = await this.authorizeTool(request.sessionId, request.projectPath, permissionMode, event.toolName, event.input, stats.numTurns + 1);
|
|
921
913
|
return lifecycle.cancelled || signal?.aborted ? { block: true, reason: '工具调用已取消' } : decision;
|
|
922
914
|
});
|
|
923
915
|
const unsubscribe = harness.subscribe(event => this.mapHarnessEvent(queue, event, stats, model, effort));
|
|
924
916
|
queue.push({ type: 'state_changed', state: 'running' });
|
|
925
917
|
queue.push({ type: 'status', subtype: 'started', message: `ecagent is using ${modelId}` });
|
|
918
|
+
// Ecagent 输入在 harness.prompt 调用时提交,在此前报告
|
|
919
|
+
if (request.modelOverride?.turn?.inputId) {
|
|
920
|
+
queue.push({ type: 'input_accepted', inputId: request.modelOverride.turn.inputId });
|
|
921
|
+
}
|
|
926
922
|
const ecImages = request.images?.map(image => ({
|
|
927
923
|
type: 'image', data: image.data, mimeType: image.mimeType || 'image/png',
|
|
928
924
|
}));
|
|
@@ -1171,7 +1167,7 @@ export class EcagentRunner {
|
|
|
1171
1167
|
model: model.id, effort,
|
|
1172
1168
|
};
|
|
1173
1169
|
}
|
|
1174
|
-
async authorizeTool(sessionId, projectPath, mode, toolName, input) {
|
|
1170
|
+
async authorizeTool(sessionId, projectPath, mode, toolName, input, turn) {
|
|
1175
1171
|
const permissionContext = this.permissionContexts.get(sessionId);
|
|
1176
1172
|
if (mode === 'fullaccess') {
|
|
1177
1173
|
return hasTrustedFullAccessContext(permissionContext)
|
|
@@ -1216,7 +1212,7 @@ export class EcagentRunner {
|
|
|
1216
1212
|
logger.warn(`[EcagentRunner] failed to record blocked operation: session=${sessionId} tool=${toolName} code=${policyCode} error=${error instanceof Error ? error.message : String(error)}`);
|
|
1217
1213
|
}
|
|
1218
1214
|
};
|
|
1219
|
-
const policy = permissionContext?.policyHook?.(toolName, input);
|
|
1215
|
+
const policy = permissionContext?.policyHook?.(toolName, input, { turn });
|
|
1220
1216
|
if (policy?.block) {
|
|
1221
1217
|
await recordBlockedOperation(policy.policyCode ?? 'session_policy_hook');
|
|
1222
1218
|
return { block: true, reason: policy.reason || '当前会话策略拒绝此工具调用' };
|
|
@@ -514,6 +514,10 @@ export class GeminiRunner {
|
|
|
514
514
|
const pendingToolNames = new Map(); // toolId → toolName
|
|
515
515
|
const recordedDeniedToolIds = new Set();
|
|
516
516
|
const startTime = Date.now();
|
|
517
|
+
// Gemini 走 spawn + argv,输入在 spawn 时已提交;在第一个业务事件前报告
|
|
518
|
+
if (turn?.inputId) {
|
|
519
|
+
yield { type: 'input_accepted', inputId: turn.inputId };
|
|
520
|
+
}
|
|
517
521
|
const rl = createInterface({ input: child.stdout });
|
|
518
522
|
// Build async queue from readline
|
|
519
523
|
const queue = [];
|
package/dist/aun/aid/store.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
import fs from 'fs';
|
|
2
2
|
import path from 'path';
|
|
3
3
|
import { AUN_KEYSTORE_ENCRYPTION_SEED } from './encryption-seed-policy.js';
|
|
4
|
-
// fastaun uses maxPages=1 for the background tail -> forward handoff. That is
|
|
5
|
-
// useful as a latency guard, but it can leave a group backlog when no later
|
|
6
|
-
// push arrives to trigger the next page. Bound the daemon recovery pull to ten
|
|
7
|
-
// pages so a large backlog is drained without monopolizing the sync loop.
|
|
8
|
-
const FULL_GROUP_PULL_MAX_PAGES = 10;
|
|
9
|
-
const GROUP_PULL_PAGINATION_PATCH = Symbol('evolcore.groupPullPaginationPatch');
|
|
10
|
-
const RELIABLE_MESSAGE_DELIVERY_PATCH = Symbol('evolcore.reliableMessageDeliveryPatch');
|
|
11
4
|
/**
|
|
12
5
|
* Slot 命名约定(基于 fastaun 0.4.3 隔离键语义)。
|
|
13
6
|
*
|
|
@@ -77,80 +70,6 @@ export async function loadClient(store, aid) {
|
|
|
77
70
|
const { AUNClient } = await import('@agentunion/fastaun');
|
|
78
71
|
return new AUNClient(loadAid(store, aid));
|
|
79
72
|
}
|
|
80
|
-
/**
|
|
81
|
-
* Enable bounded multi-page group pulls for the long-lived daemon client.
|
|
82
|
-
*
|
|
83
|
-
* Older SDK recovery paths used `maxPages=1`; for a daemon that can strand a
|
|
84
|
-
* backlog after a tail sync. SDK 0.5.15 normally chooses a larger recovery
|
|
85
|
-
* window, but this adapter still expands an explicit single-page request and
|
|
86
|
-
* keeps older clients safe. It is isolated to the client that opts in.
|
|
87
|
-
*/
|
|
88
|
-
export function enableFullGroupPullPagination(client) {
|
|
89
|
-
const target = client;
|
|
90
|
-
if (target[GROUP_PULL_PAGINATION_PATCH])
|
|
91
|
-
return false;
|
|
92
|
-
const pull = target._pullGroupV2;
|
|
93
|
-
if (typeof pull !== 'function')
|
|
94
|
-
return false;
|
|
95
|
-
const wrappedPull = function (groupId, afterSeq, limit, opts) {
|
|
96
|
-
const expandedOpts = opts?.maxPages === 1
|
|
97
|
-
? { ...opts, maxPages: FULL_GROUP_PULL_MAX_PAGES }
|
|
98
|
-
: opts;
|
|
99
|
-
return pull.call(this, groupId, afterSeq, limit, expandedOpts);
|
|
100
|
-
};
|
|
101
|
-
Object.defineProperty(target, GROUP_PULL_PAGINATION_PATCH, {
|
|
102
|
-
configurable: false,
|
|
103
|
-
enumerable: false,
|
|
104
|
-
value: true,
|
|
105
|
-
writable: false,
|
|
106
|
-
});
|
|
107
|
-
target._pullGroupV2 = wrappedPull;
|
|
108
|
-
return true;
|
|
109
|
-
}
|
|
110
|
-
/**
|
|
111
|
-
* Make SDK pull delivery wait until EvolCore's application handlers finish.
|
|
112
|
-
*
|
|
113
|
-
* fastaun publishes message events asynchronously, while the sequence tracker
|
|
114
|
-
* is a transport watermark. A daemon restart can therefore acknowledge a
|
|
115
|
-
* pulled message before the application has durably claimed it. SDK 0.5.15
|
|
116
|
-
* split protocol and application queues; prefer its application-only flush so
|
|
117
|
-
* an unrelated protocol event cannot delay the pull commit. Older SDKs fall
|
|
118
|
-
* back to the combined flush method.
|
|
119
|
-
*/
|
|
120
|
-
export function enableReliableMessageDelivery(client) {
|
|
121
|
-
const target = client;
|
|
122
|
-
if (target[RELIABLE_MESSAGE_DELIVERY_PATCH])
|
|
123
|
-
return false;
|
|
124
|
-
const publish = target._publishAppEvent;
|
|
125
|
-
const dispatcher = target._dispatcher;
|
|
126
|
-
const flushApplication = typeof dispatcher?.flushApplication === 'function'
|
|
127
|
-
? dispatcher.flushApplication.bind(dispatcher)
|
|
128
|
-
: typeof dispatcher?.flush === 'function'
|
|
129
|
-
? dispatcher.flush.bind(dispatcher)
|
|
130
|
-
: undefined;
|
|
131
|
-
if (typeof publish !== 'function' || !flushApplication)
|
|
132
|
-
return false;
|
|
133
|
-
const wrappedPublish = async function (event, payload, source, ...rest) {
|
|
134
|
-
const result = await publish.call(this, event, payload, source, ...rest);
|
|
135
|
-
// Pull/recovery paths must not advance SeqTracker until the application
|
|
136
|
-
// handlers have completed. Push delivery has no pull commit to gate and
|
|
137
|
-
// remains asynchronous as intended by the SDK.
|
|
138
|
-
const reliable = (event === 'message.received' || event === 'group.message_created')
|
|
139
|
-
&& source !== 'push'
|
|
140
|
-
&& source !== 'inline-push';
|
|
141
|
-
if (reliable)
|
|
142
|
-
await flushApplication();
|
|
143
|
-
return result;
|
|
144
|
-
};
|
|
145
|
-
Object.defineProperty(target, RELIABLE_MESSAGE_DELIVERY_PATCH, {
|
|
146
|
-
configurable: false,
|
|
147
|
-
enumerable: false,
|
|
148
|
-
value: true,
|
|
149
|
-
writable: false,
|
|
150
|
-
});
|
|
151
|
-
target._publishAppEvent = wrappedPublish;
|
|
152
|
-
return true;
|
|
153
|
-
}
|
|
154
73
|
/** 加载本地 AID 值对象(用于离线签名/验签,无需连接)。load 失败抛 AidLoadError。 */
|
|
155
74
|
export function loadAid(store, aid) {
|
|
156
75
|
const r = store.load(aid);
|
|
@@ -39,16 +39,7 @@ function sha256Hex(bytes) {
|
|
|
39
39
|
return createHash('sha256').update(bytes).digest('hex');
|
|
40
40
|
}
|
|
41
41
|
function bearerHeaders(client) {
|
|
42
|
-
const
|
|
43
|
-
if (typeof anyClient.getAccessToken === 'function') {
|
|
44
|
-
const token = stringValue(anyClient.getAccessToken());
|
|
45
|
-
if (token)
|
|
46
|
-
return { Authorization: `Bearer ${token}` };
|
|
47
|
-
}
|
|
48
|
-
const token = stringValue(anyClient.accessToken)
|
|
49
|
-
|| stringValue(anyClient.access_token)
|
|
50
|
-
|| stringValue(anyClient._identity?.access_token)
|
|
51
|
-
|| stringValue(anyClient._sessionParams?.access_token);
|
|
42
|
+
const token = stringValue(client.getAccessToken());
|
|
52
43
|
return token ? { Authorization: `Bearer ${token}` } : undefined;
|
|
53
44
|
}
|
|
54
45
|
function stringValue(value) {
|
|
@@ -117,7 +117,6 @@ async function tryDaemonGroupSend(args, payload, runtimeContext, file) {
|
|
|
117
117
|
mentions: args.mentions,
|
|
118
118
|
encrypt: args.encrypt,
|
|
119
119
|
thread,
|
|
120
|
-
returnPolicy: args.returnPolicy,
|
|
121
120
|
originSessionId: runtimeContext.sessionId,
|
|
122
121
|
originMessageId: runtimeContext.messageId,
|
|
123
122
|
delegationToken: readDelegationCredential(),
|
package/dist/aun/msg/history.js
CHANGED
|
@@ -171,6 +171,7 @@ function readHistoryScopes(input) {
|
|
|
171
171
|
.filter(({ entry, sessionIds }) => sessionIds === undefined
|
|
172
172
|
|| (typeof entry.sessionId === 'string' && sessionIds.has(entry.sessionId)))
|
|
173
173
|
.filter(({ entry }) => input.direction === 'all' || entry.dir === input.direction)
|
|
174
|
+
.filter(({ entry }) => input.args.threadId === undefined || entry.threadId === input.args.threadId)
|
|
174
175
|
.filter(({ entry }) => input.args.after === undefined || entry.ts > input.args.after)
|
|
175
176
|
.filter(({ entry }) => input.args.before === undefined || entry.ts < input.args.before)
|
|
176
177
|
.sort((left, right) => left.entry.ts - right.entry.ts || left.scope - right.scope)
|
|
@@ -807,27 +807,30 @@ function positiveInteger(value, flag, max) {
|
|
|
807
807
|
}
|
|
808
808
|
function parseRemote(value, allowEmpty) {
|
|
809
809
|
if (!value)
|
|
810
|
-
return failFs('INVALID_ARGUMENT', 'missing remote
|
|
810
|
+
return failFs('INVALID_ARGUMENT', 'missing remote storage path');
|
|
811
811
|
const separator = value.indexOf(':');
|
|
812
812
|
if (separator <= 0)
|
|
813
813
|
return failFs('INVALID_PATH', 'remote path must use <group-aid>:<absolute-path>');
|
|
814
|
-
let
|
|
814
|
+
let targetAid;
|
|
815
815
|
const remotePath = value.slice(separator + 1);
|
|
816
|
+
const rawId = value.slice(0, separator).trim();
|
|
816
817
|
try {
|
|
817
|
-
|
|
818
|
+
targetAid = normalizeGroupAid(rawId);
|
|
818
819
|
}
|
|
819
820
|
catch (error) {
|
|
820
|
-
|
|
821
|
+
if (!isValidAid(rawId))
|
|
822
|
+
return failFs('INVALID_GROUP', `invalid group AID: ${error.message}`);
|
|
823
|
+
targetAid = rawId;
|
|
821
824
|
}
|
|
822
825
|
if (remotePath === '' && allowEmpty)
|
|
823
|
-
return {
|
|
826
|
+
return { targetAid, remotePath: '' };
|
|
824
827
|
if (!remotePath.startsWith('/') || remotePath.length > MAX_REMOTE_PATH_LENGTH || /[\u0000-\u001f\u007f]/.test(remotePath)
|
|
825
828
|
|| remotePath.split('/').includes('..')) {
|
|
826
|
-
return failFs('INVALID_PATH', 'remote
|
|
829
|
+
return failFs('INVALID_PATH', 'remote storage path must be a bounded absolute path');
|
|
827
830
|
}
|
|
828
|
-
return {
|
|
831
|
+
return { targetAid, remotePath };
|
|
829
832
|
}
|
|
830
|
-
/** Parse the daemon-owned
|
|
833
|
+
/** Parse the daemon-owned managed filesystem grammar for group or self storage. */
|
|
831
834
|
export function resolveManagedFsOperation(argv) {
|
|
832
835
|
const raw = argv[0] === 'fs' ? argv.slice(1) : argv;
|
|
833
836
|
const rawKind = raw[0];
|
|
@@ -904,11 +907,11 @@ export function resolveManagedFsOperation(argv) {
|
|
|
904
907
|
if (values.has('-m') || values.has('-x'))
|
|
905
908
|
return failFs('NOT_ALLOWED', 'getfacl does not accept ACL mutation flags');
|
|
906
909
|
const remote = remoteOrError(positionals[0]);
|
|
907
|
-
if (!('
|
|
910
|
+
if (!('targetAid' in remote))
|
|
908
911
|
return remote;
|
|
909
912
|
return { ok: true, command: {
|
|
910
913
|
kind: 'getfacl', operationId: 'ec.fs.getfacl', canonicalArgv: ['fs', 'getfacl', positionals[0], ...(actorAid ? ['--as', actorAid] : [])],
|
|
911
|
-
actorAid,
|
|
914
|
+
actorAid, targetAid: remote.targetAid, remotePath: remote.remotePath,
|
|
912
915
|
} };
|
|
913
916
|
}
|
|
914
917
|
if (rawKind === 'setfacl') {
|
|
@@ -921,17 +924,17 @@ export function resolveManagedFsOperation(argv) {
|
|
|
921
924
|
if (!('grantee' in parsedAcl))
|
|
922
925
|
return parsedAcl;
|
|
923
926
|
const remote = remoteOrError(positionals[0]);
|
|
924
|
-
if (!('
|
|
927
|
+
if (!('targetAid' in remote))
|
|
925
928
|
return remote;
|
|
926
929
|
return { ok: true, command: {
|
|
927
930
|
kind: 'setfacl', operationId: 'ec.fs.setfacl', canonicalArgv: ['fs', 'setfacl', positionals[0], modify !== undefined ? '-m' : '-x', spec, ...(actorAid ? ['--as', actorAid] : [])],
|
|
928
|
-
actorAid,
|
|
931
|
+
actorAid, targetAid: remote.targetAid, remotePath: remote.remotePath,
|
|
929
932
|
aclGrantee: parsedAcl.grantee, ...(parsedAcl.perms ? { aclPerms: parsedAcl.perms } : {}), aclRemove: remove !== undefined,
|
|
930
933
|
} };
|
|
931
934
|
}
|
|
932
935
|
if (rawKind === 'cp') {
|
|
933
936
|
const destination = remoteOrError(positionals[1]);
|
|
934
|
-
if (!('
|
|
937
|
+
if (!('targetAid' in destination))
|
|
935
938
|
return destination;
|
|
936
939
|
// Windows absolute paths contain a drive-letter colon, but are local
|
|
937
940
|
// upload sources rather than managed group references.
|
|
@@ -939,46 +942,46 @@ export function resolveManagedFsOperation(argv) {
|
|
|
939
942
|
const source = positionals[0].includes(':') && !isWindowsAbsolutePath
|
|
940
943
|
? remoteOrError(positionals[0])
|
|
941
944
|
: undefined;
|
|
942
|
-
if (source && !('
|
|
945
|
+
if (source && !('targetAid' in source))
|
|
943
946
|
return source;
|
|
944
|
-
if (source && source.
|
|
945
|
-
return failFs('INVALID_GROUP', 'managed cp cannot cross
|
|
947
|
+
if (source && source.targetAid !== destination.targetAid)
|
|
948
|
+
return failFs('INVALID_GROUP', 'managed cp cannot cross targets');
|
|
946
949
|
const kind = source ? 'copy' : 'upload';
|
|
947
950
|
return { ok: true, command: {
|
|
948
951
|
kind, operationId: `ec.fs.${kind}`, canonicalArgv: ['fs', 'cp', positionals[0], positionals[1], ...(actorAid ? ['--as', actorAid] : [])],
|
|
949
|
-
actorAid,
|
|
952
|
+
actorAid, targetAid: destination.targetAid, remotePath: destination.remotePath, destinationPath: destination.remotePath,
|
|
950
953
|
...(source ? { remoteSourcePath: source.remotePath } : { localPath: positionals[0] }), overwrite, recursive,
|
|
951
954
|
} };
|
|
952
955
|
}
|
|
953
956
|
if (rawKind === 'mv') {
|
|
954
957
|
const source = remoteOrError(positionals[0]);
|
|
955
958
|
const destination = remoteOrError(positionals[1]);
|
|
956
|
-
if (!('
|
|
959
|
+
if (!('targetAid' in source))
|
|
957
960
|
return source;
|
|
958
|
-
if (!('
|
|
961
|
+
if (!('targetAid' in destination))
|
|
959
962
|
return destination;
|
|
960
|
-
if (source.
|
|
961
|
-
return failFs('INVALID_GROUP', 'managed mv cannot cross
|
|
963
|
+
if (source.targetAid !== destination.targetAid)
|
|
964
|
+
return failFs('INVALID_GROUP', 'managed mv cannot cross targets');
|
|
962
965
|
return { ok: true, command: {
|
|
963
966
|
kind: 'move', operationId: 'ec.fs.move', canonicalArgv: ['fs', 'mv', positionals[0], positionals[1], ...(actorAid ? ['--as', actorAid] : [])],
|
|
964
|
-
actorAid,
|
|
967
|
+
actorAid, targetAid: destination.targetAid, remotePath: destination.remotePath, destinationPath: destination.remotePath,
|
|
965
968
|
remoteSourcePath: source.remotePath, overwrite,
|
|
966
969
|
} };
|
|
967
970
|
}
|
|
968
971
|
const remote = remoteOrError(positionals[0], rawKind === 'df');
|
|
969
|
-
if (!('
|
|
972
|
+
if (!('targetAid' in remote))
|
|
970
973
|
return remote;
|
|
971
974
|
if (rawKind === 'mkdir')
|
|
972
975
|
return { ok: true, command: {
|
|
973
976
|
kind: 'mkdir', operationId: 'ec.fs.mkdir', canonicalArgv: ['fs', 'mkdir', positionals[0], ...(actorAid ? ['--as', actorAid] : [])],
|
|
974
|
-
actorAid,
|
|
977
|
+
actorAid, targetAid: remote.targetAid, remotePath: remote.remotePath, parents: booleanFlags.has('-p') || booleanFlags.has('--parents'),
|
|
975
978
|
} };
|
|
976
979
|
if (rawKind === 'rm' && remote.remotePath === '/')
|
|
977
980
|
return failFs('INVALID_PATH', 'managed rm cannot target the group root');
|
|
978
981
|
if (rawKind === 'rm')
|
|
979
982
|
return { ok: true, command: {
|
|
980
983
|
kind: 'remove', operationId: 'ec.fs.remove', canonicalArgv: ['fs', 'rm', positionals[0], ...(actorAid ? ['--as', actorAid] : [])],
|
|
981
|
-
actorAid,
|
|
984
|
+
actorAid, targetAid: remote.targetAid, remotePath: remote.remotePath, recursive, overwrite,
|
|
982
985
|
} };
|
|
983
986
|
const effectiveKind = rawKind === 'stat' && !follow ? 'lstat' : rawKind;
|
|
984
987
|
const maxBytes = positiveInteger(values.get('--max-bytes'), '--max-bytes', MAX_MANAGED_FS_CAT_BYTES);
|
|
@@ -998,7 +1001,7 @@ export function resolveManagedFsOperation(argv) {
|
|
|
998
1001
|
return failFs('INVALID_ARGUMENT', '--type only supports f|d|l');
|
|
999
1002
|
return { ok: true, command: {
|
|
1000
1003
|
kind: effectiveKind, operationId: `ec.fs.${effectiveKind}`, canonicalArgv: ['fs', effectiveKind, positionals[0], ...(actorAid ? ['--as', actorAid] : [])],
|
|
1001
|
-
actorAid,
|
|
1004
|
+
actorAid, targetAid: remote.targetAid, remotePath: remote.remotePath, maxBytes, headBytes,
|
|
1002
1005
|
name: values.get('--name') ?? values.get('--pattern'), nodeType, size: values.get('--size'), mtime: values.get('--mtime'), page, pageSize,
|
|
1003
1006
|
} };
|
|
1004
1007
|
}
|
|
@@ -1055,9 +1058,104 @@ async function withClient(actorAid, fn) {
|
|
|
1055
1058
|
export async function executeManagedFsOperation(command) {
|
|
1056
1059
|
if (!command.actorAid)
|
|
1057
1060
|
throw new ManagedFsOperationError('INVALID_ACTOR', 'managed fs actor is required');
|
|
1058
|
-
|
|
1061
|
+
if (!command.storageBackend)
|
|
1062
|
+
throw new ManagedFsOperationError('INVALID_TARGET', 'managed fs storage backend must be resolved before execution');
|
|
1063
|
+
return withClient(command.actorAid, client => executeManagedFsOperationWithClient(command, client));
|
|
1064
|
+
}
|
|
1065
|
+
/** Execute against an already authenticated SDK client; used by integration tests. */
|
|
1066
|
+
export async function executeManagedFsOperationWithClient(command, client) {
|
|
1067
|
+
if (!command.actorAid)
|
|
1068
|
+
throw new ManagedFsOperationError('INVALID_ACTOR', 'managed fs actor is required');
|
|
1069
|
+
if (!command.storageBackend)
|
|
1070
|
+
throw new ManagedFsOperationError('INVALID_TARGET', 'managed fs storage backend must be resolved before execution');
|
|
1071
|
+
const ref = `${command.targetAid}:${command.remotePath}`;
|
|
1059
1072
|
try {
|
|
1060
|
-
return await
|
|
1073
|
+
return await (async () => {
|
|
1074
|
+
if (command.storageBackend === 'personal') {
|
|
1075
|
+
const owner = command.targetAid;
|
|
1076
|
+
switch (command.kind) {
|
|
1077
|
+
case 'mkdir':
|
|
1078
|
+
return { ok: true, command: 'mkdir', path: ref,
|
|
1079
|
+
result: await client.storage.mkdir(command.remotePath, { owner, parents: command.parents }) };
|
|
1080
|
+
case 'upload': {
|
|
1081
|
+
if (!command.localPath)
|
|
1082
|
+
throw new ManagedFsOperationError('INVALID_SOURCE', 'managed upload source is required');
|
|
1083
|
+
return { ok: true, command: 'upload', path: ref, localPath: command.localPath,
|
|
1084
|
+
result: await client.storage.uploadFile(command.localPath, command.remotePath, { owner, overwrite: command.overwrite }) };
|
|
1085
|
+
}
|
|
1086
|
+
case 'copy': {
|
|
1087
|
+
if (!command.remoteSourcePath)
|
|
1088
|
+
throw new ManagedFsOperationError('INVALID_SOURCE', 'managed copy source is required');
|
|
1089
|
+
const source = `${owner}:${command.remoteSourcePath}`;
|
|
1090
|
+
return { ok: true, command: 'copy', src: source, path: ref,
|
|
1091
|
+
result: await client.storage.copy(command.remoteSourcePath, command.remotePath, {
|
|
1092
|
+
owner, dstOwner: owner, overwrite: command.overwrite, recursive: command.recursive,
|
|
1093
|
+
}) };
|
|
1094
|
+
}
|
|
1095
|
+
case 'move': {
|
|
1096
|
+
if (!command.remoteSourcePath)
|
|
1097
|
+
throw new ManagedFsOperationError('INVALID_SOURCE', 'managed move source is required');
|
|
1098
|
+
const source = `${owner}:${command.remoteSourcePath}`;
|
|
1099
|
+
return { ok: true, command: 'move', src: source, path: ref,
|
|
1100
|
+
result: await client.storage.rename(command.remoteSourcePath, command.remotePath, { owner, overwrite: command.overwrite }) };
|
|
1101
|
+
}
|
|
1102
|
+
case 'remove':
|
|
1103
|
+
return { ok: true, command: 'remove', path: ref,
|
|
1104
|
+
result: await client.storage.remove(command.remotePath, { owner, recursive: command.recursive }) };
|
|
1105
|
+
case 'ls':
|
|
1106
|
+
return { ok: true, command: 'ls', path: ref,
|
|
1107
|
+
items: await client.storage.list(command.remotePath || '/', { owner }) };
|
|
1108
|
+
case 'stat':
|
|
1109
|
+
return { ok: true, command: 'stat', path: ref,
|
|
1110
|
+
node: await client.storage.stat(command.remotePath, { owner }) };
|
|
1111
|
+
case 'lstat':
|
|
1112
|
+
return { ok: true, command: 'lstat', path: ref,
|
|
1113
|
+
node: await client.storage.lstat(command.remotePath, { owner }) };
|
|
1114
|
+
case 'find':
|
|
1115
|
+
return { ok: true, command: 'find', path: ref,
|
|
1116
|
+
items: await client.storage.find(command.remotePath, {
|
|
1117
|
+
owner, name: command.name, nodeType: command.nodeType, size: command.size,
|
|
1118
|
+
mtime: command.mtime, page: command.page, pageSize: command.pageSize,
|
|
1119
|
+
}) };
|
|
1120
|
+
case 'df':
|
|
1121
|
+
return { ok: true, command: 'df', path: `${owner}:`, usage: await client.storage.df({ owner }) };
|
|
1122
|
+
case 'getfacl':
|
|
1123
|
+
return { ok: true, command: 'getfacl', path: ref, result: await client.storage.listAcl(command.remotePath, { owner }) };
|
|
1124
|
+
case 'setfacl':
|
|
1125
|
+
throw new ManagedFsOperationError('NOT_ALLOWED', 'Managed personal storage ACL changes are not supported');
|
|
1126
|
+
case 'cat': {
|
|
1127
|
+
const node = await client.storage.stat(command.remotePath, { owner });
|
|
1128
|
+
const size = numberFrom(node, ['size', 'sizeBytes', 'size_bytes']);
|
|
1129
|
+
const maxBytes = Math.min(command.maxBytes ?? MAX_MANAGED_FS_CAT_BYTES, MAX_MANAGED_FS_CAT_BYTES);
|
|
1130
|
+
if (size === undefined)
|
|
1131
|
+
throw new ManagedFsOperationError('FS_SIZE_REQUIRED', 'personal file size is required before managed cat');
|
|
1132
|
+
if (size > maxBytes)
|
|
1133
|
+
throw new ManagedFsOperationError('FS_CAT_TOO_LARGE', `managed cat is limited to ${maxBytes} bytes`);
|
|
1134
|
+
const bytes = await client.storage.readBytes(command.remotePath, { owner });
|
|
1135
|
+
if (bytes.byteLength > maxBytes)
|
|
1136
|
+
throw new ManagedFsOperationError('FS_CAT_TOO_LARGE', `managed cat is limited to ${maxBytes} bytes`);
|
|
1137
|
+
const headBytes = Math.min(command.headBytes ?? 256, MAX_MANAGED_FS_HEAD_BYTES, bytes.byteLength);
|
|
1138
|
+
if (bytes.subarray(0, Math.min(bytes.byteLength, 8192)).some(byte => byte === 0)) {
|
|
1139
|
+
return {
|
|
1140
|
+
ok: true,
|
|
1141
|
+
command: 'cat',
|
|
1142
|
+
path: ref,
|
|
1143
|
+
size: bytes.byteLength,
|
|
1144
|
+
binary: true,
|
|
1145
|
+
head: { encoding: 'base64', bytes: headBytes, data: Buffer.from(bytes.subarray(0, headBytes)).toString('base64') },
|
|
1146
|
+
};
|
|
1147
|
+
}
|
|
1148
|
+
let text;
|
|
1149
|
+
try {
|
|
1150
|
+
text = new TextDecoder('utf-8', { fatal: true }).decode(bytes);
|
|
1151
|
+
}
|
|
1152
|
+
catch {
|
|
1153
|
+
throw new ManagedFsOperationError('FS_NOT_UTF8', 'managed cat only returns UTF-8 text or a bounded binary head');
|
|
1154
|
+
}
|
|
1155
|
+
return { ok: true, command: 'cat', path: ref, size: bytes.byteLength, binary: false, text };
|
|
1156
|
+
}
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1061
1159
|
switch (command.kind) {
|
|
1062
1160
|
case 'mkdir':
|
|
1063
1161
|
return { ok: true, command: 'mkdir', path: ref, result: await client.group.fs.mkdir(ref, { parents: command.parents }) };
|
|
@@ -1070,14 +1168,14 @@ export async function executeManagedFsOperation(command) {
|
|
|
1070
1168
|
case 'copy': {
|
|
1071
1169
|
if (!command.remoteSourcePath)
|
|
1072
1170
|
throw new ManagedFsOperationError('INVALID_SOURCE', 'managed copy source is required');
|
|
1073
|
-
const source = `${command.
|
|
1171
|
+
const source = `${command.targetAid}:${command.remoteSourcePath}`;
|
|
1074
1172
|
return { ok: true, command: 'copy', src: source, path: ref,
|
|
1075
1173
|
result: await client.group.fs.cp(source, ref, { recursive: command.recursive, overwrite: command.overwrite, force: command.overwrite }) };
|
|
1076
1174
|
}
|
|
1077
1175
|
case 'move': {
|
|
1078
1176
|
if (!command.remoteSourcePath)
|
|
1079
1177
|
throw new ManagedFsOperationError('INVALID_SOURCE', 'managed move source is required');
|
|
1080
|
-
const source = `${command.
|
|
1178
|
+
const source = `${command.targetAid}:${command.remoteSourcePath}`;
|
|
1081
1179
|
return { ok: true, command: 'move', src: source, path: ref,
|
|
1082
1180
|
result: await client.group.fs.mv(source, ref, { overwrite: command.overwrite, force: command.overwrite }) };
|
|
1083
1181
|
}
|
|
@@ -1109,7 +1207,7 @@ export async function executeManagedFsOperation(command) {
|
|
|
1109
1207
|
return { ok: true, command: 'find', path: ref, items };
|
|
1110
1208
|
}
|
|
1111
1209
|
case 'df':
|
|
1112
|
-
return { ok: true, command: 'df', path: `${command.
|
|
1210
|
+
return { ok: true, command: 'df', path: `${command.targetAid}:`, usage: await client.group.fs.df(`${command.targetAid}:`) };
|
|
1113
1211
|
case 'getfacl':
|
|
1114
1212
|
return { ok: true, command: 'getfacl', path: ref, result: await client.group.fs.getAcl(ref) };
|
|
1115
1213
|
case 'setfacl': {
|
|
@@ -1152,7 +1250,7 @@ export async function executeManagedFsOperation(command) {
|
|
|
1152
1250
|
return { ok: true, command: 'cat', path: ref, size: bytes.byteLength, binary: false, text };
|
|
1153
1251
|
}
|
|
1154
1252
|
}
|
|
1155
|
-
});
|
|
1253
|
+
})();
|
|
1156
1254
|
}
|
|
1157
1255
|
catch (error) {
|
|
1158
1256
|
if (error instanceof ManagedFsOperationError)
|
package/dist/aun/msg/p2p.js
CHANGED
|
@@ -134,7 +134,6 @@ async function tryDaemonMsgSend(args, payload, runtimeContext, file) {
|
|
|
134
134
|
...(payload ? { payload } : { file }),
|
|
135
135
|
encrypt: args.encrypt,
|
|
136
136
|
thread,
|
|
137
|
-
returnPolicy: args.returnPolicy,
|
|
138
137
|
handoffContext: args.handoffContext,
|
|
139
138
|
originSessionId: runtimeContext.sessionId,
|
|
140
139
|
originMessageId: runtimeContext.messageId,
|