londai 0.1.0-alpha.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 (102) hide show
  1. package/LICENSE +21 -0
  2. package/dist/bin-create.d.ts +3 -0
  3. package/dist/bin-create.d.ts.map +1 -0
  4. package/dist/bin-create.js +3 -0
  5. package/dist/bin-create.js.map +1 -0
  6. package/dist/bin.d.ts +3 -0
  7. package/dist/bin.d.ts.map +1 -0
  8. package/dist/bin.js +3 -0
  9. package/dist/bin.js.map +1 -0
  10. package/dist/config-loader.d.ts +12 -0
  11. package/dist/config-loader.d.ts.map +1 -0
  12. package/dist/config-loader.js +22 -0
  13. package/dist/config-loader.js.map +1 -0
  14. package/dist/define-agent.d.ts +34 -0
  15. package/dist/define-agent.d.ts.map +1 -0
  16. package/dist/define-agent.js +38 -0
  17. package/dist/define-agent.js.map +1 -0
  18. package/dist/define-config.d.ts +27 -0
  19. package/dist/define-config.d.ts.map +1 -0
  20. package/dist/define-config.js +88 -0
  21. package/dist/define-config.js.map +1 -0
  22. package/dist/define-skill.d.ts +10 -0
  23. package/dist/define-skill.d.ts.map +1 -0
  24. package/dist/define-skill.js +45 -0
  25. package/dist/define-skill.js.map +1 -0
  26. package/dist/define-tool.d.ts +27 -0
  27. package/dist/define-tool.d.ts.map +1 -0
  28. package/dist/define-tool.js +44 -0
  29. package/dist/define-tool.js.map +1 -0
  30. package/dist/errors.d.ts +29 -0
  31. package/dist/errors.d.ts.map +1 -0
  32. package/dist/errors.js +88 -0
  33. package/dist/errors.js.map +1 -0
  34. package/dist/index.d.ts +25 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +24 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/logger.d.ts +12 -0
  39. package/dist/logger.d.ts.map +1 -0
  40. package/dist/logger.js +69 -0
  41. package/dist/logger.js.map +1 -0
  42. package/dist/londai.d.ts +15 -0
  43. package/dist/londai.d.ts.map +1 -0
  44. package/dist/londai.js +74 -0
  45. package/dist/londai.js.map +1 -0
  46. package/dist/registry.d.ts +57 -0
  47. package/dist/registry.d.ts.map +1 -0
  48. package/dist/registry.js +130 -0
  49. package/dist/registry.js.map +1 -0
  50. package/dist/server/abort.d.ts +23 -0
  51. package/dist/server/abort.d.ts.map +1 -0
  52. package/dist/server/abort.js +35 -0
  53. package/dist/server/abort.js.map +1 -0
  54. package/dist/server/agent-builder.d.ts +49 -0
  55. package/dist/server/agent-builder.d.ts.map +1 -0
  56. package/dist/server/agent-builder.js +107 -0
  57. package/dist/server/agent-builder.js.map +1 -0
  58. package/dist/server/app.d.ts +21 -0
  59. package/dist/server/app.d.ts.map +1 -0
  60. package/dist/server/app.js +34 -0
  61. package/dist/server/app.js.map +1 -0
  62. package/dist/server/middleware/auth.d.ts +23 -0
  63. package/dist/server/middleware/auth.d.ts.map +1 -0
  64. package/dist/server/middleware/auth.js +102 -0
  65. package/dist/server/middleware/auth.js.map +1 -0
  66. package/dist/server/middleware/error.d.ts +10 -0
  67. package/dist/server/middleware/error.d.ts.map +1 -0
  68. package/dist/server/middleware/error.js +17 -0
  69. package/dist/server/middleware/error.js.map +1 -0
  70. package/dist/server/middleware/rate-limit.d.ts +18 -0
  71. package/dist/server/middleware/rate-limit.d.ts.map +1 -0
  72. package/dist/server/middleware/rate-limit.js +55 -0
  73. package/dist/server/middleware/rate-limit.js.map +1 -0
  74. package/dist/server/routes/approve.d.ts +11 -0
  75. package/dist/server/routes/approve.d.ts.map +1 -0
  76. package/dist/server/routes/approve.js +38 -0
  77. package/dist/server/routes/approve.js.map +1 -0
  78. package/dist/server/routes/chat-completion.d.ts +14 -0
  79. package/dist/server/routes/chat-completion.d.ts.map +1 -0
  80. package/dist/server/routes/chat-completion.js +70 -0
  81. package/dist/server/routes/chat-completion.js.map +1 -0
  82. package/dist/server/routes/chat-stream.d.ts +29 -0
  83. package/dist/server/routes/chat-stream.d.ts.map +1 -0
  84. package/dist/server/routes/chat-stream.js +190 -0
  85. package/dist/server/routes/chat-stream.js.map +1 -0
  86. package/dist/server/routes/common.d.ts +47 -0
  87. package/dist/server/routes/common.d.ts.map +1 -0
  88. package/dist/server/routes/common.js +143 -0
  89. package/dist/server/routes/common.js.map +1 -0
  90. package/dist/server/routes/session.d.ts +22 -0
  91. package/dist/server/routes/session.d.ts.map +1 -0
  92. package/dist/server/routes/session.js +228 -0
  93. package/dist/server/routes/session.js.map +1 -0
  94. package/dist/skills-loader.d.ts +46 -0
  95. package/dist/skills-loader.d.ts.map +1 -0
  96. package/dist/skills-loader.js +113 -0
  97. package/dist/skills-loader.js.map +1 -0
  98. package/dist/types.d.ts +128 -0
  99. package/dist/types.d.ts.map +1 -0
  100. package/dist/types.js +9 -0
  101. package/dist/types.js.map +1 -0
  102. package/package.json +47 -0
