@nomadamas/k-skill 0.9.1 → 0.10.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 (58) hide show
  1. package/bin/k-skill.js +64 -43
  2. package/package.json +2 -2
  3. package/skills/biz-health-check/instruction.md +2 -0
  4. package/skills/company-analysis/instruction.md +68 -0
  5. package/skills/company-analysis/references/source-contract.md +75 -0
  6. package/skills/company-analysis/scripts/dart-rows.js +52 -0
  7. package/skills/company-analysis/scripts/dart-rows.ts +48 -0
  8. package/skills/company-analysis/scripts/evidence.js +567 -0
  9. package/skills/company-analysis/scripts/evidence.ts +520 -0
  10. package/skills/company-analysis/scripts/fetch-public.js +85 -0
  11. package/skills/company-analysis/scripts/fetch-public.ts +75 -0
  12. package/skills/company-analysis/skill.json +6 -0
  13. package/skills/express-bus-booking/scripts/kobus_express_booking.py +46 -18
  14. package/skills/foresttrip-vacancy/scripts/run_foresttrip_vacancy.py +53 -3
  15. package/skills/g2b-order-plan-search/instruction.md +17 -0
  16. package/skills/g2b-sanctioned-supplier/instruction.md +10 -1
  17. package/skills/g2b-sanctioned-supplier/scripts/g2b_sanctioned_supplier.py +8 -4
  18. package/skills/g2b-sanctioned-supplier/scripts/test_g2b_sanctioned_supplier.py +19 -0
  19. package/skills/government-bond-analysis/instruction.md +216 -0
  20. package/skills/government-bond-analysis/references/methodology.md +63 -0
  21. package/skills/government-bond-analysis/scripts/cli.mjs +268 -0
  22. package/skills/government-bond-analysis/scripts/collect.mjs +171 -0
  23. package/skills/government-bond-analysis/scripts/core.mjs +224 -0
  24. package/skills/government-bond-analysis/scripts/dual.mjs +178 -0
  25. package/skills/government-bond-analysis/scripts/harness.mjs +406 -0
  26. package/skills/government-bond-analysis/scripts/modes.mjs +136 -0
  27. package/skills/government-bond-analysis/scripts/news.mjs +113 -0
  28. package/skills/government-bond-analysis/scripts/render.mjs +120 -0
  29. package/skills/government-bond-analysis/scripts/schedule.mjs +96 -0
  30. package/skills/government-bond-analysis/scripts/ust.mjs +204 -0
  31. package/skills/government-bond-analysis/skill.json +8 -0
  32. package/skills/korean-bond-search/instruction.md +122 -0
  33. package/skills/korean-bond-search/references/fields.md +48 -0
  34. package/skills/korean-bond-search/references/source-notes.md +11 -0
  35. package/skills/korean-bond-search/scripts/bond_search.py +906 -0
  36. package/skills/korean-bond-search/skill.json +9 -0
  37. package/skills/market-event-impact/instruction.md +150 -0
  38. package/skills/market-event-impact/references/event-taxonomy.md +74 -0
  39. package/skills/market-event-impact/references/methodology.md +98 -0
  40. package/skills/market-event-impact/references/research-contract.md +120 -0
  41. package/skills/market-event-impact/references/source-priority.md +25 -0
  42. package/skills/market-event-impact/scripts/adapters.py +32 -0
  43. package/skills/market-event-impact/scripts/asset_selector.py +120 -0
  44. package/skills/market-event-impact/scripts/calendars.py +179 -0
  45. package/skills/market-event-impact/scripts/event_resolver.py +260 -0
  46. package/skills/market-event-impact/scripts/event_study.py +171 -0
  47. package/skills/market-event-impact/scripts/market_data.py +204 -0
  48. package/skills/market-event-impact/scripts/market_event.py +1065 -0
  49. package/skills/market-event-impact/scripts/research.py +389 -0
  50. package/skills/market-event-impact/skill.json +9 -0
  51. package/skills/multi-asset-morning-briefing/instruction.md +117 -0
  52. package/skills/multi-asset-morning-briefing/references/format-rules.md +236 -0
  53. package/skills/multi-asset-morning-briefing/scripts/market_data.py +1003 -0
  54. package/skills/multi-asset-morning-briefing/skill.json +9 -0
  55. package/skills/store-longevity-radar/scripts/__pycache__/store_longevity_download.cpython-312.pyc +0 -0
  56. package/src/analytics-policy.json +18 -0
  57. package/src/analytics.js +106 -0
  58. package/src/metrics.js +49 -0
