@kevisual/router 0.0.83 → 0.0.84

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/src/opencode.ts CHANGED
@@ -10,7 +10,7 @@ export const addCallFn = (app: App) => {
10
10
  path: 'call',
11
11
  key: '',
12
12
  description: '调用',
13
- middleware: ['auth'],
13
+ middleware: ['auth-admin'],
14
14
  metadata: {
15
15
  tags: ['opencode'],
16
16
  ...createSkill({
@@ -24,7 +24,7 @@ export const addCallFn = (app: App) => {
24
24
  args: {
25
25
  path: tool.schema.string().describe('应用路径,例如 cnb'),
26
26
  key: tool.schema.string().optional().describe('应用key,例如 list-repos'),
27
- payload: tool.schema.object({}).optional().describe('调用参数'),
27
+ payload: tool.schema.object({}).optional().describe('调用参数, 为对象, 例如 { "query": "javascript" }'),
28
28
  }
29
29
  })
30
30
  },
@@ -59,9 +59,16 @@ export const createRouterAgentPluginFn = (opts?: {
59
59
  if (!router.hasRoute('call', '')) {
60
60
  addCallFn(router as App)
61
61
  }
62
- if (!router.hasRoute('auth', '')) {
63
- router.route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App)
62
+ if (router) {
63
+ (router as any).route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
64
+ overwrite: false
65
+ });
66
+
67
+ (router as any).route({ path: 'auth-admin', key: '', id: 'auth-admin', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
68
+ overwrite: false
69
+ })
64
70
  }
71
+
65
72
  const _routes = filter(router.routes, opts?.query || '')
66
73
  const routes = _routes.filter(r => {
67
74
  const metadata = r.metadata as Skill
@@ -75,7 +82,7 @@ export const createRouterAgentPluginFn = (opts?: {
75
82
  });
76
83
  // opencode run "使用技能查看系统信息"
77
84
  const AgentPlugin: Plugin = async (pluginInput) => {
78
- useContextKey<PluginInput>('plugin-input', () => pluginInput, true)
85
+ useContextKey<PluginInput>('plugin-input', () => pluginInput, { isNew: true })
79
86
  const hooks = opts?.hooks ? await opts.hooks(pluginInput) : {}
80
87
  return {
81
88
  ...hooks,
package/src/route.ts CHANGED
@@ -6,7 +6,24 @@ import { randomId } from './utils/random.ts';
6
6
  import * as schema from './validator/schema.ts';
7
7
 
8
8
  export type RouterContextT = { code?: number;[key: string]: any };
9
- export type RouteContext<T = { code?: number }, S = any> = {
9
+
10
+ type ExtractArgs<A> = A extends z.ZodTypeAny ? z.infer<A> : A;
11
+
12
+ type OptionalKeys<T> = {
13
+ [K in keyof T]-?: {} extends Pick<T, K> ? K : never;
14
+ }[keyof T];
15
+
16
+ type MakeOptional<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
17
+
18
+ type BuildRouteContext<M, U> = M extends { args?: infer A }
19
+ ? A extends z.ZodObject<any>
20
+ ? RouteContext<{ args?: z.infer<A> }, U>
21
+ : A extends Record<string, z.ZodTypeAny>
22
+ ? RouteContext<{ args?: { [K in keyof A]: z.infer<A[K]> } }, U>
23
+ : RouteContext<U>
24
+ : RouteContext<U>;
25
+
26
+ export type RouteContext<T = { code?: number }, U extends SimpleObject = {}, S = { [key: string]: any }> = {
10
27
  /**
11
28
  * 本地自己调用的时候使用,可以标识为当前自调用,那么 auth 就不许重复的校验
12
29
  * 或者不需要登录的,直接调用
@@ -23,9 +40,15 @@ export type RouteContext<T = { code?: number }, S = any> = {
23
40
  code?: number;
24
41
  /** return msg */
25
42
  message?: string;
26
- // 传递状态
43
+ /**
44
+ * 传递状态
45
+ */
27
46
  state?: S;
28
47
  // transfer data
48
+ /**
49
+ * 当前routerId
50
+ */
51
+ currentId?: string;
29
52
  /**
30
53
  * 当前路径
31
54
  */
@@ -54,19 +77,19 @@ export type RouteContext<T = { code?: number }, S = any> = {
54
77
  ctx?: RouteContext & { [key: string]: any },
55
78
  ) => Promise<any>;
56
79
  /** 请求 route的返回结果,解析了body为data,就类同于 query.post获取的数据*/
57
- run?: (message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) => Promise<any>;
80
+ run?: (message: { path: string; key?: string; payload?: any }, ctx?: RouteContext) => Promise<any>;
58
81
  index?: number;
59
82
  throw?: throwError['throw'];
60
83
  /** 是否需要序列化, 使用JSON.stringify和JSON.parse */
61
84
  needSerialize?: boolean;
62
- } & T;
85
+ } & T & U;
63
86
  export type SimpleObject = Record<string, any>;
64
87
  export type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
65
88
  export type RunMessage = { path?: string; key?: string; id?: string; payload?: any; };
66
89
  export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
67
90
  export type RouteMiddleware =
68
91
  | {
69
- path: string;
92
+ path?: string;
70
93
  key?: string;
71
94
  id?: string;
72
95
  }
@@ -123,7 +146,13 @@ export const createSkill = <T = SimpleObject>(skill: Skill<T>): Skill<T> => {
123
146
 
124
147
  export type RouteInfo = Pick<Route, (typeof pickValue)[number]>;
125
148
 
126
- export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleObject> implements throwError {
149
+ type ExtractMetadata<M> = M extends { metadata?: infer Meta } ? Meta extends SimpleObject ? Meta : SimpleObject : SimpleObject;
150
+
151
+ /**
152
+ * @M 是 route的 metadate的类型,默认是 SimpleObject
153
+ * @U 是 RouteContext 里 state的类型
154
+ */
155
+ export class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject = SimpleObject> implements throwError {
127
156
  /**
128
157
  * 一级路径
129
158
  */
@@ -133,10 +162,10 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
133
162
  */
134
163
  key?: string;
135
164
  id?: string;
136
- run?: Run;
165
+ run?: Run<BuildRouteContext<M, U>>;
137
166
  nextRoute?: NextRoute; // route to run after this route
138
167
  description?: string;
139
- metadata?: T;
168
+ metadata?: M;
140
169
  middleware?: RouteMiddleware[]; // middleware
141
170
  type? = 'route';
142
171
  /**
@@ -157,10 +186,10 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
157
186
  const delimiter = opts.delimiter ?? '$#$';
158
187
  this.id = path + delimiter + key;
159
188
  }
160
- this.run = opts.run;
189
+ this.run = opts.run as Run<BuildRouteContext<M, U>>;
161
190
  this.nextRoute = opts.nextRoute;
162
191
  this.description = opts.description;
163
- this.metadata = opts.metadata as T;
192
+ this.metadata = opts.metadata as M;
164
193
  this.type = opts.type || 'route';
165
194
  this.middleware = opts.middleware || [];
166
195
  this.key = opts.key || key;
@@ -184,9 +213,9 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
184
213
  return this;
185
214
  }
186
215
  define<T extends { [key: string]: any } = RouterContextT>(opts: DefineRouteOpts): this;
187
- define<T extends { [key: string]: any } = RouterContextT>(fn: Run<T & U>): this;
188
- define<T extends { [key: string]: any } = RouterContextT>(key: string, fn: Run<T & U>): this;
189
- define<T extends { [key: string]: any } = RouterContextT>(path: string, key: string, fn: Run<T & U>): this;
216
+ define<T extends { [key: string]: any } = RouterContextT>(fn: Run<T & BuildRouteContext<M, U>>): this;
217
+ define<T extends { [key: string]: any } = RouterContextT>(key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
218
+ define<T extends { [key: string]: any } = RouterContextT>(path: string, key: string, fn: Run<T & BuildRouteContext<M, U>>): this;
190
219
  define(...args: any[]) {
191
220
  const [path, key, opts] = args;
192
221
  // 全覆盖,所以opts需要准确,不能由idUsePath 需要check的变量
@@ -209,7 +238,7 @@ export class Route<U = { [key: string]: any }, T extends SimpleObject = SimpleOb
209
238
  return this;
210
239
  }
211
240
  if (typeof path === 'function') {
212
- this.run = path;
241
+ this.run = path as Run<BuildRouteContext<M, U>>;
213
242
  return this;
214
243
  }
215
244
  if (typeof path === 'string' && typeof key === 'function') {
@@ -262,11 +291,11 @@ export const fromJSONSchema = schema.fromJSONSchema;
262
291
  * @parmas overwrite 是否覆盖已存在的route,默认true
263
292
  */
264
293
  export type AddOpts = { overwrite?: boolean };
265
- export class QueryRouter implements throwError {
294
+ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throwError {
266
295
  appId: string = '';
267
296
  routes: Route[];
268
297
  maxNextRoute = 40;
269
- context?: RouteContext = {}; // default context for call
298
+ context?: RouteContext<T> = {} as RouteContext<T>; // default context for call
270
299
  constructor() {
271
300
  this.routes = [];
272
301
  }
@@ -309,11 +338,12 @@ export class QueryRouter implements throwError {
309
338
  * @param ctx
310
339
  * @returns
311
340
  */
312
- async runRoute(path: string, key: string, ctx?: RouteContext) {
341
+ async runRoute(path: string, key: string, ctx?: RouteContext<T>): Promise<RouteContext<T>> {
313
342
  const route = this.routes.find((r) => r.path === path && r.key === key);
314
343
  const maxNextRoute = this.maxNextRoute;
315
- ctx = (ctx || {}) as RouteContext;
344
+ ctx = (ctx || {}) as RouteContext<T>;
316
345
  ctx.currentPath = path;
346
+ ctx.currentId = route?.id;
317
347
  ctx.currentKey = key;
318
348
  ctx.currentRoute = route;
319
349
  ctx.index = (ctx.index || 0) + 1;
@@ -327,7 +357,7 @@ export class QueryRouter implements throwError {
327
357
  ctx.code = 500;
328
358
  ctx.message = 'Too many nextRoute';
329
359
  ctx.body = null;
330
- return;
360
+ return ctx;
331
361
  }
332
362
  // run middleware
333
363
  if (route && route.middleware && route.middleware.length > 0) {
@@ -382,7 +412,7 @@ export class QueryRouter implements throwError {
382
412
  const middleware = routeMiddleware[i];
383
413
  if (middleware) {
384
414
  try {
385
- await middleware.run(ctx as Required<RouteContext>);
415
+ await middleware.run(ctx as Required<RouteContext<T>>);
386
416
  } catch (e) {
387
417
  if (route?.isDebug) {
388
418
  console.error('=====debug====:middlerware error');
@@ -404,6 +434,7 @@ export class QueryRouter implements throwError {
404
434
  return ctx;
405
435
  }
406
436
  if (ctx.end) {
437
+ return ctx;
407
438
  }
408
439
  }
409
440
  }
@@ -412,7 +443,7 @@ export class QueryRouter implements throwError {
412
443
  if (route) {
413
444
  if (route.run) {
414
445
  try {
415
- await route.run(ctx as Required<RouteContext>);
446
+ await route.run(ctx as Required<RouteContext<T>>);
416
447
  } catch (e) {
417
448
  if (route?.isDebug) {
418
449
  console.error('=====debug====:route error');
@@ -467,7 +498,7 @@ export class QueryRouter implements throwError {
467
498
  }
468
499
  }
469
500
  // 如果没有找到route,返回404,这是因为出现了错误
470
- return Promise.resolve({ code: 404, body: 'Not found' });
501
+ return Promise.resolve({ code: 404, body: 'Not found' } as RouteContext<T>);
471
502
  }
472
503
  /**
473
504
  * 第一次执行
@@ -475,12 +506,12 @@ export class QueryRouter implements throwError {
475
506
  * @param ctx
476
507
  * @returns
477
508
  */
478
- async parse(message: { path: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
509
+ async parse(message: { path: string; key?: string; payload?: any }, ctx?: RouteContext<T> & { [key: string]: any }) {
479
510
  if (!message?.path) {
480
- return Promise.resolve({ code: 404, body: null, message: 'Not found path' });
511
+ return Promise.resolve({ code: 404, body: null, message: 'Not found path' } as RouteContext<T>);
481
512
  }
482
513
  const { path, key = '', payload = {}, ...query } = message;
483
- ctx = ctx || {};
514
+ ctx = ctx || {} as RouteContext<T>;
484
515
  ctx.query = { ...ctx.query, ...query, ...payload };
485
516
  ctx.args = ctx.query;
486
517
  ctx.state = { ...ctx?.state };
@@ -514,7 +545,7 @@ export class QueryRouter implements throwError {
514
545
  * @param ctx
515
546
  * @returns
516
547
  */
517
- async call(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
548
+ async call(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext<T> & { [key: string]: any }) {
518
549
  let path = message.path;
519
550
  let key = message.key;
520
551
  // 优先 path + key
@@ -555,7 +586,7 @@ export class QueryRouter implements throwError {
555
586
  * @param ctx
556
587
  * @returns
557
588
  */
558
- async run(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
589
+ async run(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext<T> & { [key: string]: any }) {
559
590
  const res = await this.call(message, { ...this.context, ...ctx });
560
591
  return {
561
592
  code: res.code,
@@ -569,7 +600,7 @@ export class QueryRouter implements throwError {
569
600
  * @param ctx
570
601
  */
571
602
  setContext(ctx: RouteContext) {
572
- this.context = ctx;
603
+ this.context = ctx as RouteContext<T>;
573
604
  }
574
605
  getList(filter?: (route: Route) => boolean): RouteInfo[] {
575
606
  return this.routes.filter(filter || (() => true)).map((r) => {
@@ -580,11 +611,11 @@ export class QueryRouter implements throwError {
580
611
  /**
581
612
  * 获取handle函数, 这里会去执行parse函数
582
613
  */
583
- getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn<T>, ctx?: RouteContext) {
584
- return async (msg: { id?: string; path?: string; key?: string;[key: string]: any }, handleContext?: RouteContext) => {
614
+ getHandle<T = any>(router: QueryRouter, wrapperFn?: HandleFn, ctx?: RouteContext) {
615
+ return async (msg: { id?: string; path?: string; key?: string;[key: string]: any }, handleContext?: RouteContext<T>) => {
585
616
  try {
586
617
  const context = { ...ctx, ...handleContext };
587
- const res = await router.call(msg, context);
618
+ const res = await router.call(msg, context) as any;
588
619
  if (wrapperFn) {
589
620
  res.data = res.body;
590
621
  return wrapperFn(res, context);
@@ -637,7 +668,7 @@ export class QueryRouter implements throwError {
637
668
  description: '列出当前应用下的所有的路由信息',
638
669
  middleware: opts?.middleware || [],
639
670
  run: async (ctx: RouteContext) => {
640
- const tokenUser = ctx.state.tokenUser;
671
+ const tokenUser = ctx.state as unknown as { tokenUser?: any };
641
672
  let isUser = !!tokenUser;
642
673
  const list = this.getList(opts?.filter).filter((item) => {
643
674
  if (item.id === 'auth' || item.id === 'auth-can' || item.id === 'check-auth-admin' || item.id === 'auth-admin') {
@@ -683,10 +714,11 @@ export class QueryRouter implements throwError {
683
714
  fromJSONSchema = fromJSONSchema;
684
715
  }
685
716
 
686
- type QueryRouterServerOpts = {
717
+ type QueryRouterServerOpts<C extends SimpleObject = SimpleObject> = {
687
718
  handleFn?: HandleFn;
688
- context?: RouteContext;
719
+ context?: RouteContext<C>;
689
720
  appId?: string;
721
+ initHandle?: boolean;
690
722
  };
691
723
  interface HandleFn<T = any> {
692
724
  (msg: { path: string;[key: string]: any }, ctx?: any): { code: string; data?: any; message?: string;[key: string]: any };
@@ -695,13 +727,18 @@ interface HandleFn<T = any> {
695
727
  /**
696
728
  * QueryRouterServer
697
729
  * @description 移除server相关的功能,只保留router相关的功能,和http.createServer不相关,独立
730
+ * @template C 自定义 RouteContext 类型
698
731
  */
699
- export class QueryRouterServer extends QueryRouter {
732
+ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends QueryRouter<C> {
700
733
  declare appId: string;
701
734
  handle: any;
702
- constructor(opts?: QueryRouterServerOpts) {
735
+ declare context: RouteContext<C>;
736
+ constructor(opts?: QueryRouterServerOpts<C>) {
703
737
  super();
704
- this.handle = this.getHandle(this, opts?.handleFn, opts?.context);
738
+ const initHandle = opts?.initHandle ?? true;
739
+ if (initHandle || opts?.handleFn) {
740
+ this.handle = this.getHandle(this, opts?.handleFn, opts?.context);
741
+ }
705
742
  this.setContext({ needSerialize: false, ...opts?.context });
706
743
  if (opts?.appId) {
707
744
  this.appId = opts.appId;
@@ -716,37 +753,28 @@ export class QueryRouterServer extends QueryRouter {
716
753
  this.add(route, opts);
717
754
  }
718
755
  Route = Route;
719
- route(opts: RouteOpts): Route<Required<RouteContext>>;
720
- route(path: string, key?: string): Route<Required<RouteContext>>;
721
- route(path: string, opts?: RouteOpts): Route<Required<RouteContext>>;
722
- route(path: string, key?: string, opts?: RouteOpts): Route<Required<RouteContext>>;
723
- route(...args: any[]) {
756
+ route<M extends SimpleObject = SimpleObject>(opts: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext<C>>>;
757
+ route<M extends SimpleObject = SimpleObject>(path: string, opts?: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext<C>>>;
758
+ route<M extends SimpleObject = SimpleObject>(path: string, key?: string): Route<M, Required<RouteContext<C>>>;
759
+ route<M extends SimpleObject = SimpleObject>(path: string, key?: string, opts?: RouteOpts & { metadata?: M }): Route<M, Required<RouteContext<C>>>;
760
+ route<M extends SimpleObject = SimpleObject>(...args: any[]) {
724
761
  const [path, key, opts] = args;
725
762
  if (typeof path === 'object') {
726
- return new Route(path.path, path.key, path);
763
+ return new Route<M, Required<RouteContext<C>>>(path.path, path.key, path);
727
764
  }
728
765
  if (typeof path === 'string') {
729
766
  if (opts) {
730
- return new Route(path, key, opts);
767
+ return new Route<M, Required<RouteContext<C>>>(path, key, opts);
731
768
  }
732
769
  if (key && typeof key === 'object') {
733
- return new Route(path, key?.key || '', key);
770
+ return new Route<M, Required<RouteContext<C>>>(path, key?.key || '', key);
734
771
  }
735
- return new Route(path, key);
772
+ return new Route<M, Required<RouteContext<C>>>(path, key);
736
773
  }
737
- return new Route(path, key, opts);
774
+ return new Route<M, Required<RouteContext<C>>>(path, key, opts);
738
775
  }
739
- prompt(description: string): Route<Required<RouteContext>>;
740
- prompt(description: Function): Route<Required<RouteContext>>;
741
- prompt(...args: any[]) {
742
- const [desc] = args;
743
- let description = ''
744
- if (typeof desc === 'string') {
745
- description = desc;
746
- } else if (typeof desc === 'function') {
747
- description = desc() || ''; // 如果是Promise,需要addTo App之前就要获取应有的函数了。
748
- }
749
- return new Route('', '', { description });
776
+ prompt(description: string) {
777
+ return new Route(undefined, undefined, { description });
750
778
  }
751
779
 
752
780
  /**
@@ -754,12 +782,12 @@ export class QueryRouterServer extends QueryRouter {
754
782
  * @param param0
755
783
  * @returns
756
784
  */
757
- async run(msg: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext & { [key: string]: any }) {
785
+ async run(msg: { id?: string; path?: string; key?: string; payload?: any }, ctx?: Partial<RouteContext<C>>) {
758
786
  const handle = this.handle;
759
787
  if (handle) {
760
788
  return handle(msg, ctx);
761
789
  }
762
- return super.run(msg, ctx);
790
+ return super.run(msg, ctx as RouteContext<C>);
763
791
  }
764
792
  }
765
793
 
@@ -1,13 +1,69 @@
1
- import { App } from '../app.ts'
1
+ import { App, AppRouteContext } from "@/app.ts";
2
+ import { QueryRouterServer, RouteContext } from "@/app.ts";
3
+ import z from "zod";
4
+ const route: RouteContext<{ customField: string }> = {} as any;
5
+ route.customField
6
+ const appRoute: AppRouteContext<{ customField: string }> = {} as any;
7
+ appRoute.customField
8
+ // 示例 1: 使用 App,它会自动使用 AppRouteContext<U> 作为 ctx 类型
9
+ const app = new App<{
10
+ customField: string;
11
+ }>();
12
+ app.context.customField = "customValue"; // 可以在 app.context 中添加自定义字段,这些字段会在 ctx 中可用
13
+ app.route({
14
+ path: 'test1',
15
+ metadata: {
16
+ args: {
17
+ name: z.string(),
18
+ }
19
+ },
20
+ }).define(async (ctx) => {
21
+ // ctx.app 是 App 类型
22
+ const appName = ctx.app.appId;
23
+ // ctx.customField 来自自定义泛型参数
24
+ const customField: string | undefined = ctx.customField;
2
25
 
3
- const app = new App<{ f: string }>();
26
+ // ctx.req ctx.res 来自 HandleCtx
27
+ const req = ctx.req;
28
+ const res = ctx.res;
4
29
 
5
- app.route({
6
- path: 't',
7
- run: async (ctx) => {
8
- // ctx.r
9
- ctx.app;
10
- }
30
+ // ctx.args 从 metadata.args 推断
31
+ const name: string = ctx.args.name;
32
+ const name2: string = ctx.query.name;
33
+
34
+
35
+ ctx.body = `Hello ${name}!`;
36
+ });
37
+ // 示例 2: 使用 QueryRouterServer,它可以传递自定义的 Context 类型
38
+ const router = new QueryRouterServer<{
39
+ routerContextField: number;
40
+ }>();
41
+ router.context.routerContextField
42
+ router.route({
43
+ path: 'router-test',
44
+ metadata: {
45
+ args: {
46
+ value: z.number(),
47
+ }
48
+ },
49
+ }).define(async (ctx) => {
50
+ const value: number = ctx.args.value;
51
+ const field: number | undefined = ctx.routerContextField;
52
+
53
+ ctx.body = value;
54
+ });
55
+ // 示例 3: 不带泛型参数的 QueryRouterServer,使用默认的 RouteContext
56
+ const defaultRouter = new QueryRouterServer();
57
+ defaultRouter.route({
58
+ path: 'default-test',
59
+ metadata: {
60
+ args: {
61
+ id: z.string(),
62
+ }
63
+ },
11
64
  }).define(async (ctx) => {
12
- ctx.f = 'hello';
13
- }).addTo(app);
65
+ const id: string = ctx.args.id;
66
+
67
+ ctx.body = id;
68
+ });
69
+ export { app, router, defaultRouter };
package/src/test/chat.ts CHANGED
@@ -14,4 +14,4 @@ app.prompt('获取天气的工具。\n参数是 city 为对应的城市').define
14
14
 
15
15
  export const chat = new RouterChat({ router: app.router });
16
16
 
17
- console.log(chat.chat());
17
+ console.log(chat.getChatPrompt());
@@ -0,0 +1,15 @@
1
+ import { QueryRouterServer } from "@/route.ts";
2
+ import z from "zod";
3
+
4
+ const router = new QueryRouterServer()
5
+
6
+ router.route({
7
+ metadata: {
8
+ args: {
9
+ a: z.string(),
10
+ }
11
+ },
12
+ }).define(async (ctx) => {
13
+ const argA: string = ctx.args.a;
14
+ ctx.body = '1';
15
+ })