@koalaauto/agentchannel 0.0.0-stage → 3.0.0-rc.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.
Files changed (71) hide show
  1. package/LICENSE +202 -0
  2. package/README.md +154 -2
  3. package/dist/src/adapters/claude.d.ts +65 -0
  4. package/dist/src/adapters/claude.js +243 -0
  5. package/dist/src/adapters/codex.d.ts +74 -0
  6. package/dist/src/adapters/codex.js +237 -0
  7. package/dist/src/adapters/fake.d.ts +65 -0
  8. package/dist/src/adapters/fake.js +105 -0
  9. package/dist/src/adapters/index.d.ts +11 -0
  10. package/dist/src/adapters/index.js +26 -0
  11. package/dist/src/adapters/paths.d.ts +35 -0
  12. package/dist/src/adapters/paths.js +113 -0
  13. package/dist/src/adapters/procgroup.d.ts +14 -0
  14. package/dist/src/adapters/procgroup.js +49 -0
  15. package/dist/src/adapters/types.d.ts +57 -0
  16. package/dist/src/adapters/types.js +1 -0
  17. package/dist/src/args.d.ts +14 -0
  18. package/dist/src/args.js +257 -0
  19. package/dist/src/attachments.d.ts +63 -0
  20. package/dist/src/attachments.js +227 -0
  21. package/dist/src/attention.d.ts +85 -0
  22. package/dist/src/attention.js +262 -0
  23. package/dist/src/avatars.d.ts +40 -0
  24. package/dist/src/avatars.js +90 -0
  25. package/dist/src/cli.d.ts +45 -0
  26. package/dist/src/cli.js +1822 -0
  27. package/dist/src/client.d.ts +520 -0
  28. package/dist/src/client.js +449 -0
  29. package/dist/src/config.d.ts +62 -0
  30. package/dist/src/config.js +121 -0
  31. package/dist/src/desknotify.d.ts +154 -0
  32. package/dist/src/desknotify.js +426 -0
  33. package/dist/src/doctor.d.ts +75 -0
  34. package/dist/src/doctor.js +375 -0
  35. package/dist/src/env.d.ts +31 -0
  36. package/dist/src/env.js +52 -0
  37. package/dist/src/import.d.ts +245 -0
  38. package/dist/src/import.js +1008 -0
  39. package/dist/src/index.d.ts +13 -0
  40. package/dist/src/index.js +13 -0
  41. package/dist/src/invite.d.ts +103 -0
  42. package/dist/src/invite.js +229 -0
  43. package/dist/src/invite_person.d.ts +16 -0
  44. package/dist/src/invite_person.js +75 -0
  45. package/dist/src/keystore.d.ts +55 -0
  46. package/dist/src/keystore.js +108 -0
  47. package/dist/src/mcp.d.ts +62 -0
  48. package/dist/src/mcp.js +503 -0
  49. package/dist/src/names.d.ts +30 -0
  50. package/dist/src/names.js +108 -0
  51. package/dist/src/netproxy.d.ts +20 -0
  52. package/dist/src/netproxy.js +36 -0
  53. package/dist/src/onboard.d.ts +105 -0
  54. package/dist/src/onboard.js +270 -0
  55. package/dist/src/perm.d.ts +12 -0
  56. package/dist/src/perm.js +20 -0
  57. package/dist/src/prompts.d.ts +166 -0
  58. package/dist/src/prompts.js +409 -0
  59. package/dist/src/runner/runner.d.ts +212 -0
  60. package/dist/src/runner/runner.js +1148 -0
  61. package/dist/src/runner/state.d.ts +68 -0
  62. package/dist/src/runner/state.js +80 -0
  63. package/dist/src/runner/workspace.d.ts +70 -0
  64. package/dist/src/runner/workspace.js +265 -0
  65. package/dist/src/service.d.ts +29 -0
  66. package/dist/src/service.js +101 -0
  67. package/dist/src/version.d.ts +3 -0
  68. package/dist/src/version.js +3 -0
  69. package/dist/src/wiki.d.ts +74 -0
  70. package/dist/src/wiki.js +222 -0
  71. package/package.json +48 -4
