@flytedesk/app-kit 0.3.0 → 0.4.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 (56) hide show
  1. package/README.md +6 -3
  2. package/dist/bigquery/client.d.ts +18 -0
  3. package/dist/bigquery/client.js +37 -0
  4. package/dist/bigquery/client.js.map +1 -0
  5. package/dist/bigquery/errors.d.ts +26 -0
  6. package/dist/bigquery/errors.js +80 -0
  7. package/dist/bigquery/errors.js.map +1 -0
  8. package/dist/bigquery/extract.d.ts +15 -0
  9. package/dist/bigquery/extract.js +88 -0
  10. package/dist/bigquery/extract.js.map +1 -0
  11. package/dist/bigquery/index.d.ts +47 -0
  12. package/dist/bigquery/index.js +46 -0
  13. package/dist/bigquery/index.js.map +1 -0
  14. package/dist/bigquery/labels.d.ts +16 -0
  15. package/dist/bigquery/labels.js +26 -0
  16. package/dist/bigquery/labels.js.map +1 -0
  17. package/dist/bigquery/query.d.ts +16 -0
  18. package/dist/bigquery/query.js +86 -0
  19. package/dist/bigquery/query.js.map +1 -0
  20. package/dist/bigquery/types.d.ts +155 -0
  21. package/dist/bigquery/types.js +15 -0
  22. package/dist/bigquery/types.js.map +1 -0
  23. package/dist/chat/callback-secret.d.ts +21 -0
  24. package/dist/chat/callback-secret.js +33 -0
  25. package/dist/chat/callback-secret.js.map +1 -0
  26. package/dist/chat/env.d.ts +27 -0
  27. package/dist/chat/env.js +44 -0
  28. package/dist/chat/env.js.map +1 -0
  29. package/dist/chat/index.d.ts +72 -0
  30. package/dist/chat/index.js +70 -0
  31. package/dist/chat/index.js.map +1 -0
  32. package/dist/chat/launcher.d.ts +43 -0
  33. package/dist/chat/launcher.js +103 -0
  34. package/dist/chat/launcher.js.map +1 -0
  35. package/dist/chat/mcp-protocol.d.ts +96 -0
  36. package/dist/chat/mcp-protocol.js +200 -0
  37. package/dist/chat/mcp-protocol.js.map +1 -0
  38. package/dist/chat/mcp-server.d.ts +17 -0
  39. package/dist/chat/mcp-server.js +71 -0
  40. package/dist/chat/mcp-server.js.map +1 -0
  41. package/dist/chat/types.d.ts +91 -0
  42. package/dist/chat/types.js +5 -0
  43. package/dist/chat/types.js.map +1 -0
  44. package/dist/cli/flags-sync.js +2 -5
  45. package/dist/cli/flags-sync.js.map +1 -1
  46. package/dist/cli/profile-sync.js +2 -5
  47. package/dist/cli/profile-sync.js.map +1 -1
  48. package/dist/cli/sync-engine.d.ts +32 -0
  49. package/dist/cli/sync-engine.js +190 -23
  50. package/dist/cli/sync-engine.js.map +1 -1
  51. package/dist/cli/trace-sync.js +2 -5
  52. package/dist/cli/trace-sync.js.map +1 -1
  53. package/package.json +10 -1
  54. package/scripts/pending-release-count.mjs +37 -0
  55. package/scripts/release.sh +126 -0
  56. package/scripts/release.test.ts +205 -0
