agent-sin 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (150) hide show
  1. package/CHANGELOG.md +33 -0
  2. package/LICENSE +21 -0
  3. package/README.md +81 -0
  4. package/assets/logo.png +0 -0
  5. package/builtin-skills/_shared/_models_lib.py +227 -0
  6. package/builtin-skills/_shared/_profile_lib.py +98 -0
  7. package/builtin-skills/_shared/_schedules_lib.py +313 -0
  8. package/builtin-skills/_shared/_skill_settings_lib.py +153 -0
  9. package/builtin-skills/_shared/i18n.py +26 -0
  10. package/builtin-skills/memo-delete/main.py +155 -0
  11. package/builtin-skills/memo-delete/skill.yaml +57 -0
  12. package/builtin-skills/memo-index/main.py +178 -0
  13. package/builtin-skills/memo-index/skill.yaml +53 -0
  14. package/builtin-skills/memo-save/README.md +5 -0
  15. package/builtin-skills/memo-save/main.py +74 -0
  16. package/builtin-skills/memo-save/skill.yaml +52 -0
  17. package/builtin-skills/memo-search/README.md +10 -0
  18. package/builtin-skills/memo-search/main.py +97 -0
  19. package/builtin-skills/memo-search/skill.yaml +51 -0
  20. package/builtin-skills/memo-vector-search/main.py +121 -0
  21. package/builtin-skills/memo-vector-search/skill.yaml +53 -0
  22. package/builtin-skills/model-add/main.py +180 -0
  23. package/builtin-skills/model-add/skill.yaml +112 -0
  24. package/builtin-skills/model-list/main.py +93 -0
  25. package/builtin-skills/model-list/skill.yaml +48 -0
  26. package/builtin-skills/model-set/main.py +123 -0
  27. package/builtin-skills/model-set/skill.yaml +69 -0
  28. package/builtin-skills/profile-delete/_profile_lib.py +98 -0
  29. package/builtin-skills/profile-delete/main.py +98 -0
  30. package/builtin-skills/profile-delete/skill.yaml +64 -0
  31. package/builtin-skills/profile-edit/_profile_lib.py +98 -0
  32. package/builtin-skills/profile-edit/main.py +97 -0
  33. package/builtin-skills/profile-edit/skill.yaml +72 -0
  34. package/builtin-skills/profile-save/main.py +52 -0
  35. package/builtin-skills/profile-save/skill.yaml +69 -0
  36. package/builtin-skills/schedule-add/_schedules_lib.py +303 -0
  37. package/builtin-skills/schedule-add/main.py +137 -0
  38. package/builtin-skills/schedule-add/skill.yaml +94 -0
  39. package/builtin-skills/schedule-list/_schedules_lib.py +303 -0
  40. package/builtin-skills/schedule-list/main.py +86 -0
  41. package/builtin-skills/schedule-list/skill.yaml +45 -0
  42. package/builtin-skills/schedule-remove/_schedules_lib.py +303 -0
  43. package/builtin-skills/schedule-remove/main.py +69 -0
  44. package/builtin-skills/schedule-remove/skill.yaml +49 -0
  45. package/builtin-skills/schedule-toggle/_schedules_lib.py +303 -0
  46. package/builtin-skills/schedule-toggle/main.py +78 -0
  47. package/builtin-skills/schedule-toggle/skill.yaml +61 -0
  48. package/builtin-skills/skills-disable/main.py +63 -0
  49. package/builtin-skills/skills-disable/skill.yaml +52 -0
  50. package/builtin-skills/skills-enable/main.py +62 -0
  51. package/builtin-skills/skills-enable/skill.yaml +51 -0
  52. package/builtin-skills/todo-add/main.py +68 -0
  53. package/builtin-skills/todo-add/skill.yaml +53 -0
  54. package/builtin-skills/todo-delete/main.py +65 -0
  55. package/builtin-skills/todo-delete/skill.yaml +47 -0
  56. package/builtin-skills/todo-done/main.py +75 -0
  57. package/builtin-skills/todo-done/skill.yaml +47 -0
  58. package/builtin-skills/todo-list/main.py +91 -0
  59. package/builtin-skills/todo-list/skill.yaml +48 -0
  60. package/builtin-skills/todo-tick/main.py +125 -0
  61. package/builtin-skills/todo-tick/skill.yaml +48 -0
  62. package/dist/builder/build-action-classifier.d.ts +18 -0
  63. package/dist/builder/build-action-classifier.js +142 -0
  64. package/dist/builder/build-commands.d.ts +19 -0
  65. package/dist/builder/build-commands.js +133 -0
  66. package/dist/builder/build-flow.d.ts +72 -0
  67. package/dist/builder/build-flow.js +416 -0
  68. package/dist/builder/builder-session.d.ts +117 -0
  69. package/dist/builder/builder-session.js +1129 -0
  70. package/dist/builder/conversation-router.d.ts +22 -0
  71. package/dist/builder/conversation-router.js +69 -0
  72. package/dist/builder/intent-runtime-store.d.ts +7 -0
  73. package/dist/builder/intent-runtime-store.js +60 -0
  74. package/dist/builder/progress-format.d.ts +7 -0
  75. package/dist/builder/progress-format.js +46 -0
  76. package/dist/cli/index.d.ts +2 -0
  77. package/dist/cli/index.js +2835 -0
  78. package/dist/cli/spinner.d.ts +30 -0
  79. package/dist/cli/spinner.js +164 -0
  80. package/dist/core/ai-provider.d.ts +75 -0
  81. package/dist/core/ai-provider.js +678 -0
  82. package/dist/core/builtin-skills.d.ts +27 -0
  83. package/dist/core/builtin-skills.js +120 -0
  84. package/dist/core/chat-engine.d.ts +70 -0
  85. package/dist/core/chat-engine.js +812 -0
  86. package/dist/core/config.d.ts +127 -0
  87. package/dist/core/config.js +1379 -0
  88. package/dist/core/daily-memory-promotion.d.ts +21 -0
  89. package/dist/core/daily-memory-promotion.js +422 -0
  90. package/dist/core/i18n.d.ts +23 -0
  91. package/dist/core/i18n.js +167 -0
  92. package/dist/core/info-lines.d.ts +5 -0
  93. package/dist/core/info-lines.js +39 -0
  94. package/dist/core/input-schema.d.ts +2 -0
  95. package/dist/core/input-schema.js +156 -0
  96. package/dist/core/intent-router.d.ts +27 -0
  97. package/dist/core/intent-router.js +160 -0
  98. package/dist/core/logger.d.ts +60 -0
  99. package/dist/core/logger.js +240 -0
  100. package/dist/core/memory.d.ts +10 -0
  101. package/dist/core/memory.js +72 -0
  102. package/dist/core/message-utils.d.ts +13 -0
  103. package/dist/core/message-utils.js +104 -0
  104. package/dist/core/notifier.d.ts +17 -0
  105. package/dist/core/notifier.js +424 -0
  106. package/dist/core/output-writer.d.ts +13 -0
  107. package/dist/core/output-writer.js +100 -0
  108. package/dist/core/plan-decision.d.ts +16 -0
  109. package/dist/core/plan-decision.js +88 -0
  110. package/dist/core/profile-memory.d.ts +17 -0
  111. package/dist/core/profile-memory.js +142 -0
  112. package/dist/core/runtime.d.ts +50 -0
  113. package/dist/core/runtime.js +187 -0
  114. package/dist/core/scheduler.d.ts +28 -0
  115. package/dist/core/scheduler.js +155 -0
  116. package/dist/core/secrets.d.ts +31 -0
  117. package/dist/core/secrets.js +214 -0
  118. package/dist/core/service.d.ts +35 -0
  119. package/dist/core/service.js +479 -0
  120. package/dist/core/skill-planner.d.ts +24 -0
  121. package/dist/core/skill-planner.js +100 -0
  122. package/dist/core/skill-registry.d.ts +98 -0
  123. package/dist/core/skill-registry.js +319 -0
  124. package/dist/core/skill-scaffold.d.ts +33 -0
  125. package/dist/core/skill-scaffold.js +256 -0
  126. package/dist/core/skill-settings.d.ts +11 -0
  127. package/dist/core/skill-settings.js +63 -0
  128. package/dist/core/transfer.d.ts +31 -0
  129. package/dist/core/transfer.js +270 -0
  130. package/dist/core/update-notifier.d.ts +2 -0
  131. package/dist/core/update-notifier.js +140 -0
  132. package/dist/discord/bot.d.ts +96 -0
  133. package/dist/discord/bot.js +2424 -0
  134. package/dist/runtimes/codex-app-server.d.ts +53 -0
  135. package/dist/runtimes/codex-app-server.js +305 -0
  136. package/dist/runtimes/python-runner.d.ts +7 -0
  137. package/dist/runtimes/python-runner.js +302 -0
  138. package/dist/runtimes/typescript-runner.d.ts +5 -0
  139. package/dist/runtimes/typescript-runner.js +172 -0
  140. package/dist/skills-sdk/types.d.ts +38 -0
  141. package/dist/skills-sdk/types.js +1 -0
  142. package/dist/telegram/bot.d.ts +94 -0
  143. package/dist/telegram/bot.js +1219 -0
  144. package/install.ps1 +132 -0
  145. package/install.sh +130 -0
  146. package/package.json +60 -0
  147. package/templates/skill-python/main.py +74 -0
  148. package/templates/skill-python/skill.yaml +48 -0
  149. package/templates/skill-typescript/main.ts +87 -0
  150. package/templates/skill-typescript/skill.yaml +42 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Terminal spinner used during long-running operations such as model calls
