evolcore 0.0.22 → 0.0.24
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 +74 -14
- package/README.md +4 -0
- package/bin/codex-managed-acl.ps1 +160 -0
- package/bin/codex-managed-hook.mjs +127 -10
- package/bin/ec-safe-output.js +85 -3
- package/bin/install-codex-managed-hooks.mjs +384 -95
- package/dist/agents/baseagent-availability.js +48 -0
- package/dist/agents/baseagent.js +30 -2
- package/dist/agents/claude-runner.js +179 -240
- package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +90 -20
- package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
- package/dist/agents/codex/catalog.js +70 -0
- package/dist/agents/codex/diagnostics.js +369 -0
- package/dist/agents/codex-runner.js +839 -192
- package/dist/agents/ecagent-runner.js +27 -34
- package/dist/agents/gemini-runner.js +62 -8
- package/dist/agents/runner-types.js +1 -1
- package/dist/aun/aid/managed-operation.js +28 -6
- package/dist/aun/aid/store.js +43 -0
- package/dist/aun/menu-client.js +272 -0
- package/dist/aun/msg/group.js +65 -4
- package/dist/aun/msg/index.js +1 -1
- package/dist/aun/msg/managed-operation.js +57 -5
- package/dist/aun/outbox.js +56 -18
- package/dist/aun/rpc/client.js +7 -1
- package/dist/channels/aun.js +178 -77
- package/dist/channels/daemon.js +7 -1
- package/dist/channels/dingtalk.js +1 -0
- package/dist/channels/feishu.js +10 -4
- package/dist/channels/wechat.js +81 -10
- package/dist/channels/wecom.js +2 -1
- package/dist/cli/agent-command.js +29 -3
- package/dist/cli/agent-create.js +538 -0
- package/dist/cli/agent.js +26 -675
- package/dist/cli/aun-commands.js +108 -24
- package/dist/cli/command-log.js +21 -2
- package/dist/cli/ctl-command.js +2 -0
- package/dist/cli/daemon-commands.js +289 -61
- package/dist/cli/index.js +22 -2
- package/dist/cli/init.js +2 -10
- package/dist/cli/managed-command-guard.js +3 -0
- package/dist/cli/menu-client.js +95 -0
- package/dist/cli/model.js +23 -8
- package/dist/cli/restart-monitor.js +432 -8
- package/dist/cli/stats.js +110 -0
- package/dist/cli/task-context.js +12 -2
- package/dist/cli/trigger-command.js +9 -1
- package/dist/config/builtin-roles.js +2 -0
- package/dist/config/schema-migration.js +14 -2
- package/dist/core/auth/agent-delegation.js +10 -7
- package/dist/core/auth/auth-gateway.js +3 -2
- package/dist/core/auth/authorization-audit.js +75 -18
- package/dist/core/auth/operation-authorizer.js +63 -3
- package/dist/core/auth/operation-catalog.js +14 -2
- package/dist/core/auth/remote-access-store.js +136 -0
- package/dist/core/baseagent-loader.js +4 -4
- package/dist/core/bootstrap-messages.js +39 -18
- package/dist/core/bootstrap-service.js +32 -26
- package/dist/core/capability/capability-manager.js +8 -4
- package/dist/core/capability/providers/codex-capability-provider.js +1 -1
- package/dist/core/command/agent-control.js +7 -2
- package/dist/core/command/command-handler.js +128 -30
- package/dist/core/command/daemon-diagnostics.js +448 -0
- package/dist/core/command/menu-catalog.js +6 -1
- package/dist/core/command/menu-handler.js +410 -98
- package/dist/core/command/menu-protocol.js +123 -0
- package/dist/core/command/slash-gate.js +4 -6
- package/dist/core/command/slash-handler.js +199 -70
- package/dist/core/data-migration.js +5 -15
- package/dist/core/event-catalog.js +3 -0
- package/dist/core/handoff/runtime.js +3 -1
- package/dist/core/handoff/store.js +7 -1
- package/dist/core/message/im-renderer.js +13 -6
- package/dist/core/message/message-bridge.js +5 -36
- package/dist/core/message/message-queue.js +20 -15
- package/dist/core/message/message-utils.js +6 -3
- package/dist/core/message/response-engine.js +147 -94
- package/dist/core/model/catalog-service.js +310 -0
- package/dist/core/model/model-catalog.js +134 -334
- package/dist/core/model/model-diagnostics.js +4 -5
- package/dist/core/model/model-fallback.js +9 -16
- package/dist/core/model/model-permission.js +5 -2
- package/dist/core/permission/approval-gateway.js +183 -32
- package/dist/core/permission/protected-paths.js +63 -4
- package/dist/core/permission/sandbox-runtime.js +4 -2
- package/dist/core/permission/tool-policy.js +257 -31
- package/dist/core/runtime-lock.js +13 -8
- package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
- package/dist/core/session/session-manager.js +49 -13
- package/dist/core/session/session-renew.js +1 -0
- package/dist/index.js +214 -57
- package/dist/ipc.js +191 -102
- package/dist/paths.js +23 -1
- package/dist/stats/billing.js +18 -4
- package/dist/trigger/manager.js +3 -1
- package/dist/trigger/parser.js +77 -13
- package/dist/trigger/patch.js +104 -1
- package/dist/utils/atomic-write.js +26 -2
- package/dist/utils/cross-platform.js +436 -1
- package/dist/utils/ecweb-supervisor.js +11 -2
- package/dist/utils/ecweb-utils.js +8 -26
- package/dist/utils/error-utils.js +16 -2
- package/dist/utils/model-prices.jsonl +23 -20
- package/dist/utils/npm-ops.js +70 -15
- package/dist/utils/windows-autostart.js +1 -1
- package/kits/docs/evolcore/INDEX.md +1 -0
- package/kits/docs/evolcore/agent-create.md +13 -0
- package/kits/docs/evolcore/group-collaboration.md +7 -2
- package/kits/docs/evolcore/menu-client.md +34 -0
- package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
- package/kits/migrations/migrate-role-config-v4.mjs +11 -5
- package/kits/migrations/migrate-role-config-v5.mjs +8 -2
- package/kits/templates/roles/admin.json +2 -0
- package/kits/templates/roles/visitor.json +1 -0
- package/kits/templates/system-fragments/bootstrap.md +8 -1
- package/package.json +16 -4
- package/dist/utils/codex-cli.js +0 -43
|
@@ -122,6 +122,7 @@ export class HandoffStore {
|
|
|
122
122
|
request: {
|
|
123
123
|
payload: clonePayload(input.payload),
|
|
124
124
|
encrypt: input.encrypt,
|
|
125
|
+
...(input.contextOnly ? { contextOnly: true } : {}),
|
|
125
126
|
...(input.delivery ? { delivery: input.delivery } : {}),
|
|
126
127
|
},
|
|
127
128
|
...(input.originAuthorization
|
|
@@ -129,7 +130,12 @@ export class HandoffStore {
|
|
|
129
130
|
: {}),
|
|
130
131
|
causation: normalizeCausation(input.causation),
|
|
131
132
|
return_policy: input.returnPolicy ?? 'required',
|
|
132
|
-
|
|
133
|
+
// Local-only requests are already available for the next target-session
|
|
134
|
+
// turn and must never enter the outbound dispatch queue. Keep them in
|
|
135
|
+
// target_sent while waiting for the target turn to bind the context;
|
|
136
|
+
// target_context_pending is reserved for a context-only handoff after
|
|
137
|
+
// it has been consumed by a returnPolicy=none target turn.
|
|
138
|
+
state: input.contextOnly ? 'target_sent' : 'queued',
|
|
133
139
|
target_message_id: null,
|
|
134
140
|
response_message_id: null,
|
|
135
141
|
consumed_at: null,
|
|
@@ -227,25 +227,32 @@ export class IMRenderer {
|
|
|
227
227
|
durationMs: opts.durationMs,
|
|
228
228
|
});
|
|
229
229
|
}
|
|
230
|
-
/** 发送不进入 activity/thought
|
|
231
|
-
async
|
|
230
|
+
/** 发送不进入 activity/thought 历史、也不代表执行活跃的任务级 notice。 */
|
|
231
|
+
async sendStatusNotice(message, severity = 'info', subtype, details) {
|
|
232
232
|
const payload = {
|
|
233
|
-
kind: 'status.
|
|
233
|
+
kind: 'status.notice',
|
|
234
234
|
metadata: {
|
|
235
|
-
activityType: 'progress',
|
|
236
235
|
message,
|
|
237
|
-
severity
|
|
236
|
+
severity,
|
|
238
237
|
...(subtype !== undefined && { subtype }),
|
|
239
238
|
...(details?.missingItems !== undefined && { missingItems: details.missingItems }),
|
|
239
|
+
...(details?.idleSec !== undefined && { idleSec: details.idleSec }),
|
|
240
|
+
...(details?.totalEvents !== undefined && { totalEvents: details.totalEvents }),
|
|
241
|
+
...(details?.totalToolCalls !== undefined && { totalToolCalls: details.totalToolCalls }),
|
|
242
|
+
...(details?.lastToolName !== undefined && { lastToolName: details.lastToolName }),
|
|
240
243
|
},
|
|
241
244
|
};
|
|
242
245
|
try {
|
|
243
246
|
await this.opts.send(payload);
|
|
244
247
|
}
|
|
245
248
|
catch (error) {
|
|
246
|
-
logger.warn(`[IMRenderer]
|
|
249
|
+
logger.warn(`[IMRenderer] status notice send failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
247
250
|
}
|
|
248
251
|
}
|
|
252
|
+
/** 兼容旧调用方:发送 warning 级别的任务 notice。 */
|
|
253
|
+
async sendWarningStatus(message, subtype, details) {
|
|
254
|
+
return this.sendStatusNotice(message, 'warn', subtype, details);
|
|
255
|
+
}
|
|
249
256
|
/** 添加任务生命周期边界事件,复用 activity.batch 投影路径。 */
|
|
250
257
|
addLifecycle(phase, metadata, text) {
|
|
251
258
|
const item = {
|
|
@@ -680,40 +680,6 @@ export class MessageBridge {
|
|
|
680
680
|
}
|
|
681
681
|
return d;
|
|
682
682
|
}
|
|
683
|
-
availableBaseagentsFor(channelName) {
|
|
684
|
-
const owningAgent = this.agentRegistry?.resolveByChannel(channelName);
|
|
685
|
-
if (!owningAgent)
|
|
686
|
-
return [];
|
|
687
|
-
const prefix = `${owningAgent.name}::`;
|
|
688
|
-
return this.processor.getAvailableAgents()
|
|
689
|
-
.filter(key => key.startsWith(prefix))
|
|
690
|
-
.map(key => key.slice(prefix.length));
|
|
691
|
-
}
|
|
692
|
-
async alignSessionBaseagent(channelName, session) {
|
|
693
|
-
const owningAgent = this.agentRegistry?.resolveByChannel(channelName);
|
|
694
|
-
if (!owningAgent)
|
|
695
|
-
return session;
|
|
696
|
-
const available = this.availableBaseagentsFor(channelName);
|
|
697
|
-
if (available.length === 0 || available.includes(session.baseagent))
|
|
698
|
-
return session;
|
|
699
|
-
// A topic's backend binding is fenced by SessionManager and cannot be
|
|
700
|
-
// cleared as a side effect of routing alignment. Reassigning the
|
|
701
|
-
// baseagent while leaving the old provider's agentSessionId persisted
|
|
702
|
-
// would make the new runner resume an incompatible backend. Keep the
|
|
703
|
-
// binding intact and let normal baseagent-mismatch handling report it;
|
|
704
|
-
// an explicit boundary operation must perform any future migration.
|
|
705
|
-
if (session.threadId) {
|
|
706
|
-
logger.error(`[MessageBridge] Cannot align topic to another baseagent: `
|
|
707
|
-
+ `session=${session.id} thread=${session.threadId} current=${session.baseagent} preferred=${owningAgent.baseagent}`);
|
|
708
|
-
return session;
|
|
709
|
-
}
|
|
710
|
-
const preferred = available.includes(owningAgent.baseagent)
|
|
711
|
-
? owningAgent.baseagent
|
|
712
|
-
: available[0];
|
|
713
|
-
logger.warn(`[MessageBridge] Aligning unavailable session baseagent: session=${session.id} ${session.baseagent} -> ${preferred} agent=${owningAgent.name} available=${available.join(',')}`);
|
|
714
|
-
await this.sessionManager.updateSession(session.id, { baseagent: preferred });
|
|
715
|
-
return { ...session, baseagent: preferred };
|
|
716
|
-
}
|
|
717
683
|
/**
|
|
718
684
|
* 为渠道注册消息桥梁:入站处理管线 + 出站命令响应
|
|
719
685
|
*
|
|
@@ -1140,7 +1106,6 @@ export class MessageBridge {
|
|
|
1140
1106
|
if (session.threadId && typeof this.messageQueue.reserveSessionIngress === 'function') {
|
|
1141
1107
|
releaseSessionIngress = this.messageQueue.reserveSessionIngress(session.id);
|
|
1142
1108
|
}
|
|
1143
|
-
session = await this.alignSessionBaseagent(channelName, session);
|
|
1144
1109
|
const replyToMessageId = typeof msg.replyContext?.metadata?.refMessageId === 'string'
|
|
1145
1110
|
? msg.replyContext.metadata.refMessageId
|
|
1146
1111
|
: msg.replyContext?.replyToMessageId ?? null;
|
|
@@ -1163,6 +1128,7 @@ export class MessageBridge {
|
|
|
1163
1128
|
content,
|
|
1164
1129
|
replyToMessageId,
|
|
1165
1130
|
isNewSession: !hadMainSession,
|
|
1131
|
+
currentBaseagent: owningAgent?.baseagent,
|
|
1166
1132
|
causation: inboundCausation,
|
|
1167
1133
|
});
|
|
1168
1134
|
session = renewResult.session;
|
|
@@ -1537,7 +1503,10 @@ export class MessageBridge {
|
|
|
1537
1503
|
channelId: msg.channelId,
|
|
1538
1504
|
args,
|
|
1539
1505
|
});
|
|
1540
|
-
const result = await this.cmdHandler.execMenuUpdate(this.resolveCmd(name, cmd), request.value, channel, execution.channelId, execution.subject.actorId, execution.subject.identity, execution.subject.fromControlChannel, execution.args, execution.subject
|
|
1506
|
+
const result = await this.cmdHandler.execMenuUpdate(this.resolveCmd(name, cmd), request.value, channel, execution.channelId, execution.subject.actorId, execution.subject.identity, execution.subject.fromControlChannel, execution.args, execution.subject, 'menu', {
|
|
1507
|
+
...(msg.replyContext ?? {}),
|
|
1508
|
+
...(msg.threadId ? { threadId: msg.threadId } : {}),
|
|
1509
|
+
});
|
|
1541
1510
|
if ('error' in result)
|
|
1542
1511
|
throw result;
|
|
1543
1512
|
return menuSuccess(header, result.data);
|
|
@@ -234,6 +234,7 @@ export class MessageQueue {
|
|
|
234
234
|
}
|
|
235
235
|
const tmp = `${this.dedupPath}.tmp-${process.pid}-${Date.now()}-${this.enqueueSequence}`;
|
|
236
236
|
let fd;
|
|
237
|
+
let renamed = false;
|
|
237
238
|
try {
|
|
238
239
|
fs.mkdirSync(path.dirname(this.dedupPath), { recursive: true });
|
|
239
240
|
const content = Buffer.from(JSON.stringify({
|
|
@@ -253,20 +254,22 @@ export class MessageQueue {
|
|
|
253
254
|
fs.closeSync(fd);
|
|
254
255
|
fd = undefined;
|
|
255
256
|
fs.renameSync(tmp, this.dedupPath);
|
|
256
|
-
|
|
257
|
-
try {
|
|
258
|
-
fs.fsyncSync(persistedFd);
|
|
259
|
-
}
|
|
260
|
-
finally {
|
|
261
|
-
fs.closeSync(persistedFd);
|
|
262
|
-
}
|
|
257
|
+
renamed = true;
|
|
263
258
|
if (process.platform !== 'win32') {
|
|
264
|
-
const directoryFd = fs.openSync(path.dirname(this.dedupPath), 'r');
|
|
265
259
|
try {
|
|
266
|
-
fs.
|
|
260
|
+
const directoryFd = fs.openSync(path.dirname(this.dedupPath), 'r');
|
|
261
|
+
try {
|
|
262
|
+
fs.fsyncSync(directoryFd);
|
|
263
|
+
}
|
|
264
|
+
finally {
|
|
265
|
+
fs.closeSync(directoryFd);
|
|
266
|
+
}
|
|
267
267
|
}
|
|
268
|
-
|
|
269
|
-
|
|
268
|
+
catch (error) {
|
|
269
|
+
// The file contents were already fsynced before rename. A platform
|
|
270
|
+
// that cannot fsync directory metadata must not make a committed
|
|
271
|
+
// dedup claim look uncommitted to the caller.
|
|
272
|
+
logger.warn(`[Queue] Durable dedup ledger directory fsync unavailable after commit: ${error instanceof Error ? error.message : String(error)}`);
|
|
270
273
|
}
|
|
271
274
|
}
|
|
272
275
|
return true;
|
|
@@ -279,11 +282,13 @@ export class MessageQueue {
|
|
|
279
282
|
}
|
|
280
283
|
catch { }
|
|
281
284
|
}
|
|
282
|
-
|
|
283
|
-
|
|
285
|
+
if (!renamed) {
|
|
286
|
+
try {
|
|
287
|
+
fs.unlinkSync(tmp);
|
|
288
|
+
}
|
|
289
|
+
catch { }
|
|
284
290
|
}
|
|
285
|
-
|
|
286
|
-
return false;
|
|
291
|
+
return renamed;
|
|
287
292
|
}
|
|
288
293
|
}
|
|
289
294
|
hasEnqueuedMessage(sessionKey, messageId, selfAID) {
|
|
@@ -7,8 +7,9 @@ import { renderCommandCardAsText, renderActionAsText } from '../interaction-rout
|
|
|
7
7
|
/** A legacy adapter resolved its send call without providing a structured receipt. */
|
|
8
8
|
export const LEGACY_INTERACTION_ACCEPTED = 'legacy-accepted';
|
|
9
9
|
export function isInteractionSendAccepted(result) {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
if (result === LEGACY_INTERACTION_ACCEPTED || result === 'sent')
|
|
11
|
+
return true;
|
|
12
|
+
return result !== false && (result.status === 'sent' || result.status === 'queued');
|
|
12
13
|
}
|
|
13
14
|
/**
|
|
14
15
|
* 构造出站消息信封
|
|
@@ -148,8 +149,10 @@ export async function sendInteractionPayload(adapter, envelope, interaction, fal
|
|
|
148
149
|
try {
|
|
149
150
|
const enriched = replyCtx ? withEnvelopeReplyContext(envelope, replyCtx) : envelope;
|
|
150
151
|
const receipt = await adapter.send(enriched, payload);
|
|
152
|
+
// Preserve the historical `sent` result for void-returning adapters while
|
|
153
|
+
// still accepting the newer structured SendReceipt contract.
|
|
151
154
|
if (!receipt)
|
|
152
|
-
return
|
|
155
|
+
return 'sent';
|
|
153
156
|
if (receipt.status === 'sent' && !(receipt.messageId || receipt.messages[0]?.messageId))
|
|
154
157
|
return false;
|
|
155
158
|
return receipt;
|