@agent-team-foundation/first-tree-hub 0.3.0 → 0.3.1

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.
@@ -1,9 +1,12 @@
1
1
  #!/usr/bin/env node
2
- import { A as SessionRegistry, B as clientConfigSchema, C as stopPostgres, D as DEFAULT_WORKSPACE_TTL_MS, E as AgentSlot, F as createAdminUser, G as resetConfig, H as initConfig, J as setConfigValue, K as resetConfigMeta, L as DEFAULT_CONFIG_DIR, M as getHandlerFactory, N as loadRuntimeConfig, O as FirstTreeHubSDK, P as registerBuiltinHandlers, R as DEFAULT_DATA_DIR, T as AgentRuntime, U as loadAgents, V as getConfigValue, W as readConfigFile, _ as checkWebSocket, a as runMigrations, c as checkClientConfig, d as checkDocker, f as checkGitHubToken, g as checkServerReachable, h as checkServerHealth, i as promptMissingFields, j as cleanWorkspaces, k as SdkError, l as checkContextTreeRepo, m as checkServerConfig, o as checkAgentConfigs, p as checkNodeVersion, q as serverConfigSchema, r as promptAddAgent, s as checkAgentTokens, t as startServer, u as checkDatabase, v as printResults, w as ClientRuntime, z as agentConfigSchema } from "../core-uG-Hkr9K.mjs";
2
+ import { _ as resetConfig, b as serverConfigSchema, c as DEFAULT_CONFIG_DIR, d as clientConfigSchema, g as readConfigFile, h as loadAgents, l as DEFAULT_DATA_DIR, m as initConfig, o as resolveAgentToken, p as getConfigValue, s as resolveServerUrl, t as bootstrapToken, u as agentConfigSchema, v as resetConfigMeta, x as setConfigValue } from "../bootstrap-B9JsJR3Z.mjs";
3
+ import { A as ClientRuntime, B as registerBuiltinHandlers, C as checkWebSocket, F as SdkError, I as SessionRegistry, L as cleanWorkspaces, M as AgentSlot, N as DEFAULT_WORKSPACE_TTL_MS, P as FirstTreeHubSDK, R as getHandlerFactory, S as checkServerReachable, V as createAdminUser, _ as checkDocker, a as formatCheckReport, b as checkServerConfig, c as onboardContinue, d as runMigrations, f as checkAgentConfigs, g as checkDatabase, h as checkContextTreeRepo, i as promptMissingFields, j as AgentRuntime, k as stopPostgres, l as onboardCreate, m as checkClientConfig, n as isInteractive, o as loadOnboardState, p as checkAgentTokens, r as promptAddAgent, s as onboardCheck, t as startServer, u as saveOnboardState, v as checkGitHubToken, w as printResults, x as checkServerHealth, y as checkNodeVersion, z as loadRuntimeConfig } from "../core-D-c9r7D6.mjs";
4
+ import { n as bindFeishuUser, t as bindFeishuBot } from "../feishu-Y4m2zFc3.mjs";
3
5
  import { createRequire } from "node:module";
4
6
  import { Command } from "commander";
5
7
  import { existsSync, mkdirSync, readdirSync, rmSync } from "node:fs";
6
8
  import { join } from "node:path";
9
+ import { confirm, input, select } from "@inquirer/prompts";
7
10
  //#region src/commands/admin.ts
8
11
  function registerAdminCommands(program) {
9
12
  program.command("admin").description("Admin user management").command("create").description("Create an admin user").option("-u, --username <name>", "Admin username", "admin").option("-p, --password <pass>", "Admin password (auto-generated if omitted)").action(async (options) => {
@@ -84,6 +87,37 @@ function registerAgentCommands(program) {
84
87
  });
85
88
  }
86
89
  //#endregion
90
+ //#region src/commands/bind.ts
91
+ function registerBindCommands(program) {
92
+ program.command("bind-bot").description("Bind a Feishu bot to this agent (self-service)").requiredOption("--platform <platform>", "Platform: feishu").requiredOption("--app-id <id>", "Feishu bot App ID").requiredOption("--app-secret <secret>", "Feishu bot App Secret").option("--server <url>", "Hub server URL").action(async (options) => {
93
+ try {
94
+ if (options.platform !== "feishu") fail("UNSUPPORTED_PLATFORM", `Platform "${options.platform}" is not supported. Use "feishu".`);
95
+ await bindFeishuBot(resolveServerUrl(options.server), resolveAgentToken(), options.appId, options.appSecret);
96
+ process.stderr.write("Feishu bot bound successfully.\n");
97
+ success({
98
+ platform: "feishu",
99
+ bound: true
100
+ });
101
+ } catch (error) {
102
+ fail("BIND_BOT_ERROR", error instanceof Error ? error.message : String(error));
103
+ }
104
+ });
105
+ program.command("bind-user <humanAgentId>").description("Bind a Feishu user to a human agent (via delegate_mention)").requiredOption("--platform <platform>", "Platform: feishu").requiredOption("--feishu-id <id>", "Feishu user ID (ou_xxx)").option("--server <url>", "Hub server URL").action(async (humanAgentId, options) => {
106
+ try {
107
+ if (options.platform !== "feishu") fail("UNSUPPORTED_PLATFORM", `Platform "${options.platform}" is not supported. Use "feishu".`);
108
+ await bindFeishuUser(resolveServerUrl(options.server), resolveAgentToken(), humanAgentId, options.feishuId);
109
+ process.stderr.write(`Feishu user ${options.feishuId} bound to ${humanAgentId}.\n`);
110
+ success({
111
+ platform: "feishu",
112
+ humanAgentId,
113
+ feishuUserId: options.feishuId
114
+ });
115
+ } catch (error) {
116
+ fail("BIND_USER_ERROR", error instanceof Error ? error.message : String(error));
117
+ }
118
+ });
119
+ }
120
+ //#endregion
87
121
  //#region src/cli/util.ts
88
122
  function resolveConfig() {
89
123
  const token = process.env.FIRST_TREE_HUB_TOKEN;
@@ -422,6 +456,142 @@ function registerHistoryCommand(program) {
422
456
  });
423
457
  }
