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.
Files changed (117) hide show
  1. package/CHANGELOG.md +74 -14
  2. package/README.md +4 -0
  3. package/bin/codex-managed-acl.ps1 +160 -0
  4. package/bin/codex-managed-hook.mjs +127 -10
  5. package/bin/ec-safe-output.js +85 -3
  6. package/bin/install-codex-managed-hooks.mjs +384 -95
  7. package/dist/agents/baseagent-availability.js +48 -0
  8. package/dist/agents/baseagent.js +30 -2
  9. package/dist/agents/claude-runner.js +179 -240
  10. package/dist/agents/{codex-app-server-client.js → codex/app-server-client.js} +90 -20
  11. package/dist/{utils/codex-app-server-registry.js → agents/codex/app-server-registry.js} +2 -2
  12. package/dist/agents/codex/catalog.js +70 -0
  13. package/dist/agents/codex/diagnostics.js +369 -0
  14. package/dist/agents/codex-runner.js +839 -192
  15. package/dist/agents/ecagent-runner.js +27 -34
  16. package/dist/agents/gemini-runner.js +62 -8
  17. package/dist/agents/runner-types.js +1 -1
  18. package/dist/aun/aid/managed-operation.js +28 -6
  19. package/dist/aun/aid/store.js +43 -0
  20. package/dist/aun/menu-client.js +272 -0
  21. package/dist/aun/msg/group.js +65 -4
  22. package/dist/aun/msg/index.js +1 -1
  23. package/dist/aun/msg/managed-operation.js +57 -5
  24. package/dist/aun/outbox.js +56 -18
  25. package/dist/aun/rpc/client.js +7 -1
  26. package/dist/channels/aun.js +178 -77
  27. package/dist/channels/daemon.js +7 -1
  28. package/dist/channels/dingtalk.js +1 -0
  29. package/dist/channels/feishu.js +10 -4
  30. package/dist/channels/wechat.js +81 -10
  31. package/dist/channels/wecom.js +2 -1
  32. package/dist/cli/agent-command.js +29 -3
  33. package/dist/cli/agent-create.js +538 -0
  34. package/dist/cli/agent.js +26 -675
  35. package/dist/cli/aun-commands.js +108 -24
  36. package/dist/cli/command-log.js +21 -2
  37. package/dist/cli/ctl-command.js +2 -0
  38. package/dist/cli/daemon-commands.js +289 -61
  39. package/dist/cli/index.js +22 -2
  40. package/dist/cli/init.js +2 -10
  41. package/dist/cli/managed-command-guard.js +3 -0
  42. package/dist/cli/menu-client.js +95 -0
  43. package/dist/cli/model.js +23 -8
  44. package/dist/cli/restart-monitor.js +432 -8
  45. package/dist/cli/stats.js +110 -0
  46. package/dist/cli/task-context.js +12 -2
  47. package/dist/cli/trigger-command.js +9 -1
  48. package/dist/config/builtin-roles.js +2 -0
  49. package/dist/config/schema-migration.js +14 -2
  50. package/dist/core/auth/agent-delegation.js +10 -7
  51. package/dist/core/auth/auth-gateway.js +3 -2
  52. package/dist/core/auth/authorization-audit.js +75 -18
  53. package/dist/core/auth/operation-authorizer.js +63 -3
  54. package/dist/core/auth/operation-catalog.js +14 -2
  55. package/dist/core/auth/remote-access-store.js +136 -0
  56. package/dist/core/baseagent-loader.js +4 -4
  57. package/dist/core/bootstrap-messages.js +39 -18
  58. package/dist/core/bootstrap-service.js +32 -26
  59. package/dist/core/capability/capability-manager.js +8 -4
  60. package/dist/core/capability/providers/codex-capability-provider.js +1 -1
  61. package/dist/core/command/agent-control.js +7 -2
  62. package/dist/core/command/command-handler.js +128 -30
  63. package/dist/core/command/daemon-diagnostics.js +448 -0
  64. package/dist/core/command/menu-catalog.js +6 -1
  65. package/dist/core/command/menu-handler.js +410 -98
  66. package/dist/core/command/menu-protocol.js +123 -0
  67. package/dist/core/command/slash-gate.js +4 -6
  68. package/dist/core/command/slash-handler.js +199 -70
  69. package/dist/core/data-migration.js +5 -15
  70. package/dist/core/event-catalog.js +3 -0
  71. package/dist/core/handoff/runtime.js +3 -1
  72. package/dist/core/handoff/store.js +7 -1
  73. package/dist/core/message/im-renderer.js +13 -6
  74. package/dist/core/message/message-bridge.js +5 -36
  75. package/dist/core/message/message-queue.js +20 -15
  76. package/dist/core/message/message-utils.js +6 -3
  77. package/dist/core/message/response-engine.js +147 -94
  78. package/dist/core/model/catalog-service.js +310 -0
  79. package/dist/core/model/model-catalog.js +134 -334
  80. package/dist/core/model/model-diagnostics.js +4 -5
  81. package/dist/core/model/model-fallback.js +9 -16
  82. package/dist/core/model/model-permission.js +5 -2
  83. package/dist/core/permission/approval-gateway.js +183 -32
  84. package/dist/core/permission/protected-paths.js +63 -4
  85. package/dist/core/permission/sandbox-runtime.js +4 -2
  86. package/dist/core/permission/tool-policy.js +257 -31
  87. package/dist/core/runtime-lock.js +13 -8
  88. package/dist/core/session/adapters/codex-session-file-adapter.js +71 -3
  89. package/dist/core/session/session-manager.js +49 -13
  90. package/dist/core/session/session-renew.js +1 -0
  91. package/dist/index.js +214 -57
  92. package/dist/ipc.js +191 -102
  93. package/dist/paths.js +23 -1
  94. package/dist/stats/billing.js +18 -4
  95. package/dist/trigger/manager.js +3 -1
  96. package/dist/trigger/parser.js +77 -13
  97. package/dist/trigger/patch.js +104 -1
  98. package/dist/utils/atomic-write.js +26 -2
  99. package/dist/utils/cross-platform.js +436 -1
  100. package/dist/utils/ecweb-supervisor.js +11 -2
  101. package/dist/utils/ecweb-utils.js +8 -26
  102. package/dist/utils/error-utils.js +16 -2
  103. package/dist/utils/model-prices.jsonl +23 -20
  104. package/dist/utils/npm-ops.js +70 -15
  105. package/dist/utils/windows-autostart.js +1 -1
  106. package/kits/docs/evolcore/INDEX.md +1 -0
  107. package/kits/docs/evolcore/agent-create.md +13 -0
  108. package/kits/docs/evolcore/group-collaboration.md +7 -2
  109. package/kits/docs/evolcore/menu-client.md +34 -0
  110. package/kits/migrations/migrate-contact-book-v2.mjs +9 -1
  111. package/kits/migrations/migrate-role-config-v4.mjs +11 -5
  112. package/kits/migrations/migrate-role-config-v5.mjs +8 -2
  113. package/kits/templates/roles/admin.json +2 -0
  114. package/kits/templates/roles/visitor.json +1 -0
  115. package/kits/templates/system-fragments/bootstrap.md +8 -1
  116. package/package.json +16 -4
  117. package/dist/utils/codex-cli.js +0 -43