@@ -0,0 +1,9 @@
1
+ {
2
+ "name": "multi-asset-morning-briefing",
3
+ "description": "글로벌 주식·금리·외환·원자재·변동성과 한국시장 전달 경로를 연결해 근거 링크가 있는 7개 섹션의 멀티에셋 모닝 브리핑을 작성한다. Use when the user asks 모닝 브리핑, Morning Call, 오버나이트 시황, 데일리 마켓 브리핑 또는 기존 브리핑 검수. Not for 실시간 호가, 국내 개별 종목 단독 조회(korean-stock-search), 투자 권유·매매 판단.",
4
+ "profiles": [
5
+ "lookup",
6
+ "browser"
7
+ ],
8
+ "frontmatter": "name: multi-asset-morning-briefing\ndescription: 글로벌 주식·금리·외환·원자재·변동성과 한국시장 전달 경로를 연결해 근거 링크가 있는 7개 섹션의 멀티에셋 모닝 브리핑을 작성한다. Use when the user asks 모닝 브리핑, Morning Call, 오버나이트 시황, 데일리 마켓 브리핑 또는 기존 브리핑 검수. Not for 실시간 호가, 국내 개별 종목 단독 조회(korean-stock-search), 투자 권유·매매 판단.\nlicense: MIT\nmetadata:\n category: finance\n locale: ko-KR\n phase: v1"
9
+ }
@@ -0,0 +1,18 @@
1
+ {
2
+ "purpose": "usage_statistics_only",
3
+ "event": "cli_invocation",
4
+ "collected_properties": [
5
+ "command",
6
+ "skill_name",
7
+ "cli_version",
8
+ "runtime_mode",
9
+ "success",
10
+ "analytics_schema_version"
11
+ ],
12
+ "excluded_data": [
13
+ "command_arguments",
14
+ "command_input",
15
+ "file_contents"
16
+ ],
17
+ "opt_out_environment_variable": "KSKILL_ANALYTICS_DISABLED"
18
+ }
@@ -0,0 +1,106 @@
1
+ "use strict";
2
+
3
+ const crypto = require("node:crypto");
4
+ const fs = require("node:fs");
5
+ const os = require("node:os");
6
+ const path = require("node:path");
7
+ const { version: cliVersion } = require("../package.json");
8
+ const policy = require("./analytics-policy.json");
9
+
10
+ const DEFAULT_HOST = "https://us.i.posthog.com";
11
+ const DEFAULT_PROJECT_API_KEY =
12
+ "phc_xlJYWKplsT2UNHng9eDULTGddlq0RoTuE8Dh64nrpmL";
13
+ const ANALYTICS_SCHEMA_VERSION = 1;
14
+ const DISABLED_VALUES = new Set(["1", "true", "yes", "on"]);
15
+
16
+ function isDisabled(env) {
17
+ return DISABLED_VALUES.has(String(env.KSKILL_ANALYTICS_DISABLED || "").toLowerCase());
18
+ }
19
+
20
+ function analyticsIdPath(env) {
21
+ return (
22
+ env.KSKILL_ANALYTICS_ID_FILE ||
23
+ path.join(env.KSKILL_CONFIG_DIR || path.join(os.homedir(), ".config", "k-skill"), "analytics-id")
24
+ );
25
+ }
26
+
27
+ function readOrCreateAnalyticsId(env, randomUUID = crypto.randomUUID) {
28
+ if (env.KSKILL_ANALYTICS_ID) return env.KSKILL_ANALYTICS_ID;
29
+
30
+ const idPath = analyticsIdPath(env);
31
+ try {
32
+ const existing = fs.readFileSync(idPath, "utf8").trim();
33
+ if (existing) return existing;
34
+ } catch (error) {
35
+ if (error.code !== "ENOENT") return randomUUID();
36
+ }
37
+
38
+ const generated = randomUUID();
39
+ try {
40
+ fs.mkdirSync(path.dirname(idPath), { recursive: true, mode: 0o700 });
41
+ fs.writeFileSync(idPath, `${generated}\n`, { encoding: "utf8", mode: 0o600 });
42
+ } catch {
43
+ // Analytics must never make the CLI command fail.
44
+ }
45
+ return generated;
46
+ }
47
+
48
+ function analyticsConfig(env = process.env) {
49
+ if (isDisabled(env)) return null;
50
+
51
+ return {
52
+ apiKey: env.POSTHOG_API_KEY || DEFAULT_PROJECT_API_KEY,
53
+ host: (env.POSTHOG_HOST || DEFAULT_HOST).replace(/\/+$/, ""),
54
+ distinctId: readOrCreateAnalyticsId(env),
55
+ };
56
+ }
57
+
58
+ function buildInvocationEvent({ command, skillName, runtimeMode, success }) {
59
+ return {
60
+ event: policy.event,
61
+ properties: {
62
+ command: command || null,
63
+ skill_name: skillName || null,
64
+ cli_version: cliVersion,
65
+ runtime_mode: runtimeMode,
66
+ success: Boolean(success),
67
+ analytics_schema_version: ANALYTICS_SCHEMA_VERSION,
68
+ $process_person_profile: false,
69
+ disable_geoip: true,
70
+ },
71
+ };
72
+ }
73
+
74
+ async function captureInvocation(details, env = process.env, fetchImpl = fetch) {
75
+ const config = analyticsConfig(env);
76
+ if (!config) return false;
77
+
78
+ const event = buildInvocationEvent(details);
79
+ const payload = JSON.stringify({
80
+ api_key: config.apiKey,
81
+ distinct_id: config.distinctId,
82
+ event: event.event,
83
+ properties: event.properties,
84
+ });
85
+
86
+ try {
87
+ const response = await fetchImpl(`${config.host}/i/v0/e/`, {
88
+ method: "POST",
89
+ headers: { "content-type": "application/json" },
90
+ body: payload,
91
+ signal: AbortSignal.timeout(1500),
92
+ });
93
+ return response.ok;
94
+ } catch {
95
+ return false;
96
+ }
97
+ }
98
+
99
+ module.exports = {
100
+ ANALYTICS_SCHEMA_VERSION,
101
+ DEFAULT_PROJECT_API_KEY,
102
+ analyticsConfig,
103
+ buildInvocationEvent,
104
+ captureInvocation,
105
+ readOrCreateAnalyticsId,
106
+ };
package/src/metrics.js ADDED
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+
3
+ function inWindow(timestamp, start, end) {
4
+ const value = new Date(timestamp).getTime();
5
+ return Number.isFinite(value) && value >= start && value < end;
6
+ }
7
+
8
+ function uniqueIds(events) {
9
+ return new Set(events.map((event) => event.distinct_id).filter(Boolean)).size;
10
+ }
11
+
12
+ function deriveUsageMetrics(events, end = Date.now()) {
13
+ const windows = {
14
+ daily: 24 * 60 * 60 * 1000,
15
+ weekly: 7 * 24 * 60 * 60 * 1000,
16
+ monthly: 30 * 24 * 60 * 60 * 1000,
17
+ };
18
+
19
+ const metrics = {};
20
+ for (const [name, duration] of Object.entries(windows)) {
21
+ const selected = events.filter((event) =>
22
+ inWindow(event.timestamp, end - duration, end),
23
+ );
24
+ const uniqueUsers = uniqueIds(selected);
25
+ metrics[name] = {
26
+ calls: selected.length,
27
+ uniqueUsers,
28
+ executionsPerUniqueUser: uniqueUsers ? selected.length / uniqueUsers : 0,
29
+ };
30
+ }
31
+
32
+ const recentIds = new Set(
33
+ events
34
+ .filter((event) => inWindow(event.timestamp, end - windows.weekly, end))
35
+ .map((event) => event.distinct_id)
36
+ .filter(Boolean),
37
+ );
38
+ const priorIds = new Set(
39
+ events
40
+ .filter((event) => inWindow(event.timestamp, end - 2 * windows.weekly, end - windows.weekly))
41
+ .map((event) => event.distinct_id)
42
+ .filter(Boolean),
43
+ );
44
+ metrics.recurrentUsers = [...recentIds].filter((id) => priorIds.has(id)).length;
45
+
46
+ return metrics;
47
+ }
48
+
49
+ module.exports = { deriveUsageMetrics };