424
458
  //#endregion
459
+ //#region src/commands/onboard.ts
460
+ async function promptMissing(args) {
461
+ let ghUsername = null;
462
+ try {
463
+ const { getGitHubUsername } = await import("../bootstrap-B9JsJR3Z.mjs").then((n) => n.n);
464
+ ghUsername = getGitHubUsername();
465
+ } catch {}
466
+ if (!args.id) {
467
+ args.id = await input({
468
+ message: "Member ID (directory name):",
469
+ default: ghUsername ?? void 0
470
+ });
471
+ saveOnboardState(args);
472
+ }
473
+ if (!args.type) {
474
+ args.type = await select({
475
+ message: "Agent type:",
476
+ choices: [
477
+ {
478
+ name: "human",
479
+ value: "human"
480
+ },
481
+ {
482
+ name: "personal_assistant",
483
+ value: "personal_assistant"
484
+ },
485
+ {
486
+ name: "autonomous_agent",
487
+ value: "autonomous_agent"
488
+ }
489
+ ]
490
+ });
491
+ saveOnboardState(args);
492
+ }
493
+ if (!args.role) {
494
+ args.role = await input({ message: "Role:" });
495
+ saveOnboardState(args);
496
+ }
497
+ if (!args.domains) {
498
+ args.domains = await input({ message: "Domains (comma-separated):" });
499
+ saveOnboardState(args);
500
+ }
501
+ if (!args.displayName) {
502
+ const name = await input({ message: `Display name (Enter to use "${args.id}"):` });
503
+ if (name) {
504
+ args.displayName = name;
505
+ saveOnboardState(args);
506
+ }
507
+ }
508
+ if (!args.assistant) {
509
+ if (await confirm({
510
+ message: "Create a personal assistant?",
511
+ default: false
512
+ })) {
513
+ args.assistant = await input({
514
+ message: "Assistant ID:",
515
+ default: `${args.id}-assistant`
516
+ });
517
+ saveOnboardState(args);
518
+ }
519
+ }
520
+ if (!args.server) try {
521
+ const { resolveServerUrl } = await import("../bootstrap-B9JsJR3Z.mjs").then((n) => n.n);
522
+ resolveServerUrl();
523
+ } catch {
524
+ args.server = await input({ message: "Hub server URL:" });
525
+ saveOnboardState(args);
526
+ }
527
+ if (!args.feishuBotAppId) {
528
+ if (await confirm({
529
+ message: "Bind Feishu bot?",
530
+ default: false
531
+ })) {
532
+ args.feishuBotAppId = await input({ message: "Feishu App ID:" });
533
+ args.feishuBotAppSecret = await input({ message: "Feishu App Secret:" });
534
+ saveOnboardState(args);
535
+ }
536
+ }
537
+ }
538
+ function registerOnboardCommand(program) {
539
+ program.command("onboard").description("Onboard a new member to First Tree Hub (end-to-end)").option("--id <id>", "Member ID (directory name)").option("--type <type>", "Agent type: human | personal_assistant | autonomous_agent").option("--display-name <name>", "Display name (defaults to id)").option("--role <role>", "Role description").option("--domains <domains>", "Comma-separated domains").option("--assistant <id>", "Also create a personal_assistant with this ID").option("--delegate-mention <id>", "Set delegate_mention field").option("--server <url>", "Hub server URL").option("--feishu-bot-app-id <id>", "Feishu bot App ID").option("--feishu-bot-app-secret <secret>", "Feishu bot App Secret").option("--check", "Dry-run: show readiness checklist without executing").option("--continue", "Resume after PR merge (Phase 2)").action(async (options) => {
540
+ try {
541
+ const args = {
542
+ ...loadOnboardState() ?? {},
543
+ ...options.id && { id: options.id },
544
+ ...options.type && { type: options.type },
545
+ ...options.displayName && { displayName: options.displayName },
546
+ ...options.role && { role: options.role },
547
+ ...options.domains && { domains: options.domains },
548
+ ...options.assistant && { assistant: options.assistant },
549
+ ...options.delegateMention && { delegateMention: options.delegateMention },
550
+ ...options.server && { server: options.server },
551
+ ...options.feishuBotAppId && { feishuBotAppId: options.feishuBotAppId },
552
+ ...options.feishuBotAppSecret && { feishuBotAppSecret: options.feishuBotAppSecret },
553
+ check: options.check,
554
+ continue: options.continue
555
+ };
556
+ if (!args.feishuBotAppId && process.env.FEISHU_APP_ID) args.feishuBotAppId = process.env.FEISHU_APP_ID;
557
+ if (!args.feishuBotAppSecret && process.env.FEISHU_APP_SECRET) args.feishuBotAppSecret = process.env.FEISHU_APP_SECRET;
558
+ if (args.continue) {
559
+ await onboardContinue(args);
560
+ return;
561
+ }
562
+ if (args.check) {
563
+ const items = await onboardCheck(args);
564
+ const report = formatCheckReport(items);
565
+ process.stderr.write(`\nOnboard Check: ${args.id ?? "(no id)"}\n\n${report}\n\n`);
566
+ if (items.some((i) => i.status === "missing_required" || i.status === "error")) process.exit(1);
567
+ return;
568
+ }
569
+ if (isInteractive()) await promptMissing(args);
570
+ const items = await onboardCheck(args);
571
+ if (items.some((i) => i.status === "missing_required" || i.status === "error")) {
572
+ const report = formatCheckReport(items);
573
+ process.stderr.write(`\nOnboard Check: ${args.id ?? "(no id)"}\n\n${report}\n\n`);
574
+ fail("MISSING_PARAMS", "Required parameters are missing. See checklist above.");
575
+ }
576
+ const result = await onboardCreate(args);
577
+ process.stderr.write(`\nPR created: ${result.prUrl}\n`);
578
+ process.stderr.write("Review and merge the PR, then run:\n");
579
+ process.stderr.write(" first-tree-hub onboard --continue\n\n");
580
+ success({
581
+ phase: "create",
582
+ prUrl: result.prUrl
583
+ });
584
+ } catch (error) {
585
+ const msg = error instanceof Error ? error.message : String(error);
586
+ if (isInteractive()) {
587
+ process.stderr.write(`\n❌ ${msg}\n\n`);
588
+ process.exit(1);
589
+ }
590
+ fail("ONBOARD_ERROR", msg);
591
+ }
592
+ });
593
+ }
594
+ //#endregion
425
595
  //#region src/commands/send.ts
