@taicho-ai/framework 0.1.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.
Files changed (75) hide show
  1. package/README.md +4 -0
  2. package/package.json +48 -0
  3. package/src/coaching/patterns.ts +103 -0
  4. package/src/coaching/proposal.ts +29 -0
  5. package/src/coaching/retrieval.ts +27 -0
  6. package/src/coaching/supersede.ts +14 -0
  7. package/src/coaching/teach.ts +74 -0
  8. package/src/core/agent-status.ts +79 -0
  9. package/src/core/auth/constants.ts +53 -0
  10. package/src/core/auth/login.ts +110 -0
  11. package/src/core/auth/pkce.ts +18 -0
  12. package/src/core/auth/profile.ts +38 -0
  13. package/src/core/auth/refresh.ts +57 -0
  14. package/src/core/auth/status.ts +26 -0
  15. package/src/core/command-guard.ts +126 -0
  16. package/src/core/conversation-artifacts.ts +40 -0
  17. package/src/core/conversation-replay.ts +160 -0
  18. package/src/core/costs.ts +97 -0
  19. package/src/core/discovery.ts +22 -0
  20. package/src/core/draft.ts +6 -0
  21. package/src/core/e2e-model.ts +315 -0
  22. package/src/core/embed.ts +221 -0
  23. package/src/core/events.ts +133 -0
  24. package/src/core/firecrawl.ts +25 -0
  25. package/src/core/headless.ts +260 -0
  26. package/src/core/instrument.ts +88 -0
  27. package/src/core/logger.ts +143 -0
  28. package/src/core/mcp/adapter.ts +34 -0
  29. package/src/core/mcp/manager.ts +145 -0
  30. package/src/core/mcp/oauth.ts +119 -0
  31. package/src/core/memory.ts +13 -0
  32. package/src/core/mock-model.ts +70 -0
  33. package/src/core/model.ts +91 -0
  34. package/src/core/pricing.ts +27 -0
  35. package/src/core/providers/openai-codex.ts +67 -0
  36. package/src/core/registry.ts +67 -0
  37. package/src/core/run.ts +909 -0
  38. package/src/core/schedule-cli.ts +55 -0
  39. package/src/core/scheduler.ts +356 -0
  40. package/src/core/tasks.ts +108 -0
  41. package/src/core/team-cli.ts +118 -0
  42. package/src/core/team-routing.ts +58 -0
  43. package/src/core/tools.ts +1104 -0
  44. package/src/core/turn-audit.ts +100 -0
  45. package/src/core/verification.ts +102 -0
  46. package/src/core/workflow-run.ts +119 -0
  47. package/src/index.ts +8 -0
  48. package/src/knowledge/retrieval.ts +73 -0
  49. package/src/knowledge/sync.ts +28 -0
  50. package/src/skills/retrieval.ts +22 -0
  51. package/src/store/annotations.ts +107 -0
  52. package/src/store/artifacts.ts +338 -0
  53. package/src/store/config.ts +187 -0
  54. package/src/store/conversation.ts +107 -0
  55. package/src/store/db.ts +34 -0
  56. package/src/store/files.ts +51 -0
  57. package/src/store/knowledge.ts +201 -0
  58. package/src/store/mcp-store.ts +65 -0
  59. package/src/store/migrate.ts +278 -0
  60. package/src/store/plans.ts +260 -0
  61. package/src/store/policy.ts +66 -0
  62. package/src/store/prefs.ts +64 -0
  63. package/src/store/roster.ts +308 -0
  64. package/src/store/run-transcript.ts +103 -0
  65. package/src/store/schedules.ts +94 -0
  66. package/src/store/seed-skills.ts +75 -0
  67. package/src/store/skills.ts +89 -0
  68. package/src/store/sources.ts +58 -0
  69. package/src/store/spend-ledger.ts +114 -0
  70. package/src/store/task-state.ts +267 -0
  71. package/src/store/teams.ts +227 -0
  72. package/src/store/thread.ts +72 -0
  73. package/src/store/trace.ts +98 -0
  74. package/src/store/vectors.ts +26 -0
  75. package/src/store/workflows.ts +144 -0
@@ -0,0 +1,58 @@
1
+ /** Plan 19: resolving `delegate_task(to: "news")` to the agent that will actually run.
2
+ *
3
+ * A PURE function — no DB, no files, no model. The caller supplies the team, its members, and the
4
+ * chain of agents already above this delegation. Two shapes:
5
+ *
6
+ * · a team with a LEAD routes to the lead, an ordinary agent that then delegates within its team.
7
+ * Costs one delegation level and one model call.
8
+ * · a team WITHOUT a lead is routed by the engine: the best-ranked member takes the goal directly.
9
+ * Costs neither. Leadless is the right default; a team that needs editorial judgment has a lead.
10
+ *
11
+ * The routing decision is never silent. `why` is surfaced to the captain as a note breadcrumb and
12
+ * recorded on the trace, because rankAgents is a keyword match and will sometimes pick badly — a bad
13
+ * pick you can see is a bug report, a bad pick you can't is a mystery. */
14
+ import type { TeamDef } from "@taicho-ai/contracts/team";
15
+ import { rankAgents } from "./discovery";
16
+
17
+ export interface RouteCandidate { id: string; role: string }
18
+ export interface TeamRouteOk { ok: true; agentId: string; why: string }
19
+ export interface TeamRouteErr { ok: false; error: string }
20
+ export type TeamRoute = TeamRouteOk | TeamRouteErr;
21
+
22
+ /** @param exclude agent ids already in this delegation chain (the caller and its ancestors). Routing
23
+ * to any of them would close a cycle, so they are never candidates. */
24
+ export function routeToTeam(team: TeamDef, members: RouteCandidate[], goal: string, exclude: string[]): TeamRoute {
25
+ const blocked = new Set(exclude);
26
+
27
+ if (team.lead) {
28
+ // A lead may not address its own team: it would resolve straight back to itself. This is the one
29
+ // self-loop the resolution creates that the generic cycle guard would report confusingly.
30
+ if (blocked.has(team.lead))
31
+ return {
32
+ ok: false,
33
+ error: `team "${team.id}" routes to its lead "${team.lead}", which is already in this delegation chain — a lead cannot address its own team`,
34
+ };
35
+ if (!members.some((m) => m.id === team.lead))
36
+ return { ok: false, error: `team "${team.id}" names lead "${team.lead}", which is not a member of it` };
37
+ return { ok: true, agentId: team.lead, why: "lead" };
38
+ }
39
+
40
+ const candidates = members.filter((m) => !blocked.has(m.id));
41
+ if (!candidates.length)
42
+ return {
43
+ ok: false,
44
+ error: members.length
45
+ ? `team "${team.id}" has no member outside this delegation chain`
46
+ : `team "${team.id}" has no members`,
47
+ };
48
+
49
+ // rankAgents skips is_root rows; a team member is never root, so 0 is the honest value here.
50
+ const [best] = rankAgents(candidates.map((c) => ({ ...c, is_root: 0 })), goal, 1);
51
+ // rankAgents returns nothing when no term overlaps. Fall back to the first candidate by id rather
52
+ // than failing: an unranked pick is still a working delegation, and `why` says exactly what happened.
53
+ if (!best) {
54
+ const first = [...candidates].sort((a, b) => a.id.localeCompare(b.id))[0]!;
55
+ return { ok: true, agentId: first.id, why: "no capability match; first member by id" };
56
+ }
57
+ return { ok: true, agentId: best.id, why: `ranked ${best.score} on capability` };
58
+ }