ticlawk 0.1.16-dev.10 → 0.1.16-dev.12
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/bin/ticlawk.mjs +117 -0
- package/package.json +1 -1
- package/src/adapters/ticlawk/api.mjs +189 -0
- package/src/adapters/ticlawk/index.mjs +63 -4
- package/src/cli/agent-commands.mjs +397 -1
- package/src/core/agent-cli-handlers.mjs +300 -0
- package/src/core/agent-home.mjs +45 -1
- package/src/core/argv.mjs +11 -1
- package/src/core/http.mjs +102 -0
- package/src/runtimes/_shared/standing-prompt.mjs +2 -0
|
@@ -160,6 +160,13 @@ export async function runMessageSendCommand(args) {
|
|
|
160
160
|
mediaAssetIds.push(upload.assetId);
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
// Optional --kind <s> classifies the message via metadata.kind. The
|
|
164
|
+
// canonical user-facing value is 'report' (奏折 surface). Anything else
|
|
165
|
+
// is passed through as-is so we don't have to update this list to add
|
|
166
|
+
// new conventions.
|
|
167
|
+
const kind = getArg(args, 'kind');
|
|
168
|
+
const metadata = kind ? { kind } : undefined;
|
|
169
|
+
|
|
163
170
|
const body = {
|
|
164
171
|
target,
|
|
165
172
|
conversation_id: conversationId,
|
|
@@ -167,6 +174,7 @@ export async function runMessageSendCommand(args) {
|
|
|
167
174
|
seen_up_to_seq: getNumberArg(args, 'seen-up-to-seq'),
|
|
168
175
|
reply_to_message_id: getArg(args, 'reply-to'),
|
|
169
176
|
media_asset_ids: mediaAssetIds.length > 0 ? mediaAssetIds : undefined,
|
|
177
|
+
metadata,
|
|
170
178
|
};
|
|
171
179
|
const res = await daemonRequest({
|
|
172
180
|
method: 'POST',
|
|
@@ -800,6 +808,338 @@ export async function runGroupMembersCommand(args) {
|
|
|
800
808
|
return exitFromStatus(res.statusCode);
|
|
801
809
|
}
|
|
802
810
|
|
|
811
|
+
export async function runWorkstreamCreateCommand(args) {
|
|
812
|
+
const env = requireAgentEnv();
|
|
813
|
+
const name = getArg(args, 'name');
|
|
814
|
+
if (!name) { console.error('--name is required'); return 2; }
|
|
815
|
+
const description = getArg(args, 'description');
|
|
816
|
+
const memberArgs = args.member;
|
|
817
|
+
const memberAgentIds = Array.isArray(memberArgs)
|
|
818
|
+
? memberArgs
|
|
819
|
+
: memberArgs ? [memberArgs] : [];
|
|
820
|
+
// Optional charter from stdin when --charter is supplied with no value
|
|
821
|
+
let charter = null;
|
|
822
|
+
if (args.charter === true) {
|
|
823
|
+
charter = await readStdin();
|
|
824
|
+
} else if (typeof args.charter === 'string') {
|
|
825
|
+
charter = args.charter;
|
|
826
|
+
}
|
|
827
|
+
const res = await daemonRequest({
|
|
828
|
+
method: 'POST',
|
|
829
|
+
path: '/agent/workstream/create',
|
|
830
|
+
headers: commonHeaders(env),
|
|
831
|
+
body: {
|
|
832
|
+
name,
|
|
833
|
+
description,
|
|
834
|
+
charter,
|
|
835
|
+
member_agent_ids: memberAgentIds.map((s) => String(s).trim()).filter(Boolean),
|
|
836
|
+
},
|
|
837
|
+
});
|
|
838
|
+
printJson(res.body);
|
|
839
|
+
return exitFromStatus(res.statusCode);
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
export async function runWorkstreamDeleteCommand(args) {
|
|
843
|
+
const env = requireAgentEnv();
|
|
844
|
+
const target = getArg(args, 'target');
|
|
845
|
+
const conversationId = getArg(args, 'conversation-id');
|
|
846
|
+
if (!target && !conversationId) {
|
|
847
|
+
console.error('--target or --conversation-id is required');
|
|
848
|
+
return 2;
|
|
849
|
+
}
|
|
850
|
+
const res = await daemonRequest({
|
|
851
|
+
method: 'POST',
|
|
852
|
+
path: '/agent/workstream/delete',
|
|
853
|
+
headers: commonHeaders(env),
|
|
854
|
+
body: { target, conversation_id: conversationId },
|
|
855
|
+
});
|
|
856
|
+
printJson(res.body);
|
|
857
|
+
return exitFromStatus(res.statusCode);
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
export async function runWorkstreamListCommand(args) {
|
|
861
|
+
const env = requireAgentEnv();
|
|
862
|
+
const res = await daemonRequest({
|
|
863
|
+
method: 'GET',
|
|
864
|
+
path: '/agent/workstream/list',
|
|
865
|
+
headers: commonHeaders(env),
|
|
866
|
+
});
|
|
867
|
+
printJson(res.body);
|
|
868
|
+
return exitFromStatus(res.statusCode);
|
|
869
|
+
}
|
|
870
|
+
|
|
871
|
+
export async function runAgentCreateCommand(args) {
|
|
872
|
+
const env = requireAgentEnv();
|
|
873
|
+
const name = getArg(args, 'name');
|
|
874
|
+
const runtime = getArg(args, 'runtime');
|
|
875
|
+
if (!name) { console.error('--name is required'); return 2; }
|
|
876
|
+
if (!runtime) { console.error('--runtime is required'); return 2; }
|
|
877
|
+
const res = await daemonRequest({
|
|
878
|
+
method: 'POST',
|
|
879
|
+
path: '/agent/agent/create',
|
|
880
|
+
headers: commonHeaders(env),
|
|
881
|
+
body: {
|
|
882
|
+
name,
|
|
883
|
+
runtime,
|
|
884
|
+
description: getArg(args, 'description'),
|
|
885
|
+
display_name: getArg(args, 'display-name'),
|
|
886
|
+
model: getArg(args, 'model'),
|
|
887
|
+
},
|
|
888
|
+
});
|
|
889
|
+
printJson(res.body);
|
|
890
|
+
return exitFromStatus(res.statusCode);
|
|
891
|
+
}
|
|
892
|
+
|
|
893
|
+
export async function runAgentDeleteCommand(args) {
|
|
894
|
+
const env = requireAgentEnv();
|
|
895
|
+
const agentId = getArg(args, 'agent-id');
|
|
896
|
+
if (!agentId) { console.error('--agent-id is required'); return 2; }
|
|
897
|
+
const res = await daemonRequest({
|
|
898
|
+
method: 'POST',
|
|
899
|
+
path: '/agent/agent/delete',
|
|
900
|
+
headers: commonHeaders(env),
|
|
901
|
+
body: { agent_id: agentId },
|
|
902
|
+
});
|
|
903
|
+
printJson(res.body);
|
|
904
|
+
return exitFromStatus(res.statusCode);
|
|
905
|
+
}
|
|
906
|
+
|
|
907
|
+
function readJsonFromFileOrInline(value) {
|
|
908
|
+
if (!value) return null;
|
|
909
|
+
// Accept either a path to a .json file or a raw JSON string.
|
|
910
|
+
try {
|
|
911
|
+
return JSON.parse(value);
|
|
912
|
+
} catch {}
|
|
913
|
+
try {
|
|
914
|
+
const fs = require('node:fs');
|
|
915
|
+
const txt = fs.readFileSync(value, 'utf8');
|
|
916
|
+
return JSON.parse(txt);
|
|
917
|
+
} catch (err) {
|
|
918
|
+
throw new Error(`could not parse JSON from ${value}: ${err?.message || err}`);
|
|
919
|
+
}
|
|
920
|
+
}
|
|
921
|
+
|
|
922
|
+
export async function runServiceCreateCommand(args) {
|
|
923
|
+
const env = requireAgentEnv();
|
|
924
|
+
const name = getArg(args, 'name');
|
|
925
|
+
if (!name) { console.error('--name is required'); return 2; }
|
|
926
|
+
const description = getArg(args, 'description');
|
|
927
|
+
let contractSchema = null;
|
|
928
|
+
let endpointConfig = null;
|
|
929
|
+
try {
|
|
930
|
+
const contractRaw = getArg(args, 'contract');
|
|
931
|
+
if (contractRaw) contractSchema = readJsonFromFileOrInline(contractRaw);
|
|
932
|
+
const endpointRaw = getArg(args, 'endpoint');
|
|
933
|
+
if (endpointRaw) endpointConfig = readJsonFromFileOrInline(endpointRaw);
|
|
934
|
+
} catch (err) {
|
|
935
|
+
console.error(err.message);
|
|
936
|
+
return 2;
|
|
937
|
+
}
|
|
938
|
+
if (!endpointConfig) { console.error('--endpoint <path-or-json> is required'); return 2; }
|
|
939
|
+
const res = await daemonRequest({
|
|
940
|
+
method: 'POST', path: '/agent/service/create',
|
|
941
|
+
headers: commonHeaders(env),
|
|
942
|
+
body: { name, description, contract_schema: contractSchema, endpoint_config: endpointConfig },
|
|
943
|
+
});
|
|
944
|
+
printJson(res.body);
|
|
945
|
+
return exitFromStatus(res.statusCode);
|
|
946
|
+
}
|
|
947
|
+
|
|
948
|
+
export async function runServiceUpdateCommand(args) {
|
|
949
|
+
const env = requireAgentEnv();
|
|
950
|
+
const serviceId = getArg(args, 'service-id');
|
|
951
|
+
if (!serviceId) { console.error('--service-id is required'); return 2; }
|
|
952
|
+
const body = { service_id: serviceId };
|
|
953
|
+
if (getArg(args, 'description')) body.description = getArg(args, 'description');
|
|
954
|
+
if (getArg(args, 'contract')) body.contract_schema = readJsonFromFileOrInline(getArg(args, 'contract'));
|
|
955
|
+
if (getArg(args, 'endpoint')) body.endpoint_config = readJsonFromFileOrInline(getArg(args, 'endpoint'));
|
|
956
|
+
if (getArg(args, 'status')) body.status = getArg(args, 'status');
|
|
957
|
+
const res = await daemonRequest({
|
|
958
|
+
method: 'POST', path: '/agent/service/update',
|
|
959
|
+
headers: commonHeaders(env), body,
|
|
960
|
+
});
|
|
961
|
+
printJson(res.body);
|
|
962
|
+
return exitFromStatus(res.statusCode);
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
export async function runServiceDeleteCommand(args) {
|
|
966
|
+
const env = requireAgentEnv();
|
|
967
|
+
const serviceId = getArg(args, 'service-id');
|
|
968
|
+
if (!serviceId) { console.error('--service-id is required'); return 2; }
|
|
969
|
+
const res = await daemonRequest({
|
|
970
|
+
method: 'POST', path: '/agent/service/delete',
|
|
971
|
+
headers: commonHeaders(env),
|
|
972
|
+
body: { service_id: serviceId },
|
|
973
|
+
});
|
|
974
|
+
printJson(res.body);
|
|
975
|
+
return exitFromStatus(res.statusCode);
|
|
976
|
+
}
|
|
977
|
+
|
|
978
|
+
export async function runServiceListCommand(args) {
|
|
979
|
+
const env = requireAgentEnv();
|
|
980
|
+
const res = await daemonRequest({
|
|
981
|
+
method: 'GET', path: '/agent/service/list',
|
|
982
|
+
headers: commonHeaders(env),
|
|
983
|
+
});
|
|
984
|
+
printJson(res.body);
|
|
985
|
+
return exitFromStatus(res.statusCode);
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
export async function runServiceInfoCommand(args) {
|
|
989
|
+
const env = requireAgentEnv();
|
|
990
|
+
const name = getArg(args, 'name');
|
|
991
|
+
if (!name) { console.error('--name is required'); return 2; }
|
|
992
|
+
const params = new URLSearchParams();
|
|
993
|
+
params.set('name', name);
|
|
994
|
+
const res = await daemonRequest({
|
|
995
|
+
method: 'GET', path: `/agent/service/info?${params}`,
|
|
996
|
+
headers: commonHeaders(env),
|
|
997
|
+
});
|
|
998
|
+
printJson(res.body);
|
|
999
|
+
return exitFromStatus(res.statusCode);
|
|
1000
|
+
}
|
|
1001
|
+
|
|
1002
|
+
export async function runServiceCallCommand(args) {
|
|
1003
|
+
const env = requireAgentEnv();
|
|
1004
|
+
const name = getArg(args, 'name');
|
|
1005
|
+
if (!name) { console.error('--name is required'); return 2; }
|
|
1006
|
+
const inputText = await readStdin();
|
|
1007
|
+
let input = null;
|
|
1008
|
+
if (inputText && inputText.trim().length > 0) {
|
|
1009
|
+
try {
|
|
1010
|
+
input = JSON.parse(inputText);
|
|
1011
|
+
} catch (err) {
|
|
1012
|
+
console.error('stdin must be JSON for service call input');
|
|
1013
|
+
return 2;
|
|
1014
|
+
}
|
|
1015
|
+
}
|
|
1016
|
+
const res = await daemonRequest({
|
|
1017
|
+
method: 'POST', path: '/agent/service/call',
|
|
1018
|
+
headers: commonHeaders(env),
|
|
1019
|
+
body: { name, input },
|
|
1020
|
+
});
|
|
1021
|
+
printJson(res.body);
|
|
1022
|
+
return exitFromStatus(res.statusCode);
|
|
1023
|
+
}
|
|
1024
|
+
|
|
1025
|
+
export async function runCredentialRequestCommand(args) {
|
|
1026
|
+
const env = requireAgentEnv();
|
|
1027
|
+
const name = getArg(args, 'name');
|
|
1028
|
+
if (!name) { console.error('--name is required (e.g. GEMINI_API_KEY)'); return 2; }
|
|
1029
|
+
const description = getArg(args, 'description');
|
|
1030
|
+
const workstream = getArg(args, 'workstream');
|
|
1031
|
+
const res = await daemonRequest({
|
|
1032
|
+
method: 'POST',
|
|
1033
|
+
path: '/agent/credential/request',
|
|
1034
|
+
headers: commonHeaders(env),
|
|
1035
|
+
body: {
|
|
1036
|
+
name,
|
|
1037
|
+
description,
|
|
1038
|
+
target: workstream,
|
|
1039
|
+
},
|
|
1040
|
+
});
|
|
1041
|
+
printJson(res.body);
|
|
1042
|
+
return exitFromStatus(res.statusCode);
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
export async function runDashboardSetCommand(args) {
|
|
1046
|
+
const env = requireAgentEnv();
|
|
1047
|
+
const target = getArg(args, 'target');
|
|
1048
|
+
const conversationId = getArg(args, 'conversation-id');
|
|
1049
|
+
if (!target && !conversationId) {
|
|
1050
|
+
console.error('--target or --conversation-id is required');
|
|
1051
|
+
return 2;
|
|
1052
|
+
}
|
|
1053
|
+
// Body is read from stdin as JSON: { data_json?, html_template? }
|
|
1054
|
+
const stdinText = await readStdin();
|
|
1055
|
+
let payload = {};
|
|
1056
|
+
if (stdinText && stdinText.trim().length > 0) {
|
|
1057
|
+
try {
|
|
1058
|
+
payload = JSON.parse(stdinText);
|
|
1059
|
+
} catch (err) {
|
|
1060
|
+
console.error('stdin must be JSON: { data_json?, html_template? }');
|
|
1061
|
+
return 2;
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
1064
|
+
const res = await daemonRequest({
|
|
1065
|
+
method: 'POST',
|
|
1066
|
+
path: '/agent/dashboard/set',
|
|
1067
|
+
headers: commonHeaders(env),
|
|
1068
|
+
body: {
|
|
1069
|
+
target,
|
|
1070
|
+
conversation_id: conversationId,
|
|
1071
|
+
...(('data_json' in payload) ? { data_json: payload.data_json } : {}),
|
|
1072
|
+
...(('html_template' in payload) ? { html_template: payload.html_template } : {}),
|
|
1073
|
+
},
|
|
1074
|
+
});
|
|
1075
|
+
printJson(res.body);
|
|
1076
|
+
return exitFromStatus(res.statusCode);
|
|
1077
|
+
}
|
|
1078
|
+
|
|
1079
|
+
export async function runDashboardGetCommand(args) {
|
|
1080
|
+
const env = requireAgentEnv();
|
|
1081
|
+
const target = getArg(args, 'target');
|
|
1082
|
+
const conversationId = getArg(args, 'conversation-id');
|
|
1083
|
+
if (!target && !conversationId) {
|
|
1084
|
+
console.error('--target or --conversation-id is required');
|
|
1085
|
+
return 2;
|
|
1086
|
+
}
|
|
1087
|
+
const params = new URLSearchParams();
|
|
1088
|
+
if (target) params.set('target', target);
|
|
1089
|
+
if (conversationId) params.set('conversation_id', conversationId);
|
|
1090
|
+
const res = await daemonRequest({
|
|
1091
|
+
method: 'GET',
|
|
1092
|
+
path: `/agent/dashboard/get?${params}`,
|
|
1093
|
+
headers: commonHeaders(env),
|
|
1094
|
+
});
|
|
1095
|
+
printJson(res.body);
|
|
1096
|
+
return exitFromStatus(res.statusCode);
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
export async function runWorkstreamCharterGetCommand(args) {
|
|
1100
|
+
const env = requireAgentEnv();
|
|
1101
|
+
const target = getArg(args, 'target');
|
|
1102
|
+
const conversationId = getArg(args, 'conversation-id');
|
|
1103
|
+
if (!target && !conversationId) {
|
|
1104
|
+
console.error('--target or --conversation-id is required');
|
|
1105
|
+
return 2;
|
|
1106
|
+
}
|
|
1107
|
+
const params = new URLSearchParams();
|
|
1108
|
+
if (target) params.set('target', target);
|
|
1109
|
+
if (conversationId) params.set('conversation_id', conversationId);
|
|
1110
|
+
const res = await daemonRequest({
|
|
1111
|
+
method: 'GET',
|
|
1112
|
+
path: `/agent/workstream/charter/get?${params}`,
|
|
1113
|
+
headers: commonHeaders(env),
|
|
1114
|
+
});
|
|
1115
|
+
printJson(res.body);
|
|
1116
|
+
return exitFromStatus(res.statusCode);
|
|
1117
|
+
}
|
|
1118
|
+
|
|
1119
|
+
export async function runWorkstreamCharterSetCommand(args) {
|
|
1120
|
+
const env = requireAgentEnv();
|
|
1121
|
+
const target = getArg(args, 'target');
|
|
1122
|
+
const conversationId = getArg(args, 'conversation-id');
|
|
1123
|
+
if (!target && !conversationId) {
|
|
1124
|
+
console.error('--target or --conversation-id is required');
|
|
1125
|
+
return 2;
|
|
1126
|
+
}
|
|
1127
|
+
// Body from stdin (heredoc / pipe). Empty input clears the charter.
|
|
1128
|
+
const charter = await readStdin();
|
|
1129
|
+
const res = await daemonRequest({
|
|
1130
|
+
method: 'POST',
|
|
1131
|
+
path: '/agent/workstream/charter/set',
|
|
1132
|
+
headers: commonHeaders(env),
|
|
1133
|
+
body: {
|
|
1134
|
+
target,
|
|
1135
|
+
conversation_id: conversationId,
|
|
1136
|
+
charter: charter ?? '',
|
|
1137
|
+
},
|
|
1138
|
+
});
|
|
1139
|
+
printJson(res.body);
|
|
1140
|
+
return exitFromStatus(res.statusCode);
|
|
1141
|
+
}
|
|
1142
|
+
|
|
803
1143
|
export async function runServerInfoCommand(args) {
|
|
804
1144
|
const env = requireAgentEnv();
|
|
805
1145
|
const params = new URLSearchParams();
|
|
@@ -815,8 +1155,11 @@ export async function runServerInfoCommand(args) {
|
|
|
815
1155
|
|
|
816
1156
|
export const AGENT_COMMAND_HELP = {
|
|
817
1157
|
message: `ticlawk message <send|read|check|search|react>
|
|
818
|
-
ticlawk message send --target "<target>" [--seen-up-to-seq N] [--reply-to <msg-id>] [--attach <file> ...]
|
|
1158
|
+
ticlawk message send --target "<target>" [--seen-up-to-seq N] [--reply-to <msg-id>] [--attach <file> ...] [--kind <kind>]
|
|
819
1159
|
Body is read from stdin (use <<'EOF' ... EOF for multiline).
|
|
1160
|
+
--kind <kind> tags this message via metadata.kind. The CoS uses
|
|
1161
|
+
--kind report to publish a 奏折 / status report that the Office
|
|
1162
|
+
tab can list separately.
|
|
820
1163
|
Targets:
|
|
821
1164
|
dm:@<user> private message
|
|
822
1165
|
#<group> group conversation
|
|
@@ -861,6 +1204,59 @@ export const AGENT_COMMAND_HELP = {
|
|
|
861
1204
|
ticlawk task unclaim --task-id <id>
|
|
862
1205
|
ticlawk task update --task-id <id> --status <todo|in_progress|in_review|done|canceled>
|
|
863
1206
|
ticlawk task list [--target <target>]
|
|
1207
|
+
`,
|
|
1208
|
+
workstream: `ticlawk workstream <create|delete|list|charter>
|
|
1209
|
+
workstream create --name X [--description Y] [--member <agent-id> ...] [--charter [<text>]]
|
|
1210
|
+
CoS-only. Create a managed group conversation. If --charter has no
|
|
1211
|
+
value, body is read from stdin (heredoc / pipe). Empty stdin = no
|
|
1212
|
+
charter. Members are joined alongside CoS.
|
|
1213
|
+
workstream delete --target "#<group>"
|
|
1214
|
+
CoS-only. Hard-delete the workstream (messages, members, deliveries
|
|
1215
|
+
cascade). Use carefully.
|
|
1216
|
+
workstream list
|
|
1217
|
+
List all workstreams (group conversations) owned by your user.
|
|
1218
|
+
workstream charter get --target "#<group>"
|
|
1219
|
+
Print the workstream's charter (CoS-authored markdown).
|
|
1220
|
+
workstream charter set --target "#<group>" # body via stdin
|
|
1221
|
+
Replace the workstream charter. CoS-only — non-CoS callers get 403.
|
|
1222
|
+
Empty stdin clears the charter. Hard cap 4096 chars (DB-enforced).
|
|
1223
|
+
`,
|
|
1224
|
+
service: `ticlawk service <create|update|delete|list|info|call>
|
|
1225
|
+
service create --name X --endpoint <path-or-json> [--description Y] [--contract <path-or-json>]
|
|
1226
|
+
CoS-only. Register a callable service. --endpoint takes either a
|
|
1227
|
+
.json file path or a JSON string; same for --contract.
|
|
1228
|
+
endpoint_config shape: { url, method?, headers? }.
|
|
1229
|
+
service update --service-id <id> [--description Y] [--contract <json>] [--endpoint <json>] [--status <active|down|archived>]
|
|
1230
|
+
CoS-only.
|
|
1231
|
+
service delete --service-id <id>
|
|
1232
|
+
CoS-only. Soft-archives.
|
|
1233
|
+
service list
|
|
1234
|
+
Any agent. Returns active services (no endpoint_config).
|
|
1235
|
+
service info --name X
|
|
1236
|
+
Any agent. Returns contract_schema + description.
|
|
1237
|
+
service call --name X # input from stdin (JSON)
|
|
1238
|
+
Any agent. Backend proxies to endpoint_config.url. No retry.
|
|
1239
|
+
`,
|
|
1240
|
+
credential: `ticlawk credential request --name <ENV_VAR> [--description Y] [--workstream "#<ws>"]
|
|
1241
|
+
CoS-only. Pre-allocate a credential slot. Response includes a deep
|
|
1242
|
+
link the user opens in the mobile app (Settings → Connections) to
|
|
1243
|
+
fill the value. Once filled, the daemon injects it as an env var
|
|
1244
|
+
when spawning agents.
|
|
1245
|
+
`,
|
|
1246
|
+
dashboard: `ticlawk dashboard <set|get> --target "#<workstream>"
|
|
1247
|
+
dashboard set --target "#<workstream>" # body via stdin (JSON)
|
|
1248
|
+
CoS-only. stdin = { "data_json": ..., "html_template": "..." }.
|
|
1249
|
+
Either field may be omitted (leaves unchanged) or null (clears).
|
|
1250
|
+
dashboard get --target "#<workstream>"
|
|
1251
|
+
Any member of the workstream can read.
|
|
1252
|
+
`,
|
|
1253
|
+
agent: `ticlawk agent <create|delete>
|
|
1254
|
+
agent create --name X --runtime <claude_code|codex|opencode|openclaw|pi> [--description Y] [--display-name N] [--model M]
|
|
1255
|
+
CoS-only. Pre-allocate an agent slot (status='unpaired'). User
|
|
1256
|
+
later pairs a runtime to fill it.
|
|
1257
|
+
agent delete --agent-id <id>
|
|
1258
|
+
CoS-only. Soft-delete the agent (status='archived'). Cannot archive
|
|
1259
|
+
self.
|
|
864
1260
|
`,
|
|
865
1261
|
group: `ticlawk group <create|members>
|
|
866
1262
|
ticlawk group create --name <n> [--description <d>] [--member <agent-id> ...]
|