426
596
  const MAX_STDIN_BYTES = 10 * 1024 * 1024;
427
597
  /** Read all of stdin as a string. Returns null if stdin is a TTY. */
@@ -582,6 +752,23 @@ function formatUptime(seconds) {
582
752
  return `${mins}m`;
583
753
  }
584
754
  //#endregion
755
+ //#region src/commands/token.ts
756
+ function registerTokenCommands(program) {
757
+ program.command("token").description("Agent token management").command("bootstrap <agentId>").description("Bootstrap a token using GitHub identity (requires gh CLI)").option("--save-to <target>", "Save token to: \"agent\" (default) or a file path", "agent").option("--server <url>", "Hub server URL").action(async (agentId, options) => {
758
+ try {
759
+ const result = await bootstrapToken(resolveServerUrl(options.server), agentId, { saveTo: options.saveTo });
760
+ if (options.saveTo === "agent") process.stderr.write(`Token saved to ~/.first-tree-hub/agents/${agentId}/agent.yaml\n`);
761
+ else process.stderr.write(`Token saved to ${options.saveTo}\n`);
762
+ success({
763
+ agentId: result.agentId,
764
+ tokenSaved: true
765
+ });
766
+ } catch (error) {
767
+ fail("BOOTSTRAP_ERROR", error instanceof Error ? error.message : String(error));
768
+ }
769
+ });
770
+ }
771
+ //#endregion
585
772
  //#region src/cli/connect.ts
586
773
  function registerConnectCommand(program) {
587
774
  program.command("connect").description("Connect a single agent to server and process messages").option("-t, --type <type>", "Handler type", "claude-code").option("--concurrency <n>", "Max parallel message processing", "5").option("--server <url>", "Override FIRST_TREE_HUB_SERVER").action(async (options) => {
@@ -655,6 +842,9 @@ registerStatusCommand(program);
655
842
  registerConnectCommand(program);
656
843
  registerStartCommand(program);
657
844
  registerAgentCommands(program);
845
+ registerOnboardCommand(program);
846
+ registerTokenCommands(program);
847
+ registerBindCommands(program);
658
848
  registerSendCommand(program);
659
849
  registerChatsCommand(program);
660
850
  registerHistoryCommand(program);