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.
- package/README.md +4 -4
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +6 -9
- package/dist/api.js.map +1 -1
- package/dist/assertProjectRoot.d.ts.map +1 -1
- package/dist/assertProjectRoot.js +1 -1
- package/dist/assertProjectRoot.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +4 -4
- package/dist/auth.js.map +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +8 -11
- package/dist/deploy.js.map +1 -1
- package/dist/generate.d.ts.map +1 -1
- package/dist/generate.js +47 -22
- package/dist/generate.js.map +1 -1
- package/dist/index.js +2 -5
- package/dist/index.js.map +1 -1
- package/dist/init.d.ts.map +1 -1
- package/dist/init.js +3 -3
- package/dist/init.js.map +1 -1
- package/dist/integrate.d.ts.map +1 -1
- package/dist/integrate.js +8 -12
- package/dist/integrate.js.map +1 -1
- package/dist/integrationApi.d.ts +2 -2
- package/dist/integrationApi.d.ts.map +1 -1
- package/dist/integrationApi.js.map +1 -1
- package/dist/loadJob.d.ts.map +1 -1
- package/dist/loadJob.js +2 -2
- package/dist/loadJob.js.map +1 -1
- package/dist/providers/LanguageProvider.d.ts +2 -2
- package/dist/providers/LanguageProvider.d.ts.map +1 -1
- package/dist/providers/codegenTypes.d.ts +1 -12
- package/dist/providers/codegenTypes.d.ts.map +1 -1
- package/dist/providers/python/PythonProvider.d.ts +1 -1
- package/dist/providers/python/PythonProvider.d.ts.map +1 -1
- package/dist/providers/python/PythonProvider.js +19 -26
- package/dist/providers/python/PythonProvider.js.map +1 -1
- package/dist/providers/python/preparePythonCodegenData.d.ts +16 -0
- package/dist/providers/python/preparePythonCodegenData.d.ts.map +1 -1
- package/dist/providers/python/preparePythonCodegenData.js +76 -55
- package/dist/providers/python/preparePythonCodegenData.js.map +1 -1
- package/dist/providers/python/pythonTemplateEngine.d.ts.map +1 -1
- package/dist/providers/python/pythonTemplateEngine.js +2 -2
- package/dist/providers/python/pythonTemplateEngine.js.map +1 -1
- package/dist/providers/resolveProvider.d.ts.map +1 -1
- package/dist/providers/resolveProvider.js +1 -1
- package/dist/providers/resolveProvider.js.map +1 -1
- package/dist/providers/shared/sessionStream.d.ts +1 -1
- package/dist/providers/shared/sessionStream.d.ts.map +1 -1
- package/dist/providers/shared/sessionStream.js +8 -10
- package/dist/providers/shared/sessionStream.js.map +1 -1
- package/dist/providers/shared/shellUtils.d.ts.map +1 -1
- package/dist/providers/shared/shellUtils.js +3 -4
- package/dist/providers/shared/shellUtils.js.map +1 -1
- package/dist/providers/templateUtils.d.ts.map +1 -1
- package/dist/providers/templateUtils.js +1 -1
- package/dist/providers/templateUtils.js.map +1 -1
- package/dist/providers/typescript/TypeScriptProvider.d.ts +1 -1
- package/dist/providers/typescript/TypeScriptProvider.d.ts.map +1 -1
- package/dist/providers/typescript/TypeScriptProvider.js +8 -10
- package/dist/providers/typescript/TypeScriptProvider.js.map +1 -1
- package/dist/providers/typescript/prepareCodegenData.d.ts +1 -2
- package/dist/providers/typescript/prepareCodegenData.d.ts.map +1 -1
- package/dist/providers/typescript/prepareCodegenData.js +168 -251
- package/dist/providers/typescript/prepareCodegenData.js.map +1 -1
- package/dist/providers/typescript/templateEngine.d.ts.map +1 -1
- package/dist/providers/typescript/templateEngine.js +2 -2
- package/dist/providers/typescript/templateEngine.js.map +1 -1
- package/dist/run.d.ts.map +1 -1
- package/dist/run.js +2 -2
- package/dist/run.js.map +1 -1
- package/dist/shared/ToolDisplayUtils.d.ts.map +1 -1
- package/dist/shared/ToolDisplayUtils.js +13 -1
- package/dist/shared/ToolDisplayUtils.js.map +1 -1
- package/dist/shared/types.d.ts +13 -0
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/test.d.ts.map +1 -1
- package/dist/test.js +7 -7
- package/dist/test.js.map +1 -1
- package/dist/util.d.ts +1 -1
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js.map +1 -1
- package/package.json +12 -8
- package/templates/python/codegen/generated.hbs +1 -0
- package/templates/python/codegen/partials/attio-section.hbs +4 -5
- package/templates/python/codegen/partials/attio-upsert-record-method.hbs +3 -3
- package/templates/python/codegen/partials/deterministic-tools-section.hbs +115 -1
- package/templates/python/codegen/partials/slack-section.hbs +178 -0
- package/templates/python/codegen/partials/tool-name-types.hbs +3 -0
- package/templates/python/init/README.md.hbs +5 -3
- package/templates/typescript/codegen/partials/slack-section.hbs +5 -6
- 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
|
|
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[] }):
|
|
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[] }):
|
|
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[] }):
|
|
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
|
|
20
|
-
return new SlackOutputConfig("{{escape id}}", opts
|
|
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
|
|
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}}: {
|