@@ -0,0 +1,520 @@
1
+ import type { Config } from './config.js';
2
+ import { type Attachment, type StorageConfig, type TaskFile } from './attachments.js';
3
+ export type TaskStatus = 'submitted' | 'working' | 'input-required' | 'completed' | 'failed' | 'canceled';
4
+ export declare const TERMINAL: readonly TaskStatus[];
5
+ export declare function isTerminal(s: string | undefined): boolean;
6
+ export type MessageKind = 'question' | 'answer' | 'decision_request' | 'decision' | 'progress' | 'result' | 'note';
7
+ export interface Agent {
8
+ id: string;
9
+ name: string;
10
+ owner?: string;
11
+ owner_name?: string;
12
+ runtime?: string;
13
+ description?: string;
14
+ perm_level?: string;
15
+ budget_usd?: number;
16
+ spent_usd?: number;
17
+ active?: boolean;
18
+ last_seen?: string;
19
+ /** P2: domains the agent's sandbox may reach ("*" = any; admin-only). */
20
+ net_allow?: string[];
21
+ }
22
+ export interface Task {
23
+ id: string;
24
+ title: string;
25
+ priority?: string;
26
+ purpose?: string;
27
+ money?: string;
28
+ status: TaskStatus;
29
+ from_agent?: string;
30
+ to_agent?: string;
31
+ owner_user?: string;
32
+ handoff?: string;
33
+ handoff_version?: number;
34
+ waiting_on?: string;
35
+ depends_on?: string[];
36
+ cost_usd?: number;
37
+ links?: Record<string, unknown> | null;
38
+ run_id?: string;
39
+ /** P1: who holds the claim: a runner, or a person's interactive agent. */
40
+ claim_mode?: '' | 'runner' | 'interactive';
41
+ /** P6: the one question this task must answer. */
42
+ key_question?: string;
43
+ result?: string;
44
+ created?: string;
45
+ updated?: string;
46
+ /** §19: human-friendly number ("T-128" = ref) and permalink. */
47
+ seq?: number;
48
+ ref?: string;
49
+ url?: string;
50
+ /** §16: the task's channel. */
51
+ channel?: string;
52
+ channel_name?: string;
53
+ /** Optional expansions some routes add. */
54
+ from_agent_name?: string;
55
+ to_agent_name?: string;
56
+ [k: string]: unknown;
57
+ }
58
+ export interface Message {
59
+ id: string;
60
+ task: string;
61
+ author_type?: 'agent' | 'human' | 'system';
62
+ author_agent?: string;
63
+ author_user?: string;
64
+ kind: MessageKind | string;
65
+ body: string;
66
+ to_agent?: string;
67
+ to_user?: string;
68
+ reply_to?: string;
69
+ evidence?: string;
70
+ resolved?: boolean;
71
+ created?: string;
72
+ [k: string]: unknown;
73
+ }
74
+ export interface HandoffVersion {
75
+ version: number;
76
+ body: string;
77
+ change_note?: string;
78
+ author_agent?: string;
79
+ created?: string;
80
+ attachments?: Attachment[];
81
+ }
82
+ export interface TaskBundle {
83
+ task: Task;
84
+ handoff: string;
85
+ messages: Message[];
86
+ history: HandoffVersion[];
87
+ /** Attachments of the current handoff version. */
88
+ handoffAttachments?: Attachment[];
89
+ /** §21-revised: the hub's wiki context for this task's worker prompt (claim / get as the worker). */
90
+ wiki?: WikiContext | null;
91
+ }
92
+ /** §21-revised: what the hub picked from the team wiki for a worker prompt (≤ ~1k tokens). */
93
+ export interface WikiContext {
94
+ budget_chars?: number;
95
+ decisions: {
96
+ id: string;
97
+ text: string;
98
+ decider?: string;
99
+ as_of?: string;
100
+ url?: string;
101
+ human_confirmed?: boolean;
102
+ use?: string;
103
+ }[];
104
+ figures: {
105
+ topic: string;
106
+ metric: string;
107
+ value: string;
108
+ unit?: string;
109
+ env?: string;
110
+ as_of: string;
111
+ source: string;
112
+ stale?: boolean;
113
+ use?: string;
114
+ }[];
115
+ lessons: {
116
+ page: string;
117
+ text: string;
118
+ stale?: boolean;
119
+ use?: string;
120
+ }[];
121
+ overview?: string[];
122
+ used_chars?: number;
123
+ pages: {
124
+ slug: string;
125
+ title: string;
126
+ url?: string;
127
+ }[];
128
+ truncated?: boolean;
129
+ /** Values Memory marks superseded (never injected; used to redact them from channel posts). */
130
+ superseded?: {
131
+ topic?: string;
132
+ metric: string;
133
+ value: string;
134
+ unit?: string;
135
+ env?: string;
136
+ }[];
137
+ }
138
+ export interface ClaimResult extends TaskBundle {
139
+ /** Empty for interactive claims (no spawned agent). */
140
+ run_token: string;
141
+ }
142
+ export type ClaimMode = 'runner' | 'interactive';
143
+ export interface Inbox {
144
+ tasks_to_me: Task[];
145
+ questions_to_me: Message[];
146
+ answers_to_me: Message[];
147
+ decisions_for_me: Message[];
148
+ /** Human notes on tasks I work (author_type human), addressed to me. */
149
+ notes_for_me: Message[];
150
+ /** §16: open @mentions of me in channel posts; each wakes a read-only mention run. */
151
+ mentions_for_me: MentionItem[];
152
+ updates_on_my_tasks: unknown[];
153
+ server_time: string;
154
+ }
155
+ /** §16: a channel post or thread reply. */
156
+ export interface Post {
157
+ id: string;
158
+ url?: string;
159
+ channel: string;
160
+ channel_name?: string;
161
+ kind: 'post' | 'task' | 'system' | string;
162
+ parent?: string;
163
+ author_type?: 'agent' | 'human' | 'system';
164
+ author_name?: string;
165
+ body: string;
166
+ evidence?: string;
167
+ escalated?: boolean;
168
+ mentions?: string[];
169
+ task?: string;
170
+ task_info?: Record<string, unknown> | null;
171
+ reply_count?: number;
172
+ attachments?: Attachment[];
173
+ created?: string;
174
+ [k: string]: unknown;
175
+ }
176
+ export interface Channel {
177
+ id: string;
178
+ name: string;
179
+ description?: string;
180
+ archived?: boolean;
181
+ post_count?: number;
182
+ last_post_at?: string;
183
+ url?: string;
184
+ }
185
+ export interface Thread {
186
+ post: Post;
187
+ replies: Post[];
188
+ focus?: string;
189
+ }
190
+ export interface MentionItem {
191
+ mention: {
192
+ id: string;
193
+ post: string;
194
+ thread: string;
195
+ status: string;
196
+ by: string;
197
+ by_type: 'agent' | 'human';
198
+ created?: string;
199
+ };
200
+ post: Post;
201
+ thread: Post;
202
+ channel_name: string;
203
+ }
204
+ export interface MentionRun extends MentionItem {
205
+ replies: Post[];
206
+ recent: Post[];
207
+ run_token: string;
208
+ }
209
+ export interface SearchResult {
210
+ type: 'post' | 'task' | 'message' | 'handoff';
211
+ id: string;
212
+ url: string;
213
+ snippet: string;
214
+ channel_name?: string;
215
+ author_name?: string;
216
+ task_ref?: string;
217
+ task_title?: string;
218
+ created?: string;
219
+ [k: string]: unknown;
220
+ }
221
+ export interface SendTaskInput {
222
+ to: string;
223
+ title: string;
224
+ priority: string;
225
+ purpose: string;
226
+ money: string;
227
+ handoff: string;
228
+ key_question?: string;
229
+ depends_on?: string[];
230
+ links?: Record<string, unknown>;
231
+ /** §16: channel name; default = the channel named like links.repo, else #general. */
232
+ channel?: string;
233
+ }
234
+ /** Header fields the sender may change after send. */
235
+ export interface TaskHeaderPatch {
236
+ priority?: string;
237
+ purpose?: string;
238
+ money?: string;
239
+ key_question?: string;
240
+ }
241
+ /** A sender-chosen extra repo (read-only for the worker). */
242
+ export interface LinkRepo {
243
+ repo: string;
244
+ base?: string;
245
+ }
246
+ /** Parse `name` or `name@base` (CLI `--read-repo`). */
247
+ export declare function parseLinkRepo(v: string): LinkRepo;
248
+ export interface PostMessageInput {
249
+ kind: MessageKind | string;
250
+ body: string;
251
+ to?: string;
252
+ /** Round 5: a decision request for a named person (user id, email or name; a member of the task's channel). */
253
+ to_user?: string;
254
+ evidence?: string;
255
+ reply_to?: string;
256
+ /** Tag, e.g. 'budget' for the runner's budget decision_request (§14.6). */
257
+ topic?: string;
258
+ /** A structured decision request: one question, 2–3 options (recommended first). */
259
+ question?: string;
260
+ options?: DecisionOption[];
261
+ recommended?: number;
262
+ }
263
+ export interface DecisionOption {
264
+ label: string;
265
+ detail?: string;
266
+ money?: string;
267
+ }
268
+ export declare class HubError extends Error {
269
+ status: number;
270
+ code?: string | undefined;
271
+ body?: unknown | undefined;
272
+ constructor(status: number, message: string, code?: string | undefined, body?: unknown | undefined);
273
+ }
274
+ /** A one-time login link: open `<hub><path>` (the token is in the URL fragment). */
275
+ export interface LoginLink {
276
+ token: string;
277
+ path: string;
278
+ url: string;
279
+ expires_at: string;
280
+ }
281
+ export type FetchLike = (url: string, init: RequestInit) => Promise<Response>;
282
+ export interface ClientOptions {
283
+ hub: string;
284
+ /** Agent key (ach_sk_...), run token (ach_rt_...) or a PocketBase user token. */
285
+ token?: string;
286
+ cfId?: string;
287
+ cfSecret?: string;
288
+ fetch?: FetchLike;
289
+ }
290
+ /** Round 2: human-facing CLI text in Chinese when LANG/LC_ALL starts with zh. */
291
+ export declare function isZh(env: NodeJS.ProcessEnv): boolean;
292
+ /** Picks the bearer: run token (spawned agent) beats agent key. */
293
+ export declare function clientFromConfig(cfg: Config, opts?: {
294
+ admin?: boolean;
295
+ fetch?: FetchLike;
296
+ }): Client;
297
+ /** Accept either `{task, handoff, messages, history}` or a bare task record. */
298
+ export declare function normalizeBundle(raw: any): TaskBundle;
299
+ export declare class Client {
300
+ readonly hub: string;
301
+ private token?;
302
+ private cfId?;
303
+ private cfSecret?;
304
+ private fetchFn;
305
+ constructor(o: ClientOptions);
306
+ headers(json?: boolean): Record<string, string>;
307
+ /** `files`: local paths (already checked by resolveAttachments) sent as multipart with the JSON in field "json". */
308
+ request<T = any>(method: string, path: string, body?: unknown, files?: string[]): Promise<T>;
309
+ private storageCfg?;
310
+ /** GET /storage/config once per client (null on hubs without it). */
311
+ storageConfig(): Promise<StorageConfig | null>;
312
+ /**
313
+ * §20 v1.1: https entries become link references; media files over the hub's
314
+ * direct-upload threshold go straight to its bucket (presign, PUT, complete)
315
+ * and become upload references. The rest is sent as multipart, as before.
316
+ */
317
+ private splitAttachments;
318
+ /** Upload one file directly to the hub's bucket; returns the reference to attach ({upload}). */
319
+ directUpload(file: string, target: string): Promise<{
320
+ upload: string;
321
+ }>;
322
+ /** Avatars: send one image as multipart field "file" (plus plain fields). */
323
+ sendImage<T = any>(method: string, path: string, bytes: Uint8Array, filename: string, fields?: Record<string, string>): Promise<T>;
324
+ private ach;
325
+ /** All attachments on a task (handoff versions and messages), with hub download URLs. */
326
+ taskFiles(taskId: string): Promise<TaskFile[]>;
327
+ /** Download one attachment into `dir`; returns the local path. */
328
+ download(a: Attachment, dir: string): Promise<string>;
329
+ me(): Promise<Agent>;
330
+ agents(): Promise<Agent[]>;
331
+ sendTask(input: SendTaskInput, files?: string[]): Promise<Task>;
332
+ /** Propose a recurring task (runs after the owner approves). */
333
+ proposeSchedule(input: Record<string, unknown>): Promise<any>;
334
+ schedules(): Promise<any[]>;
335
+ scheduleAction(id: string, action: 'pause' | 'resume'): Promise<any>;
336
+ removeSchedule(id: string): Promise<any>;
337
+ /** New handoff body (+ optional header fields, same version). Sender's agent key only. */
338
+ updateHandoff(taskId: string, body: string, change_note: string, header?: TaskHeaderPatch, files?: string[]): Promise<any>;
339
+ /** Header fields only (priority, purpose, money, key_question). Sender's agent key only. */
340
+ updateHeader(taskId: string, header: TaskHeaderPatch, change_note?: string): Promise<any>;
341
+ getTask(taskId: string): Promise<TaskBundle>;
342
+ claim(taskId: string, run_id: string, mode?: ClaimMode): Promise<ClaimResult>;
343
+ /** Mint an answer-mode run token for a question addressed to me (§14.2). */
344
+ answerRun(taskId: string, question_id: string, run_id: string): Promise<{
345
+ run_token: string;
346
+ [k: string]: unknown;
347
+ }>;
348
+ postMessage(taskId: string, m: PostMessageInput, files?: string[]): Promise<Message>;
349
+ /** With an agent key the hub requires the task's current run_id (C3); run tokens carry their own. */
350
+ complete(taskId: string, result: string, run_id?: string, files?: string[], handoff_version?: number): Promise<any>;
351
+ fail(taskId: string, reason: string, run_id?: string): Promise<any>;
352
+ /** §23: a grantee agent answers the part of a request its grant covers. */
353
+ grantDecide(taskId: string, message_id: string, option: number, grant: string): Promise<any>;
354
+ createGrant(input: {
355
+ agent?: string;
356
+ person?: string;
357
+ task?: string;
358
+ channel?: string;
359
+ cap?: number;
360
+ until?: string;
361
+ note?: string;
362
+ requester?: string;
363
+ }): Promise<any>;
364
+ listGrants(): Promise<{
365
+ given: any[];
366
+ received: any[];
367
+ }>;
368
+ revokeGrant(id: string): Promise<any>;
369
+ cancel(taskId: string, reason: string): Promise<any>;
370
+ /** The total size of a work prompt (Memory trial metrics). */
371
+ promptSize(taskId: string, run_id: string, chars: number, parts?: Record<string, number>): Promise<any>;
372
+ usage(taskId: string, run_id: string, cost_usd: number, estimated: boolean): Promise<any>;
373
+ /** 409 when the run lost the task. Carries a fresh `run_token` when the old one is near expiry (C5). */
374
+ heartbeat(taskId: string, run_id: string): Promise<{
375
+ ok: boolean;
376
+ status: string;
377
+ run_token?: string;
378
+ }>;
379
+ /** Revoke the answer token(s) of a finished answer run (C4). */
380
+ endRun(taskId: string, run_id: string): Promise<any>;
381
+ inbox(): Promise<Inbox>;
382
+ channels(all?: boolean): Promise<Channel[]>;
383
+ channelPosts(channel: string, o?: {
384
+ since?: string;
385
+ before?: string;
386
+ limit?: number;
387
+ }): Promise<{
388
+ channel: Channel;
389
+ posts: Post[];
390
+ }>;
391
+ post(channel: string, body: string, files?: string[], o?: {
392
+ announce?: boolean;
393
+ }): Promise<Post>;
394
+ reply(postId: string, body: string, o?: {
395
+ evidence?: string;
396
+ escalate?: boolean;
397
+ }, files?: string[]): Promise<Post>;
398
+ thread(postId: string): Promise<Thread>;
399
+ search(q: string, o?: {
400
+ channel?: string;
401
+ author?: string;
402
+ limit?: number;
403
+ }): Promise<{
404
+ query: string;
405
+ mode: string;
406
+ results: SearchResult[];
407
+ }>;
408
+ /** Take an @mention: a read-only "mention" run token for its thread. */
409
+ mentionRun(mentionId: string, run_id: string): Promise<MentionRun>;
410
+ mentionEnd(mentionId: string, run_id: string): Promise<any>;
411
+ mentionUsage(mentionId: string, run_id: string, cost_usd: number, estimated: boolean): Promise<any>;
412
+ agentProfile(name: string): Promise<any>;
413
+ /** `ach remember`: a fact or lesson with its source (hub permalink or GitHub URL); toTeam promotes it to the team overview. */
414
+ remember(text: string, source: string, o?: {
415
+ channel?: string;
416
+ topic?: string;
417
+ toTeam?: boolean;
418
+ }): Promise<any>;
419
+ /** `ach decide-draft`: ask the person (a decision request); their reply records the decision. */
420
+ decideDraft(input: {
421
+ text: string;
422
+ source: string;
423
+ by?: string;
424
+ channel?: string;
425
+ topic?: string;
426
+ task?: string;
427
+ scope?: string;
428
+ }): Promise<any>;
429
+ wikiIndex(channel?: string): Promise<any>;
430
+ wikiPage(slug: string): Promise<any>;
431
+ wikiSearch(q: string, limit?: number): Promise<{
432
+ query: string;
433
+ results: any[];
434
+ }>;
435
+ wikiExport(channel?: string): Promise<{
436
+ files: {
437
+ name: string;
438
+ slug: string;
439
+ version: number;
440
+ content: string;
441
+ }[];
442
+ template: string;
443
+ }>;
444
+ wikiPush(input: {
445
+ pages: unknown[];
446
+ figures?: unknown[];
447
+ note: string;
448
+ }): Promise<{
449
+ held?: boolean;
450
+ id?: string;
451
+ conflicts?: {
452
+ reason: string;
453
+ }[];
454
+ message?: string;
455
+ pages: {
456
+ slug: string;
457
+ version: number;
458
+ note?: string;
459
+ }[];
460
+ figures: unknown[];
461
+ warnings?: {
462
+ slug: string;
463
+ line: number;
464
+ problem: string;
465
+ text: string;
466
+ }[];
467
+ }>;
468
+ wikiSeed(): Promise<any>;
469
+ /** A bounded Memory summary for an interactive session (MCP instructions, SessionStart hook). */
470
+ memoryBrief(o?: {
471
+ channel?: string;
472
+ task?: string;
473
+ }): Promise<{
474
+ channel: string;
475
+ text: string;
476
+ chars: number;
477
+ }>;
478
+ decide(taskId: string, message_id: string, decision: string, files?: string[]): Promise<any>;
479
+ /** A human note on a task (user token; admins and the owners of either agent). */
480
+ note(taskId: string, body: string, files?: string[]): Promise<any>;
481
+ panel(): Promise<any>;
482
+ /** §15: a person (email optional) plus a one-time join link (24 h). No password. */
483
+ adminCreateUser(input: {
484
+ email?: string;
485
+ name: string;
486
+ is_admin?: boolean;
487
+ }): Promise<LoginLink & {
488
+ user: any;
489
+ }>;
490
+ adminListUsers(): Promise<any[]>;
491
+ /** §15: a fresh one-time login link (24 h) for a person's new device. */
492
+ adminUserLoginLink(ref: string): Promise<LoginLink & {
493
+ user: any;
494
+ }>;
495
+ adminPatchUser(ref: string, patch: Record<string, unknown>): Promise<any>;
496
+ /** §15 `ach open`: the agent key mints a 60 s single-use login link for its owner. */
497
+ loginLink(): Promise<LoginLink>;
498
+ /** Exchange a one-time login link token for a PocketBase user session. */
499
+ exchangeLoginLink(token: string): Promise<{
500
+ token: string;
501
+ record: any;
502
+ }>;
503
+ /** P4/P5: the logged-in human's own profile (notify_webhook, password, name). */
504
+ patchMe(patch: Record<string, unknown>): Promise<any>;
505
+ adminCreateAgent(input: Record<string, unknown>): Promise<any>;
506
+ /** `cf_token`: put the hub's shared front-door token in the invites (opt-in; default false). */
507
+ adminRotateKey(agentId: string, o?: {
508
+ cf_token?: boolean;
509
+ }): Promise<any>;
510
+ adminPatchAgent(agentId: string, patch: Record<string, unknown>): Promise<any>;
511
+ /** PocketBase built-in password auth for humans. */
512
+ userLogin(email: string, password: string): Promise<{
513
+ token: string;
514
+ record: any;
515
+ }>;
516
+ }
517
+ /** Inbox message entries are `{message, task}`; flatten to the message (task id stays in `message.task`). */
518
+ export declare function flatMsgs(v: unknown): Message[];
519
+ /** "#general" -> "general". */
520
+ export declare function channelRef(c: string): string;