terse-cli 0.1.17 → 0.1.18

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 (93) hide show
  1. package/README.md +4 -4
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +6 -9
  4. package/dist/api.js.map +1 -1
  5. package/dist/assertProjectRoot.d.ts.map +1 -1
  6. package/dist/assertProjectRoot.js +1 -1
  7. package/dist/assertProjectRoot.js.map +1 -1
  8. package/dist/auth.d.ts.map +1 -1
  9. package/dist/auth.js +4 -4
  10. package/dist/auth.js.map +1 -1
  11. package/dist/deploy.d.ts.map +1 -1
  12. package/dist/deploy.js +8 -11
  13. package/dist/deploy.js.map +1 -1
  14. package/dist/generate.d.ts.map +1 -1
  15. package/dist/generate.js +47 -22
  16. package/dist/generate.js.map +1 -1
  17. package/dist/index.js +2 -5
  18. package/dist/index.js.map +1 -1
  19. package/dist/init.d.ts.map +1 -1
  20. package/dist/init.js +3 -3
  21. package/dist/init.js.map +1 -1
  22. package/dist/integrate.d.ts.map +1 -1
  23. package/dist/integrate.js +8 -12
  24. package/dist/integrate.js.map +1 -1
  25. package/dist/integrationApi.d.ts +2 -2
  26. package/dist/integrationApi.d.ts.map +1 -1
  27. package/dist/integrationApi.js.map +1 -1
  28. package/dist/loadJob.d.ts.map +1 -1
  29. package/dist/loadJob.js +2 -2
  30. package/dist/loadJob.js.map +1 -1
  31. package/dist/providers/LanguageProvider.d.ts +2 -2
  32. package/dist/providers/LanguageProvider.d.ts.map +1 -1
  33. package/dist/providers/codegenTypes.d.ts +1 -12
  34. package/dist/providers/codegenTypes.d.ts.map +1 -1
  35. package/dist/providers/python/PythonProvider.d.ts +1 -1
  36. package/dist/providers/python/PythonProvider.d.ts.map +1 -1
  37. package/dist/providers/python/PythonProvider.js +19 -26
  38. package/dist/providers/python/PythonProvider.js.map +1 -1
  39. package/dist/providers/python/preparePythonCodegenData.d.ts +16 -0
  40. package/dist/providers/python/preparePythonCodegenData.d.ts.map +1 -1
  41. package/dist/providers/python/preparePythonCodegenData.js +76 -55
  42. package/dist/providers/python/preparePythonCodegenData.js.map +1 -1
  43. package/dist/providers/python/pythonTemplateEngine.d.ts.map +1 -1
  44. package/dist/providers/python/pythonTemplateEngine.js +2 -2
  45. package/dist/providers/python/pythonTemplateEngine.js.map +1 -1
  46. package/dist/providers/resolveProvider.d.ts.map +1 -1
  47. package/dist/providers/resolveProvider.js +1 -1
  48. package/dist/providers/resolveProvider.js.map +1 -1
  49. package/dist/providers/shared/sessionStream.d.ts +1 -1
  50. package/dist/providers/shared/sessionStream.d.ts.map +1 -1
  51. package/dist/providers/shared/sessionStream.js +8 -10
  52. package/dist/providers/shared/sessionStream.js.map +1 -1
  53. package/dist/providers/shared/shellUtils.d.ts.map +1 -1
  54. package/dist/providers/shared/shellUtils.js +3 -4
  55. package/dist/providers/shared/shellUtils.js.map +1 -1
  56. package/dist/providers/templateUtils.d.ts.map +1 -1
  57. package/dist/providers/templateUtils.js +1 -1
  58. package/dist/providers/templateUtils.js.map +1 -1
  59. package/dist/providers/typescript/TypeScriptProvider.d.ts +1 -1
  60. package/dist/providers/typescript/TypeScriptProvider.d.ts.map +1 -1
  61. package/dist/providers/typescript/TypeScriptProvider.js +8 -10
  62. package/dist/providers/typescript/TypeScriptProvider.js.map +1 -1
  63. package/dist/providers/typescript/prepareCodegenData.d.ts +1 -2
  64. package/dist/providers/typescript/prepareCodegenData.d.ts.map +1 -1
  65. package/dist/providers/typescript/prepareCodegenData.js +168 -251
  66. package/dist/providers/typescript/prepareCodegenData.js.map +1 -1
  67. package/dist/providers/typescript/templateEngine.d.ts.map +1 -1
  68. package/dist/providers/typescript/templateEngine.js +2 -2
  69. package/dist/providers/typescript/templateEngine.js.map +1 -1
  70. package/dist/run.d.ts.map +1 -1
  71. package/dist/run.js +2 -2
  72. package/dist/run.js.map +1 -1
  73. package/dist/shared/ToolDisplayUtils.d.ts.map +1 -1
  74. package/dist/shared/ToolDisplayUtils.js +13 -1
  75. package/dist/shared/ToolDisplayUtils.js.map +1 -1
  76. package/dist/shared/types.d.ts +13 -0
  77. package/dist/shared/types.d.ts.map +1 -1
  78. package/dist/test.d.ts.map +1 -1
  79. package/dist/test.js +7 -7
  80. package/dist/test.js.map +1 -1
  81. package/dist/util.d.ts +1 -1
  82. package/dist/util.d.ts.map +1 -1
  83. package/dist/util.js.map +1 -1
  84. package/package.json +12 -8
  85. package/templates/python/codegen/generated.hbs +1 -0
  86. package/templates/python/codegen/partials/attio-section.hbs +4 -5
  87. package/templates/python/codegen/partials/attio-upsert-record-method.hbs +3 -3
  88. package/templates/python/codegen/partials/deterministic-tools-section.hbs +115 -1
  89. package/templates/python/codegen/partials/slack-section.hbs +178 -0
  90. package/templates/python/codegen/partials/tool-name-types.hbs +3 -0
  91. package/templates/python/init/README.md.hbs +5 -3
  92. package/templates/typescript/codegen/partials/slack-section.hbs +5 -6
  93. package/templates/typescript/codegen/partials/tools-section.hbs +2 -1