@@ -0,0 +1,96 @@
1
+ /**
2
+ * The Model Context Protocol conversation a dispatched chat agent speaks, as pure
3
+ * functions — extracted and generalized from media-planner's
4
+ * `packages/chat-mcp/src/protocol.mjs`.
5
+ *
6
+ * MCP over stdio is JSON-RPC 2.0 in newline-delimited JSON. The surface a client
7
+ * actually needs from a tools-only server is small — `initialize`, `tools/list`,
8
+ * `tools/call`, and `ping` — implemented directly here rather than pulling in the
9
+ * MCP SDK, the same reasoning the original file gave: this protocol is meant to run
10
+ * dependency-free (see mcp-server.ts), so this module imports nothing beyond
11
+ * ./types.js.
12
+ *
13
+ * The ONE thing the original hard-coded that this version generalizes: which tools
14
+ * exist. There, `planner_reply` plus five media-planner-specific tools were all
15
+ * switched on by name inside `tools/call`. Here, `tools/call` dispatches to whichever
16
+ * `AppRegisteredTool` the caller registered — `createReplyTool` below builds the
17
+ * reply tool through that SAME mechanism, so "the reply tool" and "an app's own
18
+ * tool" are not two different code paths, just two entries in the same array. That
19
+ * array is the extension point AK-12 asks for: an app adds `audience_validate`,
20
+ * `audience_sample`, `audience_propose_change`, or whatever else it needs, by
21
+ * passing more `AppRegisteredTool` entries to `createChatMcpProtocol`.
22
+ */
23
+ import type { AppRegisteredTool } from "./types.js";
24
+ /** The protocol version this server implements and will fall back to. */
25
+ export declare const FALLBACK_PROTOCOL_VERSION = "2024-11-05";
26
+ /** JSON-RPC error codes used here (the subset from the spec that applies). */
27
+ export declare const JSON_RPC: {
28
+ INVALID_PARAMS: number;
29
+ METHOD_NOT_FOUND: number;
30
+ INTERNAL_ERROR: number;
31
+ };
32
+ export interface ChatMcpProtocolOptions {
33
+ /** Advertised in `initialize`'s `serverInfo.name`. */
34
+ serverName: string;
35
+ /** Advertised in `initialize`'s `serverInfo.version`. Defaults to "0.1.0". */
36
+ serverVersion?: string;
37
+ /** Every tool this server exposes — the reply tool (via `createReplyTool`) plus
38
+ * whatever the consuming app registers of its own. Order is preserved in
39
+ * `tools/list`. */
40
+ tools: AppRegisteredTool[];
41
+ }
42
+ export interface ChatMcpProtocol {
43
+ /**
44
+ * Handle one incoming JSON-RPC message. Returns `null` for anything that must not
45
+ * be answered — notifications (which carry no id and by spec get no response).
46
+ * The caller writes whatever is returned and writes nothing otherwise.
47
+ */
48
+ handleMessage(message: Record<string, unknown>): Promise<Record<string, unknown> | null>;
49
+ }
50
+ export declare function createChatMcpProtocol(options: ChatMcpProtocolOptions): ChatMcpProtocol;
51
+ export interface ChatReplyPayload {
52
+ kind: "progress" | "final";
53
+ text: string;
54
+ packet?: {
55
+ type: string;
56
+ payload: Record<string, unknown>;
57
+ };
58
+ citations?: unknown[];
59
+ }
60
+ export type ReplyDeliverResult = {
61
+ ok: true;
62
+ } | {
63
+ ok: false;
64
+ retryable: boolean;
65
+ message: string;
66
+ };
67
+ export interface ParseReplyArgumentsOptions {
68
+ /** Restrict `packet.type` to this list. Omit to allow any non-empty string —
69
+ * useful when the app validates packet shape downstream of delivery instead
70
+ * (the same choice media-planner's own `/chat/internal/reply` route makes). */
71
+ packetTypes?: string[];
72
+ }
73
+ /** Validate the arguments of a reply-tool call. Exported for direct unit testing,
74
+ * matching the original protocol.mjs's own `parseReplyArguments`. */
75
+ export declare function parseReplyArguments(args: unknown, options?: ParseReplyArgumentsOptions): {
76
+ ok: true;
77
+ value: ChatReplyPayload;
78
+ } | {
79
+ ok: false;
80
+ message: string;
81
+ };
82
+ export interface ReplyToolOptions {
83
+ /** Tool name advertised to the agent. Default "chat_reply". */
84
+ name?: string;
85
+ /** Full description shown to the model — write this in your own product's voice;
86
+ * it is the one thing that tells the agent this is its ONLY way to speak. */
87
+ description: string;
88
+ /** See ParseReplyArgumentsOptions.packetTypes. */
89
+ packetTypes?: string[];
90
+ /** POST (or otherwise deliver) one reply to the app's own callback route. */
91
+ deliver: (reply: ChatReplyPayload) => Promise<ReplyDeliverResult>;
92
+ }
93
+ /** Build the reply tool — the ONE tool every consumer of this module needs, and the
94
+ * one built-in entry alongside whatever `AppRegisteredTool`s the app adds of its
95
+ * own (the extension point). */
96
+ export declare function createReplyTool(options: ReplyToolOptions): AppRegisteredTool;
@@ -0,0 +1,200 @@
1
+ /** The protocol version this server implements and will fall back to. */
2
+ export const FALLBACK_PROTOCOL_VERSION = "2024-11-05";
3
+ /** JSON-RPC error codes used here (the subset from the spec that applies). */
4
+ export const JSON_RPC = {
5
+ INVALID_PARAMS: -32602,
6
+ METHOD_NOT_FOUND: -32601,
7
+ INTERNAL_ERROR: -32603,
8
+ };
9
+ function ok(id, result) {
10
+ return { jsonrpc: "2.0", id, result };
11
+ }
12
+ function err(id, code, message) {
13
+ return { jsonrpc: "2.0", id, error: { code, message } };
14
+ }
15
+ /**
16
+ * A tool-call outcome that is the AGENT's mistake rather than a transport failure —
17
+ * a bad argument, or a reply sent after the turn already closed. MCP models these as
18
+ * a successful call whose result carries `isError`, which is what puts the message
19
+ * in front of the model so it can correct itself, instead of a JSON-RPC error that
20
+ * surfaces as a broken tool.
21
+ */
22
+ function toolError(id, message) {
23
+ return ok(id, { content: [{ type: "text", text: message }], isError: true });
24
+ }
25
+ function toolSuccess(id, content) {
26
+ return ok(id, { content });
27
+ }
28
+ export function createChatMcpProtocol(options) {
29
+ const toolsByName = new Map(options.tools.map((tool) => [tool.name, tool]));
30
+ return {
31
+ async handleMessage(message) {
32
+ const method = typeof message.method === "string" ? message.method : "";
33
+ const hasId = message.id !== undefined && message.id !== null;
34
+ const id = hasId ? message.id : null;
35
+ // Notifications carry no id and get no response, per JSON-RPC.
36
+ if (!hasId)
37
+ return null;
38
+ switch (method) {
39
+ case "initialize": {
40
+ const params = (message.params ?? {});
41
+ const requested = params.protocolVersion;
42
+ return ok(id, {
43
+ protocolVersion: typeof requested === "string" ? requested : FALLBACK_PROTOCOL_VERSION,
44
+ capabilities: { tools: {} },
45
+ serverInfo: { name: options.serverName, version: options.serverVersion ?? "0.1.0" },
46
+ });
47
+ }
48
+ case "tools/list":
49
+ return ok(id, {
50
+ tools: options.tools.map((tool) => ({
51
+ name: tool.name,
52
+ description: tool.description,
53
+ inputSchema: tool.inputSchema,
54
+ })),
55
+ });
56
+ case "tools/call": {
57
+ const params = (message.params ?? {});
58
+ const name = params.name;
59
+ if (typeof name !== "string" || name === "") {
60
+ return err(id, JSON_RPC.INVALID_PARAMS, '`params.name` must be a non-empty string.');
61
+ }
62
+ const tool = toolsByName.get(name);
63
+ if (!tool) {
64
+ return err(id, JSON_RPC.METHOD_NOT_FOUND, `Unknown tool "${name}"`);
65
+ }
66
+ const result = await tool.handler(params.arguments);
67
+ if (result.ok)
68
+ return toolSuccess(id, result.content);
69
+ // A retryable failure is the transport's fault and is reported as a
70
+ // JSON-RPC error; a non-retryable one is the agent's own mistake and is
71
+ // reported as a tool error so the model reads it and corrects itself
72
+ // rather than retrying into the same failure.
73
+ return result.retryable
74
+ ? err(id, JSON_RPC.INTERNAL_ERROR, result.message)
75
+ : toolError(id, result.message);
76
+ }
77
+ case "ping":
78
+ return ok(id, {});
79
+ default:
80
+ return err(id, JSON_RPC.METHOD_NOT_FOUND, `Unknown method "${method}"`);
81
+ }
82
+ },
83
+ };
84
+ }
85
+ /** Validate the arguments of a reply-tool call. Exported for direct unit testing,
86
+ * matching the original protocol.mjs's own `parseReplyArguments`. */
87
+ export function parseReplyArguments(args, options = {}) {
88
+ if (args === null || typeof args !== "object" || Array.isArray(args)) {
89
+ return { ok: false, message: "Arguments must be an object with `kind` and `text`." };
90
+ }
91
+ const record = args;
92
+ const { kind, text, packet, citations } = record;
93
+ if (kind !== "progress" && kind !== "final") {
94
+ return { ok: false, message: '`kind` must be either "progress" or "final".' };
95
+ }
96
+ if (typeof text !== "string" || text.trim() === "") {
97
+ return { ok: false, message: "`text` must be a non-empty string." };
98
+ }
99
+ if (packet !== undefined && packet !== null) {
100
+ if (typeof packet !== "object" || Array.isArray(packet)) {
101
+ return { ok: false, message: "`packet` must be an object with `type` and `payload`." };
102
+ }
103
+ const p = packet;
104
+ if (typeof p.type !== "string" || p.type === "") {
105
+ return { ok: false, message: "`packet.type` must be a non-empty string." };
106
+ }
107
+ if (options.packetTypes && !options.packetTypes.includes(p.type)) {
108
+ return {
109
+ ok: false,
110
+ message: `\`packet.type\` must be one of: ${options.packetTypes.join(", ")}.`,
111
+ };
112
+ }
113
+ if (p.payload === null || typeof p.payload !== "object" || Array.isArray(p.payload)) {
114
+ return { ok: false, message: "`packet.payload` must be an object." };
115
+ }
116
+ // A packet on a progress line would never be rendered — reject it rather than
117
+ // dropping it silently and leaving the agent believing it proposed something.
118
+ if (kind === "progress") {
119
+ return { ok: false, message: "A `packet` can only be attached to a `final` reply." };
120
+ }
121
+ }
122
+ if (citations !== undefined && citations !== null && !Array.isArray(citations)) {
123
+ return { ok: false, message: "`citations` must be an array." };
124
+ }
125
+ const value = { kind, text };
126
+ if (packet !== undefined && packet !== null)
127
+ value.packet = packet;
128
+ if (citations !== undefined && citations !== null)
129
+ value.citations = citations;
130
+ return { ok: true, value };
131
+ }
132
+ /** Build the reply tool — the ONE tool every consumer of this module needs, and the
133
+ * one built-in entry alongside whatever `AppRegisteredTool`s the app adds of its
134
+ * own (the extension point). */
135
+ export function createReplyTool(options) {
136
+ const name = options.name ?? "chat_reply";
137
+ return {
138
+ name,
139
+ description: options.description,
140
+ inputSchema: {
141
+ type: "object",
142
+ properties: {
143
+ kind: {
144
+ type: "string",
145
+ enum: ["progress", "final"],
146
+ description: '"progress" for a short status line shown while you work (send this immediately, ' +
147
+ 'before doing anything else); "final" for your complete answer. Exactly one "final" per turn.',
148
+ },
149
+ text: {
150
+ type: "string",
151
+ description: 'The message. For "final", markdown formatted. For "progress", one short present-tense line.',
152
+ },
153
+ packet: {
154
+ type: "object",
155
+ description: "Optional, and only on a final reply: a structured proposal attached to the answer.",
156
+ properties: {
157
+ type: options.packetTypes ? { type: "string", enum: options.packetTypes } : { type: "string" },
158
+ payload: { type: "object" },
159
+ },
160
+ required: ["type", "payload"],
161
+ },
162
+ citations: {
163
+ type: "array",
164
+ description: "Optional source references shown under a final answer.",
165
+ items: {
166
+ type: "object",
167
+ properties: {
168
+ marker: { type: "number" },
169
+ title: { type: "string" },
170
+ detail: { type: "string" },
171
+ },
172
+ required: ["marker", "title"],
173
+ },
174
+ },
175
+ },
176
+ required: ["kind", "text"],
177
+ },
178
+ async handler(args) {
179
+ const parsed = parseReplyArguments(args, { packetTypes: options.packetTypes });
180
+ if (!parsed.ok)
181
+ return { ok: false, retryable: false, message: parsed.message };
182
+ const result = await options.deliver(parsed.value);
183
+ if (result.ok) {
184
+ return {
185
+ ok: true,
186
+ content: [
187
+ {
188
+ type: "text",
189
+ text: parsed.value.kind === "final"
190
+ ? "Delivered. This turn is now complete — do not send anything further."
191
+ : "Delivered. Continue with the work, then send your final reply.",
192
+ },
193
+ ],
194
+ };
195
+ }
196
+ return { ok: false, retryable: result.retryable, message: result.message };
197
+ },
198
+ };
199
+ }
200
+ //# sourceMappingURL=mcp-protocol.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-protocol.js","sourceRoot":"","sources":["../../src/chat/mcp-protocol.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ import type { ChatMcpProtocol } from "./mcp-protocol.js";
2
+ export interface ChatMcpStdioServerOptions {
3
+ protocol: ChatMcpProtocol;
4
+ /** Defaults to `process.stdin`. Overridable for tests. */
5
+ input?: NodeJS.ReadableStream;
6
+ /** Defaults to `process.stdout`. Overridable for tests. */
7
+ output?: NodeJS.WritableStream;
8
+ /** Defaults to writing to `process.stderr`. Overridable for tests. */
9
+ onError?: (message: string) => void;
10
+ }
11
+ export interface ChatMcpStdioServer {
12
+ /** Start reading lines from `input`. Registers listeners and returns immediately —
13
+ * it does not block until the stream closes; the process stays alive on its own
14
+ * (stdin being read is enough to keep Node running) until `input` closes. */
15
+ start(): void;
16
+ }
17
+ export declare function createChatMcpStdioServer(options: ChatMcpStdioServerOptions): ChatMcpStdioServer;
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The stdio transport for a chat MCP server — extracted and generalized from
3
+ * media-planner's `packages/chat-mcp/src/server.mjs`'s I/O loop (that file's own
4
+ * `deliver`/`read`/`write` HTTP helpers stay app-specific; only the newline-delimited
5
+ * JSON-RPC plumbing moves here).
6
+ *
7
+ * Deliberately built on Node builtins ONLY (`node:readline`) — no runtime dependency
8
+ * on anything else in this package or elsewhere. The reason: danxbot runs a
9
+ * dispatched agent's MCP server straight out of a plain git clone with no install
10
+ * step, so whatever script actually executes there must be runnable with nothing
11
+ * more than `node <file>`. This module (and mcp-protocol.ts, which it composes with)
12
+ * satisfy that constraint structurally; wiring a specific app's checkout so the
13
+ * *published* `@flytedesk/app-kit` package is actually resolvable from that
14
+ * unbuilt clone is that app's own integration concern, not this module's.
15
+ */
16
+ import { createInterface } from "node:readline";
17
+ export function createChatMcpStdioServer(options) {
18
+ const input = options.input ?? process.stdin;
19
+ const output = options.output ?? process.stdout;
20
+ const onError = options.onError ?? ((message) => process.stderr.write(`${message}\n`));
21
+ function writeLine(payload) {
22
+ output.write(`${JSON.stringify(payload)}\n`);
23
+ }
24
+ return {
25
+ start() {
26
+ const rl = createInterface({ input });
27
+ rl.on("line", (line) => {
28
+ const trimmed = line.trim();
29
+ if (trimmed === "")
30
+ return;
31
+ let message;
32
+ try {
33
+ message = JSON.parse(trimmed);
34
+ }
35
+ catch {
36
+ // Unparseable input has no id to answer against, so there is nothing to
37
+ // reply to — report it and keep the stream alive rather than tearing down
38
+ // the session.
39
+ onError(`ignoring unparseable line: ${trimmed}`);
40
+ return;
41
+ }
42
+ // Handled without awaiting so a slow delivery cannot block the next
43
+ // request; JSON-RPC responses carry their own id, so out-of-order
44
+ // completion is fine.
45
+ void options.protocol
46
+ .handleMessage(message)
47
+ .then((response) => {
48
+ if (response)
49
+ writeLine(response);
50
+ })
51
+ .catch((cause) => {
52
+ const err = cause;
53
+ onError(`handler failed: ${err?.stack ?? String(cause)}`);
54
+ const id = message.id;
55
+ if (id !== undefined && id !== null) {
56
+ writeLine({
57
+ jsonrpc: "2.0",
58
+ id,
59
+ error: { code: -32603, message: `Internal error: ${err?.message ?? String(cause)}` },
60
+ });
61
+ }
62
+ });
63
+ });
64
+ // stdin closing is the client going away — nothing further to do; the
65
+ // process's own exit is the caller's concern (see this module's usage in a
66
+ // package `bin`/entrypoint script), not this function's.
67
+ rl.on("close", () => { });
68
+ },
69
+ };
70
+ }
71
+ //# sourceMappingURL=mcp-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-server.js","sourceRoot":"","sources":["../../src/chat/mcp-server.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAoBhD,MAAM,UAAU,wBAAwB,CAAC,OAAkC;IACzE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,KAAK,CAAC;IAC7C,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC;IAChD,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,IAAI,CAAC,CAAC,OAAe,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,OAAO,IAAI,CAAC,CAAC,CAAC;IAE/F,SAAS,SAAS,CAAC,OAAgC;QACjD,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/C,CAAC;IAED,OAAO;QACL,KAAK;YACH,MAAM,EAAE,GAAG,eAAe,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YAEtC,EAAE,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,IAAI,EAAE,EAAE;gBACrB,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;gBAC5B,IAAI,OAAO,KAAK,EAAE;oBAAE,OAAO;gBAE3B,IAAI,OAAgC,CAAC;gBACrC,IAAI,CAAC;oBACH,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAA4B,CAAC;gBAC3D,CAAC;gBAAC,MAAM,CAAC;oBACP,wEAAwE;oBACxE,0EAA0E;oBAC1E,eAAe;oBACf,OAAO,CAAC,8BAA8B,OAAO,EAAE,CAAC,CAAC;oBACjD,OAAO;gBACT,CAAC;gBAED,oEAAoE;gBACpE,kEAAkE;gBAClE,sBAAsB;gBACtB,KAAK,OAAO,CAAC,QAAQ;qBAClB,aAAa,CAAC,OAAO,CAAC;qBACtB,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE;oBACjB,IAAI,QAAQ;wBAAE,SAAS,CAAC,QAAQ,CAAC,CAAC;gBACpC,CAAC,CAAC;qBACD,KAAK,CAAC,CAAC,KAAc,EAAE,EAAE;oBACxB,MAAM,GAAG,GAAG,KAAyD,CAAC;oBACtE,OAAO,CAAC,mBAAmB,GAAG,EAAE,KAAK,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;oBAC1D,MAAM,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC;oBACtB,IAAI,EAAE,KAAK,SAAS,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC;wBACpC,SAAS,CAAC;4BACR,OAAO,EAAE,KAAK;4BACd,EAAE;4BACF,KAAK,EAAE,EAAE,IAAI,EAAE,CAAC,KAAK,EAAE,OAAO,EAAE,mBAAmB,GAAG,EAAE,OAAO,IAAI,MAAM,CAAC,KAAK,CAAC,EAAE,EAAE;yBACrF,CAAC,CAAC;oBACL,CAAC;gBACH,CAAC,CAAC,CAAC;YACP,CAAC,CAAC,CAAC;YAEH,sEAAsE;YACtE,2EAA2E;YAC3E,yDAAyD;YACzD,EAAE,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE,GAAE,CAAC,CAAC,CAAC;QAC3B,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Shared types for @flytedesk/app-kit/chat — see index.ts for the module overview.
3
+ */
4
+ /** danxbot's own launch/resume response shape (`POST /api/launch` / `/api/resume`). */
5
+ export interface DanxbotDispatchResult {
6
+ jobId: string;
7
+ parentJobId?: string;
8
+ }
9
+ export interface DanxbotJobStatus {
10
+ jobId: string;
11
+ /** danxbot's own vocabulary — "running", "completed", "failed", "critical_failure", … */
12
+ status: string;
13
+ summary: string;
14
+ elapsedSeconds: number;
15
+ /** Real usage off danxbot's own wire, never estimated. Defaulted to 0 only for a
16
+ * field genuinely ABSENT from an otherwise-successful response (defensive parsing
17
+ * of someone else's JSON) — a failed `getJobStatus` call throws, it never returns
18
+ * zeros to paper over a failure. */
19
+ inputTokens: number;
20
+ outputTokens: number;
21
+ cacheReadInputTokens: number;
22
+ cacheCreationInputTokens: number;
23
+ }
24
+ export interface DanxbotLauncherOptions {
25
+ /** Base URL of the danxbot worker's HTTP API, e.g. "http://localhost:5555". */
26
+ apiUrl: string;
27
+ /** Bearer token danxbot's `/api/launch`/`/api/resume`/`/api/status` expect. */
28
+ apiToken: string;
29
+ /** The danxbot board this app's chat turns dispatch onto, e.g. "sms-app:sms-app-main". */
30
+ board: string;
31
+ /** The danxbot agent profile to dispatch — the board-level chat profile the
32
+ * consuming app registered (see this module's README section on wiring a
33
+ * `.danxbot/config` profile override), NOT danxbot's own per-card `board-chat`. */
34
+ profile: string;
35
+ }
36
+ export interface DanxbotLauncher {
37
+ /** Dispatch one chat turn — see dispatchChatTurn's own doc comment for the
38
+ * launch-vs-resume branching. */
39
+ dispatchChatTurn(input: {
40
+ task: string;
41
+ overlay: Record<string, string>;
42
+ parentJobId?: string | null;
43
+ }): Promise<DanxbotDispatchResult>;
44
+ getJobStatus(jobId: string): Promise<DanxbotJobStatus>;
45
+ }
46
+ /** One MCP tool-result content block — the two kinds this module's tools ever return. */
47
+ export type ChatToolContent = {
48
+ type: "text";
49
+ text: string;
50
+ } | {
51
+ type: "image";
52
+ data: string;
53
+ mimeType: string;
54
+ };
55
+ /**
56
+ * The outcome of one tool call, common to the built-in reply tool and every
57
+ * app-registered tool. Mirrors the retryable/non-retryable split the underlying HTTP
58
+ * call already makes: a transport failure (network error, 5xx) is worth the agent
59
+ * retrying, while a 4xx/validation failure is the agent's own mistake to correct, so
60
+ * it is reported as a tool error the model reads rather than a broken tool.
61
+ */
62
+ export type ChatToolCallResult = {
63
+ ok: true;
64
+ content: ChatToolContent[];
65
+ } | {
66
+ ok: false;
67
+ retryable: boolean;
68
+ message: string;
69
+ };
70
+ /**
71
+ * One tool an app registers on top of the shared chat MCP server — the extension
72
+ * point AK-12 exists to provide. `handler` receives the raw `tools/call` arguments
73
+ * (validating them, including reporting a bad argument as a non-retryable
74
+ * `ChatToolCallResult`, is the tool's own job — the same contract MCP itself uses:
75
+ * arguments are untyped until a specific tool decides what shape it needs).
76
+ */
77
+ export interface AppRegisteredTool {
78
+ name: string;
79
+ description: string;
80
+ /** JSON Schema, exactly as advertised in `tools/list`. */
81
+ inputSchema: Record<string, unknown>;
82
+ handler: (args: unknown) => Promise<ChatToolCallResult>;
83
+ }
84
+ /** The env contract every app wiring this module in shares — see env.ts. */
85
+ export interface ChatEnv {
86
+ danxbotApiUrl: string;
87
+ danxbotBoardId: string;
88
+ danxbotApiToken: string;
89
+ danxbotCallbackApiUrl: string;
90
+ danxbotCallbackSecret: string;
91
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shared types for @flytedesk/app-kit/chat — see index.ts for the module overview.
3
+ */
4
+ export {};
5
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/chat/types.ts"],"names":[],"mappings":"AAAA;;GAEG"}
@@ -8,14 +8,11 @@
8
8
  * fragment name and the "flags-sync" bin name; trace-sync.ts/profile-sync.ts are the
9
9
  * same wrapper for the trace/profile fragments.
10
10
  */
11
- import { pathToFileURL } from "node:url";
12
- import { runSyncCli, SyncCliError } from "./sync-engine.js";
11
+ import { isRunningAsMain, runSyncCli, SyncCliError } from "./sync-engine.js";
13
12
  export async function main(argv) {
14
13
  return runSyncCli(argv, { name: "flags", binName: "flags-sync" });
15
14
  }
16
- const isMainModule = process.argv[1] !== undefined &&
17
- import.meta.url === pathToFileURL(process.argv[1]).href;
18
- if (isMainModule) {
15
+ if (isRunningAsMain(import.meta.url)) {
19
16
  main(process.argv.slice(2)).catch((err) => {
20
17
  if (!(err instanceof SyncCliError)) {
21
18
  console.error(err);
@@ -1 +1 @@
1
- {"version":3,"file":"flags-sync.js","sourceRoot":"","sources":["../../src/cli/flags-sync.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,MAAM,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;IAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAE1D,IAAI,YAAY,EAAE,CAAC;IACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,GAAG,YAAY,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"flags-sync.js","sourceRoot":"","sources":["../../src/cli/flags-sync.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC;AACpE,CAAC;AAED,IAAI,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,GAAG,YAAY,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -8,14 +8,11 @@
8
8
  * fragment name and the "profile-sync" bin name; trace-sync.ts is the same wrapper
9
9
  * for the trace fragment.
10
10
  */
11
- import { pathToFileURL } from "node:url";
12
- import { runSyncCli, SyncCliError } from "./sync-engine.js";
11
+ import { isRunningAsMain, runSyncCli, SyncCliError } from "./sync-engine.js";
13
12
  export async function main(argv) {
14
13
  return runSyncCli(argv, { name: "profile", binName: "profile-sync" });
15
14
  }
16
- const isMainModule = process.argv[1] !== undefined &&
17
- import.meta.url === pathToFileURL(process.argv[1]).href;
18
- if (isMainModule) {
15
+ if (isRunningAsMain(import.meta.url)) {
19
16
  main(process.argv.slice(2)).catch((err) => {
20
17
  if (!(err instanceof SyncCliError)) {
21
18
  console.error(err);
@@ -1 +1 @@
1
- {"version":3,"file":"profile-sync.js","sourceRoot":"","sources":["../../src/cli/profile-sync.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE5D,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,MAAM,YAAY,GAChB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,SAAS;IAC7B,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAE1D,IAAI,YAAY,EAAE,CAAC;IACjB,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,GAAG,YAAY,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"profile-sync.js","sourceRoot":"","sources":["../../src/cli/profile-sync.ts"],"names":[],"mappings":";AACA;;;;;;;;GAQG;AACH,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAE7E,MAAM,CAAC,KAAK,UAAU,IAAI,CAAC,IAAc;IACvC,OAAO,UAAU,CAAC,IAAI,EAAE,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;AACxE,CAAC;AAED,IAAI,eAAe,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;IACrC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,GAAG,YAAY,YAAY,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QACrB,CAAC;QACD,OAAO,CAAC,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC3C,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -1,3 +1,35 @@
1
+ /**
2
+ * Whether the module at `moduleUrl` (pass `import.meta.url`) is the one Node was
3
+ * invoked to run directly — the ESM successor to `require.main === module`, shared
4
+ * by every bin wrapper (trace-sync.ts/profile-sync.ts/flags-sync.ts) so there's one
5
+ * fix point instead of three copies of the same check.
6
+ *
7
+ * A raw `import.meta.url === pathToFileURL(process.argv[1]).href` string comparison
8
+ * (the previous check) is NOT reliable: a package manager's bin shim can leave
9
+ * `argv[1]` pointing at a *symlink* while Node resolves the ESM module id through
10
+ * that symlink to the real target path for `import.meta.url` — so the two name the
11
+ * same file but compare unequal. This is not hypothetical: pnpm's
12
+ * `node_modules/<pkg>` is exactly such a symlink into its content-addressable
13
+ * store, and it reproduces on Windows for every real invocation path (`pnpm exec
14
+ * flags-sync init`, an npm-script `"flags-sync init"` run via `pnpm run`, etc.) —
15
+ * confirmed by instrumenting a real 0.3.0 install: `argv[1]` resolved to
16
+ * `...\node_modules\@flytedesk\app-kit\dist\cli\flags-sync.js` (the symlinked
17
+ * path) while `import.meta.url` resolved to
18
+ * `...\node_modules\.pnpm\@flytedesk+app-kit@0.3.0_.../node_modules\@flytedesk\app-kit\dist\cli\flags-sync.js`
19
+ * (the real store path). The mismatch meant `main()` was never called at all —
20
+ * every CLI entrypoint silently no-op'd: exit code 0, no output, nothing written.
21
+ *
22
+ * `realpathSync.native` (the real OS `realpath` syscall, not Node's pure-JS
23
+ * fallback — verified directly: the JS fallback leaves an on-disk casing mismatch
24
+ * unresolved, e.g. `RealFile.js` vs `realfile.js` compare unequal even though NTFS
25
+ * treats them as the same file, while `.native` correctly normalizes both to the
26
+ * same canonical path) resolves both sides to the same canonical filesystem path
27
+ * first — following symlinks AND normalizing casing — so the comparison is correct
28
+ * regardless of symlinks, path-separator style, or casing differences between how
29
+ * a shell/bin-shim sets `argv[1]` and how Node constructs `import.meta.url` for
30
+ * the same file.
31
+ */
32
+ export declare function isRunningAsMain(moduleUrl: string): boolean;
1
33
  /**
2
34
  * Everything that differs between `trace-sync` and `profile-sync`. `name` picks out
3
35
  * prisma/fragments/<name>.prisma, prisma/fragments/<name>.meta.json, and every