3
+ * and skill execution. Mimics the "<frame> <label> (Ns)" style seen in
4
+ * Claude Code and Codex CLI. Renders only on a real TTY where carriage
5
+ * return ('\r') overwrites work; in CI, KingCoding terminals, or when
6
+ * NO_SPINNER is set we fall back to a single status line so output stays
7
+ * clean.
8
+ */
9
+ export interface SpinnerOptions {
10
+ stream?: NodeJS.WriteStream;
11
+ forceEnabled?: boolean;
12
+ }
13
+ export declare class Spinner {
14
+ private readonly stream;
15
+ private readonly animated;
16
+ private readonly enabled;
17
+ private timer;
18
+ private frameIndex;
19
+ private label;
20
+ private startTime;
21
+ private staticPrinted;
22
+ constructor(options?: SpinnerOptions);
23
+ start(label: string): void;
24
+ update(label: string): void;
25
+ stop(): void;
26
+ /** Stop the spinner and emit a final status line on its own line. */
27
+ finish(message: string): void;
28
+ isActive(): boolean;
29
+ private render;
30
+ }
@@ -0,0 +1,164 @@
1
+ /**
2
+ * Terminal spinner used during long-running operations such as model calls
3
+ * and skill execution. Mimics the "<frame> <label> (Ns)" style seen in
4
+ * Claude Code and Codex CLI. Renders only on a real TTY where carriage
5
+ * return ('\r') overwrites work; in CI, KingCoding terminals, or when
6
+ * NO_SPINNER is set we fall back to a single status line so output stays
7
+ * clean.
8
+ */
9
+ const FRAMES = ["⠋", "⠙", "⠹", "⠸", "⠼", "⠴", "⠦", "⠧", "⠇", "⠏"];
10
+ const FRAME_INTERVAL_MS = 100;
11
+ const CLEAR_LINE = "\r\x1b[2K";
12
+ const BRAND_GREEN_ANSI = "38;2;24;160;104";
13
+ function detectAnimationDisabled() {
14
+ if (process.env.AGENT_SIN_NO_SPINNER === "1")
15
+ return true;
16
+ if (process.env.NO_SPINNER === "1")
17
+ return true;
18
+ if (process.env.CI && process.env.CI !== "0" && process.env.CI !== "false")
19
+ return true;
20
+ if (process.env.TERM === "dumb")
21
+ return true;
22
+ // KingCoding runs agent-sin inside its own terminal that doesn't honor '\r'
23
+ // overwrites — every spinner tick would render as a new line.
24
+ if (process.env.KINGCODING_RUNTIME_CHANNEL)
25
+ return true;
26
+ if ((process.env.APP_DATA_DIR || "").includes("KingCoding"))
27
+ return true;
28
+ return false;
29
+ }
30
+ export class Spinner {
31
+ stream;
32
+ animated;
33
+ enabled;
34
+ timer = null;
35
+ frameIndex = 0;
36
+ label = "";
37
+ startTime = 0;
38
+ staticPrinted = false;
39
+ constructor(options = {}) {
40
+ this.stream = options.stream || process.stderr;
41
+ const isTTY = this.stream.isTTY === true;
42
+ const animationDisabled = detectAnimationDisabled();
43
+ this.animated = options.forceEnabled ?? (isTTY && !animationDisabled);
44
+ this.enabled = this.animated || isTTY;
45
+ }
46
+ start(label) {
47
+ this.label = label;
48
+ this.startTime = Date.now();
49
+ this.frameIndex = 0;
50
+ this.staticPrinted = false;
51
+ if (this.animated) {
52
+ this.render();
53
+ this.timer = setInterval(() => {
54
+ this.frameIndex = (this.frameIndex + 1) % FRAMES.length;
55
+ this.render();
56
+ }, FRAME_INTERVAL_MS);
57
+ if (typeof this.timer.unref === "function") {
58
+ this.timer.unref();
59
+ }
60
+ return;
61
+ }
62
+ if (this.enabled) {
63
+ this.stream.write(`${label}…\n`);
64
+ this.staticPrinted = true;
65
+ }
66
+ }
67
+ update(label) {
68
+ if (this.label === label) {
69
+ return;
70
+ }
71
+ this.label = label;
72
+ if (this.animated && this.timer) {
73
+ this.render();
74
+ }
75
+ // In static (non-animated) mode we deliberately drop progress updates
76
+ // to keep the output to a single status line per operation.
77
+ }
78
+ stop() {
79
+ if (this.timer) {
80
+ clearInterval(this.timer);
81
+ this.timer = null;
82
+ }
83
+ if (this.animated) {
84
+ this.stream.write(CLEAR_LINE);
85
+ }
86
+ this.staticPrinted = false;
87
+ }
88
+ /** Stop the spinner and emit a final status line on its own line. */
89
+ finish(message) {
90
+ this.stop();
91
+ if (this.enabled && message) {
92
+ this.stream.write(`${message}\n`);
93
+ }
94
+ }
95
+ isActive() {
96
+ return this.timer !== null || this.staticPrinted;
97
+ }
98
+ render() {
99
+ const elapsed = Math.floor((Date.now() - this.startTime) / 1000);
100
+ const frame = FRAMES[this.frameIndex];
101
+ const useColor = this.enabled && !process.env.NO_COLOR;
102
+ const paint = (codes, text) => useColor ? `\x1b[${codes}m${text}\x1b[0m` : text;
103
+ const elapsedText = ` (${elapsed}s)`;
104
+ // Truncate the label so the rendered line never exceeds the terminal
105
+ // width. Without this, long progress labels (e.g. streamed thinking text)
106
+ // wrap to the next line and the spinner's '\r' overwrite stops working,
107
+ // leaving every frame stacked on screen.
108
+ const columns = this.stream.columns || 80;
109
+ const reserved = 2 /* frame + space */ + elapsedText.length + 1 /* safety */;
110
+ const maxDisplayWidth = Math.max(10, columns - reserved);
111
+ const labelText = truncateToDisplayWidth(this.label, maxDisplayWidth);
112
+ const head = paint(BRAND_GREEN_ANSI, frame);
113
+ const body = paint("90", `${labelText}${elapsedText}`);
114
+ this.stream.write(`${CLEAR_LINE}${head} ${body}`);
115
+ }
116
+ }
117
+ function charDisplayWidth(codePoint) {
118
+ // Treat full-width / wide code points (CJK, kana, full-width forms,
119
+ // emoji) as 2 columns; everything else as 1. Heuristic ranges that
120
+ // cover the common cases without pulling in a wcwidth library.
121
+ if (codePoint >= 0x1100 && codePoint <= 0x115f)
122
+ return 2;
123
+ if (codePoint >= 0x2e80 && codePoint <= 0x303e)
124
+ return 2;
125
+ if (codePoint >= 0x3041 && codePoint <= 0x33ff)
126
+ return 2;
127
+ if (codePoint >= 0x3400 && codePoint <= 0x4dbf)
128
+ return 2;
129
+ if (codePoint >= 0x4e00 && codePoint <= 0x9fff)
130
+ return 2;
131
+ if (codePoint >= 0xa000 && codePoint <= 0xa4cf)
132
+ return 2;
133
+ if (codePoint >= 0xac00 && codePoint <= 0xd7a3)
134
+ return 2;
135
+ if (codePoint >= 0xf900 && codePoint <= 0xfaff)
136
+ return 2;
137
+ if (codePoint >= 0xfe30 && codePoint <= 0xfe4f)
138
+ return 2;
139
+ if (codePoint >= 0xff00 && codePoint <= 0xff60)
140
+ return 2;
141
+ if (codePoint >= 0xffe0 && codePoint <= 0xffe6)
142
+ return 2;
143
+ if (codePoint >= 0x1f300 && codePoint <= 0x1faff)
144
+ return 2;
145
+ if (codePoint >= 0x20000 && codePoint <= 0x3fffd)
146
+ return 2;
147
+ return 1;
148
+ }
149
+ function truncateToDisplayWidth(text, maxWidth) {
150
+ if (maxWidth <= 0)
151
+ return "";
152
+ let width = 0;
153
+ let result = "";
154
+ for (const char of text) {
155
+ const codePoint = char.codePointAt(0) ?? 0;
156
+ const w = charDisplayWidth(codePoint);
157
+ if (width + w > maxWidth - 1) {
158
+ return `${result}…`;
159
+ }
160
+ width += w;
161
+ result += char;
162
+ }
163
+ return result;
164
+ }
@@ -0,0 +1,75 @@
1
+ import { type AppConfig, type ModelConfig } from "./config.js";
2
+ export type AiRole = "system" | "user" | "assistant" | "tool";
3
+ export type AiMessageContent = string | AiContentPart[];
4
+ export type AiContentPart = AiTextPart | AiImagePart;
5
+ export interface AiTextPart {
6
+ type: "text";
7
+ text: string;
8
+ }
9
+ export interface AiImagePart {
10
+ type: "image";
11
+ image_url: string;
12
+ mime_type?: string;
13
+ filename?: string;
14
+ }
15
+ export interface AiMessage {
16
+ role: AiRole;
17
+ content: AiMessageContent;
18
+ }
19
+ export type AiProgressEvent = {
20
+ kind: "thinking";
21
+ text?: string;
22
+ } | {
23
+ kind: "tool";
24
+ name?: string;
25
+ text?: string;
26
+ } | {
27
+ kind: "message";
28
+ text?: string;
29
+ } | {
30
+ kind: "stderr";
31
+ text: string;
32
+ } | {
33
+ kind: "info";
34
+ text: string;
35
+ };
36
+ export type AiProgressHandler = (event: AiProgressEvent) => void;
37
+ export type AiPermissionMode = "default" | "bypass";
38
+ export type AiRoleKind = "chat" | "builder";
39
+ export interface AiProviderRequest {
40
+ model_id: string;
41
+ messages: AiMessage[];
42
+ system?: string;
43
+ temperature?: number;
44
+ onProgress?: AiProgressHandler;
45
+ permission_mode?: AiPermissionMode;
46
+ effort?: "low" | "medium" | "high" | "xhigh";
47
+ cwd?: string;
48
+ role?: AiRoleKind;
49
+ }
50
+ export interface AiProviderResponse {
51
+ text: string;
52
+ model_id: string;
53
+ provider: string;
54
+ }
55
+ export declare class AiProviderError extends Error {
56
+ readonly model_id: string;
57
+ readonly provider: string;
58
+ constructor(message: string, model_id: string, provider: string);
59
+ }
60
+ export type AiProviderFn = (config: AppConfig, request: AiProviderRequest) => Promise<AiProviderResponse>;
61
+ export declare function setAiProviderOverride(fn: AiProviderFn | null): void;
62
+ export declare function getAiProvider(): AiProviderFn;
63
+ export declare function resolveModelId(modelId: string, models: ModelConfig): string;
64
+ export declare function runChatCompletion(config: AppConfig, request: AiProviderRequest): Promise<AiProviderResponse>;
65
+ export type ModelEntry = ModelConfig["models"][string];
66
+ export declare function openAIModelAcceptsTemperature(model: string | undefined): boolean;
67
+ export declare function buildOpenAIChatBody(request: AiProviderRequest, entry: ModelEntry): Record<string, unknown>;
68
+ export declare function formatProviderApiError(args: {
69
+ provider: "openai" | "gemini" | "anthropic";
70
+ modelEntryId: string;
71
+ modelName: string | undefined;
72
+ status: number;
73
+ rawBody: string;
74
+ }): string;
75
+ export declare function messageContentToText(content: AiMessageContent): string;