agentlas 1.0.65 → 1.0.66
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +6 -4
- package/bin/agentlas.cjs +341 -16
- package/engine/acp/server.cjs +27 -1
- package/engine/agentlas-api-agent.cjs +151 -120
- package/engine/agentlas-banner.cjs +6 -2
- package/engine/agentlas-capabilities.cjs +17 -10
- package/engine/agentlas-cloud-runtime.cjs +4 -5
- package/engine/agentlas-config.cjs +19 -54
- package/engine/agentlas-core-harness.cjs +59 -5
- package/engine/agentlas-desktop-loadout.cjs +17 -3
- package/engine/agentlas-evolution.cjs +75 -18
- package/engine/agentlas-experience-exchange.cjs +145 -14
- package/engine/agentlas-experience-intake.cjs +2 -2
- package/engine/agentlas-i18n.cjs +0 -2
- package/engine/agentlas-input.cjs +273 -20
- package/engine/agentlas-judgment.cjs +0 -0
- package/engine/agentlas-mcp-env.cjs +84 -23
- package/engine/agentlas-mcp-wrapper.cjs +36 -4
- package/engine/agentlas-memory-governance.cjs +2 -1
- package/engine/agentlas-memory-import.cjs +49 -12
- package/engine/agentlas-native-host.cjs +279 -44
- package/engine/agentlas-onboard.cjs +23 -1
- package/engine/agentlas-permissions.cjs +5 -1
- package/engine/agentlas-sqlite-policy.cjs +40 -2
- package/engine/agentlas-tasks.cjs +7 -0
- package/engine/agentlas-tools.cjs +37 -10
- package/engine/agentlas-ui.cjs +26 -4
- package/engine/agentlas-workforce.cjs +29 -5
- package/engine/agentlas-workload-routing.cjs +83 -10
- package/engine/agentlas.cjs +10 -3
- package/engine/agents/builder.cjs +35 -10
- package/engine/agents/files.cjs +81 -10
- package/engine/agents/import-local.cjs +10 -2
- package/engine/agents/registry.cjs +10 -3
- package/engine/agents/router.cjs +7 -7
- package/engine/agents/routes.cjs +31 -9
- package/engine/automation/daemon.cjs +154 -40
- package/engine/automation/launchd.cjs +395 -16
- package/engine/automation/schedule.cjs +90 -3
- package/engine/automation/store.cjs +163 -59
- package/engine/browser/cdp.cjs +190 -17
- package/engine/browser/vault.cjs +1 -0
- package/engine/cli-output.cjs +80 -28
- package/engine/cloud/auth.cjs +131 -13
- package/engine/cloud/hub-client.cjs +41 -16
- package/engine/cloud-assets/cas.cjs +18 -9
- package/engine/cloud-assets/commands.cjs +108 -30
- package/engine/cloud-assets/package.cjs +66 -3
- package/engine/cloud-assets/restore.cjs +12 -9
- package/engine/cloud-assets/state.cjs +308 -113
- package/engine/commands/acp.cjs +13 -2
- package/engine/commands/automation.cjs +75 -24
- package/engine/commands/billing.cjs +6 -1
- package/engine/commands/browser.cjs +61 -29
- package/engine/commands/build.cjs +42 -12
- package/engine/commands/call.cjs +1 -1
- package/engine/commands/cd.cjs +1 -1
- package/engine/commands/cloud.cjs +2 -1
- package/engine/commands/connect.cjs +38 -13
- package/engine/commands/creds.cjs +74 -29
- package/engine/commands/doctor.cjs +17 -1
- package/engine/commands/document.cjs +38 -10
- package/engine/commands/env.cjs +6 -1
- package/engine/commands/firm.cjs +42 -12
- package/engine/commands/graph.cjs +36 -32
- package/engine/commands/help.cjs +11 -1
- package/engine/commands/hep.cjs +1 -1
- package/engine/commands/import.cjs +5 -4
- package/engine/commands/index.cjs +1 -1
- package/engine/commands/install.cjs +6 -4
- package/engine/commands/list.cjs +56 -16
- package/engine/commands/login.cjs +5 -0
- package/engine/commands/logout.cjs +6 -1
- package/engine/commands/mcp.cjs +8 -2
- package/engine/commands/memory.cjs +3 -2
- package/engine/commands/multimodal.cjs +12 -0
- package/engine/commands/native.cjs +5 -1
- package/engine/commands/one.cjs +78 -33
- package/engine/commands/plugin.cjs +13 -2
- package/engine/commands/project.cjs +15 -12
- package/engine/commands/research.cjs +18 -7
- package/engine/commands/roles.cjs +104 -28
- package/engine/commands/route.cjs +2 -2
- package/engine/commands/run.cjs +42 -9
- package/engine/commands/search.cjs +23 -2
- package/engine/commands/setup.cjs +6 -1
- package/engine/commands/storm.cjs +44 -6
- package/engine/commands/swarm.cjs +47 -9
- package/engine/commands/telegram.cjs +6 -1
- package/engine/commands/uninstall.cjs +12 -6
- package/engine/commands/update.cjs +5 -0
- package/engine/commands/upload.cjs +2 -1
- package/engine/commands/usage.cjs +6 -1
- package/engine/commands/version.cjs +6 -1
- package/engine/commands/whoami.cjs +6 -1
- package/engine/commands/workforce.cjs +60 -16
- package/engine/core/capability-grants.cjs +7 -2
- package/engine/core/daemon-client.cjs +36 -7
- package/engine/core/db.cjs +10 -2
- package/engine/core/desktop-core-fetch.cjs +477 -77
- package/engine/core/schema-ensure.cjs +23 -11
- package/engine/experience/build.cjs +5 -1
- package/engine/experience/intents.cjs +29 -82
- package/engine/experience/runtime.cjs +7 -1
- package/engine/experience/variant.cjs +58 -4
- package/engine/firms/orchestrate.cjs +9 -6
- package/engine/graph/ask-model.cjs +22 -11
- package/engine/graph/interview.cjs +74 -23
- package/engine/graph/package.cjs +63 -8
- package/engine/hephaestus/local-core.cjs +18 -5
- package/engine/hephaestus/runtime.cjs +48 -43
- package/engine/hub/install.cjs +230 -61
- package/engine/hub/plugins.cjs +391 -29
- package/engine/mcp/consent.cjs +25 -17
- package/engine/mcp/contract.cjs +229 -24
- package/engine/mcp/inventory.cjs +15 -5
- package/engine/mcp/plan.cjs +5 -1
- package/engine/mcp/probe.cjs +24 -9
- package/engine/memory-cli/curate.cjs +74 -16
- package/engine/oberon/common.cjs +37 -12
- package/engine/oberon/manifest.cjs +25 -2
- package/engine/oberon/outputs.cjs +49 -19
- package/engine/oberon/render.cjs +665 -40
- package/engine/project/career-graph.cjs +15 -2
- package/engine/project/controller.cjs +133 -15
- package/engine/project/credentials.cjs +212 -34
- package/engine/project/env-file.cjs +93 -8
- package/engine/project/memory-context.cjs +11 -57
- package/engine/project/ontology.cjs +66 -25
- package/engine/project/paths.cjs +42 -8
- package/engine/project/seed.cjs +88 -51
- package/engine/project/state.cjs +41 -16
- package/engine/project/team.cjs +26 -1
- package/engine/runtime-refusal.cjs +4 -1
- package/engine/runtimes/acp-driver.cjs +56 -9
- package/engine/runtimes/auth-evidence.cjs +21 -2
- package/engine/runtimes/detect.cjs +28 -8
- package/engine/runtimes/kinds.cjs +12 -4
- package/engine/runtimes/overrides.cjs +4 -3
- package/engine/runtimes/resolve.cjs +8 -7
- package/engine/runtimes/roles.cjs +7 -5
- package/engine/sessions/apply-fences.cjs +396 -56
- package/engine/sessions/fences.cjs +111 -27
- package/engine/sessions/memory-turn.cjs +62 -3
- package/engine/sessions/orchestrator.cjs +11 -1
- package/engine/sessions/prompt.cjs +66 -9
- package/engine/sessions/session.cjs +70 -10
- package/engine/sessions/sink.cjs +78 -12
- package/engine/sessions/store.cjs +29 -7
- package/engine/storm/storm.cjs +26 -3
- package/engine/storm/swarm.cjs +31 -3
- package/engine/telegram/connect.cjs +185 -22
- package/engine/ui/commands-catalog.cjs +1 -1
- package/engine/ui/palette.cjs +12 -2
- package/engine/ui/repl.cjs +57 -9
- package/engine/ui/screens.cjs +2 -4
- package/engine/vendor/desktop-core.manifest.json +5 -5
- package/engine/workforce/capture.cjs +9 -27
- package/engine/workforce/deps.cjs +18 -6
- package/engine/workforce/local-core-transport.cjs +68 -5
- package/package.json +1 -1
- package/engine/commands/career-graph.cjs +0 -51
|
@@ -166,30 +166,80 @@ function writePurposeRepairCopy(root, projection) {
|
|
|
166
166
|
return tempRoot;
|
|
167
167
|
}
|
|
168
168
|
|
|
169
|
-
|
|
169
|
+
const CLOUD_VALUE_FLAGS = ["limit", "name", "purpose", "scope", "slug", "visibility"];
|
|
170
|
+
const CLOUD_BOOLEAN_FLAGS = ["dry-run", "json", "llm-review", "overwrite", "strict"];
|
|
171
|
+
|
|
172
|
+
function cloudArgumentError(message) {
|
|
173
|
+
const error = new Error(message);
|
|
174
|
+
error.code = "INVALID_ARGUMENT";
|
|
175
|
+
return error;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
function parseCloudFlags(args, spec = {}) {
|
|
179
|
+
const values = new Set(spec.values || CLOUD_VALUE_FLAGS);
|
|
180
|
+
const booleans = new Set(spec.booleans || CLOUD_BOOLEAN_FLAGS);
|
|
170
181
|
const flags = { _: [] };
|
|
182
|
+
const seen = new Set();
|
|
183
|
+
let positionalOnly = false;
|
|
171
184
|
for (let i = 0; i < args.length; i++) {
|
|
172
185
|
const a = args[i];
|
|
173
|
-
if (
|
|
174
|
-
const key = a.slice(2);
|
|
175
|
-
const next = args[i + 1];
|
|
176
|
-
if (next !== undefined && !String(next).startsWith("--")) {
|
|
177
|
-
flags[key] = next;
|
|
178
|
-
i++;
|
|
179
|
-
} else {
|
|
180
|
-
flags[key] = true;
|
|
181
|
-
}
|
|
182
|
-
} else {
|
|
186
|
+
if (positionalOnly) {
|
|
183
187
|
flags._.push(a);
|
|
188
|
+
continue;
|
|
184
189
|
}
|
|
190
|
+
if (a === "--") {
|
|
191
|
+
positionalOnly = true;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
if (!String(a).startsWith("-")) {
|
|
195
|
+
flags._.push(a);
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (!String(a).startsWith("--")) throw cloudArgumentError(`unknown option: ${a}`);
|
|
199
|
+
const equal = String(a).indexOf("=");
|
|
200
|
+
const key = String(a).slice(2, equal === -1 ? undefined : equal);
|
|
201
|
+
if (!key || (!values.has(key) && !booleans.has(key))) throw cloudArgumentError(`unknown option: --${key || ""}`);
|
|
202
|
+
if (seen.has(key)) throw cloudArgumentError(`duplicate option: --${key}`);
|
|
203
|
+
seen.add(key);
|
|
204
|
+
if (booleans.has(key)) {
|
|
205
|
+
if (equal !== -1) throw cloudArgumentError(`--${key} does not take a value`);
|
|
206
|
+
flags[key] = true;
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
let value;
|
|
210
|
+
if (equal !== -1) {
|
|
211
|
+
value = String(a).slice(equal + 1);
|
|
212
|
+
} else {
|
|
213
|
+
const next = args[i + 1];
|
|
214
|
+
if (next === undefined || String(next).startsWith("--")) throw cloudArgumentError(`--${key} requires a value`);
|
|
215
|
+
value = String(next);
|
|
216
|
+
i++;
|
|
217
|
+
}
|
|
218
|
+
if (!value) throw cloudArgumentError(`--${key} requires a non-empty value`);
|
|
219
|
+
flags[key] = value;
|
|
185
220
|
}
|
|
186
221
|
return flags;
|
|
187
222
|
}
|
|
188
223
|
|
|
224
|
+
function requireCloudPositionals(flags, min, max, usage) {
|
|
225
|
+
if (flags._.length < min || flags._.length > max) throw cloudArgumentError(usage);
|
|
226
|
+
return flags;
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
function positiveIntegerFlag(value, fallback, name, max) {
|
|
230
|
+
if (value == null) return fallback;
|
|
231
|
+
if (!/^\d+$/.test(String(value))) throw cloudArgumentError(`--${name} must be a positive integer`);
|
|
232
|
+
const parsed = Number(value);
|
|
233
|
+
if (!Number.isSafeInteger(parsed) || parsed < 1 || parsed > max) {
|
|
234
|
+
throw cloudArgumentError(`--${name} must be between 1 and ${max}`);
|
|
235
|
+
}
|
|
236
|
+
return parsed;
|
|
237
|
+
}
|
|
238
|
+
|
|
189
239
|
function cloudVisibilityFlag(value) {
|
|
190
240
|
if (value == null) return null;
|
|
191
241
|
if (value === "private-link" || value === "marketplace") return value;
|
|
192
|
-
throw
|
|
242
|
+
throw cloudArgumentError("--visibility must be private-link or marketplace");
|
|
193
243
|
}
|
|
194
244
|
|
|
195
245
|
function cloudVisibilityForAction(sub, flags) {
|
|
@@ -213,7 +263,10 @@ function cloudVisibilityForAction(sub, flags) {
|
|
|
213
263
|
|
|
214
264
|
/** 최상위 `upload`의 실제 동작 결정: 기본 save, 명시적 marketplace만 publish. */
|
|
215
265
|
function cloudActionForTopLevelUpload(args) {
|
|
216
|
-
const flags = parseCloudFlags(args
|
|
266
|
+
const flags = requireCloudPositionals(parseCloudFlags(args, {
|
|
267
|
+
values: ["purpose", "slug", "visibility"],
|
|
268
|
+
booleans: ["dry-run", "json", "llm-review", "overwrite"],
|
|
269
|
+
}), 1, 1, "usage: agentlas upload <path> [--visibility marketplace]");
|
|
217
270
|
return cloudVisibilityFlag(flags.visibility) === "marketplace" ? "publish" : "save";
|
|
218
271
|
}
|
|
219
272
|
|
|
@@ -269,17 +322,20 @@ const CLOUD_HELP = [
|
|
|
269
322
|
async function runCloud(ctx, args) {
|
|
270
323
|
const sub = args[0] || "help";
|
|
271
324
|
if (sub === "help" || sub === "--help" || sub === "-h") {
|
|
325
|
+
requireCloudPositionals(parseCloudFlags(args.slice(1), { values: [], booleans: ["json"] }), 0, 0, "usage: agentlas cloud help");
|
|
272
326
|
ctx.out(CLOUD_HELP);
|
|
273
327
|
return 0;
|
|
274
328
|
}
|
|
275
329
|
if (sub === "search") {
|
|
276
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
330
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
331
|
+
values: ["limit"], booleans: ["json"],
|
|
332
|
+
}), 1, Number.MAX_SAFE_INTEGER, 'usage: agentlas cloud search "<what you need>" [--limit 10]');
|
|
277
333
|
const query = flags._.join(" ").trim();
|
|
278
334
|
if (!query) {
|
|
279
335
|
ctx.err('usage: agentlas cloud search "<what you need>" [--limit 10]');
|
|
280
336
|
return 1;
|
|
281
337
|
}
|
|
282
|
-
const limit =
|
|
338
|
+
const limit = positiveIntegerFlag(flags.limit, 10, "limit", 30);
|
|
283
339
|
let result;
|
|
284
340
|
try {
|
|
285
341
|
result = await callHubTool("marketplace.search_agents", { q: query, limit });
|
|
@@ -287,6 +343,7 @@ async function runCloud(ctx, args) {
|
|
|
287
343
|
ctx.err(e instanceof HubError ? e.message : `Marketplace connection failed: ${(e && e.message) || e}`);
|
|
288
344
|
return 1;
|
|
289
345
|
}
|
|
346
|
+
if (flags.json) { ctx.out(JSON.stringify(result, null, 2)); return 0; }
|
|
290
347
|
const items = (result && (result.results || result.agents || result.items)) || [];
|
|
291
348
|
if (!Array.isArray(items) || !items.length) {
|
|
292
349
|
ctx.out(`No results for "${query}"`);
|
|
@@ -298,8 +355,10 @@ async function runCloud(ctx, args) {
|
|
|
298
355
|
return 0;
|
|
299
356
|
}
|
|
300
357
|
if (sub === "list") {
|
|
301
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
302
|
-
|
|
358
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
359
|
+
values: ["limit"], booleans: ["json"],
|
|
360
|
+
}), 0, 0, "usage: agentlas cloud list [--limit 100] [--json]");
|
|
361
|
+
const result = await listOwnedCloudAgents(positiveIntegerFlag(flags.limit, 100, "limit", 1000));
|
|
303
362
|
if (flags.json) { ctx.out(JSON.stringify(result, null, 2)); return 0; }
|
|
304
363
|
const agents = Array.isArray(result.results) ? result.results : [];
|
|
305
364
|
if (!agents.length) { ctx.out("No agents are stored in Private Agent Cloud."); return 0; }
|
|
@@ -332,7 +391,9 @@ async function runCloud(ctx, args) {
|
|
|
332
391
|
return 0;
|
|
333
392
|
}
|
|
334
393
|
if (sub === "restore") {
|
|
335
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
394
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
395
|
+
values: [], booleans: ["json"],
|
|
396
|
+
}), 1, 1, "usage: agentlas cloud restore <slug> [--json]");
|
|
336
397
|
const slug = flags._[0];
|
|
337
398
|
if (!slug) { ctx.err("usage: agentlas cloud restore <slug> [--json]"); return 1; }
|
|
338
399
|
const result = await restoreOwnedCloudAgent(ctx.db(), slug);
|
|
@@ -344,7 +405,9 @@ async function runCloud(ctx, args) {
|
|
|
344
405
|
return 0;
|
|
345
406
|
}
|
|
346
407
|
if (sub === "delete" || sub === "unpublish") {
|
|
347
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
408
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
409
|
+
values: ["scope"], booleans: ["json"],
|
|
410
|
+
}), 1, 1, `usage: agentlas cloud ${sub} <slug> [--scope owner-private|hub-public] [--json]`);
|
|
348
411
|
const slug = flags._[0];
|
|
349
412
|
if (!slug) { ctx.err(`usage: agentlas cloud ${sub} <slug> [--json]`); return 1; }
|
|
350
413
|
const result = await deleteCloudAgent(slug, { scope: flags.scope });
|
|
@@ -356,7 +419,9 @@ async function runCloud(ctx, args) {
|
|
|
356
419
|
}
|
|
357
420
|
// ── agentlas-cloud-runtime 소비 지점 (스캔/매니페스트/lazy-read/필드테스트) ──
|
|
358
421
|
if (sub === "wizard") {
|
|
359
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
422
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
423
|
+
values: ["name"], booleans: ["json"],
|
|
424
|
+
}), 1, 1, "usage: agentlas cloud wizard <path> [--name name] [--json]");
|
|
360
425
|
const root = flags._[0];
|
|
361
426
|
if (!root) { ctx.err("usage: agentlas cloud wizard <path> [--name name]"); return 1; }
|
|
362
427
|
const result = cloudRuntime.runWizard(root, { name: typeof flags.name === "string" ? flags.name : undefined });
|
|
@@ -365,7 +430,9 @@ async function runCloud(ctx, args) {
|
|
|
365
430
|
}
|
|
366
431
|
if (sub === "security") {
|
|
367
432
|
if (args[1] !== "scan") { ctx.err("usage: agentlas cloud security scan <path> [--strict]"); return 1; }
|
|
368
|
-
const flags = parseCloudFlags(args.slice(2)
|
|
433
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(2), {
|
|
434
|
+
values: [], booleans: ["json", "strict"],
|
|
435
|
+
}), 1, 1, "usage: agentlas cloud security scan <path> [--strict]");
|
|
369
436
|
const root = flags._[0];
|
|
370
437
|
if (!root) { ctx.err("usage: agentlas cloud security scan <path> [--strict]"); return 1; }
|
|
371
438
|
const report = cloudRuntime.scanFolder(root);
|
|
@@ -375,15 +442,18 @@ async function runCloud(ctx, args) {
|
|
|
375
442
|
if (sub === "runtime") {
|
|
376
443
|
const action = args[1];
|
|
377
444
|
if (action === "bundle") {
|
|
378
|
-
const
|
|
379
|
-
|
|
445
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(2), {
|
|
446
|
+
values: [], booleans: ["json"],
|
|
447
|
+
}), 1, 1, "usage: agentlas cloud runtime bundle <path> [--json]");
|
|
448
|
+
const root = flags._[0];
|
|
380
449
|
ctx.out(JSON.stringify(cloudRuntime.compileBundle(root), null, 2));
|
|
381
450
|
return 0;
|
|
382
451
|
}
|
|
383
452
|
if (action === "read-agent-file") {
|
|
384
|
-
const
|
|
385
|
-
|
|
386
|
-
|
|
453
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(2), {
|
|
454
|
+
values: [], booleans: ["json"],
|
|
455
|
+
}), 2, 2, "usage: agentlas cloud runtime read-agent-file <path> <file> [--json]");
|
|
456
|
+
const [root, targetPath] = flags._;
|
|
387
457
|
ctx.out(JSON.stringify(cloudRuntime.readAgentFile(root, targetPath), null, 2));
|
|
388
458
|
return 0;
|
|
389
459
|
}
|
|
@@ -391,15 +461,20 @@ async function runCloud(ctx, args) {
|
|
|
391
461
|
return 1;
|
|
392
462
|
}
|
|
393
463
|
if (sub === "field-test") {
|
|
394
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
464
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
465
|
+
values: [], booleans: ["json"],
|
|
466
|
+
}), 0, 0, "usage: agentlas cloud field-test [--json]");
|
|
395
467
|
const result = cloudRuntime.runFieldTest();
|
|
396
468
|
ctx.out(flags.json ? JSON.stringify(result, null, 2) : `${result.suite}: ${result.status}`);
|
|
397
469
|
return result.status === "PASS" ? 0 : 1;
|
|
398
470
|
}
|
|
399
471
|
if (sub === "install") {
|
|
400
|
-
const
|
|
401
|
-
|
|
472
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
473
|
+
values: [], booleans: ["json"],
|
|
474
|
+
}), 1, 1, "usage: agentlas cloud install <slug> [--json]");
|
|
475
|
+
const slug = flags._[0];
|
|
402
476
|
const agent = await installHubAgent(ctx.db(), slug);
|
|
477
|
+
if (flags.json) { ctx.out(JSON.stringify(agent, null, 2)); return 0; }
|
|
403
478
|
ctx.out(`${ctx.ui.green("✓")} Hub installed ${agent.slug} — ${agent.name}`);
|
|
404
479
|
if (agent.localPath) ctx.out(` files: ${agent.localPath}`);
|
|
405
480
|
return 0;
|
|
@@ -408,7 +483,10 @@ async function runCloud(ctx, args) {
|
|
|
408
483
|
ctx.err("usage: agentlas cloud <save|publish|package|list|restore|install|delete|field-test> ...");
|
|
409
484
|
return 1;
|
|
410
485
|
}
|
|
411
|
-
const flags = parseCloudFlags(args.slice(1)
|
|
486
|
+
const flags = requireCloudPositionals(parseCloudFlags(args.slice(1), {
|
|
487
|
+
values: ["purpose", "slug", "visibility"],
|
|
488
|
+
booleans: ["dry-run", "json", "llm-review", "overwrite"],
|
|
489
|
+
}), 1, 1, `usage: agentlas cloud ${sub} <path>`);
|
|
412
490
|
const root = flags._[0];
|
|
413
491
|
if (!root) { ctx.err(`usage: agentlas cloud ${sub} <path>`); return 1; }
|
|
414
492
|
const visibility = cloudVisibilityForAction(sub, flags);
|
|
@@ -52,6 +52,7 @@ const cas = require("./cas.cjs");
|
|
|
52
52
|
// 터미널 업로드가 그 파일들을 아예 열지 않았다.
|
|
53
53
|
const CLOUD_TEXT_EXTS = new Set(SECRET_SCAN_TEXT_EXTENSIONS);
|
|
54
54
|
const CLOUD_AGENT_FILES = new Set(UPLOAD_AGENT_DEFINITION_FILES);
|
|
55
|
+
const CLOUD_AGENT_FILE_KEYS = new Set([...CLOUD_AGENT_FILES].map((name) => name.toLowerCase()));
|
|
55
56
|
const CLOUD_SKIP_DIRS = new Set(UPLOAD_SKIP_DIRECTORIES);
|
|
56
57
|
const CLOUD_BLOCKED_FILE_RE = [/^\.env(?:\..*)?$/i, /^id_rsa(?:\.pub)?$/i, /^credentials(?:\..*)?$/i, /^secrets?(?:\..*)?$/i, /^cloud-asset-state\.v1\.json$/i, /(?:^|[._-])service-account(?:[._-]|$)/i, /\.(?:key|pem|p12|pfx|mobileprovision)$/i];
|
|
57
58
|
const CLOUD_ROUTING_CARD_PATH = ".agentlas/routing-card.json";
|
|
@@ -385,7 +386,11 @@ const CLOUD_BULK_DATA_RE = /\.(log|jsonl|csv|tsv|lock)$/;
|
|
|
385
386
|
function cloudTrimRank(rel, bytes) {
|
|
386
387
|
const lower = String(rel || "").toLowerCase();
|
|
387
388
|
const base = lower.split("/").pop() || lower;
|
|
388
|
-
|
|
389
|
+
// The generated catalog intentionally carries case-distinct root names
|
|
390
|
+
// (`AGENTS.md`, `AGENT.md`, `agent.md`). Ranking lower-cases paths, so the
|
|
391
|
+
// lookup must lower-case the catalog as well. Otherwise a package at the
|
|
392
|
+
// byte limit can evict AGENTS.md while retaining an unrelated cache file.
|
|
393
|
+
if (CLOUD_AGENT_FILE_KEYS.has(base)) return 0;
|
|
389
394
|
if (lower.startsWith(".agentlas/")) return 0;
|
|
390
395
|
if (base === "agentlas.json" || base === "manifest.json" || base === "package.json") return 0;
|
|
391
396
|
if (CLOUD_CAPABILITY_DIR_RE.test(lower)) return 0;
|
|
@@ -427,13 +432,16 @@ function scanCloudFolder(rootPath) {
|
|
|
427
432
|
let freed = 0;
|
|
428
433
|
while (totalBytes - freed + needBytes > CLOUD_MAX_TOTAL_BYTES) {
|
|
429
434
|
let victimIndex = -1;
|
|
430
|
-
let victimRank =
|
|
435
|
+
let victimRank = Number.POSITIVE_INFINITY;
|
|
431
436
|
let victimBytes = -1;
|
|
432
437
|
for (let index = 0; index < included.length; index += 1) {
|
|
433
438
|
const candidate = included[index];
|
|
434
439
|
const rank = cloudTrimRank(candidate.path, candidate.bytes);
|
|
435
440
|
if (rank === 0) continue;
|
|
436
|
-
|
|
441
|
+
// Rank 1 is disposable build/cache output; larger numbers are closer
|
|
442
|
+
// to ordinary authored content. Desktop's canonical trimmer removes
|
|
443
|
+
// the smallest positive rank first, then the largest file in that tier.
|
|
444
|
+
if (rank < victimRank || (rank === victimRank && candidate.bytes > victimBytes)) {
|
|
437
445
|
victimIndex = index;
|
|
438
446
|
victimRank = rank;
|
|
439
447
|
victimBytes = candidate.bytes;
|
|
@@ -709,6 +717,60 @@ function scanCloudFolder(rootPath) {
|
|
|
709
717
|
return { files, included, findings, omissions, totalBytes, localPackageMarker };
|
|
710
718
|
}
|
|
711
719
|
|
|
720
|
+
/**
|
|
721
|
+
* Generated metadata is added after the stable source scan. Re-apply the
|
|
722
|
+
* public package limits at that exact boundary so injecting agentlas.json (or
|
|
723
|
+
* replacing a redacted public card) cannot turn a valid 400-file scan into a
|
|
724
|
+
* 401-file bundle that the server will reject.
|
|
725
|
+
*/
|
|
726
|
+
function cloudFitGeneratedMetadataToLimits(scan) {
|
|
727
|
+
const removeVictim = () => {
|
|
728
|
+
let victimIndex = -1;
|
|
729
|
+
let victimRank = Number.POSITIVE_INFINITY;
|
|
730
|
+
let victimBytes = -1;
|
|
731
|
+
for (let index = 0; index < scan.included.length; index += 1) {
|
|
732
|
+
const candidate = scan.included[index];
|
|
733
|
+
const rank = cloudTrimRank(candidate.path, candidate.bytes);
|
|
734
|
+
if (rank === 0) continue;
|
|
735
|
+
if (rank < victimRank || (rank === victimRank && candidate.bytes > victimBytes)) {
|
|
736
|
+
victimIndex = index;
|
|
737
|
+
victimRank = rank;
|
|
738
|
+
victimBytes = candidate.bytes;
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
if (victimIndex < 0) return false;
|
|
742
|
+
const victim = scan.included.splice(victimIndex, 1)[0];
|
|
743
|
+
scan.omissions.push({
|
|
744
|
+
path: victim.path,
|
|
745
|
+
reason: "trimmed-for-package-limits",
|
|
746
|
+
sourceBytes: victim.bytes,
|
|
747
|
+
sourceSha256: victim.sha256,
|
|
748
|
+
sourceHashKind: "content",
|
|
749
|
+
});
|
|
750
|
+
const record = scan.files.find((item) => item.path === victim.path && item.included);
|
|
751
|
+
if (record) {
|
|
752
|
+
record.included = false;
|
|
753
|
+
record.reason = "trimmed-for-package-limits";
|
|
754
|
+
}
|
|
755
|
+
return true;
|
|
756
|
+
};
|
|
757
|
+
|
|
758
|
+
scan.totalBytes = scan.included.reduce((sum, file) => sum + file.bytes, 0);
|
|
759
|
+
while (scan.included.length > CLOUD_MAX_FILES || scan.totalBytes > CLOUD_MAX_TOTAL_BYTES) {
|
|
760
|
+
if (!removeVictim()) {
|
|
761
|
+
const error = new Error(
|
|
762
|
+
"Agent Cloud package cannot fit required agent metadata within the package limits. " +
|
|
763
|
+
"Reduce the number or size of capability files and retry.",
|
|
764
|
+
);
|
|
765
|
+
error.code = "AGENTLAS_CLOUD_PACKAGE_LIMITS";
|
|
766
|
+
throw error;
|
|
767
|
+
}
|
|
768
|
+
scan.totalBytes = scan.included.reduce((sum, file) => sum + file.bytes, 0);
|
|
769
|
+
}
|
|
770
|
+
scan.included.sort(cloudCodePointPathOrder);
|
|
771
|
+
scan.omissions.sort(cloudCodePointPathOrder);
|
|
772
|
+
}
|
|
773
|
+
|
|
712
774
|
function cloudOmissionReceipt(omissions) {
|
|
713
775
|
if (!Array.isArray(omissions) || omissions.length === 0) return undefined;
|
|
714
776
|
const entries = omissions.map((entry) => ({
|
|
@@ -1074,6 +1136,7 @@ async function packageCloudAgent(db, root, opts = {}) {
|
|
|
1074
1136
|
}
|
|
1075
1137
|
// 신원은 해시 계산 전에 채운다 — 클라우드 해시는 agentlas.json 을 포함한다.
|
|
1076
1138
|
cloudEnsureAgentIdentity(scan, snapshot, rootPath.split("/").pop());
|
|
1139
|
+
cloudFitGeneratedMetadataToLimits(scan);
|
|
1077
1140
|
snapshot = cloudPackageSnapshot(scan.included);
|
|
1078
1141
|
const routingCard = isPublicHubPublish ? readCloudRoutingCard(snapshot) : {};
|
|
1079
1142
|
if (routingCard.finding) scan.findings.push(routingCard.finding);
|
|
@@ -30,15 +30,18 @@ async function listOwnedCloudAgents(limit = 100) {
|
|
|
30
30
|
};
|
|
31
31
|
if (!Array.isArray(result.results)) throw new Error("Agent Cloud list returned an invalid results contract.");
|
|
32
32
|
if (result.results.length) {
|
|
33
|
-
const
|
|
34
|
-
|
|
35
|
-
const descriptor
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
33
|
+
const descriptors = result.results.map((raw) => normalizeCloudAssetDescriptor(raw, "Agent Cloud list result"));
|
|
34
|
+
state.updateCloudAssetState((stateValue) => {
|
|
35
|
+
for (const descriptor of descriptors) {
|
|
36
|
+
const key = state.cloudDescriptorKey(descriptor);
|
|
37
|
+
const previous = stateValue.assets[key];
|
|
38
|
+
// A list response may race a save that completed after the server made
|
|
39
|
+
// the list snapshot. Never regress a newer locally observed receipt.
|
|
40
|
+
if (previous && Date.parse(previous.descriptor.updatedAt) > Date.parse(descriptor.updatedAt)) continue;
|
|
41
|
+
const preserveRoots = previous && previous.descriptor.cloudId === descriptor.cloudId && previous.descriptor.revision === descriptor.revision;
|
|
42
|
+
stateValue.assets[key] = { descriptor, sourceRoots: preserveRoots ? previous.sourceRoots : [] };
|
|
43
|
+
}
|
|
44
|
+
});
|
|
42
45
|
}
|
|
43
46
|
return result;
|
|
44
47
|
}
|