@@ -297,8 +297,16 @@ export async function groupAck(args) {
297
297
  }
298
298
  }
299
299
  export async function groupCreate(args) {
300
- const store = await getAidStore({ slotId: args.slotId ?? SLOT.cli, aunPath: args.aunPath });
301
- const conn = await loadClient(store, args.from);
300
+ return groupCreateWithDependencies(args, { getAidStore, loadClient });
301
+ }
302
+ /**
303
+ * Injectable boundary for the lifecycle call. Keeping the store/client
304
+ * construction outside the RPC makes the aidStore contract regression-testable
305
+ * without opening a real gateway connection.
306
+ */
307
+ export async function groupCreateWithDependencies(args, dependencies) {
308
+ const store = await dependencies.getAidStore({ slotId: args.slotId ?? SLOT.cli, aunPath: args.aunPath });
309
+ const conn = await dependencies.loadClient(store, args.from);
302
310
  try {
303
311
  await conn.connect({ connection_kind: 'short', short_ttl_ms: 30000, auto_reconnect: false });
304
312
  const params = { name: args.name };
@@ -313,7 +321,7 @@ export async function groupCreate(args) {
313
321
  params.description = args.description;
314
322
  if (args.joinMode)
315
323
  params.join_mode = args.joinMode;
316
- const result = await conn.createGroup(params);
324
+ const result = await conn.createGroup(params, { aidStore: store });
317
325
  return { ok: true, group: result?.group ?? result };
318
326
  }
319
327
  catch (e) {
@@ -510,7 +518,16 @@ export async function groupInvite(args) {
510
518
  try {
511
519
  for (const memberAid of args.members) {
512
520
  try {
513
- await conn.call('group.add_member', { group_id: args.groupId, aid: memberAid });
521
+ // fastaun 0.5.12 introduced targeted invitations. The current gateway
522
+ // supports this lifecycle directly; do not bypass invitee consent with
523
+ // the immediate-membership group.add_member operation.
524
+ const inviteParams = {
525
+ group_id: args.groupId,
526
+ aid: memberAid,
527
+ };
528
+ if (args.memberType !== undefined)
529
+ inviteParams.member_type = args.memberType;
530
+ await conn.call('group.invite_member', inviteParams);
514
531
  added.push(memberAid);
515
532
  }
516
533
  catch (e) {
@@ -523,6 +540,50 @@ export async function groupInvite(args) {
523
540
  await conn.close();
524
541
  }
525
542
  }
543
+ /** List pending targeted invitations for the authenticated AID. */
544
+ export async function groupInvites(args) {
545
+ const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
546
+ try {
547
+ const params = {};
548
+ if (args.page !== undefined)
549
+ params.page = args.page;
550
+ if (args.size !== undefined)
551
+ params.size = args.size;
552
+ const result = await conn.call('group.list_my_invites', params);
553
+ const invites = Array.isArray(result) ? result : Array.isArray(result?.invites)
554
+ ? result.invites
555
+ : Array.isArray(result?.items) ? result.items : [];
556
+ return {
557
+ ok: true,
558
+ invites,
559
+ page: typeof result?.page === 'number' ? result.page : args.page,
560
+ size: typeof result?.size === 'number' ? result.size : args.size,
561
+ nextCursor: typeof result?.next_cursor === 'string' ? result.next_cursor : null,
562
+ };
563
+ }
564
+ catch (e) {
565
+ return formatRpcError(e);
566
+ }
567
+ finally {
568
+ await conn.close();
569
+ }
570
+ }
571
+ async function groupInviteAction(args, method) {
572
+ const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
573
+ try {
574
+ const result = await conn.call(method, { invite_id: args.inviteId });
575
+ return { ok: true, group_id: result?.group_id ?? '', data: result };
576
+ }
577
+ catch (e) {
578
+ return formatRpcError(e);
579
+ }
580
+ finally {
581
+ await conn.close();
582
+ }
583
+ }
584
+ export const groupAcceptInvite = (args) => groupInviteAction(args, 'group.accept_invite');
585
+ export const groupRejectInvite = (args) => groupInviteAction(args, 'group.reject_invite');
586
+ export const groupRevokeInvite = (args) => groupInviteAction(args, 'group.revoke_invite');
526
587
  export async function groupKick(args) {
527
588
  const conn = await createShortConnection(args.from, { aunPath: args.aunPath, slotId: args.slotId });
528
589
  try {
@@ -1,4 +1,4 @@
1
1
  export { msgSend, msgPull, msgAck, msgRecall, msgOnline, } from './p2p.js';
2
2
  export { msgHistory, MAX_MSG_HISTORY_LIMIT } from './history.js';
3
- export { groupSend, groupPull, groupAck, groupCreate, groupInfo, groupList, groupUpdate, groupDissolve, groupSuspend, groupResume, groupJoin, groupLeave, groupInvite, groupKick, groupMembers, groupOnline, groupSetRole, groupTransferOwner, groupBan, groupUnban, groupBanlist, groupRules, groupUpdateRules, groupRulesFileGet, groupRulesFileSet, groupRulesFilePublish, } from './group.js';
3
+ export { groupSend, groupPull, groupAck, groupCreate, groupInfo, groupList, groupUpdate, groupDissolve, groupSuspend, groupResume, groupJoin, groupLeave, groupInvite, groupInvites, groupAcceptInvite, groupRejectInvite, groupRevokeInvite, groupKick, groupMembers, groupOnline, groupSetRole, groupTransferOwner, groupBan, groupUnban, groupBanlist, groupRules, groupUpdateRules, groupRulesFileGet, groupRulesFileSet, groupRulesFilePublish, } from './group.js';
4
4
  export { uploadFileAndBuildPayload, inferPayloadType, isValidPayloadType } from './upload.js';
@@ -7,7 +7,7 @@ import { isExplicitGroupId } from '../group-identity.js';
7
7
  import { isValidAid } from '../aid/validation.js';
8
8
  import { tryParseChannelKey } from '../../core/channel-loader.js';
9
9
  import { downloadGroupFsBytes } from '../group-fs-download.js';
10
- import { groupBan, groupBanlist, groupCreate, groupDissolve, groupInfo, groupInvite, groupJoin, groupKick, groupLeave, groupList, groupMembers, groupOnline, groupPull, groupAck, groupResume, groupRules, groupRulesFileGet, groupRulesFilePublish, groupRulesFileSet, groupSetRole, groupSuspend, groupTransferOwner, groupUnban, groupUpdate, groupUpdateRules, } from './group.js';
10
+ import { groupBan, groupBanlist, groupCreate, groupDissolve, groupInfo, groupInvite, groupJoin, groupKick, groupLeave, groupList, groupMembers, groupOnline, groupPull, groupAck, groupAcceptInvite, groupInvites, groupRejectInvite, groupRevokeInvite, groupResume, groupRules, groupRulesFileGet, groupRulesFilePublish, groupRulesFileSet, groupSetRole, groupSuspend, groupTransferOwner, groupUnban, groupUpdate, groupUpdateRules, } from './group.js';
11
11
  /** Rules uploaded by a managed task are carried as bounded UTF-8 content. */
12
12
  export const MAX_MANAGED_GROUP_RULES_BYTES = 4 * 1024;
13
13
  const RELATION_GROUP_READ_KINDS = new Set([
@@ -32,7 +32,7 @@ export class ManagedGroupOperationError extends Error {
32
32
  }
33
33
  const GROUP_VALUE_FLAGS = new Set([
34
34
  '--format', '--after-seq', '--limit', '--visibility', '--description', '--join-mode', '--group-id',
35
- '--name', '--page', '--size', '--mode', '--question', '--max-pending', '--message', '--answer', '--duration',
35
+ '--name', '--page', '--size', '--mode', '--question', '--max-pending', '--message', '--answer', '--duration', '--member-type',
36
36
  ]);
37
37
  function failGroup(code, reason) {
38
38
  return { ok: false, code, reason };
@@ -125,6 +125,37 @@ export function resolveManagedGroupOperation(argv) {
125
125
  if (!('positionals' in parsed))
126
126
  return parsed;
127
127
  const { positionals, values } = parsed;
128
+ if (sub === 'invites') {
129
+ const flagsError = onlyFlags(values, ['--page', '--size']);
130
+ if (flagsError)
131
+ return flagsError;
132
+ if (positionals.length !== 1)
133
+ return failGroup('INVALID_ARGUMENT', 'invites accepts exactly <from>');
134
+ const from = requiredAid(positionals[0], 'from AID');
135
+ if (typeof from !== 'string')
136
+ return from;
137
+ const page = numberFlag(values, '--page');
138
+ const size = numberFlag(values, '--size');
139
+ if (typeof page !== 'number' && page !== undefined)
140
+ return page;
141
+ if (typeof size !== 'number' && size !== undefined)
142
+ return size;
143
+ return command(sub, 'ec.group.invites', ['group', sub, from], from, { page, size });
144
+ }
145
+ if (sub === 'accept-invite' || sub === 'reject-invite' || sub === 'revoke-invite') {
146
+ const flagsError = onlyFlags(values, []);
147
+ if (flagsError)
148
+ return flagsError;
149
+ if (positionals.length !== 2)
150
+ return failGroup('INVALID_ARGUMENT', `${sub} accepts exactly <from> <invite-id>`);
151
+ const from = requiredAid(positionals[0], 'from AID');
152
+ if (typeof from !== 'string')
153
+ return from;
154
+ const inviteId = String(positionals[1]).trim();
155
+ if (!inviteId)
156
+ return failGroup('INVALID_ARGUMENT', 'missing invite-id');
157
+ return command(sub, `ec.group.${sub}`, ['group', sub, from, inviteId], from, { inviteId });
158
+ }
128
159
  if (sub === 'list') {
129
160
  const flagsError = onlyFlags(values, ['--size']);
130
161
  if (flagsError)
@@ -170,7 +201,7 @@ export function resolveManagedGroupOperation(argv) {
170
201
  if (simple.has(sub)) {
171
202
  const allowedFlags = {
172
203
  pull: ['--after-seq', '--limit'], ack: [], info: [], update: ['--name', '--description'], dissolve: [],
173
- suspend: [], resume: [], join: ['--message', '--answer'], leave: [], invite: [], kick: [],
204
+ suspend: [], resume: [], join: ['--message', '--answer'], leave: [], invite: ['--member-type'], kick: [],
174
205
  members: ['--page', '--size'], online: [], role: [], owner: [], ban: ['--duration'], unban: [],
175
206
  };
176
207
  const flagsError = onlyFlags(values, allowedFlags[sub] ?? []);
@@ -216,7 +247,11 @@ export function resolveManagedGroupOperation(argv) {
216
247
  if (typeof checked !== 'string')
217
248
  return checked;
218
249
  }
250
+ const memberType = values.get('--member-type');
251
+ if (memberType !== undefined && memberType !== 'human' && memberType !== 'ai')
252
+ return failGroup('INVALID_ARGUMENT', 'invalid --member-type');
219
253
  extra.members = members;
254
+ extra.memberType = memberType;
220
255
  }
221
256
  else if (sub === 'kick' || sub === 'unban') {
222
257
  if (positionals.length !== 3)
@@ -357,7 +392,19 @@ export async function executeManagedGroupOperation(command, rulesContent) {
357
392
  result = await groupLeave({ from: command.from, groupId: command.groupId, ...opts });
358
393
  break;
359
394
  case 'invite':
360
- result = await groupInvite({ from: command.from, groupId: command.groupId, members: command.members, ...opts });
395
+ result = await groupInvite({ from: command.from, groupId: command.groupId, members: command.members, memberType: command.memberType, ...opts });
396
+ break;
397
+ case 'invites':
398
+ result = await groupInvites({ from: command.from, page: command.page, size: command.size, ...opts });
399
+ break;
400
+ case 'accept-invite':
401
+ result = await groupAcceptInvite({ from: command.from, inviteId: command.inviteId, ...opts });
402
+ break;
403
+ case 'reject-invite':
404
+ result = await groupRejectInvite({ from: command.from, inviteId: command.inviteId, ...opts });
405
+ break;
406
+ case 'revoke-invite':
407
+ result = await groupRevokeInvite({ from: command.from, inviteId: command.inviteId, ...opts });
361
408
  break;
362
409
  case 'kick':
363
410
  result = await groupKick({ from: command.from, groupId: command.groupId, memberAid: command.memberAid, ...opts });
@@ -750,7 +797,12 @@ export function resolveManagedFsOperation(argv) {
750
797
  const destination = remoteOrError(positionals[1]);
751
798
  if (!('groupId' in destination))
752
799
  return destination;
753
- const source = positionals[0].includes(':') ? remoteOrError(positionals[0]) : undefined;
800
+ // Windows absolute paths contain a drive-letter colon, but are local
801
+ // upload sources rather than managed group references.
802
+ const isWindowsAbsolutePath = /^[A-Za-z]:[\\/]/.test(positionals[0]);
803
+ const source = positionals[0].includes(':') && !isWindowsAbsolutePath
804
+ ? remoteOrError(positionals[0])
805
+ : undefined;
754
806
  if (source && !('groupId' in source))
755
807
  return source;
756
808
  if (source && source.groupId !== destination.groupId)
@@ -1,5 +1,6 @@
1
1
  import crypto from 'crypto';
2
- import { agentActivityOutboxPath, agentOutboxPath } from '../paths.js';
2
+ import fs from 'fs';
3
+ import { agentActivityOutboxPath, agentOutboxPath, legacyAgentActivityOutboxPath, legacyAgentOutboxPath, legacyFlatOutboxPath, } from '../paths.js';
3
4
  import { atomicRead, atomicWrite } from '../utils/atomic-write.js';
4
5
  import { isDeliveryTarget, isDeliveryTargetForChannel, sameDeliveryTarget } from '../core/message/message-utils.js';
5
6
  export const DEFAULT_OUTBOX_MAX_ENTRIES = 200;
@@ -10,11 +11,13 @@ const MAX_TERMINAL_ENTRIES_PER_AID = 100;
10
11
  const QUEUE_CONFIG = {
11
12
  default: {
12
13
  file: agentOutboxPath,
14
+ legacyFiles: aid => [legacyAgentOutboxPath(aid), legacyFlatOutboxPath(aid)],
13
15
  maxEntries: DEFAULT_OUTBOX_MAX_ENTRIES,
14
16
  defaultTtl: DEFAULT_OUTBOX_TTL_MS,
15
17
  },
16
18
  activity: {
17
19
  file: agentActivityOutboxPath,
20
+ legacyFiles: aid => [legacyAgentActivityOutboxPath(aid)],
18
21
  maxEntries: ACTIVITY_OUTBOX_MAX_ENTRIES,
19
22
  defaultTtl: ACTIVITY_OUTBOX_TTL_MS,
20
23
  },
@@ -28,6 +31,55 @@ export function defaultTtl(queue = 'default') {
28
31
  function outboxFile(aid, queue = 'default') {
29
32
  return queueConfig(queue).file(aid);
30
33
  }
34
+ const migratedOutboxes = new Set();
35
+ function parseEntriesFile(file) {
36
+ try {
37
+ const content = atomicRead(file)?.trim();
38
+ if (!content)
39
+ return [];
40
+ return content.split('\n').map(line => {
41
+ try {
42
+ return JSON.parse(line);
43
+ }
44
+ catch {
45
+ return null;
46
+ }
47
+ }).filter((entry) => entry !== null);
48
+ }
49
+ catch {
50
+ return [];
51
+ }
52
+ }
53
+ /** Import old outbox layouts without deleting their recovery copies. */
54
+ function ensureOutboxMigrated(aid, queue) {
55
+ const canonical = outboxFile(aid, queue);
56
+ const key = canonical;
57
+ if (migratedOutboxes.has(key))
58
+ return;
59
+ const merged = fs.existsSync(canonical) ? parseEntriesFile(canonical) : [];
60
+ const ids = new Set(merged.map(entry => entry.id));
61
+ let changed = false;
62
+ for (const legacy of queueConfig(queue).legacyFiles(aid)) {
63
+ if (legacy === canonical || !fs.existsSync(legacy))
64
+ continue;
65
+ for (const entry of parseEntriesFile(legacy)) {
66
+ if (ids.has(entry.id))
67
+ continue;
68
+ ids.add(entry.id);
69
+ merged.push(entry);
70
+ changed = true;
71
+ }
72
+ }
73
+ if (!changed) {
74
+ migratedOutboxes.add(key);
75
+ return;
76
+ }
77
+ const content = merged.length > 0
78
+ ? merged.map(entry => JSON.stringify(entry)).join('\n') + '\n'
79
+ : '';
80
+ atomicWrite(canonical, content);
81
+ migratedOutboxes.add(key);
82
+ }
31
83
  function entryQueue(entry) {
32
84
  return entry.queue ?? 'default';
33
85
  }
@@ -50,25 +102,11 @@ export function isDeliveryForChannel(value, channelId) {
50
102
  return isDeliveryTargetForChannel(value, channelId);
51
103
  }
52
104
  function readEntries(aid, queue = 'default') {
53
- const file = outboxFile(aid, queue);
54
- try {
55
- const content = atomicRead(file)?.trim();
56
- if (!content)
57
- return [];
58
- return content.split('\n').map(line => {
59
- try {
60
- return JSON.parse(line);
61
- }
62
- catch {
63
- return null;
64
- }
65
- }).filter((e) => e !== null);
66
- }
67
- catch {
68
- return [];
69
- }
105
+ ensureOutboxMigrated(aid, queue);
106
+ return parseEntriesFile(outboxFile(aid, queue));
70
107
  }
71
108
  function writeEntries(aid, entries, queue = 'default') {
109
+ ensureOutboxMigrated(aid, queue);
72
110
  const file = outboxFile(aid, queue);
73
111
  const boundedEntries = trimFinalEntries(entries);
74
112
  const content = boundedEntries.length > 0
@@ -3,11 +3,17 @@ export async function createShortConnection(aid, opts) {
3
3
  const store = await getAidStore({ slotId: opts?.slotId ?? SLOT.cli, aunPath: opts?.aunPath });
4
4
  try {
5
5
  const client = await loadClient(store, aid);
6
- await client.connect({ connection_kind: 'short', short_ttl_ms: 30000, auto_reconnect: false });
6
+ await client.connect({ connection_kind: 'short', short_ttl_ms: opts?.shortTtlMs ?? 30000, auto_reconnect: false });
7
7
  return {
8
8
  async call(method, params) {
9
9
  return client.call(method, params);
10
10
  },
11
+ group: {
12
+ createInviteCode: (params) => client.group.createInviteCode(params),
13
+ listInviteCodes: (params) => client.group.listInviteCodes(params),
14
+ useInviteCode: (params) => client.group.useInviteCode(params),
15
+ revokeInviteCode: (params) => client.group.revokeInviteCode(params),
16
+ },
11
17
  async close() {
12
18
  try {
13
19
  await client.close();