package/dist/index.js ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Public API of the `londai` framework package.
3
+ *
4
+ * ```ts
5
+ * import { londai, defineConfig, defineAgent, defineTool, defineSkill } from "londai";
6
+ * ```
7
+ */
8
+ import "@londai/providers"; // side-effect: install streamSimple as default streamFn
9
+ // Re-export the core agent runtime essentials users build with.
10
+ export { Agent, convertToLlm, err, ok, } from "@londai/core";
11
+ // Re-export the provider primitives users often need.
12
+ export { createStreamFn, getDefaultModels, setDefaultModels, streamSimple, toolInputSchema } from "@londai/providers";
13
+ // Session re-exports from @londai/session.
14
+ export { buildSchema, conversations, createSessionRepo, loandaiSchema, MemorySessionRepo, messages, PostgresSessionRepo, } from "@londai/session";
15
+ export { defineAgent, formatSkillsForSystemPrompt } from "./define-agent.js";
16
+ export { defineConfig } from "./define-config.js";
17
+ export { defineSkill } from "./define-skill.js";
18
+ export { defineTool } from "./define-tool.js";
19
+ export { codeToStatus, errorCodeOf, errorToStatus, FrameworkError } from "./errors.js";
20
+ export { createConsoleLogger, silentLogger } from "./logger.js";
21
+ export { londai } from "./londai.js";
22
+ export { getAuthConfig, getModels, requireConfig, requireModels, resetRegistry, } from "./registry.js";
23
+ export { formatSkillsForSystemPrompt as formatSkills, loadSkillFromFile, parseFrontmatter, validateSkillDescription, validateSkillName, } from "./skills-loader.js";
24
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,mBAAmB,CAAC,CAAC,wDAAwD;AAEpF,gEAAgE;AAChE,OAAO,EACN,KAAK,EAML,YAAY,EACZ,GAAG,EAKH,EAAE,GAMF,MAAM,cAAc,CAAC;AACtB,sDAAsD;AACtD,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,gBAAgB,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AAUtH,2CAA2C;AAC3C,OAAO,EACN,WAAW,EACX,aAAa,EACb,iBAAiB,EACjB,aAAa,EACb,iBAAiB,EACjB,QAAQ,EACR,mBAAmB,GACnB,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,WAAW,EAAE,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACvF,OAAO,EAAE,mBAAmB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAChE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EACN,aAAa,EACb,SAAS,EACT,aAAa,EACb,aAAa,EACb,aAAa,GACb,MAAM,eAAe,CAAC;AACvB,OAAO,EACN,2BAA2B,IAAI,YAAY,EAC3C,iBAAiB,EACjB,gBAAgB,EAChB,wBAAwB,EACxB,iBAAiB,GACjB,MAAM,oBAAoB,CAAC"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Minimal console-based logger.
3
+ *
4
+ * DESIGN §22 mentions pino as the future logger, but the MVP observability
5
+ * requirement is satisfied by a level-filtering console logger. `createConsoleLogger`
6
+ * returns a {@link Logger} that respects the configured minimum level.
7
+ */
8
+ import type { Logger, LoggerConfig } from "./types.ts";
9
+ export declare function createConsoleLogger(config?: LoggerConfig): Logger;
10
+ /** No-op logger used when none is provided. */
11
+ export declare const silentLogger: Logger;
12
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAavD,wBAAgB,mBAAmB,CAAC,MAAM,CAAC,EAAE,YAAY,GAAG,MAAM,CAmBjE;AAoBD,+CAA+C;AAC/C,eAAO,MAAM,YAAY,EAAE,MAK1B,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Minimal console-based logger.
3
+ *
4
+ * DESIGN §22 mentions pino as the future logger, but the MVP observability
5
+ * requirement is satisfied by a level-filtering console logger. `createConsoleLogger`
6
+ * returns a {@link Logger} that respects the configured minimum level.
7
+ */
8
+ const LEVEL_PRIORITY = {
9
+ debug: 10,
10
+ info: 20,
11
+ warn: 30,
12
+ error: 40,
13
+ };
14
+ function levelEnabled(current, target) {
15
+ return LEVEL_PRIORITY[target] >= current;
16
+ }
17
+ export function createConsoleLogger(config) {
18
+ const level = config?.level ?? "info";
19
+ const threshold = LEVEL_PRIORITY[level] ?? LEVEL_PRIORITY.info;
20
+ const prefix = "[londai]";
21
+ return {
22
+ debug: (...args) => {
23
+ if (levelEnabled(threshold, "debug"))
24
+ console.debug(prefix, ...args);
25
+ },
26
+ info: (...args) => {
27
+ if (levelEnabled(threshold, "info"))
28
+ console.info(prefix, ...args);
29
+ },
30
+ warn: (...args) => {
31
+ if (levelEnabled(threshold, "warn"))
32
+ console.warn(prefix, ...args);
33
+ },
34
+ error: (...args) => {
35
+ if (levelEnabled(threshold, "error"))
36
+ console.error(prefix, ...args);
37
+ },
38
+ child: (p) => createChildLogger(`${prefix} ${p}`, threshold),
39
+ };
40
+ }
41
+ function createChildLogger(prefix, threshold) {
42
+ return {
43
+ debug: (...args) => {
44
+ if (levelEnabled(threshold, "debug"))
45
+ console.debug(prefix, ...args);
46
+ },
47
+ info: (...args) => {
48
+ if (levelEnabled(threshold, "info"))
49
+ console.info(prefix, ...args);
50
+ },
51
+ warn: (...args) => {
52
+ if (levelEnabled(threshold, "warn"))
53
+ console.warn(prefix, ...args);
54
+ },
55
+ error: (...args) => {
56
+ if (levelEnabled(threshold, "error"))
57
+ console.error(prefix, ...args);
58
+ },
59
+ child: (p) => createChildLogger(`${prefix} ${p}`, threshold),
60
+ };
61
+ }
62
+ /** No-op logger used when none is provided. */
63
+ export const silentLogger = {
64
+ debug() { },
65
+ info() { },
66
+ warn() { },
67
+ error() { },
68
+ };
69
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `londai.run()` — the single boot method.
3
+ *
4
+ * Loads config from the registry, builds the internal Hono app, binds it via
5
+ * `@hono/node-server`, and returns a {@link LondaiServerHandle} for graceful
6
+ * shutdown. User code never holds the Hono instance.
7
+ *
8
+ * Milestone note: session routes (`/session/*`) are skipped — milestone 04.
9
+ */
10
+ import "@londai/providers";
11
+ import type { LondaiRunOptions, LondaiServerHandle } from "./types.ts";
12
+ export declare const londai: {
13
+ run(options: LondaiRunOptions): Promise<LondaiServerHandle>;
14
+ };
15
+ //# sourceMappingURL=londai.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"londai.d.ts","sourceRoot":"","sources":["../src/londai.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,OAAO,mBAAmB,CAAC;AAK3B,OAAO,KAAK,EAAkB,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAQvF,eAAO,MAAM,MAAM;iBACC,gBAAgB,GAAG,OAAO,CAAC,kBAAkB,CAAC;CA4DjE,CAAC"}
package/dist/londai.js ADDED
@@ -0,0 +1,74 @@
1
+ /**
2
+ * `londai.run()` — the single boot method.
3
+ *
4
+ * Loads config from the registry, builds the internal Hono app, binds it via
5
+ * `@hono/node-server`, and returns a {@link LondaiServerHandle} for graceful
6
+ * shutdown. User code never holds the Hono instance.
7
+ *
8
+ * Milestone note: session routes (`/session/*`) are skipped — milestone 04.
9
+ */
10
+ import { serve } from "@hono/node-server";
11
+ import "@londai/providers"; // side-effect: install streamSimple as default streamFn
12
+ import { loadConfig } from "./config-loader.js";
13
+ import { FrameworkError } from "./errors.js";
14
+ import { getAuthConfig, getSessionRepo } from "./registry.js";
15
+ import { buildApp } from "./server/app.js";
16
+ function resolveApprovalConfig(value) {
17
+ if (value === undefined || value === false)
18
+ return false;
19
+ if (value === true)
20
+ return {};
21
+ return value;
22
+ }
23
+ export const londai = {
24
+ async run(options) {
25
+ const { config, logger } = loadConfig();
26
+ const port = options.port ?? 3000;
27
+ const hostname = options.hostname ?? "0.0.0.0";
28
+ // Production safety: reject if auth is unset.
29
+ if (process.env.NODE_ENV === "production") {
30
+ const auth = getAuthConfig() ?? config.auth;
31
+ if (auth === undefined) {
32
+ throw new FrameworkError("config", "londai: `auth` is not configured and NODE_ENV=production. Set `auth` in defineConfig (or explicit `auth: false`).");
33
+ }
34
+ }
35
+ // Session warm-up: fail fast if session configured but not migrated.
36
+ const sessionRepo = getSessionRepo();
37
+ if (sessionRepo?.ping) {
38
+ try {
39
+ await sessionRepo.ping();
40
+ logger.info("londai: session repo ready.");
41
+ }
42
+ catch (error) {
43
+ throw new FrameworkError("config", `londai: session repo ping failed. Pastikan database sudah di-migrate. Jalankan 'npx londai migrate' dulu.\n ${error instanceof Error ? error.message : String(error)}`, error);
44
+ }
45
+ }
46
+ const approval = resolveApprovalConfig(options.approval);
47
+ const app = buildApp({ spec: options.agent, approval, onEvent: options.onEvent });
48
+ const runLogger = options.logger ?? logger;
49
+ let resolvedPort = port;
50
+ const server = serve({ fetch: app.fetch, port, hostname });
51
+ // Wait for the socket to bind so `handle.port` is the real listening port
52
+ // (port:0 → OS-assigned) before we return the handle.
53
+ await new Promise((resolve, reject) => {
54
+ server.on("listening", () => {
55
+ const address = server.address();
56
+ if (typeof address === "object" && address)
57
+ resolvedPort = address.port;
58
+ runLogger.info(`londai server listening on http://${hostname}:${resolvedPort}`);
59
+ resolve();
60
+ });
61
+ server.on("error", (err) => reject(err));
62
+ });
63
+ return {
64
+ port: resolvedPort,
65
+ hostname,
66
+ async close() {
67
+ // Close session repo if it has a close hook.
68
+ await sessionRepo?.close?.();
69
+ await new Promise((resolve) => server.close(() => resolve()));
70
+ },
71
+ };
72
+ },
73
+ };
74
+ //# sourceMappingURL=londai.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"londai.js","sourceRoot":"","sources":["../src/londai.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAmB,KAAK,EAAE,MAAM,mBAAmB,CAAC;AAC3D,OAAO,mBAAmB,CAAC,CAAC,wDAAwD;AACpF,OAAO,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC9D,OAAO,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAG3C,SAAS,qBAAqB,CAAC,KAAmC;IACjE,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,KAAK;QAAE,OAAO,KAAK,CAAC;IACzD,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,EAAE,CAAC;IAC9B,OAAO,KAAK,CAAC;AACd,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACrB,KAAK,CAAC,GAAG,CAAC,OAAyB;QAClC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,UAAU,EAAE,CAAC;QACxC,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,IAAI,CAAC;QAClC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,SAAS,CAAC;QAE/C,8CAA8C;QAC9C,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE,CAAC;YAC3C,MAAM,IAAI,GAAG,aAAa,EAAE,IAAI,MAAM,CAAC,IAAI,CAAC;YAC5C,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACxB,MAAM,IAAI,cAAc,CACvB,QAAQ,EACR,mHAAmH,CACnH,CAAC;YACH,CAAC;QACF,CAAC;QAED,qEAAqE;QACrE,MAAM,WAAW,GAAG,cAAc,EAAE,CAAC;QACrC,IAAI,WAAW,EAAE,IAAI,EAAE,CAAC;YACvB,IAAI,CAAC;gBACJ,MAAM,WAAW,CAAC,IAAI,EAAE,CAAC;gBACzB,MAAM,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;YAC5C,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBAChB,MAAM,IAAI,cAAc,CACvB,QAAQ,EACR,gHAAgH,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,EACxK,KAAK,CACL,CAAC;YACH,CAAC;QACF,CAAC;QAED,MAAM,QAAQ,GAAG,qBAAqB,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACzD,MAAM,GAAG,GAAG,QAAQ,CAAC,EAAE,IAAI,EAAE,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAClF,MAAM,SAAS,GAAG,OAAO,CAAC,MAAM,IAAI,MAAM,CAAC;QAE3C,IAAI,YAAY,GAAG,IAAI,CAAC;QACxB,MAAM,MAAM,GAAe,KAAK,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QAEvE,0EAA0E;QAC1E,sDAAsD;QACtD,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;YAC3C,MAAM,CAAC,EAAE,CAAC,WAAW,EAAE,GAAG,EAAE;gBAC3B,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;gBACjC,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO;oBAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;gBACxE,SAAS,CAAC,IAAI,CAAC,qCAAqC,QAAQ,IAAI,YAAY,EAAE,CAAC,CAAC;gBAChF,OAAO,EAAE,CAAC;YACX,CAAC,CAAC,CAAC;YACH,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAA0B,EAAE,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QACjE,CAAC,CAAC,CAAC;QAEH,OAAO;YACN,IAAI,EAAE,YAAY;YAClB,QAAQ;YACR,KAAK,CAAC,KAAK;gBACV,6CAA6C;gBAC7C,MAAM,WAAW,EAAE,KAAK,EAAE,EAAE,CAAC;gBAC7B,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACrE,CAAC;SACD,CAAC;IACH,CAAC;CACD,CAAC"}
@@ -0,0 +1,57 @@
1
+ /**
2
+ * Global framework registry.
3
+ *
4
+ * Holds the resolved configuration (providers → `Models`, auth, rate-limit,
5
+ * logger, session) and tracks per-conversation concurrency + approval state.
6
+ * `defineConfig(...)` populates this singleton; `londai.run()` reads from it.
7
+ *
8
+ * The registry is intentionally process-global — londai's MVP runs as a single
9
+ * process. Multi-instance fairness (rate-limit, concurrency) is a roadmap item.
10
+ */
11
+ import type { createModels, MutableModels } from "@londai/providers";
12
+ import type { SessionRepo } from "@londai/session";
13
+ import type { AuthConfig, ConfigSpec, Logger, RateLimitConfig, SessionConfig } from "./types.ts";
14
+ export interface PendingApproval {
15
+ conversationId: string;
16
+ callId: string;
17
+ toolName: string;
18
+ args: unknown;
19
+ /** Resolves the paused `beforeToolCall` hook. `true` = allow, `false` = block. */
20
+ resolve: (decision: ApprovalDecision) => void;
21
+ timer: ReturnType<typeof setTimeout>;
22
+ }
23
+ export interface ApprovalDecision {
24
+ approved: boolean;
25
+ reason?: string;
26
+ }
27
+ /** Reset the registry (test helper). */
28
+ export declare function resetRegistry(): void;
29
+ export declare function setConfig(config: ConfigSpec, models: MutableModels, logger: Logger): void;
30
+ export declare function getConfig(): ConfigSpec | undefined;
31
+ export declare function requireConfig(): ConfigSpec;
32
+ /** Lazily build/return the resolved `Models` collection. Throws if unset. */
33
+ export declare function requireModels(): MutableModels;
34
+ export declare function getModels(): MutableModels | undefined;
35
+ export declare function getAuthConfig(): AuthConfig | undefined;
36
+ export declare function getRateLimitConfig(): RateLimitConfig | undefined;
37
+ export declare function getSessionConfig(): SessionConfig | undefined;
38
+ export declare function setSessionRepo(repo: SessionRepo): void;
39
+ export declare function getSessionRepo(): SessionRepo | undefined;
40
+ export declare function requireSessionRepo(): SessionRepo;
41
+ export type { SessionRepo } from "@londai/session";
42
+ export declare function getLogger(): Logger | undefined;
43
+ /** Attempt to register an active run for `conversationId`. Returns false if one exists. */
44
+ export declare function beginRun(conversationId: string, controller: AbortController): boolean;
45
+ export declare function endRun(conversationId: string): void;
46
+ export declare function isRunning(conversationId: string): boolean;
47
+ /** Abort the active run for `conversationId`, if any. */
48
+ export declare function abortRun(conversationId: string): boolean;
49
+ export declare function registerPendingApproval(pending: PendingApproval): void;
50
+ export declare function getPendingApproval(conversationId: string): PendingApproval | undefined;
51
+ export declare function resolvePendingApproval(conversationId: string, decision: ApprovalDecision): boolean;
52
+ export declare function hasPendingApproval(conversationId: string): boolean;
53
+ /** Cancel (auto-deny) a pending approval after its timeout. */
54
+ export declare function expirePendingApproval(conversationId: string): void;
55
+ export type { Models, MutableModels } from "@londai/providers";
56
+ export type { createModels };
57
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,KAAK,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACrE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAajG,MAAM,WAAW,eAAe;IAC/B,cAAc,EAAE,MAAM,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,kFAAkF;IAClF,OAAO,EAAE,CAAC,QAAQ,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC9C,KAAK,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;CACrC;AAED,MAAM,WAAW,gBAAgB;IAChC,QAAQ,EAAE,OAAO,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;CAChB;AAeD,wCAAwC;AACxC,wBAAgB,aAAa,IAAI,IAAI,CAMpC;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,CAIzF;AAED,wBAAgB,SAAS,IAAI,UAAU,GAAG,SAAS,CAElD;AAED,wBAAgB,aAAa,IAAI,UAAU,CAQ1C;AAED,6EAA6E;AAC7E,wBAAgB,aAAa,IAAI,aAAa,CAK7C;AAED,wBAAgB,SAAS,IAAI,aAAa,GAAG,SAAS,CAErD;AAED,wBAAgB,aAAa,IAAI,UAAU,GAAG,SAAS,CAEtD;AAED,wBAAgB,kBAAkB,IAAI,eAAe,GAAG,SAAS,CAEhE;AAED,wBAAgB,gBAAgB,IAAI,aAAa,GAAG,SAAS,CAE5D;AAID,wBAAgB,cAAc,CAAC,IAAI,EAAE,WAAW,GAAG,IAAI,CAEtD;AAED,wBAAgB,cAAc,IAAI,WAAW,GAAG,SAAS,CAExD;AAED,wBAAgB,kBAAkB,IAAI,WAAW,CAMhD;AAED,YAAY,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,wBAAgB,SAAS,IAAI,MAAM,GAAG,SAAS,CAE9C;AAID,2FAA2F;AAC3F,wBAAgB,QAAQ,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,EAAE,eAAe,GAAG,OAAO,CAIrF;AAED,wBAAgB,MAAM,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAEzD;AAED,yDAAyD;AACzD,wBAAgB,QAAQ,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAKxD;AAID,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,eAAe,GAAG,IAAI,CAEtE;AAED,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,eAAe,GAAG,SAAS,CAEtF;AAED,wBAAgB,sBAAsB,CAAC,cAAc,EAAE,MAAM,EAAE,QAAQ,EAAE,gBAAgB,GAAG,OAAO,CAOlG;AAED,wBAAgB,kBAAkB,CAAC,cAAc,EAAE,MAAM,GAAG,OAAO,CAElE;AAED,+DAA+D;AAC/D,wBAAgB,qBAAqB,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAKlE;AAED,YAAY,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAC/D,YAAY,EAAE,YAAY,EAAE,CAAC"}
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Global framework registry.
3
+ *
4
+ * Holds the resolved configuration (providers → `Models`, auth, rate-limit,
5
+ * logger, session) and tracks per-conversation concurrency + approval state.
6
+ * `defineConfig(...)` populates this singleton; `londai.run()` reads from it.
7
+ *
8
+ * The registry is intentionally process-global — londai's MVP runs as a single
9
+ * process. Multi-instance fairness (rate-limit, concurrency) is a roadmap item.
10
+ */
11
+ function createRegistryState() {
12
+ return {
13
+ config: undefined,
14
+ models: undefined,
15
+ logger: undefined,
16
+ sessionRepo: undefined,
17
+ activeRuns: new Map(),
18
+ pendingApprovals: new Map(),
19
+ };
20
+ }
21
+ let state = createRegistryState();
22
+ /** Reset the registry (test helper). */
23
+ export function resetRegistry() {
24
+ for (const pending of state.pendingApprovals.values()) {
25
+ clearTimeout(pending.timer);
26
+ pending.resolve({ approved: false, reason: "registry reset" });
27
+ }
28
+ state = createRegistryState();
29
+ }
30
+ export function setConfig(config, models, logger) {
31
+ state.config = config;
32
+ state.models = models;
33
+ state.logger = logger;
34
+ }
35
+ export function getConfig() {
36
+ return state.config;
37
+ }
38
+ export function requireConfig() {
39
+ const config = state.config;
40
+ if (!config) {
41
+ throw new Error('londai: no config registered. Call defineConfig(...) (side-effect via `import "./config"`) before londai.run().');
42
+ }
43
+ return config;
44
+ }
45
+ /** Lazily build/return the resolved `Models` collection. Throws if unset. */
46
+ export function requireModels() {
47
+ if (!state.models) {
48
+ throw new Error("londai: models collection not initialized — defineConfig was not called.");
49
+ }
50
+ return state.models;
51
+ }
52
+ export function getModels() {
53
+ return state.models;
54
+ }
55
+ export function getAuthConfig() {
56
+ return state.config?.auth;
57
+ }
58
+ export function getRateLimitConfig() {
59
+ return state.config?.rateLimit;
60
+ }
61
+ export function getSessionConfig() {
62
+ return state.config?.session;
63
+ }
64
+ // --- session repo -----------------------------------------------------------
65
+ export function setSessionRepo(repo) {
66
+ state.sessionRepo = repo;
67
+ }
68
+ export function getSessionRepo() {
69
+ return state.sessionRepo;
70
+ }
71
+ export function requireSessionRepo() {
72
+ const repo = state.sessionRepo;
73
+ if (!repo) {
74
+ throw new Error("londai: session not configured. Set `session` in defineConfig.");
75
+ }
76
+ return repo;
77
+ }
78
+ export function getLogger() {
79
+ return state.logger;
80
+ }
81
+ // --- concurrency -------------------------------------------------------------
82
+ /** Attempt to register an active run for `conversationId`. Returns false if one exists. */
83
+ export function beginRun(conversationId, controller) {
84
+ if (state.activeRuns.has(conversationId))
85
+ return false;
86
+ state.activeRuns.set(conversationId, controller);
87
+ return true;
88
+ }
89
+ export function endRun(conversationId) {
90
+ state.activeRuns.delete(conversationId);
91
+ }
92
+ export function isRunning(conversationId) {
93
+ return state.activeRuns.has(conversationId);
94
+ }
95
+ /** Abort the active run for `conversationId`, if any. */
96
+ export function abortRun(conversationId) {
97
+ const controller = state.activeRuns.get(conversationId);
98
+ if (!controller)
99
+ return false;
100
+ controller.abort();
101
+ return true;
102
+ }
103
+ // --- approvals ---------------------------------------------------------------
104
+ export function registerPendingApproval(pending) {
105
+ state.pendingApprovals.set(pending.conversationId, pending);
106
+ }
107
+ export function getPendingApproval(conversationId) {
108
+ return state.pendingApprovals.get(conversationId);
109
+ }
110
+ export function resolvePendingApproval(conversationId, decision) {
111
+ const pending = state.pendingApprovals.get(conversationId);
112
+ if (!pending)
113
+ return false;
114
+ clearTimeout(pending.timer);
115
+ state.pendingApprovals.delete(conversationId);
116
+ pending.resolve(decision);
117
+ return true;
118
+ }
119
+ export function hasPendingApproval(conversationId) {
120
+ return state.pendingApprovals.has(conversationId);
121
+ }
122
+ /** Cancel (auto-deny) a pending approval after its timeout. */
123
+ export function expirePendingApproval(conversationId) {
124
+ const pending = state.pendingApprovals.get(conversationId);
125
+ if (!pending)
126
+ return;
127
+ state.pendingApprovals.delete(conversationId);
128
+ pending.resolve({ approved: false, reason: "approval timed out" });
129
+ }
130
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../src/registry.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Concurrency + abort wiring.
3
+ *
4
+ * - 1 active run per `conversationId`: a second concurrent request returns 409.
5
+ * - `c.req.raw.signal` (client disconnect) aborts the active run's controller.
6
+ *
7
+ * The route is responsible for calling `beginRun`/`endRun`; this module exposes
8
+ * `trackRequest` to plow the HTTP signal into the agent's controller.
9
+ */
10
+ export interface TrackedRun {
11
+ controller: AbortController;
12
+ signal: AbortSignal;
13
+ }
14
+ /**
15
+ * Register a new active run for `conversationId`. Returns `null` if a run is
16
+ * already active (caller should respond 409). Hooks the HTTP request signal so a
17
+ * client disconnect aborts the agent.
18
+ */
19
+ export declare function trackRequest(conversationId: string, requestOptions?: {
20
+ requestSignal?: AbortSignal;
21
+ }): TrackedRun | null;
22
+ export declare function finishRun(conversationId: string): void;
23
+ //# sourceMappingURL=abort.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.d.ts","sourceRoot":"","sources":["../../src/server/abort.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,MAAM,WAAW,UAAU;IAC1B,UAAU,EAAE,eAAe,CAAC;IAC5B,MAAM,EAAE,WAAW,CAAC;CACpB;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC3B,cAAc,EAAE,MAAM,EACtB,cAAc,CAAC,EAAE;IAAE,aAAa,CAAC,EAAE,WAAW,CAAA;CAAE,GAC9C,UAAU,GAAG,IAAI,CAcnB;AAED,wBAAgB,SAAS,CAAC,cAAc,EAAE,MAAM,GAAG,IAAI,CAEtD"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Concurrency + abort wiring.
3
+ *
4
+ * - 1 active run per `conversationId`: a second concurrent request returns 409.
5
+ * - `c.req.raw.signal` (client disconnect) aborts the active run's controller.
6
+ *
7
+ * The route is responsible for calling `beginRun`/`endRun`; this module exposes
8
+ * `trackRequest` to plow the HTTP signal into the agent's controller.
9
+ */
10
+ import { beginRun, endRun } from "../registry.js";
11
+ /**
12
+ * Register a new active run for `conversationId`. Returns `null` if a run is
13
+ * already active (caller should respond 409). Hooks the HTTP request signal so a
14
+ * client disconnect aborts the agent.
15
+ */
16
+ export function trackRequest(conversationId, requestOptions) {
17
+ const controller = new AbortController();
18
+ if (!beginRun(conversationId, controller)) {
19
+ return null;
20
+ }
21
+ const requestSignal = requestOptions?.requestSignal;
22
+ if (requestSignal) {
23
+ if (requestSignal.aborted) {
24
+ controller.abort();
25
+ }
26
+ else {
27
+ requestSignal.addEventListener("abort", () => controller.abort(), { once: true });
28
+ }
29
+ }
30
+ return { controller, signal: controller.signal };
31
+ }
32
+ export function finishRun(conversationId) {
33
+ endRun(conversationId);
34
+ }
35
+ //# sourceMappingURL=abort.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"abort.js","sourceRoot":"","sources":["../../src/server/abort.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,MAAM,gBAAgB,CAAC;AAOlD;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAC3B,cAAsB,EACtB,cAAgD;IAEhD,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;IACzC,IAAI,CAAC,QAAQ,CAAC,cAAc,EAAE,UAAU,CAAC,EAAE,CAAC;QAC3C,OAAO,IAAI,CAAC;IACb,CAAC;IACD,MAAM,aAAa,GAAG,cAAc,EAAE,aAAa,CAAC;IACpD,IAAI,aAAa,EAAE,CAAC;QACnB,IAAI,aAAa,CAAC,OAAO,EAAE,CAAC;YAC3B,UAAU,CAAC,KAAK,EAAE,CAAC;QACpB,CAAC;aAAM,CAAC;YACP,aAAa,CAAC,gBAAgB,CAAC,OAAO,EAAE,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;QACnF,CAAC;IACF,CAAC;IACD,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,UAAU,CAAC,MAAM,EAAE,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,cAAsB;IAC/C,MAAM,CAAC,cAAc,CAAC,CAAC;AACxB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Build a per-request `Agent` from an {@link AgentSpec}.
3
+ *
4
+ * Londai is stateless-by-default (DESIGN §18): each request rebuilds the agent
5
+ * from the spec + conversation context. The agent's streamFn comes from the
6
+ * resolved `Models` registry (set by `@londai/providers`' side-effect import),
7
+ * or an explicit `streamFn` override.
8
+ *
9
+ * The agent's system prompt is composed at build time: base prompt (static or
10
+ * dynamic function result) + the skills `<available_skills>` block.
11
+ *
12
+ * Approval hook injection: when `approval` is enabled, a `beforeToolCall` hook
13
+ * is layered in front of any user-supplied hook: for tools whose `risk` meets
14
+ * the configured threshold, it emits an `approval_required` event (via a
15
+ * caller-supplied `emitApproval` callback) and awaits a decision from the
16
+ * registry's pending-approval machinery.
17
+ */
18
+ import { Agent, type AgentMessage } from "@londai/core";
19
+ import type { MutableModels } from "@londai/providers";
20
+ import type { AgentSpec, ApprovalConfig } from "../types.ts";
21
+ export interface BuildAgentContext {
22
+ /** Conversation id used for concurrency + approval tracking. */
23
+ conversationId: string;
24
+ /** Existing messages (from session) seeded into the agent. */
25
+ messages?: AgentMessage[];
26
+ /** Authenticated user id (from auth middleware). */
27
+ userId?: string;
28
+ /** Per-request abort signal (from HTTP request). */
29
+ signal?: AbortSignal;
30
+ }
31
+ export interface ApprovalEmitContext {
32
+ /** Emit an SSE `approval_required` event for the client. */
33
+ emitApprovalRequired: (info: {
34
+ conversationId: string;
35
+ callId: string;
36
+ toolName: string;
37
+ args: unknown;
38
+ timeoutMs: number;
39
+ }) => void;
40
+ approvalConfig?: ApprovalConfig | false;
41
+ }
42
+ /**
43
+ * Build a per-request `Agent` from the spec.
44
+ *
45
+ * `models` resolves the model by `(spec.provider, spec.model)`. The agent's
46
+ * `streamFn` defaults via `setDefaultStreamFn` (installed by `@londai/providers`).
47
+ */
48
+ export declare function buildAgent(spec: AgentSpec, ctx: BuildAgentContext, models: MutableModels, approval?: ApprovalEmitContext): Promise<Agent>;
49
+ //# sourceMappingURL=agent-builder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agent-builder.d.ts","sourceRoot":"","sources":["../../src/server/agent-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,OAAO,EACN,KAAK,EACL,KAAK,YAAY,EAIjB,MAAM,cAAc,CAAC;AACtB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAGvD,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAqB,MAAM,aAAa,CAAC;AAIhF,MAAM,WAAW,iBAAiB;IACjC,gEAAgE;IAChE,cAAc,EAAE,MAAM,CAAC;IACvB,8DAA8D;IAC9D,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,oDAAoD;IACpD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oDAAoD;IACpD,MAAM,CAAC,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IACnC,4DAA4D;IAC5D,oBAAoB,EAAE,CAAC,IAAI,EAAE;QAC5B,cAAc,EAAE,MAAM,CAAC;QACvB,MAAM,EAAE,MAAM,CAAC;QACf,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,OAAO,CAAC;QACd,SAAS,EAAE,MAAM,CAAC;KAClB,KAAK,IAAI,CAAC;IACX,cAAc,CAAC,EAAE,cAAc,GAAG,KAAK,CAAC;CACxC;AASD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC/B,IAAI,EAAE,SAAS,EACf,GAAG,EAAE,iBAAiB,EACtB,MAAM,EAAE,aAAa,EACrB,QAAQ,CAAC,EAAE,mBAAmB,GAC5B,OAAO,CAAC,KAAK,CAAC,CAsFhB"}