u-foo 1.2.16 → 1.4.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/modules/online/README.md +18 -0
- package/package.json +2 -1
- package/src/agent/cliRunner.js +1 -1
- package/src/agent/launcher.js +23 -4
- package/src/agent/ptyRunner.js +39 -16
- package/src/agent/ufooAgent.js +2 -1
- package/src/assistant/agent.js +2 -1
- package/src/assistant/bridge.js +9 -3
- package/src/assistant/constants.js +15 -0
- package/src/assistant/engine.js +7 -2
- package/src/assistant/ufooEngineCli.js +9 -3
- package/src/chat/commandExecutor.js +188 -13
- package/src/chat/commands.js +11 -0
- package/src/chat/daemonMessageRouter.js +107 -0
- package/src/cli/groupCoreCommands.js +246 -0
- package/src/cli/onlineCoreCommands.js +8 -0
- package/src/cli.js +325 -2
- package/src/daemon/groupOrchestrator.js +557 -0
- package/src/daemon/index.js +319 -1
- package/src/daemon/status.js +48 -0
- package/src/group/diagram.js +222 -0
- package/src/group/templates.js +280 -0
- package/src/group/validateTemplate.js +234 -0
- package/src/online/server.js +320 -28
- package/src/shared/eventContract.js +5 -0
- package/src/ufoo/paths.js +2 -0
- package/templates/groups/dev-basic.json +78 -0
- package/templates/groups/research-quick.json +49 -0
|
@@ -74,6 +74,109 @@ function createDaemonMessageRouter(options = {}) {
|
|
|
74
74
|
return false;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
+
function logGroupMembers(members = []) {
|
|
78
|
+
if (!Array.isArray(members) || members.length === 0) return;
|
|
79
|
+
members.forEach((member) => {
|
|
80
|
+
const nickname = member && member.nickname ? member.nickname : (member && member.template_agent_id ? member.template_agent_id : "unknown");
|
|
81
|
+
const type = member && member.type ? ` [${member.type}]` : "";
|
|
82
|
+
const status = member && member.status ? ` (${member.status})` : "";
|
|
83
|
+
const subscriber = member && member.subscriber_id ? ` -> ${member.subscriber_id}` : "";
|
|
84
|
+
logMessage(
|
|
85
|
+
"system",
|
|
86
|
+
` • ${escapeBlessed(`${nickname}${type}${status}${subscriber}`)}`
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
function parseGroupErrorEntry(err) {
|
|
92
|
+
const errPath = err && (err.path || err.filePath) ? (err.path || err.filePath) : "template";
|
|
93
|
+
const errMessage = err && (err.message || err.error) ? (err.message || err.error) : "validation error";
|
|
94
|
+
return { errPath, errMessage };
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function logGroupPayload(group) {
|
|
98
|
+
if (!group || typeof group !== "object") return;
|
|
99
|
+
|
|
100
|
+
if (typeof group.diagram === "string" && group.diagram) {
|
|
101
|
+
const mode = group.mode ? ` ${group.mode}` : "";
|
|
102
|
+
const format = group.format ? ` ${group.format}` : "";
|
|
103
|
+
logMessage("system", `{cyan-fg}Group diagram:{/cyan-fg} ${escapeBlessed(`${mode}${format}`.trim())}`);
|
|
104
|
+
group.diagram.split(/\r?\n/).forEach((line) => {
|
|
105
|
+
logMessage("system", escapeBlessed(line));
|
|
106
|
+
});
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (Object.prototype.hasOwnProperty.call(group, "target") && Array.isArray(group.errors)) {
|
|
111
|
+
if (group.ok) {
|
|
112
|
+
const alias = group.alias || group.target || "";
|
|
113
|
+
const source = group.source ? ` (${group.source})` : "";
|
|
114
|
+
logMessage("system", `{white-fg}✓{/white-fg} Group template valid: ${escapeBlessed(`${alias}${source}`)}`);
|
|
115
|
+
} else {
|
|
116
|
+
logMessage("error", `{white-fg}✗{/white-fg} Group template invalid: ${escapeBlessed(group.target || group.alias || "unknown")}`);
|
|
117
|
+
group.errors.forEach((err) => {
|
|
118
|
+
const { errPath, errMessage } = parseGroupErrorEntry(err);
|
|
119
|
+
logMessage("error", ` - ${escapeBlessed(`${errPath}: ${errMessage}`)}`);
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
if (Array.isArray(group.groups)) {
|
|
126
|
+
logMessage("system", `{cyan-fg}Groups:{/cyan-fg} ${group.groups.length}`);
|
|
127
|
+
group.groups.forEach((item) => {
|
|
128
|
+
const id = item && item.group_id ? item.group_id : "unknown";
|
|
129
|
+
const status = item && item.status ? item.status : "unknown";
|
|
130
|
+
const alias = item && item.template_alias ? item.template_alias : "-";
|
|
131
|
+
const active = Number(item && item.members_active) || 0;
|
|
132
|
+
const total = Number(item && item.members_total) || 0;
|
|
133
|
+
logMessage(
|
|
134
|
+
"system",
|
|
135
|
+
` • ${escapeBlessed(id)} [${escapeBlessed(status)}] ${escapeBlessed(alias)} active=${active}/${total}`
|
|
136
|
+
);
|
|
137
|
+
});
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
if (group.group && typeof group.group === "object") {
|
|
142
|
+
const runtime = group.group;
|
|
143
|
+
const id = runtime.group_id || group.group_id || "unknown";
|
|
144
|
+
const status = runtime.status || group.status || "unknown";
|
|
145
|
+
const alias = runtime.template_alias || group.template_alias || "-";
|
|
146
|
+
logMessage(
|
|
147
|
+
"system",
|
|
148
|
+
`{cyan-fg}Group:{/cyan-fg} ${escapeBlessed(id)} [${escapeBlessed(status)}] ${escapeBlessed(alias)}`
|
|
149
|
+
);
|
|
150
|
+
logGroupMembers(runtime.members);
|
|
151
|
+
if (Array.isArray(group.stopped_agents) && group.stopped_agents.length > 0) {
|
|
152
|
+
logMessage("system", `{white-fg}Stopped:{/white-fg} ${group.stopped_agents.length} agent(s)`);
|
|
153
|
+
}
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
if (group.group_id && Array.isArray(group.members)) {
|
|
158
|
+
const status = group.dry_run ? "dry_run" : (group.status || "unknown");
|
|
159
|
+
const alias = group.template_alias || "-";
|
|
160
|
+
logMessage(
|
|
161
|
+
"system",
|
|
162
|
+
`{cyan-fg}Group:{/cyan-fg} ${escapeBlessed(group.group_id)} [${escapeBlessed(status)}] ${escapeBlessed(alias)}`
|
|
163
|
+
);
|
|
164
|
+
logGroupMembers(group.members);
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (group.ok === false && group.error) {
|
|
169
|
+
logMessage("error", `{white-fg}✗{/white-fg} ${escapeBlessed(group.error)}`);
|
|
170
|
+
const validationErrors = Array.isArray(group.validationErrors)
|
|
171
|
+
? group.validationErrors
|
|
172
|
+
: (Array.isArray(group.errors) ? group.errors : []);
|
|
173
|
+
validationErrors.forEach((err) => {
|
|
174
|
+
const { errPath, errMessage } = parseGroupErrorEntry(err);
|
|
175
|
+
logMessage("error", ` - ${escapeBlessed(`${errPath}: ${errMessage}`)}`);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
77
180
|
function handleResponseMessage(msg) {
|
|
78
181
|
const payload = msg.data || {};
|
|
79
182
|
if (payload.reply) {
|
|
@@ -150,6 +253,10 @@ function createDaemonMessageRouter(options = {}) {
|
|
|
150
253
|
}
|
|
151
254
|
}
|
|
152
255
|
|
|
256
|
+
if (payload.group && typeof payload.group === "object") {
|
|
257
|
+
logGroupPayload(payload.group);
|
|
258
|
+
}
|
|
259
|
+
|
|
153
260
|
if (payload.dispatch && payload.dispatch.length > 0) {
|
|
154
261
|
const targets = payload.dispatch.map((d) => d.target || d).join(", ");
|
|
155
262
|
logMessage("dispatch", `{white-fg}→{/white-fg} Dispatched to: ${escapeBlessed(targets)}`);
|
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
const path = require("path");
|
|
4
|
+
const {
|
|
5
|
+
loadTemplateRegistry,
|
|
6
|
+
resolveTemplateReference,
|
|
7
|
+
createTemplateFromBuiltin,
|
|
8
|
+
} = require("../group/templates");
|
|
9
|
+
const { validateTemplate } = require("../group/validateTemplate");
|
|
10
|
+
|
|
11
|
+
function parseTemplateNewArgs(args = []) {
|
|
12
|
+
const alias = String(args[0] || "").trim();
|
|
13
|
+
const options = {
|
|
14
|
+
from: "",
|
|
15
|
+
scope: "project",
|
|
16
|
+
force: false,
|
|
17
|
+
};
|
|
18
|
+
let sawGlobal = false;
|
|
19
|
+
let sawProject = false;
|
|
20
|
+
|
|
21
|
+
for (let i = 1; i < args.length; i += 1) {
|
|
22
|
+
const token = args[i];
|
|
23
|
+
if (token === "--from") {
|
|
24
|
+
options.from = String(args[i + 1] || "").trim();
|
|
25
|
+
i += 1;
|
|
26
|
+
continue;
|
|
27
|
+
}
|
|
28
|
+
if (token === "--global") {
|
|
29
|
+
sawGlobal = true;
|
|
30
|
+
options.scope = "global";
|
|
31
|
+
continue;
|
|
32
|
+
}
|
|
33
|
+
if (token === "--project") {
|
|
34
|
+
sawProject = true;
|
|
35
|
+
options.scope = "project";
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
if (token === "--force") {
|
|
39
|
+
options.force = true;
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (token === "--json") {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
throw new Error(`Unknown option for template new: ${token}`);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
if (!alias) throw new Error("template new requires <alias>");
|
|
49
|
+
if (!options.from) throw new Error("template new requires --from <builtin-alias>");
|
|
50
|
+
if (sawGlobal && sawProject) {
|
|
51
|
+
throw new Error("template new cannot use both --global and --project");
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
return { alias, ...options };
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function formatDisplayPath(filePath = "", cwd = "") {
|
|
58
|
+
const target = String(filePath || "");
|
|
59
|
+
if (!target) return "";
|
|
60
|
+
const base = String(cwd || "").trim();
|
|
61
|
+
if (!base) return target;
|
|
62
|
+
const relative = path.relative(base, target);
|
|
63
|
+
if (!relative || relative.startsWith("..")) return target;
|
|
64
|
+
return relative;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function printList({ templates, errors }, { write, json, cwd }) {
|
|
68
|
+
if (json) {
|
|
69
|
+
write(JSON.stringify({ templates, errors }, null, 2));
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
if (!templates.length) {
|
|
74
|
+
write("No group templates found.");
|
|
75
|
+
} else {
|
|
76
|
+
for (const item of templates) {
|
|
77
|
+
const nameLabel = item.templateName || item.alias;
|
|
78
|
+
const idLabel = item.templateId || "-";
|
|
79
|
+
const verLabel = Number.isInteger(item.schemaVersion) ? item.schemaVersion : "-";
|
|
80
|
+
const displayPath = formatDisplayPath(item.filePath, cwd);
|
|
81
|
+
write(`- ${item.alias} [${item.source}]`);
|
|
82
|
+
write(` name: ${nameLabel}`);
|
|
83
|
+
write(` id: ${idLabel} schema: ${verLabel}`);
|
|
84
|
+
write(` file: ${displayPath}`);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (errors.length > 0) {
|
|
89
|
+
write(`Warnings: ${errors.length} template file(s) failed to load`);
|
|
90
|
+
for (const err of errors) {
|
|
91
|
+
const displayPath = formatDisplayPath(err.filePath, cwd);
|
|
92
|
+
write(` - ${displayPath}: ${err.error}`);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function formatResolveErrors(errors = []) {
|
|
98
|
+
if (!Array.isArray(errors) || errors.length === 0) return "";
|
|
99
|
+
return errors
|
|
100
|
+
.map((item) => `${item.filePath}: ${item.error}`)
|
|
101
|
+
.join("; ");
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function throwResolveFailure(target, resolved = {}) {
|
|
105
|
+
const details = formatResolveErrors(resolved.errors || []);
|
|
106
|
+
if (details) {
|
|
107
|
+
throw new Error(`Failed to load template "${target}": ${details}`);
|
|
108
|
+
}
|
|
109
|
+
throw new Error(`Template not found: ${target}`);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function printValidation(result, target, entry, { write, json }) {
|
|
113
|
+
if (json) {
|
|
114
|
+
write(
|
|
115
|
+
JSON.stringify(
|
|
116
|
+
{
|
|
117
|
+
target,
|
|
118
|
+
alias: entry.alias,
|
|
119
|
+
source: entry.source,
|
|
120
|
+
filePath: entry.filePath,
|
|
121
|
+
ok: result.ok,
|
|
122
|
+
errors: result.errors,
|
|
123
|
+
},
|
|
124
|
+
null,
|
|
125
|
+
2
|
|
126
|
+
)
|
|
127
|
+
);
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
if (result.ok) {
|
|
132
|
+
write(`✓ Template "${entry.alias}" is valid (${entry.source})`);
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
write(`✗ Template "${entry.alias}" is invalid (${result.errors.length} error(s))`);
|
|
137
|
+
for (const err of result.errors) {
|
|
138
|
+
write(` - ${err.path}: ${err.message}`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
async function runGroupCoreCommand(subcmd, cmdArgs = [], options = {}) {
|
|
143
|
+
const cwd = options.cwd || process.cwd();
|
|
144
|
+
const write = typeof options.write === "function" ? options.write : console.log;
|
|
145
|
+
const json = Boolean(options.json);
|
|
146
|
+
const templatesOptions = options.templatesOptions || {};
|
|
147
|
+
|
|
148
|
+
const args = Array.isArray(cmdArgs) ? cmdArgs.filter((item) => item !== undefined) : [];
|
|
149
|
+
const normalizedSubcmd = String(subcmd || "").trim().toLowerCase();
|
|
150
|
+
|
|
151
|
+
if (normalizedSubcmd === "templates") {
|
|
152
|
+
const action = String(args[0] || "list").trim().toLowerCase();
|
|
153
|
+
if (action !== "list" && action !== "ls") {
|
|
154
|
+
throw new Error(`Unknown group templates action: ${action}`);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
const registry = loadTemplateRegistry(cwd, templatesOptions);
|
|
158
|
+
const templates = registry.templates.map((item) => ({
|
|
159
|
+
alias: item.alias,
|
|
160
|
+
source: item.source,
|
|
161
|
+
filePath: item.filePath,
|
|
162
|
+
templateId: item.templateId || "",
|
|
163
|
+
templateName: item.templateName || "",
|
|
164
|
+
schemaVersion: item.schemaVersion,
|
|
165
|
+
}));
|
|
166
|
+
printList({ templates, errors: registry.errors }, { write, json, cwd });
|
|
167
|
+
return;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (normalizedSubcmd !== "template") {
|
|
171
|
+
throw new Error(`Unknown group subcommand: ${subcmd}`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
const action = String(args[0] || "list").trim().toLowerCase();
|
|
175
|
+
|
|
176
|
+
if (action === "list") {
|
|
177
|
+
const registry = loadTemplateRegistry(cwd, templatesOptions);
|
|
178
|
+
const templates = registry.templates.map((item) => ({
|
|
179
|
+
alias: item.alias,
|
|
180
|
+
source: item.source,
|
|
181
|
+
filePath: item.filePath,
|
|
182
|
+
templateId: item.templateId || "",
|
|
183
|
+
templateName: item.templateName || "",
|
|
184
|
+
schemaVersion: item.schemaVersion,
|
|
185
|
+
}));
|
|
186
|
+
printList({ templates, errors: registry.errors }, { write, json, cwd });
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
if (action === "show") {
|
|
191
|
+
const target = String(args[1] || "").trim();
|
|
192
|
+
if (!target) throw new Error("group template show requires <alias>");
|
|
193
|
+
const resolved = resolveTemplateReference(cwd, target, {
|
|
194
|
+
allowPath: false,
|
|
195
|
+
cwd,
|
|
196
|
+
...templatesOptions,
|
|
197
|
+
});
|
|
198
|
+
if (!resolved.entry) {
|
|
199
|
+
throwResolveFailure(target, resolved);
|
|
200
|
+
}
|
|
201
|
+
write(JSON.stringify(resolved.entry.data, null, 2));
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
if (action === "validate") {
|
|
206
|
+
const target = String(args[1] || "").trim();
|
|
207
|
+
if (!target) throw new Error("group template validate requires <alias|path>");
|
|
208
|
+
const resolved = resolveTemplateReference(cwd, target, {
|
|
209
|
+
allowPath: true,
|
|
210
|
+
cwd,
|
|
211
|
+
...templatesOptions,
|
|
212
|
+
});
|
|
213
|
+
if (!resolved.entry) {
|
|
214
|
+
throwResolveFailure(target, resolved);
|
|
215
|
+
}
|
|
216
|
+
const result = validateTemplate(resolved.entry.data);
|
|
217
|
+
printValidation(result, target, resolved.entry, { write, json });
|
|
218
|
+
if (!result.ok) {
|
|
219
|
+
throw new Error(`Template validation failed: ${resolved.entry.alias}`);
|
|
220
|
+
}
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
if (action === "new") {
|
|
225
|
+
const params = parseTemplateNewArgs(args.slice(1));
|
|
226
|
+
const created = createTemplateFromBuiltin(cwd, params.alias, params.from, {
|
|
227
|
+
...templatesOptions,
|
|
228
|
+
scope: params.scope,
|
|
229
|
+
force: params.force,
|
|
230
|
+
});
|
|
231
|
+
|
|
232
|
+
if (json) {
|
|
233
|
+
write(JSON.stringify(created, null, 2));
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const relative = path.relative(cwd, created.filePath) || created.filePath;
|
|
237
|
+
write(`Created template "${created.alias}" from "${created.from}" at ${relative}`);
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
throw new Error(`Unknown group template action: ${action}`);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = {
|
|
245
|
+
runGroupCoreCommand,
|
|
246
|
+
};
|
|
@@ -95,10 +95,12 @@ async function runOnlineRoom(action, opts = {}, onlineAuthHeaders) {
|
|
|
95
95
|
return;
|
|
96
96
|
}
|
|
97
97
|
if (action === "create") {
|
|
98
|
+
const creator = String(opts.createdBy || opts.creator || opts.nickname || opts.subscriber || "").trim();
|
|
98
99
|
const payload = {
|
|
99
100
|
name: opts.name,
|
|
100
101
|
type: opts.type,
|
|
101
102
|
password: opts.password,
|
|
103
|
+
created_by: creator || undefined,
|
|
102
104
|
};
|
|
103
105
|
if (!payload.type) {
|
|
104
106
|
throw new Error("online room create requires --type");
|
|
@@ -132,9 +134,11 @@ async function runOnlineChannel(action, opts = {}, onlineAuthHeaders) {
|
|
|
132
134
|
return;
|
|
133
135
|
}
|
|
134
136
|
if (action === "create") {
|
|
137
|
+
const creator = String(opts.createdBy || opts.creator || opts.nickname || opts.subscriber || "").trim();
|
|
135
138
|
const payload = {
|
|
136
139
|
name: opts.name,
|
|
137
140
|
type: opts.type,
|
|
141
|
+
created_by: creator || undefined,
|
|
138
142
|
};
|
|
139
143
|
if (!payload.name) {
|
|
140
144
|
throw new Error("online channel create requires --name");
|
|
@@ -233,6 +237,7 @@ async function runOnlineCommand(subcmd, payload = {}, options = {}) {
|
|
|
233
237
|
name: opts.name,
|
|
234
238
|
type: opts.type,
|
|
235
239
|
password: opts.password,
|
|
240
|
+
createdBy: opts.createdBy || "",
|
|
236
241
|
}, onlineAuthHeaders);
|
|
237
242
|
case "channel":
|
|
238
243
|
return runOnlineChannel(payload.action, {
|
|
@@ -243,6 +248,7 @@ async function runOnlineCommand(subcmd, payload = {}, options = {}) {
|
|
|
243
248
|
nickname: opts.nickname || "",
|
|
244
249
|
name: opts.name,
|
|
245
250
|
type: opts.type,
|
|
251
|
+
createdBy: opts.createdBy || "",
|
|
246
252
|
}, onlineAuthHeaders);
|
|
247
253
|
case "connect":
|
|
248
254
|
return runOnlineConnect({
|
|
@@ -312,6 +318,7 @@ async function runOnlineCommand(subcmd, payload = {}, options = {}) {
|
|
|
312
318
|
name: getFallbackOpt(argv, "--name"),
|
|
313
319
|
type: getFallbackOpt(argv, "--type"),
|
|
314
320
|
password: getFallbackOpt(argv, "--password"),
|
|
321
|
+
createdBy: getFallbackOpt(argv, "--created-by"),
|
|
315
322
|
}, onlineAuthHeaders);
|
|
316
323
|
}
|
|
317
324
|
case "channel": {
|
|
@@ -325,6 +332,7 @@ async function runOnlineCommand(subcmd, payload = {}, options = {}) {
|
|
|
325
332
|
nickname: getFallbackOpt(argv, "--nickname"),
|
|
326
333
|
name: getFallbackOpt(argv, "--name"),
|
|
327
334
|
type: getFallbackOpt(argv, "--type") || defaultChannelType,
|
|
335
|
+
createdBy: getFallbackOpt(argv, "--created-by"),
|
|
328
336
|
}, onlineAuthHeaders);
|
|
329
337
|
}
|
|
330
338
|
case "connect": {
|