@@ -0,0 +1,178 @@
1
+ {{#if slack}}
2
+
3
+
4
+ # === Slack ===
5
+
6
+
7
+ class SlackChannel(BaseModel):
8
+ model_config = ConfigDict(frozen=True)
9
+ channel_id: str
10
+ name: str
11
+ {{#if slack.channels.length}}
12
+ {{#each slack.channels}}
13
+ {{staticName}}: ClassVar["SlackChannel"]
14
+ {{/each}}
15
+
16
+ {{#each slack.channels}}
17
+ SlackChannel.{{staticName}} = SlackChannel(channel_id={{{channelIdRepr}}}, name={{{nameRepr}}})
18
+ {{/each}}
19
+ {{/if}}
20
+
21
+
22
+ class Slack:
23
+ @staticmethod
24
+ def on_message(channel: SlackChannel, *, user_ids: Sequence[str] | None = None) -> TriggerConfig:
25
+ return TriggerConfig(
26
+ integration_id={{{slack.instanceIdRepr}}},
27
+ integration_type='slack',
28
+ event_type='message',
29
+ config_type='slack',
30
+ config=_compact_dict(
31
+ channelId=channel.channel_id,
32
+ channelName=channel.name,
33
+ listenToUserDms=False,
34
+ userIds=list(user_ids) if user_ids is not None else None,
35
+ eventTypes=['message'],
36
+ ),
37
+ )
38
+
39
+ @staticmethod
40
+ def on_dm(*, user_ids: Sequence[str] | None = None) -> TriggerConfig:
41
+ return TriggerConfig(
42
+ integration_id={{{slack.instanceIdRepr}}},
43
+ integration_type='slack',
44
+ event_type='message',
45
+ config_type='slack',
46
+ config=_compact_dict(
47
+ listenToUserDms=True,
48
+ userIds=list(user_ids) if user_ids is not None else None,
49
+ eventTypes=['message'],
50
+ ),
51
+ )
52
+
53
+ @staticmethod
54
+ def trigger(
55
+ *,
56
+ channel: SlackChannel | None = None,
57
+ listen_to_user_dms: bool | None = None,
58
+ user_ids: Sequence[str] | None = None,
59
+ event_types: Sequence[SlackEventType] | None = None,
60
+ ) -> TriggerConfig:
61
+ return TriggerConfig(
62
+ integration_id={{{slack.instanceIdRepr}}},
63
+ integration_type='slack',
64
+ config_type='slack',
65
+ config=_compact_dict(
66
+ channelId=channel.channel_id if channel is not None else None,
67
+ channelName=channel.name if channel is not None else None,
68
+ listenToUserDms=listen_to_user_dms,
69
+ userIds=list(user_ids) if user_ids is not None else None,
70
+ eventTypes=list(event_types) if event_types is not None else None,
71
+ ),
72
+ )
73
+
74
+ @staticmethod
75
+ def skill(
76
+ *,
77
+ channel: SlackChannel | None = None,
78
+ user_ids: Sequence[str] | None = None,
79
+ user_names: Sequence[str] | None = None,
80
+ listen_to_user_dms: bool | None = None,
81
+ ) -> SkillConfig[{{slack.skillToolType}}]:
82
+ return SkillConfig(
83
+ integration_id={{{slack.instanceIdRepr}}},
84
+ integration_type='slack',
85
+ config_type='slack_output',
86
+ config=_compact_dict(
87
+ channelId=channel.channel_id if channel is not None else None,
88
+ channelName=channel.name if channel is not None else None,
89
+ userIds=list(user_ids) if user_ids is not None else None,
90
+ userNames=list(user_names) if user_names is not None else None,
91
+ listenToUserDms=listen_to_user_dms,
92
+ ),
93
+ )
94
+ {{else}}
95
+
96
+
97
+ # === Slack ===
98
+
99
+
100
+ class SlackChannel:
101
+ def __init__(self, channel_id: str, name: str) -> None:
102
+ self.channel_id = channel_id
103
+ self.name = name
104
+
105
+
106
+ class Slack:
107
+ @staticmethod
108
+ def on_message(channel: SlackChannel, *, user_ids: list[str] | None = None) -> TriggerConfig:
109
+ return TriggerConfig(
110
+ integration_id='slack_placeholder',
111
+ integration_type='slack',
112
+ event_type='message',
113
+ config_type='slack',
114
+ config=_compact_dict(
115
+ channelId=channel.channel_id,
116
+ channelName=channel.name,
117
+ listenToUserDms=False,
118
+ userIds=list(user_ids) if user_ids is not None else None,
119
+ eventTypes=['message'],
120
+ ),
121
+ )
122
+
123
+ @staticmethod
124
+ def on_dm(*, user_ids: list[str] | None = None) -> TriggerConfig:
125
+ return TriggerConfig(
126
+ integration_id='slack_placeholder',
127
+ integration_type='slack',
128
+ event_type='message',
129
+ config_type='slack',
130
+ config=_compact_dict(
131
+ listenToUserDms=True,
132
+ userIds=list(user_ids) if user_ids is not None else None,
133
+ eventTypes=['message'],
134
+ ),
135
+ )
136
+
137
+ @staticmethod
138
+ def trigger(
139
+ *,
140
+ channel: SlackChannel | None = None,
141
+ listen_to_user_dms: bool | None = None,
142
+ user_ids: list[str] | None = None,
143
+ event_types: list[str] | None = None,
144
+ ) -> TriggerConfig:
145
+ return TriggerConfig(
146
+ integration_id='slack_placeholder',
147
+ integration_type='slack',
148
+ config_type='slack',
149
+ config=_compact_dict(
150
+ channelId=channel.channel_id if channel is not None else None,
151
+ channelName=channel.name if channel is not None else None,
152
+ listenToUserDms=listen_to_user_dms,
153
+ userIds=list(user_ids) if user_ids is not None else None,
154
+ eventTypes=list(event_types) if event_types is not None else None,
155
+ ),
156
+ )
157
+
158
+ @staticmethod
159
+ def skill(
160
+ *,
161
+ channel: SlackChannel | None = None,
162
+ user_ids: list[str] | None = None,
163
+ user_names: list[str] | None = None,
164
+ listen_to_user_dms: bool | None = None,
165
+ ) -> SkillConfig[str]:
166
+ return SkillConfig(
167
+ integration_id='slack_placeholder',
168
+ integration_type='slack',
169
+ config_type='slack_output',
170
+ config=_compact_dict(
171
+ channelId=channel.channel_id if channel is not None else None,
172
+ channelName=channel.name if channel is not None else None,
173
+ userIds=list(user_ids) if user_ids is not None else None,
174
+ userNames=list(user_names) if user_names is not None else None,
175
+ listenToUserDms=listen_to_user_dms,
176
+ ),
177
+ )
178
+ {{/if}}
@@ -6,6 +6,9 @@
6
6
  {{#if attioToolNamesLiteral}}
7
7
  AttioToolNames = Literal[{{{attioToolNamesLiteral}}}]
8
8
  {{/if}}
9
+ {{#if slackToolNamesLiteral}}
10
+ SlackToolNames = Literal[{{{slackToolNamesLiteral}}}]
11
+ {{/if}}
9
12
  {{#if snowflakeToolNamesLiteral}}
10
13
  SnowflakeToolNames = Literal[{{{snowflakeToolNamesLiteral}}}]
11
14
  {{/if}}
@@ -27,12 +27,14 @@ Edit `src/main.py` to register jobs with `@app.job(...)`.
27
27
 
28
28
  The starter scaffold registers `Attio.skill()` and `Snowflake.skill()` by default.
29
29
 
30
- After you connect Attio or Snowflake in Terse, rerun `terse generate` to refresh `src/terse_generated.py` with the real integration IDs and deterministic tool wrappers.
30
+ After you connect Attio, Slack, or Snowflake in Terse, rerun `terse generate` to refresh `src/terse_generated.py` with the real integration IDs, generated resources, and deterministic tool wrappers.
31
31
 
32
- Import helpers like `Attio`, `AttioObject`, `Schedule`, `Snowflake`, and `TerseAgent` from `terse_generated`.
32
+ Import helpers like `Attio`, `AttioObject`, `Schedule`, `Slack`, `SlackChannel`, `Snowflake`, and `TerseAgent` from `terse_generated`.
33
33
 
34
- If a job registers `skills=[Snowflake.skill()]`, it can call deterministic wrappers like:
34
+ If a job includes the integration in `triggers=` or `skills=`, it can call deterministic wrappers like:
35
35
 
36
36
  ```python
37
37
  agent.tools.snowflake.execute_query(query="select 1")
38
38
  ```
39
+
40
+ Use `agent.tools.slack.*` for direct deterministic Slack calls. Use `skills=[Slack.skill(...)]` when you want Slack to be visible to the model during `run()` or `run_and_wait()`.
@@ -4,20 +4,19 @@
4
4
 
5
5
  export const Slack = {
6
6
  /** Trigger on any message in a channel */
7
- onMessage(opts: { channel: SlackChannel; userIds?: string[] }): SlackConfig {
7
+ onMessage(opts: { channel: SlackChannel; userIds?: string[] }): TypedTrigger<SlackMessageEvent> {
8
8
  return new SlackConfig("{{escape id}}", opts.channel.channelId, opts.channel.name, false, opts.userIds, [SlackEventType.MESSAGE])
9
9
  },
10
10
  /** Trigger on direct messages to the bot */
11
- onDm(opts?: { userIds?: string[] }): SlackConfig {
11
+ onDm(opts?: { userIds?: string[] }): TypedTrigger<SlackMessageEvent> {
12
12
  return new SlackConfig("{{escape id}}", undefined, undefined, true, opts?.userIds, [SlackEventType.MESSAGE])
13
13
  },
14
14
  /** Trigger on all Slack events (messages + DMs) for a channel */
15
- trigger(opts?: { channel?: SlackChannel; listenToUserDms?: boolean; userIds?: string[]; eventTypes?: SlackEventType[] }): SlackConfig {
15
+ trigger(opts?: { channel?: SlackChannel; listenToUserDms?: boolean; userIds?: string[]; eventTypes?: SlackEventType[] }): TypedTrigger<SlackMessageEvent> {
16
16
  return new SlackConfig("{{escape id}}", opts?.channel?.channelId, opts?.channel?.name, opts?.listenToUserDms, opts?.userIds, opts?.eventTypes)
17
17
  },
18
18
  /** Use in `skills[]` */
19
- skill(opts?: { channel?: SlackChannel; userIds?: string[]; userNames?: string[]; listenToUserDms?: boolean }): TypedSkill<{{{skillToolType}}}> {
20
- return new SlackOutputConfig("{{escape id}}", opts?.channel?.channelId, opts?.channel?.name, opts?.userIds, opts?.userNames, opts?.listenToUserDms) as TypedSkill<{{{skillToolType}}}>
19
+ skill(opts: { channel: SlackChannel; userIds?: string[]; userNames?: string[]; listenToUserDms?: boolean }): TypedSkill<{{{skillToolType}}}> {
20
+ return new SlackOutputConfig("{{escape id}}", opts.channel.channelId ?? null, opts.channel.name ?? null, opts.userIds ?? null, opts.userNames ?? null, opts.listenToUserDms)
21
21
  },
22
22
  }
23
-
@@ -51,7 +51,8 @@ declare module "terse-sdk" {
51
51
  }
52
52
 
53
53
  function createTools(agent: TerseAgent): GeneratedTools {
54
- const allowed: Set<string> = new Set(agent.skills.map(s => s.integrationType))
54
+ const manualToolConfigs = agent.manualToolConfigs ?? agent.skills
55
+ const allowed: Set<string> = new Set(manualToolConfigs.map(config => config.integrationType))
55
56
  return {
56
57
  {{#each groups}}
57
58
  ...(allowed.has("{{escape integrationType}}") ? { {{key}}: {