synomem 0.1.1 → 0.3.0
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/ARCHITECTURE.md +2 -2
- package/CHANGELOG.md +37 -0
- package/README.md +26 -13
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +379 -51
- package/dist/cli.js.map +1 -1
- package/dist/client.d.ts +131 -17
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +489 -76
- package/dist/client.js.map +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +8 -8
- package/dist/import.d.ts +356 -13
- package/dist/import.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +213 -31
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp-server.js +54 -8
- package/dist/mcp-server.js.map +1 -1
- package/dist/ports/repository.d.ts +21 -1
- package/dist/ports/repository.d.ts.map +1 -1
- package/dist/projections.d.ts +26 -1
- package/dist/projections.d.ts.map +1 -1
- package/dist/projections.js +208 -44
- package/dist/projections.js.map +1 -1
- package/dist/remote.d.ts +82 -9
- package/dist/remote.d.ts.map +1 -1
- package/dist/remote.js +53 -2
- package/dist/remote.js.map +1 -1
- package/dist/schemas.d.ts +476 -21
- package/dist/schemas.d.ts.map +1 -1
- package/dist/schemas.js +204 -26
- package/dist/schemas.js.map +1 -1
- package/dist/service.d.ts +82 -10
- package/dist/service.d.ts.map +1 -1
- package/dist/skill-install.d.ts +8 -2
- package/dist/skill-install.d.ts.map +1 -1
- package/dist/skill-install.js +6 -11
- package/dist/skill-install.js.map +1 -1
- package/dist/storage.d.ts +51 -1
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +366 -36
- package/dist/storage.js.map +1 -1
- package/dist/types.d.ts +310 -38
- package/dist/types.d.ts.map +1 -1
- package/docs/cli.md +53 -20
- package/docs/examples.md +4 -4
- package/docs/mcp.md +12 -4
- package/docs/skill.md +10 -7
- package/docs/storage-format.md +4 -4
- package/openapi/synomem-v1.yaml +24 -24
- package/package.json +1 -1
- package/skills/synomem/SKILL.md +24 -8
- package/skills/synomem/agents/openai.yaml +1 -1
- package/skills/synomem/references/examples.md +1 -1
- package/src/cli.ts +610 -95
- package/src/client.ts +587 -79
- package/src/config.ts +8 -8
- package/src/index.ts +11 -1
- package/src/mcp/index.ts +265 -30
- package/src/mcp-server.ts +58 -8
- package/src/ports/repository.ts +21 -0
- package/src/projections.ts +209 -44
- package/src/remote.ts +166 -8
- package/src/schemas.ts +211 -26
- package/src/service.ts +85 -7
- package/src/skill-install.ts +14 -17
- package/src/storage.ts +472 -34
- package/src/types.ts +332 -39
package/src/cli.ts
CHANGED
|
@@ -34,7 +34,7 @@ import type {
|
|
|
34
34
|
KudosSummary,
|
|
35
35
|
ItemListInput,
|
|
36
36
|
ItemSummary,
|
|
37
|
-
|
|
37
|
+
TaskDue,
|
|
38
38
|
} from './types.js';
|
|
39
39
|
import { packageVersion } from './version.js';
|
|
40
40
|
import type { SynomemService, SynomemServiceFactory } from './service.js';
|
|
@@ -125,11 +125,11 @@ function defaultActor(
|
|
|
125
125
|
return actor(env.SYNOMEM_ACTOR_KIND?.trim() || fallbackKind, id, env.SYNOMEM_ACTOR_NAME?.trim());
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
function
|
|
128
|
+
function taskDue(options: {
|
|
129
129
|
dueDate?: string;
|
|
130
130
|
dueAt?: string;
|
|
131
131
|
timeZone?: string;
|
|
132
|
-
}):
|
|
132
|
+
}): TaskDue | undefined {
|
|
133
133
|
if (options.dueDate && options.dueAt)
|
|
134
134
|
throw new SynomemError('INVALID_INPUT', 'Use due-date or due-at, not both.');
|
|
135
135
|
if (options.dueDate) return { kind: 'date', date: options.dueDate };
|
|
@@ -637,29 +637,73 @@ export function createCli(
|
|
|
637
637
|
.option('--yes', 'apply the displayed plan', false)
|
|
638
638
|
.option('--force', 'replace a conflicting synomem directory', false)
|
|
639
639
|
.option('--link', 'symlink to the packaged skill instead of copying it', false)
|
|
640
|
-
.option('--
|
|
641
|
-
.option('--actor-name <name>', 'display name used in MCP registration commands')
|
|
640
|
+
.option('--agent <id-or-alias>', 'bind this installation to an agent')
|
|
642
641
|
.action(
|
|
643
|
-
(
|
|
642
|
+
async (
|
|
644
643
|
options: {
|
|
645
644
|
runtime: string[];
|
|
646
645
|
yes: boolean;
|
|
647
646
|
force: boolean;
|
|
648
647
|
link: boolean;
|
|
649
|
-
|
|
650
|
-
actorName?: string;
|
|
648
|
+
agent?: string;
|
|
651
649
|
},
|
|
652
650
|
command: Command,
|
|
653
651
|
) => {
|
|
654
652
|
const global = globals(command);
|
|
653
|
+
const runtimes = skillRuntimes(options.runtime);
|
|
654
|
+
|
|
655
|
+
/*
|
|
656
|
+
* The agent is resolved BEFORE anything is written. An ambiguous or
|
|
657
|
+
* unknown name then stops the command with a name to fix, rather than
|
|
658
|
+
* leaving a skill installed and pointed at an agent that does not
|
|
659
|
+
* exist.
|
|
660
|
+
*/
|
|
661
|
+
let agentId: string | undefined;
|
|
662
|
+
if (options.agent) {
|
|
663
|
+
agentId = await withClient(
|
|
664
|
+
global.home,
|
|
665
|
+
defaultActor(env, 'system', 'cli'),
|
|
666
|
+
async (client) => {
|
|
667
|
+
const resolution = await client.agents.resolve(options.agent!);
|
|
668
|
+
if (!resolution.match) {
|
|
669
|
+
throw new SynomemError(
|
|
670
|
+
'AGENT_NOT_FOUND',
|
|
671
|
+
resolution.candidates.length
|
|
672
|
+
? `"${options.agent}" matches ${resolution.candidates.length} agents: ${resolution.candidates
|
|
673
|
+
.map((candidate) => candidate.id)
|
|
674
|
+
.join(', ')}. Name one of them.`
|
|
675
|
+
: `Unknown agent: ${options.agent}`,
|
|
676
|
+
);
|
|
677
|
+
}
|
|
678
|
+
return resolution.match.id;
|
|
679
|
+
},
|
|
680
|
+
);
|
|
681
|
+
}
|
|
682
|
+
|
|
655
683
|
const result = installSkill({
|
|
656
|
-
runtimes:
|
|
684
|
+
...(runtimes ? { runtimes } : {}),
|
|
657
685
|
apply: options.yes,
|
|
658
686
|
force: options.force,
|
|
659
687
|
link: options.link,
|
|
660
|
-
|
|
661
|
-
actorName: options.actorName,
|
|
688
|
+
...(agentId ? { agentId } : {}),
|
|
662
689
|
});
|
|
690
|
+
|
|
691
|
+
// Bindings follow what was actually installed, and only on a real run:
|
|
692
|
+
// a dry run must not claim a binding it did not make, and a runtime
|
|
693
|
+
// whose harness is not present here is not somewhere this agent runs.
|
|
694
|
+
if (agentId && options.yes) {
|
|
695
|
+
const installed = result.locations
|
|
696
|
+
.filter((location) => location.state !== 'unavailable')
|
|
697
|
+
.map((location) => location.runtime);
|
|
698
|
+
if (installed.length) {
|
|
699
|
+
await withClient(global.home, defaultActor(env, 'system', 'cli'), async (client) => {
|
|
700
|
+
for (const runtime of installed) {
|
|
701
|
+
await client.agents.bindRuntime({ agentId, runtime });
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
663
707
|
output(io, global.json, result, formatSkillResult(result, 'install'));
|
|
664
708
|
},
|
|
665
709
|
);
|
|
@@ -668,19 +712,15 @@ export function createCli(
|
|
|
668
712
|
.command('status')
|
|
669
713
|
.description('Show installed, stale, missing, or conflicting skill copies')
|
|
670
714
|
.option('--runtime <runtime>', `${skillRuntimeHelp} (repeatable)`, collect, [])
|
|
671
|
-
.option('--
|
|
672
|
-
.
|
|
673
|
-
|
|
674
|
-
|
|
675
|
-
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
});
|
|
681
|
-
output(io, global.json, result, formatSkillResult(result, 'status'));
|
|
682
|
-
},
|
|
683
|
-
);
|
|
715
|
+
.option('--agent <id>', 'print the registration command for this agent')
|
|
716
|
+
.action((options: { runtime: string[]; agent?: string }, command: Command) => {
|
|
717
|
+
const global = globals(command);
|
|
718
|
+
const result = skillStatus({
|
|
719
|
+
runtimes: skillRuntimes(options.runtime),
|
|
720
|
+
...(options.agent ? { agentId: options.agent } : {}),
|
|
721
|
+
});
|
|
722
|
+
output(io, global.json, result, formatSkillResult(result, 'status'));
|
|
723
|
+
});
|
|
684
724
|
|
|
685
725
|
skillCommand
|
|
686
726
|
.command('uninstall')
|
|
@@ -762,6 +802,293 @@ export function createCli(
|
|
|
762
802
|
},
|
|
763
803
|
);
|
|
764
804
|
|
|
805
|
+
agentCommand
|
|
806
|
+
.command('resolve <name>')
|
|
807
|
+
.description('Resolve a name or alias to one agent, or list the candidates')
|
|
808
|
+
.action(async (name: string, _options, command: Command) => {
|
|
809
|
+
const global = globals(command);
|
|
810
|
+
const resolution = await withClient(
|
|
811
|
+
global.home,
|
|
812
|
+
defaultActor(env, 'system', 'cli'),
|
|
813
|
+
(client) => client.agents.resolve(name),
|
|
814
|
+
);
|
|
815
|
+
// An ambiguous name is a question, not a failure: exit zero and show the
|
|
816
|
+
// candidates so the caller can pick one.
|
|
817
|
+
const human = resolution.match
|
|
818
|
+
? `${resolution.match.displayName} (${resolution.match.id})`
|
|
819
|
+
: resolution.candidates.length
|
|
820
|
+
? `"${resolution.query}" is ambiguous. Candidates:\n${resolution.candidates
|
|
821
|
+
.map((profile) => ` ${profile.id} ${profile.displayName}`)
|
|
822
|
+
.join('\n')}`
|
|
823
|
+
: `No agent answers to "${resolution.query}".`;
|
|
824
|
+
output(io, global.json, resolution, human);
|
|
825
|
+
});
|
|
826
|
+
|
|
827
|
+
agentCommand
|
|
828
|
+
.command('directory')
|
|
829
|
+
.description('List agents with their runtime bindings')
|
|
830
|
+
.action(async (_options, command: Command) => {
|
|
831
|
+
const global = globals(command);
|
|
832
|
+
const entries = await withClient(global.home, defaultActor(env, 'system', 'cli'), (client) =>
|
|
833
|
+
client.agents.directory(),
|
|
834
|
+
);
|
|
835
|
+
const human = entries.length
|
|
836
|
+
? entries
|
|
837
|
+
.map((entry) => {
|
|
838
|
+
const runtimes = entry.runtimeBindings.length
|
|
839
|
+
? entry.runtimeBindings
|
|
840
|
+
.map(
|
|
841
|
+
(binding) =>
|
|
842
|
+
` ${binding.runtime}${binding.profile ? `/${binding.profile}` : ''}` +
|
|
843
|
+
// Last-seen is advisory, so it is labelled as an
|
|
844
|
+
// observation rather than a status.
|
|
845
|
+
`${binding.lastSeenAt ? ` last seen ${binding.lastSeenAt}` : ' not yet seen'}`,
|
|
846
|
+
)
|
|
847
|
+
.join('\n')
|
|
848
|
+
: ' no runtime bindings';
|
|
849
|
+
return `${entry.profile.id} ${entry.profile.displayName}\n${runtimes}`;
|
|
850
|
+
})
|
|
851
|
+
.join('\n')
|
|
852
|
+
: 'No agents configured.';
|
|
853
|
+
output(io, global.json, { entries }, human);
|
|
854
|
+
});
|
|
855
|
+
|
|
856
|
+
const runtimeCommand = agentCommand.command('runtime').description('Record where an agent runs');
|
|
857
|
+
|
|
858
|
+
runtimeCommand
|
|
859
|
+
.command('bind <agent>')
|
|
860
|
+
.description('Bind an agent to a runtime')
|
|
861
|
+
.requiredOption('--runtime <name>', 'runtime family, e.g. claude-code')
|
|
862
|
+
.option('--profile <name>', 'named configuration within the runtime')
|
|
863
|
+
.option('--installation <id>', 'hosted installation this binding belongs to')
|
|
864
|
+
.action(
|
|
865
|
+
async (
|
|
866
|
+
agent: string,
|
|
867
|
+
options: { runtime: string; profile?: string; installation?: string },
|
|
868
|
+
command: Command,
|
|
869
|
+
) => {
|
|
870
|
+
const global = globals(command);
|
|
871
|
+
const binding = await withClient(
|
|
872
|
+
global.home,
|
|
873
|
+
defaultActor(env, 'system', 'cli'),
|
|
874
|
+
(client) =>
|
|
875
|
+
client.agents.bindRuntime({
|
|
876
|
+
agentId: agent,
|
|
877
|
+
runtime: options.runtime,
|
|
878
|
+
...(options.profile ? { profile: options.profile } : {}),
|
|
879
|
+
...(options.installation ? { installationId: options.installation } : {}),
|
|
880
|
+
}),
|
|
881
|
+
);
|
|
882
|
+
output(
|
|
883
|
+
io,
|
|
884
|
+
global.json,
|
|
885
|
+
binding,
|
|
886
|
+
`Bound ${binding.agentId} to ${binding.runtime}${binding.profile ? `/${binding.profile}` : ''} (${binding.id})`,
|
|
887
|
+
);
|
|
888
|
+
},
|
|
889
|
+
);
|
|
890
|
+
|
|
891
|
+
runtimeCommand
|
|
892
|
+
.command('list <agent>')
|
|
893
|
+
.description('List an agent runtime bindings')
|
|
894
|
+
.action(async (agent: string, _options, command: Command) => {
|
|
895
|
+
const global = globals(command);
|
|
896
|
+
const bindings = await withClient(global.home, defaultActor(env, 'system', 'cli'), (client) =>
|
|
897
|
+
client.agents.bindings(agent),
|
|
898
|
+
);
|
|
899
|
+
const human = bindings.length
|
|
900
|
+
? bindings
|
|
901
|
+
.map(
|
|
902
|
+
(binding) =>
|
|
903
|
+
`${binding.id} ${binding.runtime}${binding.profile ? `/${binding.profile}` : ''} bound ${binding.boundAt}`,
|
|
904
|
+
)
|
|
905
|
+
.join('\n')
|
|
906
|
+
: 'No runtime bindings.';
|
|
907
|
+
output(io, global.json, { bindings }, human);
|
|
908
|
+
});
|
|
909
|
+
|
|
910
|
+
runtimeCommand
|
|
911
|
+
.command('unbind <binding-id>')
|
|
912
|
+
.description('Remove a runtime binding')
|
|
913
|
+
.action(async (bindingId: string, _options, command: Command) => {
|
|
914
|
+
const global = globals(command);
|
|
915
|
+
const removed = await withClient(global.home, defaultActor(env, 'system', 'cli'), (client) =>
|
|
916
|
+
client.agents.unbindRuntime(bindingId),
|
|
917
|
+
);
|
|
918
|
+
output(
|
|
919
|
+
io,
|
|
920
|
+
global.json,
|
|
921
|
+
{ removed },
|
|
922
|
+
removed ? `Removed binding ${bindingId}.` : `No binding ${bindingId}.`,
|
|
923
|
+
);
|
|
924
|
+
});
|
|
925
|
+
|
|
926
|
+
const postCommand = program.command('post').description('Publish to everyone in the workspace');
|
|
927
|
+
|
|
928
|
+
postCommand
|
|
929
|
+
.command('create')
|
|
930
|
+
.description('Publish a post the whole workspace can read')
|
|
931
|
+
.requiredOption('--as <actor-id>')
|
|
932
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
933
|
+
.requiredOption('--title <title>')
|
|
934
|
+
.requiredOption('--body <body>')
|
|
935
|
+
.option('--tag <tag>', 'repeatable', collect, [])
|
|
936
|
+
.option('--reply-to <post-id>')
|
|
937
|
+
.action(
|
|
938
|
+
async (
|
|
939
|
+
options: {
|
|
940
|
+
as: string;
|
|
941
|
+
actorKind: string;
|
|
942
|
+
title: string;
|
|
943
|
+
body: string;
|
|
944
|
+
tag: string[];
|
|
945
|
+
replyTo?: string;
|
|
946
|
+
},
|
|
947
|
+
command: Command,
|
|
948
|
+
) => {
|
|
949
|
+
const global = globals(command);
|
|
950
|
+
const result = await withClient(
|
|
951
|
+
global.home,
|
|
952
|
+
actor(options.actorKind, options.as),
|
|
953
|
+
(client) =>
|
|
954
|
+
client.posts.create({
|
|
955
|
+
title: options.title,
|
|
956
|
+
body: options.body,
|
|
957
|
+
...(options.tag.length ? { tags: options.tag } : {}),
|
|
958
|
+
...(options.replyTo ? { replyTo: options.replyTo } : {}),
|
|
959
|
+
}),
|
|
960
|
+
);
|
|
961
|
+
output(io, global.json, result, `Published ${result.record.event.id}`);
|
|
962
|
+
},
|
|
963
|
+
);
|
|
964
|
+
|
|
965
|
+
postCommand
|
|
966
|
+
.command('list')
|
|
967
|
+
.description('List posts in this workspace')
|
|
968
|
+
.requiredOption('--as <actor-id>')
|
|
969
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
970
|
+
.option('--limit <n>', 'default 10, maximum 50')
|
|
971
|
+
.action(
|
|
972
|
+
async (options: { as: string; actorKind: string; limit?: string }, command: Command) => {
|
|
973
|
+
const global = globals(command);
|
|
974
|
+
const page = await withClient(global.home, actor(options.actorKind, options.as), (client) =>
|
|
975
|
+
client.posts.list(options.limit ? { limit: Number(options.limit) } : {}),
|
|
976
|
+
);
|
|
977
|
+
const human = page.items.length
|
|
978
|
+
? page.items.map((item) => `${item.id} ${item.title}`).join('\n')
|
|
979
|
+
: 'No posts yet.';
|
|
980
|
+
output(io, global.json, page, human);
|
|
981
|
+
},
|
|
982
|
+
);
|
|
983
|
+
|
|
984
|
+
postCommand
|
|
985
|
+
.command('show <post-id>')
|
|
986
|
+
.description('Show one post with its acknowledgements')
|
|
987
|
+
.requiredOption('--as <actor-id>')
|
|
988
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
989
|
+
.action(
|
|
990
|
+
async (postId: string, options: { as: string; actorKind: string }, command: Command) => {
|
|
991
|
+
const global = globals(command);
|
|
992
|
+
const record = await withClient(
|
|
993
|
+
global.home,
|
|
994
|
+
actor(options.actorKind, options.as),
|
|
995
|
+
(client) => client.posts.get(postId),
|
|
996
|
+
);
|
|
997
|
+
const acks = record.acknowledgments.length
|
|
998
|
+
? record.acknowledgments
|
|
999
|
+
.map((entry) => ` ${entry.actor.id}${entry.note ? ` — ${entry.note}` : ''}`)
|
|
1000
|
+
.join('\n')
|
|
1001
|
+
: ' none yet';
|
|
1002
|
+
output(
|
|
1003
|
+
io,
|
|
1004
|
+
global.json,
|
|
1005
|
+
record,
|
|
1006
|
+
`${record.title}\n\n${record.body}\n\nAcknowledged by:\n${acks}`,
|
|
1007
|
+
);
|
|
1008
|
+
},
|
|
1009
|
+
);
|
|
1010
|
+
|
|
1011
|
+
postCommand
|
|
1012
|
+
.command('acknowledge <post-id>')
|
|
1013
|
+
.description('Say you have seen a post')
|
|
1014
|
+
.requiredOption('--as <actor-id>')
|
|
1015
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1016
|
+
.option('--note <text>', 'optional context for the author')
|
|
1017
|
+
.action(
|
|
1018
|
+
async (
|
|
1019
|
+
postId: string,
|
|
1020
|
+
options: { as: string; actorKind: string; note?: string },
|
|
1021
|
+
command: Command,
|
|
1022
|
+
) => {
|
|
1023
|
+
const global = globals(command);
|
|
1024
|
+
const record = await withClient(
|
|
1025
|
+
global.home,
|
|
1026
|
+
actor(options.actorKind, options.as),
|
|
1027
|
+
(client) =>
|
|
1028
|
+
client.posts.acknowledge({
|
|
1029
|
+
postId,
|
|
1030
|
+
...(options.note ? { note: options.note } : {}),
|
|
1031
|
+
}),
|
|
1032
|
+
);
|
|
1033
|
+
output(io, global.json, record, `Acknowledged ${postId}`);
|
|
1034
|
+
},
|
|
1035
|
+
);
|
|
1036
|
+
|
|
1037
|
+
postCommand
|
|
1038
|
+
.command('roster <post-id>')
|
|
1039
|
+
.description('Who has acknowledged a post, and who has not')
|
|
1040
|
+
.requiredOption('--as <actor-id>')
|
|
1041
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1042
|
+
.action(
|
|
1043
|
+
async (postId: string, options: { as: string; actorKind: string }, command: Command) => {
|
|
1044
|
+
const global = globals(command);
|
|
1045
|
+
const roster = await withClient(
|
|
1046
|
+
global.home,
|
|
1047
|
+
actor(options.actorKind, options.as),
|
|
1048
|
+
(client) => client.posts.roster(postId),
|
|
1049
|
+
);
|
|
1050
|
+
// "Outstanding" means no acknowledgement recorded — never that somebody
|
|
1051
|
+
// has not read it, which this cannot know.
|
|
1052
|
+
const lines = [
|
|
1053
|
+
`Acknowledged (${roster.acknowledged.length}):`,
|
|
1054
|
+
...(roster.acknowledged.length
|
|
1055
|
+
? roster.acknowledged.map((entry) => ` ${entry.actor.id}`)
|
|
1056
|
+
: [' none yet']),
|
|
1057
|
+
`No acknowledgement recorded (${roster.outstanding.length}):`,
|
|
1058
|
+
...(roster.outstanding.length
|
|
1059
|
+
? roster.outstanding.map((entry) => ` ${entry.id}`)
|
|
1060
|
+
: [' none']),
|
|
1061
|
+
];
|
|
1062
|
+
if (roster.joinedSince > 0) {
|
|
1063
|
+
lines.push(`${roster.joinedSince} agent(s) joined after this was posted.`);
|
|
1064
|
+
}
|
|
1065
|
+
output(io, global.json, roster, lines.join('\n'));
|
|
1066
|
+
},
|
|
1067
|
+
);
|
|
1068
|
+
|
|
1069
|
+
postCommand
|
|
1070
|
+
.command('archive <post-id>')
|
|
1071
|
+
.description('Archive a post you wrote')
|
|
1072
|
+
.requiredOption('--as <actor-id>')
|
|
1073
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1074
|
+
.option('--reason <text>')
|
|
1075
|
+
.action(
|
|
1076
|
+
async (
|
|
1077
|
+
postId: string,
|
|
1078
|
+
options: { as: string; actorKind: string; reason?: string },
|
|
1079
|
+
command: Command,
|
|
1080
|
+
) => {
|
|
1081
|
+
const global = globals(command);
|
|
1082
|
+
const record = await withClient(
|
|
1083
|
+
global.home,
|
|
1084
|
+
actor(options.actorKind, options.as),
|
|
1085
|
+
(client) =>
|
|
1086
|
+
client.posts.archive({ postId, ...(options.reason ? { reason: options.reason } : {}) }),
|
|
1087
|
+
);
|
|
1088
|
+
output(io, global.json, record, `Archived ${postId}`);
|
|
1089
|
+
},
|
|
1090
|
+
);
|
|
1091
|
+
|
|
765
1092
|
const kudosCommand = program.command('kudos').description('Give and manage agent recognition');
|
|
766
1093
|
|
|
767
1094
|
kudosCommand
|
|
@@ -819,7 +1146,7 @@ export function createCli(
|
|
|
819
1146
|
|
|
820
1147
|
program
|
|
821
1148
|
.command('inbox [agent]')
|
|
822
|
-
.description('Show pending kudos, memos, and
|
|
1149
|
+
.description('Show pending kudos, memos, and tasks for an agent')
|
|
823
1150
|
.option('--as <agent-id>', 'defaults to the positional agent')
|
|
824
1151
|
.option('--limit <number>', 'maximum results (default 10, maximum 50)', '10')
|
|
825
1152
|
.option('--cursor <cursor>', 'opaque cursor returned by the previous page')
|
|
@@ -876,7 +1203,7 @@ export function createCli(
|
|
|
876
1203
|
program
|
|
877
1204
|
.command('list')
|
|
878
1205
|
.description('List compact summaries across all record types')
|
|
879
|
-
.option('--kind <kind>', 'kudos, memo, note, or
|
|
1206
|
+
.option('--kind <kind>', 'kudos, memo, note, or task (repeatable)', collect, [])
|
|
880
1207
|
.option('--participant <agent>')
|
|
881
1208
|
.option('--actor <id>')
|
|
882
1209
|
.option('--tag <tag>')
|
|
@@ -1194,8 +1521,163 @@ export function createCli(
|
|
|
1194
1521
|
},
|
|
1195
1522
|
);
|
|
1196
1523
|
|
|
1197
|
-
const todoCommand = program
|
|
1524
|
+
const todoCommand = program
|
|
1525
|
+
.command('todo')
|
|
1526
|
+
.description('Create and manage your own private reminders');
|
|
1527
|
+
todoCommand
|
|
1528
|
+
.command('create')
|
|
1529
|
+
.requiredOption('--as <actor-id>')
|
|
1530
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1531
|
+
.requiredOption('--title <title>')
|
|
1532
|
+
.option('--details <text>', 'private working detail')
|
|
1533
|
+
.option('--priority <number>', '1 highest, 4 lowest', '3')
|
|
1534
|
+
.option('--due-date <date>')
|
|
1535
|
+
.option('--due-at <datetime>')
|
|
1536
|
+
.option('--time-zone <iana-zone>')
|
|
1537
|
+
.option('--tag <tag>', 'tag (repeatable)', collect, [])
|
|
1538
|
+
.option('--idempotency-key <key>')
|
|
1539
|
+
.action(
|
|
1540
|
+
async (
|
|
1541
|
+
options: {
|
|
1542
|
+
as: string;
|
|
1543
|
+
actorKind: string;
|
|
1544
|
+
title: string;
|
|
1545
|
+
details?: string;
|
|
1546
|
+
priority: string;
|
|
1547
|
+
dueDate?: string;
|
|
1548
|
+
dueAt?: string;
|
|
1549
|
+
timeZone?: string;
|
|
1550
|
+
tag: string[];
|
|
1551
|
+
idempotencyKey?: string;
|
|
1552
|
+
},
|
|
1553
|
+
command: Command,
|
|
1554
|
+
) => {
|
|
1555
|
+
const global = globals(command);
|
|
1556
|
+
const result = await withClient(
|
|
1557
|
+
global.home,
|
|
1558
|
+
actor(options.actorKind, options.as),
|
|
1559
|
+
(client) =>
|
|
1560
|
+
client.todos.create({
|
|
1561
|
+
title: options.title,
|
|
1562
|
+
...(options.details ? { details: options.details } : {}),
|
|
1563
|
+
priority: Number(options.priority) as 1 | 2 | 3 | 4,
|
|
1564
|
+
...((due) => (due ? { due } : {}))(taskDue(options)),
|
|
1565
|
+
...(options.tag.length ? { tags: options.tag } : {}),
|
|
1566
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1567
|
+
}),
|
|
1568
|
+
);
|
|
1569
|
+
output(
|
|
1570
|
+
io,
|
|
1571
|
+
global.json,
|
|
1572
|
+
result,
|
|
1573
|
+
`${result.deduplicated ? 'Found existing' : 'Created'} private todo\nTitle: ${result.record.current.title}\nID: ${result.record.event.id}`,
|
|
1574
|
+
);
|
|
1575
|
+
},
|
|
1576
|
+
);
|
|
1577
|
+
todoCommand
|
|
1578
|
+
.command('list')
|
|
1579
|
+
.requiredOption('--as <actor-id>')
|
|
1580
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1581
|
+
.option('--status <status>')
|
|
1582
|
+
.option('--limit <number>', 'maximum results', '10')
|
|
1583
|
+
.action(
|
|
1584
|
+
async (
|
|
1585
|
+
options: { as: string; actorKind: string; status?: string; limit: string },
|
|
1586
|
+
command: Command,
|
|
1587
|
+
) => {
|
|
1588
|
+
const global = globals(command);
|
|
1589
|
+
const page = await withClient(global.home, actor(options.actorKind, options.as), (client) =>
|
|
1590
|
+
client.todos.list({
|
|
1591
|
+
...(options.status ? { status: options.status } : {}),
|
|
1592
|
+
limit: Number(options.limit),
|
|
1593
|
+
}),
|
|
1594
|
+
);
|
|
1595
|
+
output(
|
|
1596
|
+
io,
|
|
1597
|
+
global.json,
|
|
1598
|
+
page,
|
|
1599
|
+
page.items.length
|
|
1600
|
+
? page.items
|
|
1601
|
+
.map((item) => `${item.id} ${item.status.padEnd(9)} ${item.title}`)
|
|
1602
|
+
.join('\n')
|
|
1603
|
+
: 'No todos.',
|
|
1604
|
+
);
|
|
1605
|
+
},
|
|
1606
|
+
);
|
|
1198
1607
|
todoCommand
|
|
1608
|
+
.command('show <todo-id>')
|
|
1609
|
+
.requiredOption('--as <actor-id>')
|
|
1610
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1611
|
+
.action(async (id: string, options: { as: string; actorKind: string }, command: Command) => {
|
|
1612
|
+
const global = globals(command);
|
|
1613
|
+
const record = await withClient(global.home, actor(options.actorKind, options.as), (client) =>
|
|
1614
|
+
client.todos.get(id),
|
|
1615
|
+
);
|
|
1616
|
+
output(
|
|
1617
|
+
io,
|
|
1618
|
+
global.json,
|
|
1619
|
+
record,
|
|
1620
|
+
`${record.current.title}\nStatus: ${record.status}\nPriority: ${record.current.priority}\nVersion: ${record.current.version}${record.current.details ? `\n\n${record.current.details}` : ''}`,
|
|
1621
|
+
);
|
|
1622
|
+
});
|
|
1623
|
+
for (const operation of ['complete', 'reopen', 'cancel', 'archive'] as const) {
|
|
1624
|
+
todoCommand
|
|
1625
|
+
.command(`${operation} <todo-id>`)
|
|
1626
|
+
.requiredOption('--as <actor-id>')
|
|
1627
|
+
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
1628
|
+
.option('--note <text>')
|
|
1629
|
+
.option('--reason <text>')
|
|
1630
|
+
.option('--idempotency-key <key>')
|
|
1631
|
+
.action(
|
|
1632
|
+
async (
|
|
1633
|
+
id: string,
|
|
1634
|
+
options: {
|
|
1635
|
+
as: string;
|
|
1636
|
+
actorKind: string;
|
|
1637
|
+
note?: string;
|
|
1638
|
+
reason?: string;
|
|
1639
|
+
idempotencyKey?: string;
|
|
1640
|
+
},
|
|
1641
|
+
command: Command,
|
|
1642
|
+
) => {
|
|
1643
|
+
const global = globals(command);
|
|
1644
|
+
const record = await withClient(
|
|
1645
|
+
global.home,
|
|
1646
|
+
actor(options.actorKind, options.as),
|
|
1647
|
+
(client) =>
|
|
1648
|
+
operation === 'complete'
|
|
1649
|
+
? client.todos.complete({
|
|
1650
|
+
todoId: id,
|
|
1651
|
+
...(options.note ? { note: options.note } : {}),
|
|
1652
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1653
|
+
})
|
|
1654
|
+
: operation === 'cancel'
|
|
1655
|
+
? client.todos.cancel({
|
|
1656
|
+
todoId: id,
|
|
1657
|
+
...(options.reason ? { reason: options.reason } : {}),
|
|
1658
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1659
|
+
})
|
|
1660
|
+
: operation === 'archive'
|
|
1661
|
+
? client.todos.archive({
|
|
1662
|
+
todoId: id,
|
|
1663
|
+
...(options.idempotencyKey
|
|
1664
|
+
? { idempotencyKey: options.idempotencyKey }
|
|
1665
|
+
: {}),
|
|
1666
|
+
})
|
|
1667
|
+
: client.todos.reopen({
|
|
1668
|
+
todoId: id,
|
|
1669
|
+
...(options.idempotencyKey
|
|
1670
|
+
? { idempotencyKey: options.idempotencyKey }
|
|
1671
|
+
: {}),
|
|
1672
|
+
}),
|
|
1673
|
+
);
|
|
1674
|
+
output(io, global.json, record, `Todo ${id} is now ${record.status}.`);
|
|
1675
|
+
},
|
|
1676
|
+
);
|
|
1677
|
+
}
|
|
1678
|
+
|
|
1679
|
+
const taskCommand = program.command('task').description('Create and manage agent tasks');
|
|
1680
|
+
taskCommand
|
|
1199
1681
|
.command('create <assignee>')
|
|
1200
1682
|
.requiredOption('--from <actor-id>')
|
|
1201
1683
|
.option('--actor-kind <kind>', 'human, agent, or system', 'agent')
|
|
@@ -1231,12 +1713,12 @@ export function createCli(
|
|
|
1231
1713
|
global.home,
|
|
1232
1714
|
actor(options.actorKind, options.from),
|
|
1233
1715
|
(client) =>
|
|
1234
|
-
client.
|
|
1716
|
+
client.tasks.create({
|
|
1235
1717
|
assigneeAgentId: assignee,
|
|
1236
1718
|
title: options.title,
|
|
1237
1719
|
...(options.description ? { description: options.description } : {}),
|
|
1238
1720
|
priority: Number(options.priority) as 1 | 2 | 3 | 4,
|
|
1239
|
-
...((due) => (due ? { due } : {}))(
|
|
1721
|
+
...((due) => (due ? { due } : {}))(taskDue(options)),
|
|
1240
1722
|
...(options.tag.length ? { tags: options.tag } : {}),
|
|
1241
1723
|
visibility: options.visibility,
|
|
1242
1724
|
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
@@ -1246,11 +1728,11 @@ export function createCli(
|
|
|
1246
1728
|
io,
|
|
1247
1729
|
global.json,
|
|
1248
1730
|
result,
|
|
1249
|
-
`${result.deduplicated ? 'Found existing' : 'Created'}
|
|
1731
|
+
`${result.deduplicated ? 'Found existing' : 'Created'} task for ${result.record.event.assigneeDisplayName}\nTitle: ${result.record.current.title}\nID: ${result.record.event.id}`,
|
|
1250
1732
|
);
|
|
1251
1733
|
},
|
|
1252
1734
|
);
|
|
1253
|
-
|
|
1735
|
+
taskCommand
|
|
1254
1736
|
.command('list')
|
|
1255
1737
|
.option('--assignee <agent>')
|
|
1256
1738
|
.option('--status <status>')
|
|
@@ -1262,21 +1744,21 @@ export function createCli(
|
|
|
1262
1744
|
global.home,
|
|
1263
1745
|
defaultActor(env, 'human', 'local-cli'),
|
|
1264
1746
|
(client) =>
|
|
1265
|
-
client.
|
|
1747
|
+
client.tasks.list({
|
|
1266
1748
|
...(options.assignee ? { participantAgentId: options.assignee } : {}),
|
|
1267
1749
|
...(options.status ? { status: options.status } : {}),
|
|
1268
1750
|
limit: Number(options.limit),
|
|
1269
1751
|
}),
|
|
1270
1752
|
);
|
|
1271
|
-
output(io, global.json, page, page.items.map(lineForItem).join('\n') || 'No
|
|
1753
|
+
output(io, global.json, page, page.items.map(lineForItem).join('\n') || 'No tasks found.');
|
|
1272
1754
|
},
|
|
1273
1755
|
);
|
|
1274
|
-
|
|
1756
|
+
taskCommand.command('show <task-id>').action(async (id: string, _options, command: Command) => {
|
|
1275
1757
|
const global = globals(command);
|
|
1276
1758
|
const record = await withClient(
|
|
1277
1759
|
global.home,
|
|
1278
1760
|
defaultActor(env, 'human', 'local-cli'),
|
|
1279
|
-
(client) => client.
|
|
1761
|
+
(client) => client.tasks.get(id),
|
|
1280
1762
|
);
|
|
1281
1763
|
output(
|
|
1282
1764
|
io,
|
|
@@ -1285,8 +1767,8 @@ export function createCli(
|
|
|
1285
1767
|
`${record.current.title}\nID: ${record.event.id}\nStatus: ${record.status}\nVersion: ${record.current.version}`,
|
|
1286
1768
|
);
|
|
1287
1769
|
});
|
|
1288
|
-
|
|
1289
|
-
.command('update <
|
|
1770
|
+
taskCommand
|
|
1771
|
+
.command('update <task-id>')
|
|
1290
1772
|
.requiredOption('--as <actor-id>')
|
|
1291
1773
|
.option('--actor-kind <kind>', 'agent or human', 'agent')
|
|
1292
1774
|
.requiredOption('--expected-version <number>')
|
|
@@ -1319,13 +1801,13 @@ export function createCli(
|
|
|
1319
1801
|
command: Command,
|
|
1320
1802
|
) => {
|
|
1321
1803
|
const global = globals(command);
|
|
1322
|
-
const parsedDue =
|
|
1804
|
+
const parsedDue = taskDue(options);
|
|
1323
1805
|
const record = await withClient(
|
|
1324
1806
|
global.home,
|
|
1325
1807
|
actor(options.actorKind, options.as),
|
|
1326
1808
|
(client) =>
|
|
1327
|
-
client.
|
|
1328
|
-
|
|
1809
|
+
client.tasks.update({
|
|
1810
|
+
taskId: id,
|
|
1329
1811
|
expectedVersion: Number(options.expectedVersion),
|
|
1330
1812
|
...(options.title ? { title: options.title } : {}),
|
|
1331
1813
|
...(options.description !== undefined ? { description: options.description } : {}),
|
|
@@ -1335,71 +1817,78 @@ export function createCli(
|
|
|
1335
1817
|
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1336
1818
|
}),
|
|
1337
1819
|
);
|
|
1338
|
-
output(io, global.json, record, `Updated
|
|
1820
|
+
output(io, global.json, record, `Updated task ${id} to version ${record.current.version}.`);
|
|
1339
1821
|
},
|
|
1340
1822
|
);
|
|
1341
1823
|
for (const operation of ['accept', 'reject', 'complete', 'reopen', 'cancel'] as const) {
|
|
1342
|
-
|
|
1343
|
-
.command(`${operation} <
|
|
1824
|
+
const command_ = taskCommand
|
|
1825
|
+
.command(`${operation} <task-id>`)
|
|
1344
1826
|
.requiredOption('--as <actor-id>')
|
|
1345
1827
|
.option('--actor-kind <kind>', 'agent or human', 'agent')
|
|
1346
1828
|
.option('--note <text>')
|
|
1347
1829
|
.option('--reason <text>')
|
|
1348
|
-
.option('--idempotency-key <key>')
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1352
|
-
|
|
1353
|
-
|
|
1354
|
-
|
|
1355
|
-
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1362
|
-
|
|
1363
|
-
|
|
1364
|
-
|
|
1365
|
-
|
|
1366
|
-
|
|
1367
|
-
|
|
1368
|
-
|
|
1830
|
+
.option('--idempotency-key <key>');
|
|
1831
|
+
// Rejecting requires saying why; accepting may. Marked required at the
|
|
1832
|
+
// parser so the CLI refuses before touching the store.
|
|
1833
|
+
if (operation === 'reject') {
|
|
1834
|
+
command_.requiredOption('--response <text>', 'why the task is being refused');
|
|
1835
|
+
} else if (operation === 'accept') {
|
|
1836
|
+
command_.option('--response <text>', 'conditions, timing, or partial capability');
|
|
1837
|
+
}
|
|
1838
|
+
command_.action(
|
|
1839
|
+
async (
|
|
1840
|
+
id: string,
|
|
1841
|
+
options: {
|
|
1842
|
+
as: string;
|
|
1843
|
+
actorKind: string;
|
|
1844
|
+
note?: string;
|
|
1845
|
+
reason?: string;
|
|
1846
|
+
response?: string;
|
|
1847
|
+
idempotencyKey?: string;
|
|
1848
|
+
},
|
|
1849
|
+
command: Command,
|
|
1850
|
+
) => {
|
|
1851
|
+
const global = globals(command);
|
|
1852
|
+
const record = await withClient(
|
|
1853
|
+
global.home,
|
|
1854
|
+
actor(options.actorKind, options.as),
|
|
1855
|
+
(client) =>
|
|
1856
|
+
operation === 'accept'
|
|
1857
|
+
? client.tasks.accept({
|
|
1858
|
+
taskId: id,
|
|
1859
|
+
...(options.response ? { response: options.response } : {}),
|
|
1860
|
+
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1861
|
+
})
|
|
1862
|
+
: operation === 'reject'
|
|
1863
|
+
? client.tasks.reject({
|
|
1864
|
+
taskId: id,
|
|
1865
|
+
response: options.response ?? options.reason ?? '',
|
|
1369
1866
|
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1370
1867
|
})
|
|
1371
|
-
: operation === '
|
|
1372
|
-
? client.
|
|
1373
|
-
|
|
1374
|
-
...(options.
|
|
1868
|
+
: operation === 'complete'
|
|
1869
|
+
? client.tasks.complete({
|
|
1870
|
+
taskId: id,
|
|
1871
|
+
...(options.note ? { note: options.note } : {}),
|
|
1375
1872
|
...(options.idempotencyKey ? { idempotencyKey: options.idempotencyKey } : {}),
|
|
1376
1873
|
})
|
|
1377
|
-
: operation === '
|
|
1378
|
-
? client.
|
|
1379
|
-
|
|
1380
|
-
...(options.
|
|
1874
|
+
: operation === 'cancel'
|
|
1875
|
+
? client.tasks.cancel({
|
|
1876
|
+
taskId: id,
|
|
1877
|
+
...(options.reason ? { reason: options.reason } : {}),
|
|
1381
1878
|
...(options.idempotencyKey
|
|
1382
1879
|
? { idempotencyKey: options.idempotencyKey }
|
|
1383
1880
|
: {}),
|
|
1384
1881
|
})
|
|
1385
|
-
:
|
|
1386
|
-
|
|
1387
|
-
|
|
1388
|
-
|
|
1389
|
-
|
|
1390
|
-
|
|
1391
|
-
|
|
1392
|
-
|
|
1393
|
-
|
|
1394
|
-
|
|
1395
|
-
...(options.idempotencyKey
|
|
1396
|
-
? { idempotencyKey: options.idempotencyKey }
|
|
1397
|
-
: {}),
|
|
1398
|
-
}),
|
|
1399
|
-
);
|
|
1400
|
-
output(io, global.json, record, `Todo ${id} is ${record.status}.`);
|
|
1401
|
-
},
|
|
1402
|
-
);
|
|
1882
|
+
: client.tasks.reopen({
|
|
1883
|
+
taskId: id,
|
|
1884
|
+
...(options.idempotencyKey
|
|
1885
|
+
? { idempotencyKey: options.idempotencyKey }
|
|
1886
|
+
: {}),
|
|
1887
|
+
}),
|
|
1888
|
+
);
|
|
1889
|
+
output(io, global.json, record, `Task ${id} is ${record.status}.`);
|
|
1890
|
+
},
|
|
1891
|
+
);
|
|
1403
1892
|
}
|
|
1404
1893
|
|
|
1405
1894
|
kudosCommand
|
|
@@ -1621,18 +2110,44 @@ export function createCli(
|
|
|
1621
2110
|
program
|
|
1622
2111
|
.command('mcp')
|
|
1623
2112
|
.description('Run the actor-bound MCP server over stdio')
|
|
1624
|
-
.
|
|
1625
|
-
.
|
|
1626
|
-
.option('--actor-
|
|
2113
|
+
.option('--agent-id <id>', 'bound agent, whose identity is read from Synomem')
|
|
2114
|
+
.option('--actor-id <id>', 'bound non-agent actor ID')
|
|
2115
|
+
.option('--actor-kind <kind>', 'human or system')
|
|
2116
|
+
.option('--actor-name <display-name>', 'display name for a non-agent actor')
|
|
1627
2117
|
.action(
|
|
1628
2118
|
async (
|
|
1629
|
-
options: { actorId
|
|
2119
|
+
options: { agentId?: string; actorId?: string; actorKind?: string; actorName?: string },
|
|
1630
2120
|
command: Command,
|
|
1631
2121
|
) => {
|
|
1632
2122
|
const global = globals(command);
|
|
2123
|
+
// An agent's name comes from its profile, never from the command line:
|
|
2124
|
+
// the name is written into every event the session appends, and a
|
|
2125
|
+
// harness must not be able to sign another agent's name to work.
|
|
2126
|
+
const bound = options.agentId
|
|
2127
|
+
? await withClient(global.home, defaultActor(env, 'system', 'cli'), async (client) => {
|
|
2128
|
+
const resolution = await client.agents.resolve(options.agentId!);
|
|
2129
|
+
if (!resolution.match) {
|
|
2130
|
+
throw new SynomemError(
|
|
2131
|
+
'AGENT_NOT_FOUND',
|
|
2132
|
+
resolution.candidates.length
|
|
2133
|
+
? `"${options.agentId}" matches ${resolution.candidates.length} agents: ${resolution.candidates
|
|
2134
|
+
.map((candidate) => candidate.id)
|
|
2135
|
+
.join(', ')}. Name one of them.`
|
|
2136
|
+
: `Unknown agent: ${options.agentId}`,
|
|
2137
|
+
);
|
|
2138
|
+
}
|
|
2139
|
+
return actor('agent', resolution.match.id, resolution.match.displayName);
|
|
2140
|
+
})
|
|
2141
|
+
: undefined;
|
|
2142
|
+
if (!bound && !(options.actorId && options.actorKind)) {
|
|
2143
|
+
throw new SynomemError(
|
|
2144
|
+
'INVALID_INPUT',
|
|
2145
|
+
'Specify --agent-id, or --actor-id with --actor-kind for a non-agent actor.',
|
|
2146
|
+
);
|
|
2147
|
+
}
|
|
1633
2148
|
await startMcpServer({
|
|
1634
2149
|
...(global.home ? { home: global.home } : {}),
|
|
1635
|
-
actor: actor(options.actorKind
|
|
2150
|
+
actor: bound ?? actor(options.actorKind!, options.actorId!, options.actorName),
|
|
1636
2151
|
});
|
|
1637
2152
|
},
|
|
1638
2153
|
);
|